Changeset d6e2938 in mainline


Ignore:
Timestamp:
2011-09-23T12:17:27Z (13 years ago)
Author:
Jan Vesely <jano.vesely@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
48a31be
Parents:
bba0f1fc
Message:

usbhub: Refactor handling of port changes.

Location:
uspace/drv/bus/usb/usbhub
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • uspace/drv/bus/usb/usbhub/port_status.h

    rbba0f1fc rd6e2938  
    4747 */
    4848typedef uint32_t usb_port_status_t;
     49// TODO Mind the endiannes, changes are in the first byte of the second word
     50// status is in the first byte of the first word
     51#define USB_HUB_PORT_STATUS_CONNECTION (1 << (USB_HUB_FEATURE_PORT_CONNECTION))
     52#define USB_HUB_PORT_STATUS_ENABLED (1 << (USB_HUB_FEATURE_PORT_ENABLE))
     53#define USB_HUB_PORT_STATUS_SUSPEND (1 << (USB_HUB_FEATURE_PORT_SUSPEND))
     54#define USB_HUB_PORT_STATUS_OC (1 << (USB_HUB_FEATURE_PORT_OVER_CURRENT))
     55#define USB_HUB_PORT_STATUS_RESET (1 << (USB_HUB_FEATURE_PORT_RESET))
     56#define USB_HUB_PORT_STATUS_POWER (1 << (USB_HUB_FEATURE_PORT_POWER))
     57#define USB_HUB_PORT_STATUS_LOW_SPEED (1 << (USB_HUB_FEATURE_PORT_LOW_SPEED))
     58
     59#define USB_HUB_PORT_C_STATUS_CONNECTION \
     60    (1 << (USB_HUB_FEATURE_C_PORT_CONNECTION))
     61#define USB_HUB_PORT_C_STATUS_ENABLED \
     62    (1 << (USB_HUB_FEATURE_C_PORT_ENABLE))
     63#define USB_HUB_PORT_C_STATUS_SUSPEND \
     64    (1 << (USB_HUB_FEATURE_C_PORT_SUSPEND))
     65#define USB_HUB_PORT_C_STATUS_OC \
     66    (1 << (USB_HUB_FEATURE_C_PORT_OVER_CURRENT))
     67#define USB_HUB_PORT_C_STATUS_RESET \
     68    (1 << (USB_HUB_FEATURE_C_PORT_RESET))
    4969
    5070/**
     
    5777typedef uint32_t usb_hub_status_t;
    5878// TODO Mind the endiannes, changes are in the first byte of the second word
    59 // status is int he first byte of the first word
     79// status is in the first byte of the first word
    6080#define USB_HUB_STATUS_OVER_CURRENT \
    6181    (1 << (USB_HUB_FEATURE_HUB_OVER_CURRENT))
  • uspace/drv/bus/usb/usbhub/ports.c

    rbba0f1fc rd6e2938  
    5454};
    5555
    56 /**
    57  * count of port status changes that are not explicitly handled by
    58  * any function here and must be cleared by hand
    59  */
    60 static const unsigned int non_handled_changes_count = 2;
    61 
    62 /**
    63  * port status changes that are not explicitly handled by
    64  * any function here and must be cleared by hand
    65  */
    66 static const int non_handled_changes[] = {
    67         USB_HUB_FEATURE_C_PORT_ENABLE,
    68         USB_HUB_FEATURE_C_PORT_SUSPEND
    69 };
    70 
    71 static void usb_hub_removed_device(
    72     usb_hub_info_t *hub, uint16_t port);
    73 
     56static void usb_hub_removed_device(usb_hub_info_t *hub, size_t port);
    7457static void usb_hub_port_reset_completed(usb_hub_info_t *hub,
    7558    uint16_t port, uint32_t status);
    76 
    77 static void usb_hub_port_over_current(usb_hub_info_t *hub,
    78     uint16_t port, uint32_t status);
    79 
    8059static int get_port_status(usb_pipe_t *ctrl_pipe, size_t port,
    8160    usb_port_status_t *status);
    82 
    8361static int enable_port_callback(int port_no, void *arg);
    84 
    8562static int add_device_phase1_worker_fibril(void *arg);
    86 
    8763static int create_add_device_fibril(usb_hub_info_t *hub, size_t port,
    8864    usb_speed_t speed);
     
    9571 * @param port port number, starting from 1
    9672 */
    97 void usb_hub_process_port_interrupt(usb_hub_info_t *hub, uint16_t port)
    98 {
    99         usb_log_debug("Interrupt at port %zu\n", (size_t) port);
     73void usb_hub_process_port_interrupt(usb_hub_info_t *hub, size_t port)
     74{
     75        usb_log_debug("Interrupt at port %zu\n", port);
    10076
    10177        usb_port_status_t status;
     
    10480        if (opResult != EOK) {
    10581                usb_log_error("Failed to get port %zu status: %s.\n",
    106                     (size_t) port, str_error(opResult));
     82                    port, str_error(opResult));
    10783                return;
    10884        }
    109         //connection change
    110         if (usb_port_is_status(status, USB_HUB_FEATURE_C_PORT_CONNECTION)) {
    111                 bool device_connected = usb_port_is_status(status,
    112                     USB_HUB_FEATURE_PORT_CONNECTION);
    113                 usb_log_debug("Connection change on port %zu: %s.\n",
    114                     (size_t) port,
    115                     device_connected ? "device attached" : "device removed");
     85
     86        /* Connection change */
     87        if (status & USB_HUB_PORT_C_STATUS_CONNECTION) {
     88                const bool device_connected =
     89                    (status & USB_HUB_PORT_STATUS_CONNECTION) != 0;
     90                usb_log_debug("Connection change on port %zu: device %s.\n",
     91                    port, device_connected ? "attached" : "removed");
     92                /* ACK the change */
     93                const int opResult =
     94                    usb_hub_clear_port_feature(hub->control_pipe,
     95                    port, USB_HUB_FEATURE_C_PORT_CONNECTION);
     96                if (opResult != EOK) {
     97                        usb_log_warning("Failed to clear "
     98                            "port-change-connection flag: %s.\n",
     99                            str_error(opResult));
     100                }
    116101
    117102                if (device_connected) {
     
    121106                                usb_log_error(
    122107                                    "Cannot handle change on port %zu: %s.\n",
    123                                     (size_t) port, str_error(opResult));
     108                                    port, str_error(opResult));
    124109                        }
    125110                } else {
     
    127112                }
    128113        }
    129         //over current
    130         if (usb_port_is_status(status, USB_HUB_FEATURE_C_PORT_OVER_CURRENT)) {
    131                 //check if it was not auto-resolved
    132                 usb_log_debug("Overcurrent change on port\n");
    133                 usb_hub_port_over_current(hub, port, status);
    134         }
    135         //port reset
    136         if (usb_port_is_status(status, USB_HUB_FEATURE_C_PORT_RESET)) {
     114
     115        /* Enable change, ports are automatically disabled on errors. */
     116        if (status & USB_HUB_PORT_C_STATUS_ENABLED) {
     117                // TODO: Remove device that was connected
     118                // TODO: Clear feature C_PORT_ENABLE
     119
     120        }
     121
     122        /* Suspend change */
     123        if (status & USB_HUB_PORT_C_STATUS_SUSPEND) {
     124                usb_log_error("Port %zu went to suspend state, this should"
     125                    "NOT happen as we do not support suspend state!", port);
     126                // TODO: Clear feature C_PORT_SUSPEND
     127        }
     128
     129        /* Over current */
     130        if (status & USB_HUB_PORT_C_STATUS_OC) {
     131                /* According to the USB specs:
     132                 * 11.13.5 Over-current Reporting and Recovery
     133                 * Hub device is responsible for putting port in power off
     134                 * mode. USB system software is responsible for powering port
     135                 * back on when the over-curent condition is gone */
     136                if (!(status & ~USB_HUB_PORT_STATUS_OC)) {
     137                        // TODO: Power port on, this will cause connect
     138                        // change and device initialization.
     139                }
     140                // TODO: Ack over-power change.
     141        }
     142
     143        /* Port reset, set on port reset complete. */
     144        if (status & USB_HUB_PORT_C_STATUS_RESET) {
    137145                usb_hub_port_reset_completed(hub, port, status);
    138146        }
    139         usb_log_debug("Port %d status 0x%08" PRIx32 "\n", (int) port, status);
    140 
    141         usb_port_status_set_bit(
    142             &status, USB_HUB_FEATURE_C_PORT_CONNECTION, false);
    143         usb_port_status_set_bit(
    144             &status, USB_HUB_FEATURE_C_PORT_RESET, false);
    145         usb_port_status_set_bit(
    146             &status, USB_HUB_FEATURE_C_PORT_OVER_CURRENT, false);
    147 
    148         //clearing not yet handled changes     
    149         unsigned int feature_idx;
    150         for (feature_idx = 0;
    151             feature_idx < non_handled_changes_count;
    152             ++feature_idx) {
    153                 unsigned int bit_idx = non_handled_changes[feature_idx];
    154                 if (status & (1 << bit_idx)) {
    155                         usb_log_info(
    156                             "There was not yet handled change on port %d: %d"
    157                             ";clearing it\n",
    158                             port, bit_idx);
    159                         int opResult = usb_hub_clear_port_feature(
    160                             hub->control_pipe,
    161                             port, bit_idx);
    162                         if (opResult != EOK) {
    163                                 usb_log_warning(
    164                                     "Could not clear port flag %d: %s\n",
    165                                     bit_idx, str_error(opResult)
    166                                     );
    167                         }
    168                         usb_port_status_set_bit(
    169                             &status, bit_idx, false);
    170                 }
    171         }
    172         if (status >> 16) {
    173                 usb_log_info("There is still some unhandled change %X\n",
    174                     status);
    175         }
     147
     148        usb_log_debug("Port %zu status 0x%08" PRIx32 "\n", port, status);
    176149}
    177150
     
    185158 * @param port port number, starting from 1
    186159 */
    187 static void usb_hub_removed_device(
    188     usb_hub_info_t *hub, uint16_t port) {
    189 
    190         int opResult = usb_hub_clear_port_feature(hub->control_pipe,
    191             port, USB_HUB_FEATURE_C_PORT_CONNECTION);
    192         if (opResult != EOK) {
    193                 usb_log_warning("Could not clear port-change-connection flag\n");
    194         }
     160static void usb_hub_removed_device(usb_hub_info_t *hub, size_t port)
     161{
     162
    195163        /** \TODO remove device from device manager - not yet implemented in
    196164         * devide manager
     
    237205 */
    238206static void usb_hub_port_reset_completed(usb_hub_info_t *hub,
    239     uint16_t port, uint32_t status) {
     207    uint16_t port, uint32_t status)
     208{
    240209        usb_log_debug("Port %zu reset complete.\n", (size_t) port);
    241210        if (usb_port_is_status(status, USB_HUB_FEATURE_PORT_ENABLE)) {
     
    261230}
    262231
    263 /**
    264  * Process over current condition on port.
    265  *
    266  * Turn off the power on the port.
    267  *
    268  * @param hub hub representation
    269  * @param port port number, starting from 1
    270  */
    271 static void usb_hub_port_over_current(usb_hub_info_t *hub,
    272     uint16_t port, uint32_t status) {
    273         int opResult;
    274         if (usb_port_is_status(status, USB_HUB_FEATURE_PORT_OVER_CURRENT)) {
    275                 opResult = usb_hub_clear_port_feature(hub->control_pipe,
    276                     port, USB_HUB_FEATURE_PORT_POWER);
    277                 if (opResult != EOK) {
    278                         usb_log_error("Cannot power off port %d; %s\n",
    279                             port, str_error(opResult));
    280                 }
    281         } else {
    282                 opResult = usb_hub_set_port_feature(hub->control_pipe,
    283                     port, USB_HUB_FEATURE_PORT_POWER);
    284                 if (opResult != EOK) {
    285                         usb_log_error("Cannot power on port %d; %s\n",
    286                             port, str_error(opResult));
    287                 }
    288         }
    289 }
    290 
    291232/** Retrieve port status.
    292233 *
     
    301242        size_t recv_size;
    302243        usb_port_status_t status_tmp;
    303         /* USB hub specific GET_PORT_STATUS request. See USB Spec 11.16.2.6 */
     244        /* USB hub specific GET_PORT_STATUS request. See USB Spec 11.16.2.6
     245         * Generic GET_STATUS request cannot be used because of the difference
     246         * in status data size (2B vs. 4B)*/
    304247        const usb_device_request_setup_packet_t request = {
    305248                .request_type = USB_HUB_REQ_TYPE_GET_PORT_STATUS,
     
    327270        return EOK;
    328271}
    329 
     272/*----------------------------------------------------------------------------*/
    330273/** Callback for enabling a specific port.
    331274 *
     
    337280 * @return Error code.
    338281 */
    339 static int enable_port_callback(int port_no, void *arg) {
     282static int enable_port_callback(int port_no, void *arg)
     283{
    340284        usb_hub_info_t *hub = arg;
    341         int rc;
     285        assert(hub);
     286        usb_hub_port_t *my_port = hub->ports + port_no;
     287
    342288        usb_device_request_setup_packet_t request;
    343         usb_hub_port_t *my_port = hub->ports + port_no;
    344 
    345289        usb_hub_set_reset_port_request(&request, port_no);
    346         rc = usb_pipe_control_write(hub->control_pipe,
     290
     291        const int rc = usb_pipe_control_write(hub->control_pipe,
    347292            &request, sizeof (request), NULL, 0);
    348293        if (rc != EOK) {
     
    375320 * @return 0 Always.
    376321 */
    377 static int add_device_phase1_worker_fibril(void *arg) {
    378         struct add_device_phase1 *data
    379             = (struct add_device_phase1 *) arg;
     322static int add_device_phase1_worker_fibril(void *arg)
     323{
     324        struct add_device_phase1 *data = arg;
     325        assert(data);
    380326
    381327        usb_address_t new_address;
    382328        devman_handle_t child_handle;
    383329
    384         int rc = usb_hc_new_device_wrapper(data->hub->usb_device->ddf_dev,
     330        const int rc = usb_hc_new_device_wrapper(data->hub->usb_device->ddf_dev,
    385331            &data->hub->connection, data->speed,
    386332            enable_port_callback, (int) data->port, data->hub,
     
    427373 */
    428374static int create_add_device_fibril(usb_hub_info_t *hub, size_t port,
    429     usb_speed_t speed) {
     375    usb_speed_t speed)
     376{
    430377        struct add_device_phase1 *data
    431378            = malloc(sizeof (struct add_device_phase1));
     
    443390        fibril_mutex_unlock(&the_port->reset_mutex);
    444391
    445         int rc = usb_hub_clear_port_feature(hub->control_pipe, port,
    446             USB_HUB_FEATURE_C_PORT_CONNECTION);
    447         if (rc != EOK) {
    448                 free(data);
    449                 usb_log_warning("Failed to clear port change flag: %s.\n",
    450                     str_error(rc));
    451                 return rc;
    452         }
    453 
    454392        fid_t fibril = fibril_create(add_device_phase1_worker_fibril, data);
    455393        if (fibril == 0) {
  • uspace/drv/bus/usb/usbhub/ports.h

    rbba0f1fc rd6e2938  
    7272
    7373
    74 void usb_hub_process_port_interrupt(usb_hub_info_t *hub, uint16_t port);
     74void usb_hub_process_port_interrupt(usb_hub_info_t *hub, size_t port);
    7575
    7676
Note: See TracChangeset for help on using the changeset viewer.