Ignore:
File:
1 edited

Legend:

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

    r5203e256 r612af1a0  
    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.