// The USB core: everything between "the controller can talk to a device" and // "a driver knows what the device is". // // The split matters. xhci.c deals in TRBs, slot IDs and doorbells; nothing // here knows any of those words. A class driver deals in reports and // commands; nothing here knows those either. What lives in the middle is the // part of USB that is the same for every device ever made: read the // configuration, choose one, look at the interface, find someone who wants it. #include "core/types.h" #include "core/defs.h" #include "core/param.h" #include "arch/memlayout.h" #include "arch/mmu.h" #include "core/spinlock.h" #include "core/dma.h" #include "dev/usb.h" #include "core/hwinfo.h" // A staging buffer for control transfers. // // It exists because a descriptor has to be read into memory the controller // can reach and that does not straddle a 64 KB boundary -- a rule that holds // for xHCI data stages and that a static buffer inside some other structure // satisfies only by luck. One page, allocated once, copied out of afterwards. static void *scratch; static void * get_scratch(void) { if(scratch == 0) scratch = dma_alloc(4096, 4096); return scratch; } static int get_descriptor(struct usb_dev *dev, int type, int index, void *buf, int len) { struct usb_setup s; // Clear first. The scratch buffer is shared by every device on the bus, and // a control transfer reports success without saying how many bytes it // actually moved -- so a device that answers short leaves the previous // device's descriptor visible past the end of its own, and the parser // happily walks into it. Zeroed bytes stop the walk instead, because a // descriptor whose length is 0 is rejected. memset(buf, 0, len); s.bmRequestType = USB_DIR_IN | USB_TYPE_STANDARD | USB_RECIP_DEVICE; s.bRequest = USB_REQ_GET_DESCRIPTOR; s.wValue = (type << 8) | index; s.wIndex = 0; s.wLength = len; return dev->ops->control(dev, &s, buf, len); } static int set_configuration(struct usb_dev *dev, int value) { struct usb_setup s; s.bmRequestType = USB_DIR_OUT | USB_TYPE_STANDARD | USB_RECIP_DEVICE; s.bRequest = USB_REQ_SET_CONFIG; s.wValue = value; s.wIndex = 0; s.wLength = 0; return dev->ops->control(dev, &s, 0, 0); } // Walk the configuration descriptor. // // What comes back from GET_DESCRIPTOR(CONFIG) is not one descriptor: it is // the configuration descriptor followed by every interface and endpoint // descriptor belonging to it, packed end to end, each one starting with its // own length. That length is the only thing that can be relied on to find the // next -- descriptor types this kernel has never heard of appear in the // middle (HID's own, class-specific ones) and skipping them by size is the // only way through. A parser that assumed a fixed order would work on one // device and fail on the next. // // `nth` picks the interface: the nth one at alternate setting 0, counted from // zero. Returns 0 if there is one, -1 when there are no more. static int parse_config(struct usb_dev *dev, int nth) { int off = 0; int seen_iface = 0; int count = 0; dev->has_intr_in = dev->has_bulk_in = dev->has_bulk_out = 0; while(off + 2 <= dev->conflen){ uint8 len = dev->conf[off]; uint8 type = dev->conf[off + 1]; if(len < 2 || off + len > dev->conflen) break; // malformed: stop rather than guess if(type == USB_DT_INTERFACE && len >= (int)sizeof(dev->iface)){ struct usb_interface_desc *id = (struct usb_interface_desc *)&dev->conf[off]; if(seen_iface) break; // the next interface: this one is done // Alternate settings are the same interface again with other // endpoints. Setting 0 is the one in force after SET_CONFIGURATION. if(id->bAlternateSetting == 0 && count++ == nth){ memmove(&dev->iface, id, sizeof(dev->iface)); seen_iface = 1; } } else if(type == USB_DT_ENDPOINT && seen_iface && len >= (int)sizeof(struct usb_endpoint_desc)){ struct usb_endpoint_desc ep; int in; memmove(&ep, &dev->conf[off], sizeof(ep)); in = USB_EP_IS_IN(ep.bEndpointAddress); switch(USB_EP_XFERTYPE(ep.bmAttributes)){ case USB_EP_INTERRUPT: if(in && !dev->has_intr_in){ dev->intr_in = ep; dev->has_intr_in = 1; } break; case USB_EP_BULK: if(in && !dev->has_bulk_in){ dev->bulk_in = ep; dev->has_bulk_in = 1; } if(!in && !dev->has_bulk_out){ dev->bulk_out = ep; dev->has_bulk_out = 1; } break; } } off += len; } return seen_iface ? 0 : -1; } // One usb_dev for every interface after the first. See `base` in // include/dev/usb.h. A fixed pool, like everything else here. It was sixteen, // which a dock -- hub, Ethernet, audio, card reader, each two or three // interfaces -- and a couple of receivers already reach. 672 bytes each. #define NIFDEV 64 static struct usb_dev ifdevs[NIFDEV]; // --------------------------------------------------------------------------- // Class drivers // --------------------------------------------------------------------------- extern const struct usb_driver usb_hid_driver; void usb_bind_all(struct usb_dev *dev); static int matches(const struct usb_driver *drv, struct usb_dev *dev) { if(drv->class != 0xFF && drv->class != dev->iface.bInterfaceClass) return 0; if(drv->subclass != 0xFF && drv->subclass != dev->iface.bInterfaceSubClass) return 0; if(drv->protocol != 0xFF && drv->protocol != dev->iface.bInterfaceProtocol) return 0; return 1; } // Offer a device to one driver. Returns 1 if it was claimed. int usb_offer(const struct usb_driver *drv, struct usb_dev *dev) { if(dev->driver || !matches(drv, dev)) return 0; if(drv->probe(dev) != 0) return 0; dev->driver = drv->name; dev->drv = drv; return 1; } // --------------------------------------------------------------------------- // What is plugged in, for /sys/bus/usb/devices. // // The controller owns each usb_dev; this only remembers which ones are // attached, from usb_attach until usb_detach, and copies their identity out // under the lock so a reader never follows a pointer the controller may be // about to reuse. A bus number is handed to each controller the first time one // of its devices appears, in that order, as Linux numbers usb1, usb2. #define NPRESENT 64 #define NBUSES 8 static struct spinlock present_lock; static int present_init; static struct usb_dev *present[NPRESENT]; static void *buses[NBUSES]; static void present_add(struct usb_dev *dev) { if(!present_init){ initlock(&present_lock, "usbpresent"); present_init = 1; } acquire(&present_lock); for(int i = 0; i < NPRESENT; i++) if(present[i] == 0){ present[i] = dev; break; } for(int b = 0; b < NBUSES; b++){ if(buses[b] == dev->hc) break; if(buses[b] == 0){ buses[b] = dev->hc; break; } } release(&present_lock); } static void present_del(struct usb_dev *dev) { if(!present_init) return; acquire(&present_lock); for(int i = 0; i < NPRESENT; i++) if(present[i] == dev) present[i] = 0; release(&present_lock); } static void put_num(char *out, int *n, int cap, int v) { char t[12]; int k = 0; do { t[k++] = '0' + v % 10; v /= 10; } while(v); while(k && *n < cap - 1) out[(*n)++] = t[--k]; out[*n] = 0; } int usb_info_nth(int idx, struct usb_info *o) { if(!present_init) return -1; acquire(&present_lock); int seen = 0; for(int i = 0; i < NPRESENT; i++){ struct usb_dev *d = present[i]; if(d == 0 || seen++ != idx) continue; memset(o, 0, sizeof *o); o->bus = 1; for(int b = 0; b < NBUSES; b++) if(buses[b] == d->hc){ o->bus = b + 1; break; } o->devnum = d->slot; o->speed = d->speed; o->vid = d->desc.idVendor; o->pid = d->desc.idProduct; o->bcd = d->desc.bcdDevice; o->cls = d->desc.bDeviceClass; o->subcls = d->desc.bDeviceSubClass; o->proto = d->desc.bDeviceProtocol; o->nconf = d->desc.bNumConfigurations; // "-[....]": the route string holds one // downstream port per tier below the root, a nibble each. int n = 0, cap = (int)sizeof o->path; put_num(o->path, &n, cap, o->bus); o->path[n++] = '-'; put_num(o->path, &n, cap, d->port); for(int t = 0; t < d->tier && n < cap - 3; t++){ o->path[n++] = '.'; put_num(o->path, &n, cap, (int)((d->route >> (4 * t)) & 0xF)); } const char *drv = d->driver; for(int k = 0; !drv && k < NIFDEV; k++) if(ifdevs[k].in_use && ifdevs[k].base == d) drv = ifdevs[k].driver; if(drv) safestrcpy(o->driver, drv, sizeof o->driver); release(&present_lock); return 0; } release(&present_lock); return -1; } void usb_attach(struct usb_dev *dev) { struct usb_config_desc *cd; void *buf = get_scratch(); int total; if(buf == 0) return; present_add(dev); // Nine bytes first, because wTotalLength is in them and there is no other // way to know how much to ask for. if(get_descriptor(dev, USB_DT_CONFIG, 0, buf, 9) < 0){ cprintf("usb: slot %d would not give up its configuration\n", dev->slot); return; } cd = buf; total = cd->wTotalLength; // A configuration that does not contain its own descriptor is not one we // can do anything with, and reading it as a length would walk off the end. if(cd->bDescriptorType != USB_DT_CONFIG || total < (int)sizeof(*cd)){ cprintf("usb: slot %d returned a malformed configuration descriptor\n", dev->slot); return; } if(total > USB_MAXCONF) total = USB_MAXCONF; if(get_descriptor(dev, USB_DT_CONFIG, 0, buf, total) < 0) return; memmove(dev->conf, buf, total); dev->conflen = total; // A device is not obliged to do anything at all until it has been // configured -- before this, endpoints other than 0 do not exist. if(set_configuration(dev, cd->bConfigurationValue) < 0){ cprintf("usb: slot %d refused SET_CONFIGURATION\n", dev->slot); return; } // Every interface, each offered to the class drivers on its own. This used // to stop after the first, which is how a wireless receiver's mouse -- // interface 1, behind the keyboard on 0 -- was never heard from. for(int n = 0; ; n++){ struct usb_dev *d = dev; if(n > 0){ d = 0; for(int i = 0; i < NIFDEV; i++) if(!ifdevs[i].in_use){ d = &ifdevs[i]; break; } if(d == 0){ cprintf("usb: out of interface slots; the rest are not used\n"); break; } *d = *dev; d->base = dev; d->driver = 0; d->drv = 0; d->drvdata = 0; d->complete = 0; } if(parse_config(d, n) < 0){ if(n > 0) d->in_use = 0; break; } kinfo("usb: interface %d: class %d.%d protocol %d, %d endpoint%s%s%s%s\n", d->iface.bInterfaceNumber, d->iface.bInterfaceClass, d->iface.bInterfaceSubClass, d->iface.bInterfaceProtocol, d->iface.bNumEndpoints, d->iface.bNumEndpoints == 1 ? "" : "s", d->has_intr_in ? ", interrupt IN" : "", d->has_bulk_in ? ", bulk IN" : "", d->has_bulk_out ? ", bulk OUT" : ""); usb_bind_all(d); if(d->driver == 0){ kinfo("usb: no driver for this interface\n"); if(n > 0) d->in_use = 0; // nothing will ever use it; give it back } } } // Tell every driver bound to any interface of `dev` that it is gone, and give // the interface slots back. The controller frees the endpoints afterwards. void usb_detach(struct usb_dev *dev) { present_del(dev); for(int i = 0; i < NIFDEV; i++){ struct usb_dev *d = &ifdevs[i]; if(!d->in_use || d->base != dev) continue; if(d->drv && d->drv->disconnect) d->drv->disconnect(d); d->in_use = 0; } if(dev->drv && dev->drv->disconnect) dev->drv->disconnect(dev); dev->drv = 0; dev->driver = 0; }