Changeset e50cd7f in mainline for uspace/lib/usb


Ignore:
Timestamp:
2011-04-17T19:17:55Z (14 years ago)
Author:
Matej Klonfar <maklf@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
63517c2, cfbbe1d3
Parents:
ef354b6 (diff), 8595577b (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:

new report structure fixes

Location:
uspace/lib/usb
Files:
7 added
27 edited

Legend:

Unmodified
Added
Removed
  • uspace/lib/usb/Makefile

    ref354b6 re50cd7f  
    3434SOURCES = \
    3535        src/addrkeep.c \
     36        src/altiface.c \
    3637        src/class.c \
    3738        src/ddfiface.c \
     
    4142        src/dp.c \
    4243        src/dump.c \
     44        src/hidiface.c \
    4345        src/hidparser.c \
    4446        src/hub.c \
     47        src/pipepriv.c \
    4548        src/pipes.c \
    4649        src/pipesinit.c \
  • uspace/lib/usb/include/usb/classes/hidparser.h

    ref354b6 re50cd7f  
    317317usb_hid_report_path_t *usb_hid_report_path_clone(usb_hid_report_path_t *usage_path);
    318318
     319usb_hid_report_field_t *usb_hid_report_get_sibling(usb_hid_report_t *report, usb_hid_report_field_t *field, usb_hid_report_path_t *path, int flags, usb_hid_report_type_t type);
    319320
    320321/*
  • uspace/lib/usb/include/usb/classes/hub.h

    ref354b6 re50cd7f  
    4343 */
    4444typedef enum {
     45        USB_HUB_FEATURE_HUB_LOCAL_POWER = 0,
     46        USB_HUB_FEATURE_HUB_OVER_CURRENT = 1,
    4547        USB_HUB_FEATURE_C_HUB_LOCAL_POWER = 0,
    4648        USB_HUB_FEATURE_C_HUB_OVER_CURRENT = 1,
     
    5961        /* USB_HUB_FEATURE_ = , */
    6062} usb_hub_class_feature_t;
     63
    6164
    6265/** Header of standard hub descriptor without the "variadic" part. */
     
    149152            maximum of 255 ports).
    150153     */
    151     uint8_t * devices_removable;
     154    uint8_t devices_removable[32];
    152155
    153156    /**
  • uspace/lib/usb/include/usb/devdrv.h

    ref354b6 re50cd7f  
    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 *);
     164int usb_device_retrieve_descriptors(usb_pipe_t *, usb_device_descriptors_t *);
     165int usb_device_create_pipes(ddf_dev_t *, usb_device_connection_t *,
     166    usb_endpoint_description_t **, uint8_t *, size_t, int, int,
     167    usb_endpoint_mapping_t **, size_t *);
     168int 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 **);
    167170
    168 int usb_device_auto_poll(usb_device_t *, size_t,
    169     usb_polling_callback_t, size_t, usb_polling_terminted_callback_t, void *);
     171size_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 **);
    170174
    171175#endif
  • uspace/lib/usb/include/usb/host/batch.h

    ref354b6 re50cd7f  
    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);
     78
     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);
     81void usb_transfer_batch_finish(usb_transfer_batch_t *instance);
     82void usb_transfer_batch_dispose(usb_transfer_batch_t *instance);
     83
     84static inline void usb_transfer_batch_finish_error(
     85    usb_transfer_batch_t *instance, int error)
     86{
     87        assert(instance);
     88        instance->error = error;
     89        usb_transfer_batch_finish(instance);
     90}
    8591
    8692static inline usb_transfer_batch_t *usb_transfer_batch_from_link(link_t *l)
     
    9096}
    9197
    92 void usb_transfer_batch_call_in(usb_transfer_batch_t *instance);
    93 void usb_transfer_batch_call_out(usb_transfer_batch_t *instance);
    94 void usb_transfer_batch_finish(usb_transfer_batch_t *instance, int error);
    95 
    9698#endif
    9799/**
  • uspace/lib/usb/include/usb/host/device_keeper.h

    ref354b6 re50cd7f  
    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_add_ep(
    74     usb_device_keeper_t *instance, usb_address_t address, endpoint_t *ep);
    75 
    76 void usb_device_keeper_reserve_default_address(
    77     usb_device_keeper_t *instance, usb_speed_t speed);
    78 
    79 void usb_device_keeper_release_default_address(usb_device_keeper_t *instance);
    80 
    81 void usb_device_keeper_reset_if_need(usb_device_keeper_t *instance,
    82     usb_target_t target, const uint8_t *setup_data);
    8369
    8470usb_address_t device_keeper_get_free_address(usb_device_keeper_t *instance,
     
    9682usb_speed_t usb_device_keeper_get_speed(usb_device_keeper_t *instance,
    9783    usb_address_t address);
    98 
    99 void usb_device_keeper_use_control(usb_device_keeper_t *instance,
    100     usb_target_t target);
    101 
    102 void usb_device_keeper_release_control(usb_device_keeper_t *instance,
    103     usb_target_t target);
    104 
    10584#endif
    10685/**
  • uspace/lib/usb/include/usb/host/endpoint.h

    ref354b6 re50cd7f  
    3939#include <bool.h>
    4040#include <adt/list.h>
     41#include <fibril_synch.h>
     42
    4143#include <usb/usb.h>
    4244
     
    4850        usb_speed_t speed;
    4951        size_t max_packet_size;
    50         bool active;
    5152        unsigned toggle:1;
    52         link_t same_device_eps;
     53        fibril_mutex_t guard;
     54        fibril_condvar_t avail;
     55        volatile bool active;
     56        struct {
     57                void *data;
     58                int (*toggle_get)(void *);
     59                void (*toggle_set)(void *, int);
     60        } hc_data;
    5361} endpoint_t;
    5462
     
    5967void endpoint_destroy(endpoint_t *instance);
    6068
     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);
     73
     74void endpoint_use(endpoint_t *instance);
     75
     76void endpoint_release(endpoint_t *instance);
     77
    6178int endpoint_toggle_get(endpoint_t *instance);
    6279
    6380void endpoint_toggle_set(endpoint_t *instance, int toggle);
    6481
    65 void endpoint_toggle_reset(link_t *ep);
    66 
    67 void endpoint_toggle_reset_filtered(link_t *ep, usb_endpoint_t epn);
    68 
     82void endpoint_toggle_reset_filtered(endpoint_t *instance, usb_target_t target);
    6983#endif
    7084/**
  • uspace/lib/usb/include/usb/host/usb_endpoint_manager.h

    ref354b6 re50cd7f  
    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);
     
    7873    size_t *bw);
    7974
     75void usb_endpoint_manager_reset_if_need(
     76    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}
    80101#endif
    81102/**
  • uspace/lib/usb/include/usb/hub.h

    ref354b6 re50cd7f  
    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/pipes.h

    ref354b6 re50cd7f  
    4242#include <ipc/devman.h>
    4343#include <ddf/driver.h>
     44#include <fibril_synch.h>
    4445
    4546/** Abstraction of a physical connection to the device.
     
    5960 * This endpoint must be bound with existing usb_device_connection_t
    6061 * (i.e. the wire to send data over).
     62 *
     63 * Locking order: if you want to lock both mutexes
     64 * (@c guard and @c hc_phone_mutex), lock @c guard first.
     65 * It is not necessary to lock @c guard if you want to lock @c hc_phone_mutex
     66 * only.
    6167 */
    6268typedef struct {
     69        /** Guard of the whole pipe. */
     70        fibril_mutex_t guard;
     71
    6372        /** The connection used for sending the data. */
    6473        usb_device_connection_t *wire;
     
    7887        /** Phone to the host controller.
    7988         * Negative when no session is active.
     89         * It is an error to access this member without @c hc_phone_mutex
     90         * being locked.
     91         * If call over the phone is to be made, it must be preceeded by
     92         * call to pipe_add_ref() [internal libusb function].
    8093         */
    8194        int hc_phone;
     95
     96        /** Guard for serialization of requests over the phone. */
     97        fibril_mutex_t hc_phone_mutex;
     98
     99        /** Number of active transfers over the pipe. */
     100        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;
    82106} usb_pipe_t;
    83107
     
    134158int usb_pipe_initialize_from_configuration(usb_endpoint_mapping_t *,
    135159    size_t, uint8_t *, size_t, usb_device_connection_t *);
     160int usb_pipe_register_with_speed(usb_pipe_t *, usb_speed_t,
     161    unsigned int, usb_hc_connection_t *);
    136162int usb_pipe_register(usb_pipe_t *, unsigned int, usb_hc_connection_t *);
    137163int usb_pipe_unregister(usb_pipe_t *, usb_hc_connection_t *);
     
    140166int usb_pipe_end_session(usb_pipe_t *);
    141167bool usb_pipe_is_session_started(usb_pipe_t *);
     168
     169int usb_pipe_start_long_transfer(usb_pipe_t *);
     170void usb_pipe_end_long_transfer(usb_pipe_t *);
    142171
    143172int usb_pipe_read(usb_pipe_t *, void *, size_t, size_t *);
  • uspace/lib/usb/include/usb/request.h

    ref354b6 re50cd7f  
    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/include/usb/usb.h

    ref354b6 re50cd7f  
    7777        USB_SPEED_FULL,
    7878        /** USB 2.0 high speed (480Mbits/s). */
    79         USB_SPEED_HIGH
     79        USB_SPEED_HIGH,
     80        /** Psuedo-speed serving as a boundary. */
     81        USB_SPEED_MAX
    8082} usb_speed_t;
    8183
  • uspace/lib/usb/src/devdrv.c

    ref354b6 re50cd7f  
    7272}
    7373
    74 /** Log out of memory error on given device.
    75  *
    76  * @param dev Device causing the trouble.
    77  */
    78 static void usb_log_oom(ddf_dev_t *dev)
    79 {
    80         usb_log_error("Out of memory when adding device `%s'.\n",
    81             dev->name);
    82 }
    83 
    8474/** Count number of pipes the driver expects.
    8575 *
     
    10898 */
    10999static int initialize_other_pipes(usb_endpoint_description_t **endpoints,
    110     usb_device_t *dev)
    111 {
    112         int rc;
    113 
    114         size_t pipe_count = count_other_pipes(endpoints);
    115         if (pipe_count == 0) {
     100    usb_device_t *dev, int alternate_setting)
     101{
     102        if (endpoints == NULL) {
     103                dev->pipes = NULL;
     104                dev->pipes_count = 0;
    116105                return EOK;
    117106        }
    118107
    119         dev->pipes = malloc(sizeof(usb_endpoint_mapping_t) * pipe_count);
    120         if (dev->pipes == NULL) {
    121                 usb_log_oom(dev->ddf_dev);
    122                 return ENOMEM;
    123         }
    124 
    125         size_t i;
    126 
    127         /* Initialize to NULL first for rollback purposes. */
    128         for (i = 0; i < pipe_count; i++) {
    129                 dev->pipes[i].pipe = NULL;
    130         }
    131 
    132         for (i = 0; i < pipe_count; i++) {
    133                 dev->pipes[i].pipe = malloc(sizeof(usb_pipe_t));
    134                 if (dev->pipes[i].pipe == NULL) {
    135                         usb_log_oom(dev->ddf_dev);
    136                         rc = ENOMEM;
    137                         goto rollback;
    138                 }
    139 
    140                 dev->pipes[i].description = endpoints[i];
    141                 dev->pipes[i].interface_no = dev->interface_no;
    142                 dev->pipes[i].interface_setting = 0;
    143         }
    144 
    145         rc = usb_pipe_initialize_from_configuration(dev->pipes, pipe_count,
     108        usb_endpoint_mapping_t *pipes;
     109        size_t pipes_count;
     110
     111        int rc = usb_device_create_pipes(dev->ddf_dev, &dev->wire, endpoints,
    146112            dev->descriptors.configuration, dev->descriptors.configuration_size,
    147             &dev->wire);
    148         if (rc != EOK) {
    149                 usb_log_error("Failed initializing USB endpoints: %s.\n",
    150                     str_error(rc));
    151                 goto rollback;
    152         }
    153 
    154         /* Register the endpoints. */
    155         usb_hc_connection_t hc_conn;
    156         rc = usb_hc_connection_initialize_from_device(&hc_conn, dev->ddf_dev);
    157         if (rc != EOK) {
    158                 usb_log_error(
    159                     "Failed initializing connection to host controller: %s.\n",
    160                     str_error(rc));
    161                 goto rollback;
    162         }
    163         rc = usb_hc_connection_open(&hc_conn);
    164         if (rc != EOK) {
    165                 usb_log_error("Failed to connect to host controller: %s.\n",
    166                     str_error(rc));
    167                 goto rollback;
    168         }
    169         for (i = 0; i < pipe_count; i++) {
    170                 if (dev->pipes[i].present) {
    171                         rc = usb_pipe_register(dev->pipes[i].pipe,
    172                             dev->pipes[i].descriptor->poll_interval,
    173                             &hc_conn);
    174                         /* Ignore error when operation not supported by HC. */
    175                         if ((rc != EOK) && (rc != ENOTSUP)) {
    176                                 /* FIXME: what shall we do? */
    177                                 dev->pipes[i].present = false;
    178                                 free(dev->pipes[i].pipe);
    179                                 dev->pipes[i].pipe = NULL;
    180                         }
    181                 }
    182         }
    183         /* Ignoring errors here. */
    184         usb_hc_connection_close(&hc_conn);
    185 
    186         dev->pipes_count = pipe_count;
    187 
    188         return EOK;
    189 
    190 rollback:
    191         for (i = 0; i < pipe_count; i++) {
    192                 if (dev->pipes[i].pipe != NULL) {
    193                         free(dev->pipes[i].pipe);
    194                 }
    195         }
    196         free(dev->pipes);
    197 
    198         return rc;
    199 }
    200 
    201 /** Initialize all endpoint pipes.
    202  *
    203  * @param drv The driver.
    204  * @param dev The device to be initialized.
    205  * @return Error code.
    206  */
    207 static int initialize_pipes(usb_device_t *dev)
    208 {
    209         int rc;
    210 
    211         rc = usb_device_connection_initialize_from_device(&dev->wire,
    212             dev->ddf_dev);
    213         if (rc != EOK) {
    214                 usb_log_error(
    215                     "Failed initializing connection on device `%s'. %s.\n",
    216                     dev->ddf_dev->name, str_error(rc));
    217                 return rc;
    218         }
    219 
    220         rc = usb_pipe_initialize_default_control(&dev->ctrl_pipe,
    221             &dev->wire);
    222         if (rc != EOK) {
    223                 usb_log_error("Failed to initialize default control pipe " \
    224                     "on device `%s': %s.\n",
    225                     dev->ddf_dev->name, str_error(rc));
    226                 return rc;
    227         }
    228 
    229         rc = usb_pipe_probe_default_control(&dev->ctrl_pipe);
    230         if (rc != EOK) {
    231                 usb_log_error(
    232                     "Probing default control pipe on device `%s' failed: %s.\n",
    233                     dev->ddf_dev->name, str_error(rc));
    234                 return rc;
    235         }
    236 
    237         /* Get our interface. */
    238         dev->interface_no = usb_device_get_assigned_interface(dev->ddf_dev);
    239 
    240         /*
    241          * For further actions, we need open session on default control pipe.
    242          */
    243         rc = usb_pipe_start_session(&dev->ctrl_pipe);
    244         if (rc != EOK) {
    245                 usb_log_error("Failed to start an IPC session: %s.\n",
    246                     str_error(rc));
    247                 return rc;
    248         }
    249 
    250         /* Get the device descriptor. */
    251         rc = usb_request_get_device_descriptor(&dev->ctrl_pipe,
    252             &dev->descriptors.device);
    253         if (rc != EOK) {
    254                 usb_log_error("Failed to retrieve device descriptor: %s.\n",
    255                     str_error(rc));
    256                 return rc;
    257         }
    258 
    259         /* Get the full configuration descriptor. */
    260         rc = usb_request_get_full_configuration_descriptor_alloc(
    261             &dev->ctrl_pipe, 0, (void **) &dev->descriptors.configuration,
    262             &dev->descriptors.configuration_size);
    263         if (rc != EOK) {
    264                 usb_log_error("Failed retrieving configuration descriptor: %s. %s\n",
    265                     dev->ddf_dev->name, str_error(rc));
    266                 return rc;
    267         }
    268 
    269         if (driver->endpoints != NULL) {
    270                 rc = initialize_other_pipes(driver->endpoints, dev);
    271         }
    272 
    273         /* No checking here. */
    274         usb_pipe_end_session(&dev->ctrl_pipe);
    275 
    276         /* Rollback actions. */
    277         if (rc != EOK) {
    278                 if (dev->descriptors.configuration != NULL) {
    279                         free(dev->descriptors.configuration);
    280                 }
    281         }
    282 
    283         return rc;
    284 }
    285 
    286 /** Count number of alternate settings of a interface.
    287  *
    288  * @param config_descr Full configuration descriptor.
    289  * @param config_descr_size Size of @p config_descr in bytes.
    290  * @param interface_no Interface number.
    291  * @return Number of alternate interfaces for @p interface_no interface.
    292  */
    293 static size_t count_alternate_interfaces(uint8_t *config_descr,
    294     size_t config_descr_size, int interface_no)
    295 {
    296         assert(config_descr != NULL);
    297         usb_dp_parser_t dp_parser = {
    298                 .nesting = usb_dp_standard_descriptor_nesting
    299         };
    300         usb_dp_parser_data_t dp_data = {
    301                 .data = config_descr,
    302                 .size = config_descr_size,
    303                 .arg = NULL
    304         };
    305 
    306         size_t alternate_count = 0;
    307 
    308         uint8_t *iface_ptr = usb_dp_get_nested_descriptor(&dp_parser,
    309             &dp_data, config_descr);
    310         while (iface_ptr != NULL) {
    311                 usb_standard_interface_descriptor_t *iface
    312                     = (usb_standard_interface_descriptor_t *) iface_ptr;
    313                 if (iface->descriptor_type == USB_DESCTYPE_INTERFACE) {
    314                         if (iface->interface_number == interface_no) {
    315                                 alternate_count++;
    316                         }
    317                 }
    318                 iface_ptr = usb_dp_get_sibling_descriptor(&dp_parser, &dp_data,
    319                     config_descr, iface_ptr);
    320         }
    321 
    322         return alternate_count;
    323 }
    324 
    325 /** Initialize structures related to alternate interfaces.
    326  *
    327  * @param dev Device where alternate settings shall be initialized.
    328  * @return Error code.
    329  */
    330 static int initialize_alternate_interfaces(usb_device_t *dev)
    331 {
    332         if (dev->interface_no < 0) {
    333                 dev->alternate_interfaces = NULL;
    334                 return EOK;
    335         }
    336 
    337         usb_alternate_interfaces_t *alternates
    338             = malloc(sizeof(usb_alternate_interfaces_t));
    339 
    340         if (alternates == NULL) {
    341                 return ENOMEM;
    342         }
    343 
    344         alternates->alternative_count
    345             = count_alternate_interfaces(dev->descriptors.configuration,
    346             dev->descriptors.configuration_size, dev->interface_no);
    347 
    348         if (alternates->alternative_count == 0) {
    349                 free(alternates);
    350                 return ENOENT;
    351         }
    352 
    353         alternates->alternatives = malloc(alternates->alternative_count
    354             * sizeof(usb_alternate_interface_descriptors_t));
    355         if (alternates->alternatives == NULL) {
    356                 free(alternates);
    357                 return ENOMEM;
    358         }
    359 
    360         alternates->current = 0;
    361 
    362         usb_dp_parser_t dp_parser = {
    363                 .nesting = usb_dp_standard_descriptor_nesting
    364         };
    365         usb_dp_parser_data_t dp_data = {
    366                 .data = dev->descriptors.configuration,
    367                 .size = dev->descriptors.configuration_size,
    368                 .arg = NULL
    369         };
    370 
    371         usb_alternate_interface_descriptors_t *cur_alt_iface
    372             = &alternates->alternatives[0];
    373 
    374         uint8_t *iface_ptr = usb_dp_get_nested_descriptor(&dp_parser,
    375             &dp_data, dp_data.data);
    376         while (iface_ptr != NULL) {
    377                 usb_standard_interface_descriptor_t *iface
    378                     = (usb_standard_interface_descriptor_t *) iface_ptr;
    379                 if ((iface->descriptor_type != USB_DESCTYPE_INTERFACE)
    380                     || (iface->interface_number != dev->interface_no)) {
    381                         iface_ptr = usb_dp_get_sibling_descriptor(&dp_parser,
    382                             &dp_data,
    383                             dp_data.data, iface_ptr);
    384                         continue;
    385                 }
    386 
    387                 cur_alt_iface->interface = iface;
    388                 cur_alt_iface->nested_descriptors = iface_ptr + sizeof(*iface);
    389 
    390                 /* Find next interface to count size of nested descriptors. */
    391                 iface_ptr = usb_dp_get_sibling_descriptor(&dp_parser, &dp_data,
    392                     dp_data.data, iface_ptr);
    393                 if (iface_ptr == NULL) {
    394                         uint8_t *next = dp_data.data + dp_data.size;
    395                         cur_alt_iface->nested_descriptors_size
    396                             = next - cur_alt_iface->nested_descriptors;
    397                 } else {
    398                         cur_alt_iface->nested_descriptors_size
    399                             = iface_ptr - cur_alt_iface->nested_descriptors;
    400                 }
    401 
    402                 cur_alt_iface++;
    403         }
    404 
    405         dev->alternate_interfaces = alternates;
     113            dev->interface_no, alternate_setting,
     114            &pipes, &pipes_count);
     115
     116        if (rc != EOK) {
     117                return rc;
     118        }
     119
     120        dev->pipes = pipes;
     121        dev->pipes_count = pipes_count;
    406122
    407123        return EOK;
     
    423139        int rc;
    424140
    425         usb_device_t *dev = malloc(sizeof(usb_device_t));
    426         if (dev == NULL) {
    427                 usb_log_error("Out of memory when adding device `%s'.\n",
    428                     gen_dev->name);
    429                 return ENOMEM;
    430         }
    431 
    432 
    433         dev->ddf_dev = gen_dev;
    434         dev->ddf_dev->driver_data = dev;
    435         dev->driver_data = NULL;
    436         dev->descriptors.configuration = NULL;
    437 
    438         dev->pipes_count = 0;
    439         dev->pipes = NULL;
    440 
    441         rc = initialize_pipes(dev);
    442         if (rc != EOK) {
    443                 free(dev);
    444                 return rc;
    445         }
    446 
    447         (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        }
    448149
    449150        return driver->ops->add_device(dev);
     
    457158static int destroy_current_pipes(usb_device_t *dev)
    458159{
    459         size_t i;
    460         int rc;
    461 
    462         /* TODO: this shall be done under some device mutex. */
    463 
    464         /* First check that no session is opened. */
    465         for (i = 0; i < dev->pipes_count; i++) {
    466                 if (usb_pipe_is_session_started(dev->pipes[i].pipe)) {
    467                         return EBUSY;
    468                 }
    469         }
    470 
    471         /* Prepare connection to HC. */
    472         usb_hc_connection_t hc_conn;
    473         rc = usb_hc_connection_initialize_from_device(&hc_conn, dev->ddf_dev);
    474         if (rc != EOK) {
    475                 return rc;
    476         }
    477         rc = usb_hc_connection_open(&hc_conn);
    478         if (rc != EOK) {
    479                 return rc;
    480         }
    481 
    482         /* Destroy the pipes. */
    483         for (i = 0; i < dev->pipes_count; i++) {
    484                 usb_pipe_unregister(dev->pipes[i].pipe, &hc_conn);
    485                 free(dev->pipes[i].pipe);
    486         }
    487 
    488         usb_hc_connection_close(&hc_conn);
    489 
    490         free(dev->pipes);
     160        int rc = usb_device_destroy_pipes(dev->ddf_dev,
     161            dev->pipes, dev->pipes_count);
     162        if (rc != EOK) {
     163                return rc;
     164        }
     165
    491166        dev->pipes = NULL;
    492167        dev->pipes_count = 0;
     
    505180 * with usb_pipe_initialize_from_configuration().
    506181 *
     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 *
    507189 * @param dev USB device.
    508190 * @param alternate_setting Alternate setting to choose.
     
    519201        int rc;
    520202
    521         /* TODO: more transactional behavior. */
    522 
    523203        /* Destroy existing pipes. */
    524204        rc = destroy_current_pipes(dev);
     
    535215
    536216        /* Create new pipes. */
    537         rc = initialize_other_pipes(endpoints, dev);
     217        rc = initialize_other_pipes(endpoints, dev, (int) alternate_setting);
    538218
    539219        return rc;
     220}
     221
     222/** Retrieve basic descriptors from the device.
     223 *
     224 * @param[in] ctrl_pipe Control endpoint pipe.
     225 * @param[out] descriptors Where to store the descriptors.
     226 * @return Error code.
     227 */
     228int usb_device_retrieve_descriptors(usb_pipe_t *ctrl_pipe,
     229    usb_device_descriptors_t *descriptors)
     230{
     231        assert(descriptors != NULL);
     232
     233        descriptors->configuration = NULL;
     234
     235        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        }
     242
     243        /* Get the device descriptor. */
     244        rc = usb_request_get_device_descriptor(ctrl_pipe, &descriptors->device);
     245        if (rc != EOK) {
     246                goto leave;
     247        }
     248
     249        /* Get the full configuration descriptor. */
     250        rc = usb_request_get_full_configuration_descriptor_alloc(
     251            ctrl_pipe, 0, (void **) &descriptors->configuration,
     252            &descriptors->configuration_size);
     253
     254leave:
     255        usb_pipe_end_long_transfer(ctrl_pipe);
     256
     257        return rc;
     258}
     259
     260/** Create pipes for a device.
     261 *
     262 * This is more or less a wrapper that does following actions:
     263 * - allocate and initialize pipes
     264 * - map endpoints to the pipes based on the descriptions
     265 * - registers endpoints with the host controller
     266 *
     267 * @param[in] dev Generic DDF device backing the USB one.
     268 * @param[in] wire Initialized backing connection to the host controller.
     269 * @param[in] endpoints Endpoints description, NULL terminated.
     270 * @param[in] config_descr Configuration descriptor of active configuration.
     271 * @param[in] config_descr_size Size of @p config_descr in bytes.
     272 * @param[in] interface_no Interface to map from.
     273 * @param[in] interface_setting Interface setting (default is usually 0).
     274 * @param[out] pipes_ptr Where to store array of created pipes
     275 *      (not NULL terminated).
     276 * @param[out] pipes_count_ptr Where to store number of pipes
     277 *      (set to if you wish to ignore the count).
     278 * @return Error code.
     279 */
     280int usb_device_create_pipes(ddf_dev_t *dev, usb_device_connection_t *wire,
     281    usb_endpoint_description_t **endpoints,
     282    uint8_t *config_descr, size_t config_descr_size,
     283    int interface_no, int interface_setting,
     284    usb_endpoint_mapping_t **pipes_ptr, size_t *pipes_count_ptr)
     285{
     286        assert(dev != NULL);
     287        assert(wire != NULL);
     288        assert(endpoints != NULL);
     289        assert(config_descr != NULL);
     290        assert(config_descr_size > 0);
     291        assert(pipes_ptr != NULL);
     292
     293        size_t i;
     294        int rc;
     295
     296        size_t pipe_count = count_other_pipes(endpoints);
     297        if (pipe_count == 0) {
     298                *pipes_ptr = NULL;
     299                return EOK;
     300        }
     301
     302        usb_endpoint_mapping_t *pipes
     303            = malloc(sizeof(usb_endpoint_mapping_t) * pipe_count);
     304        if (pipes == NULL) {
     305                return ENOMEM;
     306        }
     307
     308        /* Initialize to NULL to allow smooth rollback. */
     309        for (i = 0; i < pipe_count; i++) {
     310                pipes[i].pipe = NULL;
     311        }
     312
     313        /* Now allocate and fully initialize. */
     314        for (i = 0; i < pipe_count; i++) {
     315                pipes[i].pipe = malloc(sizeof(usb_pipe_t));
     316                if (pipes[i].pipe == NULL) {
     317                        rc = ENOMEM;
     318                        goto rollback_free_only;
     319                }
     320                pipes[i].description = endpoints[i];
     321                pipes[i].interface_no = interface_no;
     322                pipes[i].interface_setting = interface_setting;
     323        }
     324
     325        /* Find the mapping from configuration descriptor. */
     326        rc = usb_pipe_initialize_from_configuration(pipes, pipe_count,
     327            config_descr, config_descr_size, wire);
     328        if (rc != EOK) {
     329                goto rollback_free_only;
     330        }
     331
     332        /* Register the endpoints with HC. */
     333        usb_hc_connection_t hc_conn;
     334        rc = usb_hc_connection_initialize_from_device(&hc_conn, dev);
     335        if (rc != EOK) {
     336                goto rollback_free_only;
     337        }
     338
     339        rc = usb_hc_connection_open(&hc_conn);
     340        if (rc != EOK) {
     341                goto rollback_free_only;
     342        }
     343
     344        for (i = 0; i < pipe_count; i++) {
     345                if (pipes[i].present) {
     346                        rc = usb_pipe_register(pipes[i].pipe,
     347                            pipes[i].descriptor->poll_interval, &hc_conn);
     348                        if (rc != EOK) {
     349                                goto rollback_unregister_endpoints;
     350                        }
     351                }
     352        }
     353
     354        usb_hc_connection_close(&hc_conn);
     355
     356        *pipes_ptr = pipes;
     357        if (pipes_count_ptr != NULL) {
     358                *pipes_count_ptr = pipe_count;
     359        }
     360
     361        return EOK;
     362
     363        /*
     364         * Jump here if something went wrong after endpoints have
     365         * been registered.
     366         * This is also the target when the registration of
     367         * endpoints fails.
     368         */
     369rollback_unregister_endpoints:
     370        for (i = 0; i < pipe_count; i++) {
     371                if (pipes[i].present) {
     372                        usb_pipe_unregister(pipes[i].pipe, &hc_conn);
     373                }
     374        }
     375
     376        usb_hc_connection_close(&hc_conn);
     377
     378        /*
     379         * Jump here if something went wrong before some actual communication
     380         * with HC. Then the only thing that needs to be done is to free
     381         * allocated memory.
     382         */
     383rollback_free_only:
     384        for (i = 0; i < pipe_count; i++) {
     385                if (pipes[i].pipe != NULL) {
     386                        free(pipes[i].pipe);
     387                }
     388        }
     389        free(pipes);
     390
     391        return rc;
     392}
     393
     394/** Destroy pipes previously created by usb_device_create_pipes.
     395 *
     396 * @param[in] dev Generic DDF device backing the USB one.
     397 * @param[in] pipes Endpoint mapping to be destroyed.
     398 * @param[in] pipes_count Number of endpoints.
     399 */
     400int usb_device_destroy_pipes(ddf_dev_t *dev,
     401    usb_endpoint_mapping_t *pipes, size_t pipes_count)
     402{
     403        assert(dev != NULL);
     404        assert(((pipes != NULL) && (pipes_count > 0))
     405            || ((pipes == NULL) && (pipes_count == 0)));
     406
     407        if (pipes_count == 0) {
     408                return EOK;
     409        }
     410
     411        int rc;
     412
     413        /* Prepare connection to HC to allow endpoint unregistering. */
     414        usb_hc_connection_t hc_conn;
     415        rc = usb_hc_connection_initialize_from_device(&hc_conn, dev);
     416        if (rc != EOK) {
     417                return rc;
     418        }
     419        rc = usb_hc_connection_open(&hc_conn);
     420        if (rc != EOK) {
     421                return rc;
     422        }
     423
     424        /* Destroy the pipes. */
     425        size_t i;
     426        for (i = 0; i < pipes_count; i++) {
     427                usb_pipe_unregister(pipes[i].pipe, &hc_conn);
     428                free(pipes[i].pipe);
     429        }
     430
     431        usb_hc_connection_close(&hc_conn);
     432
     433        free(pipes);
     434
     435        return EOK;
     436}
     437
     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;
    540536}
    541537
  • uspace/lib/usb/src/devpoll.c

    ref354b6 re50cd7f  
    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 *
     
    6674        usb_pipe_t *pipe
    6775            = polling_data->dev->pipes[polling_data->pipe_index].pipe;
     76       
     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        }
    6890
    6991        size_t failed_attempts = 0;
    70         while (failed_attempts < MAX_FAILED_ATTEMPTS) {
     92        while (failed_attempts <= polling_data->max_failures) {
    7193                int rc;
    72 
    73                 rc = usb_pipe_start_session(pipe);
    74                 if (rc != EOK) {
    75                         failed_attempts++;
    76                         continue;
    77                 }
    7894
    7995                size_t actual_size;
     
    8197                    polling_data->request_size, &actual_size);
    8298
    83                 /* Quit the session regardless of errors. */
    84                 usb_pipe_end_session(pipe);
     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                }
    85124
    86125                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                        }
    87135                        failed_attempts++;
    88136                        continue;
     
    90138
    91139                /* We have the data, execute the callback now. */
    92                 bool carry_on = polling_data->callback(polling_data->dev,
     140                bool carry_on = polling_data->on_data(polling_data->dev,
    93141                    polling_data->buffer, actual_size,
    94142                    polling_data->custom_arg);
     
    101149                /* Reset as something might be only a temporary problem. */
    102150                failed_attempts = 0;
    103         }
    104 
    105         if (failed_attempts > 0) {
    106                 usb_log_error(
    107                     "Polling of device `%s' terminated: recurring failures.\n",
    108                     polling_data->dev->ddf_dev->name);
    109         }
    110 
    111         if (polling_data->terminated_callback != NULL) {
    112                 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,
    113158                    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                }
    114173        }
    115174
     
    154213        }
    155214
     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
    156272        polling_data_t *polling_data = malloc(sizeof(polling_data_t));
    157273        if (polling_data == NULL) {
     
    159275        }
    160276
    161         /* Allocate now to prevent immediate failure in the polling fibril. */
    162         polling_data->buffer = malloc(request_size);
     277        /* Fill-in the data. */
     278        polling_data->buffer = malloc(sizeof(request_size));
    163279        if (polling_data->buffer == NULL) {
    164280                free(polling_data);
    165281                return ENOMEM;
    166282        }
     283        polling_data->request_size = request_size;
    167284        polling_data->dev = dev;
    168285        polling_data->pipe_index = pipe_index;
    169         polling_data->callback = callback;
    170         polling_data->terminated_callback = terminated_callback;
    171         polling_data->request_size = request_size;
    172286        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;
    173301
    174302        fid_t fibril = fibril_create(polling_fibril, polling_data);
     
    176304                free(polling_data->buffer);
    177305                free(polling_data);
    178                 /* FIXME: better error code. */
    179306                return ENOMEM;
    180307        }
    181308        fibril_add_ready(fibril);
    182309
    183         /* The allocated buffer etc. will be freed by the fibril. */
     310        /* Fibril launched. That fibril will free the allocated data. */
    184311
    185312        return EOK;
  • uspace/lib/usb/src/hidparser.c

    ref354b6 re50cd7f  
    877877
    878878        offset = item->offset + (j * item->size);
    879        
    880879        // FIXME
    881880        if((size_t)(offset/8) != (size_t)((offset+item->size-1)/8)) {
     
    13521351
    13531352                field = list_get_instance(field_it, usb_hid_report_field_t, link);
    1354                 usb_hid_report_path_append_item (field->collection_path, field->usage_page, field->usage);
    1355                 if(usb_hid_report_compare_usage_path (field->collection_path, path, flags) == EOK) {
    1356                         ret++;
    1357                 }
    1358                 usb_hid_report_remove_last_item (field->collection_path);
     1353                if(USB_HID_ITEM_FLAG_CONSTANT(field->item_flags) == 0){
     1354                        usb_hid_report_path_append_item (field->collection_path, field->usage_page, field->usage);
     1355                        if(usb_hid_report_compare_usage_path (field->collection_path, path, flags) == EOK) {
     1356                                ret++;
     1357                        }
     1358                        usb_hid_report_remove_last_item (field->collection_path);
     1359                }
    13591360               
    13601361                field_it = field_it->next;
     
    15361537
    15371538/**
    1538  * Clones given report item structure and returns the new one
    1539  *
    1540  * @param item Report item structure to clone
    1541  * @return Clonned item
    1542  */
    1543 usb_hid_report_item_t *usb_hid_report_item_clone(const usb_hid_report_item_t *item)
    1544 {
    1545         usb_hid_report_item_t *new_report_item;
    1546        
    1547         if(!(new_report_item = malloc(sizeof(usb_hid_report_item_t)))) {
    1548                 return NULL;
    1549         }                                       
    1550         memcpy(new_report_item,item, sizeof(usb_hid_report_item_t));
    1551         link_initialize(&(new_report_item->link));
    1552 
    1553         return new_report_item;
    1554 }
    1555 
    1556 
    1557 /**
    15581539 *
    15591540 *
     
    16041585}
    16051586
     1587
     1588usb_hid_report_item_t *usb_hid_report_item_clone(const usb_hid_report_item_t *item)
     1589{
     1590        usb_hid_report_item_t *new_report_item;
     1591       
     1592        if(!(new_report_item = malloc(sizeof(usb_hid_report_item_t)))) {
     1593                return NULL;
     1594        }                                       
     1595        memcpy(new_report_item,item, sizeof(usb_hid_report_item_t));
     1596        link_initialize(&(new_report_item->link));
     1597
     1598        return new_report_item;
     1599}
     1600
     1601
     1602usb_hid_report_field_t *usb_hid_report_get_sibling(usb_hid_report_t *report,
     1603                                                        usb_hid_report_field_t *field,
     1604                            usb_hid_report_path_t *path, int flags,
     1605                            usb_hid_report_type_t type)
     1606{
     1607        usb_hid_report_description_t *report_des = usb_hid_report_find_description (report, path->report_id, type);
     1608        link_t *field_it;
     1609       
     1610        if(report_des == NULL){
     1611                return NULL;
     1612        }
     1613
     1614        if(field == NULL){
     1615                // vezmu prvni co mathuje podle path!!
     1616                field_it = report_des->report_items.next;
     1617        }
     1618        else {
     1619                field_it = field->link.next;
     1620        }
     1621
     1622        while(field_it != &report_des->report_items) {
     1623                field = list_get_instance(field_it, usb_hid_report_field_t, link);
     1624                       
     1625                usb_hid_report_path_append_item (field->collection_path, field->usage_page, field->usage);
     1626                if(usb_hid_report_compare_usage_path (field->collection_path, path, flags) == EOK){
     1627                        usb_hid_report_remove_last_item (field->collection_path);
     1628                        usb_log_debug("....OK\n");
     1629                        return field;
     1630                }
     1631                usb_hid_report_remove_last_item (field->collection_path);
     1632
     1633                field_it = field_it->next;
     1634        }
     1635
     1636        return NULL;
     1637}
    16061638/**
    16071639 * @}
  • uspace/lib/usb/src/hidreport.c

    ref354b6 re50cd7f  
    8080                d = usb_dp_get_sibling_descriptor(&parser, &parser_data,
    8181                    dev->descriptors.configuration, d);
     82                ++i;
    8283        }
    8384       
     
    118119        uint16_t length =  hid_desc->report_desc_info.length;
    119120        size_t actual_size = 0;
    120        
    121         /*
    122          * Start session for the control transfer.
    123          */
    124         int sess_rc = usb_pipe_start_session(&dev->ctrl_pipe);
    125         if (sess_rc != EOK) {
    126                 usb_log_warning("Failed to start a session: %s.\n",
    127                     str_error(sess_rc));
    128                 return sess_rc;
    129         }
    130121
    131122        /*
     
    161152                    "%u)\n", actual_size, length);
    162153                return EINVAL;
    163         }
    164        
    165         /*
    166          * End session for the control transfer.
    167          */
    168         sess_rc = usb_pipe_end_session(&dev->ctrl_pipe);
    169         if (sess_rc != EOK) {
    170                 usb_log_warning("Failed to end a session: %s.\n",
    171                     str_error(sess_rc));
    172                 free(*report_desc);
    173                 *report_desc = NULL;
    174                 return sess_rc;
    175154        }
    176155       
  • uspace/lib/usb/src/hidreq.c

    ref354b6 re50cd7f  
    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

    ref354b6 re50cd7f  
    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 = USB_DIRECTION_BOTH;
     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;
     77        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);
    81100}
    82101/*----------------------------------------------------------------------------*/
     
    86105 *
    87106 */
    88 void usb_transfer_batch_finish(usb_transfer_batch_t *instance, int error)
     107void usb_transfer_batch_finish(usb_transfer_batch_t *instance)
    89108{
    90109        assert(instance);
    91         instance->error = error;
     110        assert(instance->ep);
     111        endpoint_release(instance->ep);
    92112        instance->next_step(instance);
    93113}
     
    103123        assert(instance);
    104124        assert(instance->callback_in);
     125        assert(instance->ep);
    105126
    106127        /* We are data in, we need data */
    107         memcpy(instance->buffer, instance->transport_buffer,
    108             instance->buffer_size);
     128        memcpy(instance->buffer, instance->data_buffer, instance->buffer_size);
    109129
    110130        usb_log_debug("Batch %p done (T%d.%d, %s %s in, %zuB): %s (%d).\n",
    111             instance,
    112             instance->target.address, instance->target.endpoint,
    113             usb_str_speed(instance->speed),
    114             usb_str_transfer_type_short(instance->transfer_type),
    115             instance->transfered_size,
    116             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);
    117135
    118136        instance->callback_in(instance->fun, instance->error,
     
    130148
    131149        usb_log_debug("Batch %p done (T%d.%d, %s %s out): %s (%d).\n",
    132             instance,
    133             instance->target.address, instance->target.endpoint,
    134             usb_str_speed(instance->speed),
    135             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),
    136153            str_error(instance->error), instance->error);
    137154
     
    139156            instance->error, instance->arg);
    140157}
     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}
    141173/**
    142174 * @}
  • uspace/lib/usb/src/host/device_keeper.c

    ref354b6 re50cd7f  
    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) {
    5552                instance->devices[i].occupied = false;
    56                 instance->devices[i].control_used = 0;
    5753                instance->devices[i].handle = 0;
    58                 list_initialize(&instance->devices[i].endpoints);
     54                instance->devices[i].speed = USB_SPEED_MAX;
    5955        }
    60 }
    61 /*----------------------------------------------------------------------------*/
    62 void usb_device_keeper_add_ep(
    63     usb_device_keeper_t *instance, usb_address_t address, endpoint_t *ep)
    64 {
    65         assert(instance);
    66         fibril_mutex_lock(&instance->guard);
    67         assert(instance->devices[address].occupied);
    68         list_append(&ep->same_device_eps, &instance->devices[address].endpoints);
    69         fibril_mutex_unlock(&instance->guard);
    70 }
    71 /*----------------------------------------------------------------------------*/
    72 /** Attempt to obtain address 0, blocks.
    73  *
    74  * @param[in] instance Device keeper structure to use.
    75  * @param[in] speed Speed of the device requesting default address.
    76  */
    77 void usb_device_keeper_reserve_default_address(
    78     usb_device_keeper_t *instance, usb_speed_t speed)
    79 {
    80         assert(instance);
    81         fibril_mutex_lock(&instance->guard);
    82         while (instance->devices[USB_ADDRESS_DEFAULT].occupied) {
    83                 fibril_condvar_wait(&instance->change, &instance->guard);
    84         }
    85         instance->devices[USB_ADDRESS_DEFAULT].occupied = true;
    86         instance->devices[USB_ADDRESS_DEFAULT].speed = speed;
    87         fibril_mutex_unlock(&instance->guard);
    88 }
    89 /*----------------------------------------------------------------------------*/
    90 /** Attempt to obtain address 0, blocks.
    91  *
    92  * @param[in] instance Device keeper structure to use.
    93  * @param[in] speed Speed of the device requesting default address.
    94  */
    95 void usb_device_keeper_release_default_address(usb_device_keeper_t *instance)
    96 {
    97         assert(instance);
    98         fibril_mutex_lock(&instance->guard);
    99         instance->devices[USB_ADDRESS_DEFAULT].occupied = false;
    100         fibril_mutex_unlock(&instance->guard);
    101         fibril_condvar_signal(&instance->change);
    102 }
    103 /*----------------------------------------------------------------------------*/
    104 /** Check setup packet data for signs of toggle reset.
    105  *
    106  * @param[in] instance Device keeper structure to use.
    107  * @param[in] target Device to receive setup packet.
    108  * @param[in] data Setup packet data.
    109  *
    110  * Really ugly one.
    111  */
    112 void usb_device_keeper_reset_if_need(
    113     usb_device_keeper_t *instance, usb_target_t target, const uint8_t *data)
    114 {
    115         assert(instance);
    116         fibril_mutex_lock(&instance->guard);
    117         if (target.endpoint > 15 || target.endpoint < 0
    118             || target.address >= USB_ADDRESS_COUNT || target.address < 0
    119             || !instance->devices[target.address].occupied) {
    120                 fibril_mutex_unlock(&instance->guard);
    121                 usb_log_error("Invalid data when checking for toggle reset.\n");
    122                 return;
    123         }
    124 
    125         switch (data[1])
    126         {
    127         case 0x01: /*clear feature*/
    128                 /* recipient is endpoint, value is zero (ENDPOINT_STALL) */
    129                 if (((data[0] & 0xf) == 1) && ((data[2] | data[3]) == 0)) {
    130                         link_t *current =
    131                             instance->devices[target.address].endpoints.next;
    132                         while (current !=
    133                            &instance->devices[target.address].endpoints)
    134                         {
    135                         /* endpoint number is < 16, thus first byte is enough */
    136                                 endpoint_toggle_reset_filtered(
    137                                     current, data[4]);
    138                                 current = current->next;
    139                         }
    140                 }
    141         break;
    142 
    143         case 0x9: /* set configuration */
    144         case 0x11: /* set interface */
    145                 /* target must be device */
    146                 if ((data[0] & 0xf) == 0) {
    147                         link_t *current =
    148                             instance->devices[target.address].endpoints.next;
    149                         while (current !=
    150                            &instance->devices[target.address].endpoints)
    151                         {
    152                                 endpoint_toggle_reset(current);
    153                                 current = current->next;
    154                         }
    155                 }
    156         break;
    157         }
    158         fibril_mutex_unlock(&instance->guard);
     56        // TODO: is this hack enough?
     57        // (it is needed to allow smooth registration at default address)
     58        instance->devices[0].occupied = true;
     59        instance->last_address = 0;
     60        fibril_mutex_initialize(&instance->guard);
    15961}
    16062/*----------------------------------------------------------------------------*/
     
    18486        assert(new_address != USB_ADDRESS_DEFAULT);
    18587        assert(instance->devices[new_address].occupied == false);
     88
    18689        instance->devices[new_address].occupied = true;
    18790        instance->devices[new_address].speed = speed;
    18891        instance->last_address = new_address;
     92
    18993        fibril_mutex_unlock(&instance->guard);
    19094        return new_address;
     
    202106        assert(instance);
    203107        fibril_mutex_lock(&instance->guard);
     108
    204109        assert(address > 0);
    205110        assert(address <= USB11_ADDRESS_MAX);
    206111        assert(instance->devices[address].occupied);
     112
    207113        instance->devices[address].handle = handle;
    208114        fibril_mutex_unlock(&instance->guard);
     
    223129        fibril_mutex_lock(&instance->guard);
    224130        assert(instance->devices[address].occupied);
     131
    225132        instance->devices[address].occupied = false;
    226133        fibril_mutex_unlock(&instance->guard);
     
    241148        while (address <= USB11_ADDRESS_MAX) {
    242149                if (instance->devices[address].handle == handle) {
     150                        assert(instance->devices[address].occupied);
    243151                        fibril_mutex_unlock(&instance->guard);
    244152                        return address;
     
    262170        assert(address >= 0);
    263171        assert(address <= USB11_ADDRESS_MAX);
     172
    264173        return instance->devices[address].speed;
    265 }
    266 /*----------------------------------------------------------------------------*/
    267 void usb_device_keeper_use_control(
    268     usb_device_keeper_t *instance, usb_target_t target)
    269 {
    270         assert(instance);
    271         const uint16_t ep = 1 << target.endpoint;
    272         fibril_mutex_lock(&instance->guard);
    273         while (instance->devices[target.address].control_used & ep) {
    274                 fibril_condvar_wait(&instance->change, &instance->guard);
    275         }
    276         instance->devices[target.address].control_used |= ep;
    277         fibril_mutex_unlock(&instance->guard);
    278 }
    279 /*----------------------------------------------------------------------------*/
    280 void usb_device_keeper_release_control(
    281     usb_device_keeper_t *instance, usb_target_t target)
    282 {
    283         assert(instance);
    284         const uint16_t ep = 1 << target.endpoint;
    285         fibril_mutex_lock(&instance->guard);
    286         assert((instance->devices[target.address].control_used & ep) != 0);
    287         instance->devices[target.address].control_used &= ~ep;
    288         fibril_mutex_unlock(&instance->guard);
    289         fibril_condvar_signal(&instance->change);
    290174}
    291175/**
  • uspace/lib/usb/src/host/endpoint.c

    ref354b6 re50cd7f  
    3434 */
    3535
     36#include <assert.h>
    3637#include <errno.h>
    3738#include <usb/host/endpoint.h>
     
    4950        instance->max_packet_size = max_packet_size;
    5051        instance->toggle = 0;
    51         link_initialize(&instance->same_device_eps);
     52        instance->active = false;
     53        fibril_mutex_initialize(&instance->guard);
     54        fibril_condvar_initialize(&instance->avail);
     55        endpoint_clear_hc_data(instance);
    5256        return EOK;
    5357}
     
    5660{
    5761        assert(instance);
    58         list_remove(&instance->same_device_eps);
     62        assert(!instance->active);
    5963        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;
     81}
     82/*----------------------------------------------------------------------------*/
     83void endpoint_use(endpoint_t *instance)
     84{
     85        assert(instance);
     86        fibril_mutex_lock(&instance->guard);
     87        while (instance->active)
     88                fibril_condvar_wait(&instance->avail, &instance->guard);
     89        instance->active = true;
     90        fibril_mutex_unlock(&instance->guard);
     91}
     92/*----------------------------------------------------------------------------*/
     93void endpoint_release(endpoint_t *instance)
     94{
     95        assert(instance);
     96        fibril_mutex_lock(&instance->guard);
     97        instance->active = false;
     98        fibril_mutex_unlock(&instance->guard);
     99        fibril_condvar_signal(&instance->avail);
    60100}
    61101/*----------------------------------------------------------------------------*/
     
    63103{
    64104        assert(instance);
     105        if (instance->hc_data.toggle_get)
     106                instance->toggle =
     107                    instance->hc_data.toggle_get(instance->hc_data.data);
    65108        return (int)instance->toggle;
    66109}
     
    70113        assert(instance);
    71114        assert(toggle == 0 || toggle == 1);
     115        if (instance->hc_data.toggle_set)
     116                instance->hc_data.toggle_set(instance->hc_data.data, toggle);
    72117        instance->toggle = toggle;
    73118}
    74119/*----------------------------------------------------------------------------*/
    75 void endpoint_toggle_reset(link_t *ep)
     120void endpoint_toggle_reset_filtered(endpoint_t *instance, usb_target_t target)
    76121{
    77         endpoint_t *instance =
    78             list_get_instance(ep, endpoint_t, same_device_eps);
    79122        assert(instance);
    80         instance->toggle = 0;
    81 }
    82 /*----------------------------------------------------------------------------*/
    83 void endpoint_toggle_reset_filtered(link_t *ep, usb_endpoint_t epn)
    84 {
    85         endpoint_t *instance =
    86             list_get_instance(ep, endpoint_t, same_device_eps);
    87         assert(instance);
    88         if (instance->endpoint == epn)
    89                 instance->toggle = 0;
     123        if (instance->address == target.address &&
     124            (instance->endpoint == target.endpoint || target.endpoint == 0))
     125                endpoint_toggle_set(instance, 0);
    90126}
    91127/**
  • uspace/lib/usb/src/host/usb_endpoint_manager.c

    ref354b6 re50cd7f  
    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/*----------------------------------------------------------------------------*/
     
    202211
    203212        node_t *node = hash_table_get_instance(item, node_t, link);
     213        if (node->ep->active)
     214                return EBUSY;
     215
    204216        instance->free_bw += node->bw;
    205217        hash_table_remove(&instance->ep_table, key, MAX_KEYS);
     
    230242        return node->ep;
    231243}
     244/*----------------------------------------------------------------------------*/
     245/** Check setup packet data for signs of toggle reset.
     246 *
     247 * @param[in] instance Device keeper structure to use.
     248 * @param[in] target Device to receive setup packet.
     249 * @param[in] data Setup packet data.
     250 *
     251 * Really ugly one.
     252 */
     253void usb_endpoint_manager_reset_if_need(
     254    usb_endpoint_manager_t *instance, usb_target_t target, const uint8_t *data)
     255{
     256        assert(instance);
     257        if (target.endpoint > 15 || target.endpoint < 0
     258            || target.address >= USB11_ADDRESS_MAX || target.address < 0) {
     259                usb_log_error("Invalid data when checking for toggle reset.\n");
     260                return;
     261        }
     262
     263        switch (data[1])
     264        {
     265        case 0x01: /*clear feature*/
     266                /* recipient is endpoint, value is zero (ENDPOINT_STALL) */
     267                if (((data[0] & 0xf) == 1) && ((data[2] | data[3]) == 0)) {
     268                        /* endpoint number is < 16, thus first byte is enough */
     269                        usb_target_t reset_target =
     270                            { .address = target.address, data[4] };
     271                        fibril_mutex_lock(&instance->guard);
     272                        hash_table_apply(&instance->ep_table,
     273                            node_toggle_reset_filtered, &reset_target);
     274                        fibril_mutex_unlock(&instance->guard);
     275                }
     276        break;
     277
     278        case 0x9: /* set configuration */
     279        case 0x11: /* set interface */
     280                /* target must be device */
     281                if ((data[0] & 0xf) == 0) {
     282                        usb_target_t reset_target =
     283                            { .address = target.address, 0 };
     284                        fibril_mutex_lock(&instance->guard);
     285                        hash_table_apply(&instance->ep_table,
     286                            node_toggle_reset_filtered, &reset_target);
     287                        fibril_mutex_unlock(&instance->guard);
     288                }
     289        break;
     290        }
     291}
  • uspace/lib/usb/src/hub.c

    ref354b6 re50cd7f  
    4040#include <errno.h>
    4141#include <assert.h>
     42#include <usb/debug.h>
     43
     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))
    4248
    4349/** Check that HC connection is alright.
     
    5359        } while (false)
    5460
    55 
    56 /** Tell host controller to reserve default address.
    57  *
    58  * @param connection Opened connection to host controller.
    59  * @param speed Speed of the device that will respond on the default address.
    60  * @return Error code.
    61  */
    62 int usb_hc_reserve_default_address(usb_hc_connection_t *connection,
    63     usb_speed_t speed)
    64 {
    65         CHECK_CONNECTION(connection);
    66 
    67         return async_req_2_0(connection->hc_phone,
    68             DEV_IFACE_ID(USBHC_DEV_IFACE),
    69             IPC_M_USBHC_RESERVE_DEFAULT_ADDRESS, speed);
    70 }
    71 
    72 /** Tell host controller to release default address.
    73  *
    74  * @param connection Opened connection to host controller.
    75  * @return Error code.
    76  */
    77 int usb_hc_release_default_address(usb_hc_connection_t *connection)
    78 {
    79         CHECK_CONNECTION(connection);
    80 
    81         return async_req_1_0(connection->hc_phone,
    82             DEV_IFACE_ID(USBHC_DEV_IFACE),
    83             IPC_M_USBHC_RELEASE_DEFAULT_ADDRESS);
    84 }
    85 
    8661/** Ask host controller for free address assignment.
    8762 *
     
    178153 * error codes than those listed as return codes by this function itself).
    179154 *
     155 * The @p connection representing connection with host controller does not
     156 * need to be started.
     157 * This function duplicates the connection to allow simultaneous calls of
     158 * this function (i.e. from different fibrils).
     159 *
    180160 * @param[in] parent Parent device (i.e. the hub device).
    181  * @param[in] connection Opened connection to host controller.
     161 * @param[in] connection Connection to host controller.
    182162 * @param[in] dev_speed New device speed.
    183163 * @param[in] enable_port Function for enabling signaling through the port the
     
    206186    ddf_dev_ops_t *dev_ops, void *new_dev_data, ddf_fun_t **new_fun)
    207187{
    208         CHECK_CONNECTION(connection);
     188        assert(connection != NULL);
     189        // FIXME: this is awful, we are accessing directly the structure.
     190        usb_hc_connection_t hc_conn = {
     191                .hc_handle = connection->hc_handle,
     192                .hc_phone = -1
     193        };
     194
     195        int rc;
     196
     197        rc = usb_hc_connection_open(&hc_conn);
     198        if (rc != EOK) {
     199                return rc;
     200        }
     201
    209202
    210203        /*
    211204         * Request new address.
    212205         */
    213         usb_address_t dev_addr = usb_hc_request_address(connection, dev_speed);
     206        usb_address_t dev_addr = usb_hc_request_address(&hc_conn, dev_speed);
    214207        if (dev_addr < 0) {
     208                usb_hc_connection_close(&hc_conn);
    215209                return EADDRNOTAVAIL;
    216210        }
    217211
    218         int rc;
    219 
    220         /*
    221          * Reserve the default address.
    222          */
    223         rc = usb_hc_reserve_default_address(connection, dev_speed);
    224         if (rc != EOK) {
    225                 rc = EBUSY;
    226                 goto leave_release_free_address;
    227         }
    228 
    229         /*
    230          * Enable the port (i.e. allow signaling through this port).
    231          */
    232         rc = enable_port(port_no, arg);
    233         if (rc != EOK) {
    234                 goto leave_release_default_address;
    235         }
    236 
    237         /*
    238          * Change the address from default to the free one.
    239          * We need to create a new control pipe for that.
     212        /*
     213         * We will not register control pipe on default address.
     214         * The registration might fail. That means that someone else already
     215         * registered that endpoint. We will simply wait and try again.
     216         * (Someone else already wants to add a new device.)
    240217         */
    241218        usb_device_connection_t dev_conn;
    242219        rc = usb_device_connection_initialize_on_default_address(&dev_conn,
    243             connection);
     220            &hc_conn);
    244221        if (rc != EOK) {
    245222                rc = ENOTCONN;
    246                 goto leave_release_default_address;
     223                goto leave_release_free_address;
    247224        }
    248225
     
    252229        if (rc != EOK) {
    253230                rc = ENOTCONN;
     231                goto leave_release_free_address;
     232        }
     233
     234        do {
     235                rc = usb_pipe_register_with_speed(&ctrl_pipe, dev_speed, 0,
     236                    &hc_conn);
     237                if (rc != EOK) {
     238                        /* Do not overheat the CPU ;-). */
     239                        async_usleep(ENDPOINT_0_0_REGISTER_ATTEMPT_DELAY_USEC);
     240                }
     241        } while (rc != EOK);
     242
     243        /*
     244         * Endpoint is registered. We can enable the port and change
     245         * device address.
     246         */
     247        rc = enable_port(port_no, arg);
     248        if (rc != EOK) {
    254249                goto leave_release_default_address;
    255250        }
    256251
    257         /* Before sending any traffic, we need to register this
    258          * endpoint.
    259          */
    260         rc = usb_pipe_register(&ctrl_pipe, 0, connection);
    261         if (rc != EOK) {
    262                 rc = EREFUSED;
     252        rc = usb_pipe_probe_default_control(&ctrl_pipe);
     253        if (rc != EOK) {
     254                rc = ESTALL;
    263255                goto leave_release_default_address;
    264256        }
    265         rc = usb_pipe_probe_default_control(&ctrl_pipe);
    266         if (rc != EOK) {
    267                 rc = ENOTCONN;
     257
     258        rc = usb_request_set_address(&ctrl_pipe, dev_addr);
     259        if (rc != EOK) {
     260                rc = ESTALL;
    268261                goto leave_release_default_address;
    269262        }
    270263
    271         rc = usb_pipe_start_session(&ctrl_pipe);
    272         if (rc != EOK) {
    273                 rc = ENOTCONN;
    274                 goto leave_unregister_endpoint;
    275         }
    276 
    277         rc = usb_request_set_address(&ctrl_pipe, dev_addr);
    278         if (rc != EOK) {
    279                 rc = ESTALL;
    280                 goto leave_stop_session;
    281         }
    282 
    283         usb_pipe_end_session(&ctrl_pipe);
    284 
    285         /*
    286          * Register the control endpoint for the new device.
    287          */
    288         rc = usb_pipe_register(&ctrl_pipe, 0, connection);
    289         if (rc != EOK) {
    290                 rc = EREFUSED;
    291                 goto leave_unregister_endpoint;
    292         }
    293 
    294         /*
    295          * Release the original endpoint.
    296          */
    297         unregister_control_endpoint_on_default_address(connection);
    298 
    299         /*
    300          * Once the address is changed, we can return the default address.
    301          */
    302         usb_hc_release_default_address(connection);
    303 
     264        /*
     265         * Address changed. We can release the original endpoint, thus
     266         * allowing other to access the default address.
     267         */
     268        unregister_control_endpoint_on_default_address(&hc_conn);
     269
     270        /*
     271         * Time to register the new endpoint.
     272         */
     273        rc = usb_pipe_register(&ctrl_pipe, 0, &hc_conn);
     274        if (rc != EOK) {
     275                goto leave_release_free_address;
     276        }
    304277
    305278        /*
     
    316289        }
    317290
    318 
    319 
    320291        /*
    321292         * And now inform the host controller about the handle.
     
    325296                .handle = child_handle
    326297        };
    327         rc = usb_hc_register_device(connection, &new_device);
     298        rc = usb_hc_register_device(&hc_conn, &new_device);
    328299        if (rc != EOK) {
    329300                rc = EDESTADDRREQ;
     
    349320         * Completely ignoring errors here.
    350321         */
    351 
    352 leave_stop_session:
    353         usb_pipe_end_session(&ctrl_pipe);
    354 
    355 leave_unregister_endpoint:
    356         usb_pipe_unregister(&ctrl_pipe, connection);
    357 
    358322leave_release_default_address:
    359         usb_hc_release_default_address(connection);
     323        usb_pipe_unregister(&ctrl_pipe, &hc_conn);
    360324
    361325leave_release_free_address:
    362         usb_hc_unregister_device(connection, dev_addr);
     326        usb_hc_unregister_device(&hc_conn, dev_addr);
     327
     328        usb_hc_connection_close(&hc_conn);
    363329
    364330        return rc;
  • uspace/lib/usb/src/pipes.c

    ref354b6 re50cd7f  
    4141#include <errno.h>
    4242#include <assert.h>
     43#include "pipepriv.h"
    4344
    4445#define IPC_AGAIN_DELAY (1000 * 2) /* 2ms */
     
    241242 * necessary.
    242243 *
     244 * @deprecated
     245 * Obsoleted with introduction of usb_pipe_start_long_transfer
     246 *
    243247 * @param pipe Endpoint pipe to start the session on.
    244248 * @return Error code.
     
    246250int usb_pipe_start_session(usb_pipe_t *pipe)
    247251{
    248         assert(pipe);
    249 
    250         if (usb_pipe_is_session_started(pipe)) {
    251                 return EBUSY;
    252         }
    253 
    254         int phone = devman_device_connect(pipe->wire->hc_handle, 0);
    255         if (phone < 0) {
    256                 return phone;
    257         }
    258 
    259         pipe->hc_phone = phone;
    260 
     252        usb_log_warning("usb_pipe_start_session() was deprecated.\n");
    261253        return EOK;
    262254}
     
    265257/** Ends a session on the endpoint pipe.
    266258 *
     259 * @deprecated
     260 * Obsoleted with introduction of usb_pipe_end_long_transfer
     261 *
    267262 * @see usb_pipe_start_session
    268263 *
     
    272267int usb_pipe_end_session(usb_pipe_t *pipe)
    273268{
    274         assert(pipe);
    275 
    276         if (!usb_pipe_is_session_started(pipe)) {
    277                 return ENOENT;
    278         }
    279 
    280         int rc = async_hangup(pipe->hc_phone);
    281         if (rc != EOK) {
    282                 return rc;
    283         }
    284 
    285         pipe->hc_phone = -1;
    286 
     269        usb_log_warning("usb_pipe_end_session() was deprecated.\n");
    287270        return EOK;
    288271}
     
    298281bool usb_pipe_is_session_started(usb_pipe_t *pipe)
    299282{
    300         return (pipe->hc_phone >= 0);
     283        pipe_acquire(pipe);
     284        bool started = pipe->refcount > 0;
     285        pipe_release(pipe);
     286        return started;
     287}
     288
     289/** Prepare pipe for a long transfer.
     290 *
     291 * By a long transfer is mean transfer consisting of several
     292 * requests to the HC.
     293 * Calling such function is optional and it has positive effect of
     294 * improved performance because IPC session is initiated only once.
     295 *
     296 * @param pipe Pipe over which the transfer will happen.
     297 * @return Error code.
     298 */
     299int usb_pipe_start_long_transfer(usb_pipe_t *pipe)
     300{
     301        return pipe_add_ref(pipe);
     302}
     303
     304/** Terminate a long transfer on a pipe.
     305 *
     306 * @see usb_pipe_start_long_transfer
     307 *
     308 * @param pipe Pipe where to end the long transfer.
     309 */
     310void usb_pipe_end_long_transfer(usb_pipe_t *pipe)
     311{
     312        pipe_drop_ref(pipe);
    301313}
    302314
  • uspace/lib/usb/src/pipesinit.c

    ref354b6 re50cd7f  
    356356        assert(connection);
    357357
     358        fibril_mutex_initialize(&pipe->guard);
    358359        pipe->wire = connection;
    359360        pipe->hc_phone = -1;
     361        fibril_mutex_initialize(&pipe->hc_phone_mutex);
    360362        pipe->endpoint_no = endpoint_no;
    361363        pipe->transfer_type = transfer_type;
    362364        pipe->max_packet_size = max_packet_size;
    363365        pipe->direction = direction;
     366        pipe->refcount = 0;
     367        pipe->auto_reset_halt = false;
    364368
    365369        return EOK;
     
    382386            0, USB_TRANSFER_CONTROL, CTRL_PIPE_MIN_PACKET_SIZE,
    383387            USB_DIRECTION_BOTH);
     388
     389        pipe->auto_reset_halt = true;
    384390
    385391        return rc;
     
    413419        int rc;
    414420
    415         TRY_LOOP(failed_attempts) {
    416                 rc = usb_pipe_start_session(pipe);
    417                 if (rc == EOK) {
    418                         break;
    419                 }
    420         }
     421        rc = usb_pipe_start_long_transfer(pipe);
    421422        if (rc != EOK) {
    422423                return rc;
     
    439440                }
    440441        }
    441         usb_pipe_end_session(pipe);
     442        usb_pipe_end_long_transfer(pipe);
    442443        if (rc != EOK) {
    443444                return rc;
     
    461462    usb_hc_connection_t *hc_connection)
    462463{
     464        return usb_pipe_register_with_speed(pipe, USB_SPEED_MAX + 1,
     465            interval, hc_connection);
     466}
     467
     468/** Register endpoint with a speed at the host controller.
     469 *
     470 * You will rarely need to use this function because it is needed only
     471 * if the registered endpoint is of address 0 and there is no other way
     472 * to tell speed of the device at address 0.
     473 *
     474 * @param pipe Pipe to be registered.
     475 * @param speed Speed of the device
     476 *      (invalid speed means use previously specified one).
     477 * @param interval Polling interval.
     478 * @param hc_connection Connection to the host controller (must be opened).
     479 * @return Error code.
     480 */
     481int usb_pipe_register_with_speed(usb_pipe_t *pipe, usb_speed_t speed,
     482    unsigned int interval,
     483    usb_hc_connection_t *hc_connection)
     484{
    463485        assert(pipe);
    464486        assert(hc_connection);
     
    468490        }
    469491
    470 #define _PACK(high, low) ((high) * 256 + (low))
    471 
    472         return async_req_5_0(hc_connection->hc_phone,
     492#define _PACK2(high, low) (((high) << 16) + (low))
     493#define _PACK3(high, middle, low) (((((high) << 8) + (middle)) << 8) + (low))
     494
     495        return async_req_4_0(hc_connection->hc_phone,
    473496            DEV_IFACE_ID(USBHC_DEV_IFACE), IPC_M_USBHC_REGISTER_ENDPOINT,
    474             _PACK(pipe->wire->address, pipe->endpoint_no),
    475             _PACK(pipe->transfer_type, pipe->direction),
    476             pipe->max_packet_size, interval);
    477 
    478 #undef _PACK
     497            _PACK2(pipe->wire->address, pipe->endpoint_no),
     498            _PACK3(speed, pipe->transfer_type, pipe->direction),
     499            _PACK2(pipe->max_packet_size, interval));
     500
     501#undef _PACK2
     502#undef _PACK3
    479503}
    480504
  • uspace/lib/usb/src/pipesio.c

    ref354b6 re50cd7f  
    4949#include <assert.h>
    5050#include <usbhc_iface.h>
     51#include <usb/request.h>
     52#include "pipepriv.h"
    5153
    5254/** Request an in transfer, no checking of input parameters.
     
    7880        }
    7981
     82        /* Ensure serialization over the phone. */
     83        pipe_start_transaction(pipe);
     84
    8085        /*
    8186         * Make call identifying target USB device and type of transfer.
    8287         */
    83         aid_t opening_request = async_send_4(pipe->hc_phone,
     88        aid_t opening_request = async_send_3(pipe->hc_phone,
    8489            DEV_IFACE_ID(USBHC_DEV_IFACE), ipc_method,
    8590            pipe->wire->address, pipe->endpoint_no,
    86             pipe->max_packet_size,
    8791            NULL);
    8892        if (opening_request == 0) {
     93                pipe_end_transaction(pipe);
    8994                return ENOMEM;
    9095        }
     
    96101        aid_t data_request = async_data_read(pipe->hc_phone, buffer, size,
    97102            &data_request_call);
     103
     104        /*
     105         * Since now on, someone else might access the backing phone
     106         * without breaking the transfer IPC protocol.
     107         */
     108        pipe_end_transaction(pipe);
    98109
    99110        if (data_request == 0) {
     
    146157
    147158        if (buffer == NULL) {
    148                         return EINVAL;
     159                return EINVAL;
    149160        }
    150161
    151162        if (size == 0) {
    152163                return EINVAL;
    153         }
    154 
    155         if (!usb_pipe_is_session_started(pipe)) {
    156                 return EBADF;
    157164        }
    158165
     
    165172        }
    166173
     174        int rc;
     175        rc = pipe_add_ref(pipe);
     176        if (rc != EOK) {
     177                return rc;
     178        }
     179
     180
    167181        size_t act_size = 0;
    168         int rc;
    169182
    170183        rc = usb_pipe_read_no_checks(pipe, buffer, size, &act_size);
     184
     185        pipe_drop_ref(pipe);
     186
    171187        if (rc != EOK) {
    172188                return rc;
     
    210226        }
    211227
     228        /* Ensure serialization over the phone. */
     229        pipe_start_transaction(pipe);
     230
    212231        /*
    213232         * Make call identifying target USB device and type of transfer.
    214233         */
    215         aid_t opening_request = async_send_4(pipe->hc_phone,
     234        aid_t opening_request = async_send_3(pipe->hc_phone,
    216235            DEV_IFACE_ID(USBHC_DEV_IFACE), ipc_method,
    217236            pipe->wire->address, pipe->endpoint_no,
    218             pipe->max_packet_size,
    219237            NULL);
    220238        if (opening_request == 0) {
     239                pipe_end_transaction(pipe);
    221240                return ENOMEM;
    222241        }
     
    226245         */
    227246        int rc = async_data_write_start(pipe->hc_phone, buffer, size);
     247
     248        /*
     249         * Since now on, someone else might access the backing phone
     250         * without breaking the transfer IPC protocol.
     251         */
     252        pipe_end_transaction(pipe);
     253
    228254        if (rc != EOK) {
    229255                async_wait_for(opening_request, NULL);
     
    260286        }
    261287
    262         if (!usb_pipe_is_session_started(pipe)) {
    263                 return EBADF;
    264         }
    265 
    266288        if (pipe->direction != USB_DIRECTION_OUT) {
    267289                return EBADF;
     
    272294        }
    273295
    274         int rc = usb_pipe_write_no_check(pipe, buffer, size);
     296        int rc;
     297
     298        rc = pipe_add_ref(pipe);
     299        if (rc != EOK) {
     300                return rc;
     301        }
     302
     303        rc = usb_pipe_write_no_check(pipe, buffer, size);
     304
     305        pipe_drop_ref(pipe);
    275306
    276307        return rc;
     308}
     309
     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;
    277327}
    278328
     
    293343    void *data_buffer, size_t data_buffer_size, size_t *data_transfered_size)
    294344{
     345        /* Ensure serialization over the phone. */
     346        pipe_start_transaction(pipe);
     347
    295348        /*
    296349         * Make call identifying target USB device and control transfer type.
    297350         */
    298         aid_t opening_request = async_send_4(pipe->hc_phone,
     351        aid_t opening_request = async_send_3(pipe->hc_phone,
    299352            DEV_IFACE_ID(USBHC_DEV_IFACE), IPC_M_USBHC_CONTROL_READ,
    300353            pipe->wire->address, pipe->endpoint_no,
    301             pipe->max_packet_size,
    302354            NULL);
    303355        if (opening_request == 0) {
     
    311363            setup_buffer, setup_buffer_size);
    312364        if (rc != EOK) {
     365                pipe_end_transaction(pipe);
    313366                async_wait_for(opening_request, NULL);
    314367                return rc;
     
    322375            data_buffer, data_buffer_size,
    323376            &data_request_call);
     377
     378        /*
     379         * Since now on, someone else might access the backing phone
     380         * without breaking the transfer IPC protocol.
     381         */
     382        pipe_end_transaction(pipe);
     383
     384
    324385        if (data_request == 0) {
    325386                async_wait_for(opening_request, NULL);
     
    379440        }
    380441
    381         if (!usb_pipe_is_session_started(pipe)) {
    382                 return EBADF;
    383         }
    384 
    385442        if ((pipe->direction != USB_DIRECTION_BOTH)
    386443            || (pipe->transfer_type != USB_TRANSFER_CONTROL)) {
     
    388445        }
    389446
     447        int rc;
     448
     449        rc = pipe_add_ref(pipe);
     450        if (rc != EOK) {
     451                return rc;
     452        }
     453
    390454        size_t act_size = 0;
    391         int rc = usb_pipe_control_read_no_check(pipe,
     455        rc = usb_pipe_control_read_no_check(pipe,
    392456            setup_buffer, setup_buffer_size,
    393457            data_buffer, data_buffer_size, &act_size);
     458
     459        if (rc == ESTALL) {
     460                clear_self_endpoint_halt(pipe);
     461        }
     462
     463        pipe_drop_ref(pipe);
    394464
    395465        if (rc != EOK) {
     
    418488    void *data_buffer, size_t data_buffer_size)
    419489{
     490        /* Ensure serialization over the phone. */
     491        pipe_start_transaction(pipe);
     492
    420493        /*
    421494         * Make call identifying target USB device and control transfer type.
    422495         */
    423         aid_t opening_request = async_send_5(pipe->hc_phone,
     496        aid_t opening_request = async_send_4(pipe->hc_phone,
    424497            DEV_IFACE_ID(USBHC_DEV_IFACE), IPC_M_USBHC_CONTROL_WRITE,
    425498            pipe->wire->address, pipe->endpoint_no,
    426499            data_buffer_size,
    427             pipe->max_packet_size,
    428500            NULL);
    429501        if (opening_request == 0) {
     502                pipe_end_transaction(pipe);
    430503                return ENOMEM;
    431504        }
     
    437510            setup_buffer, setup_buffer_size);
    438511        if (rc != EOK) {
     512                pipe_end_transaction(pipe);
    439513                async_wait_for(opening_request, NULL);
    440514                return rc;
     
    447521                rc = async_data_write_start(pipe->hc_phone,
    448522                    data_buffer, data_buffer_size);
     523
     524                /* All data sent, pipe can be released. */
     525                pipe_end_transaction(pipe);
     526
    449527                if (rc != EOK) {
    450528                        async_wait_for(opening_request, NULL);
    451529                        return rc;
    452530                }
     531        } else {
     532                /* No data to send, we can release the pipe for others. */
     533                pipe_end_transaction(pipe);
    453534        }
    454535
     
    491572        }
    492573
    493         if (!usb_pipe_is_session_started(pipe)) {
    494                 return EBADF;
    495         }
    496 
    497574        if ((pipe->direction != USB_DIRECTION_BOTH)
    498575            || (pipe->transfer_type != USB_TRANSFER_CONTROL)) {
     
    500577        }
    501578
    502         int rc = usb_pipe_control_write_no_check(pipe,
     579        int rc;
     580
     581        rc = pipe_add_ref(pipe);
     582        if (rc != EOK) {
     583                return rc;
     584        }
     585
     586        rc = usb_pipe_control_write_no_check(pipe,
    503587            setup_buffer, setup_buffer_size, data_buffer, data_buffer_size);
     588
     589        if (rc == ESTALL) {
     590                clear_self_endpoint_halt(pipe);
     591        }
     592
     593        pipe_drop_ref(pipe);
    504594
    505595        return rc;
  • uspace/lib/usb/src/recognise.c

    ref354b6 re50cd7f  
    404404        child->driver_data = dev_data;
    405405
    406         rc = usb_pipe_start_session(&ctrl_pipe);
    407         if (rc != EOK) {
    408                 goto failure;
    409         }
    410 
    411406        rc = usb_device_create_match_ids(&ctrl_pipe, &child->match_ids);
    412         if (rc != EOK) {
    413                 goto failure;
    414         }
    415 
    416         rc = usb_pipe_end_session(&ctrl_pipe);
    417407        if (rc != EOK) {
    418408                goto failure;
  • uspace/lib/usb/src/request.c

    ref354b6 re50cd7f  
    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.