Changes in / [0cec844:b8f7a0d2] in mainline
- Files:
-
- 8 edited
Legend:
- Unmodified
- Added
- Removed
-
.bzrignore
r0cec844 rb8f7a0d2 93 93 ./uspace/drv/usbhub/usbhub 94 94 ./uspace/drv/usbhid/usbhid 95 ./uspace/drv/usbkbd/usbkbd96 95 ./uspace/drv/usbmid/usbmid 97 96 ./uspace/drv/usbmouse/usbmouse -
uspace/drv/usbmid/explore.c
r0cec844 rb8f7a0d2 48 48 }; 49 49 50 /** Tell whether given interface is already in the list. 51 * 52 * @param list List of usbmid_interface_t members to be searched. 53 * @param interface_no Interface number caller is looking for. 54 * @return Interface @p interface_no is already present in the list. 55 */ 56 static bool interface_in_list(link_t *list, int interface_no) 50 /** Find starting indexes of all interface descriptors in a configuration. 51 * 52 * @param config_descriptor Full configuration descriptor. 53 * @param config_descriptor_size Size of @p config_descriptor in bytes. 54 * @param interface_positions Array where to store indexes of interfaces. 55 * @param interface_count Size of @p interface_positions array. 56 * @return Number of found interfaces. 57 * @retval (size_t)-1 Error occured. 58 */ 59 static size_t find_interface_descriptors(uint8_t *config_descriptor, 60 size_t config_descriptor_size, 61 size_t *interface_positions, size_t interface_count) 57 62 { 58 link_t *l; 59 for (l = list->next; l != list; l = l->next) { 60 usbmid_interface_t *iface 61 = list_get_instance(l, usbmid_interface_t, link); 62 if (iface->interface_no == interface_no) { 63 return true; 64 } 65 } 66 67 return false; 68 } 69 70 /** Create list of interfaces from configuration descriptor. 71 * 72 * @param config_descriptor Configuration descriptor. 73 * @param config_descriptor_size Size of configuration descriptor in bytes. 74 * @param list List where to add the interfaces. 75 */ 76 static void create_interfaces(uint8_t *config_descriptor, 77 size_t config_descriptor_size, link_t *list) 78 { 63 if (interface_count == 0) { 64 return (size_t) -1; 65 } 66 79 67 usb_dp_parser_data_t data = { 80 68 .data = config_descriptor, … … 87 75 }; 88 76 89 uint8_t *interface _ptr= usb_dp_get_nested_descriptor(&parser, &data,77 uint8_t *interface = usb_dp_get_nested_descriptor(&parser, &data, 90 78 data.data); 91 if (interface_ptr == NULL) { 92 return; 93 } 94 95 do { 96 if (interface_ptr[1] != USB_DESCTYPE_INTERFACE) { 97 goto next_descriptor; 79 if (interface == NULL) { 80 return (size_t) -1; 81 } 82 if (interface[1] != USB_DESCTYPE_INTERFACE) { 83 return (size_t) -1; 84 } 85 86 size_t found_interfaces = 0; 87 interface_positions[found_interfaces] = interface - config_descriptor; 88 found_interfaces++; 89 90 while (interface != NULL) { 91 interface = usb_dp_get_sibling_descriptor(&parser, &data, 92 data.data, interface); 93 if ((interface != NULL) 94 && (found_interfaces < interface_count) 95 && (interface[1] == USB_DESCTYPE_INTERFACE)) { 96 interface_positions[found_interfaces] 97 = interface - config_descriptor; 98 found_interfaces++; 98 99 } 99 100 usb_standard_interface_descriptor_t *interface 101 = (usb_standard_interface_descriptor_t *) interface_ptr; 102 103 /* Skip alternate interfaces. */ 104 if (!interface_in_list(list, interface->interface_number)) { 105 usbmid_interface_t *iface 106 = malloc(sizeof(usbmid_interface_t)); 107 if (iface == NULL) { 108 break; 109 } 110 link_initialize(&iface->link); 111 iface->fun = NULL; 112 iface->interface_no = interface->interface_number; 113 iface->interface = interface; 114 115 list_append(&iface->link, list); 116 } 117 118 /* TODO: add the alternatives and create match ids from them 119 * as well. 120 */ 121 122 next_descriptor: 123 interface_ptr = usb_dp_get_sibling_descriptor(&parser, &data, 124 data.data, interface_ptr); 125 126 } while (interface_ptr != NULL); 127 100 } 101 102 return found_interfaces; 128 103 } 129 104 … … 155 130 (usb_standard_configuration_descriptor_t *) config_descriptor_raw; 156 131 132 size_t *interface_descriptors 133 = malloc(sizeof(size_t) * config_descriptor->interface_count); 134 if (interface_descriptors == NULL) { 135 usb_log_error("Out of memory (wanted %zuB).\n", 136 sizeof(size_t) * config_descriptor->interface_count); 137 free(config_descriptor_raw); 138 return false; 139 } 140 size_t interface_descriptors_count 141 = find_interface_descriptors( 142 config_descriptor_raw, config_descriptor_size, 143 interface_descriptors, config_descriptor->interface_count); 144 145 if (interface_descriptors_count == (size_t) -1) { 146 usb_log_error("Problem parsing configuration descriptor.\n"); 147 free(interface_descriptors); 148 return false; 149 } 150 157 151 /* Select the first configuration */ 158 152 rc = usb_request_set_configuration(&dev->ctrl_pipe, … … 161 155 usb_log_error("Failed to set device configuration: %s.\n", 162 156 str_error(rc)); 163 return false; 164 } 157 free(interface_descriptors); 158 return false; 159 } 160 165 161 166 162 /* Create control function */ … … 168 164 if (ctl_fun == NULL) { 169 165 usb_log_error("Failed to create control function.\n"); 166 free(interface_descriptors); 170 167 return false; 171 168 } … … 177 174 usb_log_error("Failed to bind control function: %s.\n", 178 175 str_error(rc)); 179 return false; 180 } 181 182 /* Create interface children. */ 183 link_t interface_list; 184 list_initialize(&interface_list); 185 create_interfaces(config_descriptor_raw, config_descriptor_size, 186 &interface_list); 187 188 link_t *link; 189 for (link = interface_list.next; link != &interface_list; 190 link = link->next) { 191 usbmid_interface_t *iface = list_get_instance(link, 192 usbmid_interface_t, link); 193 176 free(interface_descriptors); 177 return false; 178 } 179 180 /* Spawn interface children */ 181 size_t i; 182 for (i = 0; i < interface_descriptors_count; i++) { 183 usb_standard_interface_descriptor_t *interface 184 = (usb_standard_interface_descriptor_t *) 185 (config_descriptor_raw + interface_descriptors[i]); 186 usb_log_debug2("Interface descriptor at index %zu (type %d).\n", 187 interface_descriptors[i], (int) interface->descriptor_type); 194 188 usb_log_info("Creating child for interface %d (%s).\n", 195 (int) iface->interface_no, 196 usb_str_class(iface->interface->interface_class)); 197 198 rc = usbmid_spawn_interface_child(dev, iface, 199 &dev->descriptors.device, iface->interface); 189 (int) interface->interface_number, 190 usb_str_class(interface->interface_class)); 191 rc = usbmid_spawn_interface_child(dev, &dev->descriptors.device, 192 interface); 200 193 if (rc != EOK) { 201 194 usb_log_error("Failed to create interface child: %s.\n", -
uspace/drv/usbmid/usbmid.c
r0cec844 rb8f7a0d2 79 79 }; 80 80 81 /** Create new interface for USB MID device. 82 * 83 * @param fun Backing generic DDF device function (representing interface). 84 * @param iface_no Interface number. 85 * @return New interface. 86 * @retval NULL Error occured. 87 */ 88 usbmid_interface_t *usbmid_interface_create(ddf_fun_t *fun, int iface_no) 89 { 90 usbmid_interface_t *iface = malloc(sizeof(usbmid_interface_t)); 91 if (iface == NULL) { 92 usb_log_error("Out of memory (wanted %zuB).\n", 93 sizeof(usbmid_interface_t)); 94 return NULL; 95 } 96 97 iface->fun = fun; 98 iface->interface_no = iface_no; 99 100 return iface; 101 } 102 81 103 82 104 /** Spawn new child device from one interface. 83 105 * 84 106 * @param parent Parent MID device. 85 * @param iface Interface information.86 107 * @param device_descriptor Device descriptor. 87 108 * @param interface_descriptor Interface descriptor. … … 89 110 */ 90 111 int usbmid_spawn_interface_child(usb_device_t *parent, 91 usbmid_interface_t *iface,92 112 const usb_standard_device_descriptor_t *device_descriptor, 93 113 const usb_standard_interface_descriptor_t *interface_descriptor) … … 95 115 ddf_fun_t *child = NULL; 96 116 char *child_name = NULL; 117 usbmid_interface_t *child_as_interface = NULL; 97 118 int rc; 98 119 … … 116 137 } 117 138 118 iface->fun = child;119 139 120 child->driver_data = iface; 140 141 child_as_interface = usbmid_interface_create(child, 142 (int) interface_descriptor->interface_number); 143 if (child_as_interface == NULL) { 144 rc = ENOMEM; 145 goto error_leave; 146 } 147 148 child->driver_data = child_as_interface; 121 149 child->ops = &child_device_ops; 122 150 … … 144 172 free(child_name); 145 173 } 174 if (child_as_interface != NULL) { 175 free(child_as_interface); 176 } 146 177 147 178 return rc; -
uspace/drv/usbmid/usbmid.h
r0cec844 rb8f7a0d2 37 37 #define USBMID_H_ 38 38 39 #include <adt/list.h>40 39 #include <ddf/driver.h> 41 40 #include <usb/usb.h> … … 50 49 /** Function container. */ 51 50 ddf_fun_t *fun; 52 /** Interface descriptor. */ 53 usb_standard_interface_descriptor_t *interface; 51 54 52 /** Interface number. */ 55 53 int interface_no; 56 /** List link. */57 link_t link;58 54 } usbmid_interface_t; 59 55 56 usbmid_interface_t *usbmid_interface_create(ddf_fun_t *, int); 60 57 bool usbmid_explore_device(usb_device_t *); 61 int usbmid_spawn_interface_child(usb_device_t *, usbmid_interface_t *,58 int usbmid_spawn_interface_child(usb_device_t *, 62 59 const usb_standard_device_descriptor_t *, 63 60 const usb_standard_interface_descriptor_t *); -
uspace/lib/usb/include/usb/devdrv.h
r0cec844 rb8f7a0d2 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 and51 * 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 72 49 /** USB device structure. */ 73 50 typedef struct { … … 79 56 */ 80 57 usb_endpoint_mapping_t *pipes; 81 /** Number of other endpoint pipes. */82 size_t pipes_count;83 58 /** Current interface. 84 59 * Usually, drivers operate on single interface only. … … 86 61 */ 87 62 int interface_no; 88 89 /** Alternative interfaces.90 * Set to NULL when the driver controls whole device91 * (i.e. more (or any) interfaces).92 */93 usb_alternate_interfaces_t *alternate_interfaces;94 63 95 64 /** Some useful descriptors. */ … … 123 92 */ 124 93 const char *name; 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. 94 /** Expected endpoints description, excluding default control endpoint. 130 95 * 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 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. 153 99 */ 154 100 usb_endpoint_description_t **endpoints; … … 159 105 int usb_driver_main(usb_driver_t *); 160 106 161 int usb_device_select_interface(usb_device_t *, uint8_t,162 usb_endpoint_description_t **);163 164 107 typedef bool (*usb_polling_callback_t)(usb_device_t *, 165 108 uint8_t *, size_t, void *); 166 109 typedef void (*usb_polling_terminted_callback_t)(usb_device_t *, bool, void *); 110 167 111 168 112 int usb_device_auto_poll(usb_device_t *, size_t, -
uspace/lib/usb/include/usb/pipes.h
r0cec844 rb8f7a0d2 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;111 109 /** Found descriptor fitting the description. */ 112 110 usb_standard_endpoint_descriptor_t *descriptor; -
uspace/lib/usb/src/devdrv.c
r0cec844 rb8f7a0d2 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 -
uspace/lib/usb/src/pipesinit.c
r0cec844 rb8f7a0d2 121 121 usb_endpoint_mapping_t *mapping, size_t mapping_count, 122 122 usb_endpoint_description_t *found_endpoint, 123 int interface_number , int interface_setting)123 int interface_number) 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 132 129 bool endpoint_descriptions_fits = endpoint_fits_description( 133 130 mapping->description, found_endpoint); 134 131 135 if (interface_number_fits 136 && interface_setting_fits 137 && endpoint_descriptions_fits) { 132 if (interface_number_fits && endpoint_descriptions_fits) { 138 133 return mapping; 139 134 } … … 186 181 */ 187 182 usb_endpoint_mapping_t *ep_mapping = find_endpoint_mapping(mapping, 188 mapping_count, &description, 189 interface->interface_number, interface->alternate_setting); 183 mapping_count, &description, interface->interface_number); 190 184 if (ep_mapping == NULL) { 191 185 return ENOENT;
Note:
See TracChangeset
for help on using the changeset viewer.