Annotation of qemu/roms/seabios/src/usb.c, revision 1.1.1.2

1.1       root        1: // Main code for handling USB controllers and devices.
                      2: //
                      3: // Copyright (C) 2009  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 "pci.h" // foreachpci
                      9: #include "config.h" // CONFIG_*
                     10: #include "pci_regs.h" // PCI_CLASS_REVISION
                     11: #include "pci_ids.h" // PCI_CLASS_SERIAL_USB_UHCI
                     12: #include "usb-uhci.h" // uhci_init
                     13: #include "usb-ohci.h" // ohci_init
                     14: #include "usb-hid.h" // usb_keyboard_setup
                     15: #include "usb.h" // struct usb_s
                     16: #include "biosvar.h" // GET_GLOBAL
                     17: 
                     18: struct usb_s USBControllers[16] VAR16VISIBLE;
                     19: 
                     20: static int
                     21: send_control(u32 endp, int dir, const void *cmd, int cmdsize
                     22:              , void *data, int datasize)
                     23: {
                     24:     struct usb_s *cntl = endp2cntl(endp);
                     25:     switch (cntl->type) {
                     26:     default:
                     27:     case USB_TYPE_UHCI:
                     28:         return uhci_control(endp, dir, cmd, cmdsize, data, datasize);
                     29:     case USB_TYPE_OHCI:
                     30:         return ohci_control(endp, dir, cmd, cmdsize, data, datasize);
                     31:     }
                     32: }
                     33: 
                     34: struct usb_pipe *
                     35: alloc_intr_pipe(u32 endp, int period)
                     36: {
                     37:     struct usb_s *cntl = endp2cntl(endp);
                     38:     switch (cntl->type) {
                     39:     default:
                     40:     case USB_TYPE_UHCI:
                     41:         return uhci_alloc_intr_pipe(endp, period);
                     42:     case USB_TYPE_OHCI:
                     43:         return ohci_alloc_intr_pipe(endp, period);
                     44:     }
                     45: }
                     46: 
                     47: int
                     48: usb_poll_intr(struct usb_pipe *pipe, void *data)
                     49: {
                     50:     u32 endp = GET_FLATPTR(pipe->endp);
                     51:     struct usb_s *cntl = endp2cntl(endp);
                     52:     switch (GET_GLOBAL(cntl->type)) {
                     53:     default:
                     54:     case USB_TYPE_UHCI:
                     55:         return uhci_poll_intr(pipe, data);
                     56:     case USB_TYPE_OHCI:
                     57:         return ohci_poll_intr(pipe, data);
                     58:     }
                     59: }
                     60: 
                     61: int
                     62: send_default_control(u32 endp, const struct usb_ctrlrequest *req, void *data)
                     63: {
                     64:     return send_control(endp, req->bRequestType & USB_DIR_IN
                     65:                         , req, sizeof(*req), data, req->wLength);
                     66: }
                     67: 
                     68: // Get the first 8 bytes of the device descriptor.
                     69: static int
                     70: get_device_info8(struct usb_device_descriptor *dinfo, u32 endp)
                     71: {
                     72:     struct usb_ctrlrequest req;
                     73:     req.bRequestType = USB_DIR_IN | USB_TYPE_STANDARD | USB_RECIP_DEVICE;
                     74:     req.bRequest = USB_REQ_GET_DESCRIPTOR;
                     75:     req.wValue = USB_DT_DEVICE<<8;
                     76:     req.wIndex = 0;
                     77:     req.wLength = 8;
                     78:     return send_default_control(endp, &req, dinfo);
                     79: }
                     80: 
                     81: static struct usb_config_descriptor *
                     82: get_device_config(u32 endp)
                     83: {
                     84:     struct usb_config_descriptor cfg;
                     85: 
                     86:     struct usb_ctrlrequest req;
                     87:     req.bRequestType = USB_DIR_IN | USB_TYPE_STANDARD | USB_RECIP_DEVICE;
                     88:     req.bRequest = USB_REQ_GET_DESCRIPTOR;
                     89:     req.wValue = USB_DT_CONFIG<<8;
                     90:     req.wIndex = 0;
                     91:     req.wLength = sizeof(cfg);
                     92:     int ret = send_default_control(endp, &req, &cfg);
                     93:     if (ret)
                     94:         return NULL;
                     95: 
                     96:     void *config = malloc_tmphigh(cfg.wTotalLength);
                     97:     if (!config)
                     98:         return NULL;
                     99:     req.wLength = cfg.wTotalLength;
                    100:     ret = send_default_control(endp, &req, config);
                    101:     if (ret)
                    102:         return NULL;
                    103:     //hexdump(config, cfg.wTotalLength);
                    104:     return config;
                    105: }
                    106: 
                    107: static u32
                    108: set_address(u32 endp)
                    109: {
                    110:     dprintf(3, "set_address %x\n", endp);
                    111:     struct usb_s *cntl = endp2cntl(endp);
                    112:     if (cntl->maxaddr >= USB_MAXADDR)
                    113:         return 0;
                    114: 
                    115:     struct usb_ctrlrequest req;
                    116:     req.bRequestType = USB_DIR_OUT | USB_TYPE_STANDARD | USB_RECIP_DEVICE;
                    117:     req.bRequest = USB_REQ_SET_ADDRESS;
                    118:     req.wValue = cntl->maxaddr + 1;
                    119:     req.wIndex = 0;
                    120:     req.wLength = 0;
                    121:     int ret = send_default_control(endp, &req, NULL);
                    122:     if (ret)
                    123:         return 0;
                    124:     msleep(2);
                    125: 
                    126:     cntl->maxaddr++;
                    127:     return mkendp(cntl, cntl->maxaddr, 0, endp2speed(endp), endp2maxsize(endp));
                    128: }
                    129: 
                    130: static int
                    131: set_configuration(u32 endp, u16 val)
                    132: {
                    133:     struct usb_ctrlrequest req;
                    134:     req.bRequestType = USB_DIR_OUT | USB_TYPE_STANDARD | USB_RECIP_DEVICE;
                    135:     req.bRequest = USB_REQ_SET_CONFIGURATION;
                    136:     req.wValue = val;
                    137:     req.wIndex = 0;
                    138:     req.wLength = 0;
                    139:     return send_default_control(endp, &req, NULL);
                    140: }
                    141: 
                    142: // Called for every found device - see if a driver is available for
                    143: // this device and do setup if so.
                    144: int
                    145: configure_usb_device(struct usb_s *cntl, int lowspeed)
                    146: {
                    147:     dprintf(1, "config_usb: %p %d\n", cntl, lowspeed);
                    148: 
                    149:     // Get device info
                    150:     u32 endp = mkendp(cntl, 0, 0, lowspeed, 8);
                    151:     struct usb_device_descriptor dinfo;
                    152:     int ret = get_device_info8(&dinfo, endp);
                    153:     if (ret)
                    154:         return 0;
                    155:     dprintf(3, "device rev=%04x cls=%02x sub=%02x proto=%02x size=%02x\n"
                    156:             , dinfo.bcdUSB, dinfo.bDeviceClass, dinfo.bDeviceSubClass
                    157:             , dinfo.bDeviceProtocol, dinfo.bMaxPacketSize0);
                    158:     if (dinfo.bMaxPacketSize0 < 8 || dinfo.bMaxPacketSize0 > 64)
                    159:         return 0;
                    160:     endp = mkendp(cntl, 0, 0, lowspeed, dinfo.bMaxPacketSize0);
                    161: 
                    162:     // Get configuration
                    163:     struct usb_config_descriptor *config = get_device_config(endp);
                    164:     if (!config)
                    165:         return 0;
                    166: 
                    167:     // Determine if a driver exists for this device - only look at the
                    168:     // first interface of the first configuration.
                    169:     struct usb_interface_descriptor *iface = (void*)(&config[1]);
                    170:     if (iface->bInterfaceClass != USB_CLASS_HID
                    171:         || iface->bInterfaceSubClass != USB_INTERFACE_SUBCLASS_BOOT
                    172:         || iface->bInterfaceProtocol != USB_INTERFACE_PROTOCOL_KEYBOARD)
                    173:         // Not a "boot" keyboard
                    174:         goto fail;
                    175: 
                    176:     // Set the address and configure device.
                    177:     endp = set_address(endp);
                    178:     if (!endp)
                    179:         goto fail;
                    180:     ret = set_configuration(endp, config->bConfigurationValue);
                    181:     if (ret)
                    182:         goto fail;
                    183: 
                    184:     // Configure driver.
                    185:     ret = usb_keyboard_init(endp, iface, ((void*)config + config->wTotalLength
                    186:                                           - (void*)iface));
                    187:     if (ret)
                    188:         goto fail;
                    189: 
                    190:     free(config);
                    191:     return 1;
                    192: fail:
                    193:     free(config);
                    194:     return 0;
                    195: }
                    196: 
                    197: void
1.1.1.2 ! root      198: usb_setup(void)
1.1       root      199: {
                    200:     if (! CONFIG_USB)
                    201:         return;
                    202: 
                    203:     dprintf(3, "init usb\n");
                    204: 
                    205:     usb_keyboard_setup();
                    206: 
                    207:     // Look for USB controllers
                    208:     int count = 0;
                    209:     int bdf, max;
                    210:     foreachpci(bdf, max) {
                    211:         u32 code = pci_config_readl(bdf, PCI_CLASS_REVISION) >> 8;
                    212: 
                    213:         if (code >> 8 != PCI_CLASS_SERIAL_USB)
                    214:             continue;
                    215: 
                    216:         struct usb_s *cntl = &USBControllers[count];
                    217:         cntl->bdf = bdf;
                    218: 
                    219:         if (code == PCI_CLASS_SERIAL_USB_UHCI)
                    220:             run_thread(uhci_init, cntl);
                    221:         else if (code == PCI_CLASS_SERIAL_USB_OHCI)
                    222:             run_thread(ohci_init, cntl);
                    223:         else
                    224:             continue;
                    225: 
                    226:         count++;
                    227:         if (count >= ARRAY_SIZE(USBControllers))
                    228:             break;
                    229:     }
                    230: }

unix.superglobalmegacorp.com

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