#include "usb-uhci.h" // uhci_init
#include "usb-ohci.h" // ohci_init
#include "usb-hid.h" // usb_keyboard_setup
+#include "usb-hub.h" // usb_hub_init
+#include "usb-msc.h" // usb_msc_init
#include "usb.h" // struct usb_s
#include "biosvar.h" // GET_GLOBAL
struct usb_s USBControllers[16] VAR16VISIBLE;
+
+/****************************************************************
+ * Controller function wrappers
+ ****************************************************************/
+
+// Send a message on a control pipe using the default control descriptor.
static int
send_control(u32 endp, int dir, const void *cmd, int cmdsize
, void *data, int datasize)
}
}
+struct usb_pipe *
+alloc_bulk_pipe(u32 endp)
+{
+ struct usb_s *cntl = endp2cntl(endp);
+ switch (cntl->type) {
+ default:
+ case USB_TYPE_UHCI:
+ return uhci_alloc_bulk_pipe(endp);
+ case USB_TYPE_OHCI:
+ return NULL;
+ }
+}
+
+int
+usb_send_bulk(struct usb_pipe *pipe, int dir, void *data, int datasize)
+{
+ u32 endp = GET_FLATPTR(pipe->endp);
+ struct usb_s *cntl = endp2cntl(endp);
+ switch (cntl->type) {
+ default:
+ case USB_TYPE_UHCI:
+ return uhci_send_bulk(pipe, dir, data, datasize);
+ case USB_TYPE_OHCI:
+ return -1;
+ }
+}
+
struct usb_pipe *
alloc_intr_pipe(u32 endp, int period)
{
}
}
+
+/****************************************************************
+ * Helper functions
+ ****************************************************************/
+
+// Find the first endpoing of a given type in an interface description.
+struct usb_endpoint_descriptor *
+findEndPointDesc(struct usb_interface_descriptor *iface, int imax
+ , int type, int dir)
+{
+ struct usb_endpoint_descriptor *epdesc = (void*)&iface[1];
+ for (;;) {
+ if ((void*)epdesc >= (void*)iface + imax
+ || epdesc->bDescriptorType == USB_DT_INTERFACE) {
+ return NULL;
+ }
+ if (epdesc->bDescriptorType == USB_DT_ENDPOINT
+ && (epdesc->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == dir
+ && (epdesc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == type)
+ return epdesc;
+ epdesc = (void*)epdesc + epdesc->bLength;
+ }
+}
+
+// Build an encoded "endp" from an endpoint descriptor.
+u32
+mkendpFromDesc(u32 endp, struct usb_endpoint_descriptor *epdesc)
+{
+ return mkendp(endp2cntl(endp), endp2devaddr(endp)
+ , epdesc->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK
+ , endp2speed(endp), epdesc->wMaxPacketSize);
+}
+
+// Send a message to the default control pipe of a device.
int
send_default_control(u32 endp, const struct usb_ctrlrequest *req, void *data)
{
return send_default_control(endp, &req, NULL);
}
+
+/****************************************************************
+ * Initialization and enumeration
+ ****************************************************************/
+
// Called for every found device - see if a driver is available for
// this device and do setup if so.
int
configure_usb_device(struct usb_s *cntl, int lowspeed)
{
- dprintf(1, "config_usb: %p %d\n", cntl, lowspeed);
+ dprintf(3, "config_usb: %p %d\n", cntl, lowspeed);
// Get device info
u32 endp = mkendp(cntl, 0, 0, lowspeed, 8);
// Determine if a driver exists for this device - only look at the
// first interface of the first configuration.
struct usb_interface_descriptor *iface = (void*)(&config[1]);
- if (iface->bInterfaceClass != USB_CLASS_HID
- || iface->bInterfaceSubClass != USB_INTERFACE_SUBCLASS_BOOT
- || iface->bInterfaceProtocol != USB_INTERFACE_PROTOCOL_KEYBOARD)
- // Not a "boot" keyboard
+ if ((iface->bInterfaceClass != USB_CLASS_HID
+ || iface->bInterfaceSubClass != USB_INTERFACE_SUBCLASS_BOOT
+ || iface->bInterfaceProtocol != USB_INTERFACE_PROTOCOL_KEYBOARD)
+ && (iface->bInterfaceClass != USB_CLASS_MASS_STORAGE)
+ && (iface->bInterfaceClass != USB_CLASS_HUB))
+ // Not a supported device.
goto fail;
// Set the address and configure device.
goto fail;
// Configure driver.
- ret = usb_keyboard_init(endp, iface, ((void*)config + config->wTotalLength
- - (void*)iface));
+ if (iface->bInterfaceClass == USB_CLASS_HUB) {
+ free(config);
+ return usb_hub_init(endp);
+ }
+ int imax = (void*)config + config->wTotalLength - (void*)iface;
+ if (iface->bInterfaceClass == USB_CLASS_MASS_STORAGE)
+ ret = usb_msc_init(endp, iface, imax);
+ else
+ ret = usb_keyboard_init(endp, iface, imax);
if (ret)
goto fail;