diff options
author | Frank Gevaerts <frank@gevaerts.be> | 2008-02-20 22:54:26 +0000 |
---|---|---|
committer | Frank Gevaerts <frank@gevaerts.be> | 2008-02-20 22:54:26 +0000 |
commit | 07427592a928ab3d164fbcca842399af6d5ca7ef (patch) | |
tree | eb7b1b748f8ac9ea28ce357290bc5992f5e2403f /firmware/usbstack/usb_core.c | |
parent | 6af732d17aa1eb882e3c52242b2bf7f2fcccc752 (diff) | |
download | rockbox-07427592a928ab3d164fbcca842399af6d5ca7ef.tar.gz rockbox-07427592a928ab3d164fbcca842399af6d5ca7ef.zip |
Major USB stack improvements. It now works at nearly the maximum speed for a full speed connection, and does seem stable.
Still not enabled by default, #define USE_ROCKBOX_USB is still required to enable it.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@16360 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'firmware/usbstack/usb_core.c')
-rw-r--r-- | firmware/usbstack/usb_core.c | 508 |
1 files changed, 264 insertions, 244 deletions
diff --git a/firmware/usbstack/usb_core.c b/firmware/usbstack/usb_core.c index 13993f9271..c68093b0d2 100644 --- a/firmware/usbstack/usb_core.c +++ b/firmware/usbstack/usb_core.c | |||
@@ -23,44 +23,42 @@ | |||
23 | //#define LOGF_ENABLE | 23 | //#define LOGF_ENABLE |
24 | #include "logf.h" | 24 | #include "logf.h" |
25 | 25 | ||
26 | #ifndef BOOTLOADER | ||
27 | //#define USB_SERIAL | ||
28 | //#define USB_BENCHMARK | ||
29 | #ifdef USE_ROCKBOX_USB | ||
30 | #define USB_STORAGE | ||
31 | #else | ||
32 | #define USB_CHARGING_ONLY | ||
33 | #endif /* USE_ROCKBOX_USB */ | ||
34 | #else | ||
35 | #define USB_CHARGING_ONLY | ||
36 | #endif | ||
37 | |||
38 | #include "usb_ch9.h" | 26 | #include "usb_ch9.h" |
39 | #include "usb_drv.h" | 27 | #include "usb_drv.h" |
40 | #include "usb_core.h" | 28 | #include "usb_core.h" |
41 | 29 | ||
30 | #define USB_THREAD | ||
31 | |||
42 | #if defined(USB_STORAGE) | 32 | #if defined(USB_STORAGE) |
43 | #include "usb_storage.h" | 33 | #include "usb_storage.h" |
44 | #define USB_THREAD | 34 | #endif |
45 | #elif defined(USB_SERIAL) | 35 | |
46 | #define USB_THREAD | 36 | #if defined(USB_SERIAL) |
47 | #include "usb_serial.h" | 37 | #include "usb_serial.h" |
48 | #elif defined(USB_BENCHMARK) | 38 | #endif |
39 | |||
40 | #if defined(USB_BENCHMARK) | ||
49 | #include "usb_benchmark.h" | 41 | #include "usb_benchmark.h" |
50 | #endif | 42 | #endif |
51 | 43 | ||
44 | /* TODO: Move this target-specific stuff somewhere else (serial number reading) */ | ||
45 | |||
46 | #ifdef HAVE_AS3514 | ||
47 | #include "i2c-pp.h" | ||
48 | #include "as3514.h" | ||
49 | #endif | ||
50 | |||
51 | |||
52 | /*-------------------------------------------------------------------------*/ | 52 | /*-------------------------------------------------------------------------*/ |
53 | /* USB protocol descriptors: */ | 53 | /* USB protocol descriptors: */ |
54 | 54 | ||
55 | #define USB_SC_SCSI 0x06 /* Transparent */ | 55 | #define USB_SC_SCSI 0x06 /* Transparent */ |
56 | #define USB_PROT_BULK 0x50 /* bulk only */ | 56 | #define USB_PROT_BULK 0x50 /* bulk only */ |
57 | 57 | ||
58 | int usb_max_pkt_size = 512; | 58 | static const struct usb_device_descriptor device_descriptor= { |
59 | |||
60 | static const struct usb_device_descriptor device_descriptor = { | ||
61 | .bLength = sizeof(struct usb_device_descriptor), | 59 | .bLength = sizeof(struct usb_device_descriptor), |
62 | .bDescriptorType = USB_DT_DEVICE, | 60 | .bDescriptorType = USB_DT_DEVICE, |
63 | .bcdUSB = 0x0200, /* USB version 2.0 */ | 61 | .bcdUSB = 0x0200, |
64 | .bDeviceClass = USB_CLASS_PER_INTERFACE, | 62 | .bDeviceClass = USB_CLASS_PER_INTERFACE, |
65 | .bDeviceSubClass = 0, | 63 | .bDeviceSubClass = 0, |
66 | .bDeviceProtocol = 0, | 64 | .bDeviceProtocol = 0, |
@@ -74,158 +72,34 @@ static const struct usb_device_descriptor device_descriptor = { | |||
74 | .bNumConfigurations = 1 | 72 | .bNumConfigurations = 1 |
75 | }; | 73 | }; |
76 | 74 | ||
77 | static const struct { | 75 | static struct { |
78 | struct usb_config_descriptor config_descriptor; | 76 | struct usb_config_descriptor config_descriptor; |
79 | struct usb_interface_descriptor interface_descriptor; | ||
80 | struct usb_endpoint_descriptor ep1_in_descriptor; | ||
81 | struct usb_endpoint_descriptor ep1_out_descriptor; | ||
82 | } config_data_fs = | ||
83 | { | ||
84 | { | ||
85 | .bLength = sizeof(struct usb_config_descriptor), | ||
86 | .bDescriptorType = USB_DT_CONFIG, | ||
87 | .wTotalLength = sizeof config_data_fs, | ||
88 | .bNumInterfaces = 1, | ||
89 | .bConfigurationValue = 1, | ||
90 | .iConfiguration = 0, | ||
91 | .bmAttributes = USB_CONFIG_ATT_ONE | USB_CONFIG_ATT_SELFPOWER, | ||
92 | .bMaxPower = 250, /* 500mA in 2mA units */ | ||
93 | }, | ||
94 | |||
95 | #ifdef USB_CHARGING_ONLY | 77 | #ifdef USB_CHARGING_ONLY |
96 | /* dummy interface for charging-only */ | 78 | struct usb_interface_descriptor charging_interface_descriptor; |
97 | { | 79 | struct usb_endpoint_descriptor charging_ep_in_descriptor; |
98 | .bLength = sizeof(struct usb_interface_descriptor), | 80 | struct usb_endpoint_descriptor charging_ep_out_descriptor; |
99 | .bDescriptorType = USB_DT_INTERFACE, | ||
100 | .bInterfaceNumber = 0, | ||
101 | .bAlternateSetting = 0, | ||
102 | .bNumEndpoints = 2, | ||
103 | .bInterfaceClass = USB_CLASS_VENDOR_SPEC, | ||
104 | .bInterfaceSubClass = 0, | ||
105 | .bInterfaceProtocol = 0, | ||
106 | .iInterface = 5 | ||
107 | }, | ||
108 | |||
109 | { | ||
110 | .bLength = sizeof(struct usb_endpoint_descriptor), | ||
111 | .bDescriptorType = USB_DT_ENDPOINT, | ||
112 | .bEndpointAddress = EP_TX | USB_DIR_IN, | ||
113 | .bmAttributes = USB_ENDPOINT_XFER_BULK, | ||
114 | .wMaxPacketSize = 512, | ||
115 | .bInterval = 0 | ||
116 | }, | ||
117 | { | ||
118 | .bLength = sizeof(struct usb_endpoint_descriptor), | ||
119 | .bDescriptorType = USB_DT_ENDPOINT, | ||
120 | .bEndpointAddress = EP_RX | USB_DIR_OUT, | ||
121 | .bmAttributes = USB_ENDPOINT_XFER_BULK, | ||
122 | .wMaxPacketSize = 512, | ||
123 | .bInterval = 0 | ||
124 | } | ||
125 | #endif | 81 | #endif |
126 | |||
127 | #ifdef USB_STORAGE | 82 | #ifdef USB_STORAGE |
128 | /* storage interface */ | 83 | struct usb_interface_descriptor mass_storage_interface_descriptor; |
129 | { | 84 | struct usb_endpoint_descriptor mass_storage_ep_in_descriptor; |
130 | .bLength = sizeof(struct usb_interface_descriptor), | 85 | struct usb_endpoint_descriptor mass_storage_ep_out_descriptor; |
131 | .bDescriptorType = USB_DT_INTERFACE, | ||
132 | .bInterfaceNumber = 0, | ||
133 | .bAlternateSetting = 0, | ||
134 | .bNumEndpoints = 2, | ||
135 | .bInterfaceClass = USB_CLASS_MASS_STORAGE, | ||
136 | .bInterfaceSubClass = USB_SC_SCSI, | ||
137 | .bInterfaceProtocol = USB_PROT_BULK, | ||
138 | .iInterface = 0 | ||
139 | }, | ||
140 | |||
141 | { | ||
142 | .bLength = sizeof(struct usb_endpoint_descriptor), | ||
143 | .bDescriptorType = USB_DT_ENDPOINT, | ||
144 | .bEndpointAddress = EP_TX | USB_DIR_IN, | ||
145 | .bmAttributes = USB_ENDPOINT_XFER_BULK, | ||
146 | .wMaxPacketSize = 16, | ||
147 | .bInterval = 0 | ||
148 | }, | ||
149 | { | ||
150 | .bLength = sizeof(struct usb_endpoint_descriptor), | ||
151 | .bDescriptorType = USB_DT_ENDPOINT, | ||
152 | .bEndpointAddress = EP_RX | USB_DIR_OUT, | ||
153 | .bmAttributes = USB_ENDPOINT_XFER_BULK, | ||
154 | .wMaxPacketSize = 16, | ||
155 | .bInterval = 0 | ||
156 | } | ||
157 | #endif | 86 | #endif |
158 | |||
159 | #ifdef USB_SERIAL | 87 | #ifdef USB_SERIAL |
160 | /* serial interface */ | 88 | struct usb_interface_descriptor serial_interface_descriptor; |
161 | { | 89 | struct usb_endpoint_descriptor serial_ep_in_descriptor; |
162 | .bLength = sizeof(struct usb_interface_descriptor), | 90 | struct usb_endpoint_descriptor serial_ep_out_descriptor; |
163 | .bDescriptorType = USB_DT_INTERFACE, | ||
164 | .bInterfaceNumber = 0, | ||
165 | .bAlternateSetting = 0, | ||
166 | .bNumEndpoints = 2, | ||
167 | .bInterfaceClass = USB_CLASS_CDC_DATA, | ||
168 | .bInterfaceSubClass = 0, | ||
169 | .bInterfaceProtocol = 0, | ||
170 | .iInterface = 0 | ||
171 | }, | ||
172 | |||
173 | { | ||
174 | .bLength = sizeof(struct usb_endpoint_descriptor), | ||
175 | .bDescriptorType = USB_DT_ENDPOINT, | ||
176 | .bEndpointAddress = EP_TX | USB_DIR_IN, | ||
177 | .bmAttributes = USB_ENDPOINT_XFER_BULK, | ||
178 | .wMaxPacketSize = 64, | ||
179 | .bInterval = 0 | ||
180 | }, | ||
181 | { | ||
182 | .bLength = sizeof(struct usb_endpoint_descriptor), | ||
183 | .bDescriptorType = USB_DT_ENDPOINT, | ||
184 | .bEndpointAddress = EP_RX | USB_DIR_OUT, | ||
185 | .bmAttributes = USB_ENDPOINT_XFER_BULK, | ||
186 | .wMaxPacketSize = 64, | ||
187 | .bInterval = 0 | ||
188 | } | ||
189 | #endif | 91 | #endif |
190 | |||
191 | #ifdef USB_BENCHMARK | 92 | #ifdef USB_BENCHMARK |
192 | /* bulk test interface */ | 93 | struct usb_interface_descriptor benchmark_interface_descriptor; |
193 | { | 94 | struct usb_endpoint_descriptor benchmark_ep_in_descriptor; |
194 | .bLength = sizeof(struct usb_interface_descriptor), | 95 | struct usb_endpoint_descriptor benchmark_ep_out_descriptor; |
195 | .bDescriptorType = USB_DT_INTERFACE, | ||
196 | .bInterfaceNumber = 0, | ||
197 | .bAlternateSetting = 0, | ||
198 | .bNumEndpoints = 2, | ||
199 | .bInterfaceClass = USB_CLASS_VENDOR_SPEC, | ||
200 | .bInterfaceSubClass = 255, | ||
201 | .bInterfaceProtocol = 255, | ||
202 | .iInterface = 4 | ||
203 | }, | ||
204 | |||
205 | { | ||
206 | .bLength = sizeof(struct usb_endpoint_descriptor), | ||
207 | .bDescriptorType = USB_DT_ENDPOINT, | ||
208 | .bEndpointAddress = EP_RX | USB_DIR_OUT, | ||
209 | .bmAttributes = USB_ENDPOINT_XFER_BULK, | ||
210 | .wMaxPacketSize = 64, | ||
211 | .bInterval = 0 | ||
212 | }, | ||
213 | { | ||
214 | .bLength = sizeof(struct usb_endpoint_descriptor), | ||
215 | .bDescriptorType = USB_DT_ENDPOINT, | ||
216 | .bEndpointAddress = EP_TX | USB_DIR_IN, | ||
217 | .bmAttributes = USB_ENDPOINT_XFER_BULK, | ||
218 | .wMaxPacketSize = 64, | ||
219 | .bInterval = 0 | ||
220 | } | ||
221 | #endif | 96 | #endif |
222 | }, | 97 | } __attribute__((packed)) *config_data, _config_data = |
223 | config_data_hs = | ||
224 | { | 98 | { |
225 | { | 99 | { |
226 | .bLength = sizeof(struct usb_config_descriptor), | 100 | .bLength = sizeof(struct usb_config_descriptor), |
227 | .bDescriptorType = USB_DT_CONFIG, | 101 | .bDescriptorType = USB_DT_CONFIG, |
228 | .wTotalLength = sizeof config_data_hs, | 102 | .wTotalLength = sizeof _config_data, |
229 | .bNumInterfaces = 1, | 103 | .bNumInterfaces = 1, |
230 | .bConfigurationValue = 1, | 104 | .bConfigurationValue = 1, |
231 | .iConfiguration = 0, | 105 | .iConfiguration = 0, |
@@ -246,23 +120,23 @@ config_data_hs = | |||
246 | .bInterfaceProtocol = 0, | 120 | .bInterfaceProtocol = 0, |
247 | .iInterface = 5 | 121 | .iInterface = 5 |
248 | }, | 122 | }, |
249 | 123 | /* TODO: try with zero endpoints */ | |
250 | { | 124 | { |
251 | .bLength = sizeof(struct usb_endpoint_descriptor), | 125 | .bLength = sizeof(struct usb_endpoint_descriptor), |
252 | .bDescriptorType = USB_DT_ENDPOINT, | 126 | .bDescriptorType = USB_DT_ENDPOINT, |
253 | .bEndpointAddress = EP_TX | USB_DIR_IN, | 127 | .bEndpointAddress = EP_CHARGING_ONLY | USB_DIR_IN, |
254 | .bmAttributes = USB_ENDPOINT_XFER_BULK, | 128 | .bmAttributes = USB_ENDPOINT_XFER_BULK, |
255 | .wMaxPacketSize = 512, | 129 | .wMaxPacketSize = 16, |
256 | .bInterval = 0 | 130 | .bInterval = 0 |
257 | }, | 131 | }, |
258 | { | 132 | { |
259 | .bLength = sizeof(struct usb_endpoint_descriptor), | 133 | .bLength = sizeof(struct usb_endpoint_descriptor), |
260 | .bDescriptorType = USB_DT_ENDPOINT, | 134 | .bDescriptorType = USB_DT_ENDPOINT, |
261 | .bEndpointAddress = EP_RX | USB_DIR_OUT, | 135 | .bEndpointAddress = EP_CHARGING_ONLY | USB_DIR_OUT, |
262 | .bmAttributes = USB_ENDPOINT_XFER_BULK, | 136 | .bmAttributes = USB_ENDPOINT_XFER_BULK, |
263 | .wMaxPacketSize = 512, | 137 | .wMaxPacketSize = 16, |
264 | .bInterval = 0 | 138 | .bInterval = 0 |
265 | } | 139 | }, |
266 | #endif | 140 | #endif |
267 | 141 | ||
268 | #ifdef USB_STORAGE | 142 | #ifdef USB_STORAGE |
@@ -282,19 +156,19 @@ config_data_hs = | |||
282 | { | 156 | { |
283 | .bLength = sizeof(struct usb_endpoint_descriptor), | 157 | .bLength = sizeof(struct usb_endpoint_descriptor), |
284 | .bDescriptorType = USB_DT_ENDPOINT, | 158 | .bDescriptorType = USB_DT_ENDPOINT, |
285 | .bEndpointAddress = EP_TX | USB_DIR_IN, | 159 | .bEndpointAddress = EP_MASS_STORAGE | USB_DIR_IN, |
286 | .bmAttributes = USB_ENDPOINT_XFER_BULK, | 160 | .bmAttributes = USB_ENDPOINT_XFER_BULK, |
287 | .wMaxPacketSize = 512, | 161 | .wMaxPacketSize = 16, |
288 | .bInterval = 0 | 162 | .bInterval = 0 |
289 | }, | 163 | }, |
290 | { | 164 | { |
291 | .bLength = sizeof(struct usb_endpoint_descriptor), | 165 | .bLength = sizeof(struct usb_endpoint_descriptor), |
292 | .bDescriptorType = USB_DT_ENDPOINT, | 166 | .bDescriptorType = USB_DT_ENDPOINT, |
293 | .bEndpointAddress = EP_RX | USB_DIR_OUT, | 167 | .bEndpointAddress = EP_MASS_STORAGE | USB_DIR_OUT, |
294 | .bmAttributes = USB_ENDPOINT_XFER_BULK, | 168 | .bmAttributes = USB_ENDPOINT_XFER_BULK, |
295 | .wMaxPacketSize = 512, | 169 | .wMaxPacketSize = 16, |
296 | .bInterval = 0 | 170 | .bInterval = 0 |
297 | } | 171 | }, |
298 | #endif | 172 | #endif |
299 | 173 | ||
300 | #ifdef USB_SERIAL | 174 | #ifdef USB_SERIAL |
@@ -314,19 +188,19 @@ config_data_hs = | |||
314 | { | 188 | { |
315 | .bLength = sizeof(struct usb_endpoint_descriptor), | 189 | .bLength = sizeof(struct usb_endpoint_descriptor), |
316 | .bDescriptorType = USB_DT_ENDPOINT, | 190 | .bDescriptorType = USB_DT_ENDPOINT, |
317 | .bEndpointAddress = EP_TX | USB_DIR_IN, | 191 | .bEndpointAddress = EP_SERIAL | USB_DIR_IN, |
318 | .bmAttributes = USB_ENDPOINT_XFER_BULK, | 192 | .bmAttributes = USB_ENDPOINT_XFER_BULK, |
319 | .wMaxPacketSize = 512, | 193 | .wMaxPacketSize = 16, |
320 | .bInterval = 0 | 194 | .bInterval = 0 |
321 | }, | 195 | }, |
322 | { | 196 | { |
323 | .bLength = sizeof(struct usb_endpoint_descriptor), | 197 | .bLength = sizeof(struct usb_endpoint_descriptor), |
324 | .bDescriptorType = USB_DT_ENDPOINT, | 198 | .bDescriptorType = USB_DT_ENDPOINT, |
325 | .bEndpointAddress = EP_RX | USB_DIR_OUT, | 199 | .bEndpointAddress = EP_SERIAL | USB_DIR_OUT, |
326 | .bmAttributes = USB_ENDPOINT_XFER_BULK, | 200 | .bmAttributes = USB_ENDPOINT_XFER_BULK, |
327 | .wMaxPacketSize = 512, | 201 | .wMaxPacketSize = 16, |
328 | .bInterval = 0 | 202 | .bInterval = 0 |
329 | } | 203 | }, |
330 | #endif | 204 | #endif |
331 | 205 | ||
332 | #ifdef USB_BENCHMARK | 206 | #ifdef USB_BENCHMARK |
@@ -346,19 +220,19 @@ config_data_hs = | |||
346 | { | 220 | { |
347 | .bLength = sizeof(struct usb_endpoint_descriptor), | 221 | .bLength = sizeof(struct usb_endpoint_descriptor), |
348 | .bDescriptorType = USB_DT_ENDPOINT, | 222 | .bDescriptorType = USB_DT_ENDPOINT, |
349 | .bEndpointAddress = EP_RX | USB_DIR_OUT, | 223 | .bEndpointAddress = EP_BENCHMARK | USB_DIR_OUT, |
350 | .bmAttributes = USB_ENDPOINT_XFER_BULK, | 224 | .bmAttributes = USB_ENDPOINT_XFER_BULK, |
351 | .wMaxPacketSize = 512, | 225 | .wMaxPacketSize = 16, |
352 | .bInterval = 0 | 226 | .bInterval = 0 |
353 | }, | 227 | }, |
354 | { | 228 | { |
355 | .bLength = sizeof(struct usb_endpoint_descriptor), | 229 | .bLength = sizeof(struct usb_endpoint_descriptor), |
356 | .bDescriptorType = USB_DT_ENDPOINT, | 230 | .bDescriptorType = USB_DT_ENDPOINT, |
357 | .bEndpointAddress = EP_TX | USB_DIR_IN, | 231 | .bEndpointAddress = EP_BENCHMARK | USB_DIR_IN, |
358 | .bmAttributes = USB_ENDPOINT_XFER_BULK, | 232 | .bmAttributes = USB_ENDPOINT_XFER_BULK, |
359 | .wMaxPacketSize = 512, | 233 | .wMaxPacketSize = 16, |
360 | .bInterval = 0 | 234 | .bInterval = 0 |
361 | } | 235 | }, |
362 | #endif | 236 | #endif |
363 | }; | 237 | }; |
364 | 238 | ||
@@ -388,13 +262,22 @@ static struct usb_string_descriptor usb_string_iProduct = | |||
388 | {'R','o','c','k','b','o','x',' ','m','e','d','i','a',' ','p','l','a','y','e','r'} | 262 | {'R','o','c','k','b','o','x',' ','m','e','d','i','a',' ','p','l','a','y','e','r'} |
389 | }; | 263 | }; |
390 | 264 | ||
265 | #if defined(HAVE_AS3514) | ||
391 | static struct usb_string_descriptor usb_string_iSerial = | 266 | static struct usb_string_descriptor usb_string_iSerial = |
392 | { | 267 | { |
393 | 34, | 268 | 66, |
394 | USB_DT_STRING, | 269 | USB_DT_STRING, |
395 | {'0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0'} | 270 | {'0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0', |
271 | '0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0'} | ||
396 | }; | 272 | }; |
397 | 273 | #else | |
274 | static struct usb_string_descriptor usb_string_iSerial = | ||
275 | { | ||
276 | 34, | ||
277 | USB_DT_STRING, | ||
278 | {'0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0'} | ||
279 | }; | ||
280 | #endif | ||
398 | 281 | ||
399 | /* Generic for all targets */ | 282 | /* Generic for all targets */ |
400 | 283 | ||
@@ -443,10 +326,25 @@ static long usbcore_stack[DEFAULT_STACK_SIZE]; | |||
443 | static void usb_core_thread(void); | 326 | static void usb_core_thread(void); |
444 | #endif | 327 | #endif |
445 | 328 | ||
446 | static void ack_control(struct usb_ctrlrequest* req); | 329 | static void usb_core_control_request_handler(struct usb_ctrlrequest* req); |
330 | static int ack_control(struct usb_ctrlrequest* req); | ||
331 | |||
332 | static unsigned char *response_data; | ||
333 | static unsigned char __response_data[CACHEALIGN_UP(2)] CACHEALIGN_ATTR; | ||
334 | |||
335 | struct usb_core_event | ||
336 | { | ||
337 | unsigned char endpoint; | ||
338 | bool in; | ||
339 | int status; | ||
340 | int length; | ||
341 | void* data; | ||
342 | }; | ||
343 | |||
344 | static struct usb_core_event events[NUM_ENDPOINTS]; | ||
447 | 345 | ||
448 | #ifdef IPOD_ARCH | 346 | #ifdef IPOD_ARCH |
449 | void set_serial_descriptor(void) | 347 | static void set_serial_descriptor(void) |
450 | { | 348 | { |
451 | static short hex[16] = {'0','1','2','3','4','5','6','7', | 349 | static short hex[16] = {'0','1','2','3','4','5','6','7', |
452 | '8','9','A','B','C','D','E','F'}; | 350 | '8','9','A','B','C','D','E','F'}; |
@@ -471,7 +369,23 @@ void set_serial_descriptor(void) | |||
471 | x >>= 4; | 369 | x >>= 4; |
472 | } | 370 | } |
473 | } | 371 | } |
372 | } | ||
373 | #elif defined(HAVE_AS3514) | ||
374 | static void set_serial_descriptor(void) | ||
375 | { | ||
376 | static short hex[16] = {'0','1','2','3','4','5','6','7', | ||
377 | '8','9','A','B','C','D','E','F'}; | ||
474 | 378 | ||
379 | unsigned char serial[16]; | ||
380 | short* p = usb_string_iSerial.wString; | ||
381 | int i; | ||
382 | |||
383 | i2c_readbytes(AS3514_I2C_ADDR, 0x30, 0x10, serial); | ||
384 | for (i = 0; i < 16; i++) | ||
385 | { | ||
386 | *p++ = hex[(serial[i] >> 4) & 0xF]; | ||
387 | *p++ = hex[(serial[i] >> 0) & 0xF]; | ||
388 | } | ||
475 | } | 389 | } |
476 | #endif | 390 | #endif |
477 | 391 | ||
@@ -480,9 +394,8 @@ void usb_core_init(void) | |||
480 | if (initialized) | 394 | if (initialized) |
481 | return; | 395 | return; |
482 | 396 | ||
483 | #ifdef IPOD_ARCH | 397 | config_data = (void*)UNCACHED_ADDR(&_config_data); |
484 | set_serial_descriptor(); | 398 | response_data = (void*)UNCACHED_ADDR(&__response_data); |
485 | #endif | ||
486 | 399 | ||
487 | queue_init(&usbcore_queue, false); | 400 | queue_init(&usbcore_queue, false); |
488 | usb_drv_init(); | 401 | usb_drv_init(); |
@@ -514,10 +427,11 @@ void usb_core_exit(void) | |||
514 | { | 427 | { |
515 | if (initialized) { | 428 | if (initialized) { |
516 | usb_drv_exit(); | 429 | usb_drv_exit(); |
517 | queue_delete(&usbcore_queue); | ||
518 | #ifdef USB_THREAD | 430 | #ifdef USB_THREAD |
519 | remove_thread(usbcore_thread); | 431 | queue_post(&usbcore_queue, USB_CORE_QUIT, 0); |
432 | thread_wait(usbcore_thread); | ||
520 | #endif | 433 | #endif |
434 | queue_delete(&usbcore_queue); | ||
521 | } | 435 | } |
522 | data_connection = false; | 436 | data_connection = false; |
523 | initialized = false; | 437 | initialized = false; |
@@ -532,25 +446,52 @@ bool usb_core_data_connection(void) | |||
532 | #ifdef USB_THREAD | 446 | #ifdef USB_THREAD |
533 | void usb_core_thread(void) | 447 | void usb_core_thread(void) |
534 | { | 448 | { |
449 | #if defined(IPOD_ARCH) || defined(HAVE_AS3514) | ||
450 | set_serial_descriptor(); | ||
451 | #endif | ||
452 | |||
535 | while (1) { | 453 | while (1) { |
536 | struct queue_event ev; | 454 | struct queue_event ev; |
537 | 455 | ||
538 | queue_wait(&usbcore_queue, &ev); | 456 | queue_wait(&usbcore_queue, &ev); |
457 | if (ev.id == USB_CORE_QUIT) { | ||
458 | cancel_cpu_boost(); | ||
459 | return; | ||
460 | } | ||
539 | 461 | ||
462 | if (ev.id == USB_CORE_TRANSFER_COMPLETION) { | ||
463 | struct usb_core_event* event = (struct usb_core_event*)ev.data; | ||
464 | switch(event->endpoint) { | ||
465 | case EP_CONTROL: | ||
466 | logf("ctrl handled %ld",current_tick); | ||
467 | usb_core_control_request_handler((struct usb_ctrlrequest*)event->data); | ||
468 | break; | ||
540 | #ifdef USB_STORAGE | 469 | #ifdef USB_STORAGE |
541 | usb_storage_transfer_complete(ev.id); | 470 | case EP_MASS_STORAGE: |
471 | usb_storage_transfer_complete(event->in,event->status,event->length); | ||
472 | break; | ||
542 | #endif | 473 | #endif |
543 | |||
544 | #ifdef USB_SERIAL | 474 | #ifdef USB_SERIAL |
545 | usb_serial_transfer_complete(ev.id); | 475 | case EP_SERIAL: |
476 | usb_serial_transfer_complete(event->in,event->status,event->length); | ||
477 | break; | ||
546 | #endif | 478 | #endif |
547 | 479 | #ifdef USB_BENCHMARK | |
480 | case EP_BENCHMARK: | ||
481 | usb_benchmark_transfer_complete(event->in); | ||
482 | break; | ||
483 | #endif | ||
484 | #ifdef USB_CHARGING_ONLY | ||
485 | case EP_CHARGING_ONLY: | ||
486 | break; | ||
487 | #endif | ||
488 | } | ||
489 | } | ||
548 | } | 490 | } |
549 | } | 491 | } |
550 | #endif | 492 | #endif |
551 | 493 | ||
552 | /* called by usb_drv_int() */ | 494 | static void usb_core_control_request_handler(struct usb_ctrlrequest* req) |
553 | void usb_core_control_request(struct usb_ctrlrequest* req) | ||
554 | { | 495 | { |
555 | /* note: interrupt context */ | 496 | /* note: interrupt context */ |
556 | data_connection = true; | 497 | data_connection = true; |
@@ -565,29 +506,31 @@ void usb_core_control_request(struct usb_ctrlrequest* req) | |||
565 | switch (req->bRequest) { | 506 | switch (req->bRequest) { |
566 | case USB_REQ_SET_CONFIGURATION: | 507 | case USB_REQ_SET_CONFIGURATION: |
567 | logf("usb_core: SET_CONFIG"); | 508 | logf("usb_core: SET_CONFIG"); |
509 | usb_drv_cancel_all_transfers(); | ||
510 | if (req->wValue){ | ||
511 | usb_state = CONFIGURED; | ||
568 | #ifdef USB_STORAGE | 512 | #ifdef USB_STORAGE |
569 | usb_storage_control_request(req); | 513 | usb_storage_control_request(req); |
570 | #endif | 514 | #endif |
571 | 515 | ||
572 | #ifdef USB_SERIAL | 516 | #ifdef USB_SERIAL |
573 | usb_serial_control_request(req); | 517 | usb_serial_control_request(req); |
574 | #endif | 518 | #endif |
575 | ack_control(req); | 519 | } |
576 | if (req->wValue) | 520 | else { |
577 | usb_state = CONFIGURED; | ||
578 | else | ||
579 | usb_state = ADDRESS; | 521 | usb_state = ADDRESS; |
522 | } | ||
523 | ack_control(req); | ||
580 | break; | 524 | break; |
581 | 525 | ||
582 | case USB_REQ_GET_CONFIGURATION: { | 526 | case USB_REQ_GET_CONFIGURATION: { |
583 | static char confignum; | ||
584 | char* tmp = (void*)UNCACHED_ADDR(&confignum); | ||
585 | logf("usb_core: GET_CONFIG"); | 527 | logf("usb_core: GET_CONFIG"); |
586 | if (usb_state == ADDRESS) | 528 | if (usb_state == ADDRESS) |
587 | *tmp = 0; | 529 | response_data[0] = 0; |
588 | else | 530 | else |
589 | *tmp = 1; | 531 | response_data[0] = 1; |
590 | usb_drv_send(EP_CONTROL, tmp, 1); | 532 | if(usb_drv_send(EP_CONTROL, response_data, 1)!= 0) |
533 | break; | ||
591 | ack_control(req); | 534 | ack_control(req); |
592 | break; | 535 | break; |
593 | } | 536 | } |
@@ -597,29 +540,54 @@ void usb_core_control_request(struct usb_ctrlrequest* req) | |||
597 | ack_control(req); | 540 | ack_control(req); |
598 | break; | 541 | break; |
599 | 542 | ||
543 | case USB_REQ_GET_INTERFACE: | ||
544 | logf("usb_core: GET_INTERFACE"); | ||
545 | response_data[0] = 0; | ||
546 | if(usb_drv_send(EP_CONTROL, response_data, 1)!=0) | ||
547 | break; | ||
548 | ack_control(req); | ||
549 | break; | ||
600 | case USB_REQ_CLEAR_FEATURE: | 550 | case USB_REQ_CLEAR_FEATURE: |
601 | logf("usb_core: CLEAR_FEATURE"); | 551 | logf("usb_core: CLEAR_FEATURE"); |
602 | if (req->wValue) | 552 | if (req->wValue) |
603 | usb_drv_stall(req->wIndex, true); | 553 | usb_drv_stall(req->wIndex & 0xf, false,(req->wIndex & 0x80) !=0); |
604 | else | 554 | else |
605 | usb_drv_stall(req->wIndex, false); | 555 | usb_drv_stall(req->wIndex & 0xf, false,(req->wIndex & 0x80) !=0); |
606 | ack_control(req); | 556 | ack_control(req); |
607 | break; | 557 | break; |
608 | 558 | ||
609 | case USB_REQ_SET_ADDRESS: | 559 | case USB_REQ_SET_FEATURE: |
610 | usb_address = req->wValue; | 560 | logf("usb_core: SET_FEATURE"); |
611 | logf("usb_core: SET_ADR %d", usb_address); | 561 | if (req->wValue) |
562 | usb_drv_stall(req->wIndex & 0xf, true,(req->wIndex & 0x80) !=0); | ||
563 | else | ||
564 | usb_drv_stall(req->wIndex & 0xf, false,(req->wIndex & 0x80) !=0); | ||
612 | ack_control(req); | 565 | ack_control(req); |
566 | break; | ||
567 | |||
568 | case USB_REQ_SET_ADDRESS: { | ||
569 | unsigned char address = req->wValue; | ||
570 | logf("usb_core: SET_ADR %d", address); | ||
571 | if(ack_control(req)!=0) | ||
572 | break; | ||
573 | usb_drv_cancel_all_transfers(); | ||
574 | usb_address = address; | ||
613 | usb_drv_set_address(usb_address); | 575 | usb_drv_set_address(usb_address); |
614 | usb_state = ADDRESS; | 576 | usb_state = ADDRESS; |
615 | break; | 577 | break; |
578 | } | ||
616 | 579 | ||
617 | case USB_REQ_GET_STATUS: { | 580 | case USB_REQ_GET_STATUS: { |
618 | static char tmp[2] = {0,0}; | 581 | response_data[0]= 0; |
619 | tmp[0] = 0; | 582 | response_data[1]= 0; |
620 | tmp[1] = 0; | ||
621 | logf("usb_core: GET_STATUS"); | 583 | logf("usb_core: GET_STATUS"); |
622 | usb_drv_send(EP_CONTROL, UNCACHED_ADDR(&tmp), 2); | 584 | if(req->wIndex>0) { |
585 | if(usb_drv_stalled(req->wIndex&0xf,(req->wIndex&0x80)!=0)) | ||
586 | response_data[0] = 1; | ||
587 | } | ||
588 | logf("usb_core: %X %X",response_data[0],response_data[1]); | ||
589 | if(usb_drv_send(EP_CONTROL, response_data, 2)!=0) | ||
590 | break; | ||
623 | ack_control(req); | 591 | ack_control(req); |
624 | break; | 592 | break; |
625 | } | 593 | } |
@@ -637,18 +605,59 @@ void usb_core_control_request(struct usb_ctrlrequest* req) | |||
637 | size = sizeof device_descriptor; | 605 | size = sizeof device_descriptor; |
638 | break; | 606 | break; |
639 | 607 | ||
640 | case USB_DT_CONFIG: | 608 | case USB_DT_OTHER_SPEED_CONFIG: |
641 | if(usb_drv_port_speed()) | 609 | case USB_DT_CONFIG: { |
642 | { | 610 | int max_packet_size; |
643 | ptr = &config_data_hs; | 611 | int interface_number=0; |
644 | size = sizeof config_data_hs; | 612 | |
613 | if(req->wValue >> 8 == USB_DT_CONFIG) { | ||
614 | if(usb_drv_port_speed()) { | ||
615 | max_packet_size=512; | ||
616 | } | ||
617 | else { | ||
618 | max_packet_size=64; | ||
619 | } | ||
620 | config_data->config_descriptor.bDescriptorType=USB_DT_CONFIG; | ||
645 | } | 621 | } |
646 | else | 622 | else { |
647 | { | 623 | if(usb_drv_port_speed()) { |
648 | ptr = &config_data_fs; | 624 | max_packet_size=64; |
649 | size = sizeof config_data_fs; | 625 | } |
626 | else { | ||
627 | max_packet_size=512; | ||
628 | } | ||
629 | config_data->config_descriptor.bDescriptorType=USB_DT_OTHER_SPEED_CONFIG; | ||
650 | } | 630 | } |
631 | |||
632 | #ifdef USB_CHARGING_ONLY | ||
633 | memcpy(&config_data->charging_ep_in_descriptor.wMaxPacketSize,&max_packet_size,sizeof(unsigned short)); | ||
634 | memcpy(&config_data->charging_ep_out_descriptor.wMaxPacketSize,&max_packet_size,sizeof(unsigned short)); | ||
635 | config_data->charging_interface_descriptor.bInterfaceNumber=interface_number; | ||
636 | interface_number++; | ||
637 | #endif | ||
638 | #ifdef USB_STORAGE | ||
639 | memcpy(&config_data->mass_storage_ep_in_descriptor.wMaxPacketSize,&max_packet_size,sizeof(unsigned short)); | ||
640 | memcpy(&config_data->mass_storage_ep_out_descriptor.wMaxPacketSize,&max_packet_size,sizeof(unsigned short)); | ||
641 | config_data->mass_storage_interface_descriptor.bInterfaceNumber=interface_number; | ||
642 | interface_number++; | ||
643 | #endif | ||
644 | #ifdef USB_SERIAL | ||
645 | memcpy(&config_data->serial_ep_in_descriptor.wMaxPacketSize,&max_packet_size,sizeof(unsigned short)); | ||
646 | memcpy(&config_data->serial_ep_out_descriptor.wMaxPacketSize,&max_packet_size,sizeof(unsigned short)); | ||
647 | config_data->serial_interface_descriptor.bInterfaceNumber=interface_number; | ||
648 | interface_number++; | ||
649 | #endif | ||
650 | #ifdef USB_BENCHMARK | ||
651 | memcpy(&config_data->benchmark_ep_in_descriptor.wMaxPacketSize,&max_packet_size,sizeof(unsigned short)); | ||
652 | memcpy(&config_data->benchmark_ep_out_descriptor.wMaxPacketSize,&max_packet_size,sizeof(unsigned short)); | ||
653 | config_data.benchmark_interface_descriptor.bInterfaceNumber=interface_number; | ||
654 | interface_number++; | ||
655 | #endif | ||
656 | config_data->config_descriptor.bNumInterfaces=interface_number; | ||
657 | ptr = config_data; | ||
658 | size = sizeof _config_data; | ||
651 | break; | 659 | break; |
660 | } | ||
652 | 661 | ||
653 | case USB_DT_STRING: | 662 | case USB_DT_STRING: |
654 | if ((unsigned)index < (sizeof(usb_strings)/sizeof(struct usb_string_descriptor*))) { | 663 | if ((unsigned)index < (sizeof(usb_strings)/sizeof(struct usb_string_descriptor*))) { |
@@ -657,7 +666,7 @@ void usb_core_control_request(struct usb_ctrlrequest* req) | |||
657 | } | 666 | } |
658 | else { | 667 | else { |
659 | logf("bad string id %d", index); | 668 | logf("bad string id %d", index); |
660 | usb_drv_stall(EP_CONTROL, true); | 669 | usb_drv_stall(EP_CONTROL, true,true); |
661 | } | 670 | } |
662 | break; | 671 | break; |
663 | 672 | ||
@@ -668,13 +677,14 @@ void usb_core_control_request(struct usb_ctrlrequest* req) | |||
668 | 677 | ||
669 | default: | 678 | default: |
670 | logf("bad desc %d", req->wValue >> 8); | 679 | logf("bad desc %d", req->wValue >> 8); |
671 | usb_drv_stall(EP_CONTROL, true); | 680 | usb_drv_stall(EP_CONTROL, true,true); |
672 | break; | 681 | break; |
673 | } | 682 | } |
674 | 683 | ||
675 | if (ptr) { | 684 | if (ptr) { |
676 | length = MIN(size, length); | 685 | length = MIN(size, length); |
677 | usb_drv_send(EP_CONTROL, (void*)UNCACHED_ADDR(ptr), length); | 686 | if(usb_drv_send(EP_CONTROL, (void*)UNCACHED_ADDR(ptr), length)!=0) |
687 | break; | ||
678 | } | 688 | } |
679 | ack_control(req); | 689 | ack_control(req); |
680 | break; | 690 | break; |
@@ -693,7 +703,7 @@ void usb_core_control_request(struct usb_ctrlrequest* req) | |||
693 | { | 703 | { |
694 | /* nope. flag error */ | 704 | /* nope. flag error */ |
695 | logf("usb bad req %d", req->bRequest); | 705 | logf("usb bad req %d", req->bRequest); |
696 | usb_drv_stall(EP_CONTROL, true); | 706 | usb_drv_stall(EP_CONTROL, true,true); |
697 | ack_control(req); | 707 | ack_control(req); |
698 | } | 708 | } |
699 | break; | 709 | break; |
@@ -709,9 +719,9 @@ void usb_core_bus_reset(void) | |||
709 | } | 719 | } |
710 | 720 | ||
711 | /* called by usb_drv_transfer_completed() */ | 721 | /* called by usb_drv_transfer_completed() */ |
712 | void usb_core_transfer_complete(int endpoint, bool in) | 722 | void usb_core_transfer_complete(int endpoint, bool in, int status,int length) |
713 | { | 723 | { |
714 | #ifdef USB_CHARGING_ONLY | 724 | #if defined(USB_CHARGING_ONLY) || defined(USB_STORAGE) |
715 | (void)in; | 725 | (void)in; |
716 | #endif | 726 | #endif |
717 | 727 | ||
@@ -720,25 +730,35 @@ void usb_core_transfer_complete(int endpoint, bool in) | |||
720 | /* already handled */ | 730 | /* already handled */ |
721 | break; | 731 | break; |
722 | 732 | ||
723 | case EP_RX: | ||
724 | case EP_TX: | ||
725 | #if defined(USB_BENCHMARK) | ||
726 | usb_benchmark_transfer_complete(endpoint, in); | ||
727 | #elif defined(USB_STORAGE) || defined(USB_SERIAL) | ||
728 | queue_post(&usbcore_queue, endpoint, 0); | ||
729 | #endif | ||
730 | break; | ||
731 | |||
732 | default: | 733 | default: |
734 | events[endpoint].endpoint=endpoint; | ||
735 | events[endpoint].in=in; | ||
736 | events[endpoint].data=0; | ||
737 | events[endpoint].status=status; | ||
738 | events[endpoint].length=length; | ||
739 | /* All other endoints. Let the thread deal with it */ | ||
740 | queue_post(&usbcore_queue, USB_CORE_TRANSFER_COMPLETION, (intptr_t)&events[endpoint]); | ||
733 | break; | 741 | break; |
734 | } | 742 | } |
735 | } | 743 | } |
736 | 744 | ||
737 | static void ack_control(struct usb_ctrlrequest* req) | 745 | /* called by usb_drv_int() */ |
746 | void usb_core_control_request(struct usb_ctrlrequest* req) | ||
747 | { | ||
748 | events[0].endpoint=0; | ||
749 | events[0].in=0; | ||
750 | events[0].data=(void *)req; | ||
751 | events[0].status=0; | ||
752 | events[0].length=0; | ||
753 | logf("ctrl received %ld",current_tick); | ||
754 | queue_post(&usbcore_queue, USB_CORE_TRANSFER_COMPLETION,(intptr_t)&events[0]); | ||
755 | } | ||
756 | |||
757 | static int ack_control(struct usb_ctrlrequest* req) | ||
738 | { | 758 | { |
739 | if (req->bRequestType & 0x80) | 759 | if (req->bRequestType & 0x80) |
740 | usb_drv_recv(EP_CONTROL, NULL, 0); | 760 | return usb_drv_recv(EP_CONTROL, NULL, 0); |
741 | else | 761 | else |
742 | usb_drv_send(EP_CONTROL, NULL, 0); | 762 | return usb_drv_send(EP_CONTROL, NULL, 0); |
743 | } | 763 | } |
744 | 764 | ||