Changeset bf73a02 in mainline


Ignore:
Timestamp:
2011-09-19T15:18:23Z (13 years ago)
Author:
Jan Vesely <jano.vesely@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
ea6de35
Parents:
7a05ced0
Message:

usbhub: Refactor handling of global hub events.

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

Legend:

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

    r7a05ced0 rbf73a02  
    5050/**
    5151 * structure holding hub status and changes flags.
    52  * should not be accessed directly, use supplied getter/setter methods.
    5352 *
    5453 * For more information refer to table 11.16.2.5 in
     
    5756 */
    5857typedef uint32_t usb_hub_status_t;
     58// 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
     60#define USB_HUB_STATUS_OVER_CURRENT \
     61    (1 << (USB_HUB_FEATURE_HUB_OVER_CURRENT))
     62#define USB_HUB_STATUS_LOCAL_POWER \
     63    (1 << (USB_HUB_FEATURE_HUB_LOCAL_POWER))
     64
     65#define USB_HUB_STATUS_C_OVER_CURRENT \
     66    (1 << (16 + USB_HUB_FEATURE_C_HUB_OVER_CURRENT))
     67#define USB_HUB_STATUS_C_LOCAL_POWER \
     68    (1 << (16 + USB_HUB_FEATURE_C_HUB_LOCAL_POWER))
    5969
    6070/**
     
    6474 */
    6575static inline void usb_hub_set_port_status_request(
    66     usb_device_request_setup_packet_t *request, uint16_t port) {
     76    usb_device_request_setup_packet_t *request, uint16_t port)
     77{
    6778        request->index = port;
    6879        request->request_type = USB_HUB_REQ_TYPE_GET_PORT_STATUS;
     
    7384
    7485/**
    75  * set values in request to be it a port status request
    76  * @param request
    77  * @param port
    78  */
    79 static inline void usb_hub_set_hub_status_request(
    80     usb_device_request_setup_packet_t *request) {
    81         request->index = 0;
    82         request->request_type = USB_HUB_REQ_TYPE_GET_HUB_STATUS;
    83         request->request = USB_HUB_REQUEST_GET_STATUS;
    84         request->value = 0;
    85         request->length = 4;
    86 }
    87 
    88 /**
    8986 * create request for usb hub port status
    9087 * @param port
     
    9289 */
    9390static inline usb_device_request_setup_packet_t *
    94 usb_hub_create_port_status_request(uint16_t port) {
     91    usb_hub_create_port_status_request(uint16_t port)
     92{
    9593        usb_device_request_setup_packet_t *result =
    96             malloc(sizeof (usb_device_request_setup_packet_t));
     94            malloc(sizeof(usb_device_request_setup_packet_t));
    9795        usb_hub_set_port_status_request(result, port);
    9896        return result;
     
    355353
    356354#endif  /* HUB_PORT_STATUS_H */
    357 
    358355/**
    359356 * @}
  • uspace/drv/bus/usb/usbhub/usbhub.c

    r7a05ced0 rbf73a02  
    5757#define HUB_FNC_NAME "hub"
    5858
     59/** Standard get hub global status request */
     60static const usb_device_request_setup_packet_t get_hub_status_request = {
     61        .index = 0,
     62        .request_type = USB_HUB_REQ_TYPE_GET_HUB_STATUS,
     63        .request = USB_HUB_REQUEST_GET_STATUS,
     64        .value = 0,
     65        .length = sizeof(usb_hub_status_t),
     66};
     67
    5968static int usb_set_first_configuration(usb_device_t *usb_device);
    6069static usb_hub_info_t * usb_hub_info_create(usb_device_t *usb_dev);
    6170static int usb_hub_process_hub_specific_info(usb_hub_info_t *hub_info);
    62 static int usb_process_hub_over_current(usb_hub_info_t *hub_info,
    63     usb_hub_status_t status);
    64 static int usb_process_hub_local_power_change(usb_hub_info_t *hub_info,
     71static void usb_process_hub_over_current(usb_hub_info_t *hub_info,
    6572    usb_hub_status_t status);
    6673static void usb_hub_process_global_interrupt(usb_hub_info_t *hub_info);
     
    371378 * @return error code
    372379 */
    373 static int usb_process_hub_over_current(usb_hub_info_t *hub_info,
    374     usb_hub_status_t status) {
    375         int opResult;
    376         if (usb_hub_is_status(status, USB_HUB_FEATURE_HUB_OVER_CURRENT)) {
    377                 //poweroff all ports
    378                 unsigned int port;
     380static void usb_process_hub_over_current(usb_hub_info_t *hub_info,
     381    usb_hub_status_t status)
     382{
     383        if (status & USB_HUB_STATUS_OVER_CURRENT) {
     384                /* Over-current detected on one or all ports,
     385                 * switch them all off to prevent damage. */
     386                //TODO Consider ganged power switching here.
     387                size_t port;
    379388                for (port = 1; port <= hub_info->port_count; ++port) {
    380                         opResult = usb_hub_clear_port_feature(
     389                        const int opResult = usb_hub_clear_port_feature(
    381390                            hub_info->control_pipe, port,
    382391                            USB_HUB_FEATURE_PORT_POWER);
    383392                        if (opResult != EOK) {
    384393                                usb_log_warning(
    385                                     "Cannot power off port %d;  %s\n",
     394                                    "HUB OVER-CURRENT: Cannot power off port"
     395                                    " %d:  %s\n",
    386396                                    port, str_error(opResult));
    387397                        }
    388398                }
    389399        } else {
    390                 //power all ports
    391                 unsigned int port;
     400                /* Over-current condition is gone, it is safe to turn the
     401                 * ports on. */
     402                size_t port;
    392403                for (port = 1; port <= hub_info->port_count; ++port) {
    393                         opResult = usb_hub_set_port_feature(
     404                        const int opResult = usb_hub_set_port_feature(
    394405                            hub_info->control_pipe, port,
    395406                            USB_HUB_FEATURE_PORT_POWER);
    396407                        if (opResult != EOK) {
    397408                                usb_log_warning(
    398                                     "Cannot power off port %d;  %s\n",
     409                                    "HUB OVER-CURRENT GONE: Cannot power on "
     410                                    "port %d;  %s\n",
    399411                                    port, str_error(opResult));
    400412                        }
    401413                }
    402414        }
    403         return opResult;
    404 }
    405 
    406 /**
    407  * process hub local power change
    408  *
    409  * This change is ignored.
    410  * @param hub_info hub instance
    411  * @param status hub status bitmask
    412  * @return error code
    413  */
    414 static int usb_process_hub_local_power_change(usb_hub_info_t *hub_info,
    415     usb_hub_status_t status) {
    416         int opResult = EOK;
    417         opResult = usb_hub_clear_feature(hub_info->control_pipe,
    418             USB_HUB_FEATURE_C_HUB_LOCAL_POWER);
    419         if (opResult != EOK) {
    420                 usb_log_error("Cannnot clear hub power change flag: "
    421                     "%s\n",
    422                     str_error(opResult));
    423         }
    424         return opResult;
    425 }
    426 
     415}
     416/*----------------------------------------------------------------------------*/
    427417/**
    428418 * process hub interrupts
     
    432422 * @param hub_info hub instance
    433423 */
    434 static void usb_hub_process_global_interrupt(usb_hub_info_t *hub_info) {
     424static void usb_hub_process_global_interrupt(usb_hub_info_t *hub_info)
     425{
     426        assert(hub_info);
     427        assert(hub_info->usb_device);
    435428        usb_log_debug("Global interrupt on a hub\n");
    436         usb_pipe_t *pipe = hub_info->control_pipe;
     429        usb_pipe_t *ctrlpipe = &hub_info->usb_device->ctrl_pipe;
    437430        int opResult;
    438431
    439         usb_port_status_t status;
     432        usb_hub_status_t status;
    440433        size_t rcvd_size;
    441         usb_device_request_setup_packet_t request;
    442         //int opResult;
    443         usb_hub_set_hub_status_request(&request);
    444         //endpoint 0
    445434
    446435        opResult = usb_pipe_control_read(
    447             pipe,
    448             &request, sizeof (usb_device_request_setup_packet_t),
    449             &status, 4, &rcvd_size
    450             );
     436            ctrlpipe, &get_hub_status_request, sizeof(get_hub_status_request),
     437            &status, sizeof(usb_hub_status_t), &rcvd_size);
    451438        if (opResult != EOK) {
    452439                usb_log_error("Could not get hub status: %s\n",
     
    454441                return;
    455442        }
    456         if (rcvd_size != sizeof (usb_port_status_t)) {
     443        if (rcvd_size != sizeof(usb_hub_status_t)) {
    457444                usb_log_error("Received status has incorrect size\n");
    458445                return;
    459446        }
    460         //port reset
    461         if (
    462             usb_hub_is_status(status, 16 + USB_HUB_FEATURE_C_HUB_OVER_CURRENT)) {
     447
     448        /* Handle status changes */
     449        if (status & USB_HUB_STATUS_C_OVER_CURRENT)
    463450                usb_process_hub_over_current(hub_info, status);
    464         }
    465         if (
    466             usb_hub_is_status(status, 16 + USB_HUB_FEATURE_C_HUB_LOCAL_POWER)) {
    467                 usb_process_hub_local_power_change(hub_info, status);
     451
     452        if (status & USB_HUB_STATUS_C_LOCAL_POWER) {
     453                /* NOTE: Handling this is more complicated.
     454                 * If the transition is from bus power to local power, all
     455                 * is good and we may signal the parent hub that we don't
     456                 * need the power.
     457                 * If the transition is from local power to bus power
     458                 * the hub should turn off all the ports and devices need
     459                 * to be reinitialized taking into account the limited power
     460                 * that is now available.
     461                 * There is no support for power distribution in HelenOS,
     462                 * (or other OSes/hub devices that I've seen) so this is not
     463                 * implemented.
     464                 * Just ACK the change.
     465                 */
     466                const int opResult = usb_hub_clear_feature(ctrlpipe,
     467                    USB_HUB_FEATURE_C_HUB_LOCAL_POWER);
     468                if (opResult != EOK) {
     469                        usb_log_error("Cannot clear hub power change flag: "
     470                            "%s\n",
     471                            str_error(opResult));
     472                }
    468473        }
    469474}
Note: See TracChangeset for help on using the changeset viewer.