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
38 hci_t *controller = malloc (sizeof (hci_t));
41 controller->next = usb_hcs;
49 detach_controller (hci_t *controller)
53 if (usb_hcs == controller) {
54 usb_hcs = controller->next;
58 if (it->next == controller) {
59 it->next = controller->next;
67 * Polls all hubs on all USB controllers, to find out about device changes
74 hci_t *controller = usb_hcs;
75 while (controller != 0) {
77 for (i = 0; i < 128; i++) {
78 if (controller->devices[i].address != -1) {
79 controller->devices[i].poll (&controller->
83 controller = controller->next;
88 init_device_entry (hci_t *controller, int i)
90 controller->devices[i].controller = controller;
91 controller->devices[i].address = -1;
92 controller->devices[i].hub = -1;
93 controller->devices[i].port = -1;
94 controller->devices[i].init = usb_nop_init;
95 controller->devices[i].init (&controller->devices[i]);
99 set_feature (usbdev_t *dev, int endp, int feature, int rtype)
103 dr.bmRequestType = rtype;
104 dr.data_dir = host_to_device;
105 dr.bRequest = SET_FEATURE;
109 dev->controller->control (dev, OUT, sizeof (dr), &dr, 0, 0);
113 get_status (usbdev_t *dev, int intf, int rtype, int len, void *data)
117 dr.bmRequestType = rtype;
118 dr.data_dir = device_to_host;
119 dr.bRequest = GET_STATUS;
123 dev->controller->control (dev, IN, sizeof (dr), &dr, len, data);
127 get_descriptor (usbdev_t *dev, unsigned char bmRequestType, int descType,
128 int descIdx, int langID)
135 dr.bmRequestType = bmRequestType;
136 dr.data_dir = device_to_host; // always like this for descriptors
137 dr.bRequest = GET_DESCRIPTOR;
138 dr.wValue = (descType << 8) | descIdx;
141 if (dev->controller->control (dev, IN, sizeof (dr), &dr, 8, buf)) {
142 printf ("getting descriptor size (type %x) failed\n",
147 device_descriptor_t *dd = (device_descriptor_t *) buf;
148 printf ("maxPacketSize0: %x\n", dd->bMaxPacketSize0);
149 if (dd->bMaxPacketSize0 != 0)
150 dev->endpoints[0].maxpacketsize = dd->bMaxPacketSize0;
153 /* special case for configuration descriptors: they carry all their
154 subsequent descriptors with them, and keep the entire size at a
155 different location */
158 int realsize = ((unsigned short *) (buf + 2))[0];
161 result = malloc (size);
162 memset (result, 0, size);
164 if (dev->controller->
165 control (dev, IN, sizeof (dr), &dr, size, result)) {
166 printf ("getting descriptor (type %x, size %x) failed\n",
174 set_configuration (usbdev_t *dev)
178 dr.bmRequestType = 0;
179 dr.bRequest = SET_CONFIGURATION;
180 dr.wValue = dev->configuration[5];
183 dev->controller->control (dev, OUT, sizeof (dr), &dr, 0, 0);
187 clear_stall (endpoint_t *ep)
189 usbdev_t *dev = ep->dev;
190 int endp = ep->endpoint;
193 dr.bmRequestType = 0;
195 dr.req_recp = endp_recp;
197 dr.bRequest = CLEAR_FEATURE;
198 dr.wValue = ENDPOINT_HALT;
201 dev->controller->control (dev, OUT, sizeof (dr), &dr, 0, 0);
205 /* returns free address or -1 */
207 get_free_address (hci_t *controller)
210 for (i = 1; i < 128; i++) {
211 if (controller->devices[i].address != i)
214 printf ("no free address found\n");
215 return -1; // no free address
219 set_address (hci_t *controller, int lowspeed)
221 int adr = get_free_address (controller); // address to set
223 configuration_descriptor_t *cd;
224 device_descriptor_t *dd;
226 memset (&dr, 0, sizeof (dr));
227 dr.data_dir = host_to_device;
228 dr.req_type = standard_type;
229 dr.req_recp = dev_recp;
230 dr.bRequest = SET_ADDRESS;
235 usbdev_t *dev = &controller->devices[adr];
236 // dummy values for registering the address
238 dev->lowspeed = lowspeed;
239 dev->endpoints[0].dev = dev;
240 dev->endpoints[0].endpoint = 0;
241 dev->endpoints[0].maxpacketsize = 8;
242 dev->endpoints[0].toggle = 0;
243 dev->endpoints[0].direction = SETUP;
245 if (dev->controller->control (dev, OUT, sizeof (dr), &dr, 0, 0)) {
246 printf ("set_address failed\n");
253 gen_bmRequestType (device_to_host,
254 standard_type, dev_recp),
256 dd = (device_descriptor_t *) dev->descriptor;
257 printf ("device version: %x.%x\n", dd->bcdUSB >> 8,
259 printf ("device has %x configurations\n", dd->bNumConfigurations);
260 if (dd->bNumConfigurations == 0) {
261 /* device isn't usable */
262 printf ("no usable configuration!\n");
268 gen_bmRequestType (device_to_host,
269 standard_type, dev_recp),
271 cd = (configuration_descriptor_t *) dev->configuration;
272 set_configuration (dev);
273 interface_descriptor_t *interface =
274 (interface_descriptor_t *) (((char *) cd) + cd->bLength);
277 int num = cd->bNumInterfaces;
278 interface_descriptor_t *current = interface;
279 printf ("device has %x interfaces\n", num);
280 num = (num > 5) ? 5 : num;
281 for (i = 0; i < num; i++) {
283 printf (" #%x has %x endpoints, interface %x:%x, protocol %x\n", current->bInterfaceNumber, current->bNumEndpoints, current->bInterfaceClass, current->bInterfaceSubClass, current->bInterfaceProtocol);
284 endpoint_descriptor_t *endp =
285 (endpoint_descriptor_t *) (((char *) current)
288 if (interface->bInterfaceClass == 0x3)
289 endp = (endpoint_descriptor_t *) (((char *) endp) + ((char *) endp)[0]); // ignore HID descriptor
290 memset (dev->endpoints, 0, sizeof (dev->endpoints));
291 dev->num_endp = 1; // 0 always exists
292 dev->endpoints[0].dev = dev;
293 dev->endpoints[0].maxpacketsize = dd->bMaxPacketSize0;
294 dev->endpoints[0].direction = SETUP;
295 dev->endpoints[0].type = CONTROL;
296 for (j = 1; j <= current->bNumEndpoints; j++) {
297 static const char *transfertypes[4] =
298 { "control", "isochronous", "bulk",
301 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]);
303 &dev->endpoints[dev->num_endp++];
305 ep->endpoint = endp->bEndpointAddress;
307 ep->maxpacketsize = endp->wMaxPacketSize;
309 ((endp->bEndpointAddress & 0x80) ==
311 ep->type = endp->bmAttributes;
312 endp = (endpoint_descriptor_t
313 *) (((char *) endp) + endp->bLength);
315 current = (interface_descriptor_t *) endp;
318 int class = dd->bDeviceClass;
320 class = interface->bInterfaceClass;
322 enum { hid_device = 0x3, msc_device = 0x8, hub_device = 0x9 };
324 printf ("device of class %x found\n", class);
325 if (class == hub_device) {
326 printf ("hub found\n");
327 #ifdef CONFIG_USB_HUB
328 controller->devices[adr].init = usb_hub_init;
330 printf ("support not compiled in\n");
333 if (class == hid_device) {
334 printf ("HID found\n");
335 #ifdef CONFIG_USB_HID
336 controller->devices[adr].init = usb_hid_init;
338 printf ("support not compiled in\n");
341 if (class == msc_device) {
342 printf ("MSC found\n");
343 #ifdef CONFIG_USB_MSC
344 controller->devices[adr].init = usb_msc_init;
346 printf ("support not compiled in\n");