X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=payloads%2Flibpayload%2Fdrivers%2Fusb%2Fusb.c;h=1f21e6a9940d7716e7eadaf2adca6d13119714f4;hb=db89ec975c39e6523336563923ccf8b7397cc313;hp=25e80065d7041c67a70fe060dd727035d8d2b8b6;hpb=5fe6e23c61bf1fde7a1a0568b38d32c4e625f0ef;p=coreboot.git diff --git a/payloads/libpayload/drivers/usb/usb.c b/payloads/libpayload/drivers/usb/usb.c index 25e80065d..1f21e6a99 100644 --- a/payloads/libpayload/drivers/usb/usb.c +++ b/payloads/libpayload/drivers/usb/usb.c @@ -1,7 +1,7 @@ /* * This file is part of the libpayload project. * - * Copyright (C) 2008 coresystems GmbH + * Copyright (C) 2008-2010 coresystems GmbH * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -27,6 +27,8 @@ * SUCH DAMAGE. */ +//#define USB_DEBUG + #include #include @@ -65,21 +67,36 @@ detach_controller (hci_t *controller) } } +/** + * Shut down all controllers + */ +int +usb_exit (void) +{ + if (usb_hcs == 0) + return 0; + hci_t *controller = usb_hcs; + while (controller != NULL) { + controller->shutdown(controller); + controller = controller->next; + } + return 0; +} + /** * Polls all hubs on all USB controllers, to find out about device changes */ void -usb_poll () +usb_poll (void) { if (usb_hcs == 0) return; hci_t *controller = usb_hcs; - while (controller != 0) { + while (controller != NULL) { int i; for (i = 0; i < 128; i++) { if (controller->devices[i] != 0) { - controller->devices[i]->poll (controller-> - devices[i]); + controller->devices[i]->poll (controller->devices[i]); } } controller = controller->next; @@ -90,7 +107,7 @@ void init_device_entry (hci_t *controller, int i) { if (controller->devices[i] != 0) - printf("warning: device %d reassigned?\n", i); + debug("warning: device %d reassigned?\n", i); controller->devices[i] = malloc(sizeof(usbdev_t)); controller->devices[i]->controller = controller; controller->devices[i]->address = -1; @@ -144,13 +161,13 @@ get_descriptor (usbdev_t *dev, unsigned char bmRequestType, int descType, dr.wIndex = langID; dr.wLength = 8; if (dev->controller->control (dev, IN, sizeof (dr), &dr, 8, buf)) { - printf ("getting descriptor size (type %x) failed\n", + debug ("getting descriptor size (type %x) failed\n", descType); } if (descType == 1) { device_descriptor_t *dd = (device_descriptor_t *) buf; - printf ("maxPacketSize0: %x\n", dd->bMaxPacketSize0); + debug ("maxPacketSize0: %x\n", dd->bMaxPacketSize0); if (dd->bMaxPacketSize0 != 0) dev->endpoints[0].maxpacketsize = dd->bMaxPacketSize0; } @@ -168,7 +185,7 @@ get_descriptor (usbdev_t *dev, unsigned char bmRequestType, int descType, dr.wLength = size; if (dev->controller-> control (dev, IN, sizeof (dr), &dr, size, result)) { - printf ("getting descriptor (type %x, size %x) failed\n", + debug ("getting descriptor (type %x, size %x) failed\n", descType, size); } @@ -204,6 +221,7 @@ clear_stall (endpoint_t *ep) dr.wIndex = endp; dr.wLength = 0; dev->controller->control (dev, OUT, sizeof (dr), &dr, 0, 0); + ep->toggle = 0; return 0; } @@ -216,12 +234,12 @@ get_free_address (hci_t *controller) if (controller->devices[i] == 0) return i; } - printf ("no free address found\n"); + debug ("no free address found\n"); return -1; // no free address } int -set_address (hci_t *controller, int lowspeed) +set_address (hci_t *controller, int speed) { int adr = get_free_address (controller); // address to set dev_req_t dr; @@ -241,7 +259,7 @@ set_address (hci_t *controller, int lowspeed) usbdev_t *dev = controller->devices[adr]; // dummy values for registering the address dev->address = 0; - dev->lowspeed = lowspeed; + dev->speed = speed; dev->endpoints[0].dev = dev; dev->endpoints[0].endpoint = 0; dev->endpoints[0].maxpacketsize = 8; @@ -249,31 +267,30 @@ set_address (hci_t *controller, int lowspeed) dev->endpoints[0].direction = SETUP; mdelay (50); if (dev->controller->control (dev, OUT, sizeof (dr), &dr, 0, 0)) { - printf ("set_address failed\n"); + debug ("set_address failed\n"); return -1; } mdelay (50); dev->address = adr; - dev->descriptor = - get_descriptor (dev, - gen_bmRequestType (device_to_host, - standard_type, dev_recp), - 1, 0, 0); + dev->descriptor = get_descriptor (dev, gen_bmRequestType + (device_to_host, standard_type, dev_recp), 1, 0, 0); dd = (device_descriptor_t *) dev->descriptor; - printf ("device version: %x.%x\n", dd->bcdUSB >> 8, - dd->bcdUSB & 0xff); - printf ("device has %x configurations\n", dd->bNumConfigurations); + + printf ("* found device (0x%04x:0x%04x, USB %x.%x)", + dd->idVendor, dd->idProduct, + dd->bcdUSB >> 8, dd->bcdUSB & 0xff); + dev->quirks = usb_quirk_check(dd->idVendor, dd->idProduct); + + debug ("\ndevice has %x configurations\n", dd->bNumConfigurations); if (dd->bNumConfigurations == 0) { /* device isn't usable */ - printf ("no usable configuration!\n"); + printf ("... no usable configuration!\n"); dev->address = 0; return -1; } - dev->configuration = - get_descriptor (dev, - gen_bmRequestType (device_to_host, - standard_type, dev_recp), - 2, 0, 0); + + dev->configuration = get_descriptor (dev, gen_bmRequestType + (device_to_host, standard_type, dev_recp), 2, 0, 0); cd = (configuration_descriptor_t *) dev->configuration; set_configuration (dev); interface_descriptor_t *interface = @@ -282,24 +299,33 @@ set_address (hci_t *controller, int lowspeed) int i; int num = cd->bNumInterfaces; interface_descriptor_t *current = interface; - printf ("device has %x interfaces\n", num); - if (num>1) - printf ("NOTICE: This driver defaults to using the first interface.\n" - "This might be the wrong choice and lead to limited functionality\n" - "of the device. Please report such a case to coreboot@coreboot.org\n" - "as you might be the first.\n"); - /* we limit to the first interface, as there was no need to - implement something else for the time being. If you need - it, see the SetInterface and GetInterface functions in - the USB specification, and adapt appropriately. */ - num = (num > 1) ? 1 : num; + debug ("device has %x interfaces\n", num); + if (num > 1) { + int interfaces = usb_interface_check(dd->idVendor, dd->idProduct); + if (interfaces) { + /* Well known device, don't warn */ + num = interfaces; + } else { + + printf ("\nNOTICE: This driver defaults to using the first interface.\n" + "This might be the wrong choice and lead to limited functionality\n" + "of the device. Please report such a case to coreboot@coreboot.org\n" + "as you might be the first.\n"); + /* we limit to the first interface, as there was no need to + * implement something else for the time being. If you need + * it, see the SetInterface and GetInterface functions in + * the USB specification, and adapt appropriately. + */ + num = (num > 1) ? 1 : num; + } + } for (i = 0; i < num; i++) { int j; - printf (" #%x has %x endpoints, interface %x:%x, protocol %x\n", current->bInterfaceNumber, current->bNumEndpoints, current->bInterfaceClass, current->bInterfaceSubClass, current->bInterfaceProtocol); + debug (" #%x has %x endpoints, interface %x:%x, protocol %x\n", + current->bInterfaceNumber, current->bNumEndpoints, current->bInterfaceClass, current->bInterfaceSubClass, current->bInterfaceProtocol); endpoint_descriptor_t *endp = (endpoint_descriptor_t *) (((char *) current) - + - current->bLength); + + current->bLength); if (interface->bInterfaceClass == 0x3) endp = (endpoint_descriptor_t *) (((char *) endp) + ((char *) endp)[0]); // ignore HID descriptor memset (dev->endpoints, 0, sizeof (dev->endpoints)); @@ -309,11 +335,12 @@ set_address (hci_t *controller, int lowspeed) dev->endpoints[0].direction = SETUP; dev->endpoints[0].type = CONTROL; for (j = 1; j <= current->bNumEndpoints; j++) { - static const char *transfertypes[4] = - { "control", "isochronous", "bulk", - "interrupt" +#ifdef USB_DEBUG + static const char *transfertypes[4] = { + "control", "isochronous", "bulk", "interrupt" }; - printf (" #%x: Endpoint %x (%s), max packet size %x, type %s\n", j, endp->bEndpointAddress & 0x7f, ((endp->bEndpointAddress & 0x80) != 0) ? "in" : "out", endp->wMaxPacketSize, transfertypes[endp->bmAttributes]); + debug (" #%x: Endpoint %x (%s), max packet size %x, type %s\n", j, endp->bEndpointAddress & 0x7f, ((endp->bEndpointAddress & 0x80) != 0) ? "in" : "out", endp->wMaxPacketSize, transfertypes[endp->bmAttributes]); +#endif endpoint_t *ep = &dev->endpoints[dev->num_endp++]; ep->dev = dev; @@ -330,36 +357,94 @@ set_address (hci_t *controller, int lowspeed) current = (interface_descriptor_t *) endp; } } + int class = dd->bDeviceClass; if (class == 0) class = interface->bInterfaceClass; - enum { hid_device = 0x3, msc_device = 0x8, hub_device = 0x9 }; - - printf ("device of class %x found\n", class); - if (class == hub_device) { - printf ("hub found\n"); -#ifdef CONFIG_USB_HUB - controller->devices[adr]->init = usb_hub_init; -#else - printf ("support not compiled in\n"); -#endif - } - if (class == hid_device) { - printf ("HID found\n"); + enum { + audio_device = 0x01, + comm_device = 0x02, + hid_device = 0x03, + physical_device = 0x05, + imaging_device = 0x06, + printer_device = 0x07, + msc_device = 0x08, + hub_device = 0x09, + cdc_device = 0x0a, + ccid_device = 0x0b, + security_device = 0x0d, + video_device = 0x0e, + healthcare_device = 0x0f, + diagnostic_device = 0xdc, + wireless_device = 0xe0, + misc_device = 0xef, + }; + printf(", class: "); + switch (class) { + case audio_device: + printf("audio\n"); + break; + case comm_device: + printf("communication\n"); + break; + case hid_device: + printf ("HID\n"); #ifdef CONFIG_USB_HID controller->devices[adr]->init = usb_hid_init; #else - printf ("support not compiled in\n"); + debug ("NOTICE: USB HID support not compiled in\n"); #endif - } - if (class == msc_device) { - printf ("MSC found\n"); + break; + case physical_device: + printf("physical\n"); + break; + case imaging_device: + printf("camera\n"); + break; + case printer_device: + printf("printer\n"); + break; + case msc_device: + printf ("MSC\n"); #ifdef CONFIG_USB_MSC controller->devices[adr]->init = usb_msc_init; #else - printf ("support not compiled in\n"); + debug ("NOTICE: USB MSC support not compiled in\n"); +#endif + break; + case hub_device: + printf ("hub\n"); +#ifdef CONFIG_USB_HUB + controller->devices[adr]->init = usb_hub_init; +#else + debug ("NOTICE: USB hub support not compiled in.\n"); #endif + break; + case cdc_device: + printf("CDC\n"); + break; + case ccid_device: + printf("smartcard / CCID\n"); + break; + case security_device: + printf("content security\n"); + break; + case video_device: + printf("video\n"); + break; + case healthcare_device: + printf("healthcare\n"); + break; + case diagnostic_device: + printf("diagnostic\n"); + break; + case wireless_device: + printf("wireless\n"); + break; + default: + printf("unsupported class %x\n", class); + break; } return adr; } @@ -373,10 +458,11 @@ usb_detach_device(hci_t *controller, int devno) } int -usb_attach_device(hci_t *controller, int hubaddress, int port, int lowspeed) +usb_attach_device(hci_t *controller, int hubaddress, int port, int speed) { - printf ("%sspeed device\n", (lowspeed == 1) ? "low" : "full"); - int newdev = set_address (controller, lowspeed); + static const char* speeds[] = { "full", "low", "high" }; + debug ("%sspeed device\n", (speed <= 2) ? speeds[speed] : "invalid value - no"); + int newdev = set_address (controller, speed); if (newdev == -1) return -1; usbdev_t *newdev_t = controller->devices[newdev]; @@ -389,9 +475,3 @@ usb_attach_device(hci_t *controller, int hubaddress, int port, int lowspeed) return newdev; } -void -usb_fatal (const char *message) -{ - printf(message); - for (;;) ; -}