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
32 #include <libpayload.h>
35 typedef enum { host_to_device = 0, device_to_host = 1 } dev_req_dir;
36 typedef enum { standard_type = 0, class_type = 1, vendor_type =
39 typedef enum { dev_recp = 0, iface_recp = 1, endp_recp = 2, other_recp = 3
49 GET_CONFIGURATION = 8,
50 SET_CONFIGURATION = 9,
58 DEVICE_REMOTE_WAKEUP = 1,
65 dev_req_recp req_recp:5;
66 dev_req_type req_type:2;
67 dev_req_dir data_dir:1;
68 } __attribute__ ((packed));
69 unsigned char bmRequestType;
70 } __attribute__ ((packed));
71 unsigned char bRequest;
72 unsigned short wValue;
73 unsigned short wIndex;
74 unsigned short wLength;
75 } __attribute__ ((packed)) dev_req_t;
78 typedef struct usbdev_hc hci_t;
81 typedef struct usbdev usbdev_t;
83 typedef enum { SETUP = 0x2d, IN = 0x69, OUT = 0xe1 } pid_t;
84 typedef enum { CONTROL = 0, ISOCHRONOUS = 1, BULK = 2, INTERRUPT = 3
99 endpoint_t endpoints[32];
101 int address; // usb address
102 int hub; // hub, device is attached to
103 int port; // port where device is attached
104 int lowspeed; // 1 if lowspeed device
108 void (*init) (usbdev_t *dev);
109 void (*destroy) (usbdev_t *dev);
110 void (*poll) (usbdev_t *dev);
114 struct usbdev_hc *next;
115 pcidev_t bus_address;
117 usbdev_t *devices[128]; // dev 0 is root hub, 127 is last addressable
118 void (*start) (hci_t *controller);
119 void (*stop) (hci_t *controller);
120 void (*reset) (hci_t *controller);
121 void (*shutdown) (hci_t *controller);
122 int (*packet) (usbdev_t *dev, int endp, int pid, int toggle,
123 int length, u8 *data);
124 int (*bulk) (endpoint_t *ep, int size, u8 *data, int finalize);
125 int (*control) (usbdev_t *dev, pid_t pid, int dr_length,
126 void *devreq, int data_length, u8 *data);
127 void* (*create_intr_queue) (endpoint_t *ep, int reqsize, int reqcount, int reqtiming);
128 void (*destroy_intr_queue) (endpoint_t *ep, void *queue);
129 u8* (*poll_intr_queue) (void *queue);
134 unsigned char bDescLength;
135 unsigned char bDescriptorType;
136 unsigned char bNbrPorts;
139 unsigned long logicalPowerSwitchingMode:2;
140 unsigned long isCompoundDevice:1;
141 unsigned long overcurrentProtectionMode:2;
142 unsigned long ttThinkTime:2;
143 unsigned long arePortIndicatorsSupported:1;
145 } __attribute__ ((packed));
146 unsigned short wHubCharacteristics;
147 } __attribute__ ((packed));
148 unsigned char bPowerOn2PwrGood;
149 unsigned char bHubContrCurrent;
150 char DeviceRemovable[];
151 } __attribute__ ((packed)) hub_descriptor_t;
154 unsigned char bLength;
155 unsigned char bDescriptorType;
156 unsigned short bcdUSB;
157 unsigned char bDeviceClass;
158 unsigned char bDeviceSubClass;
159 unsigned char bDeviceProtocol;
160 unsigned char bMaxPacketSize0;
161 unsigned short idVendor;
162 unsigned short idProduct;
163 unsigned short bcdDevice;
164 unsigned char iManufacturer;
165 unsigned char iProduct;
166 unsigned char iSerialNumber;
167 unsigned char bNumConfigurations;
168 } __attribute__ ((packed)) device_descriptor_t;
171 unsigned char bLength;
172 unsigned char bDescriptorType;
173 unsigned short wTotalLength;
174 unsigned char bNumInterfaces;
175 unsigned char bConfigurationValue;
176 unsigned char iConfiguration;
177 unsigned char bmAttributes;
178 unsigned char bMaxPower;
179 } __attribute__ ((packed)) configuration_descriptor_t;
182 unsigned char bLength;
183 unsigned char bDescriptorType;
184 unsigned char bInterfaceNumber;
185 unsigned char bAlternateSetting;
186 unsigned char bNumEndpoints;
187 unsigned char bInterfaceClass;
188 unsigned char bInterfaceSubClass;
189 unsigned char bInterfaceProtocol;
190 unsigned char iInterface;
191 } __attribute__ ((packed)) interface_descriptor_t;
194 unsigned char bLength;
195 unsigned char bDescriptorType;
196 unsigned char bEndpointAddress;
197 unsigned char bmAttributes;
198 unsigned short wMaxPacketSize;
199 unsigned char bInterval;
200 } __attribute__ ((packed)) endpoint_descriptor_t;
202 hci_t *new_controller (void);
203 void detach_controller (hci_t *controller);
204 void usb_poll (void);
205 void init_device_entry (hci_t *controller, int num);
207 void set_feature (usbdev_t *dev, int endp, int feature, int rtype);
208 void get_status (usbdev_t *dev, int endp, int rtype, int len, void *data);
209 int clear_stall (endpoint_t *ep);
211 void usb_nop_init (usbdev_t *dev);
212 void usb_hub_init (usbdev_t *dev);
213 void usb_hid_init (usbdev_t *dev);
214 void usb_msc_init (usbdev_t *dev);
216 int set_address (hci_t *controller, int lowspeed);
218 u8 *get_descriptor (usbdev_t *dev, unsigned char bmRequestType,
219 int descType, int descIdx, int langID);
221 static inline unsigned char
222 gen_bmRequestType (dev_req_dir dir, dev_req_type type, dev_req_recp recp)
224 return (dir << 7) | (type << 5) | recp;
227 void usb_detach_device(hci_t *controller, int devno);
228 int usb_attach_device(hci_t *controller, int hubaddress, int port, int lowspeed);
230 void usb_fatal(const char *message) __attribute__ ((noreturn));