Changes in uspace/lib/usb/src/devdrv.c [0b4e7ca:3f2af64] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/lib/usb/src/devdrv.c
r0b4e7ca r3f2af64 72 72 } 73 73 74 /** Log out of memory error on given device.75 *76 * @param dev Device causing the trouble.77 */78 static void usb_log_oom(ddf_dev_t *dev)79 {80 usb_log_error("Out of memory when adding device `%s'.\n",81 dev->name);82 }83 84 74 /** Count number of pipes the driver expects. 85 75 * … … 108 98 */ 109 99 static int initialize_other_pipes(usb_endpoint_description_t **endpoints, 110 usb_device_t *dev) 111 { 112 int rc; 113 114 size_t pipe_count = count_other_pipes(endpoints); 115 if (pipe_count == 0) { 100 usb_device_t *dev, int alternate_setting) 101 { 102 if (endpoints == NULL) { 103 dev->pipes = NULL; 104 dev->pipes_count = 0; 116 105 return EOK; 117 106 } 118 107 119 dev->pipes = malloc(sizeof(usb_endpoint_mapping_t) * pipe_count); 120 if (dev->pipes == NULL) { 121 usb_log_oom(dev->ddf_dev); 122 return ENOMEM; 123 } 124 125 size_t i; 126 127 /* Initialize to NULL first for rollback purposes. */ 128 for (i = 0; i < pipe_count; i++) { 129 dev->pipes[i].pipe = NULL; 130 } 131 132 for (i = 0; i < pipe_count; i++) { 133 dev->pipes[i].pipe = malloc(sizeof(usb_pipe_t)); 134 if (dev->pipes[i].pipe == NULL) { 135 usb_log_oom(dev->ddf_dev); 136 rc = ENOMEM; 137 goto rollback; 138 } 139 140 dev->pipes[i].description = endpoints[i]; 141 dev->pipes[i].interface_no = dev->interface_no; 142 dev->pipes[i].interface_setting = 0; 143 } 144 145 rc = usb_pipe_initialize_from_configuration(dev->pipes, pipe_count, 108 usb_endpoint_mapping_t *pipes; 109 size_t pipes_count; 110 111 int rc = usb_device_create_pipes(dev->ddf_dev, &dev->wire, endpoints, 146 112 dev->descriptors.configuration, dev->descriptors.configuration_size, 147 &dev->wire); 148 if (rc != EOK) { 149 usb_log_error("Failed initializing USB endpoints: %s.\n", 150 str_error(rc)); 151 goto rollback; 152 } 153 154 /* Register the endpoints. */ 155 usb_hc_connection_t hc_conn; 156 rc = usb_hc_connection_initialize_from_device(&hc_conn, dev->ddf_dev); 157 if (rc != EOK) { 158 usb_log_error( 159 "Failed initializing connection to host controller: %s.\n", 160 str_error(rc)); 161 goto rollback; 162 } 163 rc = usb_hc_connection_open(&hc_conn); 164 if (rc != EOK) { 165 usb_log_error("Failed to connect to host controller: %s.\n", 166 str_error(rc)); 167 goto rollback; 168 } 169 for (i = 0; i < pipe_count; i++) { 170 if (dev->pipes[i].present) { 171 rc = usb_pipe_register(dev->pipes[i].pipe, 172 dev->pipes[i].descriptor->poll_interval, 173 &hc_conn); 174 /* Ignore error when operation not supported by HC. */ 175 if ((rc != EOK) && (rc != ENOTSUP)) { 176 /* FIXME: what shall we do? */ 177 dev->pipes[i].present = false; 178 free(dev->pipes[i].pipe); 179 dev->pipes[i].pipe = NULL; 180 } 181 } 182 } 183 /* Ignoring errors here. */ 184 usb_hc_connection_close(&hc_conn); 185 186 dev->pipes_count = pipe_count; 187 188 return EOK; 189 190 rollback: 191 for (i = 0; i < pipe_count; i++) { 192 if (dev->pipes[i].pipe != NULL) { 193 free(dev->pipes[i].pipe); 194 } 195 } 196 free(dev->pipes); 197 198 return rc; 199 } 200 201 /** Initialize all endpoint pipes. 202 * 203 * @param drv The driver. 204 * @param dev The device to be initialized. 205 * @return Error code. 206 */ 207 static int initialize_pipes(usb_device_t *dev) 208 { 209 int rc; 210 211 rc = usb_device_connection_initialize_from_device(&dev->wire, 212 dev->ddf_dev); 213 if (rc != EOK) { 214 usb_log_error( 215 "Failed initializing connection on device `%s'. %s.\n", 216 dev->ddf_dev->name, str_error(rc)); 217 return rc; 218 } 219 220 rc = usb_pipe_initialize_default_control(&dev->ctrl_pipe, 221 &dev->wire); 222 if (rc != EOK) { 223 usb_log_error("Failed to initialize default control pipe " \ 224 "on device `%s': %s.\n", 225 dev->ddf_dev->name, str_error(rc)); 226 return rc; 227 } 228 229 rc = usb_pipe_probe_default_control(&dev->ctrl_pipe); 230 if (rc != EOK) { 231 usb_log_error( 232 "Probing default control pipe on device `%s' failed: %s.\n", 233 dev->ddf_dev->name, str_error(rc)); 234 return rc; 235 } 236 237 /* Get our interface. */ 238 dev->interface_no = usb_device_get_assigned_interface(dev->ddf_dev); 239 240 /* 241 * For further actions, we need open session on default control pipe. 242 */ 243 rc = usb_pipe_start_session(&dev->ctrl_pipe); 244 if (rc != EOK) { 245 usb_log_error("Failed to start an IPC session: %s.\n", 246 str_error(rc)); 247 return rc; 248 } 249 250 /* Get the device descriptor. */ 251 rc = usb_request_get_device_descriptor(&dev->ctrl_pipe, 252 &dev->descriptors.device); 253 if (rc != EOK) { 254 usb_log_error("Failed to retrieve device descriptor: %s.\n", 255 str_error(rc)); 256 return rc; 257 } 258 259 /* Get the full configuration descriptor. */ 260 rc = usb_request_get_full_configuration_descriptor_alloc( 261 &dev->ctrl_pipe, 0, (void **) &dev->descriptors.configuration, 262 &dev->descriptors.configuration_size); 263 if (rc != EOK) { 264 usb_log_error("Failed retrieving configuration descriptor: %s.\n", 265 dev->ddf_dev->name, str_error(rc)); 266 return rc; 267 } 268 269 if (driver->endpoints != NULL) { 270 rc = initialize_other_pipes(driver->endpoints, dev); 271 } 272 273 /* No checking here. */ 274 usb_pipe_end_session(&dev->ctrl_pipe); 275 276 /* Rollback actions. */ 277 if (rc != EOK) { 278 if (dev->descriptors.configuration != NULL) { 279 free(dev->descriptors.configuration); 280 } 281 } 282 283 return rc; 284 } 285 286 /** Count number of alternate settings of a interface. 287 * 288 * @param config_descr Full configuration descriptor. 289 * @param config_descr_size Size of @p config_descr in bytes. 290 * @param interface_no Interface number. 291 * @return Number of alternate interfaces for @p interface_no interface. 292 */ 293 static size_t count_alternate_interfaces(uint8_t *config_descr, 294 size_t config_descr_size, int interface_no) 295 { 296 assert(config_descr != NULL); 297 usb_dp_parser_t dp_parser = { 298 .nesting = usb_dp_standard_descriptor_nesting 299 }; 300 usb_dp_parser_data_t dp_data = { 301 .data = config_descr, 302 .size = config_descr_size, 303 .arg = NULL 304 }; 305 306 size_t alternate_count = 0; 307 308 uint8_t *iface_ptr = usb_dp_get_nested_descriptor(&dp_parser, 309 &dp_data, config_descr); 310 while (iface_ptr != NULL) { 311 usb_standard_interface_descriptor_t *iface 312 = (usb_standard_interface_descriptor_t *) iface_ptr; 313 if (iface->descriptor_type == USB_DESCTYPE_INTERFACE) { 314 if (iface->interface_number == interface_no) { 315 alternate_count++; 316 } 317 } 318 iface_ptr = usb_dp_get_sibling_descriptor(&dp_parser, &dp_data, 319 config_descr, iface_ptr); 320 } 321 322 return alternate_count; 323 } 324 325 /** Initialize structures related to alternate interfaces. 326 * 327 * @param dev Device where alternate settings shall be initialized. 328 * @return Error code. 329 */ 330 static int initialize_alternate_interfaces(usb_device_t *dev) 331 { 332 if (dev->interface_no < 0) { 333 dev->alternate_interfaces = NULL; 334 return EOK; 335 } 336 337 usb_alternate_interfaces_t *alternates 338 = malloc(sizeof(usb_alternate_interfaces_t)); 339 340 if (alternates == NULL) { 341 return ENOMEM; 342 } 343 344 alternates->alternative_count 345 = count_alternate_interfaces(dev->descriptors.configuration, 346 dev->descriptors.configuration_size, dev->interface_no); 347 348 if (alternates->alternative_count == 0) { 349 free(alternates); 350 return ENOENT; 351 } 352 353 alternates->alternatives = malloc(alternates->alternative_count 354 * sizeof(usb_alternate_interface_descriptors_t)); 355 if (alternates->alternatives == NULL) { 356 free(alternates); 357 return ENOMEM; 358 } 359 360 alternates->current = 0; 361 362 usb_dp_parser_t dp_parser = { 363 .nesting = usb_dp_standard_descriptor_nesting 364 }; 365 usb_dp_parser_data_t dp_data = { 366 .data = dev->descriptors.configuration, 367 .size = dev->descriptors.configuration_size, 368 .arg = NULL 369 }; 370 371 usb_alternate_interface_descriptors_t *cur_alt_iface 372 = &alternates->alternatives[0]; 373 374 uint8_t *iface_ptr = usb_dp_get_nested_descriptor(&dp_parser, 375 &dp_data, dp_data.data); 376 while (iface_ptr != NULL) { 377 usb_standard_interface_descriptor_t *iface 378 = (usb_standard_interface_descriptor_t *) iface_ptr; 379 if ((iface->descriptor_type != USB_DESCTYPE_INTERFACE) 380 || (iface->interface_number != dev->interface_no)) { 381 iface_ptr = usb_dp_get_sibling_descriptor(&dp_parser, 382 &dp_data, 383 dp_data.data, iface_ptr); 384 continue; 385 } 386 387 cur_alt_iface->interface = iface; 388 cur_alt_iface->nested_descriptors = iface_ptr + sizeof(*iface); 389 390 /* Find next interface to count size of nested descriptors. */ 391 iface_ptr = usb_dp_get_sibling_descriptor(&dp_parser, &dp_data, 392 dp_data.data, iface_ptr); 393 if (iface_ptr == NULL) { 394 uint8_t *next = dp_data.data + dp_data.size; 395 cur_alt_iface->nested_descriptors_size 396 = next - cur_alt_iface->nested_descriptors; 397 } else { 398 cur_alt_iface->nested_descriptors_size 399 = iface_ptr - cur_alt_iface->nested_descriptors; 400 } 401 402 cur_alt_iface++; 403 } 404 405 dev->alternate_interfaces = alternates; 113 dev->interface_no, alternate_setting, 114 &pipes, &pipes_count); 115 116 if (rc != EOK) { 117 return rc; 118 } 119 120 dev->pipes = pipes; 121 dev->pipes_count = pipes_count; 406 122 407 123 return EOK; … … 423 139 int rc; 424 140 425 usb_device_t *dev = malloc(sizeof(usb_device_t)); 426 if (dev == NULL) { 427 usb_log_error("Out of memory when adding device `%s'.\n", 428 gen_dev->name); 429 return ENOMEM; 430 } 431 432 433 dev->ddf_dev = gen_dev; 434 dev->ddf_dev->driver_data = dev; 435 dev->driver_data = NULL; 436 dev->descriptors.configuration = NULL; 437 438 dev->pipes_count = 0; 439 dev->pipes = NULL; 440 441 rc = initialize_pipes(dev); 442 if (rc != EOK) { 443 free(dev); 444 return rc; 445 } 446 447 (void) initialize_alternate_interfaces(dev); 141 usb_device_t *dev = NULL; 142 const char *err_msg = NULL; 143 rc = usb_device_create(gen_dev, driver->endpoints, &dev, &err_msg); 144 if (rc != EOK) { 145 usb_log_error("USB device `%s' creation failed (%s): %s.\n", 146 gen_dev->name, err_msg, str_error(rc)); 147 return rc; 148 } 448 149 449 150 return driver->ops->add_device(dev); … … 457 158 static int destroy_current_pipes(usb_device_t *dev) 458 159 { 459 size_t i; 460 int rc; 461 462 /* TODO: this shall be done under some device mutex. */ 463 464 /* First check that no session is opened. */ 465 for (i = 0; i < dev->pipes_count; i++) { 466 if (usb_pipe_is_session_started(dev->pipes[i].pipe)) { 467 return EBUSY; 468 } 469 } 470 471 /* Prepare connection to HC. */ 472 usb_hc_connection_t hc_conn; 473 rc = usb_hc_connection_initialize_from_device(&hc_conn, dev->ddf_dev); 474 if (rc != EOK) { 475 return rc; 476 } 477 rc = usb_hc_connection_open(&hc_conn); 478 if (rc != EOK) { 479 return rc; 480 } 481 482 /* Destroy the pipes. */ 483 for (i = 0; i < dev->pipes_count; i++) { 484 usb_pipe_unregister(dev->pipes[i].pipe, &hc_conn); 485 free(dev->pipes[i].pipe); 486 } 487 488 usb_hc_connection_close(&hc_conn); 489 490 free(dev->pipes); 160 int rc = usb_device_destroy_pipes(dev->ddf_dev, 161 dev->pipes, dev->pipes_count); 162 if (rc != EOK) { 163 return rc; 164 } 165 491 166 dev->pipes = NULL; 492 167 dev->pipes_count = 0; … … 505 180 * with usb_pipe_initialize_from_configuration(). 506 181 * 182 * @warning This is a wrapper function that does several operations that 183 * can fail and that cannot be rollbacked easily. That means that a failure 184 * during the SET_INTERFACE request would result in having a device with 185 * no pipes at all (except the default control one). That is because the old 186 * pipes needs to be unregistered at HC first and the new ones could not 187 * be created. 188 * 507 189 * @param dev USB device. 508 190 * @param alternate_setting Alternate setting to choose. … … 519 201 int rc; 520 202 521 /* TODO: more transactional behavior. */522 523 203 /* Destroy existing pipes. */ 524 204 rc = destroy_current_pipes(dev); … … 535 215 536 216 /* Create new pipes. */ 537 rc = initialize_other_pipes(endpoints, dev );217 rc = initialize_other_pipes(endpoints, dev, (int) alternate_setting); 538 218 539 219 return rc; 220 } 221 222 /** Retrieve basic descriptors from the device. 223 * 224 * @param[in] ctrl_pipe Control endpoint pipe. 225 * @param[out] descriptors Where to store the descriptors. 226 * @return Error code. 227 */ 228 int usb_device_retrieve_descriptors(usb_pipe_t *ctrl_pipe, 229 usb_device_descriptors_t *descriptors) 230 { 231 assert(descriptors != NULL); 232 233 descriptors->configuration = NULL; 234 235 int rc; 236 237 /* It is worth to start a long transfer. */ 238 rc = usb_pipe_start_long_transfer(ctrl_pipe); 239 if (rc != EOK) { 240 return rc; 241 } 242 243 /* Get the device descriptor. */ 244 rc = usb_request_get_device_descriptor(ctrl_pipe, &descriptors->device); 245 if (rc != EOK) { 246 goto leave; 247 } 248 249 /* Get the full configuration descriptor. */ 250 rc = usb_request_get_full_configuration_descriptor_alloc( 251 ctrl_pipe, 0, (void **) &descriptors->configuration, 252 &descriptors->configuration_size); 253 254 leave: 255 usb_pipe_end_long_transfer(ctrl_pipe); 256 257 return rc; 258 } 259 260 /** Create pipes for a device. 261 * 262 * This is more or less a wrapper that does following actions: 263 * - allocate and initialize pipes 264 * - map endpoints to the pipes based on the descriptions 265 * - registers endpoints with the host controller 266 * 267 * @param[in] dev Generic DDF device backing the USB one. 268 * @param[in] wire Initialized backing connection to the host controller. 269 * @param[in] endpoints Endpoints description, NULL terminated. 270 * @param[in] config_descr Configuration descriptor of active configuration. 271 * @param[in] config_descr_size Size of @p config_descr in bytes. 272 * @param[in] interface_no Interface to map from. 273 * @param[in] interface_setting Interface setting (default is usually 0). 274 * @param[out] pipes_ptr Where to store array of created pipes 275 * (not NULL terminated). 276 * @param[out] pipes_count_ptr Where to store number of pipes 277 * (set to if you wish to ignore the count). 278 * @return Error code. 279 */ 280 int usb_device_create_pipes(ddf_dev_t *dev, usb_device_connection_t *wire, 281 usb_endpoint_description_t **endpoints, 282 uint8_t *config_descr, size_t config_descr_size, 283 int interface_no, int interface_setting, 284 usb_endpoint_mapping_t **pipes_ptr, size_t *pipes_count_ptr) 285 { 286 assert(dev != NULL); 287 assert(wire != NULL); 288 assert(endpoints != NULL); 289 assert(config_descr != NULL); 290 assert(config_descr_size > 0); 291 assert(pipes_ptr != NULL); 292 293 size_t i; 294 int rc; 295 296 size_t pipe_count = count_other_pipes(endpoints); 297 if (pipe_count == 0) { 298 *pipes_ptr = NULL; 299 return EOK; 300 } 301 302 usb_endpoint_mapping_t *pipes 303 = malloc(sizeof(usb_endpoint_mapping_t) * pipe_count); 304 if (pipes == NULL) { 305 return ENOMEM; 306 } 307 308 /* Initialize to NULL to allow smooth rollback. */ 309 for (i = 0; i < pipe_count; i++) { 310 pipes[i].pipe = NULL; 311 } 312 313 /* Now allocate and fully initialize. */ 314 for (i = 0; i < pipe_count; i++) { 315 pipes[i].pipe = malloc(sizeof(usb_pipe_t)); 316 if (pipes[i].pipe == NULL) { 317 rc = ENOMEM; 318 goto rollback_free_only; 319 } 320 pipes[i].description = endpoints[i]; 321 pipes[i].interface_no = interface_no; 322 pipes[i].interface_setting = interface_setting; 323 } 324 325 /* Find the mapping from configuration descriptor. */ 326 rc = usb_pipe_initialize_from_configuration(pipes, pipe_count, 327 config_descr, config_descr_size, wire); 328 if (rc != EOK) { 329 goto rollback_free_only; 330 } 331 332 /* Register the endpoints with HC. */ 333 usb_hc_connection_t hc_conn; 334 rc = usb_hc_connection_initialize_from_device(&hc_conn, dev); 335 if (rc != EOK) { 336 goto rollback_free_only; 337 } 338 339 rc = usb_hc_connection_open(&hc_conn); 340 if (rc != EOK) { 341 goto rollback_free_only; 342 } 343 344 for (i = 0; i < pipe_count; i++) { 345 if (pipes[i].present) { 346 rc = usb_pipe_register(pipes[i].pipe, 347 pipes[i].descriptor->poll_interval, &hc_conn); 348 if (rc != EOK) { 349 goto rollback_unregister_endpoints; 350 } 351 } 352 } 353 354 usb_hc_connection_close(&hc_conn); 355 356 *pipes_ptr = pipes; 357 if (pipes_count_ptr != NULL) { 358 *pipes_count_ptr = pipe_count; 359 } 360 361 return EOK; 362 363 /* 364 * Jump here if something went wrong after endpoints have 365 * been registered. 366 * This is also the target when the registration of 367 * endpoints fails. 368 */ 369 rollback_unregister_endpoints: 370 for (i = 0; i < pipe_count; i++) { 371 if (pipes[i].present) { 372 usb_pipe_unregister(pipes[i].pipe, &hc_conn); 373 } 374 } 375 376 usb_hc_connection_close(&hc_conn); 377 378 /* 379 * Jump here if something went wrong before some actual communication 380 * with HC. Then the only thing that needs to be done is to free 381 * allocated memory. 382 */ 383 rollback_free_only: 384 for (i = 0; i < pipe_count; i++) { 385 if (pipes[i].pipe != NULL) { 386 free(pipes[i].pipe); 387 } 388 } 389 free(pipes); 390 391 return rc; 392 } 393 394 /** Destroy pipes previously created by usb_device_create_pipes. 395 * 396 * @param[in] dev Generic DDF device backing the USB one. 397 * @param[in] pipes Endpoint mapping to be destroyed. 398 * @param[in] pipes_count Number of endpoints. 399 */ 400 int usb_device_destroy_pipes(ddf_dev_t *dev, 401 usb_endpoint_mapping_t *pipes, size_t pipes_count) 402 { 403 assert(dev != NULL); 404 assert(((pipes != NULL) && (pipes_count > 0)) 405 || ((pipes == NULL) && (pipes_count == 0))); 406 407 if (pipes_count == 0) { 408 return EOK; 409 } 410 411 int rc; 412 413 /* Prepare connection to HC to allow endpoint unregistering. */ 414 usb_hc_connection_t hc_conn; 415 rc = usb_hc_connection_initialize_from_device(&hc_conn, dev); 416 if (rc != EOK) { 417 return rc; 418 } 419 rc = usb_hc_connection_open(&hc_conn); 420 if (rc != EOK) { 421 return rc; 422 } 423 424 /* Destroy the pipes. */ 425 size_t i; 426 for (i = 0; i < pipes_count; i++) { 427 usb_pipe_unregister(pipes[i].pipe, &hc_conn); 428 free(pipes[i].pipe); 429 } 430 431 usb_hc_connection_close(&hc_conn); 432 433 free(pipes); 434 435 return EOK; 436 } 437 438 /** Initialize control pipe in a device. 439 * 440 * @param dev USB device in question. 441 * @param errmsg Where to store error context. 442 * @return 443 */ 444 static int init_wire_and_ctrl_pipe(usb_device_t *dev, const char **errmsg) 445 { 446 int rc; 447 448 rc = usb_device_connection_initialize_from_device(&dev->wire, 449 dev->ddf_dev); 450 if (rc != EOK) { 451 *errmsg = "device connection initialization"; 452 return rc; 453 } 454 455 rc = usb_pipe_initialize_default_control(&dev->ctrl_pipe, 456 &dev->wire); 457 if (rc != EOK) { 458 *errmsg = "default control pipe initialization"; 459 return rc; 460 } 461 462 return EOK; 463 } 464 465 466 /** Create new instance of USB device. 467 * 468 * @param[in] ddf_dev Generic DDF device backing the USB one. 469 * @param[in] endpoints NULL terminated array of endpoints (NULL for none). 470 * @param[out] dev_ptr Where to store pointer to the new device. 471 * @param[out] errstr_ptr Where to store description of context 472 * (in case error occurs). 473 * @return Error code. 474 */ 475 int usb_device_create(ddf_dev_t *ddf_dev, 476 usb_endpoint_description_t **endpoints, 477 usb_device_t **dev_ptr, const char **errstr_ptr) 478 { 479 assert(dev_ptr != NULL); 480 assert(ddf_dev != NULL); 481 482 int rc; 483 484 usb_device_t *dev = malloc(sizeof(usb_device_t)); 485 if (dev == NULL) { 486 *errstr_ptr = "structure allocation"; 487 return ENOMEM; 488 } 489 490 // FIXME: proper deallocation in case of errors 491 492 dev->ddf_dev = ddf_dev; 493 dev->driver_data = NULL; 494 dev->descriptors.configuration = NULL; 495 dev->alternate_interfaces = NULL; 496 497 dev->pipes_count = 0; 498 dev->pipes = NULL; 499 500 /* Initialize backing wire and control pipe. */ 501 rc = init_wire_and_ctrl_pipe(dev, errstr_ptr); 502 if (rc != EOK) { 503 return rc; 504 } 505 506 /* Get our interface. */ 507 dev->interface_no = usb_device_get_assigned_interface(dev->ddf_dev); 508 509 /* Retrieve standard descriptors. */ 510 rc = usb_device_retrieve_descriptors(&dev->ctrl_pipe, 511 &dev->descriptors); 512 if (rc != EOK) { 513 *errstr_ptr = "descriptor retrieval"; 514 return rc; 515 } 516 517 /* Create alternate interfaces. */ 518 rc = usb_alternate_interfaces_create(dev->descriptors.configuration, 519 dev->descriptors.configuration_size, dev->interface_no, 520 &dev->alternate_interfaces); 521 if (rc != EOK) { 522 /* We will try to silently ignore this. */ 523 dev->alternate_interfaces = NULL; 524 } 525 526 rc = initialize_other_pipes(endpoints, dev, 0); 527 if (rc != EOK) { 528 *errstr_ptr = "pipes initialization"; 529 return rc; 530 } 531 532 *errstr_ptr = NULL; 533 *dev_ptr = dev; 534 535 return EOK; 540 536 } 541 537
Note:
See TracChangeset
for help on using the changeset viewer.