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

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
        !           198: usb_setup()
        !           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.