Changeset 0cec844 in mainline


Ignore:
Timestamp:
2011-04-03T17:39:48Z (13 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

Files:
8 edited

Legend:

Unmodified
Added
Removed
  • .bzrignore

    rb8f7a0d2 r0cec844  
    9393./uspace/drv/usbhub/usbhub
    9494./uspace/drv/usbhid/usbhid
     95./uspace/drv/usbkbd/usbkbd
    9596./uspace/drv/usbmid/usbmid
    9697./uspace/drv/usbmouse/usbmouse
  • 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",
  • uspace/drv/usbmid/usbmid.c

    rb8f7a0d2 r0cec844  
    7979};
    8080
    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 
    10381
    10482/** Spawn new child device from one interface.
    10583 *
    10684 * @param parent Parent MID device.
     85 * @param iface Interface information.
    10786 * @param device_descriptor Device descriptor.
    10887 * @param interface_descriptor Interface descriptor.
     
    11089 */
    11190int usbmid_spawn_interface_child(usb_device_t *parent,
     91    usbmid_interface_t *iface,
    11292    const usb_standard_device_descriptor_t *device_descriptor,
    11393    const usb_standard_interface_descriptor_t *interface_descriptor)
     
    11595        ddf_fun_t *child = NULL;
    11696        char *child_name = NULL;
    117         usbmid_interface_t *child_as_interface = NULL;
    11897        int rc;
    11998
     
    137116        }
    138117
     118        iface->fun = child;
    139119
    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;
     120        child->driver_data = iface;
    149121        child->ops = &child_device_ops;
    150122
     
    172144                free(child_name);
    173145        }
    174         if (child_as_interface != NULL) {
    175                 free(child_as_interface);
    176         }
    177146
    178147        return rc;
  • uspace/drv/usbmid/usbmid.h

    rb8f7a0d2 r0cec844  
    3737#define USBMID_H_
    3838
     39#include <adt/list.h>
    3940#include <ddf/driver.h>
    4041#include <usb/usb.h>
     
    4950        /** Function container. */
    5051        ddf_fun_t *fun;
    51 
     52        /** Interface descriptor. */
     53        usb_standard_interface_descriptor_t *interface;
    5254        /** Interface number. */
    5355        int interface_no;
     56        /** List link. */
     57        link_t link;
    5458} usbmid_interface_t;
    5559
    56 usbmid_interface_t *usbmid_interface_create(ddf_fun_t *, int);
    5760bool usbmid_explore_device(usb_device_t *);
    58 int usbmid_spawn_interface_child(usb_device_t *,
     61int usbmid_spawn_interface_child(usb_device_t *, usbmid_interface_t *,
    5962    const usb_standard_device_descriptor_t *,
    6063    const usb_standard_interface_descriptor_t *);
  • uspace/lib/usb/include/usb/devdrv.h

    rb8f7a0d2 r0cec844  
    4747} usb_device_descriptors_t;
    4848
     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 */
     53typedef 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. */
     63typedef 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
    4972/** USB device structure. */
    5073typedef struct {
     
    5679         */
    5780        usb_endpoint_mapping_t *pipes;
     81        /** Number of other endpoint pipes. */
     82        size_t pipes_count;
    5883        /** Current interface.
    5984         * Usually, drivers operate on single interface only.
     
    6186         */
    6287        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;
    6394
    6495        /** Some useful descriptors. */
     
    92123         */
    93124        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.
    95130         *
    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
     134static 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
     143static usb_endpoint_description_t *hub_endpoints[] = {
     144        &poll_endpoint_description,
     145        NULL
     146};
     147
     148static usb_driver_t hub_driver = {
     149        .endpoints = hub_endpoints,
     150        ...
     151};
     152\endcode
    99153         */
    100154        usb_endpoint_description_t **endpoints;
     
    105159int usb_driver_main(usb_driver_t *);
    106160
     161int usb_device_select_interface(usb_device_t *, uint8_t,
     162    usb_endpoint_description_t **);
     163
    107164typedef bool (*usb_polling_callback_t)(usb_device_t *,
    108165    uint8_t *, size_t, void *);
    109166typedef void (*usb_polling_terminted_callback_t)(usb_device_t *, bool, void *);
    110 
    111167
    112168int usb_device_auto_poll(usb_device_t *, size_t,
  • uspace/lib/usb/include/usb/pipes.h

    rb8f7a0d2 r0cec844  
    107107        /** Interface number the endpoint must belong to (-1 for any). */
    108108        int interface_no;
     109        /** Alternate interface setting to choose. */
     110        int interface_setting;
    109111        /** Found descriptor fitting the description. */
    110112        usb_standard_endpoint_descriptor_t *descriptor;
  • uspace/lib/usb/src/devdrv.c

    rb8f7a0d2 r0cec844  
    3636#include <usb/request.h>
    3737#include <usb/debug.h>
     38#include <usb/dp.h>
    3839#include <errno.h>
    3940#include <str_error.h>
     
    8687 * @return Number of pipes (excluding default control pipe).
    8788 */
    88 static size_t count_other_pipes(usb_driver_t *drv)
     89static size_t count_other_pipes(usb_endpoint_description_t **endpoints)
    8990{
    9091        size_t count = 0;
    91         if (drv->endpoints == NULL) {
     92        if (endpoints == NULL) {
    9293                return 0;
    9394        }
    9495
    95         while (drv->endpoints[count] != NULL) {
     96        while (endpoints[count] != NULL) {
    9697                count++;
    9798        }
     
    106107 * @return Error code.
    107108 */
    108 static int initialize_other_pipes(usb_driver_t *drv, usb_device_t *dev)
     109static int initialize_other_pipes(usb_endpoint_description_t **endpoints,
     110    usb_device_t *dev)
    109111{
    110112        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
    114119        dev->pipes = malloc(sizeof(usb_endpoint_mapping_t) * pipe_count);
    115120        if (dev->pipes == NULL) {
     
    133138                }
    134139
    135                 dev->pipes[i].description = drv->endpoints[i];
     140                dev->pipes[i].description = endpoints[i];
    136141                dev->pipes[i].interface_no = dev->interface_no;
     142                dev->pipes[i].interface_setting = 0;
    137143        }
    138144
     
    178184        usb_hc_connection_close(&hc_conn);
    179185
     186        dev->pipes_count = pipe_count;
     187
    180188        return EOK;
    181189
     
    227235        }
    228236
     237        /* Get our interface. */
     238        dev->interface_no = usb_device_get_assigned_interface(dev->ddf_dev);
     239
    229240        /*
    230241         * For further actions, we need open session on default control pipe.
     
    257268
    258269        if (driver->endpoints != NULL) {
    259                 rc = initialize_other_pipes(driver, dev);
     270                rc = initialize_other_pipes(driver->endpoints, dev);
    260271        }
    261272
     
    271282
    272283        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 */
     293static 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 */
     330static 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;
    273408}
    274409
     
    301436        dev->descriptors.configuration = NULL;
    302437
     438        dev->pipes_count = 0;
     439        dev->pipes = NULL;
     440
    303441        rc = initialize_pipes(dev);
    304442        if (rc != EOK) {
     
    307445        }
    308446
     447        (void) initialize_alternate_interfaces(dev);
     448
    309449        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 */
     457static 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 */
     512int 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;
    310540}
    311541
  • uspace/lib/usb/src/pipesinit.c

    rb8f7a0d2 r0cec844  
    121121    usb_endpoint_mapping_t *mapping, size_t mapping_count,
    122122    usb_endpoint_description_t *found_endpoint,
    123     int interface_number)
     123    int interface_number, int interface_setting)
    124124{
    125125        while (mapping_count > 0) {
     
    127127                    || (mapping->interface_no == interface_number);
    128128
     129                bool interface_setting_fits = (mapping->interface_setting < 0)
     130                    || (mapping->interface_setting == interface_setting);
     131
    129132                bool endpoint_descriptions_fits = endpoint_fits_description(
    130133                    mapping->description, found_endpoint);
    131134
    132                 if (interface_number_fits && endpoint_descriptions_fits) {
     135                if (interface_number_fits
     136                    && interface_setting_fits
     137                    && endpoint_descriptions_fits) {
    133138                        return mapping;
    134139                }
     
    181186         */
    182187        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);
    184190        if (ep_mapping == NULL) {
    185191                return ENOENT;
Note: See TracChangeset for help on using the changeset viewer.