Changeset a4e18e1 in mainline for uspace/lib/usb/src


Ignore:
Timestamp:
2011-04-07T15:04:16Z (15 years ago)
Author:
Matus Dekanek <smekideki@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
36cd378
Parents:
9d06563 (diff), a82889e (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:

partial merge form usb/development

Location:
uspace/lib/usb/src
Files:
1 added
5 edited
1 moved

Legend:

Unmodified
Added
Removed
  • uspace/lib/usb/src/devdrv.c

    r9d06563 ra4e18e1  
    3636#include <usb/request.h>
    3737#include <usb/debug.h>
     38#include <usb/dp.h>
    3839#include <errno.h>
    3940#include <str_error.h>
     
    8687 * @return Number of pipes (excluding default control pipe).
    8788 */
    88 static size_t count_other_pipes(usb_driver_t *drv)
     89static size_t count_other_pipes(usb_endpoint_description_t **endpoints)
    8990{
    9091        size_t count = 0;
    91         if (drv->endpoints == NULL) {
     92        if (endpoints == NULL) {
    9293                return 0;
    9394        }
    9495
    95         while (drv->endpoints[count] != NULL) {
     96        while (endpoints[count] != NULL) {
    9697                count++;
    9798        }
     
    106107 * @return Error code.
    107108 */
    108 static int initialize_other_pipes(usb_driver_t *drv, usb_device_t *dev)
     109static int initialize_other_pipes(usb_endpoint_description_t **endpoints,
     110    usb_device_t *dev)
    109111{
    110112        int rc;
    111         dev->interface_no = usb_device_get_assigned_interface(dev->ddf_dev);
    112 
    113         size_t pipe_count = count_other_pipes(drv);
     113
     114        size_t pipe_count = count_other_pipes(endpoints);
     115        if (pipe_count == 0) {
     116                return EOK;
     117        }
     118
    114119        dev->pipes = malloc(sizeof(usb_endpoint_mapping_t) * pipe_count);
    115120        if (dev->pipes == NULL) {
     
    133138                }
    134139
    135                 dev->pipes[i].description = drv->endpoints[i];
     140                dev->pipes[i].description = endpoints[i];
    136141                dev->pipes[i].interface_no = dev->interface_no;
     142                dev->pipes[i].interface_setting = 0;
    137143        }
    138144
     
    178184        usb_hc_connection_close(&hc_conn);
    179185
     186        dev->pipes_count = pipe_count;
     187
    180188        return EOK;
    181189
     
    227235        }
    228236
     237        /* Get our interface. */
     238        dev->interface_no = usb_device_get_assigned_interface(dev->ddf_dev);
     239
    229240        /*
    230241         * For further actions, we need open session on default control pipe.
     
    257268
    258269        if (driver->endpoints != NULL) {
    259                 rc = initialize_other_pipes(driver, dev);
     270                rc = initialize_other_pipes(driver->endpoints, dev);
    260271        }
    261272
     
    271282
    272283        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 */
     293static 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 */
     330static 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;
     406
     407        return EOK;
    273408}
    274409
     
    301436        dev->descriptors.configuration = NULL;
    302437
     438        dev->pipes_count = 0;
     439        dev->pipes = NULL;
     440
    303441        rc = initialize_pipes(dev);
    304442        if (rc != EOK) {
     
    307445        }
    308446
     447        (void) initialize_alternate_interfaces(dev);
     448
    309449        return driver->ops->add_device(dev);
     450}
     451
     452/** Destroy existing pipes of a USB device.
     453 *
     454 * @param dev Device where to destroy the pipes.
     455 * @return Error code.
     456 */
     457static int destroy_current_pipes(usb_device_t *dev)
     458{
     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);
     491        dev->pipes = NULL;
     492        dev->pipes_count = 0;
     493
     494        return EOK;
     495}
     496
     497/** Change interface setting of a device.
     498 * This function selects new alternate setting of an interface by issuing
     499 * proper USB command to the device and also creates new USB pipes
     500 * under @c dev->pipes.
     501 *
     502 * @warning This function is intended for drivers working at interface level.
     503 * For drivers controlling the whole device, you need to change interface
     504 * manually using usb_request_set_interface() and creating new pipes
     505 * with usb_pipe_initialize_from_configuration().
     506 *
     507 * @param dev USB device.
     508 * @param alternate_setting Alternate setting to choose.
     509 * @param endpoints New endpoint descriptions.
     510 * @return Error code.
     511 */
     512int usb_device_select_interface(usb_device_t *dev, uint8_t alternate_setting,
     513    usb_endpoint_description_t **endpoints)
     514{
     515        if (dev->interface_no < 0) {
     516                return EINVAL;
     517        }
     518
     519        int rc;
     520
     521        /* TODO: more transactional behavior. */
     522
     523        /* Destroy existing pipes. */
     524        rc = destroy_current_pipes(dev);
     525        if (rc != EOK) {
     526                return rc;
     527        }
     528
     529        /* Change the interface itself. */
     530        rc = usb_request_set_interface(&dev->ctrl_pipe, dev->interface_no,
     531            alternate_setting);
     532        if (rc != EOK) {
     533                return rc;
     534        }
     535
     536        /* Create new pipes. */
     537        rc = initialize_other_pipes(endpoints, dev);
     538
     539        return rc;
    310540}
    311541
  • uspace/lib/usb/src/host/batch.c

    r9d06563 ra4e18e1  
    5454    void *arg,
    5555    ddf_fun_t *fun,
     56                endpoint_t *ep,
    5657    void *private_data
    5758    )
     
    7778        instance->next_step = NULL;
    7879        instance->error = EOK;
    79 
     80        instance->ep = ep;
    8081}
    8182/*----------------------------------------------------------------------------*/
  • uspace/lib/usb/src/host/device_keeper.c

    r9d06563 ra4e18e1  
    5656                instance->devices[i].control_used = 0;
    5757                instance->devices[i].handle = 0;
    58                 instance->devices[i].toggle_status[0] = 0;
    59                 instance->devices[i].toggle_status[1] = 0;
    60         }
     58                list_initialize(&instance->devices[i].endpoints);
     59        }
     60}
     61/*----------------------------------------------------------------------------*/
     62void 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);
    6170}
    6271/*----------------------------------------------------------------------------*/
     
    6675 * @param[in] speed Speed of the device requesting default address.
    6776 */
    68 void usb_device_keeper_reserve_default_address(usb_device_keeper_t *instance,
    69     usb_speed_t speed)
     77void usb_device_keeper_reserve_default_address(
     78    usb_device_keeper_t *instance, usb_speed_t speed)
    7079{
    7180        assert(instance);
     
    101110 * Really ugly one.
    102111 */
    103 void usb_device_keeper_reset_if_need(usb_device_keeper_t *instance,
    104     usb_target_t target, const uint8_t *data)
     112void usb_device_keeper_reset_if_need(
     113    usb_device_keeper_t *instance, usb_target_t target, const uint8_t *data)
    105114{
    106115        assert(instance);
     
    119128                /* recipient is endpoint, value is zero (ENDPOINT_STALL) */
    120129                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                        {
    121135                        /* endpoint number is < 16, thus first byte is enough */
    122                         instance->devices[target.address].toggle_status[0] &=
    123                             ~(1 << data[4]);
    124                         instance->devices[target.address].toggle_status[1] &=
    125                             ~(1 << data[4]);
     136                                endpoint_toggle_reset_filtered(
     137                                    current, data[4]);
     138                                current = current->next;
     139                        }
    126140                }
    127141        break;
     
    131145                /* target must be device */
    132146                if ((data[0] & 0xf) == 0) {
    133                         instance->devices[target.address].toggle_status[0] = 0;
    134                         instance->devices[target.address].toggle_status[1] = 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                        }
    135155                }
    136156        break;
    137157        }
    138158        fibril_mutex_unlock(&instance->guard);
    139 }
    140 /*----------------------------------------------------------------------------*/
    141 /** Get current value of endpoint toggle.
    142  *
    143  * @param[in] instance Device keeper structure to use.
    144  * @param[in] target Device and endpoint used.
    145  * @return Error code
    146  */
    147 int usb_device_keeper_get_toggle(usb_device_keeper_t *instance,
    148     usb_target_t target, usb_direction_t direction)
    149 {
    150         assert(instance);
    151         /* only control pipes are bi-directional and those do not need toggle */
    152         if (direction == USB_DIRECTION_BOTH)
    153                 return ENOENT;
    154         int ret;
    155         fibril_mutex_lock(&instance->guard);
    156         if (target.endpoint > 15 || target.endpoint < 0
    157             || target.address >= USB_ADDRESS_COUNT || target.address < 0
    158             || !instance->devices[target.address].occupied) {
    159                 usb_log_error("Invalid data when asking for toggle value.\n");
    160                 ret = EINVAL;
    161         } else {
    162                 ret = (instance->devices[target.address].toggle_status[direction]
    163                         >> target.endpoint) & 1;
    164         }
    165         fibril_mutex_unlock(&instance->guard);
    166         return ret;
    167 }
    168 /*----------------------------------------------------------------------------*/
    169 /** Set current value of endpoint toggle.
    170  *
    171  * @param[in] instance Device keeper structure to use.
    172  * @param[in] target Device and endpoint used.
    173  * @param[in] toggle Toggle value.
    174  * @return Error code.
    175  */
    176 int usb_device_keeper_set_toggle(usb_device_keeper_t *instance,
    177     usb_target_t target, usb_direction_t direction, bool toggle)
    178 {
    179         assert(instance);
    180         /* only control pipes are bi-directional and those do not need toggle */
    181         if (direction == USB_DIRECTION_BOTH)
    182                 return ENOENT;
    183         int ret;
    184         fibril_mutex_lock(&instance->guard);
    185         if (target.endpoint > 15 || target.endpoint < 0
    186             || target.address >= USB_ADDRESS_COUNT || target.address < 0
    187             || !instance->devices[target.address].occupied) {
    188                 usb_log_error("Invalid data when setting toggle value.\n");
    189                 ret = EINVAL;
    190         } else {
    191                 if (toggle) {
    192                         instance->devices[target.address].toggle_status[direction]
    193                             |= (1 << target.endpoint);
    194                 } else {
    195                         instance->devices[target.address].toggle_status[direction]
    196                             &= ~(1 << target.endpoint);
    197                 }
    198                 ret = EOK;
    199         }
    200         fibril_mutex_unlock(&instance->guard);
    201         return ret;
    202159}
    203160/*----------------------------------------------------------------------------*/
     
    208165 * @return Free address, or error code.
    209166 */
    210 usb_address_t device_keeper_get_free_address(usb_device_keeper_t *instance,
    211     usb_speed_t speed)
     167usb_address_t device_keeper_get_free_address(
     168    usb_device_keeper_t *instance, usb_speed_t speed)
    212169{
    213170        assert(instance);
     
    229186        instance->devices[new_address].occupied = true;
    230187        instance->devices[new_address].speed = speed;
    231         instance->devices[new_address].toggle_status[0] = 0;
    232         instance->devices[new_address].toggle_status[1] = 0;
    233188        instance->last_address = new_address;
    234189        fibril_mutex_unlock(&instance->guard);
     
    259214 * @param[in] address Device address
    260215 */
    261 void usb_device_keeper_release(usb_device_keeper_t *instance,
    262     usb_address_t address)
     216void usb_device_keeper_release(
     217    usb_device_keeper_t *instance, usb_address_t address)
    263218{
    264219        assert(instance);
     
    278233 * @return USB Address, or error code.
    279234 */
    280 usb_address_t usb_device_keeper_find(usb_device_keeper_t *instance,
    281     devman_handle_t handle)
     235usb_address_t usb_device_keeper_find(
     236    usb_device_keeper_t *instance, devman_handle_t handle)
    282237{
    283238        assert(instance);
     
    301256 * @return USB speed.
    302257 */
    303 usb_speed_t usb_device_keeper_get_speed(usb_device_keeper_t *instance,
    304     usb_address_t address)
     258usb_speed_t usb_device_keeper_get_speed(
     259    usb_device_keeper_t *instance, usb_address_t address)
    305260{
    306261        assert(instance);
     
    310265}
    311266/*----------------------------------------------------------------------------*/
    312 void usb_device_keeper_use_control(usb_device_keeper_t *instance,
    313     usb_target_t target)
     267void usb_device_keeper_use_control(
     268    usb_device_keeper_t *instance, usb_target_t target)
    314269{
    315270        assert(instance);
     
    323278}
    324279/*----------------------------------------------------------------------------*/
    325 void usb_device_keeper_release_control(usb_device_keeper_t *instance,
    326     usb_target_t target)
     280void usb_device_keeper_release_control(
     281    usb_device_keeper_t *instance, usb_target_t target)
    327282{
    328283        assert(instance);
  • uspace/lib/usb/src/host/usb_endpoint_manager.c

    r9d06563 ra4e18e1  
    11/*
    22 * Copyright (c) 2011 Jan Vesely
    3  * All rights reserved.
     3 * All rights eps.
    44 *
    55 * Redistribution and use in source and binary forms, with or without
     
    2727 */
    2828
     29#include <bool.h>
    2930#include <assert.h>
    3031#include <errno.h>
    31 #include <usb/host/bandwidth.h>
    32 
     32
     33#include <usb/host/usb_endpoint_manager.h>
     34
     35#define BUCKET_COUNT 7
     36
     37#define MAX_KEYS (3)
    3338typedef struct {
    34         usb_address_t address;
    35         usb_endpoint_t endpoint;
    36         usb_direction_t direction;
    37 } __attribute__((aligned (sizeof(unsigned long)))) transfer_t;
    38 /*----------------------------------------------------------------------------*/
    39 typedef struct {
    40         transfer_t transfer;
    4139        link_t link;
    42         bool used;
    43         size_t required;
    44 } transfer_status_t;
    45 /*----------------------------------------------------------------------------*/
    46 #define BUCKET_COUNT 7
    47 #define MAX_KEYS (sizeof(transfer_t) / sizeof(unsigned long))
    48 /*----------------------------------------------------------------------------*/
    49 static hash_index_t transfer_hash(unsigned long key[])
     40        size_t bw;
     41        endpoint_t *ep;
     42} node_t;
     43/*----------------------------------------------------------------------------*/
     44static hash_index_t node_hash(unsigned long key[])
    5045{
    5146        hash_index_t hash = 0;
     
    5853}
    5954/*----------------------------------------------------------------------------*/
    60 static int transfer_compare(
    61     unsigned long key[], hash_count_t keys, link_t *item)
     55static int node_compare(unsigned long key[], hash_count_t keys, link_t *item)
    6256{
    6357        assert(item);
    64         transfer_status_t *status =
    65             hash_table_get_instance(item, transfer_status_t, link);
    66         const size_t bytes =
    67             keys < MAX_KEYS ? keys * sizeof(unsigned long) : sizeof(transfer_t);
    68         return bcmp(key, &status->transfer, bytes);
    69 }
    70 /*----------------------------------------------------------------------------*/
    71 static void transfer_remove(link_t *item)
     58        node_t *node = hash_table_get_instance(item, node_t, link);
     59        assert(node);
     60        assert(node->ep);
     61        bool match = true;
     62        switch (keys) {
     63        case 3:
     64                match = match && (key[2] == node->ep->direction);
     65        case 2:
     66                match = match && (key[1] == (unsigned long)node->ep->endpoint);
     67        case 1:
     68                match = match && (key[0] == (unsigned long)node->ep->address);
     69                break;
     70        default:
     71                match = false;
     72        }
     73        return match;
     74}
     75/*----------------------------------------------------------------------------*/
     76static void node_remove(link_t *item)
    7277{
    7378        assert(item);
    74         transfer_status_t *status =
    75             hash_table_get_instance(item, transfer_status_t, link);
    76         assert(status);
    77         free(status);
    78 }
    79 /*----------------------------------------------------------------------------*/
    80 hash_table_operations_t op = {
    81         .hash = transfer_hash,
    82         .compare = transfer_compare,
    83         .remove_callback = transfer_remove,
     79        node_t *node = hash_table_get_instance(item, node_t, link);
     80        endpoint_destroy(node->ep);
     81        free(node);
     82}
     83/*----------------------------------------------------------------------------*/
     84static hash_table_operations_t op = {
     85        .hash = node_hash,
     86        .compare = node_compare,
     87        .remove_callback = node_remove,
    8488};
    8589/*----------------------------------------------------------------------------*/
     
    8791    size_t size, size_t max_packet_size)
    8892{
     93        /* We care about bandwidth only for interrupt and isochronous. */
     94        if ((type != USB_TRANSFER_INTERRUPT)
     95            && (type != USB_TRANSFER_ISOCHRONOUS)) {
     96                return 0;
     97        }
     98
    8999        const unsigned packet_count =
    90100            (size + max_packet_size - 1) / max_packet_size;
     
    120130}
    121131/*----------------------------------------------------------------------------*/
    122 int bandwidth_init(bandwidth_t *instance, size_t bandwidth,
    123     size_t (*usage_fnc)(usb_speed_t, usb_transfer_type_t, size_t, size_t))
     132int usb_endpoint_manager_init(usb_endpoint_manager_t *instance,
     133    size_t available_bandwidth)
    124134{
    125135        assert(instance);
    126136        fibril_mutex_initialize(&instance->guard);
    127         instance->free = bandwidth;
    128         instance->usage_fnc = usage_fnc;
     137        fibril_condvar_initialize(&instance->change);
     138        instance->free_bw = available_bandwidth;
    129139        bool ht =
    130             hash_table_create(&instance->reserved, BUCKET_COUNT, MAX_KEYS, &op);
     140            hash_table_create(&instance->ep_table, BUCKET_COUNT, MAX_KEYS, &op);
    131141        return ht ? EOK : ENOMEM;
    132142}
    133143/*----------------------------------------------------------------------------*/
    134 void bandwidth_destroy(bandwidth_t *instance)
    135 {
    136         hash_table_destroy(&instance->reserved);
    137 }
    138 /*----------------------------------------------------------------------------*/
    139 int bandwidth_reserve(bandwidth_t *instance, usb_address_t address,
    140     usb_endpoint_t endpoint, usb_direction_t direction, usb_speed_t speed,
    141     usb_transfer_type_t transfer_type, size_t max_packet_size, size_t size,
    142     unsigned interval)
    143 {
    144         if (transfer_type != USB_TRANSFER_ISOCHRONOUS &&
    145             transfer_type != USB_TRANSFER_INTERRUPT) {
    146                 return ENOTSUP;
    147         }
    148 
    149         assert(instance);
    150         assert(instance->usage_fnc);
    151 
    152         transfer_t trans = {
    153                 .address = address,
    154                 .endpoint = endpoint,
    155                 .direction = direction,
    156         };
     144void usb_endpoint_manager_destroy(usb_endpoint_manager_t *instance)
     145{
     146        hash_table_destroy(&instance->ep_table);
     147}
     148/*----------------------------------------------------------------------------*/
     149int usb_endpoint_manager_register_ep(usb_endpoint_manager_t *instance,
     150    endpoint_t *ep, size_t data_size)
     151{
     152        assert(ep);
     153        size_t bw = bandwidth_count_usb11(ep->speed, ep->transfer_type,
     154            data_size, ep->max_packet_size);
     155        assert(instance);
     156
     157        unsigned long key[MAX_KEYS] =
     158            {ep->address, ep->endpoint, ep->direction};
    157159        fibril_mutex_lock(&instance->guard);
    158         const size_t required =
    159             instance->usage_fnc(speed, transfer_type, size, max_packet_size);
    160 
    161         if (required > instance->free) {
     160
     161        link_t *item =
     162            hash_table_find(&instance->ep_table, key);
     163        if (item != NULL) {
     164                fibril_mutex_unlock(&instance->guard);
     165                return EEXISTS;
     166        }
     167
     168        if (bw > instance->free_bw) {
    162169                fibril_mutex_unlock(&instance->guard);
    163170                return ENOSPC;
    164171        }
    165172
    166         link_t *item =
    167             hash_table_find(&instance->reserved, (unsigned long*)&trans);
    168         if (item != NULL) {
    169                 fibril_mutex_unlock(&instance->guard);
    170                 return EEXISTS;
    171         }
    172 
    173         transfer_status_t *status = malloc(sizeof(transfer_status_t));
    174         if (status == NULL) {
     173        node_t *node = malloc(sizeof(node_t));
     174        if (node == NULL) {
    175175                fibril_mutex_unlock(&instance->guard);
    176176                return ENOMEM;
    177177        }
    178178
    179         status->transfer = trans;
    180         status->required = required;
    181         status->used = false;
    182         link_initialize(&status->link);
    183 
    184         hash_table_insert(&instance->reserved,
    185             (unsigned long*)&status->transfer, &status->link);
    186         instance->free -= required;
     179        node->bw = bw;
     180        node->ep = ep;
     181        link_initialize(&node->link);
     182
     183        hash_table_insert(&instance->ep_table, key, &node->link);
     184        instance->free_bw -= bw;
    187185        fibril_mutex_unlock(&instance->guard);
     186        fibril_condvar_broadcast(&instance->change);
    188187        return EOK;
    189         /* TODO: compute bandwidth used */
    190 }
    191 /*----------------------------------------------------------------------------*/
    192 int bandwidth_release(bandwidth_t *instance, usb_address_t address,
    193     usb_endpoint_t endpoint, usb_direction_t direction)
    194 {
    195         assert(instance);
    196         transfer_t trans = {
    197                 .address = address,
    198                 .endpoint = endpoint,
    199                 .direction = direction,
    200         };
     188}
     189/*----------------------------------------------------------------------------*/
     190int usb_endpoint_manager_unregister_ep(usb_endpoint_manager_t *instance,
     191    usb_address_t address, usb_endpoint_t endpoint, usb_direction_t direction)
     192{
     193        assert(instance);
     194        unsigned long key[MAX_KEYS] = {address, endpoint, direction};
     195
    201196        fibril_mutex_lock(&instance->guard);
    202         link_t *item =
    203             hash_table_find(&instance->reserved, (unsigned long*)&trans);
     197        link_t *item = hash_table_find(&instance->ep_table, key);
    204198        if (item == NULL) {
    205199                fibril_mutex_unlock(&instance->guard);
     
    207201        }
    208202
    209         transfer_status_t *status =
    210             hash_table_get_instance(item, transfer_status_t, link);
    211 
    212         instance->free += status->required;
    213 
    214         hash_table_remove(&instance->reserved,
    215             (unsigned long*)&trans, MAX_KEYS);
     203        node_t *node = hash_table_get_instance(item, node_t, link);
     204        instance->free_bw += node->bw;
     205        hash_table_remove(&instance->ep_table, key, MAX_KEYS);
    216206
    217207        fibril_mutex_unlock(&instance->guard);
     208        fibril_condvar_broadcast(&instance->change);
    218209        return EOK;
    219         /* TODO: compute bandwidth freed */
    220 }
    221 /*----------------------------------------------------------------------------*/
    222 int bandwidth_use(bandwidth_t *instance, usb_address_t address,
    223     usb_endpoint_t endpoint, usb_direction_t direction)
    224 {
    225         assert(instance);
    226         transfer_t trans = {
    227                 .address = address,
    228                 .endpoint = endpoint,
    229                 .direction = direction,
    230         };
     210}
     211/*----------------------------------------------------------------------------*/
     212endpoint_t * usb_endpoint_manager_get_ep(usb_endpoint_manager_t *instance,
     213    usb_address_t address, usb_endpoint_t endpoint, usb_direction_t direction,
     214    size_t *bw)
     215{
     216        assert(instance);
     217        unsigned long key[MAX_KEYS] = {address, endpoint, direction};
     218
    231219        fibril_mutex_lock(&instance->guard);
    232         link_t *item =
    233             hash_table_find(&instance->reserved, (unsigned long*)&trans);
    234         int ret = EOK;
    235         if (item != NULL) {
    236                 transfer_status_t *status =
    237                     hash_table_get_instance(item, transfer_status_t, link);
    238                 assert(status);
    239                 if (status->used) {
    240                         ret = EINPROGRESS;
    241                 }
    242                 status->used = true;
    243         } else {
    244                 ret = EINVAL;
    245         }
     220        link_t *item = hash_table_find(&instance->ep_table, key);
     221        if (item == NULL) {
     222                fibril_mutex_unlock(&instance->guard);
     223                return NULL;
     224        }
     225        node_t *node = hash_table_get_instance(item, node_t, link);
     226        if (bw)
     227                *bw = node->bw;
     228
    246229        fibril_mutex_unlock(&instance->guard);
    247         return ret;
    248 }
    249 /*----------------------------------------------------------------------------*/
    250 int bandwidth_free(bandwidth_t *instance, usb_address_t address,
    251     usb_endpoint_t endpoint, usb_direction_t direction)
    252 {
    253         assert(instance);
    254         transfer_t trans = {
    255                 .address = address,
    256                 .endpoint = endpoint,
    257                 .direction = direction,
    258         };
    259         fibril_mutex_lock(&instance->guard);
    260         link_t *item =
    261             hash_table_find(&instance->reserved, (unsigned long*)&trans);
    262         int ret = EOK;
    263         if (item != NULL) {
    264                 transfer_status_t *status =
    265                     hash_table_get_instance(item, transfer_status_t, link);
    266                 assert(status);
    267                 if (!status->used) {
    268                         ret = ENOENT;
    269                 }
    270                 status->used = false;
    271         } else {
    272                 ret = EINVAL;
    273         }
    274         fibril_mutex_unlock(&instance->guard);
    275         return ret;
    276 }
     230        return node->ep;
     231}
  • uspace/lib/usb/src/hub.c

    r9d06563 ra4e18e1  
    142142            DEV_IFACE_ID(USBHC_DEV_IFACE),
    143143            IPC_M_USBHC_RELEASE_ADDRESS, address);
     144}
     145
     146static void unregister_control_endpoint_on_default_address(
     147    usb_hc_connection_t *connection)
     148{
     149        usb_device_connection_t dev_conn;
     150        int rc = usb_device_connection_initialize_on_default_address(&dev_conn,
     151            connection);
     152        if (rc != EOK) {
     153                return;
     154        }
     155
     156        usb_pipe_t ctrl_pipe;
     157        rc = usb_pipe_initialize_default_control(&ctrl_pipe, &dev_conn);
     158        if (rc != EOK) {
     159                return;
     160        }
     161
     162        usb_pipe_unregister(&ctrl_pipe, connection);
    144163}
    145164
     
    235254                goto leave_release_default_address;
    236255        }
     256
     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;
     263                goto leave_release_default_address;
     264        }
    237265        rc = usb_pipe_probe_default_control(&ctrl_pipe);
    238266        if (rc != EOK) {
     
    244272        if (rc != EOK) {
    245273                rc = ENOTCONN;
    246                 goto leave_release_default_address;
     274                goto leave_unregister_endpoint;
    247275        }
    248276
     
    256284
    257285        /*
     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        /*
    258300         * Once the address is changed, we can return the default address.
    259301         */
    260302        usb_hc_release_default_address(connection);
     303
    261304
    262305        /*
     
    273316        }
    274317
     318
     319
    275320        /*
    276321         * And now inform the host controller about the handle.
     
    308353        usb_pipe_end_session(&ctrl_pipe);
    309354
     355leave_unregister_endpoint:
     356        usb_pipe_unregister(&ctrl_pipe, connection);
     357
    310358leave_release_default_address:
    311359        usb_hc_release_default_address(connection);
  • uspace/lib/usb/src/pipesinit.c

    r9d06563 ra4e18e1  
    121121    usb_endpoint_mapping_t *mapping, size_t mapping_count,
    122122    usb_endpoint_description_t *found_endpoint,
    123     int interface_number)
     123    int interface_number, int interface_setting)
    124124{
    125125        while (mapping_count > 0) {
     
    127127                    || (mapping->interface_no == interface_number);
    128128
     129                bool interface_setting_fits = (mapping->interface_setting < 0)
     130                    || (mapping->interface_setting == interface_setting);
     131
    129132                bool endpoint_descriptions_fits = endpoint_fits_description(
    130133                    mapping->description, found_endpoint);
    131134
    132                 if (interface_number_fits && endpoint_descriptions_fits) {
     135                if (interface_number_fits
     136                    && interface_setting_fits
     137                    && endpoint_descriptions_fits) {
    133138                        return mapping;
    134139                }
     
    181186         */
    182187        usb_endpoint_mapping_t *ep_mapping = find_endpoint_mapping(mapping,
    183             mapping_count, &description, interface->interface_number);
     188            mapping_count, &description,
     189            interface->interface_number, interface->alternate_setting);
    184190        if (ep_mapping == NULL) {
    185191                return ENOENT;
Note: See TracChangeset for help on using the changeset viewer.