Annotation of qemu/roms/seabios/src/usb-hub.c, revision 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.