Changeset d083126 in mainline for uspace/drv/bus/usb/usbhub/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/usbhub/port.c

    rcff3fb6 rd083126  
    5050/** Information for fibril for device discovery. */
    5151struct add_device_phase1 {
    52         usb_hub_info_t *hub;
     52        usb_hub_dev_t *hub;
    5353        usb_hub_port_t *port;
    5454        usb_speed_t speed;
    5555};
    5656
    57 static void usb_hub_port_removed_device(usb_hub_port_t *port,
    58     usb_hub_info_t *hub);
     57static int usb_hub_port_device_gone(usb_hub_port_t *port, usb_hub_dev_t *hub);
    5958static void usb_hub_port_reset_completed(usb_hub_port_t *port,
    6059    usb_port_status_t status);
    6160static int get_port_status(usb_hub_port_t *port, usb_port_status_t *status);
    62 static int enable_port_callback(int port_no, void *arg);
     61static int enable_port_callback(void *arg);
    6362static int add_device_phase1_worker_fibril(void *arg);
    64 static int create_add_device_fibril(usb_hub_port_t *port, usb_hub_info_t *hub,
     63static int create_add_device_fibril(usb_hub_port_t *port, usb_hub_dev_t *hub,
    6564    usb_speed_t speed);
    6665
     66int usb_hub_port_fini(usb_hub_port_t *port, usb_hub_dev_t *hub)
     67{
     68        assert(port);
     69        if (port->attached_device.fun)
     70                return usb_hub_port_device_gone(port, hub);
     71        return EOK;
     72}
     73/*----------------------------------------------------------------------------*/
    6774/**
    6875 * Clear feature on hub port.
    6976 *
    70  * @param hc Host controller telephone
    71  * @param address Hub address
    72  * @param port_index Port
    73  * @param feature Feature selector
     77 * @param port Port structure.
     78 * @param feature Feature selector.
    7479 * @return Operation result
    7580 */
     
    7883{
    7984        assert(port);
    80         usb_device_request_setup_packet_t clear_request = {
     85        const usb_device_request_setup_packet_t clear_request = {
    8186                .request_type = USB_HUB_REQ_TYPE_CLEAR_PORT_FEATURE,
    8287                .request = USB_DEVREQ_CLEAR_FEATURE,
     
    9095/*----------------------------------------------------------------------------*/
    9196/**
    92  * Clear feature on hub port.
    93  *
    94  * @param hc Host controller telephone
    95  * @param address Hub address
    96  * @param port_index Port
    97  * @param feature Feature selector
     97 * Set feature on hub port.
     98 *
     99 * @param port Port structure.
     100 * @param feature Feature selector.
    98101 * @return Operation result
    99102 */
     
    102105{
    103106        assert(port);
    104         usb_device_request_setup_packet_t clear_request = {
     107        const usb_device_request_setup_packet_t clear_request = {
    105108                .request_type = USB_HUB_REQ_TYPE_SET_PORT_FEATURE,
    106109                .request = USB_DEVREQ_SET_FEATURE,
     
    113116}
    114117/*----------------------------------------------------------------------------*/
     118/**
     119 * Mark reset process as failed due to external reasons
     120 *
     121 * @param port Port structure
     122 */
    115123void usb_hub_port_reset_fail(usb_hub_port_t *port)
    116124{
     
    124132/*----------------------------------------------------------------------------*/
    125133/**
    126  * Process interrupts on given hub port
     134 * Process interrupts on given port
    127135 *
    128136 * Accepts connection, over current and port reset change.
     137 * @param port port structure
    129138 * @param hub hub representation
    130  * @param port port number, starting from 1
    131  */
    132 void usb_hub_port_process_interrupt(usb_hub_port_t *port, usb_hub_info_t *hub)
     139 */
     140void usb_hub_port_process_interrupt(usb_hub_port_t *port, usb_hub_dev_t *hub)
    133141{
    134142        assert(port);
     
    171179                         * to that handler, it shall ACK the change too. */
    172180                        if (!(status & USB_HUB_PORT_C_STATUS_ENABLED)) {
    173                                 usb_hub_port_removed_device(port, hub);
     181                                usb_hub_port_device_gone(port, hub);
    174182                        }
    175183                }
     
    180188                usb_log_info("Port %zu, disabled because of errors.\n",
    181189                   port->port_number);
    182                 usb_hub_port_removed_device(port, hub);
     190                usb_hub_port_device_gone(port, hub);
    183191                const int rc = usb_hub_port_clear_feature(port,
    184192                        USB_HUB_FEATURE_C_PORT_ENABLE);
     
    238246            port->port_number, status);
    239247}
    240 
     248/*----------------------------------------------------------------------------*/
    241249/**
    242250 * routine called when a device on port has been removed
     
    245253 * Otherwise does not do anything, because DDF does not allow to remove device
    246254 * from it`s device tree.
     255 * @param port port structure
    247256 * @param hub hub representation
    248  * @param port port number, starting from 1
    249  */
    250 static void usb_hub_port_removed_device(usb_hub_port_t *port,
    251     usb_hub_info_t *hub)
     257 */
     258int usb_hub_port_device_gone(usb_hub_port_t *port, usb_hub_dev_t *hub)
    252259{
    253260        assert(port);
    254261        assert(hub);
    255         if (port->attached_device.address >= 0) {
    256                 fibril_mutex_lock(&port->mutex);
    257                 port->attached_device.address = -1;
    258                 port->attached_device.handle = 0;
    259                 fibril_mutex_unlock(&port->mutex);
    260                 usb_log_info("Removed device on port %zu.\n",
    261                     port->port_number);
    262         } else {
     262        if (port->attached_device.address < 0) {
    263263                usb_log_warning(
    264264                    "Device on port %zu removed before being registered.\n",
     
    271271                 */
    272272                usb_hub_port_reset_fail(port);
    273         }
    274 }
    275 
     273                return EOK;
     274        }
     275
     276        fibril_mutex_lock(&port->mutex);
     277        assert(port->attached_device.fun);
     278        usb_log_debug("Removing device on port %zu.\n", port->port_number);
     279        int ret = ddf_fun_unbind(port->attached_device.fun);
     280        if (ret != EOK) {
     281                usb_log_error("Failed to unbind child function on port"
     282                    " %zu: %s.\n", port->port_number, str_error(ret));
     283                fibril_mutex_unlock(&port->mutex);
     284                return ret;
     285        }
     286
     287        ddf_fun_destroy(port->attached_device.fun);
     288        port->attached_device.fun = NULL;
     289
     290        ret = usb_hc_unregister_device(&hub->connection,
     291            port->attached_device.address);
     292        if (ret != EOK) {
     293                usb_log_warning("Failed to unregister address of the removed "
     294                    "device: %s.\n", str_error(ret));
     295        }
     296        port->attached_device.address = -1;
     297        fibril_mutex_unlock(&port->mutex);
     298        usb_log_info("Removed device on port %zu.\n", port->port_number);
     299        return EOK;
     300}
     301/*----------------------------------------------------------------------------*/
    276302/**
    277303 * Process port reset change
     
    279305 * After this change port should be enabled, unless some problem occurred.
    280306 * This functions triggers second phase of enabling new device.
    281  * @param hub
    282  * @param port
    283  * @param status
    284  */
    285 static void usb_hub_port_reset_completed(usb_hub_port_t *port,
     307 * @param port Port structure
     308 * @param status Port status mask
     309 */
     310void usb_hub_port_reset_completed(usb_hub_port_t *port,
    286311    usb_port_status_t status)
    287312{
     
    313338/** Retrieve port status.
    314339 *
    315  * @param[in] ctrl_pipe Control pipe to use.
    316  * @param[in] port Port number (starting at 1).
     340 * @param[in] port Port structure
    317341 * @param[out] status Where to store the port status.
    318342 * @return Error code.
     
    358382 *
    359383 * @param port_no Port number (starting at 1).
    360  * @param arg Custom argument, points to @c usb_hub_info_t.
     384 * @param arg Custom argument, points to @c usb_hub_dev_t.
    361385 * @return Error code.
    362386 */
    363 static int enable_port_callback(int port_no, void *arg)
     387static int enable_port_callback(void *arg)
    364388{
    365389        usb_hub_port_t *port = arg;
     
    380404        fibril_mutex_unlock(&port->mutex);
    381405
    382         if (port->reset_okay) {
    383                 return EOK;
    384         } else {
    385                 return ESTALL;
    386         }
    387 }
    388 
     406        return port->reset_okay ? EOK : ESTALL;
     407}
     408/*----------------------------------------------------------------------------*/
    389409/** Fibril for adding a new device.
    390410 *
     
    395415 * @return 0 Always.
    396416 */
    397 static int add_device_phase1_worker_fibril(void *arg)
     417int add_device_phase1_worker_fibril(void *arg)
    398418{
    399419        struct add_device_phase1 *data = arg;
     
    401421
    402422        usb_address_t new_address;
    403         devman_handle_t child_handle;
     423        ddf_fun_t *child_fun;
    404424
    405425        const int rc = usb_hc_new_device_wrapper(data->hub->usb_device->ddf_dev,
    406             &data->hub->connection, data->speed,
    407             enable_port_callback, (int) data->port->port_number,
    408             data->port, &new_address, &child_handle,
    409             NULL, NULL, NULL);
     426            &data->hub->connection, data->speed, enable_port_callback,
     427            data->port, &new_address, NULL, NULL, &child_fun);
    410428
    411429        if (rc != EOK) {
     
    416434
    417435        fibril_mutex_lock(&data->port->mutex);
    418         data->port->attached_device.handle = child_handle;
     436        data->port->attached_device.fun = child_fun;
    419437        data->port->attached_device.address = new_address;
    420438        fibril_mutex_unlock(&data->port->mutex);
     
    423441            "address %d (handle %" PRIun ").\n",
    424442            data->hub->usb_device->ddf_dev->name, data->port->port_number,
    425             new_address, child_handle);
     443            new_address, child_fun->handle);
    426444
    427445leave:
     
    434452        free(arg);
    435453
    436         return EOK;
    437 }
    438 
     454        return rc;
     455}
     456/*----------------------------------------------------------------------------*/
    439457/** Start device adding when connection change is detected.
    440458 *
     
    446464 * @return Error code.
    447465 */
    448 static int create_add_device_fibril(usb_hub_port_t *port, usb_hub_info_t *hub,
     466static int create_add_device_fibril(usb_hub_port_t *port, usb_hub_dev_t *hub,
    449467    usb_speed_t speed)
    450468{
     
    452470        assert(port);
    453471        struct add_device_phase1 *data
    454             = malloc(sizeof (struct add_device_phase1));
     472            = malloc(sizeof(struct add_device_phase1));
    455473        if (data == NULL) {
    456474                return ENOMEM;
Note: See TracChangeset for help on using the changeset viewer.