Catch various cases in libpayload where malloc() or memalign() return NULL
[coreboot.git] / payloads / libpayload / drivers / usb / usb.c
1 /*
2  * This file is part of the libpayload project.
3  *
4  * Copyright (C) 2008 coresystems GmbH
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  * 3. The name of the author may not be used to endorse or promote products
15  *    derived from this software without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27  * SUCH DAMAGE.
28  */
29
30 #include <libpayload-config.h>
31 #include <usb/usb.h>
32
33 hci_t *usb_hcs = 0;
34
35 hci_t *
36 new_controller (void)
37 {
38         hci_t *controller = malloc (sizeof (hci_t));
39
40         if (controller) {
41                 /* atomic */
42                 controller->next = usb_hcs;
43                 usb_hcs = controller;
44                 /* atomic end */
45         }
46
47         return controller;
48 }
49
50 void
51 detach_controller (hci_t *controller)
52 {
53         if (controller == NULL)
54                 return;
55         if (usb_hcs == controller) {
56                 usb_hcs = controller->next;
57         } else {
58                 hci_t *it = usb_hcs;
59                 while (it != NULL) {
60                         if (it->next == controller) {
61                                 it->next = controller->next;
62                                 return;
63                         }
64                 }
65         }
66 }
67
68 /**
69  * Polls all hubs on all USB controllers, to find out about device changes
70  */
71 void
72 usb_poll ()
73 {
74         if (usb_hcs == 0)
75                 return;
76         hci_t *controller = usb_hcs;
77         while (controller != 0) {
78                 int i;
79                 for (i = 0; i < 128; i++) {
80                         if (controller->devices[i] != 0) {
81                                 controller->devices[i]->poll (controller->
82                                                              devices[i]);
83                         }
84                 }
85                 controller = controller->next;
86         }
87 }
88
89 void
90 init_device_entry (hci_t *controller, int i)
91 {
92         if (controller->devices[i] != 0)
93                 printf("warning: device %d reassigned?\n", i);
94         controller->devices[i] = malloc(sizeof(usbdev_t));
95         controller->devices[i]->controller = controller;
96         controller->devices[i]->address = -1;
97         controller->devices[i]->hub = -1;
98         controller->devices[i]->port = -1;
99         controller->devices[i]->init = usb_nop_init;
100         controller->devices[i]->init (controller->devices[i]);
101 }
102
103 void
104 set_feature (usbdev_t *dev, int endp, int feature, int rtype)
105 {
106         dev_req_t dr;
107
108         dr.bmRequestType = rtype;
109         dr.data_dir = host_to_device;
110         dr.bRequest = SET_FEATURE;
111         dr.wValue = feature;
112         dr.wIndex = endp;
113         dr.wLength = 0;
114         dev->controller->control (dev, OUT, sizeof (dr), &dr, 0, 0);
115 }
116
117 void
118 get_status (usbdev_t *dev, int intf, int rtype, int len, void *data)
119 {
120         dev_req_t dr;
121
122         dr.bmRequestType = rtype;
123         dr.data_dir = device_to_host;
124         dr.bRequest = GET_STATUS;
125         dr.wValue = 0;
126         dr.wIndex = intf;
127         dr.wLength = len;
128         dev->controller->control (dev, IN, sizeof (dr), &dr, len, data);
129 }
130
131 u8 *
132 get_descriptor (usbdev_t *dev, unsigned char bmRequestType, int descType,
133                 int descIdx, int langID)
134 {
135         u8 buf[8];
136         u8 *result;
137         dev_req_t dr;
138         int size;
139
140         dr.bmRequestType = bmRequestType;
141         dr.data_dir = device_to_host;   // always like this for descriptors
142         dr.bRequest = GET_DESCRIPTOR;
143         dr.wValue = (descType << 8) | descIdx;
144         dr.wIndex = langID;
145         dr.wLength = 8;
146         if (dev->controller->control (dev, IN, sizeof (dr), &dr, 8, buf)) {
147                 printf ("getting descriptor size (type %x) failed\n",
148                         descType);
149         }
150
151         if (descType == 1) {
152                 device_descriptor_t *dd = (device_descriptor_t *) buf;
153                 printf ("maxPacketSize0: %x\n", dd->bMaxPacketSize0);
154                 if (dd->bMaxPacketSize0 != 0)
155                         dev->endpoints[0].maxpacketsize = dd->bMaxPacketSize0;
156         }
157
158         /* special case for configuration descriptors: they carry all their
159            subsequent descriptors with them, and keep the entire size at a
160            different location */
161         size = buf[0];
162         if (buf[1] == 2) {
163                 int realsize = ((unsigned short *) (buf + 2))[0];
164                 size = realsize;
165         }
166         result = malloc (size);
167         memset (result, 0, size);
168         dr.wLength = size;
169         if (dev->controller->
170             control (dev, IN, sizeof (dr), &dr, size, result)) {
171                 printf ("getting descriptor (type %x, size %x) failed\n",
172                         descType, size);
173         }
174
175         return result;
176 }
177
178 void
179 set_configuration (usbdev_t *dev)
180 {
181         dev_req_t dr;
182
183         dr.bmRequestType = 0;
184         dr.bRequest = SET_CONFIGURATION;
185         dr.wValue = dev->configuration[5];
186         dr.wIndex = 0;
187         dr.wLength = 0;
188         dev->controller->control (dev, OUT, sizeof (dr), &dr, 0, 0);
189 }
190
191 int
192 clear_stall (endpoint_t *ep)
193 {
194         usbdev_t *dev = ep->dev;
195         int endp = ep->endpoint;
196         dev_req_t dr;
197
198         dr.bmRequestType = 0;
199         if (endp != 0) {
200                 dr.req_recp = endp_recp;
201         }
202         dr.bRequest = CLEAR_FEATURE;
203         dr.wValue = ENDPOINT_HALT;
204         dr.wIndex = endp;
205         dr.wLength = 0;
206         dev->controller->control (dev, OUT, sizeof (dr), &dr, 0, 0);
207         return 0;
208 }
209
210 /* returns free address or -1 */
211 static int
212 get_free_address (hci_t *controller)
213 {
214         int i;
215         for (i = 1; i < 128; i++) {
216                 if (controller->devices[i] == 0)
217                         return i;
218         }
219         printf ("no free address found\n");
220         return -1;              // no free address
221 }
222
223 int
224 set_address (hci_t *controller, int lowspeed)
225 {
226         int adr = get_free_address (controller);        // address to set
227         dev_req_t dr;
228         configuration_descriptor_t *cd;
229         device_descriptor_t *dd;
230
231         memset (&dr, 0, sizeof (dr));
232         dr.data_dir = host_to_device;
233         dr.req_type = standard_type;
234         dr.req_recp = dev_recp;
235         dr.bRequest = SET_ADDRESS;
236         dr.wValue = adr;
237         dr.wIndex = 0;
238         dr.wLength = 0;
239
240         init_device_entry(controller, adr);
241         usbdev_t *dev = controller->devices[adr];
242         // dummy values for registering the address
243         dev->address = 0;
244         dev->lowspeed = lowspeed;
245         dev->endpoints[0].dev = dev;
246         dev->endpoints[0].endpoint = 0;
247         dev->endpoints[0].maxpacketsize = 8;
248         dev->endpoints[0].toggle = 0;
249         dev->endpoints[0].direction = SETUP;
250         mdelay (50);
251         if (dev->controller->control (dev, OUT, sizeof (dr), &dr, 0, 0)) {
252                 printf ("set_address failed\n");
253                 return -1;
254         }
255         mdelay (50);
256         dev->address = adr;
257         dev->descriptor =
258                 get_descriptor (dev,
259                                 gen_bmRequestType (device_to_host,
260                                                    standard_type, dev_recp),
261                                 1, 0, 0);
262         dd = (device_descriptor_t *) dev->descriptor;
263         printf ("device version: %x.%x\n", dd->bcdUSB >> 8,
264                 dd->bcdUSB & 0xff);
265         printf ("device has %x configurations\n", dd->bNumConfigurations);
266         if (dd->bNumConfigurations == 0) {
267                 /* device isn't usable */
268                 printf ("no usable configuration!\n");
269                 dev->address = 0;
270                 return -1;
271         }
272         dev->configuration =
273                 get_descriptor (dev,
274                                 gen_bmRequestType (device_to_host,
275                                                    standard_type, dev_recp),
276                                 2, 0, 0);
277         cd = (configuration_descriptor_t *) dev->configuration;
278         set_configuration (dev);
279         interface_descriptor_t *interface =
280                 (interface_descriptor_t *) (((char *) cd) + cd->bLength);
281         {
282                 int i;
283                 int num = cd->bNumInterfaces;
284                 interface_descriptor_t *current = interface;
285                 printf ("device has %x interfaces\n", num);
286                 if (num>1)
287                         printf ("NOTICE: This driver defaults to using the first interface.\n"
288                                 "This might be the wrong choice and lead to limited functionality\n"
289                                 "of the device. Please report such a case to coreboot@coreboot.org\n"
290                                 "as you might be the first.\n");
291                 /* we limit to the first interface, as there was no need to
292                    implement something else for the time being. If you need
293                    it, see the SetInterface and GetInterface functions in
294                    the USB specification, and adapt appropriately. */
295                 num = (num > 1) ? 1 : num;
296                 for (i = 0; i < num; i++) {
297                         int j;
298                         printf (" #%x has %x endpoints, interface %x:%x, protocol %x\n", current->bInterfaceNumber, current->bNumEndpoints, current->bInterfaceClass, current->bInterfaceSubClass, current->bInterfaceProtocol);
299                         endpoint_descriptor_t *endp =
300                                 (endpoint_descriptor_t *) (((char *) current)
301                                                            +
302                                                            current->bLength);
303                         if (interface->bInterfaceClass == 0x3)
304                                 endp = (endpoint_descriptor_t *) (((char *) endp) + ((char *) endp)[0]);        // ignore HID descriptor
305                         memset (dev->endpoints, 0, sizeof (dev->endpoints));
306                         dev->num_endp = 1;      // 0 always exists
307                         dev->endpoints[0].dev = dev;
308                         dev->endpoints[0].maxpacketsize = dd->bMaxPacketSize0;
309                         dev->endpoints[0].direction = SETUP;
310                         dev->endpoints[0].type = CONTROL;
311                         for (j = 1; j <= current->bNumEndpoints; j++) {
312                                 static const char *transfertypes[4] =
313                                         { "control", "isochronous", "bulk",
314                                         "interrupt"
315                                 };
316                                 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]);
317                                 endpoint_t *ep =
318                                         &dev->endpoints[dev->num_endp++];
319                                 ep->dev = dev;
320                                 ep->endpoint = endp->bEndpointAddress;
321                                 ep->toggle = 0;
322                                 ep->maxpacketsize = endp->wMaxPacketSize;
323                                 ep->direction =
324                                         ((endp->bEndpointAddress & 0x80) ==
325                                          0) ? OUT : IN;
326                                 ep->type = endp->bmAttributes;
327                                 endp = (endpoint_descriptor_t
328                                         *) (((char *) endp) + endp->bLength);
329                         }
330                         current = (interface_descriptor_t *) endp;
331                 }
332         }
333         int class = dd->bDeviceClass;
334         if (class == 0)
335                 class = interface->bInterfaceClass;
336
337         enum { hid_device = 0x3, msc_device = 0x8, hub_device = 0x9 };
338
339         printf ("device of class %x found\n", class);
340         if (class == hub_device) {
341                 printf ("hub found\n");
342 #ifdef CONFIG_USB_HUB
343                 controller->devices[adr]->init = usb_hub_init;
344 #else
345                 printf ("support not compiled in\n");
346 #endif
347         }
348         if (class == hid_device) {
349                 printf ("HID found\n");
350 #ifdef CONFIG_USB_HID
351                 controller->devices[adr]->init = usb_hid_init;
352 #else
353                 printf ("support not compiled in\n");
354 #endif
355         }
356         if (class == msc_device) {
357                 printf ("MSC found\n");
358 #ifdef CONFIG_USB_MSC
359                 controller->devices[adr]->init = usb_msc_init;
360 #else
361                 printf ("support not compiled in\n");
362 #endif
363         }
364         return adr;
365 }
366
367 void
368 usb_detach_device(hci_t *controller, int devno)
369 {
370         controller->devices[devno]->destroy (controller->devices[devno]);
371         free(controller->devices[devno]);
372         controller->devices[devno] = 0;
373 }
374
375 int
376 usb_attach_device(hci_t *controller, int hubaddress, int port, int lowspeed)
377 {
378         printf ("%sspeed device\n", (lowspeed == 1) ? "low" : "full");
379         int newdev = set_address (controller, lowspeed);
380         if (newdev == -1)
381                 return -1;
382         usbdev_t *newdev_t = controller->devices[newdev];
383
384         newdev_t->address = newdev;
385         newdev_t->hub = hubaddress;
386         newdev_t->port = port;
387         // determine responsible driver - current done in set_address
388         newdev_t->init (newdev_t);
389         return newdev;
390 }
391
392 void
393 usb_fatal (const char *message)
394 {
395         printf(message);
396         for (;;) ;
397 }