Changes in uspace/lib/usb/src/devdrv.c [c1b1944:4ede178] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/lib/usb/src/devdrv.c
rc1b1944 r4ede178 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 74 84 /** Count number of pipes the driver expects. 75 85 * … … 98 108 */ 99 109 static int initialize_other_pipes(usb_endpoint_description_t **endpoints, 100 usb_device_t *dev, int alternate_setting) 101 { 102 usb_endpoint_mapping_t *pipes; 103 size_t pipes_count; 104 105 int rc = usb_device_create_pipes(dev->ddf_dev, &dev->wire, 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) { 116 return EOK; 117 } 118 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, 106 146 dev->descriptors.configuration, dev->descriptors.configuration_size, 107 dev->interface_no, alternate_setting, 108 &pipes, &pipes_count); 109 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); 110 157 if (rc != EOK) { 111 158 usb_log_error( 112 "Failed to create endpoint pipes for `%s': %s.\n", 113 dev->ddf_dev->name, str_error(rc)); 114 return rc; 115 } 116 117 dev->pipes = pipes; 118 dev->pipes_count = pipes_count; 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; 119 187 120 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; 121 199 } 122 200 … … 161 239 162 240 /* 163 * For further actions, we need open session on default control pipe. 241 * We will do some querying of the device, it is worth to prepare 242 * the long transfer. 164 243 */ 165 rc = usb_pipe_start_ session(&dev->ctrl_pipe);166 if (rc != EOK) { 167 usb_log_error("Failed to start an IPC session: %s.\n",244 rc = usb_pipe_start_long_transfer(&dev->ctrl_pipe); 245 if (rc != EOK) { 246 usb_log_error("Failed to start transfer: %s.\n", 168 247 str_error(rc)); 169 248 return rc; 170 249 } 171 250 172 /* Retrieve the descriptors. */ 173 rc = usb_device_retrieve_descriptors(&dev->ctrl_pipe, 174 &dev->descriptors); 175 if (rc != EOK) { 176 usb_log_error("Failed to retrieve standard device " \ 177 "descriptors of %s: %s.\n", 251 /* Get the device descriptor. */ 252 rc = usb_request_get_device_descriptor(&dev->ctrl_pipe, 253 &dev->descriptors.device); 254 if (rc != EOK) { 255 usb_pipe_end_long_transfer(&dev->ctrl_pipe); 256 usb_log_error("Failed to retrieve device descriptor: %s.\n", 257 str_error(rc)); 258 return rc; 259 } 260 261 /* Get the full configuration descriptor. */ 262 rc = usb_request_get_full_configuration_descriptor_alloc( 263 &dev->ctrl_pipe, 0, (void **) &dev->descriptors.configuration, 264 &dev->descriptors.configuration_size); 265 if (rc != EOK) { 266 usb_pipe_end_long_transfer(&dev->ctrl_pipe); 267 usb_log_error("Failed retrieving configuration descriptor: %s. %s\n", 178 268 dev->ddf_dev->name, str_error(rc)); 179 269 return rc; 180 270 } 181 271 182 183 272 if (driver->endpoints != NULL) { 184 rc = initialize_other_pipes(driver->endpoints, dev, 0); 185 } 186 187 /* No checking here. */ 188 usb_pipe_end_session(&dev->ctrl_pipe); 273 rc = initialize_other_pipes(driver->endpoints, dev); 274 } 275 276 usb_pipe_end_long_transfer(&dev->ctrl_pipe); 189 277 190 278 /* Rollback actions. */ … … 205 293 * @return Number of alternate interfaces for @p interface_no interface. 206 294 */ 207 s ize_t usb_interface_count_alternates(uint8_t *config_descr,208 size_t config_descr_size, uint8_t interface_no)295 static size_t count_alternate_interfaces(uint8_t *config_descr, 296 size_t config_descr_size, int interface_no) 209 297 { 210 298 assert(config_descr != NULL); 211 assert(config_descr_size > 0);212 213 299 usb_dp_parser_t dp_parser = { 214 300 .nesting = usb_dp_standard_descriptor_nesting … … 259 345 260 346 alternates->alternative_count 261 = usb_interface_count_alternates(dev->descriptors.configuration,347 = count_alternate_interfaces(dev->descriptors.configuration, 262 348 dev->descriptors.configuration_size, dev->interface_no); 263 349 … … 373 459 static int destroy_current_pipes(usb_device_t *dev) 374 460 { 375 int rc = usb_device_destroy_pipes(dev->ddf_dev, 376 dev->pipes, dev->pipes_count); 377 if (rc != EOK) { 378 return rc; 379 } 380 461 size_t i; 462 int rc; 463 464 /* TODO: this shall be done under some device mutex. */ 465 466 /* First check that no session is opened. */ 467 for (i = 0; i < dev->pipes_count; i++) { 468 if (usb_pipe_is_session_started(dev->pipes[i].pipe)) { 469 return EBUSY; 470 } 471 } 472 473 /* Prepare connection to HC. */ 474 usb_hc_connection_t hc_conn; 475 rc = usb_hc_connection_initialize_from_device(&hc_conn, dev->ddf_dev); 476 if (rc != EOK) { 477 return rc; 478 } 479 rc = usb_hc_connection_open(&hc_conn); 480 if (rc != EOK) { 481 return rc; 482 } 483 484 /* Destroy the pipes. */ 485 for (i = 0; i < dev->pipes_count; i++) { 486 usb_pipe_unregister(dev->pipes[i].pipe, &hc_conn); 487 free(dev->pipes[i].pipe); 488 } 489 490 usb_hc_connection_close(&hc_conn); 491 492 free(dev->pipes); 381 493 dev->pipes = NULL; 382 494 dev->pipes_count = 0; … … 425 537 426 538 /* Create new pipes. */ 427 rc = initialize_other_pipes(endpoints, dev , (int) alternate_setting);539 rc = initialize_other_pipes(endpoints, dev); 428 540 429 541 return rc; 430 }431 432 /** Retrieve basic descriptors from the device.433 *434 * @param[in] ctrl_pipe Control pipe with opened session.435 * @param[out] descriptors Where to store the descriptors.436 * @return Error code.437 */438 int usb_device_retrieve_descriptors(usb_pipe_t *ctrl_pipe,439 usb_device_descriptors_t *descriptors)440 {441 assert(descriptors != NULL);442 assert(usb_pipe_is_session_started(ctrl_pipe));443 444 descriptors->configuration = NULL;445 446 int rc;447 448 /* Get the device descriptor. */449 rc = usb_request_get_device_descriptor(ctrl_pipe, &descriptors->device);450 if (rc != EOK) {451 return rc;452 }453 454 /* Get the full configuration descriptor. */455 rc = usb_request_get_full_configuration_descriptor_alloc(456 ctrl_pipe, 0, (void **) &descriptors->configuration,457 &descriptors->configuration_size);458 if (rc != EOK) {459 return rc;460 }461 462 return EOK;463 }464 465 /** Create pipes for a device.466 *467 * This is more or less a wrapper that does following actions:468 * - allocate and initialize pipes469 * - map endpoints to the pipes based on the descriptions470 * - registers endpoints with the host controller471 *472 * @param[in] dev Generic DDF device backing the USB one.473 * @param[in] wire Initialized backing connection to the host controller.474 * @param[in] endpoints Endpoints description, NULL terminated.475 * @param[in] config_descr Configuration descriptor of active configuration.476 * @param[in] config_descr_size Size of @p config_descr in bytes.477 * @param[in] interface_no Interface to map from.478 * @param[in] interface_setting Interface setting (default is usually 0).479 * @param[out] pipes_ptr Where to store array of created pipes480 * (not NULL terminated).481 * @param[out] pipes_count_ptr Where to store number of pipes482 * (set to if you wish to ignore the count).483 * @return Error code.484 */485 int usb_device_create_pipes(ddf_dev_t *dev, usb_device_connection_t *wire,486 usb_endpoint_description_t **endpoints,487 uint8_t *config_descr, size_t config_descr_size,488 int interface_no, int interface_setting,489 usb_endpoint_mapping_t **pipes_ptr, size_t *pipes_count_ptr)490 {491 assert(dev != NULL);492 assert(wire != NULL);493 assert(endpoints != NULL);494 assert(config_descr != NULL);495 assert(config_descr_size > 0);496 assert(pipes_ptr != NULL);497 498 size_t i;499 int rc;500 501 size_t pipe_count = count_other_pipes(endpoints);502 if (pipe_count == 0) {503 *pipes_ptr = NULL;504 return EOK;505 }506 507 usb_endpoint_mapping_t *pipes508 = malloc(sizeof(usb_endpoint_mapping_t) * pipe_count);509 if (pipes == NULL) {510 return ENOMEM;511 }512 513 /* Initialize to NULL to allow smooth rollback. */514 for (i = 0; i < pipe_count; i++) {515 pipes[i].pipe = NULL;516 }517 518 /* Now allocate and fully initialize. */519 for (i = 0; i < pipe_count; i++) {520 pipes[i].pipe = malloc(sizeof(usb_pipe_t));521 if (pipes[i].pipe == NULL) {522 rc = ENOMEM;523 goto rollback_free_only;524 }525 pipes[i].description = endpoints[i];526 pipes[i].interface_no = interface_no;527 pipes[i].interface_setting = interface_setting;528 }529 530 /* Find the mapping from configuration descriptor. */531 rc = usb_pipe_initialize_from_configuration(pipes, pipe_count,532 config_descr, config_descr_size, wire);533 if (rc != EOK) {534 goto rollback_free_only;535 }536 537 /* Register the endpoints with HC. */538 usb_hc_connection_t hc_conn;539 rc = usb_hc_connection_initialize_from_device(&hc_conn, dev);540 if (rc != EOK) {541 goto rollback_free_only;542 }543 544 rc = usb_hc_connection_open(&hc_conn);545 if (rc != EOK) {546 goto rollback_free_only;547 }548 549 for (i = 0; i < pipe_count; i++) {550 if (pipes[i].present) {551 rc = usb_pipe_register(pipes[i].pipe,552 pipes[i].descriptor->poll_interval, &hc_conn);553 if (rc != EOK) {554 goto rollback_unregister_endpoints;555 }556 }557 }558 559 usb_hc_connection_close(&hc_conn);560 561 *pipes_ptr = pipes;562 if (pipes_count_ptr != NULL) {563 *pipes_count_ptr = pipe_count;564 }565 566 return EOK;567 568 /*569 * Jump here if something went wrong after endpoints have570 * been registered.571 * This is also the target when the registration of572 * endpoints fails.573 */574 rollback_unregister_endpoints:575 for (i = 0; i < pipe_count; i++) {576 if (pipes[i].present) {577 usb_pipe_unregister(pipes[i].pipe, &hc_conn);578 }579 }580 581 usb_hc_connection_close(&hc_conn);582 583 /*584 * Jump here if something went wrong before some actual communication585 * with HC. Then the only thing that needs to be done is to free586 * allocated memory.587 */588 rollback_free_only:589 for (i = 0; i < pipe_count; i++) {590 if (pipes[i].pipe != NULL) {591 free(pipes[i].pipe);592 }593 }594 free(pipes);595 596 return rc;597 }598 599 /** Destroy pipes previously created by usb_device_create_pipes.600 *601 * @param[in] dev Generic DDF device backing the USB one.602 * @param[in] pipes Endpoint mapping to be destroyed.603 * @param[in] pipes_count Number of endpoints.604 */605 int usb_device_destroy_pipes(ddf_dev_t *dev,606 usb_endpoint_mapping_t *pipes, size_t pipes_count)607 {608 assert(dev != NULL);609 assert(((pipes != NULL) && (pipes_count > 0))610 || ((pipes == NULL) && (pipes_count == 0)));611 612 if (pipes_count == 0) {613 return EOK;614 }615 616 int rc;617 618 /* Prepare connection to HC to allow endpoint unregistering. */619 usb_hc_connection_t hc_conn;620 rc = usb_hc_connection_initialize_from_device(&hc_conn, dev);621 if (rc != EOK) {622 return rc;623 }624 rc = usb_hc_connection_open(&hc_conn);625 if (rc != EOK) {626 return rc;627 }628 629 /* Destroy the pipes. */630 size_t i;631 for (i = 0; i < pipes_count; i++) {632 usb_pipe_unregister(pipes[i].pipe, &hc_conn);633 free(pipes[i].pipe);634 }635 636 usb_hc_connection_close(&hc_conn);637 638 free(pipes);639 640 return EOK;641 542 } 642 543
Note:
See TracChangeset
for help on using the changeset viewer.