Changeset 3f02935 in mainline


Ignore:
Timestamp:
2018-01-21T19:33:22Z (6 years ago)
Author:
Ondřej Hlavatý <aearsis@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
cd0cf81
Parents:
cd3fa47
Message:

usbhub: split enumeration routine for superspeed devices

File:
1 edited

Legend:

Unmodified
Added
Removed
  • uspace/drv/bus/usb/usbhub/port.c

    rcd3fa47 r3f02935  
    9999
    100100/**
    101  * Routine for adding a new device.
    102  *
    103  * Separate fibril is needed because the operation blocks on waiting for
    104  * requesting default address and resetting port, and we must not block the
    105  * control pipe.
    106  */
     101 * Routine for adding a new device in USB2.
     102 */
     103static int enumerate_device_usb2(usb_hub_port_t *port, async_exch_t *exch)
     104{
     105        int err;
     106
     107        port_log(debug, port, "Requesting default address.");
     108        err = usb_hub_reserve_default_address(port->hub, exch, &port->base);
     109        if (err != EOK) {
     110                port_log(error, port, "Failed to reserve default address: %s", str_error(err));
     111                return err;
     112        }
     113
     114        /* Reservation of default address could have blocked */
     115        if (port->base.state != PORT_CONNECTING)
     116                goto out_address;
     117
     118        port_log(debug, port, "Resetting port.");
     119        if ((err = usb_hub_set_port_feature(port->hub, port->port_number, USB_HUB_FEATURE_PORT_RESET))) {
     120                port_log(warning, port, "Port reset request failed: %s", str_error(err));
     121                goto out_address;
     122        }
     123
     124        if ((err = usb_port_wait_for_enabled(&port->base))) {
     125                port_log(error, port, "Failed to reset port: %s", str_error(err));
     126                goto out_address;
     127        }
     128
     129        port_log(debug, port, "Enumerating device.");
     130        if ((err = usbhc_device_enumerate(exch, port->port_number, port->speed))) {
     131                port_log(error, port, "Failed to enumerate device: %s", str_error(err));
     132                /* Disable the port */
     133                usb_hub_clear_port_feature(port->hub, port->port_number, USB2_HUB_FEATURE_PORT_ENABLE);
     134                goto out_address;
     135        }
     136
     137        port_log(debug, port, "Device enumerated");
     138
     139out_address:
     140        usb_hub_release_default_address(port->hub, exch);
     141        return err;
     142}
     143
     144/**
     145 * Routine for adding a new device in USB 3.
     146 */
     147static int enumerate_device_usb3(usb_hub_port_t *port, async_exch_t *exch)
     148{
     149        int err;
     150
     151        port_log(debug, port, "Issuing a warm reset.");
     152        if ((err = usb_hub_set_port_feature(port->hub, port->port_number, USB3_HUB_FEATURE_BH_PORT_RESET))) {
     153                port_log(warning, port, "Port reset request failed: %s", str_error(err));
     154                return err;
     155        }
     156
     157        if ((err = usb_port_wait_for_enabled(&port->base))) {
     158                port_log(error, port, "Failed to reset port: %s", str_error(err));
     159                return err;
     160        }
     161
     162        port_log(debug, port, "Enumerating device.");
     163        if ((err = usbhc_device_enumerate(exch, port->port_number, port->speed))) {
     164                port_log(error, port, "Failed to enumerate device: %s", str_error(err));
     165                return err;
     166        }
     167
     168        port_log(debug, port, "Device enumerated");
     169        return EOK;
     170}
     171
    107172static int enumerate_device(usb_port_t *port_base)
    108173{
    109         int err;
    110174        usb_hub_port_t *port = get_hub_port(port_base);
    111175
    112176        port_log(debug, port, "Setting up new device.");
    113 
    114177        async_exch_t *exch = usb_device_bus_exchange_begin(port->hub->usb_device);
    115178        if (!exch) {
     
    118181        }
    119182
    120         /* Reserve default address */
    121         err = usb_hub_reserve_default_address(port->hub, exch, &port->base);
    122         if (err != EOK) {
    123                 port_log(error, port, "Failed to reserve default address: %s", str_error(err));
    124                 goto out_exch;
    125         }
    126 
    127         /* Reservation of default address could have blocked */
    128         if (port->base.state != PORT_CONNECTING)
    129                 goto out_address;
    130 
    131         port_log(debug, port, "Got default address. Resetting port.");
    132         int rc = usb_hub_set_port_feature(port->hub, port->port_number, USB_HUB_FEATURE_PORT_RESET);
    133         if (rc != EOK) {
    134                 port_log(warning, port, "Port reset request failed: %s", str_error(rc));
    135                 goto out_address;
    136         }
    137 
    138         if ((err = usb_port_wait_for_enabled(&port->base))) {
    139                 port_log(error, port, "Failed to reset port: %s", str_error(err));
    140                 goto out_address;
    141         }
    142 
    143         port_log(debug, port, "Port reset, enumerating device.");
    144 
    145         if ((err = usbhc_device_enumerate(exch, port->port_number, port->speed))) {
    146                 port_log(error, port, "Failed to enumerate device: %s", str_error(err));
    147                 /* Disable the port in USB 2 (impossible in USB3) */
    148                 if (port->speed <= USB_SPEED_HIGH)
    149                         usb_hub_clear_port_feature(port->hub, port->port_number, USB2_HUB_FEATURE_PORT_ENABLE);
    150                 goto out_address;
    151         }
    152 
    153         port_log(debug, port, "Device enumerated");
    154 
    155 out_address:
    156         usb_hub_release_default_address(port->hub, exch);
    157 out_exch:
     183        const int err = port->hub->speed == USB_SPEED_SUPER
     184                ? enumerate_device_usb3(port, exch)
     185                : enumerate_device_usb2(port, exch);
     186
    158187        usb_device_bus_exchange_end(exch);
    159188        return err;
     
    165194        port_log(debug, port, "Connection change: device %s.", connected ? "attached" : "removed");
    166195
    167         if (connected) {
     196        if (connected && port->hub->speed == USB_SPEED_SUPER) {
    168197                usb_port_connected(&port->base, &enumerate_device);
    169198        } else {
     
    206235
    207236        if (enabled) {
    208                 // The connecting fibril do not touch speed until the port is enabled,
    209                 // so we do not have to lock
    210237                port->speed = get_port_speed(port, status);
    211238                usb_port_enabled(&port->base);
Note: See TracChangeset for help on using the changeset viewer.