Ignore:
Timestamp:
2011-11-10T11:29:10Z (13 years ago)
Author:
Jan Vesely <jano.vesely@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
54464f6a, c2245a3, c6f189f7
Parents:
2e1b9dc (diff), 2d1ba51 (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.

Interface changes:

  • GET_ADDRESS has been renamed to GET_MY_ADDRESS and the handle parameter was dropped. Tis call no longer cascades up to the root hub, but it is answered in the first place the information is available (nearest hub)
  • Reintroduced address reservation for USB_DEFAULT_ADDRESS. The interface now enables device drivers to request specific address on initialization and either insists on that address or accept any other if the address is not available. Note that it is not possible to get the default address if the driver does not insist.
  • Any endpoint registered is removed when address is released and a warning is produced if there were any such endpoints.
  • It is no longer necessary or possible to pass device speed information when registering endpoints.

Driver fixes: memory leaks and crashes (not only) in error paths.
Fixes or removes flaky device_remove implementation in device drivers.

File:
1 edited

Legend:

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

    r2e1b9dc r747ef72  
    3838#include <usb/host/usb_device_manager.h>
    3939
     40/** Get a free USB address
     41 *
     42 * @param[in] instance Device manager structure to use.
     43 * @param[in] speed Speed of the device requiring address.
     44 * @return Free address, or error code.
     45 */
     46static usb_address_t usb_device_manager_get_free_address(
     47    usb_device_manager_t *instance)
     48{
     49
     50        usb_address_t new_address = instance->last_address;
     51        do {
     52                new_address = (new_address + 1) % USB_ADDRESS_COUNT;
     53                if (new_address == USB_ADDRESS_DEFAULT)
     54                        new_address = 1;
     55                if (new_address == instance->last_address) {
     56                        return ENOSPC;
     57                }
     58        } while (instance->devices[new_address].occupied);
     59
     60        assert(new_address != USB_ADDRESS_DEFAULT);
     61        instance->last_address = new_address;
     62
     63        return new_address;
     64}
     65/*----------------------------------------------------------------------------*/
    4066/** Initialize device manager structure.
    4167 *
    4268 * @param[in] instance Memory place to initialize.
     69 * @param[in] max_speed Maximum allowed USB speed of devices (inclusive).
    4370 *
    4471 * Set all values to false/0.
    4572 */
    46 void usb_device_manager_init(usb_device_manager_t *instance)
     73void usb_device_manager_init(
     74    usb_device_manager_t *instance, usb_speed_t max_speed)
    4775{
    4876        assert(instance);
     
    5280                instance->devices[i].speed = USB_SPEED_MAX;
    5381        }
    54         // TODO: is this hack enough?
    55         // (it is needed to allow smooth registration at default address)
    56         instance->devices[0].occupied = true;
    57         instance->last_address = 0;
     82        instance->last_address = 1;
     83        instance->max_speed = max_speed;
    5884        fibril_mutex_initialize(&instance->guard);
    5985}
    6086/*----------------------------------------------------------------------------*/
    61 /** Get a free USB address
    62  *
    63  * @param[in] instance Device manager structure to use.
    64  * @param[in] speed Speed of the device requiring address.
    65  * @return Free address, or error code.
    66  */
    67 usb_address_t usb_device_manager_get_free_address(
    68     usb_device_manager_t *instance, usb_speed_t speed)
    69 {
    70         assert(instance);
    71         fibril_mutex_lock(&instance->guard);
    72 
    73         usb_address_t new_address = instance->last_address;
    74         do {
    75                 ++new_address;
    76                 if (new_address > USB11_ADDRESS_MAX)
    77                         new_address = 1; // NOTE it should be safe to put 0 here
    78                                          // TODO Use mod
    79                 if (new_address == instance->last_address) {
     87/** Request USB address.
     88 * @param instance usb_device_manager
     89 * @param address Pointer to requested address value, place to store new address
     90 * @parma strict Fail if the requested address is not available.
     91 * @return Error code.
     92 * @note Default address is only available in strict mode.
     93 */
     94int usb_device_manager_request_address(usb_device_manager_t *instance,
     95    usb_address_t *address, bool strict, usb_speed_t speed)
     96{
     97        assert(instance);
     98        assert(address);
     99        if (speed > instance->max_speed)
     100                return ENOTSUP;
     101
     102        if ((*address) < 0 || (*address) >= USB_ADDRESS_COUNT)
     103                return EINVAL;
     104
     105        fibril_mutex_lock(&instance->guard);
     106        /* Only grant default address to strict requests */
     107        if (( (*address) == USB_ADDRESS_DEFAULT) && !strict) {
     108                *address = instance->last_address;
     109        }
     110
     111        if (instance->devices[*address].occupied) {
     112                if (strict) {
    80113                        fibril_mutex_unlock(&instance->guard);
    81                         return ENOSPC;
     114                        return ENOENT;
    82115                }
    83         } while (instance->devices[new_address].occupied);
    84 
    85         assert(new_address != USB_ADDRESS_DEFAULT);
    86         assert(instance->devices[new_address].occupied == false);
    87         assert(instance->devices[new_address].handle == 0);
    88 
    89         instance->devices[new_address].occupied = true;
    90         instance->devices[new_address].speed = speed;
    91         instance->last_address = new_address;
    92 
    93         fibril_mutex_unlock(&instance->guard);
    94         return new_address;
     116                *address = usb_device_manager_get_free_address(instance);
     117        }
     118        assert(instance->devices[*address].occupied == false);
     119        assert(instance->devices[*address].handle == 0);
     120        assert(*address != USB_ADDRESS_DEFAULT || strict);
     121
     122        instance->devices[*address].occupied = true;
     123        instance->devices[*address].speed = speed;
     124
     125        fibril_mutex_unlock(&instance->guard);
     126        return EOK;
    95127}
    96128/*----------------------------------------------------------------------------*/
     
    102134 * @return Error code.
    103135 */
    104 int usb_device_manager_bind(usb_device_manager_t *instance,
     136int usb_device_manager_bind_address(usb_device_manager_t *instance,
    105137    usb_address_t address, devman_handle_t handle)
    106138{
     
    132164 * @return Error code.
    133165 */
    134 int usb_device_manager_release(
     166int usb_device_manager_release_address(
    135167    usb_device_manager_t *instance, usb_address_t address)
    136168{
    137         if ((address <= 0) || (address >= USB_ADDRESS_COUNT)) {
     169        if ((address < 0) || (address >= USB_ADDRESS_COUNT)) {
    138170                return EINVAL;
    139171        }
     
    188220{
    189221        assert(instance);
    190         if ((address <= 0) || (address >= USB_ADDRESS_COUNT)) {
     222        if ((address < 0) || (address >= USB_ADDRESS_COUNT)) {
    191223                return EINVAL;
    192224        }
Note: See TracChangeset for help on using the changeset viewer.