libpayload: Reduce verbosity in USB stack
[coreboot.git] / payloads / libpayload / drivers / usb / usb.c
index 3820180cbcc1636ca22464adb29043e2709be98f..6995cef7b24afbf8193d4c301c159ca2c40bef31 100644 (file)
@@ -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
  * SUCH DAMAGE.
  */
 
+//#define USB_DEBUG
+
 #include <libpayload-config.h>
 #include <usb/usb.h>
 
 hci_t *usb_hcs = 0;
 
 hci_t *
-new_controller ()
+new_controller (void)
 {
        hci_t *controller = malloc (sizeof (hci_t));
 
-       /* atomic */
-       controller->next = usb_hcs;
-       usb_hcs = controller;
-       /* atomic end */
+       if (controller) {
+               /* atomic */
+               controller->next = usb_hcs;
+               usb_hcs = controller;
+               /* atomic end */
+       }
 
        return controller;
 }
@@ -48,13 +52,13 @@ new_controller ()
 void
 detach_controller (hci_t *controller)
 {
-       if (controller == 0)
+       if (controller == NULL)
                return;
        if (usb_hcs == controller) {
                usb_hcs = controller->next;
        } else {
                hci_t *it = usb_hcs;
-               while (it != 0) {
+               while (it != NULL) {
                        if (it->next == controller) {
                                it->next = controller->next;
                                return;
@@ -67,7 +71,7 @@ detach_controller (hci_t *controller)
  * Polls all hubs on all USB controllers, to find out about device changes
  */
 void
-usb_poll ()
+usb_poll (void)
 {
        if (usb_hcs == 0)
                return;
@@ -76,8 +80,7 @@ usb_poll ()
                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;
@@ -88,7 +91,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;
@@ -142,13 +145,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;
        }
@@ -166,7 +169,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);
        }
 
@@ -202,6 +205,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;
 }
 
@@ -214,12 +218,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;
@@ -239,7 +243,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;
@@ -247,31 +251,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 =
@@ -280,15 +283,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);
-               num = (num > 5) ? 5 : 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));
@@ -298,11 +319,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;
@@ -319,36 +341,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;
 }
@@ -362,10 +442,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];
@@ -377,3 +458,10 @@ usb_attach_device(hci_t *controller, int hubaddress, int port, int lowspeed)
        newdev_t->init (newdev_t);
        return newdev;
 }
+
+void
+usb_fatal (const char *message)
+{
+       printf(message);
+       for (;;) ;
+}