2 * This file is part of the libpayload project.
4 * Copyright (C) 2008 coresystems GmbH
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
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.
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
30 #include <libpayload-config.h>
38 hci_t *controller = malloc (sizeof (hci_t));
42 controller->next = usb_hcs;
51 detach_controller (hci_t *controller)
53 if (controller == NULL)
55 if (usb_hcs == controller) {
56 usb_hcs = controller->next;
60 if (it->next == controller) {
61 it->next = controller->next;
69 * Polls all hubs on all USB controllers, to find out about device changes
76 hci_t *controller = usb_hcs;
77 while (controller != 0) {
79 for (i = 0; i < 128; i++) {
80 if (controller->devices[i] != 0) {
81 controller->devices[i]->poll (controller->
85 controller = controller->next;
90 init_device_entry (hci_t *controller, int i)
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]);
104 set_feature (usbdev_t *dev, int endp, int feature, int rtype)
108 dr.bmRequestType = rtype;
109 dr.data_dir = host_to_device;
110 dr.bRequest = SET_FEATURE;
114 dev->controller->control (dev, OUT, sizeof (dr), &dr, 0, 0);
118 get_status (usbdev_t *dev, int intf, int rtype, int len, void *data)
122 dr.bmRequestType = rtype;
123 dr.data_dir = device_to_host;
124 dr.bRequest = GET_STATUS;
128 dev->controller->control (dev, IN, sizeof (dr), &dr, len, data);
132 get_descriptor (usbdev_t *dev, unsigned char bmRequestType, int descType,
133 int descIdx, int langID)
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;
146 if (dev->controller->control (dev, IN, sizeof (dr), &dr, 8, buf)) {
147 printf ("getting descriptor size (type %x) failed\n",
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;
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 */
163 int realsize = ((unsigned short *) (buf + 2))[0];
166 result = malloc (size);
167 memset (result, 0, size);
169 if (dev->controller->
170 control (dev, IN, sizeof (dr), &dr, size, result)) {
171 printf ("getting descriptor (type %x, size %x) failed\n",
179 set_configuration (usbdev_t *dev)
183 dr.bmRequestType = 0;
184 dr.bRequest = SET_CONFIGURATION;
185 dr.wValue = dev->configuration[5];
188 dev->controller->control (dev, OUT, sizeof (dr), &dr, 0, 0);
192 clear_stall (endpoint_t *ep)
194 usbdev_t *dev = ep->dev;
195 int endp = ep->endpoint;
198 dr.bmRequestType = 0;
200 dr.req_recp = endp_recp;
202 dr.bRequest = CLEAR_FEATURE;
203 dr.wValue = ENDPOINT_HALT;
206 dev->controller->control (dev, OUT, sizeof (dr), &dr, 0, 0);
210 /* returns free address or -1 */
212 get_free_address (hci_t *controller)
215 for (i = 1; i < 128; i++) {
216 if (controller->devices[i] == 0)
219 printf ("no free address found\n");
220 return -1; // no free address
224 set_address (hci_t *controller, int lowspeed)
226 int adr = get_free_address (controller); // address to set
228 configuration_descriptor_t *cd;
229 device_descriptor_t *dd;
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;
240 init_device_entry(controller, adr);
241 usbdev_t *dev = controller->devices[adr];
242 // dummy values for registering the address
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;
251 if (dev->controller->control (dev, OUT, sizeof (dr), &dr, 0, 0)) {
252 printf ("set_address failed\n");
259 gen_bmRequestType (device_to_host,
260 standard_type, dev_recp),
262 dd = (device_descriptor_t *) dev->descriptor;
263 printf ("device version: %x.%x\n", dd->bcdUSB >> 8,
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");
274 gen_bmRequestType (device_to_host,
275 standard_type, dev_recp),
277 cd = (configuration_descriptor_t *) dev->configuration;
278 set_configuration (dev);
279 interface_descriptor_t *interface =
280 (interface_descriptor_t *) (((char *) cd) + cd->bLength);
283 int num = cd->bNumInterfaces;
284 interface_descriptor_t *current = interface;
285 printf ("device has %x interfaces\n", num);
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++) {
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)
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",
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]);
318 &dev->endpoints[dev->num_endp++];
320 ep->endpoint = endp->bEndpointAddress;
322 ep->maxpacketsize = endp->wMaxPacketSize;
324 ((endp->bEndpointAddress & 0x80) ==
326 ep->type = endp->bmAttributes;
327 endp = (endpoint_descriptor_t
328 *) (((char *) endp) + endp->bLength);
330 current = (interface_descriptor_t *) endp;
333 int class = dd->bDeviceClass;
335 class = interface->bInterfaceClass;
337 enum { hid_device = 0x3, msc_device = 0x8, hub_device = 0x9 };
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;
345 printf ("support not compiled in\n");
348 if (class == hid_device) {
349 printf ("HID found\n");
350 #ifdef CONFIG_USB_HID
351 controller->devices[adr]->init = usb_hid_init;
353 printf ("support not compiled in\n");
356 if (class == msc_device) {
357 printf ("MSC found\n");
358 #ifdef CONFIG_USB_MSC
359 controller->devices[adr]->init = usb_msc_init;
361 printf ("support not compiled in\n");
368 usb_detach_device(hci_t *controller, int devno)
370 controller->devices[devno]->destroy (controller->devices[devno]);
371 free(controller->devices[devno]);
372 controller->devices[devno] = 0;
376 usb_attach_device(hci_t *controller, int hubaddress, int port, int lowspeed)
378 printf ("%sspeed device\n", (lowspeed == 1) ? "low" : "full");
379 int newdev = set_address (controller, lowspeed);
382 usbdev_t *newdev_t = controller->devices[newdev];
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);
393 usb_fatal (const char *message)