Ignore:
File:
1 edited

Legend:

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

    r5203e256 re882e3a  
    3939
    4040#include <usb/usb.h>    /* usb_address_t */
    41 #include <usb/dev/hub.h>    /* usb_hc_new_device_wrapper */
    4241#include <usb/debug.h>
    4342
    4443#include "port.h"
    4544
     45#define MAX_ERROR_COUNT 5
     46
    4647static int uhci_port_check(void *port);
    47 static int uhci_port_reset_enable(int portno, void *arg);
     48static int uhci_port_reset_enable(void *arg);
    4849static int uhci_port_new_device(uhci_port_t *port, usb_speed_t speed);
    4950static int uhci_port_remove_device(uhci_port_t *port);
     
    100101        port->number = number;
    101102        port->wait_period_usec = usec;
    102         port->attached_device = 0;
     103        port->attached_device.fun = NULL;
     104        port->attached_device.address = -1;
    103105        port->rh = rh;
    104106
     
    150152        assert(instance);
    151153
     154        unsigned allowed_failures = MAX_ERROR_COUNT;
     155#define CHECK_RET_FAIL(ret, msg...) \
     156        if (ret != EOK) { \
     157                usb_log_error(msg); \
     158                if (!(allowed_failures-- > 0)) { \
     159                        usb_log_fatal( \
     160                           "Maximum number of failures reached, " \
     161                           "bailing out.\n"); \
     162                        return ret; \
     163                } \
     164                continue; \
     165        } else (void)0
     166
    152167        while (1) {
    153168                async_usleep(instance->wait_period_usec);
     
    167182                    instance->id_string, port_status);
    168183
     184                int ret = usb_hc_connection_open(&instance->hc_connection);
     185                CHECK_RET_FAIL(ret, "%s: Failed to connect to HC %s.\n",
     186                    instance->id_string, str_error(ret));
     187
    169188                /* Remove any old device */
    170                 if (instance->attached_device) {
    171                         usb_log_debug2("%s: Removing device.\n",
    172                             instance->id_string);
     189                if (instance->attached_device.fun) {
    173190                        uhci_port_remove_device(instance);
    174191                }
    175192
    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 
    184193                if ((port_status & STATUS_CONNECTED) != 0) {
    185                         /* New device */
     194                        /* New device, this will take care of WC bits */
    186195                        const usb_speed_t speed =
    187196                            ((port_status & STATUS_LOW_SPEED) != 0) ?
     
    196205
    197206                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                 }
     207                CHECK_RET_FAIL(ret, "%s: Failed to disconnect from hc: %s.\n",
     208                    instance->id_string, str_error(ret));
    202209        }
    203210        return EOK;
     
    212219 * Resets and enables the ub port.
    213220 */
    214 int uhci_port_reset_enable(int portno, void *arg)
     221int uhci_port_reset_enable(void *arg)
    215222{
    216223        uhci_port_t *port = arg;
     
    252259{
    253260        assert(port);
    254         assert(usb_hc_connection_is_opened(&port->hc_connection));
    255261
    256262        usb_log_debug("%s: Detected new device.\n", port->id_string);
    257263
    258         int ret, count = 0;
    259         usb_address_t dev_addr;
     264        int ret, count = MAX_ERROR_COUNT;
    260265        do {
    261266                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);
     267                    speed, uhci_port_reset_enable, port,
     268                    &port->attached_device.address, NULL, NULL,
     269                    &port->attached_device.fun);
     270        } while (ret != EOK && count-- > 0);
    265271
    266272        if (ret != EOK) {
     
    271277        }
    272278
    273         usb_log_info("New device at port %u, address %d (handle %" PRIun ").\n",
    274             port->number, dev_addr, port->attached_device);
     279        usb_log_info("%s: New device, address %d (handle %" PRIun ").\n",
     280            port->id_string, port->attached_device.address,
     281            port->attached_device.fun->handle);
    275282        return EOK;
    276283}
     
    278285/** Remove device.
    279286 *
    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).
     287 * @param[in] port Port instance to use.
     288 * @return Error code.
    286289 */
    287290int uhci_port_remove_device(uhci_port_t *port)
    288291{
    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;
     292        assert(port);
     293        /* There is nothing to remove. */
     294        if (port->attached_device.fun == NULL) {
     295                usb_log_warning("%s: Removed a ghost device.\n",
     296                    port->id_string);
     297                assert(port->attached_device.address == -1);
     298                return EOK;
     299        }
     300
     301        usb_log_debug("%s: Removing device.\n", port->id_string);
     302
     303        /* Stop driver first */
     304        int ret = ddf_fun_unbind(port->attached_device.fun);
     305        if (ret != EOK) {
     306                usb_log_error("%s: Failed to remove child function: %s.\n",
     307                   port->id_string, str_error(ret));
     308                return ret;
     309        }
     310        ddf_fun_destroy(port->attached_device.fun);
     311        port->attached_device.fun = NULL;
     312
     313        /* Driver stopped, free used address */
     314        ret = usb_hub_unregister_device(&port->hc_connection,
     315            &port->attached_device);
     316        if (ret != EOK) {
     317                usb_log_error("%s: Failed to unregister address of removed "
     318                    "device: %s.\n", port->id_string, str_error(ret));
     319                return ret;
     320        }
     321        port->attached_device.address = -1;
     322
     323        usb_log_info("%s: Removed attached device.\n", port->id_string);
     324        return EOK;
    293325}
    294326/*----------------------------------------------------------------------------*/
Note: See TracChangeset for help on using the changeset viewer.