Annotation of qemu/roms/seabios/src/usb-hub.c, revision 1.1.1.1

1.1       root        1: // Code for handling standard USB hubs.
                      2: //
                      3: // Copyright (C) 2010  Kevin O'Connor <[email protected]>
                      4: //
                      5: // This file may be distributed under the terms of the GNU LGPLv3 license.
                      6: 
                      7: #include "util.h" // dprintf
                      8: #include "config.h" // CONFIG_USB_HUB
                      9: #include "usb-hub.h" // struct usb_hub_descriptor
                     10: #include "usb.h" // struct usb_s
                     11: 
                     12: static int
                     13: get_hub_desc(struct usb_pipe *pipe, struct usb_hub_descriptor *desc)
                     14: {
                     15:     struct usb_ctrlrequest req;
                     16:     req.bRequestType = USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_DEVICE;
                     17:     req.bRequest = USB_REQ_GET_DESCRIPTOR;
                     18:     req.wValue = USB_DT_HUB<<8;
                     19:     req.wIndex = 0;
                     20:     req.wLength = sizeof(*desc);
                     21:     return send_default_control(pipe, &req, desc);
                     22: }
                     23: 
                     24: static int
                     25: set_port_feature(struct usbhub_s *hub, int port, int feature)
                     26: {
                     27:     struct usb_ctrlrequest req;
                     28:     req.bRequestType = USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_OTHER;
                     29:     req.bRequest = USB_REQ_SET_FEATURE;
                     30:     req.wValue = feature;
                     31:     req.wIndex = port + 1;
                     32:     req.wLength = 0;
                     33:     mutex_lock(&hub->lock);
                     34:     int ret = send_default_control(hub->pipe, &req, NULL);
                     35:     mutex_unlock(&hub->lock);
                     36:     return ret;
                     37: }
                     38: 
                     39: static int
                     40: clear_port_feature(struct usbhub_s *hub, int port, int feature)
                     41: {
                     42:     struct usb_ctrlrequest req;
                     43:     req.bRequestType = USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_OTHER;
                     44:     req.bRequest = USB_REQ_CLEAR_FEATURE;
                     45:     req.wValue = feature;
                     46:     req.wIndex = port + 1;
                     47:     req.wLength = 0;
                     48:     mutex_lock(&hub->lock);
                     49:     int ret = send_default_control(hub->pipe, &req, NULL);
                     50:     mutex_unlock(&hub->lock);
                     51:     return ret;
                     52: }
                     53: 
                     54: static int
                     55: get_port_status(struct usbhub_s *hub, int port, struct usb_port_status *sts)
                     56: {
                     57:     struct usb_ctrlrequest req;
                     58:     req.bRequestType = USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_OTHER;
                     59:     req.bRequest = USB_REQ_GET_STATUS;
                     60:     req.wValue = 0;
                     61:     req.wIndex = port + 1;
                     62:     req.wLength = sizeof(*sts);
                     63:     mutex_lock(&hub->lock);
                     64:     int ret = send_default_control(hub->pipe, &req, sts);
                     65:     mutex_unlock(&hub->lock);
                     66:     return ret;
                     67: }
                     68: 
                     69: // Check if device attached to port
                     70: static int
                     71: usb_hub_detect(struct usbhub_s *hub, u32 port)
                     72: {
                     73:     // Turn on power to port.
                     74:     int ret = set_port_feature(hub, port, USB_PORT_FEAT_POWER);
                     75:     if (ret)
                     76:         goto fail;
                     77: 
                     78:     // Wait for port power to stabilize.
                     79:     msleep(hub->powerwait);
                     80: 
                     81:     // Check periodically for a device connect.
                     82:     struct usb_port_status sts;
                     83:     u64 end = calc_future_tsc(USB_TIME_SIGATT);
                     84:     for (;;) {
                     85:         ret = get_port_status(hub, port, &sts);
                     86:         if (ret)
                     87:             goto fail;
                     88:         if (sts.wPortStatus & USB_PORT_STAT_CONNECTION)
                     89:             // Device connected.
                     90:             break;
                     91:         if (check_tsc(end))
                     92:             // No device found.
                     93:             return -1;
                     94:         msleep(5);
                     95:     }
                     96: 
                     97:     // XXX - wait USB_TIME_ATTDB time?
                     98: 
                     99:     return 0;
                    100: 
                    101: fail:
                    102:     dprintf(1, "Failure on hub port %d detect\n", port);
                    103:     return -1;
                    104: }
                    105: 
                    106: // Disable port
                    107: static void
                    108: usb_hub_disconnect(struct usbhub_s *hub, u32 port)
                    109: {
                    110:     int ret = clear_port_feature(hub, port, USB_PORT_FEAT_ENABLE);
                    111:     if (ret)
                    112:         dprintf(1, "Failure on hub port %d disconnect\n", port);
                    113: }
                    114: 
                    115: // Reset device on port
                    116: static int
                    117: usb_hub_reset(struct usbhub_s *hub, u32 port)
                    118: {
                    119:     int ret = set_port_feature(hub, port, USB_PORT_FEAT_RESET);
                    120:     if (ret)
                    121:         goto fail;
                    122: 
                    123:     // Wait for reset to complete.
                    124:     struct usb_port_status sts;
                    125:     u64 end = calc_future_tsc(USB_TIME_DRST * 2);
                    126:     for (;;) {
                    127:         ret = get_port_status(hub, port, &sts);
                    128:         if (ret)
                    129:             goto fail;
                    130:         if (!(sts.wPortStatus & USB_PORT_STAT_RESET))
                    131:             break;
                    132:         if (check_tsc(end)) {
                    133:             warn_timeout();
                    134:             goto fail;
                    135:         }
                    136:         msleep(5);
                    137:     }
                    138: 
                    139:     // Reset complete.
                    140:     if (!(sts.wPortStatus & USB_PORT_STAT_CONNECTION))
                    141:         // Device no longer present
                    142:         return -1;
                    143: 
                    144:     return ((sts.wPortStatus & USB_PORT_STAT_SPEED_MASK)
                    145:             >> USB_PORT_STAT_SPEED_SHIFT);
                    146: 
                    147: fail:
                    148:     dprintf(1, "Failure on hub port %d reset\n", port);
                    149:     usb_hub_disconnect(hub, port);
                    150:     return -1;
                    151: }
                    152: 
                    153: static struct usbhub_op_s HubOp = {
                    154:     .detect = usb_hub_detect,
                    155:     .reset = usb_hub_reset,
                    156:     .disconnect = usb_hub_disconnect,
                    157: };
                    158: 
                    159: // Configure a usb hub and then find devices connected to it.
                    160: int
                    161: usb_hub_init(struct usb_pipe *pipe)
                    162: {
                    163:     ASSERT32FLAT();
                    164:     if (!CONFIG_USB_HUB)
                    165:         return -1;
                    166: 
                    167:     struct usb_hub_descriptor desc;
                    168:     int ret = get_hub_desc(pipe, &desc);
                    169:     if (ret)
                    170:         return ret;
                    171: 
                    172:     struct usbhub_s hub;
                    173:     memset(&hub, 0, sizeof(hub));
                    174:     hub.pipe = pipe;
                    175:     hub.cntl = pipe->cntl;
                    176:     hub.powerwait = desc.bPwrOn2PwrGood * 2;
                    177:     hub.portcount = desc.bNbrPorts;
                    178:     hub.op = &HubOp;
                    179:     usb_enumerate(&hub);
                    180: 
                    181:     dprintf(1, "Initialized USB HUB (%d ports used)\n", hub.devcount);
                    182:     if (hub.devcount)
                    183:         return 0;
                    184:     return -1;
                    185: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.