Changeset 0cec844 in mainline for uspace/drv/usbmid/explore.c


Ignore:
Timestamp:
2011-04-03T17:39:48Z (14 years ago)
Author:
Vojtech Horky <vojtechhorky@…>
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.
Message:

Add base support for alternate interfaces

File:
1 edited

Legend:

Unmodified
Added
Removed
  • uspace/drv/usbmid/explore.c

    rb8f7a0d2 r0cec844  
    4848};
    4949
    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)
     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 */
     56static bool interface_in_list(link_t *list, int interface_no)
    6257{
    63         if (interface_count == 0) {
    64                 return (size_t) -1;
    65         }
    66 
     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 */
     76static void create_interfaces(uint8_t *config_descriptor,
     77    size_t config_descriptor_size, link_t *list)
     78{
    6779        usb_dp_parser_data_t data = {
    6880                .data = config_descriptor,
     
    7587        };
    7688
    77         uint8_t *interface = usb_dp_get_nested_descriptor(&parser, &data,
     89        uint8_t *interface_ptr = usb_dp_get_nested_descriptor(&parser, &data,
    7890            data.data);
    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++;
    99                 }
    100         }
    101 
    102         return found_interfaces;
     91        if (interface_ptr == NULL) {
     92                return;
     93        }
     94
     95        do {
     96                if (interface_ptr[1] != USB_DESCTYPE_INTERFACE) {
     97                        goto next_descriptor;
     98                }
     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
     122next_descriptor:
     123                interface_ptr = usb_dp_get_sibling_descriptor(&parser, &data,
     124                    data.data, interface_ptr);
     125
     126        } while (interface_ptr != NULL);
     127
    103128}
    104129
     
    130155            (usb_standard_configuration_descriptor_t *) config_descriptor_raw;
    131156
    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 
    151157        /* Select the first configuration */
    152158        rc = usb_request_set_configuration(&dev->ctrl_pipe,
     
    155161                usb_log_error("Failed to set device configuration: %s.\n",
    156162                    str_error(rc));
    157                 free(interface_descriptors);
    158                 return false;
    159         }
    160 
     163                return false;
     164        }
    161165
    162166        /* Create control function */
     
    164168        if (ctl_fun == NULL) {
    165169                usb_log_error("Failed to create control function.\n");
    166                 free(interface_descriptors);
    167170                return false;
    168171        }
     
    174177                usb_log_error("Failed to bind control function: %s.\n",
    175178                    str_error(rc));
    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);
     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
    188194                usb_log_info("Creating child for interface %d (%s).\n",
    189                     (int) interface->interface_number,
    190                     usb_str_class(interface->interface_class));
    191                 rc = usbmid_spawn_interface_child(dev, &dev->descriptors.device,
    192                     interface);
     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);
    193200                if (rc != EOK) {
    194201                        usb_log_error("Failed to create interface child: %s.\n",
Note: See TracChangeset for help on using the changeset viewer.