Changeset 0cec844d in mainline for uspace/lib
- Timestamp:
- 2011-04-03T17:39:48Z (15 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 3094804b, baa9d5d, c593b21
- Parents:
- b8f7a0d2 (diff), 0b4e7ca (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the(diff)links above to see all the changes relative to each parent. - Location:
- uspace/lib/usb
- Files:
-
- 4 edited
-
include/usb/devdrv.h (modified) (5 diffs)
-
include/usb/pipes.h (modified) (1 diff)
-
src/devdrv.c (modified) (10 diffs)
-
src/pipesinit.c (modified) (3 diffs)
Legend:
- Unmodified
- Added
- Removed
-
uspace/lib/usb/include/usb/devdrv.h
rb8f7a0d2 r0cec844d 47 47 } usb_device_descriptors_t; 48 48 49 /** Wrapper for data related to alternate interface setting. 50 * The pointers will typically point inside configuration descriptor and 51 * thus you shall not deallocate them. 52 */ 53 typedef struct { 54 /** Interface descriptor. */ 55 usb_standard_interface_descriptor_t *interface; 56 /** Pointer to start of descriptor tree bound with this interface. */ 57 uint8_t *nested_descriptors; 58 /** Size of data pointed by nested_descriptors in bytes. */ 59 size_t nested_descriptors_size; 60 } usb_alternate_interface_descriptors_t; 61 62 /** Alternate interface settings. */ 63 typedef struct { 64 /** Array of alternate interfaces descriptions. */ 65 usb_alternate_interface_descriptors_t *alternatives; 66 /** Size of @c alternatives array. */ 67 size_t alternative_count; 68 /** Index of currently selected one. */ 69 size_t current; 70 } usb_alternate_interfaces_t; 71 49 72 /** USB device structure. */ 50 73 typedef struct { … … 56 79 */ 57 80 usb_endpoint_mapping_t *pipes; 81 /** Number of other endpoint pipes. */ 82 size_t pipes_count; 58 83 /** Current interface. 59 84 * Usually, drivers operate on single interface only. … … 61 86 */ 62 87 int interface_no; 88 89 /** Alternative interfaces. 90 * Set to NULL when the driver controls whole device 91 * (i.e. more (or any) interfaces). 92 */ 93 usb_alternate_interfaces_t *alternate_interfaces; 63 94 64 95 /** Some useful descriptors. */ … … 92 123 */ 93 124 const char *name; 94 /** Expected endpoints description, excluding default control endpoint. 125 /** Expected endpoints description. 126 * This description shall exclude default control endpoint (pipe zero) 127 * and must be NULL terminated. 128 * When only control endpoint is expected, you may set NULL directly 129 * without creating one item array containing NULL. 95 130 * 96 * It MUST be of size expected_enpoints_count(excluding default ctrl) + 1 97 * where the last record MUST BE NULL, otherwise catastrophic things may 98 * happen. 131 * When the driver expect single interrupt in endpoint, 132 * the initialization may look like this: 133 \code 134 static usb_endpoint_description_t poll_endpoint_description = { 135 .transfer_type = USB_TRANSFER_INTERRUPT, 136 .direction = USB_DIRECTION_IN, 137 .interface_class = USB_CLASS_HUB, 138 .interface_subclass = 0, 139 .interface_protocol = 0, 140 .flags = 0 141 }; 142 143 static usb_endpoint_description_t *hub_endpoints[] = { 144 &poll_endpoint_description, 145 NULL 146 }; 147 148 static usb_driver_t hub_driver = { 149 .endpoints = hub_endpoints, 150 ... 151 }; 152 \endcode 99 153 */ 100 154 usb_endpoint_description_t **endpoints; … … 105 159 int usb_driver_main(usb_driver_t *); 106 160 161 int usb_device_select_interface(usb_device_t *, uint8_t, 162 usb_endpoint_description_t **); 163 107 164 typedef bool (*usb_polling_callback_t)(usb_device_t *, 108 165 uint8_t *, size_t, void *); 109 166 typedef void (*usb_polling_terminted_callback_t)(usb_device_t *, bool, void *); 110 111 167 112 168 int usb_device_auto_poll(usb_device_t *, size_t, -
uspace/lib/usb/include/usb/pipes.h
rb8f7a0d2 r0cec844d 107 107 /** Interface number the endpoint must belong to (-1 for any). */ 108 108 int interface_no; 109 /** Alternate interface setting to choose. */ 110 int interface_setting; 109 111 /** Found descriptor fitting the description. */ 110 112 usb_standard_endpoint_descriptor_t *descriptor; -
uspace/lib/usb/src/devdrv.c
rb8f7a0d2 r0cec844d 36 36 #include <usb/request.h> 37 37 #include <usb/debug.h> 38 #include <usb/dp.h> 38 39 #include <errno.h> 39 40 #include <str_error.h> … … 86 87 * @return Number of pipes (excluding default control pipe). 87 88 */ 88 static size_t count_other_pipes(usb_ driver_t *drv)89 static size_t count_other_pipes(usb_endpoint_description_t **endpoints) 89 90 { 90 91 size_t count = 0; 91 if ( drv->endpoints == NULL) {92 if (endpoints == NULL) { 92 93 return 0; 93 94 } 94 95 95 while ( drv->endpoints[count] != NULL) {96 while (endpoints[count] != NULL) { 96 97 count++; 97 98 } … … 106 107 * @return Error code. 107 108 */ 108 static int initialize_other_pipes(usb_driver_t *drv, usb_device_t *dev) 109 static int initialize_other_pipes(usb_endpoint_description_t **endpoints, 110 usb_device_t *dev) 109 111 { 110 112 int rc; 111 dev->interface_no = usb_device_get_assigned_interface(dev->ddf_dev); 112 113 size_t pipe_count = count_other_pipes(drv); 113 114 size_t pipe_count = count_other_pipes(endpoints); 115 if (pipe_count == 0) { 116 return EOK; 117 } 118 114 119 dev->pipes = malloc(sizeof(usb_endpoint_mapping_t) * pipe_count); 115 120 if (dev->pipes == NULL) { … … 133 138 } 134 139 135 dev->pipes[i].description = drv->endpoints[i];140 dev->pipes[i].description = endpoints[i]; 136 141 dev->pipes[i].interface_no = dev->interface_no; 142 dev->pipes[i].interface_setting = 0; 137 143 } 138 144 … … 178 184 usb_hc_connection_close(&hc_conn); 179 185 186 dev->pipes_count = pipe_count; 187 180 188 return EOK; 181 189 … … 227 235 } 228 236 237 /* Get our interface. */ 238 dev->interface_no = usb_device_get_assigned_interface(dev->ddf_dev); 239 229 240 /* 230 241 * For further actions, we need open session on default control pipe. … … 257 268 258 269 if (driver->endpoints != NULL) { 259 rc = initialize_other_pipes(driver , dev);270 rc = initialize_other_pipes(driver->endpoints, dev); 260 271 } 261 272 … … 271 282 272 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; 406 407 return EOK; 273 408 } 274 409 … … 301 436 dev->descriptors.configuration = NULL; 302 437 438 dev->pipes_count = 0; 439 dev->pipes = NULL; 440 303 441 rc = initialize_pipes(dev); 304 442 if (rc != EOK) { … … 307 445 } 308 446 447 (void) initialize_alternate_interfaces(dev); 448 309 449 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 issuing 499 * proper USB command to the device and also creates new USB pipes 500 * 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 interface 504 * manually using usb_request_set_interface() and creating new pipes 505 * 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; 310 540 } 311 541 -
uspace/lib/usb/src/pipesinit.c
rb8f7a0d2 r0cec844d 121 121 usb_endpoint_mapping_t *mapping, size_t mapping_count, 122 122 usb_endpoint_description_t *found_endpoint, 123 int interface_number )123 int interface_number, int interface_setting) 124 124 { 125 125 while (mapping_count > 0) { … … 127 127 || (mapping->interface_no == interface_number); 128 128 129 bool interface_setting_fits = (mapping->interface_setting < 0) 130 || (mapping->interface_setting == interface_setting); 131 129 132 bool endpoint_descriptions_fits = endpoint_fits_description( 130 133 mapping->description, found_endpoint); 131 134 132 if (interface_number_fits && endpoint_descriptions_fits) { 135 if (interface_number_fits 136 && interface_setting_fits 137 && endpoint_descriptions_fits) { 133 138 return mapping; 134 139 } … … 181 186 */ 182 187 usb_endpoint_mapping_t *ep_mapping = find_endpoint_mapping(mapping, 183 mapping_count, &description, interface->interface_number); 188 mapping_count, &description, 189 interface->interface_number, interface->alternate_setting); 184 190 if (ep_mapping == NULL) { 185 191 return ENOENT;
Note:
See TracChangeset
for help on using the changeset viewer.
