Changeset 3f3afb9 in mainline for uspace/lib


Ignore:
Timestamp:
2011-04-11T20:38:37Z (15 years ago)
Author:
Matus Dekanek <smekideki@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
1324ff3, a39cfb8
Parents:
58226b4 (diff), d91645ab (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:

forgotten hub port powering

Location:
uspace/lib
Files:
1 added
16 edited

Legend:

Unmodified
Added
Removed
  • uspace/lib/drv/generic/remote_usbhc.c

    r58226b4 r3f3afb9  
    5050static void remote_usbhc_control_write(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
    5151static void remote_usbhc_control_read(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
    52 static void remote_usbhc_reserve_default_address(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
    53 static void remote_usbhc_release_default_address(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
    5452static void remote_usbhc_request_address(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
    5553static void remote_usbhc_bind_address(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
     
    6159/** Remote USB host controller interface operations. */
    6260static remote_iface_func_ptr_t remote_usbhc_iface_ops [] = {
    63         remote_usbhc_reserve_default_address,
    64         remote_usbhc_release_default_address,
    65 
    6661        remote_usbhc_request_address,
    6762        remote_usbhc_bind_address,
     
    127122
    128123        return trans;
    129 }
    130 
    131 void remote_usbhc_reserve_default_address(ddf_fun_t *fun, void *iface,
    132     ipc_callid_t callid, ipc_call_t *call)
    133 {
    134         usbhc_iface_t *usb_iface = (usbhc_iface_t *) iface;
    135 
    136         if (!usb_iface->reserve_default_address) {
    137                 async_answer_0(callid, ENOTSUP);
    138                 return;
    139         }
    140        
    141         usb_speed_t speed = DEV_IPC_GET_ARG1(*call);
    142        
    143         int rc = usb_iface->reserve_default_address(fun, speed);
    144 
    145         async_answer_0(callid, rc);
    146 }
    147 
    148 void remote_usbhc_release_default_address(ddf_fun_t *fun, void *iface,
    149     ipc_callid_t callid, ipc_call_t *call)
    150 {
    151         usbhc_iface_t *usb_iface = (usbhc_iface_t *) iface;
    152 
    153         if (!usb_iface->release_default_address) {
    154                 async_answer_0(callid, ENOTSUP);
    155                 return;
    156         }
    157 
    158         int rc = usb_iface->release_default_address(fun);
    159 
    160         async_answer_0(callid, rc);
    161124}
    162125
  • uspace/lib/drv/include/usbhc_iface.h

    r58226b4 r3f3afb9  
    8484 */
    8585typedef enum {
    86         /** Reserve usage of default address.
    87          * This call informs the host controller that the caller will be
    88          * using default USB address. It is duty of the HC driver to ensure
    89          * that only single entity will have it reserved.
    90          * The address is returned via IPC_M_USBHC_RELEASE_DEFAULT_ADDRESS.
    91          * The caller can start using the address after receiving EOK
    92          * answer.
    93          */
    94         IPC_M_USBHC_RESERVE_DEFAULT_ADDRESS,
    95 
    96         /** Release usage of default address.
    97          * @see IPC_M_USBHC_RESERVE_DEFAULT_ADDRESS
    98          */
    99         IPC_M_USBHC_RELEASE_DEFAULT_ADDRESS,
    100 
    10186        /** Asks for address assignment by host controller.
    10287         * Answer:
  • uspace/lib/usb/Makefile

    r58226b4 r3f3afb9  
    3434SOURCES = \
    3535        src/addrkeep.c \
     36        src/altiface.c \
    3637        src/class.c \
    3738        src/ddfiface.c \
  • uspace/lib/usb/include/usb/devdrv.h

    r58226b4 r3f3afb9  
    174174    usb_endpoint_mapping_t **, size_t *);
    175175int usb_device_destroy_pipes(ddf_dev_t *, usb_endpoint_mapping_t *, size_t);
     176int usb_device_create(ddf_dev_t *, usb_endpoint_description_t **, usb_device_t **, const char **);
    176177
    177178size_t usb_interface_count_alternates(uint8_t *, size_t, uint8_t);
     179int usb_alternate_interfaces_create(uint8_t *, size_t, int,
     180    usb_alternate_interfaces_t **);
    178181
    179182#endif
  • uspace/lib/usb/include/usb/host/device_keeper.h

    r58226b4 r3f3afb9  
    7171void usb_device_keeper_init(usb_device_keeper_t *instance);
    7272
    73 void usb_device_keeper_add_ep(
    74     usb_device_keeper_t *instance, usb_address_t address, endpoint_t *ep);
    75 void usb_device_keeper_del_ep(
    76     usb_device_keeper_t *instance, usb_address_t address, endpoint_t *ep);
    77 
    7873void usb_device_keeper_reserve_default_address(
    7974    usb_device_keeper_t *instance, usb_speed_t speed);
  • uspace/lib/usb/include/usb/host/endpoint.h

    r58226b4 r3f3afb9  
    5454        fibril_condvar_t avail;
    5555        volatile bool active;
    56         link_t same_device_eps;
    5756} endpoint_t;
    5857
     
    7170void endpoint_toggle_set(endpoint_t *instance, int toggle);
    7271
    73 void endpoint_toggle_reset(link_t *ep);
    74 
    75 void endpoint_toggle_reset_filtered(link_t *ep, usb_endpoint_t epn);
    76 
     72void endpoint_toggle_reset_filtered(endpoint_t *instance, usb_target_t target);
    7773#endif
    7874/**
  • uspace/lib/usb/include/usb/host/usb_endpoint_manager.h

    r58226b4 r3f3afb9  
    7878    size_t *bw);
    7979
     80void usb_endpoint_manager_reset_if_need(
     81    usb_endpoint_manager_t *instance, usb_target_t target, const uint8_t *data);
    8082#endif
    8183/**
  • uspace/lib/usb/include/usb/hub.h

    r58226b4 r3f3afb9  
    5959} usb_hc_attached_device_t;
    6060
    61 int usb_hc_reserve_default_address(usb_hc_connection_t *, usb_speed_t);
    62 int usb_hc_release_default_address(usb_hc_connection_t *);
    63 
    6461usb_address_t usb_hc_request_address(usb_hc_connection_t *, usb_speed_t);
    6562int usb_hc_register_device(usb_hc_connection_t *,
  • uspace/lib/usb/include/usb/request.h

    r58226b4 r3f3afb9  
    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)
    5258
    5359/** Standard device request. */
     
    135141    char **);
    136142
     143int usb_request_clear_endpoint_halt(usb_pipe_t *, uint16_t);
     144
    137145#endif
    138146/**
  • uspace/lib/usb/src/devdrv.c

    r58226b4 r3f3afb9  
    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
    102108        usb_endpoint_mapping_t *pipes;
    103109        size_t pipes_count;
     
    109115
    110116        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));
    114117                return rc;
    115118        }
     
    117120        dev->pipes = pipes;
    118121        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  */
    129 static 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  */
    207 size_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  */
    246 static 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;
    322122
    323123        return EOK;
     
    339139        int rc;
    340140
    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);
     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        }
    364149
    365150        return driver->ops->add_device(dev);
     
    395180 * with usb_pipe_initialize_from_configuration().
    396181 *
     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 *
    397189 * @param dev USB device.
    398190 * @param alternate_setting Alternate setting to choose.
     
    409201        int rc;
    410202
    411         /* TODO: more transactional behavior. */
    412 
    413203        /* Destroy existing pipes. */
    414204        rc = destroy_current_pipes(dev);
     
    432222/** Retrieve basic descriptors from the device.
    433223 *
    434  * @param[in] ctrl_pipe Control pipe with opened session.
     224 * @param[in] ctrl_pipe Control endpoint pipe.
    435225 * @param[out] descriptors Where to store the descriptors.
    436226 * @return Error code.
     
    440230{
    441231        assert(descriptors != NULL);
    442         assert(usb_pipe_is_session_started(ctrl_pipe));
    443232
    444233        descriptors->configuration = NULL;
    445234
    446235        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        }
    447242
    448243        /* Get the device descriptor. */
    449244        rc = usb_request_get_device_descriptor(ctrl_pipe, &descriptors->device);
    450245        if (rc != EOK) {
    451                 return rc;
     246                goto leave;
    452247        }
    453248
     
    456251            ctrl_pipe, 0, (void **) &descriptors->configuration,
    457252            &descriptors->configuration_size);
    458         if (rc != EOK) {
    459                 return rc;
    460         }
    461 
    462         return EOK;
     253
     254leave:
     255        usb_pipe_end_long_transfer(ctrl_pipe);
     256
     257        return rc;
    463258}
    464259
     
    641436}
    642437
     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 */
     444static 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 */
     475int 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
    643538/**
    644539 * @}
  • uspace/lib/usb/src/hidparser.c

    r58226b4 r3f3afb9  
    900900        item->usage_page = usage_page;
    901901       
     902        usb_log_debug("Appending usage %d, usage page %d\n", usage, usage_page);
     903       
    902904        list_append (&usage_path->link, &item->link);
    903905        usage_path->depth++;
  • uspace/lib/usb/src/host/device_keeper.c

    r58226b4 r3f3afb9  
    5454        for (; i < USB_ADDRESS_COUNT; ++i) {
    5555                instance->devices[i].occupied = false;
    56                 instance->devices[i].control_used = 0;
    5756                instance->devices[i].handle = 0;
    5857                instance->devices[i].speed = USB_SPEED_MAX;
    59                 list_initialize(&instance->devices[i].endpoints);
    6058        }
    6159        // TODO: is this hack enough?
    6260        // (it is needed to allow smooth registration at default address)
    6361        instance->devices[0].occupied = true;
    64 }
    65 /*----------------------------------------------------------------------------*/
    66 void usb_device_keeper_add_ep(
    67     usb_device_keeper_t *instance, usb_address_t address, endpoint_t *ep)
    68 {
    69         assert(instance);
    70         fibril_mutex_lock(&instance->guard);
    71         assert(instance->devices[address].occupied);
    72         list_append(&ep->same_device_eps, &instance->devices[address].endpoints);
    73         fibril_mutex_unlock(&instance->guard);
    74 }
    75 /*----------------------------------------------------------------------------*/
    76 void usb_device_keeper_del_ep(
    77     usb_device_keeper_t *instance, usb_address_t address, endpoint_t *ep)
    78 {
    79         assert(instance);
    80         fibril_mutex_lock(&instance->guard);
    81         assert(instance->devices[address].occupied);
    82         list_remove(&ep->same_device_eps);
    83         list_initialize(&ep->same_device_eps);
    84         fibril_mutex_unlock(&instance->guard);
    8562}
    8663/*----------------------------------------------------------------------------*/
     
    11794}
    11895/*----------------------------------------------------------------------------*/
    119 /** Check setup packet data for signs of toggle reset.
    120  *
    121  * @param[in] instance Device keeper structure to use.
    122  * @param[in] target Device to receive setup packet.
    123  * @param[in] data Setup packet data.
    124  *
    125  * Really ugly one.
    126  */
    127 void usb_device_keeper_reset_if_need(
    128     usb_device_keeper_t *instance, usb_target_t target, const uint8_t *data)
    129 {
    130         assert(instance);
    131         fibril_mutex_lock(&instance->guard);
    132         if (target.endpoint > 15 || target.endpoint < 0
    133             || target.address >= USB_ADDRESS_COUNT || target.address < 0
    134             || !instance->devices[target.address].occupied) {
    135                 fibril_mutex_unlock(&instance->guard);
    136                 usb_log_error("Invalid data when checking for toggle reset.\n");
    137                 return;
    138         }
    139 
    140         switch (data[1])
    141         {
    142         case 0x01: /*clear feature*/
    143                 /* recipient is endpoint, value is zero (ENDPOINT_STALL) */
    144                 if (((data[0] & 0xf) == 1) && ((data[2] | data[3]) == 0)) {
    145                         link_t *current =
    146                             instance->devices[target.address].endpoints.next;
    147                         while (current !=
    148                            &instance->devices[target.address].endpoints)
    149                         {
    150                         /* endpoint number is < 16, thus first byte is enough */
    151                                 endpoint_toggle_reset_filtered(
    152                                     current, data[4]);
    153                                 current = current->next;
    154                         }
    155                 }
    156         break;
    157 
    158         case 0x9: /* set configuration */
    159         case 0x11: /* set interface */
    160                 /* target must be device */
    161                 if ((data[0] & 0xf) == 0) {
    162                         link_t *current =
    163                             instance->devices[target.address].endpoints.next;
    164                         while (current !=
    165                            &instance->devices[target.address].endpoints)
    166                         {
    167                                 endpoint_toggle_reset(current);
    168                                 current = current->next;
    169                         }
    170                 }
    171         break;
    172         }
    173         fibril_mutex_unlock(&instance->guard);
    174 }
    17596/*----------------------------------------------------------------------------*/
    17697/** Get a free USB address
  • uspace/lib/usb/src/host/endpoint.c

    r58226b4 r3f3afb9  
    5353        fibril_mutex_initialize(&instance->guard);
    5454        fibril_condvar_initialize(&instance->avail);
    55         link_initialize(&instance->same_device_eps);
    5655        return EOK;
    5756}
     
    6160        assert(instance);
    6261        assert(!instance->active);
    63         list_remove(&instance->same_device_eps);
    6462        free(instance);
    6563}
     
    9795}
    9896/*----------------------------------------------------------------------------*/
    99 void endpoint_toggle_reset(link_t *ep)
     97void endpoint_toggle_reset_filtered(endpoint_t *instance, usb_target_t target)
    10098{
    101         endpoint_t *instance =
    102             list_get_instance(ep, endpoint_t, same_device_eps);
    10399        assert(instance);
    104         instance->toggle = 0;
    105 }
    106 /*----------------------------------------------------------------------------*/
    107 void endpoint_toggle_reset_filtered(link_t *ep, usb_endpoint_t epn)
    108 {
    109         endpoint_t *instance =
    110             list_get_instance(ep, endpoint_t, same_device_eps);
    111         assert(instance);
    112         if (instance->endpoint == epn)
     100        if (instance->address == target.address &&
     101            (instance->endpoint == target.endpoint || target.endpoint == 0))
    113102                instance->toggle = 0;
    114103}
  • uspace/lib/usb/src/host/usb_endpoint_manager.c

    r58226b4 r3f3afb9  
    3131#include <errno.h>
    3232
     33#include <usb/debug.h>
    3334#include <usb/host/usb_endpoint_manager.h>
    3435
     
    8081        endpoint_destroy(node->ep);
    8182        free(node);
     83}
     84/*----------------------------------------------------------------------------*/
     85static void node_toggle_reset_filtered(link_t *item, void *arg)
     86{
     87        assert(item);
     88        node_t *node = hash_table_get_instance(item, node_t, link);
     89        usb_target_t *target = arg;
     90        endpoint_toggle_reset_filtered(node->ep, *target);
    8291}
    8392/*----------------------------------------------------------------------------*/
     
    230239        return node->ep;
    231240}
     241/*----------------------------------------------------------------------------*/
     242/** Check setup packet data for signs of toggle reset.
     243 *
     244 * @param[in] instance Device keeper structure to use.
     245 * @param[in] target Device to receive setup packet.
     246 * @param[in] data Setup packet data.
     247 *
     248 * Really ugly one.
     249 */
     250void usb_endpoint_manager_reset_if_need(
     251    usb_endpoint_manager_t *instance, usb_target_t target, const uint8_t *data)
     252{
     253        assert(instance);
     254        if (target.endpoint > 15 || target.endpoint < 0
     255            || target.address >= USB11_ADDRESS_MAX || target.address < 0) {
     256                usb_log_error("Invalid data when checking for toggle reset.\n");
     257                return;
     258        }
     259
     260        switch (data[1])
     261        {
     262        case 0x01: /*clear feature*/
     263                /* recipient is endpoint, value is zero (ENDPOINT_STALL) */
     264                if (((data[0] & 0xf) == 1) && ((data[2] | data[3]) == 0)) {
     265                        /* endpoint number is < 16, thus first byte is enough */
     266                        usb_target_t reset_target =
     267                            { .address = target.address, data[4] };
     268                        fibril_mutex_lock(&instance->guard);
     269                        hash_table_apply(&instance->ep_table,
     270                            node_toggle_reset_filtered, &reset_target);
     271                        fibril_mutex_unlock(&instance->guard);
     272                }
     273        break;
     274
     275        case 0x9: /* set configuration */
     276        case 0x11: /* set interface */
     277                /* target must be device */
     278                if ((data[0] & 0xf) == 0) {
     279                        usb_target_t reset_target =
     280                            { .address = target.address, 0 };
     281                        fibril_mutex_lock(&instance->guard);
     282                        hash_table_apply(&instance->ep_table,
     283                            node_toggle_reset_filtered, &reset_target);
     284                        fibril_mutex_unlock(&instance->guard);
     285                }
     286        break;
     287        }
     288}
  • uspace/lib/usb/src/hub.c

    r58226b4 r3f3afb9  
    4242#include <usb/debug.h>
    4343
     44/** How much time to wait between attempts to register endpoint 0:0.
     45 * The value is based on typical value for port reset + some overhead.
     46 */
     47#define ENDPOINT_0_0_REGISTER_ATTEMPT_DELAY_USEC (1000 * (10 + 2))
     48
    4449/** Check that HC connection is alright.
    4550 *
     
    5358                } \
    5459        } while (false)
    55 
    56 
    57 /** Tell host controller to reserve default address.
    58  * @deprecated
    59  *
    60  * @param connection Opened connection to host controller.
    61  * @param speed Speed of the device that will respond on the default address.
    62  * @return Error code.
    63  */
    64 int usb_hc_reserve_default_address(usb_hc_connection_t *connection,
    65     usb_speed_t speed)
    66 {
    67         CHECK_CONNECTION(connection);
    68 
    69         usb_log_warning("usb_hc_reserve_default_address() considered obsolete");
    70 
    71         return async_req_2_0(connection->hc_phone,
    72             DEV_IFACE_ID(USBHC_DEV_IFACE),
    73             IPC_M_USBHC_RESERVE_DEFAULT_ADDRESS, speed);
    74 }
    75 
    76 /** Tell host controller to release default address.
    77  * @deprecated
    78  *
    79  * @param connection Opened connection to host controller.
    80  * @return Error code.
    81  */
    82 int usb_hc_release_default_address(usb_hc_connection_t *connection)
    83 {
    84         CHECK_CONNECTION(connection);
    85 
    86         usb_log_warning("usb_hc_release_default_address() considered obsolete");
    87 
    88         return async_req_1_0(connection->hc_phone,
    89             DEV_IFACE_ID(USBHC_DEV_IFACE),
    90             IPC_M_USBHC_RELEASE_DEFAULT_ADDRESS);
    91 }
    9260
    9361/** Ask host controller for free address assignment.
     
    269237                if (rc != EOK) {
    270238                        /* Do not overheat the CPU ;-). */
    271                         async_usleep(10);
     239                        async_usleep(ENDPOINT_0_0_REGISTER_ATTEMPT_DELAY_USEC);
    272240                }
    273241        } while (rc != EOK);
  • uspace/lib/usb/src/request.c

    r58226b4 r3f3afb9  
    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 */
     879int 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
    873887/**
    874888 * @}
Note: See TracChangeset for help on using the changeset viewer.