Changes in uspace/lib/usb/src/devdrv.c [0b4e7ca:e484f3b] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/lib/usb/src/devdrv.c
r0b4e7ca re484f3b 36 36 #include <usb/request.h> 37 37 #include <usb/debug.h> 38 #include <usb/dp.h>39 38 #include <errno.h> 40 39 #include <str_error.h> … … 87 86 * @return Number of pipes (excluding default control pipe). 88 87 */ 89 static size_t count_other_pipes(usb_ endpoint_description_t **endpoints)88 static size_t count_other_pipes(usb_driver_t *drv) 90 89 { 91 90 size_t count = 0; 92 if ( endpoints == NULL) {91 if (drv->endpoints == NULL) { 93 92 return 0; 94 93 } 95 94 96 while ( endpoints[count] != NULL) {95 while (drv->endpoints[count] != NULL) { 97 96 count++; 98 97 } … … 107 106 * @return Error code. 108 107 */ 109 static int initialize_other_pipes(usb_endpoint_description_t **endpoints, 110 usb_device_t *dev) 108 static int initialize_other_pipes(usb_driver_t *drv, usb_device_t *dev) 111 109 { 112 110 int rc; 113 114 size_t pipe_count = count_other_pipes(endpoints); 115 if (pipe_count == 0) { 116 return EOK; 117 } 118 111 dev->interface_no = usb_device_get_assigned_interface(dev->ddf_dev); 112 113 size_t pipe_count = count_other_pipes(drv); 119 114 dev->pipes = malloc(sizeof(usb_endpoint_mapping_t) * pipe_count); 120 115 if (dev->pipes == NULL) { … … 138 133 } 139 134 140 dev->pipes[i].description = endpoints[i];135 dev->pipes[i].description = drv->endpoints[i]; 141 136 dev->pipes[i].interface_no = dev->interface_no; 142 dev->pipes[i].interface_setting = 0;143 137 } 144 138 … … 184 178 usb_hc_connection_close(&hc_conn); 185 179 186 dev->pipes_count = pipe_count;187 188 180 return EOK; 189 181 … … 235 227 } 236 228 237 /* Get our interface. */238 dev->interface_no = usb_device_get_assigned_interface(dev->ddf_dev);239 240 229 /* 241 230 * For further actions, we need open session on default control pipe. … … 268 257 269 258 if (driver->endpoints != NULL) { 270 rc = initialize_other_pipes(driver ->endpoints, dev);259 rc = initialize_other_pipes(driver, dev); 271 260 } 272 261 … … 282 271 283 272 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_nesting299 };300 usb_dp_parser_data_t dp_data = {301 .data = config_descr,302 .size = config_descr_size,303 .arg = NULL304 };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 *iface312 = (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 *alternates338 = malloc(sizeof(usb_alternate_interfaces_t));339 340 if (alternates == NULL) {341 return ENOMEM;342 }343 344 alternates->alternative_count345 = 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_count354 * 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_nesting364 };365 usb_dp_parser_data_t dp_data = {366 .data = dev->descriptors.configuration,367 .size = dev->descriptors.configuration_size,368 .arg = NULL369 };370 371 usb_alternate_interface_descriptors_t *cur_alt_iface372 = &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 *iface378 = (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_size396 = next - cur_alt_iface->nested_descriptors;397 } else {398 cur_alt_iface->nested_descriptors_size399 = iface_ptr - cur_alt_iface->nested_descriptors;400 }401 402 cur_alt_iface++;403 }404 405 dev->alternate_interfaces = alternates;406 407 return EOK;408 273 } 409 274 … … 436 301 dev->descriptors.configuration = NULL; 437 302 438 dev->pipes_count = 0;439 dev->pipes = NULL;440 441 303 rc = initialize_pipes(dev); 442 304 if (rc != EOK) { … … 445 307 } 446 308 447 (void) initialize_alternate_interfaces(dev);448 449 309 return driver->ops->add_device(dev); 450 }451 452 /** Destroy existing pipes of a USB device.453 *454 * @param dev Device where to destroy the pipes.455 * @return Error code.456 */457 static int destroy_current_pipes(usb_device_t *dev)458 {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);491 dev->pipes = NULL;492 dev->pipes_count = 0;493 494 return EOK;495 }496 497 /** Change interface setting of a device.498 * This function selects new alternate setting of an interface by issuing499 * proper USB command to the device and also creates new USB pipes500 * under @c dev->pipes.501 *502 * @warning This function is intended for drivers working at interface level.503 * For drivers controlling the whole device, you need to change interface504 * manually using usb_request_set_interface() and creating new pipes505 * with usb_pipe_initialize_from_configuration().506 *507 * @param dev USB device.508 * @param alternate_setting Alternate setting to choose.509 * @param endpoints New endpoint descriptions.510 * @return Error code.511 */512 int usb_device_select_interface(usb_device_t *dev, uint8_t alternate_setting,513 usb_endpoint_description_t **endpoints)514 {515 if (dev->interface_no < 0) {516 return EINVAL;517 }518 519 int rc;520 521 /* TODO: more transactional behavior. */522 523 /* Destroy existing pipes. */524 rc = destroy_current_pipes(dev);525 if (rc != EOK) {526 return rc;527 }528 529 /* Change the interface itself. */530 rc = usb_request_set_interface(&dev->ctrl_pipe, dev->interface_no,531 alternate_setting);532 if (rc != EOK) {533 return rc;534 }535 536 /* Create new pipes. */537 rc = initialize_other_pipes(endpoints, dev);538 539 return rc;540 310 } 541 311
Note:
See TracChangeset
for help on using the changeset viewer.