Changeset 20eaa82 in mainline for uspace/lib/usbhost/src/usb2_bus.c


Ignore:
Timestamp:
2017-10-15T13:44:39Z (8 years ago)
Author:
Ondřej Hlavatý <aearsis@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
2770b66
Parents:
867b375
Message:

usbhost refactoring: introduced bus→enumerate_device

File:
1 edited

Legend:

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

    r867b375 r20eaa82  
    3636#include <usb/host/usb2_bus.h>
    3737#include <usb/host/endpoint.h>
     38#include <usb/host/ddf_helpers.h>
    3839#include <usb/debug.h>
     40#include <usb/request.h>
     41#include <usb/descriptor.h>
     42#include <usb/usb.h>
    3943
    4044#include <assert.h>
    4145#include <errno.h>
    4246#include <macros.h>
     47#include <str_error.h>
    4348#include <stdlib.h>
    4449#include <stdbool.h>
     
    6166        assert(addr >= 0);
    6267        return &bus->devices[addr % ARRAY_SIZE(bus->devices)].endpoint_list;
     68}
     69
     70/** Get speed assigned to USB address.
     71 *
     72 * @param[in] bus Device manager structure to use.
     73 * @param[in] address Address the caller wants to find.
     74 * @param[out] speed Assigned speed.
     75 * @return Error code.
     76 */
     77static int usb2_bus_get_speed(bus_t *bus_base, usb_address_t address, usb_speed_t *speed)
     78{
     79        usb2_bus_t *bus = bus_to_usb2_bus(bus_base);
     80
     81        if (!usb_address_is_valid(address)) {
     82                return EINVAL;
     83        }
     84
     85        const int ret = bus->devices[address].occupied ? EOK : ENOENT;
     86        if (speed && bus->devices[address].occupied) {
     87                *speed = bus->devices[address].speed;
     88        }
     89
     90        return ret;
     91}
     92
     93static int usb2_bus_address_device(bus_t *bus, hcd_t *hcd, device_t *dev)
     94{
     95        int err;
     96
     97        static const usb_target_t default_target = {{
     98                .address = USB_ADDRESS_DEFAULT,
     99                .endpoint = 0,
     100        }};
     101
     102        /** Reserve address early, we want pretty log messages */
     103        const usb_address_t address = bus_reserve_default_address(bus, dev->speed);
     104        if (address < 0) {
     105                usb_log_error("Failed to reserve new address: %s.",
     106                    str_error(address));
     107                return address;
     108        }
     109        usb_log_debug("Device(%d): Reserved new address.", address);
     110
     111        /* Add default pipe on default address */
     112        usb_log_debug("Device(%d): Adding default target (0:0)", address);
     113        err = bus_add_ep(bus, dev, 0, USB_DIRECTION_BOTH, USB_TRANSFER_CONTROL,
     114            CTRL_PIPE_MIN_PACKET_SIZE, CTRL_PIPE_MIN_PACKET_SIZE, 1);
     115        if (err != EOK) {
     116                usb_log_error("Device(%d): Failed to add default target: %s.",
     117                    address, str_error(err));
     118                goto err_address;
     119        }
     120
     121        /* Get max packet size for default pipe */
     122        usb_standard_device_descriptor_t desc = { 0 };
     123        const usb_device_request_setup_packet_t get_device_desc_8 =
     124            GET_DEVICE_DESC(CTRL_PIPE_MIN_PACKET_SIZE);
     125
     126        usb_log_debug("Device(%d): Requesting first 8B of device descriptor.",
     127            address);
     128        ssize_t got = hcd_send_batch_sync(hcd, default_target, USB_DIRECTION_IN,
     129            &desc, CTRL_PIPE_MIN_PACKET_SIZE, *(uint64_t *)&get_device_desc_8,
     130            "read first 8 bytes of dev descriptor");
     131
     132        if (got != CTRL_PIPE_MIN_PACKET_SIZE) {
     133                err = got < 0 ? got : EOVERFLOW;
     134                usb_log_error("Device(%d): Failed to get 8B of dev descr: %s.",
     135                    address, str_error(err));
     136                goto err_default_target;
     137        }
     138
     139        /* Set new address */
     140        const usb_device_request_setup_packet_t set_address = SET_ADDRESS(address);
     141
     142        usb_log_debug("Device(%d): Setting USB address.", address);
     143        err = hcd_send_batch_sync(hcd, default_target, USB_DIRECTION_OUT,
     144            NULL, 0, *(uint64_t *)&set_address, "set address");
     145        if (err != 0) {
     146                usb_log_error("Device(%d): Failed to set new address: %s.",
     147                    address, str_error(got));
     148                goto err_default_target;
     149        }
     150
     151        dev->address = address;
     152
     153        /* Register EP on the new address */
     154        usb_log_debug("Device(%d): Registering control EP.", address);
     155        err = bus_add_ep(bus, dev, 0, USB_DIRECTION_BOTH, USB_TRANSFER_CONTROL,
     156            ED_MPS_PACKET_SIZE_GET(uint16_usb2host(desc.max_packet_size)),
     157            ED_MPS_TRANS_OPPORTUNITIES_GET(uint16_usb2host(desc.max_packet_size)),
     158            ED_MPS_PACKET_SIZE_GET(uint16_usb2host(desc.max_packet_size)));
     159        if (err != EOK) {
     160                usb_log_error("Device(%d): Failed to register EP0: %s",
     161                    address, str_error(err));
     162                goto err_default_target;
     163        }
     164
     165        bus_remove_ep(bus, default_target, USB_DIRECTION_BOTH);
     166        return EOK;
     167
     168err_default_target:
     169        bus_remove_ep(bus, default_target, USB_DIRECTION_BOTH);
     170err_address:
     171        bus_release_address(bus, address);
     172        return err;
     173}
     174
     175/** Enumerate a new USB device
     176 */
     177static int usb2_bus_enumerate_device(bus_t *bus, hcd_t *hcd, device_t *dev)
     178{
     179        int err;
     180
     181        /* The speed of the new device was reported by the hub when reserving
     182         * default address.
     183         */
     184        if ((err = usb2_bus_get_speed(bus, USB_ADDRESS_DEFAULT, &dev->speed))) {
     185                usb_log_error("Failed to verify speed: %s.", str_error(err));
     186                return err;
     187        }
     188        usb_log_debug("Found new %s speed USB device.", usb_str_speed(dev->speed));
     189
     190        /* Manage TT */
     191        if (dev->hub->speed == USB_SPEED_HIGH && usb_speed_is_11(dev->speed)) {
     192                /* For LS devices under HS hub */
     193                /* TODO: How about SS hubs? */
     194                dev->tt.address = dev->hub->address;
     195                dev->tt.port = dev->port;
     196        }
     197        else {
     198                /* Inherit hub's TT */
     199                dev->tt = dev->hub->tt;
     200        }
     201
     202        /* Assign an address to the device */
     203        if ((err = usb2_bus_address_device(bus, hcd, dev))) {
     204                usb_log_error("Failed to setup address of the new device: %s", str_error(err));
     205                return err;
     206        }
     207
     208        /* Read the device descriptor, derive the match ids */
     209        if ((err = hcd_ddf_device_explore(hcd, dev))) {
     210                usb_log_error("Device(%d): Failed to explore device: %s", dev->address, str_error(err));
     211                bus_release_address(bus, dev->address);
     212                return err;
     213        }
     214
     215        return EOK;
    63216}
    64217
     
    190343 * @param endpoint USB endpoint number.
    191344 * @param direction Communication direction.
    192  * @param callback Function to call after unregister, before destruction.
    193  * @arg Argument to pass to the callback function.
    194345 * @return Error code.
    195346 */
     
    211362                list_remove(&ep->link);
    212363
     364                usb_log_warning("Endpoint %d:%d %s was left behind, removing.\n",
     365                    ep->target.address, ep->target.endpoint, usb_str_direction(ep->direction));
     366
    213367                /* Drop bus reference */
    214368                endpoint_del_ref(ep);
     
    258412}
    259413
    260 /** Get speed assigned to USB address.
    261  *
    262  * @param[in] bus Device manager structure to use.
    263  * @param[in] address Address the caller wants to find.
    264  * @param[out] speed Assigned speed.
    265  * @return Error code.
    266  */
    267 static int usb2_bus_get_speed(bus_t *bus_base, usb_address_t address, usb_speed_t *speed)
    268 {
    269         usb2_bus_t *bus = bus_to_usb2_bus(bus_base);
    270 
    271         if (!usb_address_is_valid(address)) {
    272                 return EINVAL;
    273         }
    274 
    275         const int ret = bus->devices[address].occupied ? EOK : ENOENT;
    276         if (speed && bus->devices[address].occupied) {
    277                 *speed = bus->devices[address].speed;
    278         }
    279 
    280         return ret;
    281 }
    282 
    283414static const bus_ops_t usb2_bus_ops = {
     415        .enumerate_device = usb2_bus_enumerate_device,
    284416        .create_endpoint = usb2_bus_create_ep,
    285417        .find_endpoint = usb2_bus_find_ep,
     
    289421        .release_address = usb2_bus_release_address,
    290422        .reset_toggle = usb2_bus_reset_toggle,
    291         .get_speed = usb2_bus_get_speed,
    292423};
    293424
     
    303434        assert(bus);
    304435
    305         bus_init(&bus->base);
     436        bus_init(&bus->base, sizeof(device_t));
    306437
    307438        bus->base.ops = usb2_bus_ops;
Note: See TracChangeset for help on using the changeset viewer.