Changeset fd07e526 in mainline for uspace/lib/usbhost/src


Ignore:
Timestamp:
2011-09-16T14:50:20Z (14 years ago)
Author:
Jan Vesely <jano.vesely@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
432a269, d1e18573
Parents:
47fecbb (diff), 82a31261 (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:

Merge USB changes from bzr://krabicka.net/orome/helenos/usb/

  • Move common HC code from uhci/ohci drivers to libusbhost
  • Rewrite USB HC interface to have common read/write functions for all transfer types.
  • Restructure hc drivers to avoid some hooks and void* casts
  • Cleanup the code and remove unnecessary mallocs.
Location:
uspace/lib/usbhost/src
Files:
1 added
2 edited
2 moved

Legend:

Unmodified
Added
Removed
  • uspace/lib/usbhost/src/endpoint.c

    r47fecbb rfd07e526  
    5353                instance->toggle = 0;
    5454                instance->active = false;
     55                instance->destroy_hook = NULL;
     56                instance->hc_data.data = NULL;
     57                instance->hc_data.toggle_get = NULL;
     58                instance->hc_data.toggle_set = NULL;
    5559                fibril_mutex_initialize(&instance->guard);
    5660                fibril_condvar_initialize(&instance->avail);
     
    6468        assert(instance);
    6569        assert(!instance->active);
     70        if (instance->hc_data.data) {
     71                assert(instance->destroy_hook);
     72                instance->destroy_hook(instance);
     73        }
    6674        free(instance);
    6775}
    6876/*----------------------------------------------------------------------------*/
    6977void endpoint_set_hc_data(endpoint_t *instance,
    70     void *data, int (*toggle_get)(void *), void (*toggle_set)(void *, int))
     78    void *data, void (*destroy_hook)(endpoint_t *),
     79    int (*toggle_get)(void *), void (*toggle_set)(void *, int))
    7180{
    7281        assert(instance);
     82        instance->destroy_hook = destroy_hook;
    7383        instance->hc_data.data = data;
    7484        instance->hc_data.toggle_get = toggle_get;
     
    7989{
    8090        assert(instance);
     91        instance->destroy_hook = NULL;
    8192        instance->hc_data.data = NULL;
    8293        instance->hc_data.toggle_get = NULL;
  • uspace/lib/usbhost/src/usb_device_manager.c

    r47fecbb rfd07e526  
    3131 */
    3232/** @file
    33  * Device keeper structure and functions (implementation).
     33 * Device manager structure and functions (implementation).
    3434 */
    3535#include <assert.h>
    3636#include <errno.h>
    3737#include <usb/debug.h>
    38 #include <usb/host/device_keeper.h>
    39 
    40 /*----------------------------------------------------------------------------*/
    41 /** Initialize device keeper structure.
     38#include <usb/host/usb_device_manager.h>
     39
     40/*----------------------------------------------------------------------------*/
     41/** Initialize device manager structure.
    4242 *
    4343 * @param[in] instance Memory place to initialize.
     
    4545 * Set all values to false/0.
    4646 */
    47 void usb_device_keeper_init(usb_device_keeper_t *instance)
     47void usb_device_manager_init(usb_device_manager_t *instance)
    4848{
    4949        assert(instance);
     
    6363/** Get a free USB address
    6464 *
    65  * @param[in] instance Device keeper structure to use.
     65 * @param[in] instance Device manager structure to use.
    6666 * @param[in] speed Speed of the device requiring address.
    6767 * @return Free address, or error code.
    6868 */
    69 usb_address_t device_keeper_get_free_address(
    70     usb_device_keeper_t *instance, usb_speed_t speed)
     69usb_address_t usb_device_manager_get_free_address(
     70    usb_device_manager_t *instance, usb_speed_t speed)
    7171{
    7272        assert(instance);
     
    9797/** Bind USB address to devman handle.
    9898 *
    99  * @param[in] instance Device keeper structure to use.
     99 * @param[in] instance Device manager structure to use.
    100100 * @param[in] address Device address
    101101 * @param[in] handle Devman handle of the device.
    102102 */
    103 void usb_device_keeper_bind(usb_device_keeper_t *instance,
     103void usb_device_manager_bind(usb_device_manager_t *instance,
    104104    usb_address_t address, devman_handle_t handle)
    105105{
     
    117117/** Release used USB address.
    118118 *
    119  * @param[in] instance Device keeper structure to use.
     119 * @param[in] instance Device manager structure to use.
    120120 * @param[in] address Device address
    121121 */
    122 void usb_device_keeper_release(
    123     usb_device_keeper_t *instance, usb_address_t address)
     122void usb_device_manager_release(
     123    usb_device_manager_t *instance, usb_address_t address)
    124124{
    125125        assert(instance);
     
    136136/** Find USB address associated with the device
    137137 *
    138  * @param[in] instance Device keeper structure to use.
     138 * @param[in] instance Device manager structure to use.
    139139 * @param[in] handle Devman handle of the device seeking its address.
    140140 * @return USB Address, or error code.
    141141 */
    142 usb_address_t usb_device_keeper_find(
    143     usb_device_keeper_t *instance, devman_handle_t handle)
     142usb_address_t usb_device_manager_find(
     143    usb_device_manager_t *instance, devman_handle_t handle)
    144144{
    145145        assert(instance);
     
    161161 * Intentionally refuse to find handle of default address.
    162162 *
    163  * @param[in] instance Device keeper structure to use.
     163 * @param[in] instance Device manager structure to use.
    164164 * @param[in] address Address the caller wants to find.
    165165 * @param[out] handle Where to store found handle.
    166166 * @return Whether such address is currently occupied.
    167167 */
    168 bool usb_device_keeper_find_by_address(usb_device_keeper_t *instance,
     168bool usb_device_manager_find_by_address(usb_device_manager_t *instance,
    169169    usb_address_t address, devman_handle_t *handle)
    170170{
     
    191191/** Get speed associated with the address
    192192 *
    193  * @param[in] instance Device keeper structure to use.
     193 * @param[in] instance Device manager structure to use.
    194194 * @param[in] address Address of the device.
    195195 * @return USB speed.
    196196 */
    197 usb_speed_t usb_device_keeper_get_speed(
    198     usb_device_keeper_t *instance, usb_address_t address)
     197usb_speed_t usb_device_manager_get_speed(
     198    usb_device_manager_t *instance, usb_address_t address)
    199199{
    200200        assert(instance);
  • uspace/lib/usbhost/src/usb_endpoint_manager.c

    r47fecbb rfd07e526  
    4545static hash_index_t node_hash(unsigned long key[])
    4646{
    47         hash_index_t hash = 0;
    48         unsigned i = 0;
    49         for (;i < MAX_KEYS; ++i) {
    50                 hash ^= key[i];
    51         }
    52         hash %= BUCKET_COUNT;
    53         return hash;
     47        /* USB endpoints use 4 bits, thus ((key[0] << 4) | key[1])
     48         * produces unique value for every address.endpoint pair */
     49        return ((key[0] << 4) | key[1]) % BUCKET_COUNT;
    5450}
    5551/*----------------------------------------------------------------------------*/
     
    6359        switch (keys) {
    6460        case 3:
    65                 match = match && (key[2] == node->ep->direction);
     61                match = match &&
     62                    ((key[2] == node->ep->direction)
     63                    || (node->ep->direction == USB_DIRECTION_BOTH));
    6664        case 2:
    6765                match = match && (key[1] == (unsigned long)node->ep->endpoint);
     
    140138/*----------------------------------------------------------------------------*/
    141139int usb_endpoint_manager_init(usb_endpoint_manager_t *instance,
    142     size_t available_bandwidth)
     140    size_t available_bandwidth,
     141    size_t (*bw_count)(usb_speed_t, usb_transfer_type_t, size_t, size_t))
    143142{
    144143        assert(instance);
    145144        fibril_mutex_initialize(&instance->guard);
    146         fibril_condvar_initialize(&instance->change);
    147145        instance->free_bw = available_bandwidth;
    148         bool ht =
     146        instance->bw_count = bw_count;
     147        const bool ht =
    149148            hash_table_create(&instance->ep_table, BUCKET_COUNT, MAX_KEYS, &op);
    150149        return ht ? EOK : ENOMEM;
     
    159158    endpoint_t *ep, size_t data_size)
    160159{
     160        assert(instance);
     161        assert(instance->bw_count);
    161162        assert(ep);
    162         size_t bw = bandwidth_count_usb11(ep->speed, ep->transfer_type,
     163        const size_t bw = instance->bw_count(ep->speed, ep->transfer_type,
    163164            data_size, ep->max_packet_size);
    164         assert(instance);
     165
     166        fibril_mutex_lock(&instance->guard);
     167
     168        if (bw > instance->free_bw) {
     169                fibril_mutex_unlock(&instance->guard);
     170                return ENOSPC;
     171        }
    165172
    166173        unsigned long key[MAX_KEYS] =
    167174            {ep->address, ep->endpoint, ep->direction};
    168         fibril_mutex_lock(&instance->guard);
    169 
    170         link_t *item =
     175
     176        const link_t *item =
    171177            hash_table_find(&instance->ep_table, key);
    172178        if (item != NULL) {
    173179                fibril_mutex_unlock(&instance->guard);
    174180                return EEXISTS;
    175         }
    176 
    177         if (bw > instance->free_bw) {
    178                 fibril_mutex_unlock(&instance->guard);
    179                 return ENOSPC;
    180181        }
    181182
     
    193194        instance->free_bw -= bw;
    194195        fibril_mutex_unlock(&instance->guard);
    195         fibril_condvar_broadcast(&instance->change);
    196196        return EOK;
    197197}
     
    211211
    212212        node_t *node = hash_table_get_instance(item, node_t, link);
    213         if (node->ep->active)
     213        if (node->ep->active) {
     214                fibril_mutex_unlock(&instance->guard);
    214215                return EBUSY;
     216        }
    215217
    216218        instance->free_bw += node->bw;
     
    218220
    219221        fibril_mutex_unlock(&instance->guard);
    220         fibril_condvar_broadcast(&instance->change);
    221222        return EOK;
    222223}
     
    230231
    231232        fibril_mutex_lock(&instance->guard);
    232         link_t *item = hash_table_find(&instance->ep_table, key);
     233        const link_t *item = hash_table_find(&instance->ep_table, key);
    233234        if (item == NULL) {
    234235                fibril_mutex_unlock(&instance->guard);
    235236                return NULL;
    236237        }
    237         node_t *node = hash_table_get_instance(item, node_t, link);
     238        const node_t *node = hash_table_get_instance(item, node_t, link);
    238239        if (bw)
    239240                *bw = node->bw;
     
    255256{
    256257        assert(instance);
    257         if (target.endpoint > 15 || target.endpoint < 0
    258             || target.address >= USB11_ADDRESS_MAX || target.address < 0) {
     258        if (!usb_target_is_valid(target)) {
    259259                usb_log_error("Invalid data when checking for toggle reset.\n");
    260260                return;
    261261        }
    262262
     263        assert(data);
    263264        switch (data[1])
    264265        {
    265         case 0x01: /*clear feature*/
    266                 /* recipient is endpoint, value is zero (ENDPOINT_STALL) */
     266        case 0x01: /* Clear Feature -- resets only cleared ep */
     267                /* Recipient is endpoint, value is zero (ENDPOINT_STALL) */
    267268                if (((data[0] & 0xf) == 1) && ((data[2] | data[3]) == 0)) {
    268269                        /* endpoint number is < 16, thus first byte is enough */
     
    276277        break;
    277278
    278         case 0x9: /* set configuration */
    279         case 0x11: /* set interface */
    280                 /* target must be device */
     279        case 0x9: /* Set Configuration */
     280        case 0x11: /* Set Interface */
     281                /* Recipient must be device */
    281282                if ((data[0] & 0xf) == 0) {
    282283                        usb_target_t reset_target =
  • uspace/lib/usbhost/src/usb_transfer_batch.c

    r47fecbb rfd07e526  
    3737#include <usb/usb.h>
    3838#include <usb/debug.h>
    39 #include <usb/host/batch.h>
     39#include <usb/host/usb_transfer_batch.h>
     40#include <usb/host/hcd.h>
    4041
    41 void usb_transfer_batch_call_in(usb_transfer_batch_t *instance);
    42 void usb_transfer_batch_call_out(usb_transfer_batch_t *instance);
    43 
    44 void usb_transfer_batch_init(
    45     usb_transfer_batch_t *instance,
     42usb_transfer_batch_t * usb_transfer_batch_get(
    4643    endpoint_t *ep,
    4744    char *buffer,
    48     char *data_buffer,
    4945    size_t buffer_size,
    50     char *setup_buffer,
    51     size_t setup_size,
     46    uint64_t setup_buffer,
    5247    usbhc_iface_transfer_in_callback_t func_in,
    5348    usbhc_iface_transfer_out_callback_t func_out,
     
    5550    ddf_fun_t *fun,
    5651    void *private_data,
    57     void (*private_data_dtor)(void *p_data)
     52    void (*private_data_dtor)(void *)
    5853    )
    5954{
    60         assert(instance);
    61         link_initialize(&instance->link);
    62         instance->ep = ep;
    63         instance->callback_in = func_in;
    64         instance->callback_out = func_out;
    65         instance->arg = arg;
    66         instance->buffer = buffer;
    67         instance->data_buffer = data_buffer;
    68         instance->buffer_size = buffer_size;
    69         instance->setup_buffer = setup_buffer;
    70         instance->setup_size = setup_size;
    71         instance->fun = fun;
    72         instance->private_data = private_data;
    73         instance->private_data_dtor = private_data_dtor;
    74         instance->transfered_size = 0;
    75         instance->next_step = NULL;
    76         instance->error = EOK;
    77         endpoint_use(instance->ep);
     55        usb_transfer_batch_t *instance = malloc(sizeof(usb_transfer_batch_t));
     56        if (instance) {
     57                instance->ep = ep;
     58                instance->callback_in = func_in;
     59                instance->callback_out = func_out;
     60                instance->arg = arg;
     61                instance->buffer = buffer;
     62                instance->buffer_size = buffer_size;
     63                instance->setup_size = 0;
     64                instance->fun = fun;
     65                instance->private_data = private_data;
     66                instance->private_data_dtor = private_data_dtor;
     67                instance->transfered_size = 0;
     68                instance->error = EOK;
     69                if (ep && ep->transfer_type == USB_TRANSFER_CONTROL) {
     70                        memcpy(instance->setup_buffer, &setup_buffer,
     71                            USB_SETUP_PACKET_SIZE);
     72                        instance->setup_size = USB_SETUP_PACKET_SIZE;
     73                }
     74                if (instance->ep)
     75                        endpoint_use(instance->ep);
     76        }
     77        return instance;
    7878}
    7979/*----------------------------------------------------------------------------*/
    80 /** Helper function, calls callback and correctly destroys batch structure.
     80/** Mark batch as finished and run callback.
    8181 *
    8282 * @param[in] instance Batch structure to use.
     83 * @param[in] data Data to copy to the output buffer.
     84 * @param[in] size Size of @p data.
    8385 */
    84 void 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  */
    95 void 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);
    100 }
    101 /*----------------------------------------------------------------------------*/
    102 /** Mark batch as finished and continue with next step.
    103  *
    104  * @param[in] instance Batch structure to use.
    105  *
    106  */
    107 void usb_transfer_batch_finish(usb_transfer_batch_t *instance)
     86void usb_transfer_batch_finish(
     87    usb_transfer_batch_t *instance, const void *data, size_t size)
    10888{
    10989        assert(instance);
    11090        assert(instance->ep);
    111         assert(instance->next_step);
    112         endpoint_release(instance->ep);
    113         instance->next_step(instance);
     91        /* we care about the data and there are some to copy */
     92        if (instance->ep->direction != USB_DIRECTION_OUT
     93            && data) {
     94                const size_t min_size =
     95                    size < instance->buffer_size ? size : instance->buffer_size;
     96                memcpy(instance->buffer, data, min_size);
     97        }
     98        if (instance->callback_out)
     99                usb_transfer_batch_call_out(instance);
     100        if (instance->callback_in)
     101                usb_transfer_batch_call_in(instance);
     102
    114103}
    115104/*----------------------------------------------------------------------------*/
     
    124113        assert(instance);
    125114        assert(instance->callback_in);
    126         assert(instance->ep);
    127 
    128         /* We are data in, we need data */
    129         memcpy(instance->buffer, instance->data_buffer, instance->buffer_size);
    130115
    131116        usb_log_debug2("Batch %p " USB_TRANSFER_BATCH_FMT " completed (%zuB): %s.\n",
     
    150135            str_error(instance->error));
    151136
     137        if (instance->ep->transfer_type == USB_TRANSFER_CONTROL
     138            && instance->error == EOK) {
     139                const usb_target_t target =
     140                    {{ instance->ep->address, instance->ep->endpoint }};
     141                reset_ep_if_need(
     142                    fun_to_hcd(instance->fun), target, instance->setup_buffer);
     143        }
     144
    152145        instance->callback_out(instance->fun,
    153146            instance->error, instance->arg);
     
    160153void usb_transfer_batch_dispose(usb_transfer_batch_t *instance)
    161154{
    162         assert(instance);
     155        if (!instance)
     156                return;
    163157        usb_log_debug2("Batch %p " USB_TRANSFER_BATCH_FMT " disposing.\n",
    164158            instance, USB_TRANSFER_BATCH_ARGS(*instance));
     159        if (instance->ep) {
     160                endpoint_release(instance->ep);
     161        }
    165162        if (instance->private_data) {
    166163                assert(instance->private_data_dtor);
Note: See TracChangeset for help on using the changeset viewer.