Changes in / [c7bdfa7:1cbb4b7] in mainline


Ignore:
Location:
uspace/lib/usb
Files:
1 deleted
5 edited

Legend:

Unmodified
Added
Removed
  • uspace/lib/usb/Makefile

    rc7bdfa7 r1cbb4b7  
    3434SOURCES = \
    3535        src/addrkeep.c \
    36         src/altiface.c \
    3736        src/class.c \
    3837        src/ddfiface.c \
  • uspace/lib/usb/include/usb/devdrv.h

    rc7bdfa7 r1cbb4b7  
    174174    usb_endpoint_mapping_t **, size_t *);
    175175int usb_device_destroy_pipes(ddf_dev_t *, usb_endpoint_mapping_t *, size_t);
    176 int usb_device_create(ddf_dev_t *, usb_endpoint_description_t **, usb_device_t **, const char **);
    177176
    178177size_t usb_interface_count_alternates(uint8_t *, size_t, uint8_t);
    179 int usb_alternate_interfaces_create(uint8_t *, size_t, int,
    180     usb_alternate_interfaces_t **);
    181178
    182179#endif
  • uspace/lib/usb/include/usb/request.h

    rc7bdfa7 r1cbb4b7  
    5050/** USB endpoint status - endpoint is halted (stalled). */
    5151#define USB_ENDPOINT_STATUS_HALTED ((uint16_t)(1 << 0))
    52 
    53 /** USB feature selector - endpoint halt (stall). */
    54 #define USB_FEATURE_SELECTOR_ENDPOINT_HALT (0)
    55 
    56 /** USB feature selector - device remote wake-up. */
    57 #define USB_FEATURE_SELECTOR_REMOTE_WAKEUP (1)
    5852
    5953/** Standard device request. */
     
    141135    char **);
    142136
    143 int usb_request_clear_endpoint_halt(usb_pipe_t *, uint16_t);
    144 
    145137#endif
    146138/**
  • uspace/lib/usb/src/devdrv.c

    rc7bdfa7 r1cbb4b7  
    100100    usb_device_t *dev, int alternate_setting)
    101101{
    102         if (endpoints == NULL) {
    103                 dev->pipes = NULL;
    104                 dev->pipes_count = 0;
    105                 return EOK;
    106         }
    107 
    108102        usb_endpoint_mapping_t *pipes;
    109103        size_t pipes_count;
     
    115109
    116110        if (rc != EOK) {
     111                usb_log_error(
     112                    "Failed to create endpoint pipes for `%s': %s.\n",
     113                    dev->ddf_dev->name, str_error(rc));
    117114                return rc;
    118115        }
     
    120117        dev->pipes = pipes;
    121118        dev->pipes_count = pipes_count;
     119
     120        return EOK;
     121}
     122
     123/** Initialize all endpoint pipes.
     124 *
     125 * @param drv The driver.
     126 * @param dev The device to be initialized.
     127 * @return Error code.
     128 */
     129static int initialize_pipes(usb_device_t *dev)
     130{
     131        int rc;
     132
     133        rc = usb_device_connection_initialize_from_device(&dev->wire,
     134            dev->ddf_dev);
     135        if (rc != EOK) {
     136                usb_log_error(
     137                    "Failed initializing connection on device `%s'. %s.\n",
     138                    dev->ddf_dev->name, str_error(rc));
     139                return rc;
     140        }
     141
     142        rc = usb_pipe_initialize_default_control(&dev->ctrl_pipe,
     143            &dev->wire);
     144        if (rc != EOK) {
     145                usb_log_error("Failed to initialize default control pipe " \
     146                    "on device `%s': %s.\n",
     147                    dev->ddf_dev->name, str_error(rc));
     148                return rc;
     149        }
     150
     151        rc = usb_pipe_probe_default_control(&dev->ctrl_pipe);
     152        if (rc != EOK) {
     153                usb_log_error(
     154                    "Probing default control pipe on device `%s' failed: %s.\n",
     155                    dev->ddf_dev->name, str_error(rc));
     156                return rc;
     157        }
     158
     159        /* Get our interface. */
     160        dev->interface_no = usb_device_get_assigned_interface(dev->ddf_dev);
     161
     162        /*
     163         * We will do some querying of the device, it is worth to prepare
     164         * the long transfer.
     165         */
     166        rc = usb_pipe_start_long_transfer(&dev->ctrl_pipe);
     167        if (rc != EOK) {
     168                usb_log_error("Failed to start transfer: %s.\n",
     169                    str_error(rc));
     170                return rc;
     171        }
     172
     173        /* Retrieve the descriptors. */
     174        rc = usb_device_retrieve_descriptors(&dev->ctrl_pipe,
     175            &dev->descriptors);
     176        if (rc != EOK) {
     177                usb_log_error("Failed to retrieve standard device " \
     178                    "descriptors of %s: %s.\n",
     179                    dev->ddf_dev->name, str_error(rc));
     180                return rc;
     181        }
     182
     183
     184        if (driver->endpoints != NULL) {
     185                rc = initialize_other_pipes(driver->endpoints, dev, 0);
     186        }
     187
     188        usb_pipe_end_long_transfer(&dev->ctrl_pipe);
     189
     190        /* Rollback actions. */
     191        if (rc != EOK) {
     192                if (dev->descriptors.configuration != NULL) {
     193                        free(dev->descriptors.configuration);
     194                }
     195        }
     196
     197        return rc;
     198}
     199
     200/** Count number of alternate settings of a interface.
     201 *
     202 * @param config_descr Full configuration descriptor.
     203 * @param config_descr_size Size of @p config_descr in bytes.
     204 * @param interface_no Interface number.
     205 * @return Number of alternate interfaces for @p interface_no interface.
     206 */
     207size_t usb_interface_count_alternates(uint8_t *config_descr,
     208    size_t config_descr_size, uint8_t interface_no)
     209{
     210        assert(config_descr != NULL);
     211        assert(config_descr_size > 0);
     212
     213        usb_dp_parser_t dp_parser = {
     214                .nesting = usb_dp_standard_descriptor_nesting
     215        };
     216        usb_dp_parser_data_t dp_data = {
     217                .data = config_descr,
     218                .size = config_descr_size,
     219                .arg = NULL
     220        };
     221
     222        size_t alternate_count = 0;
     223
     224        uint8_t *iface_ptr = usb_dp_get_nested_descriptor(&dp_parser,
     225            &dp_data, config_descr);
     226        while (iface_ptr != NULL) {
     227                usb_standard_interface_descriptor_t *iface
     228                    = (usb_standard_interface_descriptor_t *) iface_ptr;
     229                if (iface->descriptor_type == USB_DESCTYPE_INTERFACE) {
     230                        if (iface->interface_number == interface_no) {
     231                                alternate_count++;
     232                        }
     233                }
     234                iface_ptr = usb_dp_get_sibling_descriptor(&dp_parser, &dp_data,
     235                    config_descr, iface_ptr);
     236        }
     237
     238        return alternate_count;
     239}
     240
     241/** Initialize structures related to alternate interfaces.
     242 *
     243 * @param dev Device where alternate settings shall be initialized.
     244 * @return Error code.
     245 */
     246static int initialize_alternate_interfaces(usb_device_t *dev)
     247{
     248        if (dev->interface_no < 0) {
     249                dev->alternate_interfaces = NULL;
     250                return EOK;
     251        }
     252
     253        usb_alternate_interfaces_t *alternates
     254            = malloc(sizeof(usb_alternate_interfaces_t));
     255
     256        if (alternates == NULL) {
     257                return ENOMEM;
     258        }
     259
     260        alternates->alternative_count
     261            = usb_interface_count_alternates(dev->descriptors.configuration,
     262            dev->descriptors.configuration_size, dev->interface_no);
     263
     264        if (alternates->alternative_count == 0) {
     265                free(alternates);
     266                return ENOENT;
     267        }
     268
     269        alternates->alternatives = malloc(alternates->alternative_count
     270            * sizeof(usb_alternate_interface_descriptors_t));
     271        if (alternates->alternatives == NULL) {
     272                free(alternates);
     273                return ENOMEM;
     274        }
     275
     276        alternates->current = 0;
     277
     278        usb_dp_parser_t dp_parser = {
     279                .nesting = usb_dp_standard_descriptor_nesting
     280        };
     281        usb_dp_parser_data_t dp_data = {
     282                .data = dev->descriptors.configuration,
     283                .size = dev->descriptors.configuration_size,
     284                .arg = NULL
     285        };
     286
     287        usb_alternate_interface_descriptors_t *cur_alt_iface
     288            = &alternates->alternatives[0];
     289
     290        uint8_t *iface_ptr = usb_dp_get_nested_descriptor(&dp_parser,
     291            &dp_data, dp_data.data);
     292        while (iface_ptr != NULL) {
     293                usb_standard_interface_descriptor_t *iface
     294                    = (usb_standard_interface_descriptor_t *) iface_ptr;
     295                if ((iface->descriptor_type != USB_DESCTYPE_INTERFACE)
     296                    || (iface->interface_number != dev->interface_no)) {
     297                        iface_ptr = usb_dp_get_sibling_descriptor(&dp_parser,
     298                            &dp_data,
     299                            dp_data.data, iface_ptr);
     300                        continue;
     301                }
     302
     303                cur_alt_iface->interface = iface;
     304                cur_alt_iface->nested_descriptors = iface_ptr + sizeof(*iface);
     305
     306                /* Find next interface to count size of nested descriptors. */
     307                iface_ptr = usb_dp_get_sibling_descriptor(&dp_parser, &dp_data,
     308                    dp_data.data, iface_ptr);
     309                if (iface_ptr == NULL) {
     310                        uint8_t *next = dp_data.data + dp_data.size;
     311                        cur_alt_iface->nested_descriptors_size
     312                            = next - cur_alt_iface->nested_descriptors;
     313                } else {
     314                        cur_alt_iface->nested_descriptors_size
     315                            = iface_ptr - cur_alt_iface->nested_descriptors;
     316                }
     317
     318                cur_alt_iface++;
     319        }
     320
     321        dev->alternate_interfaces = alternates;
    122322
    123323        return EOK;
     
    139339        int rc;
    140340
    141         usb_device_t *dev = NULL;
    142         const char *err_msg = NULL;
    143         rc = usb_device_create(gen_dev, driver->endpoints, &dev, &err_msg);
    144         if (rc != EOK) {
    145                 usb_log_error("USB device `%s' creation failed (%s): %s.\n",
    146                     gen_dev->name, err_msg, str_error(rc));
    147                 return rc;
    148         }
     341        usb_device_t *dev = malloc(sizeof(usb_device_t));
     342        if (dev == NULL) {
     343                usb_log_error("Out of memory when adding device `%s'.\n",
     344                    gen_dev->name);
     345                return ENOMEM;
     346        }
     347
     348
     349        dev->ddf_dev = gen_dev;
     350        dev->ddf_dev->driver_data = dev;
     351        dev->driver_data = NULL;
     352        dev->descriptors.configuration = NULL;
     353
     354        dev->pipes_count = 0;
     355        dev->pipes = NULL;
     356
     357        rc = initialize_pipes(dev);
     358        if (rc != EOK) {
     359                free(dev);
     360                return rc;
     361        }
     362
     363        (void) initialize_alternate_interfaces(dev);
    149364
    150365        return driver->ops->add_device(dev);
     
    180395 * with usb_pipe_initialize_from_configuration().
    181396 *
    182  * @warning This is a wrapper function that does several operations that
    183  * can fail and that cannot be rollbacked easily. That means that a failure
    184  * during the SET_INTERFACE request would result in having a device with
    185  * no pipes at all (except the default control one). That is because the old
    186  * pipes needs to be unregistered at HC first and the new ones could not
    187  * be created.
    188  *
    189397 * @param dev USB device.
    190398 * @param alternate_setting Alternate setting to choose.
     
    201409        int rc;
    202410
     411        /* TODO: more transactional behavior. */
     412
    203413        /* Destroy existing pipes. */
    204414        rc = destroy_current_pipes(dev);
     
    222432/** Retrieve basic descriptors from the device.
    223433 *
    224  * @param[in] ctrl_pipe Control endpoint pipe.
     434 * @param[in] ctrl_pipe Control pipe with opened session.
    225435 * @param[out] descriptors Where to store the descriptors.
    226436 * @return Error code.
     
    230440{
    231441        assert(descriptors != NULL);
     442        assert(usb_pipe_is_session_started(ctrl_pipe));
    232443
    233444        descriptors->configuration = NULL;
    234445
    235446        int rc;
    236 
    237         /* It is worth to start a long transfer. */
    238         rc = usb_pipe_start_long_transfer(ctrl_pipe);
    239         if (rc != EOK) {
    240                 return rc;
    241         }
    242447
    243448        /* Get the device descriptor. */
    244449        rc = usb_request_get_device_descriptor(ctrl_pipe, &descriptors->device);
    245450        if (rc != EOK) {
    246                 goto leave;
     451                return rc;
    247452        }
    248453
     
    251456            ctrl_pipe, 0, (void **) &descriptors->configuration,
    252457            &descriptors->configuration_size);
    253 
    254 leave:
    255         usb_pipe_end_long_transfer(ctrl_pipe);
    256 
    257         return rc;
     458        if (rc != EOK) {
     459                return rc;
     460        }
     461
     462        return EOK;
    258463}
    259464
     
    436641}
    437642
    438 /** Initialize control pipe in a device.
    439  *
    440  * @param dev USB device in question.
    441  * @param errmsg Where to store error context.
    442  * @return
    443  */
    444 static int init_wire_and_ctrl_pipe(usb_device_t *dev, const char **errmsg)
    445 {
    446         int rc;
    447 
    448         rc = usb_device_connection_initialize_from_device(&dev->wire,
    449             dev->ddf_dev);
    450         if (rc != EOK) {
    451                 *errmsg = "device connection initialization";
    452                 return rc;
    453         }
    454 
    455         rc = usb_pipe_initialize_default_control(&dev->ctrl_pipe,
    456             &dev->wire);
    457         if (rc != EOK) {
    458                 *errmsg = "default control pipe initialization";
    459                 return rc;
    460         }
    461 
    462         return EOK;
    463 }
    464 
    465 
    466 /** Create new instance of USB device.
    467  *
    468  * @param[in] ddf_dev Generic DDF device backing the USB one.
    469  * @param[in] endpoints NULL terminated array of endpoints (NULL for none).
    470  * @param[out] dev_ptr Where to store pointer to the new device.
    471  * @param[out] errstr_ptr Where to store description of context
    472  *      (in case error occurs).
    473  * @return Error code.
    474  */
    475 int usb_device_create(ddf_dev_t *ddf_dev,
    476     usb_endpoint_description_t **endpoints,
    477     usb_device_t **dev_ptr, const char **errstr_ptr)
    478 {
    479         assert(dev_ptr != NULL);
    480         assert(ddf_dev != NULL);
    481 
    482         int rc;
    483 
    484         usb_device_t *dev = malloc(sizeof(usb_device_t));
    485         if (dev == NULL) {
    486                 *errstr_ptr = "structure allocation";
    487                 return ENOMEM;
    488         }
    489 
    490         // FIXME: proper deallocation in case of errors
    491 
    492         dev->ddf_dev = ddf_dev;
    493         dev->driver_data = NULL;
    494         dev->descriptors.configuration = NULL;
    495         dev->alternate_interfaces = NULL;
    496 
    497         dev->pipes_count = 0;
    498         dev->pipes = NULL;
    499 
    500         /* Initialize backing wire and control pipe. */
    501         rc = init_wire_and_ctrl_pipe(dev, errstr_ptr);
    502         if (rc != EOK) {
    503                 return rc;
    504         }
    505 
    506         /* Get our interface. */
    507         dev->interface_no = usb_device_get_assigned_interface(dev->ddf_dev);
    508 
    509         /* Retrieve standard descriptors. */
    510         rc = usb_device_retrieve_descriptors(&dev->ctrl_pipe,
    511             &dev->descriptors);
    512         if (rc != EOK) {
    513                 *errstr_ptr = "descriptor retrieval";
    514                 return rc;
    515         }
    516 
    517         /* Create alternate interfaces. */
    518         rc = usb_alternate_interfaces_create(dev->descriptors.configuration,
    519             dev->descriptors.configuration_size, dev->interface_no,
    520             &dev->alternate_interfaces);
    521         if (rc != EOK) {
    522                 /* We will try to silently ignore this. */
    523                 dev->alternate_interfaces = NULL;
    524         }
    525 
    526         rc = initialize_other_pipes(endpoints, dev, 0);
    527         if (rc != EOK) {
    528                 *errstr_ptr = "pipes initialization";
    529                 return rc;
    530         }
    531 
    532         *errstr_ptr = NULL;
    533         *dev_ptr = dev;
    534 
    535         return EOK;
    536 }
    537 
    538643/**
    539644 * @}
  • uspace/lib/usb/src/request.c

    rc7bdfa7 r1cbb4b7  
    871871}
    872872
    873 /** Clear halt bit of an endpoint pipe (after pipe stall).
    874  *
    875  * @param pipe Control pipe.
    876  * @param ep_index Endpoint index (in native endianness).
    877  * @return Error code.
    878  */
    879 int usb_request_clear_endpoint_halt(usb_pipe_t *pipe, uint16_t ep_index)
    880 {
    881         return usb_request_clear_feature(pipe,
    882             USB_REQUEST_TYPE_STANDARD, USB_REQUEST_RECIPIENT_ENDPOINT,
    883             uint16_host2usb(USB_FEATURE_SELECTOR_ENDPOINT_HALT),
    884             uint16_host2usb(ep_index));
    885 }
    886 
    887873/**
    888874 * @}
Note: See TracChangeset for help on using the changeset viewer.