Changeset c7dd69d in mainline for uspace/lib/usb


Ignore:
Timestamp:
2011-04-15T13:19:59Z (14 years ago)
Author:
Lubos Slovak <lubos.slovak@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
da1dd48
Parents:
e3b5129 (diff), 8fd4ba0 (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:

Development changes

Location:
uspace/lib/usb
Files:
3 added
19 edited

Legend:

Unmodified
Added
Removed
  • uspace/lib/usb/Makefile

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

    re3b5129 rc7dd69d  
    162162    usb_endpoint_description_t **);
    163163
    164 typedef bool (*usb_polling_callback_t)(usb_device_t *,
    165     uint8_t *, size_t, void *);
    166 typedef void (*usb_polling_terminted_callback_t)(usb_device_t *, bool, void *);
    167 
    168 int usb_device_auto_poll(usb_device_t *, size_t,
    169     usb_polling_callback_t, size_t, usb_polling_terminted_callback_t, void *);
    170 
    171164int usb_device_retrieve_descriptors(usb_pipe_t *, usb_device_descriptors_t *);
    172165int usb_device_create_pipes(ddf_dev_t *, usb_device_connection_t *,
     
    174167    usb_endpoint_mapping_t **, size_t *);
    175168int usb_device_destroy_pipes(ddf_dev_t *, usb_endpoint_mapping_t *, size_t);
     169int usb_device_create(ddf_dev_t *, usb_endpoint_description_t **, usb_device_t **, const char **);
    176170
    177171size_t usb_interface_count_alternates(uint8_t *, size_t, uint8_t);
     172int usb_alternate_interfaces_create(uint8_t *, size_t, int,
     173    usb_alternate_interfaces_t **);
    178174
    179175#endif
  • uspace/lib/usb/include/usb/host/batch.h

    re3b5129 rc7dd69d  
    4343typedef struct usb_transfer_batch usb_transfer_batch_t;
    4444struct usb_transfer_batch {
     45        endpoint_t *ep;
    4546        link_t link;
    46         usb_target_t target;
    47         usb_transfer_type_t transfer_type;
    48         usb_speed_t speed;
    49         usb_direction_t direction;
    5047        usbhc_iface_transfer_in_callback_t callback_in;
    5148        usbhc_iface_transfer_out_callback_t callback_out;
     49        void *arg;
    5250        char *buffer;
    53         char *transport_buffer;
     51        char *data_buffer;
    5452        size_t buffer_size;
    5553        char *setup_buffer;
    5654        size_t setup_size;
    57         size_t max_packet_size;
    5855        size_t transfered_size;
    5956        void (*next_step)(usb_transfer_batch_t *);
    6057        int error;
    6158        ddf_fun_t *fun;
    62         void *arg;
    63         endpoint_t *ep;
    6459        void *private_data;
     60        void (*private_data_dtor)(void *p_data);
    6561};
    6662
    6763void usb_transfer_batch_init(
    6864    usb_transfer_batch_t *instance,
    69     usb_target_t target,
    70     usb_transfer_type_t transfer_type,
    71     usb_speed_t speed,
    72     size_t max_packet_size,
     65    endpoint_t *ep,
    7366    char *buffer,
    74     char *transport_buffer,
     67    char *data_buffer,
    7568    size_t buffer_size,
    7669    char *setup_buffer,
     
    8073    void *arg,
    8174    ddf_fun_t *fun,
    82                 endpoint_t *ep,
    83     void *private_data
     75    void *private_data,
     76    void (*private_data_dtor)(void *p_data)
    8477);
    8578
    86 static inline usb_transfer_batch_t *usb_transfer_batch_from_link(link_t *l)
    87 {
    88         assert(l);
    89         return list_get_instance(l, usb_transfer_batch_t, link);
    90 }
    91 
    92 void usb_transfer_batch_call_in(usb_transfer_batch_t *instance);
    93 void usb_transfer_batch_call_out(usb_transfer_batch_t *instance);
     79void usb_transfer_batch_call_in_and_dispose(usb_transfer_batch_t *instance);
     80void usb_transfer_batch_call_out_and_dispose(usb_transfer_batch_t *instance);
    9481void usb_transfer_batch_finish(usb_transfer_batch_t *instance);
     82void usb_transfer_batch_dispose(usb_transfer_batch_t *instance);
    9583
    9684static inline void usb_transfer_batch_finish_error(
     
    10290}
    10391
     92static inline usb_transfer_batch_t *usb_transfer_batch_from_link(link_t *l)
     93{
     94        assert(l);
     95        return list_get_instance(l, usb_transfer_batch_t, link);
     96}
     97
    10498#endif
    10599/**
  • uspace/lib/usb/include/usb/host/device_keeper.h

    re3b5129 rc7dd69d  
    5454        usb_speed_t speed;
    5555        bool occupied;
    56         link_t endpoints;
    57         uint16_t control_used;
    5856        devman_handle_t handle;
    5957};
     
    6563        struct usb_device_info devices[USB_ADDRESS_COUNT];
    6664        fibril_mutex_t guard;
    67         fibril_condvar_t change;
    6865        usb_address_t last_address;
    6966} usb_device_keeper_t;
    7067
    7168void usb_device_keeper_init(usb_device_keeper_t *instance);
    72 
    73 void usb_device_keeper_reserve_default_address(
    74     usb_device_keeper_t *instance, usb_speed_t speed);
    75 
    76 void usb_device_keeper_release_default_address(usb_device_keeper_t *instance);
    77 
    78 void usb_device_keeper_reset_if_need(usb_device_keeper_t *instance,
    79     usb_target_t target, const uint8_t *setup_data);
    8069
    8170usb_address_t device_keeper_get_free_address(usb_device_keeper_t *instance,
  • uspace/lib/usb/include/usb/host/endpoint.h

    re3b5129 rc7dd69d  
    5454        fibril_condvar_t avail;
    5555        volatile bool active;
     56        struct {
     57                void *data;
     58                int (*toggle_get)(void *);
     59                void (*toggle_set)(void *, int);
     60        } hc_data;
    5661} endpoint_t;
    5762
     
    6166
    6267void endpoint_destroy(endpoint_t *instance);
     68
     69void endpoint_set_hc_data(endpoint_t *instance,
     70    void *data, int (*toggle_get)(void *), void (*toggle_set)(void *, int));
     71
     72void endpoint_clear_hc_data(endpoint_t *instance);
    6373
    6474void endpoint_use(endpoint_t *instance);
  • uspace/lib/usb/include/usb/host/usb_endpoint_manager.h

    re3b5129 rc7dd69d  
    6666    endpoint_t *ep, size_t data_size);
    6767
    68 int usb_endpoint_manager_register_ep_wait(usb_endpoint_manager_t *instance,
    69     usb_address_t address, usb_endpoint_t ep, usb_direction_t direction,
    70     void *data, void (*data_remove_callback)(void* data, void* arg), void *arg,
    71     size_t bw);
    72 
    7368int usb_endpoint_manager_unregister_ep(usb_endpoint_manager_t *instance,
    7469    usb_address_t address, usb_endpoint_t ep, usb_direction_t direction);
     
    8075void usb_endpoint_manager_reset_if_need(
    8176    usb_endpoint_manager_t *instance, usb_target_t target, const uint8_t *data);
     77
     78static inline int usb_endpoint_manager_add_ep(usb_endpoint_manager_t *instance,
     79    usb_address_t address, usb_endpoint_t endpoint, usb_direction_t direction,
     80    usb_transfer_type_t type, usb_speed_t speed, size_t max_packet_size,
     81    size_t data_size)
     82{
     83        endpoint_t *ep = malloc(sizeof(endpoint_t));
     84        if (ep == NULL)
     85                return ENOMEM;
     86
     87        int ret = endpoint_init(ep, address, endpoint, direction, type, speed,
     88            max_packet_size);
     89        if (ret != EOK) {
     90                free(ep);
     91                return ret;
     92        }
     93
     94        ret = usb_endpoint_manager_register_ep(instance, ep, data_size);
     95        if (ret != EOK) {
     96                endpoint_destroy(ep);
     97                return ret;
     98        }
     99        return EOK;
     100}
    82101#endif
    83102/**
  • uspace/lib/usb/include/usb/pipes.h

    re3b5129 rc7dd69d  
    9999        /** Number of active transfers over the pipe. */
    100100        int refcount;
     101
     102        /** Whether to automatically reset halt on the endpoint.
     103         * Valid only for control endpoint zero.
     104         */
     105        bool auto_reset_halt;
    101106} usb_pipe_t;
    102107
  • uspace/lib/usb/include/usb/request.h

    re3b5129 rc7dd69d  
    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

    re3b5129 rc7dd69d  
    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/devpoll.c

    re3b5129 rc7dd69d  
    3333 * USB device driver framework - automatic interrupt polling.
    3434 */
    35 #include <usb/devdrv.h>
     35#include <usb/devpoll.h>
    3636#include <usb/request.h>
    3737#include <usb/debug.h>
     38#include <usb/classes/classes.h>
    3839#include <errno.h>
    3940#include <str_error.h>
     
    4546/** Data needed for polling. */
    4647typedef struct {
     48        int debug;
     49        size_t max_failures;
     50        useconds_t delay;
     51        bool auto_clear_halt;
     52        bool (*on_data)(usb_device_t *, uint8_t *, size_t, void *);
     53        void (*on_polling_end)(usb_device_t *, bool, void *);
     54        bool (*on_error)(usb_device_t *, int, void *);
     55
    4756        usb_device_t *dev;
    4857        size_t pipe_index;
    49         usb_polling_callback_t callback;
    50         usb_polling_terminted_callback_t terminated_callback;
    5158        size_t request_size;
    5259        uint8_t *buffer;
     
    5461} polling_data_t;
    5562
     63
    5664/** Polling fibril.
    5765 *
     
    6775            = polling_data->dev->pipes[polling_data->pipe_index].pipe;
    6876       
    69         usb_log_debug("Pipe interface number: %d, protocol: %d, subclass: %d, max packet size: %d\n",
    70             polling_data->dev->pipes[polling_data->pipe_index].interface_no,
    71             polling_data->dev->pipes[polling_data->pipe_index].description->interface_protocol,
    72             polling_data->dev->pipes[polling_data->pipe_index].description->interface_subclass,
    73             pipe->max_packet_size);
     77        if (polling_data->debug > 0) {
     78                usb_endpoint_mapping_t *mapping
     79                    = &polling_data->dev->pipes[polling_data->pipe_index];
     80                usb_log_debug("Poll0x%x: started polling of `%s' - " \
     81                    "interface %d (%s,%d,%d), %zuB/%zu.\n",
     82                    polling_data,
     83                    polling_data->dev->ddf_dev->name,
     84                    (int) mapping->interface->interface_number,
     85                    usb_str_class(mapping->interface->interface_class),
     86                    (int) mapping->interface->interface_subclass,
     87                    (int) mapping->interface->interface_protocol,
     88                    polling_data->request_size, pipe->max_packet_size);
     89        }
    7490
    7591        size_t failed_attempts = 0;
    76         while (failed_attempts < MAX_FAILED_ATTEMPTS) {
     92        while (failed_attempts <= polling_data->max_failures) {
    7793                int rc;
    7894
     
    8197                    polling_data->request_size, &actual_size);
    8298
    83                
    84 //              if (rc == ESTALL) {
    85 //                      usb_log_debug("Seding clear feature...\n");
    86 //                      usb_request_clear_feature(pipe, USB_REQUEST_TYPE_STANDARD,
    87 //                        USB_REQUEST_RECIPIENT_ENDPOINT, 0, pipe->endpoint_no);
    88 //                      continue;
    89 //              }
     99                if (polling_data->debug > 1) {
     100                        if (rc == EOK) {
     101                                usb_log_debug(
     102                                    "Poll0x%x: received: '%s' (%zuB).\n",
     103                                    polling_data,
     104                                    usb_debug_str_buffer(polling_data->buffer,
     105                                        actual_size, 16),
     106                                    actual_size);
     107                        } else {
     108                                usb_log_debug(
     109                                    "Poll0x%x: polling failed: %s.\n",
     110                                    polling_data, str_error(rc));
     111                        }
     112                }
     113
     114                /* If the pipe stalled, we can try to reset the stall. */
     115                if ((rc == ESTALL) && (polling_data->auto_clear_halt)) {
     116                        /*
     117                         * We ignore error here as this is usually a futile
     118                         * attempt anyway.
     119                         */
     120                        usb_request_clear_endpoint_halt(
     121                            &polling_data->dev->ctrl_pipe,
     122                            pipe->endpoint_no);
     123                }
    90124
    91125                if (rc != EOK) {
     126                        if (polling_data->on_error != NULL) {
     127                                bool cont = polling_data->on_error(
     128                                    polling_data->dev, rc,
     129                                    polling_data->custom_arg);
     130                                if (!cont) {
     131                                        failed_attempts
     132                                            = polling_data->max_failures;
     133                                }
     134                        }
    92135                        failed_attempts++;
    93136                        continue;
     
    95138
    96139                /* We have the data, execute the callback now. */
    97                 bool carry_on = polling_data->callback(polling_data->dev,
     140                bool carry_on = polling_data->on_data(polling_data->dev,
    98141                    polling_data->buffer, actual_size,
    99142                    polling_data->custom_arg);
     
    106149                /* Reset as something might be only a temporary problem. */
    107150                failed_attempts = 0;
    108         }
    109 
    110         if (failed_attempts > 0) {
    111                 usb_log_error(
    112                     "Polling of device `%s' terminated: recurring failures.\n",
    113                     polling_data->dev->ddf_dev->name);
    114         }
    115 
    116         if (polling_data->terminated_callback != NULL) {
    117                 polling_data->terminated_callback(polling_data->dev,
     151
     152                /* Take a rest before next request. */
     153                async_usleep(polling_data->delay);
     154        }
     155
     156        if (polling_data->on_polling_end != NULL) {
     157                polling_data->on_polling_end(polling_data->dev,
    118158                    failed_attempts > 0, polling_data->custom_arg);
     159        }
     160
     161        if (polling_data->debug > 0) {
     162                if (failed_attempts > 0) {
     163                        usb_log_error(
     164                            "Polling of device `%s' terminated: %s.\n",
     165                            polling_data->dev->ddf_dev->name,
     166                            "recurring failures");
     167                } else {
     168                        usb_log_debug(
     169                            "Polling of device `%s' terminated by user.\n",
     170                            polling_data->dev->ddf_dev->name
     171                        );
     172                }
    119173        }
    120174
     
    159213        }
    160214
     215        usb_device_auto_polling_t *auto_polling
     216            = malloc(sizeof(usb_device_auto_polling_t));
     217        if (auto_polling == NULL) {
     218                return ENOMEM;
     219        }
     220
     221        auto_polling->debug = 1;
     222        auto_polling->auto_clear_halt = true;
     223        auto_polling->delay = 0;
     224        auto_polling->max_failures = MAX_FAILED_ATTEMPTS;
     225        auto_polling->on_data = callback;
     226        auto_polling->on_polling_end = terminated_callback;
     227        auto_polling->on_error = NULL;
     228
     229        int rc = usb_device_auto_polling(dev, pipe_index, auto_polling,
     230           request_size, arg);
     231
     232        free(auto_polling);
     233
     234        return rc;
     235}
     236
     237/** Start automatic device polling over interrupt in pipe.
     238 *
     239 * The polling settings is copied thus it is okay to destroy the structure
     240 * after this function returns.
     241 *
     242 * @warning There is no guarantee when the request to the device
     243 * will be sent for the first time (it is possible that this
     244 * first request would be executed prior to return from this function).
     245 *
     246 * @param dev Device to be periodically polled.
     247 * @param pipe_index Index of the endpoint pipe used for polling.
     248 * @param polling Polling settings.
     249 * @param request_size How many bytes to ask for in each request.
     250 * @param arg Custom argument (passed as is to the callbacks).
     251 * @return Error code.
     252 * @retval EOK New fibril polling the device was already started.
     253 */
     254int usb_device_auto_polling(usb_device_t *dev, size_t pipe_index,
     255    usb_device_auto_polling_t *polling,
     256    size_t request_size, void *arg)
     257{
     258        if (dev == NULL) {
     259                return EBADMEM;
     260        }
     261        if (pipe_index >= dev->pipes_count) {
     262                return EINVAL;
     263        }
     264        if ((dev->pipes[pipe_index].pipe->transfer_type != USB_TRANSFER_INTERRUPT)
     265            || (dev->pipes[pipe_index].pipe->direction != USB_DIRECTION_IN)) {
     266                return EINVAL;
     267        }
     268        if ((polling == NULL) || (polling->on_data == NULL)) {
     269                return EBADMEM;
     270        }
     271
    161272        polling_data_t *polling_data = malloc(sizeof(polling_data_t));
    162273        if (polling_data == NULL) {
     
    164275        }
    165276
    166         /* Allocate now to prevent immediate failure in the polling fibril. */
    167         polling_data->buffer = malloc(request_size);
     277        /* Fill-in the data. */
     278        polling_data->buffer = malloc(sizeof(request_size));
    168279        if (polling_data->buffer == NULL) {
    169280                free(polling_data);
    170281                return ENOMEM;
    171282        }
     283        polling_data->request_size = request_size;
    172284        polling_data->dev = dev;
    173285        polling_data->pipe_index = pipe_index;
    174         polling_data->callback = callback;
    175         polling_data->terminated_callback = terminated_callback;
    176         polling_data->request_size = request_size;
    177286        polling_data->custom_arg = arg;
     287
     288        polling_data->debug = polling->debug;
     289        polling_data->max_failures = polling->max_failures;
     290        if (polling->delay >= 0) {
     291                polling_data->delay = (useconds_t) polling->delay;
     292        } else {
     293                polling_data->delay = (useconds_t) dev->pipes[pipe_index]
     294                    .descriptor->poll_interval;
     295        }
     296        polling_data->auto_clear_halt = polling->auto_clear_halt;
     297
     298        polling_data->on_data = polling->on_data;
     299        polling_data->on_polling_end = polling->on_polling_end;
     300        polling_data->on_error = polling->on_error;
    178301
    179302        fid_t fibril = fibril_create(polling_fibril, polling_data);
     
    181304                free(polling_data->buffer);
    182305                free(polling_data);
    183                 /* FIXME: better error code. */
    184306                return ENOMEM;
    185307        }
    186308        fibril_add_ready(fibril);
    187309
    188         /* The allocated buffer etc. will be freed by the fibril. */
     310        /* Fibril launched. That fibril will free the allocated data. */
    189311
    190312        return EOK;
  • uspace/lib/usb/src/hidreport.c

    re3b5129 rc7dd69d  
    119119        uint16_t length =  hid_desc->report_desc_info.length;
    120120        size_t actual_size = 0;
    121        
    122         /*
    123          * Start session for the control transfer.
    124          */
    125         int sess_rc = usb_pipe_start_session(&dev->ctrl_pipe);
    126         if (sess_rc != EOK) {
    127                 usb_log_warning("Failed to start a session: %s.\n",
    128                     str_error(sess_rc));
    129                 return sess_rc;
    130         }
    131121
    132122        /*
     
    162152                    "%u)\n", actual_size, length);
    163153                return EINVAL;
    164         }
    165        
    166         /*
    167          * End session for the control transfer.
    168          */
    169         sess_rc = usb_pipe_end_session(&dev->ctrl_pipe);
    170         if (sess_rc != EOK) {
    171                 usb_log_warning("Failed to end a session: %s.\n",
    172                     str_error(sess_rc));
    173                 free(*report_desc);
    174                 *report_desc = NULL;
    175                 return sess_rc;
    176154        }
    177155       
  • uspace/lib/usb/src/hidreq.c

    re3b5129 rc7dd69d  
    5656 * @retval EOK if successful.
    5757 * @retval EINVAL if no HID device is given.
    58  * @return Other value inherited from one of functions
    59  *         usb_pipe_start_session(), usb_pipe_end_session(),
    60  *         usb_control_request_set().
     58 * @return Other value inherited from function usb_control_request_set().
    6159 */
    6260int usbhid_req_set_report(usb_pipe_t *ctrl_pipe, int iface_no,
     
    7977         */
    8078       
    81         int rc, sess_rc;
    82        
    83         sess_rc = usb_pipe_start_session(ctrl_pipe);
    84         if (sess_rc != EOK) {
    85                 usb_log_warning("Failed to start a session: %s.\n",
    86                     str_error(sess_rc));
    87                 return sess_rc;
    88         }
     79        int rc;
    8980       
    9081        uint16_t value = 0;
     
    9788            USB_HIDREQ_SET_REPORT, value, iface_no, buffer, buf_size);
    9889
    99         sess_rc = usb_pipe_end_session(ctrl_pipe);
    100 
    101         if (rc != EOK) {
    102                 usb_log_warning("Error sending output report to the keyboard: "
    103                     "%s.\n", str_error(rc));
    104                 return rc;
    105         }
    106 
    107         if (sess_rc != EOK) {
    108                 usb_log_warning("Error closing session: %s.\n",
    109                     str_error(sess_rc));
    110                 return sess_rc;
     90        if (rc != EOK) {
     91                usb_log_warning("Error sending output report to the keyboard: "
     92                    "%s.\n", str_error(rc));
     93                return rc;
    11194        }
    11295       
     
    123106 * @retval EOK if successful.
    124107 * @retval EINVAL if no HID device is given.
    125  * @return Other value inherited from one of functions
    126  *         usb_pipe_start_session(), usb_pipe_end_session(),
    127  *         usb_control_request_set().
     108 * @return Other value inherited from function usb_control_request_set().
    128109 */
    129110int usbhid_req_set_protocol(usb_pipe_t *ctrl_pipe, int iface_no,
     
    146127         */
    147128       
    148         int rc, sess_rc;
    149        
    150         sess_rc = usb_pipe_start_session(ctrl_pipe);
    151         if (sess_rc != EOK) {
    152                 usb_log_warning("Failed to start a session: %s.\n",
    153                     str_error(sess_rc));
    154                 return sess_rc;
    155         }
     129        int rc;
    156130
    157131        usb_log_debug("Sending Set_Protocol request to the device ("
     
    162136            USB_HIDREQ_SET_PROTOCOL, protocol, iface_no, NULL, 0);
    163137
    164         sess_rc = usb_pipe_end_session(ctrl_pipe);
    165 
    166         if (rc != EOK) {
    167                 usb_log_warning("Error sending output report to the keyboard: "
    168                     "%s.\n", str_error(rc));
    169                 return rc;
    170         }
    171 
    172         if (sess_rc != EOK) {
    173                 usb_log_warning("Error closing session: %s.\n",
    174                     str_error(sess_rc));
    175                 return sess_rc;
     138        if (rc != EOK) {
     139                usb_log_warning("Error sending output report to the keyboard: "
     140                    "%s.\n", str_error(rc));
     141                return rc;
    176142        }
    177143       
     
    189155 * @retval EOK if successful.
    190156 * @retval EINVAL if no HID device is given.
    191  * @return Other value inherited from one of functions
    192  *         usb_pipe_start_session(), usb_pipe_end_session(),
    193  *         usb_control_request_set().
     157 * @return Other value inherited from function usb_control_request_set().
    194158 */
    195159int usbhid_req_set_idle(usb_pipe_t *ctrl_pipe, int iface_no, uint8_t duration)
     
    211175         */
    212176       
    213         int rc, sess_rc;
    214        
    215         sess_rc = usb_pipe_start_session(ctrl_pipe);
    216         if (sess_rc != EOK) {
    217                 usb_log_warning("Failed to start a session: %s.\n",
    218                     str_error(sess_rc));
    219                 return sess_rc;
    220         }
     177        int rc;
    221178
    222179        usb_log_debug("Sending Set_Idle request to the device ("
     
    229186            USB_HIDREQ_SET_IDLE, value, iface_no, NULL, 0);
    230187
    231         sess_rc = usb_pipe_end_session(ctrl_pipe);
    232 
    233         if (rc != EOK) {
    234                 usb_log_warning("Error sending output report to the keyboard: "
    235                     "%s.\n", str_error(rc));
    236                 return rc;
    237         }
    238 
    239         if (sess_rc != EOK) {
    240                 usb_log_warning("Error closing session: %s.\n",
    241                     str_error(sess_rc));
    242                 return sess_rc;
     188        if (rc != EOK) {
     189                usb_log_warning("Error sending output report to the keyboard: "
     190                    "%s.\n", str_error(rc));
     191                return rc;
    243192        }
    244193       
     
    259208 * @retval EOK if successful.
    260209 * @retval EINVAL if no HID device is given.
    261  * @return Other value inherited from one of functions
    262  *         usb_pipe_start_session(), usb_pipe_end_session(),
    263  *         usb_control_request_set().
     210 * @return Other value inherited from function usb_control_request_set().
    264211 */
    265212int usbhid_req_get_report(usb_pipe_t *ctrl_pipe, int iface_no,
     
    283230         */
    284231       
    285         int rc, sess_rc;
    286        
    287         sess_rc = usb_pipe_start_session(ctrl_pipe);
    288         if (sess_rc != EOK) {
    289                 usb_log_warning("Failed to start a session: %s.\n",
    290                     str_error(sess_rc));
    291                 return sess_rc;
    292         }
     232        int rc;
    293233
    294234        uint16_t value = 0;
     
    302242            actual_size);
    303243
    304         sess_rc = usb_pipe_end_session(ctrl_pipe);
    305 
    306         if (rc != EOK) {
    307                 usb_log_warning("Error sending output report to the keyboard: "
    308                     "%s.\n", str_error(rc));
    309                 return rc;
    310         }
    311 
    312         if (sess_rc != EOK) {
    313                 usb_log_warning("Error closing session: %s.\n",
    314                     str_error(sess_rc));
    315                 return sess_rc;
     244        if (rc != EOK) {
     245                usb_log_warning("Error sending output report to the keyboard: "
     246                    "%s.\n", str_error(rc));
     247                return rc;
    316248        }
    317249       
     
    328260 * @retval EOK if successful.
    329261 * @retval EINVAL if no HID device is given.
    330  * @return Other value inherited from one of functions
    331  *         usb_pipe_start_session(), usb_pipe_end_session(),
    332  *         usb_control_request_set().
     262 * @return Other value inherited from function usb_control_request_set().
    333263 */
    334264int usbhid_req_get_protocol(usb_pipe_t *ctrl_pipe, int iface_no,
     
    351281         */
    352282       
    353         int rc, sess_rc;
    354        
    355         sess_rc = usb_pipe_start_session(ctrl_pipe);
    356         if (sess_rc != EOK) {
    357                 usb_log_warning("Failed to start a session: %s.\n",
    358                     str_error(sess_rc));
    359                 return sess_rc;
    360         }
     283        int rc;
    361284
    362285        usb_log_debug("Sending Get_Protocol request to the device ("
     
    370293            USB_HIDREQ_GET_PROTOCOL, 0, iface_no, buffer, 1, &actual_size);
    371294
    372         sess_rc = usb_pipe_end_session(ctrl_pipe);
    373 
    374         if (rc != EOK) {
    375                 usb_log_warning("Error sending output report to the keyboard: "
    376                     "%s.\n", str_error(rc));
    377                 return rc;
    378         }
    379 
    380         if (sess_rc != EOK) {
    381                 usb_log_warning("Error closing session: %s.\n",
    382                     str_error(sess_rc));
    383                 return sess_rc;
     295        if (rc != EOK) {
     296                usb_log_warning("Error sending output report to the keyboard: "
     297                    "%s.\n", str_error(rc));
     298                return rc;
    384299        }
    385300       
     
    427342         */
    428343       
    429         int rc, sess_rc;
    430        
    431         sess_rc = usb_pipe_start_session(ctrl_pipe);
    432         if (sess_rc != EOK) {
    433                 usb_log_warning("Failed to start a session: %s.\n",
    434                     str_error(sess_rc));
    435                 return sess_rc;
    436         }
     344        int rc;
    437345
    438346        usb_log_debug("Sending Get_Idle request to the device ("
     
    448356            &actual_size);
    449357
    450         sess_rc = usb_pipe_end_session(ctrl_pipe);
    451 
    452         if (rc != EOK) {
    453                 usb_log_warning("Error sending output report to the keyboard: "
    454                     "%s.\n", str_error(rc));
    455                 return rc;
    456         }
    457 
    458         if (sess_rc != EOK) {
    459                 usb_log_warning("Error closing session: %s.\n",
    460                     str_error(sess_rc));
    461                 return sess_rc;
     358        if (rc != EOK) {
     359                usb_log_warning("Error sending output report to the keyboard: "
     360                    "%s.\n", str_error(rc));
     361                return rc;
    462362        }
    463363       
  • uspace/lib/usb/src/host/batch.c

    re3b5129 rc7dd69d  
    3939#include <usb/host/batch.h>
    4040
     41void usb_transfer_batch_call_in(usb_transfer_batch_t *instance);
     42void usb_transfer_batch_call_out(usb_transfer_batch_t *instance);
     43
    4144void usb_transfer_batch_init(
    4245    usb_transfer_batch_t *instance,
    43     usb_target_t target,
    44     usb_transfer_type_t transfer_type,
    45     usb_speed_t speed,
    46     size_t max_packet_size,
     46    endpoint_t *ep,
    4747    char *buffer,
    48     char *transport_buffer,
     48    char *data_buffer,
    4949    size_t buffer_size,
    5050    char *setup_buffer,
     
    5454    void *arg,
    5555    ddf_fun_t *fun,
    56                 endpoint_t *ep,
    57     void *private_data
     56    void *private_data,
     57    void (*private_data_dtor)(void *p_data)
    5858    )
    5959{
    6060        assert(instance);
    6161        link_initialize(&instance->link);
    62         instance->target = target;
    63         instance->transfer_type = transfer_type;
    64         instance->speed = speed;
    65         instance->direction = ep->direction;
     62        instance->ep = ep;
    6663        instance->callback_in = func_in;
    6764        instance->callback_out = func_out;
    6865        instance->arg = arg;
    6966        instance->buffer = buffer;
    70         instance->transport_buffer = transport_buffer;
     67        instance->data_buffer = data_buffer;
    7168        instance->buffer_size = buffer_size;
    7269        instance->setup_buffer = setup_buffer;
    7370        instance->setup_size = setup_size;
    74         instance->max_packet_size = max_packet_size;
    7571        instance->fun = fun;
    7672        instance->private_data = private_data;
     73        instance->private_data_dtor = private_data_dtor;
    7774        instance->transfered_size = 0;
    7875        instance->next_step = NULL;
    7976        instance->error = EOK;
    80         instance->ep = ep;
    8177        endpoint_use(instance->ep);
     78}
     79/*----------------------------------------------------------------------------*/
     80/** Helper function, calls callback and correctly destroys batch structure.
     81 *
     82 * @param[in] instance Batch structure to use.
     83 */
     84void usb_transfer_batch_call_in_and_dispose(usb_transfer_batch_t *instance)
     85{
     86        assert(instance);
     87        usb_transfer_batch_call_in(instance);
     88        usb_transfer_batch_dispose(instance);
     89}
     90/*----------------------------------------------------------------------------*/
     91/** Helper function calls callback and correctly destroys batch structure.
     92 *
     93 * @param[in] instance Batch structure to use.
     94 */
     95void usb_transfer_batch_call_out_and_dispose(usb_transfer_batch_t *instance)
     96{
     97        assert(instance);
     98        usb_transfer_batch_call_out(instance);
     99        usb_transfer_batch_dispose(instance);
    82100}
    83101/*----------------------------------------------------------------------------*/
     
    105123        assert(instance);
    106124        assert(instance->callback_in);
     125        assert(instance->ep);
    107126
    108127        /* We are data in, we need data */
    109         memcpy(instance->buffer, instance->transport_buffer,
    110             instance->buffer_size);
     128        memcpy(instance->buffer, instance->data_buffer, instance->buffer_size);
    111129
    112130        usb_log_debug("Batch %p done (T%d.%d, %s %s in, %zuB): %s (%d).\n",
    113             instance,
    114             instance->target.address, instance->target.endpoint,
    115             usb_str_speed(instance->speed),
    116             usb_str_transfer_type_short(instance->transfer_type),
    117             instance->transfered_size,
    118             str_error(instance->error), instance->error);
     131            instance, instance->ep->address, instance->ep->endpoint,
     132            usb_str_speed(instance->ep->speed),
     133            usb_str_transfer_type_short(instance->ep->transfer_type),
     134            instance->transfered_size, str_error(instance->error), instance->error);
    119135
    120136        instance->callback_in(instance->fun, instance->error,
     
    132148
    133149        usb_log_debug("Batch %p done (T%d.%d, %s %s out): %s (%d).\n",
    134             instance,
    135             instance->target.address, instance->target.endpoint,
    136             usb_str_speed(instance->speed),
    137             usb_str_transfer_type_short(instance->transfer_type),
     150            instance, instance->ep->address, instance->ep->endpoint,
     151            usb_str_speed(instance->ep->speed),
     152            usb_str_transfer_type_short(instance->ep->transfer_type),
    138153            str_error(instance->error), instance->error);
    139154
     
    141156            instance->error, instance->arg);
    142157}
     158/*----------------------------------------------------------------------------*/
     159/** Correctly dispose all used data structures.
     160 *
     161 * @param[in] instance Batch structure to use.
     162 */
     163void usb_transfer_batch_dispose(usb_transfer_batch_t *instance)
     164{
     165        assert(instance);
     166        usb_log_debug("Batch(%p) disposing.\n", instance);
     167        if (instance->private_data) {
     168                assert(instance->private_data_dtor);
     169                instance->private_data_dtor(instance->private_data);
     170        }
     171        free(instance);
     172}
    143173/**
    144174 * @}
  • uspace/lib/usb/src/host/device_keeper.c

    re3b5129 rc7dd69d  
    4848{
    4949        assert(instance);
    50         fibril_mutex_initialize(&instance->guard);
    51         fibril_condvar_initialize(&instance->change);
    52         instance->last_address = 0;
    5350        unsigned i = 0;
    5451        for (; i < USB_ADDRESS_COUNT; ++i) {
     
    6057        // (it is needed to allow smooth registration at default address)
    6158        instance->devices[0].occupied = true;
     59        instance->last_address = 0;
     60        fibril_mutex_initialize(&instance->guard);
    6261}
    63 /*----------------------------------------------------------------------------*/
    64 /** Attempt to obtain address 0, blocks.
    65  *
    66  * @param[in] instance Device keeper structure to use.
    67  * @param[in] speed Speed of the device requesting default address.
    68  */
    69 void usb_device_keeper_reserve_default_address(
    70     usb_device_keeper_t *instance, usb_speed_t speed)
    71 {
    72         assert(instance);
    73         fibril_mutex_lock(&instance->guard);
    74         while (instance->devices[USB_ADDRESS_DEFAULT].occupied) {
    75                 fibril_condvar_wait(&instance->change, &instance->guard);
    76         }
    77         instance->devices[USB_ADDRESS_DEFAULT].occupied = true;
    78         instance->devices[USB_ADDRESS_DEFAULT].speed = speed;
    79         fibril_mutex_unlock(&instance->guard);
    80 }
    81 /*----------------------------------------------------------------------------*/
    82 /** Attempt to obtain address 0, blocks.
    83  *
    84  * @param[in] instance Device keeper structure to use.
    85  * @param[in] speed Speed of the device requesting default address.
    86  */
    87 void usb_device_keeper_release_default_address(usb_device_keeper_t *instance)
    88 {
    89         assert(instance);
    90         fibril_mutex_lock(&instance->guard);
    91         instance->devices[USB_ADDRESS_DEFAULT].occupied = false;
    92         fibril_mutex_unlock(&instance->guard);
    93         fibril_condvar_signal(&instance->change);
    94 }
    95 /*----------------------------------------------------------------------------*/
    9662/*----------------------------------------------------------------------------*/
    9763/** Get a free USB address
     
    12086        assert(new_address != USB_ADDRESS_DEFAULT);
    12187        assert(instance->devices[new_address].occupied == false);
     88
    12289        instance->devices[new_address].occupied = true;
    12390        instance->devices[new_address].speed = speed;
    12491        instance->last_address = new_address;
     92
    12593        fibril_mutex_unlock(&instance->guard);
    12694        return new_address;
     
    138106        assert(instance);
    139107        fibril_mutex_lock(&instance->guard);
     108
    140109        assert(address > 0);
    141110        assert(address <= USB11_ADDRESS_MAX);
    142111        assert(instance->devices[address].occupied);
     112
    143113        instance->devices[address].handle = handle;
    144114        fibril_mutex_unlock(&instance->guard);
     
    159129        fibril_mutex_lock(&instance->guard);
    160130        assert(instance->devices[address].occupied);
     131
    161132        instance->devices[address].occupied = false;
    162133        fibril_mutex_unlock(&instance->guard);
     
    177148        while (address <= USB11_ADDRESS_MAX) {
    178149                if (instance->devices[address].handle == handle) {
     150                        assert(instance->devices[address].occupied);
    179151                        fibril_mutex_unlock(&instance->guard);
    180152                        return address;
     
    198170        assert(address >= 0);
    199171        assert(address <= USB11_ADDRESS_MAX);
     172
    200173        return instance->devices[address].speed;
    201174}
  • uspace/lib/usb/src/host/endpoint.c

    re3b5129 rc7dd69d  
    5353        fibril_mutex_initialize(&instance->guard);
    5454        fibril_condvar_initialize(&instance->avail);
     55        endpoint_clear_hc_data(instance);
    5556        return EOK;
    5657}
     
    6162        assert(!instance->active);
    6263        free(instance);
     64}
     65/*----------------------------------------------------------------------------*/
     66void endpoint_set_hc_data(endpoint_t *instance,
     67    void *data, int (*toggle_get)(void *), void (*toggle_set)(void *, int))
     68{
     69        assert(instance);
     70        instance->hc_data.data = data;
     71        instance->hc_data.toggle_get = toggle_get;
     72        instance->hc_data.toggle_set = toggle_set;
     73}
     74/*----------------------------------------------------------------------------*/
     75void endpoint_clear_hc_data(endpoint_t *instance)
     76{
     77        assert(instance);
     78        instance->hc_data.data = NULL;
     79        instance->hc_data.toggle_get = NULL;
     80        instance->hc_data.toggle_set = NULL;
    6381}
    6482/*----------------------------------------------------------------------------*/
     
    85103{
    86104        assert(instance);
     105        if (instance->hc_data.toggle_get)
     106                instance->toggle =
     107                    instance->hc_data.toggle_get(instance->hc_data.data);
    87108        return (int)instance->toggle;
    88109}
     
    92113        assert(instance);
    93114        assert(toggle == 0 || toggle == 1);
     115        if (instance->hc_data.toggle_set)
     116                instance->hc_data.toggle_set(instance->hc_data.data, toggle);
    94117        instance->toggle = toggle;
    95118}
     
    100123        if (instance->address == target.address &&
    101124            (instance->endpoint == target.endpoint || target.endpoint == 0))
    102                 instance->toggle = 0;
     125                endpoint_toggle_set(instance, 0);
    103126}
    104127/**
  • uspace/lib/usb/src/host/usb_endpoint_manager.c

    re3b5129 rc7dd69d  
    211211
    212212        node_t *node = hash_table_get_instance(item, node_t, link);
     213        if (node->ep->active)
     214                return EBUSY;
     215
    213216        instance->free_bw += node->bw;
    214217        hash_table_remove(&instance->ep_table, key, MAX_KEYS);
  • uspace/lib/usb/src/pipesinit.c

    re3b5129 rc7dd69d  
    365365        pipe->direction = direction;
    366366        pipe->refcount = 0;
     367        pipe->auto_reset_halt = false;
    367368
    368369        return EOK;
     
    385386            0, USB_TRANSFER_CONTROL, CTRL_PIPE_MIN_PACKET_SIZE,
    386387            USB_DIRECTION_BOTH);
     388
     389        pipe->auto_reset_halt = true;
    387390
    388391        return rc;
  • uspace/lib/usb/src/pipesio.c

    re3b5129 rc7dd69d  
    4949#include <assert.h>
    5050#include <usbhc_iface.h>
     51#include <usb/request.h>
    5152#include "pipepriv.h"
    5253
     
    307308}
    308309
     310/** Try to clear endpoint halt of default control pipe.
     311 *
     312 * @param pipe Pipe for control endpoint zero.
     313 */
     314static void clear_self_endpoint_halt(usb_pipe_t *pipe)
     315{
     316        assert(pipe != NULL);
     317
     318        if (!pipe->auto_reset_halt || (pipe->endpoint_no != 0)) {
     319                return;
     320        }
     321
     322
     323        /* Prevent indefinite recursion. */
     324        pipe->auto_reset_halt = false;
     325        usb_request_clear_endpoint_halt(pipe, 0);
     326        pipe->auto_reset_halt = true;
     327}
     328
    309329
    310330/** Request a control read transfer, no checking of input parameters.
     
    436456            setup_buffer, setup_buffer_size,
    437457            data_buffer, data_buffer_size, &act_size);
     458
     459        if (rc == ESTALL) {
     460                clear_self_endpoint_halt(pipe);
     461        }
    438462
    439463        pipe_drop_ref(pipe);
     
    563587            setup_buffer, setup_buffer_size, data_buffer, data_buffer_size);
    564588
     589        if (rc == ESTALL) {
     590                clear_self_endpoint_halt(pipe);
     591        }
     592
    565593        pipe_drop_ref(pipe);
    566594
  • uspace/lib/usb/src/request.c

    re3b5129 rc7dd69d  
    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.