Changeset d083126 in mainline for uspace/drv/bus/usb/uhcirh/port.c


Ignore:
Timestamp:
2011-10-13T13:20:26Z (13 years ago)
Author:
Jan Vesely <jano.vesely@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
3a5506a
Parents:
cff3fb6 (diff), 22a2b763 (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 initial USB unplug support.

Support device_remove and device_gone in libusbdev.
usbhub and uhcirh try to unbind and destroy functions of attached devices.
add unplug support for usbhub driver (only works on empty hubs as there is no support in other drivers).

Drivers to go:

usbmid
usbflbk
usbhid
usbmast
usbmouse

Tested on:

qemu UHCI and emulated hub,
ICH8 hw and Alcor Micro Corp. USB Hub

File:
1 edited

Legend:

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

    rcff3fb6 rd083126  
    3737#include <str_error.h>
    3838#include <async.h>
     39#include <devman.h>
    3940
    4041#include <usb/usb.h>    /* usb_address_t */
    41 #include <usb/dev/hub.h>    /* usb_hc_new_device_wrapper */
    4242#include <usb/debug.h>
    4343
    4444#include "port.h"
    4545
     46#define MAX_ERROR_COUNT 5
     47
    4648static int uhci_port_check(void *port);
    47 static int uhci_port_reset_enable(int portno, void *arg);
     49static int uhci_port_reset_enable(void *arg);
    4850static int uhci_port_new_device(uhci_port_t *port, usb_speed_t speed);
    4951static int uhci_port_remove_device(uhci_port_t *port);
     
    100102        port->number = number;
    101103        port->wait_period_usec = usec;
    102         port->attached_device = 0;
     104        port->attached_device.fun = NULL;
     105        port->attached_device.address = -1;
    103106        port->rh = rh;
    104107
     
    150153        assert(instance);
    151154
     155        unsigned allowed_failures = MAX_ERROR_COUNT;
     156#define CHECK_RET_FAIL(ret, msg...) \
     157        if (ret != EOK) { \
     158                usb_log_error(msg); \
     159                if (!(allowed_failures-- > 0)) { \
     160                        usb_log_fatal( \
     161                           "Maximum number of failures reached, " \
     162                           "bailing out.\n"); \
     163                        return ret; \
     164                } \
     165                continue; \
     166        } else (void)0
     167
    152168        while (1) {
    153169                async_usleep(instance->wait_period_usec);
     
    167183                    instance->id_string, port_status);
    168184
     185                int ret = usb_hc_connection_open(&instance->hc_connection);
     186                CHECK_RET_FAIL(ret, "%s: Failed to connect to HC %s.\n",
     187                    instance->id_string, str_error(ret));
     188
    169189                /* Remove any old device */
    170                 if (instance->attached_device) {
    171                         usb_log_debug2("%s: Removing device.\n",
    172                             instance->id_string);
     190                if (instance->attached_device.fun) {
    173191                        uhci_port_remove_device(instance);
    174192                }
    175193
    176                 int ret =
    177                     usb_hc_connection_open(&instance->hc_connection);
    178                 if (ret != EOK) {
    179                         usb_log_error("%s: Failed to connect to HC.",
    180                             instance->id_string);
    181                         continue;
    182                 }
    183 
    184194                if ((port_status & STATUS_CONNECTED) != 0) {
    185                         /* New device */
     195                        /* New device, this will take care of WC bits */
    186196                        const usb_speed_t speed =
    187197                            ((port_status & STATUS_LOW_SPEED) != 0) ?
     
    196206
    197207                ret = usb_hc_connection_close(&instance->hc_connection);
    198                 if (ret != EOK) {
    199                         usb_log_error("%s: Failed to disconnect.",
    200                             instance->id_string);
    201                 }
     208                CHECK_RET_FAIL(ret, "%s: Failed to disconnect from hc: %s.\n",
     209                    instance->id_string, str_error(ret));
    202210        }
    203211        return EOK;
     
    212220 * Resets and enables the ub port.
    213221 */
    214 int uhci_port_reset_enable(int portno, void *arg)
     222int uhci_port_reset_enable(void *arg)
    215223{
    216224        uhci_port_t *port = arg;
     
    256264        usb_log_debug("%s: Detected new device.\n", port->id_string);
    257265
    258         int ret, count = 0;
    259         usb_address_t dev_addr;
     266        int ret, count = MAX_ERROR_COUNT;
    260267        do {
    261268                ret = usb_hc_new_device_wrapper(port->rh, &port->hc_connection,
    262                     speed, uhci_port_reset_enable, port->number, port,
    263                     &dev_addr, &port->attached_device, NULL, NULL, NULL);
    264         } while (ret != EOK && ++count < 4);
     269                    speed, uhci_port_reset_enable, port,
     270                    &port->attached_device.address, NULL, NULL,
     271                    &port->attached_device.fun);
     272        } while (ret != EOK && count-- > 0);
    265273
    266274        if (ret != EOK) {
     
    271279        }
    272280
    273         usb_log_info("New device at port %u, address %d (handle %" PRIun ").\n",
    274             port->number, dev_addr, port->attached_device);
     281        usb_log_info("%s: New device, address %d (handle %" PRIun ").\n",
     282            port->id_string, port->attached_device.address,
     283            port->attached_device.fun->handle);
    275284        return EOK;
    276285}
     
    278287/** Remove device.
    279288 *
    280  * @param[in] port Memory structure to use.
    281  * @return Error code.
    282  *
    283  * Does not work, DDF does not support device removal.
    284  * Does not even free used USB address (it would be dangerous if tis driver
    285  * is still running).
     289 * @param[in] port Port instance to use.
     290 * @return Error code.
    286291 */
    287292int uhci_port_remove_device(uhci_port_t *port)
    288293{
    289         usb_log_error("%s: Don't know how to remove device %" PRIun ".\n",
    290             port->id_string, port->attached_device);
    291         port->attached_device = 0;
    292         return ENOTSUP;
     294        assert(port);
     295        /* There is nothing to remove. */
     296        if (port->attached_device.fun == NULL) {
     297                usb_log_warning("%s: Removed a ghost device.\n",
     298                    port->id_string);
     299                assert(port->attached_device.address == -1);
     300                return EOK;
     301        }
     302
     303        usb_log_debug("%s: Removing device.\n", port->id_string);
     304
     305        /* Stop driver first */
     306        int ret = ddf_fun_unbind(port->attached_device.fun);
     307        if (ret != EOK) {
     308                usb_log_error("%s: Failed to remove child function: %s.\n",
     309                   port->id_string, str_error(ret));
     310                return ret;
     311        }
     312        ddf_fun_destroy(port->attached_device.fun);
     313        port->attached_device.fun = NULL;
     314
     315        /* Driver stopped, free used address */
     316        ret = usb_hc_unregister_device(&port->hc_connection,
     317            port->attached_device.address);
     318        if (ret != EOK) {
     319                usb_log_error("%s: Failed to unregister address of removed "
     320                    "device: %s.\n", port->id_string, str_error(ret));
     321                return ret;
     322        }
     323        port->attached_device.address = -1;
     324
     325        usb_log_info("%s: Removed attached device.\n", port->id_string);
     326        return EOK;
    293327}
    294328/*----------------------------------------------------------------------------*/
Note: See TracChangeset for help on using the changeset viewer.