Changeset bf73a02 in mainline for uspace/drv/bus/usb/usbhub/usbhub.c


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.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • 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.