diff options
Diffstat (limited to 'firmware/usbstack/usb_core.c')
-rw-r--r-- | firmware/usbstack/usb_core.c | 750 |
1 files changed, 373 insertions, 377 deletions
diff --git a/firmware/usbstack/usb_core.c b/firmware/usbstack/usb_core.c index 96a5994417..ff54e4269f 100644 --- a/firmware/usbstack/usb_core.c +++ b/firmware/usbstack/usb_core.c | |||
@@ -27,6 +27,7 @@ | |||
27 | #include "usb_ch9.h" | 27 | #include "usb_ch9.h" |
28 | #include "usb_drv.h" | 28 | #include "usb_drv.h" |
29 | #include "usb_core.h" | 29 | #include "usb_core.h" |
30 | #include "usb_class_driver.h" | ||
30 | 31 | ||
31 | #if defined(USB_STORAGE) | 32 | #if defined(USB_STORAGE) |
32 | #include "usb_storage.h" | 33 | #include "usb_storage.h" |
@@ -36,7 +37,7 @@ | |||
36 | #include "usb_serial.h" | 37 | #include "usb_serial.h" |
37 | #endif | 38 | #endif |
38 | 39 | ||
39 | /* TODO: Move this target-specific stuff somewhere else (serial number reading) */ | 40 | /* TODO: Move target-specific stuff somewhere else (serial number reading) */ |
40 | 41 | ||
41 | #ifdef HAVE_AS3514 | 42 | #ifdef HAVE_AS3514 |
42 | #include "i2c-pp.h" | 43 | #include "i2c-pp.h" |
@@ -54,7 +55,9 @@ | |||
54 | #define USB_SC_SCSI 0x06 /* Transparent */ | 55 | #define USB_SC_SCSI 0x06 /* Transparent */ |
55 | #define USB_PROT_BULK 0x50 /* bulk only */ | 56 | #define USB_PROT_BULK 0x50 /* bulk only */ |
56 | 57 | ||
57 | static const struct usb_device_descriptor __attribute__((aligned(2))) device_descriptor= { | 58 | static const struct usb_device_descriptor __attribute__((aligned(2))) |
59 | device_descriptor= | ||
60 | { | ||
58 | .bLength = sizeof(struct usb_device_descriptor), | 61 | .bLength = sizeof(struct usb_device_descriptor), |
59 | .bDescriptorType = USB_DT_DEVICE, | 62 | .bDescriptorType = USB_DT_DEVICE, |
60 | #ifdef USE_HIGH_SPEED | 63 | #ifdef USE_HIGH_SPEED |
@@ -75,7 +78,8 @@ static const struct usb_device_descriptor __attribute__((aligned(2))) device_des | |||
75 | .bNumConfigurations = 1 | 78 | .bNumConfigurations = 1 |
76 | } ; | 79 | } ; |
77 | 80 | ||
78 | struct usb_config_descriptor __attribute__((aligned(2))) config_descriptor = | 81 | static struct usb_config_descriptor __attribute__((aligned(2))) |
82 | config_descriptor = | ||
79 | { | 83 | { |
80 | .bLength = sizeof(struct usb_config_descriptor), | 84 | .bLength = sizeof(struct usb_config_descriptor), |
81 | .bDescriptorType = USB_DT_CONFIG, | 85 | .bDescriptorType = USB_DT_CONFIG, |
@@ -89,7 +93,8 @@ struct usb_config_descriptor __attribute__((aligned(2))) config_descriptor = | |||
89 | 93 | ||
90 | #ifdef USB_CHARGING_ONLY | 94 | #ifdef USB_CHARGING_ONLY |
91 | /* dummy interface for charging-only */ | 95 | /* dummy interface for charging-only */ |
92 | struct usb_interface_descriptor __attribute__((aligned(2))) charging_interface_descriptor = | 96 | static struct usb_interface_descriptor __attribute__((aligned(2))) |
97 | charging_interface_descriptor = | ||
93 | { | 98 | { |
94 | .bLength = sizeof(struct usb_interface_descriptor), | 99 | .bLength = sizeof(struct usb_interface_descriptor), |
95 | .bDescriptorType = USB_DT_INTERFACE, | 100 | .bDescriptorType = USB_DT_INTERFACE, |
@@ -103,77 +108,8 @@ struct usb_interface_descriptor __attribute__((aligned(2))) charging_interface_d | |||
103 | }; | 108 | }; |
104 | #endif | 109 | #endif |
105 | 110 | ||
106 | #ifdef USB_STORAGE | 111 | static const struct usb_qualifier_descriptor __attribute__((aligned(2))) |
107 | /* storage interface */ | 112 | qualifier_descriptor = |
108 | struct usb_interface_descriptor __attribute__((aligned(2))) mass_storage_interface_descriptor = | ||
109 | { | ||
110 | .bLength = sizeof(struct usb_interface_descriptor), | ||
111 | .bDescriptorType = USB_DT_INTERFACE, | ||
112 | .bInterfaceNumber = 0, | ||
113 | .bAlternateSetting = 0, | ||
114 | .bNumEndpoints = 2, | ||
115 | .bInterfaceClass = USB_CLASS_MASS_STORAGE, | ||
116 | .bInterfaceSubClass = USB_SC_SCSI, | ||
117 | .bInterfaceProtocol = USB_PROT_BULK, | ||
118 | .iInterface = 0 | ||
119 | }; | ||
120 | |||
121 | struct usb_endpoint_descriptor __attribute__((aligned(2))) mass_storage_ep_in_descriptor = | ||
122 | { | ||
123 | .bLength = sizeof(struct usb_endpoint_descriptor), | ||
124 | .bDescriptorType = USB_DT_ENDPOINT, | ||
125 | .bEndpointAddress = EP_MASS_STORAGE | USB_DIR_IN, | ||
126 | .bmAttributes = USB_ENDPOINT_XFER_BULK, | ||
127 | .wMaxPacketSize = 16, | ||
128 | .bInterval = 0 | ||
129 | }; | ||
130 | struct usb_endpoint_descriptor __attribute__((aligned(2))) mass_storage_ep_out_descriptor = | ||
131 | { | ||
132 | .bLength = sizeof(struct usb_endpoint_descriptor), | ||
133 | .bDescriptorType = USB_DT_ENDPOINT, | ||
134 | .bEndpointAddress = EP_MASS_STORAGE | USB_DIR_OUT, | ||
135 | .bmAttributes = USB_ENDPOINT_XFER_BULK, | ||
136 | .wMaxPacketSize = 16, | ||
137 | .bInterval = 0 | ||
138 | }; | ||
139 | #endif | ||
140 | |||
141 | #ifdef USB_SERIAL | ||
142 | /* serial interface */ | ||
143 | struct usb_interface_descriptor __attribute__((aligned(2))) serial_interface_descriptor = | ||
144 | { | ||
145 | .bLength = sizeof(struct usb_interface_descriptor), | ||
146 | .bDescriptorType = USB_DT_INTERFACE, | ||
147 | .bInterfaceNumber = 0, | ||
148 | .bAlternateSetting = 0, | ||
149 | .bNumEndpoints = 2, | ||
150 | .bInterfaceClass = USB_CLASS_CDC_DATA, | ||
151 | .bInterfaceSubClass = 0, | ||
152 | .bInterfaceProtocol = 0, | ||
153 | .iInterface = 0 | ||
154 | }; | ||
155 | |||
156 | struct usb_endpoint_descriptor __attribute__((aligned(2))) serial_ep_in_descriptor = | ||
157 | { | ||
158 | .bLength = sizeof(struct usb_endpoint_descriptor), | ||
159 | .bDescriptorType = USB_DT_ENDPOINT, | ||
160 | .bEndpointAddress = EP_SERIAL | USB_DIR_IN, | ||
161 | .bmAttributes = USB_ENDPOINT_XFER_BULK, | ||
162 | .wMaxPacketSize = 16, | ||
163 | .bInterval = 0 | ||
164 | }; | ||
165 | struct usb_endpoint_descriptor __attribute__((aligned(2))) serial_ep_out_descriptor = | ||
166 | { | ||
167 | .bLength = sizeof(struct usb_endpoint_descriptor), | ||
168 | .bDescriptorType = USB_DT_ENDPOINT, | ||
169 | .bEndpointAddress = EP_SERIAL | USB_DIR_OUT, | ||
170 | .bmAttributes = USB_ENDPOINT_XFER_BULK, | ||
171 | .wMaxPacketSize = 16, | ||
172 | .bInterval = 0 | ||
173 | }; | ||
174 | #endif | ||
175 | |||
176 | static const struct usb_qualifier_descriptor __attribute__((aligned(2))) qualifier_descriptor = | ||
177 | { | 113 | { |
178 | .bLength = sizeof(struct usb_qualifier_descriptor), | 114 | .bLength = sizeof(struct usb_qualifier_descriptor), |
179 | .bDescriptorType = USB_DT_DEVICE_QUALIFIER, | 115 | .bDescriptorType = USB_DT_DEVICE_QUALIFIER, |
@@ -185,21 +121,26 @@ static const struct usb_qualifier_descriptor __attribute__((aligned(2))) qualifi | |||
185 | .bNumConfigurations = 1 | 121 | .bNumConfigurations = 1 |
186 | }; | 122 | }; |
187 | 123 | ||
188 | static struct usb_string_descriptor __attribute__((aligned(2))) usb_string_iManufacturer = | 124 | static struct usb_string_descriptor __attribute__((aligned(2))) |
125 | usb_string_iManufacturer = | ||
189 | { | 126 | { |
190 | 24, | 127 | 24, |
191 | USB_DT_STRING, | 128 | USB_DT_STRING, |
192 | {'R','o','c','k','b','o','x','.','o','r','g'} | 129 | {'R','o','c','k','b','o','x','.','o','r','g'} |
193 | }; | 130 | }; |
194 | 131 | ||
195 | static struct usb_string_descriptor __attribute__((aligned(2))) usb_string_iProduct = | 132 | static struct usb_string_descriptor __attribute__((aligned(2))) |
133 | usb_string_iProduct = | ||
196 | { | 134 | { |
197 | 42, | 135 | 42, |
198 | USB_DT_STRING, | 136 | USB_DT_STRING, |
199 | {'R','o','c','k','b','o','x',' ','m','e','d','i','a',' ','p','l','a','y','e','r'} | 137 | {'R','o','c','k','b','o','x',' ', |
138 | 'm','e','d','i','a',' ', | ||
139 | 'p','l','a','y','e','r'} | ||
200 | }; | 140 | }; |
201 | 141 | ||
202 | static struct usb_string_descriptor __attribute__((aligned(2))) usb_string_iSerial = | 142 | static struct usb_string_descriptor __attribute__((aligned(2))) |
143 | usb_string_iSerial = | ||
203 | { | 144 | { |
204 | 84, | 145 | 84, |
205 | USB_DT_STRING, | 146 | USB_DT_STRING, |
@@ -211,14 +152,16 @@ static struct usb_string_descriptor __attribute__((aligned(2))) usb_string_iSeri | |||
211 | /* Generic for all targets */ | 152 | /* Generic for all targets */ |
212 | 153 | ||
213 | /* this is stringid #0: languages supported */ | 154 | /* this is stringid #0: languages supported */ |
214 | static struct usb_string_descriptor __attribute__((aligned(2))) lang_descriptor = | 155 | static struct usb_string_descriptor __attribute__((aligned(2))) |
156 | lang_descriptor = | ||
215 | { | 157 | { |
216 | 4, | 158 | 4, |
217 | USB_DT_STRING, | 159 | USB_DT_STRING, |
218 | {0x0409} /* LANGID US English */ | 160 | {0x0409} /* LANGID US English */ |
219 | }; | 161 | }; |
220 | 162 | ||
221 | static struct usb_string_descriptor __attribute__((aligned(2))) usb_string_charging_only = | 163 | static struct usb_string_descriptor __attribute__((aligned(2))) |
164 | usb_string_charging_only = | ||
222 | { | 165 | { |
223 | 28, | 166 | 28, |
224 | USB_DT_STRING, | 167 | USB_DT_STRING, |
@@ -238,14 +181,56 @@ static int usb_address = 0; | |||
238 | static bool initialized = false; | 181 | static bool initialized = false; |
239 | static enum { DEFAULT, ADDRESS, CONFIGURED } usb_state; | 182 | static enum { DEFAULT, ADDRESS, CONFIGURED } usb_state; |
240 | 183 | ||
184 | static int usb_core_num_interfaces; | ||
185 | |||
186 | int usb_charging_get_config_descriptor(unsigned char *dest,int max_packet_size, | ||
187 | int interface_number,int endpoint); | ||
188 | |||
189 | struct usb_class_driver drivers[] = | ||
190 | { | ||
241 | #ifdef USB_STORAGE | 191 | #ifdef USB_STORAGE |
242 | static bool usb_core_storage_enabled = false; | 192 | [USB_DRIVER_MASS_STORAGE] = { |
193 | .enabled = false, | ||
194 | .needs_exclusive_ata = true, | ||
195 | .usb_endpoint = 0, | ||
196 | .usb_interface = 0, | ||
197 | .get_config_descriptor = usb_storage_get_config_descriptor, | ||
198 | .init_connection = usb_storage_init_connection, | ||
199 | .init = usb_storage_init, | ||
200 | .disconnect = NULL, | ||
201 | .transfer_complete = usb_storage_transfer_complete, | ||
202 | .control_request = usb_storage_control_request | ||
203 | }, | ||
204 | #endif | ||
205 | #ifdef USB_SERIAL | ||
206 | [USB_DRIVER_SERIAL] = { | ||
207 | .enabled = false, | ||
208 | .needs_exclusive_ata = false, | ||
209 | .usb_endpoint = 0, | ||
210 | .usb_interface = 0, | ||
211 | .get_config_descriptor = usb_serial_get_config_descriptor, | ||
212 | .init_connection = usb_serial_init_connection, | ||
213 | .init = usb_serial_init, | ||
214 | .disconnect = usb_serial_disconnect, | ||
215 | .transfer_complete = usb_serial_transfer_complete, | ||
216 | .control_request = usb_serial_control_request | ||
217 | }, | ||
243 | #endif | 218 | #endif |
244 | /* Next one is non-static, to enable setting it from the debug menu */ | ||
245 | bool usb_core_serial_enabled = false; | ||
246 | #ifdef USB_CHARGING_ONLY | 219 | #ifdef USB_CHARGING_ONLY |
247 | static bool usb_core_charging_enabled = false; | 220 | [USB_DRIVER_CHARGING_ONLY] = { |
221 | .enabled = false, | ||
222 | .needs_exclusive_ata = false, | ||
223 | .usb_endpoint = 0, | ||
224 | .usb_interface = 0, | ||
225 | .get_config_descriptor = usb_charging_get_config_descriptor, | ||
226 | .init_connection = NULL, | ||
227 | .init = NULL, | ||
228 | .disconnect = NULL, | ||
229 | .transfer_complete = NULL, | ||
230 | .control_request = NULL | ||
231 | }, | ||
248 | #endif | 232 | #endif |
233 | }; | ||
249 | 234 | ||
250 | static void usb_core_control_request_handler(struct usb_ctrlrequest* req); | 235 | static void usb_core_control_request_handler(struct usb_ctrlrequest* req); |
251 | static int ack_control(struct usb_ctrlrequest* req); | 236 | static int ack_control(struct usb_ctrlrequest* req); |
@@ -272,11 +257,9 @@ static void set_serial_descriptor(void) | |||
272 | uint32_t x; | 257 | uint32_t x; |
273 | int i,j; | 258 | int i,j; |
274 | 259 | ||
275 | for (i = 0; i < 2; i++) | 260 | for (i = 0; i < 2; i++) { |
276 | { | ||
277 | x = serial[i]; | 261 | x = serial[i]; |
278 | for (j=0;j<8;j++) | 262 | for (j=0;j<8;j++) { |
279 | { | ||
280 | *p-- = hex[x & 0xf]; | 263 | *p-- = hex[x & 0xf]; |
281 | x >>= 4; | 264 | x >>= 4; |
282 | } | 265 | } |
@@ -292,8 +275,7 @@ static void set_serial_descriptor(void) | |||
292 | int i; | 275 | int i; |
293 | 276 | ||
294 | i2c_readbytes(AS3514_I2C_ADDR, 0x30, 0x10, serial); | 277 | i2c_readbytes(AS3514_I2C_ADDR, 0x30, 0x10, serial); |
295 | for (i = 0; i < 16; i++) | 278 | for (i = 0; i < 16; i++) { |
296 | { | ||
297 | *p++ = hex[(serial[i] >> 4) & 0xF]; | 279 | *p++ = hex[(serial[i] >> 4) & 0xF]; |
298 | *p++ = hex[(serial[i] >> 0) & 0xF]; | 280 | *p++ = hex[(serial[i] >> 0) & 0xF]; |
299 | } | 281 | } |
@@ -309,8 +291,7 @@ static void set_serial_descriptor(void) | |||
309 | unsigned short x; | 291 | unsigned short x; |
310 | int i; | 292 | int i; |
311 | 293 | ||
312 | for (i = 10; i < 20; i++) | 294 | for (i = 10; i < 20; i++) { |
313 | { | ||
314 | x = identify[i]; | 295 | x = identify[i]; |
315 | *p++ = hex[(x >> 12) & 0xF]; | 296 | *p++ = hex[(x >> 12) & 0xF]; |
316 | *p++ = hex[(x >> 8) & 0xF]; | 297 | *p++ = hex[(x >> 8) & 0xF]; |
@@ -323,6 +304,7 @@ static void set_serial_descriptor(void) | |||
323 | 304 | ||
324 | void usb_core_init(void) | 305 | void usb_core_init(void) |
325 | { | 306 | { |
307 | int i; | ||
326 | if (initialized) | 308 | if (initialized) |
327 | return; | 309 | return; |
328 | 310 | ||
@@ -333,27 +315,34 @@ void usb_core_init(void) | |||
333 | /* class driver init functions should be safe to call even if the driver | 315 | /* class driver init functions should be safe to call even if the driver |
334 | * won't be used. This simplifies other logic (i.e. we don't need to know | 316 | * won't be used. This simplifies other logic (i.e. we don't need to know |
335 | * yet which drivers will be enabled */ | 317 | * yet which drivers will be enabled */ |
336 | #ifdef USB_STORAGE | 318 | for(i=0;i<USB_NUM_DRIVERS;i++) { |
337 | if(usb_core_storage_enabled) | 319 | if(drivers[i].enabled && drivers[i].init != NULL) |
338 | usb_storage_init(); | 320 | drivers[i].init(); |
339 | #endif | 321 | } |
340 | |||
341 | #ifdef USB_SERIAL | ||
342 | if(usb_core_serial_enabled) | ||
343 | usb_serial_init(); | ||
344 | #endif | ||
345 | 322 | ||
346 | initialized = true; | 323 | initialized = true; |
347 | usb_state = DEFAULT; | 324 | usb_state = DEFAULT; |
348 | logf("usb_core_init() finished"); | 325 | logf("usb_core_init() finished"); |
349 | } | 326 | } |
350 | 327 | ||
328 | int usb_charging_get_config_descriptor(unsigned char *dest,int max_packet_size, | ||
329 | int interface_number,int endpoint) | ||
330 | { | ||
331 | (void) max_packet_size; | ||
332 | (void) endpoint; | ||
333 | charging_interface_descriptor.bInterfaceNumber=interface_number; | ||
334 | memcpy(dest,&charging_interface_descriptor, | ||
335 | sizeof(struct usb_interface_descriptor)); | ||
336 | return sizeof(struct usb_interface_descriptor); | ||
337 | } | ||
338 | |||
351 | void usb_core_exit(void) | 339 | void usb_core_exit(void) |
352 | { | 340 | { |
353 | #ifdef USB_SERIAL | 341 | int i; |
354 | if(usb_core_serial_enabled) | 342 | for(i=0;i<USB_NUM_DRIVERS;i++) { |
355 | usb_serial_exit(); | 343 | if(drivers[i].enabled && drivers[i].disconnect != NULL) |
356 | #endif | 344 | drivers[i].disconnect (); |
345 | } | ||
357 | 346 | ||
358 | if (initialized) { | 347 | if (initialized) { |
359 | usb_drv_exit(); | 348 | usb_drv_exit(); |
@@ -362,321 +351,332 @@ void usb_core_exit(void) | |||
362 | logf("usb_core_exit() finished"); | 351 | logf("usb_core_exit() finished"); |
363 | } | 352 | } |
364 | 353 | ||
365 | void usb_core_handle_transfer_completion(struct usb_transfer_completion_event_data* event) | 354 | void usb_core_handle_transfer_completion( |
355 | struct usb_transfer_completion_event_data* event) | ||
366 | { | 356 | { |
357 | int i; | ||
367 | switch(event->endpoint) { | 358 | switch(event->endpoint) { |
368 | case EP_CONTROL: | 359 | case EP_CONTROL: |
369 | logf("ctrl handled %ld",current_tick); | 360 | logf("ctrl handled %ld",current_tick); |
370 | usb_core_control_request_handler((struct usb_ctrlrequest*)event->data); | 361 | usb_core_control_request_handler( |
371 | break; | 362 | (struct usb_ctrlrequest*)event->data); |
372 | #ifdef USB_STORAGE | ||
373 | case EP_MASS_STORAGE: | ||
374 | usb_storage_transfer_complete(event->in,event->status,event->length); | ||
375 | break; | 363 | break; |
376 | #endif | 364 | default: |
377 | #ifdef USB_SERIAL | 365 | for(i=0;i<USB_NUM_DRIVERS;i++) { |
378 | case EP_SERIAL: | 366 | if(drivers[i].enabled && |
379 | usb_serial_transfer_complete(event->in,event->status,event->length); | 367 | drivers[i].usb_endpoint == event->endpoint && |
380 | break; | 368 | drivers[i].transfer_complete != NULL) |
381 | #endif | 369 | { |
382 | #ifdef USB_CHARGING_ONLY | 370 | drivers[i].transfer_complete(event->in, |
383 | case EP_CHARGING_ONLY: | 371 | event->status,event->length); |
372 | break; | ||
373 | } | ||
374 | } | ||
384 | break; | 375 | break; |
385 | #endif | ||
386 | } | 376 | } |
387 | } | 377 | } |
388 | 378 | ||
389 | void usb_core_enable_protocol(int driver,bool enabled) | 379 | void usb_core_enable_driver(int driver,bool enabled) |
390 | { | 380 | { |
391 | switch(driver) { | 381 | drivers[driver].enabled = enabled; |
392 | #ifdef USB_STORAGE | 382 | } |
393 | case USB_DRIVER_MASS_STORAGE: | 383 | |
394 | usb_core_storage_enabled = enabled; | 384 | bool usb_core_driver_enabled(int driver) |
395 | break; | 385 | { |
396 | #endif | 386 | return drivers[driver].enabled; |
397 | #ifdef USB_SERIAL | 387 | } |
398 | case USB_DRIVER_SERIAL: | 388 | |
399 | usb_core_serial_enabled = enabled; | 389 | static void usb_core_set_serial_function_id(void) |
400 | break; | 390 | { |
401 | #endif | 391 | int id = 0; |
402 | #ifdef USB_CHARGING_ONLY | 392 | int i; |
403 | case USB_DRIVER_CHARGING_ONLY: | 393 | for(i=0;i<USB_NUM_DRIVERS;i++) { |
404 | usb_core_charging_enabled = enabled; | 394 | if(drivers[i].enabled) |
405 | break; | 395 | id |= 1<<i; |
406 | #endif | ||
407 | } | 396 | } |
397 | usb_string_iSerial.wString[0] = hex[id]; | ||
408 | } | 398 | } |
409 | 399 | ||
410 | static void usb_core_control_request_handler(struct usb_ctrlrequest* req) | 400 | static void allocate_interfaces_and_endpoints(void) |
411 | { | 401 | { |
412 | if(usb_state == DEFAULT) { | 402 | int i; |
413 | set_serial_descriptor(); | 403 | int interface=0; |
414 | 404 | int endpoint=1; | |
415 | int serial_function_id = 0; | 405 | for(i=0;i<USB_NUM_DRIVERS;i++) { |
416 | #ifdef USB_STORAGE | 406 | if(drivers[i].enabled) { |
417 | if(usb_core_storage_enabled) { | 407 | drivers[i].usb_endpoint = endpoint++; |
418 | usb_request_exclusive_ata(); | 408 | drivers[i].usb_interface = interface++; |
419 | serial_function_id |= 1; | 409 | } |
410 | if(endpoint>NUM_ENDPOINTS) { | ||
411 | drivers[i].enabled = false; | ||
420 | } | 412 | } |
421 | #endif | ||
422 | #ifdef USB_SERIAL | ||
423 | if(usb_core_serial_enabled) | ||
424 | serial_function_id |= 2; | ||
425 | #endif | ||
426 | usb_string_iSerial.wString[0] = hex[serial_function_id]; | ||
427 | } | 413 | } |
414 | usb_core_num_interfaces = interface; | ||
415 | } | ||
428 | 416 | ||
429 | switch (req->bRequest) { | 417 | static void usb_core_control_request_handler(struct usb_ctrlrequest* req) |
430 | case USB_REQ_SET_CONFIGURATION: | 418 | { |
431 | logf("usb_core: SET_CONFIG"); | 419 | int i; |
432 | usb_drv_cancel_all_transfers(); | 420 | if(usb_state == DEFAULT) { |
433 | if (req->wValue){ | 421 | set_serial_descriptor(); |
434 | usb_state = CONFIGURED; | 422 | usb_core_set_serial_function_id(); |
435 | #ifdef USB_STORAGE | ||
436 | if(usb_core_storage_enabled) | ||
437 | usb_storage_control_request(req); | ||
438 | #endif | ||
439 | 423 | ||
440 | #ifdef USB_SERIAL | 424 | allocate_interfaces_and_endpoints(); |
441 | if(usb_core_serial_enabled) | ||
442 | usb_serial_control_request(req); | ||
443 | #endif | ||
444 | } | ||
445 | else { | ||
446 | usb_state = ADDRESS; | ||
447 | } | ||
448 | ack_control(req); | ||
449 | break; | ||
450 | 425 | ||
451 | case USB_REQ_GET_CONFIGURATION: { | 426 | for(i=0;i<USB_NUM_DRIVERS;i++) { |
452 | logf("usb_core: GET_CONFIG"); | 427 | if(drivers[i].enabled && |
453 | if (usb_state == ADDRESS) | 428 | drivers[i].needs_exclusive_ata) { |
454 | response_data[0] = 0; | 429 | usb_request_exclusive_ata(); |
455 | else | ||
456 | response_data[0] = 1; | ||
457 | if(usb_drv_send(EP_CONTROL, response_data, 1)!= 0) | ||
458 | break; | 430 | break; |
459 | ack_control(req); | 431 | } |
460 | break; | ||
461 | } | 432 | } |
433 | } | ||
462 | 434 | ||
463 | case USB_REQ_SET_INTERFACE: | 435 | switch(req->bRequestType & 0x1f) { |
464 | logf("usb_core: SET_INTERFACE"); | 436 | case 0: /* Device */ |
465 | ack_control(req); | 437 | switch (req->bRequest) { |
466 | break; | 438 | case USB_REQ_GET_CONFIGURATION: { |
439 | logf("usb_core: GET_CONFIG"); | ||
440 | if (usb_state == ADDRESS) | ||
441 | response_data[0] = 0; | ||
442 | else | ||
443 | response_data[0] = 1; | ||
444 | if(usb_drv_send(EP_CONTROL, response_data, 1)!= 0) | ||
445 | break; | ||
446 | ack_control(req); | ||
447 | break; | ||
448 | case USB_REQ_SET_CONFIGURATION: | ||
449 | logf("usb_core: SET_CONFIG"); | ||
450 | usb_drv_cancel_all_transfers(); | ||
451 | if (req->wValue) { | ||
452 | usb_state = CONFIGURED; | ||
453 | for(i=0;i<USB_NUM_DRIVERS;i++) { | ||
454 | if(drivers[i].enabled && | ||
455 | drivers[i].init_connection!=NULL) | ||
456 | { | ||
457 | drivers[i].init_connection( | ||
458 | drivers[i].usb_interface, | ||
459 | drivers[i].usb_endpoint); | ||
460 | } | ||
461 | } | ||
462 | } | ||
463 | else { | ||
464 | usb_state = ADDRESS; | ||
465 | } | ||
466 | ack_control(req); | ||
467 | break; | ||
468 | } | ||
469 | case USB_REQ_SET_ADDRESS: { | ||
470 | unsigned char address = req->wValue; | ||
471 | logf("usb_core: SET_ADR %d", address); | ||
472 | if(ack_control(req)!=0) | ||
473 | break; | ||
474 | usb_drv_cancel_all_transfers(); | ||
475 | usb_address = address; | ||
476 | usb_drv_set_address(usb_address); | ||
477 | usb_state = ADDRESS; | ||
478 | break; | ||
479 | } | ||
480 | case USB_REQ_GET_DESCRIPTOR: { | ||
481 | int index = req->wValue & 0xff; | ||
482 | int length = req->wLength; | ||
483 | int size; | ||
484 | const void* ptr = NULL; | ||
485 | logf("usb_core: GET_DESC %d", req->wValue >> 8); | ||
486 | |||
487 | switch (req->wValue >> 8) { /* type */ | ||
488 | case USB_DT_DEVICE: | ||
489 | ptr = &device_descriptor; | ||
490 | size = sizeof(struct usb_device_descriptor); | ||
491 | break; | ||
492 | |||
493 | case USB_DT_OTHER_SPEED_CONFIG: | ||
494 | case USB_DT_CONFIG: { | ||
495 | int max_packet_size; | ||
496 | |||
497 | if(req->wValue >> 8 == USB_DT_CONFIG) { | ||
498 | if(usb_drv_port_speed()) | ||
499 | max_packet_size=512; | ||
500 | else | ||
501 | max_packet_size=64; | ||
502 | config_descriptor.bDescriptorType=USB_DT_CONFIG; | ||
503 | } | ||
504 | else { | ||
505 | if(usb_drv_port_speed()) | ||
506 | max_packet_size=64; | ||
507 | else | ||
508 | max_packet_size=512; | ||
509 | config_descriptor.bDescriptorType = | ||
510 | USB_DT_OTHER_SPEED_CONFIG; | ||
511 | } | ||
512 | size = sizeof(struct usb_config_descriptor); | ||
513 | |||
514 | for(i=0;i<USB_NUM_DRIVERS;i++) { | ||
515 | if(drivers[i].enabled && | ||
516 | drivers[i].get_config_descriptor) | ||
517 | { | ||
518 | size+=drivers[i].get_config_descriptor( | ||
519 | &response_data[size], | ||
520 | max_packet_size, | ||
521 | drivers[i].usb_interface, | ||
522 | drivers[i].usb_endpoint); | ||
523 | } | ||
524 | } | ||
525 | config_descriptor.bNumInterfaces = | ||
526 | usb_core_num_interfaces; | ||
527 | config_descriptor.wTotalLength = size; | ||
528 | memcpy(&response_data[0],&config_descriptor, | ||
529 | sizeof(struct usb_config_descriptor)); | ||
530 | |||
531 | ptr = response_data; | ||
532 | break; | ||
533 | } | ||
467 | 534 | ||
468 | case USB_REQ_GET_INTERFACE: | 535 | case USB_DT_STRING: |
469 | logf("usb_core: GET_INTERFACE"); | 536 | logf("STRING %d",index); |
470 | response_data[0] = 0; | 537 | if ((unsigned)index < (sizeof(usb_strings)/ |
471 | if(usb_drv_send(EP_CONTROL, response_data, 1)!=0) | 538 | sizeof(struct usb_string_descriptor*))) |
472 | break; | 539 | { |
473 | ack_control(req); | 540 | size = usb_strings[index]->bLength; |
474 | break; | 541 | memcpy(&response_data[0],usb_strings[index], |
475 | case USB_REQ_CLEAR_FEATURE: | 542 | size); |
476 | logf("usb_core: CLEAR_FEATURE"); | 543 | ptr = response_data; |
477 | if (req->wValue) | 544 | } |
478 | usb_drv_stall(req->wIndex & 0xf, false,(req->wIndex & 0x80) !=0); | 545 | else { |
479 | else | 546 | logf("bad string id %d", index); |
480 | usb_drv_stall(req->wIndex & 0xf, false,(req->wIndex & 0x80) !=0); | 547 | usb_drv_stall(EP_CONTROL, true,true); |
481 | ack_control(req); | 548 | } |
482 | break; | 549 | break; |
550 | |||
551 | case USB_DT_DEVICE_QUALIFIER: | ||
552 | ptr = &qualifier_descriptor; | ||
553 | size = sizeof (struct usb_qualifier_descriptor); | ||
554 | break; | ||
555 | |||
556 | default: | ||
557 | logf("bad desc %d", req->wValue >> 8); | ||
558 | usb_drv_stall(EP_CONTROL, true,true); | ||
559 | break; | ||
560 | } | ||
483 | 561 | ||
484 | case USB_REQ_SET_FEATURE: | 562 | if (ptr) { |
485 | logf("usb_core: SET_FEATURE"); | 563 | unsigned char *uncached = (void*)UNCACHED_ADDR(ptr); |
486 | switch(req->bRequestType & 0x0f){ | 564 | length = MIN(size, length); |
487 | case 0: /* Device */ | 565 | if(usb_drv_send(EP_CONTROL, uncached, length)!=0) |
566 | break; | ||
567 | } | ||
568 | ack_control(req); | ||
569 | break; | ||
570 | } /* USB_REQ_GET_DESCRIPTOR */ | ||
571 | case USB_REQ_CLEAR_FEATURE: | ||
572 | break; | ||
573 | case USB_REQ_SET_FEATURE: | ||
488 | if(req->wValue == 2) { /* TEST_MODE */ | 574 | if(req->wValue == 2) { /* TEST_MODE */ |
489 | int mode=req->wIndex>>8; | 575 | int mode=req->wIndex>>8; |
490 | ack_control(req); | 576 | ack_control(req); |
491 | usb_drv_set_test_mode(mode); | 577 | usb_drv_set_test_mode(mode); |
492 | } | 578 | } |
493 | break; | 579 | break; |
494 | case 2: /* Endpoint */ | 580 | case USB_REQ_GET_STATUS: |
495 | if (req->wValue) | 581 | response_data[0]= 0; |
496 | usb_drv_stall(req->wIndex & 0xf, true,(req->wIndex & 0x80) !=0); | 582 | response_data[1]= 0; |
497 | else | 583 | if(usb_drv_send(EP_CONTROL, response_data, 2)!=0) |
498 | usb_drv_stall(req->wIndex & 0xf, false,(req->wIndex & 0x80) !=0); | 584 | break; |
499 | ack_control(req); | 585 | ack_control(req); |
500 | break; | 586 | break; |
501 | default: | 587 | default: |
502 | break; | 588 | break; |
503 | } | 589 | } |
504 | break; | 590 | break; |
505 | 591 | case 1: /* Interface */ | |
506 | case USB_REQ_SET_ADDRESS: { | 592 | switch (req->bRequest) { |
507 | unsigned char address = req->wValue; | 593 | case USB_REQ_SET_INTERFACE: |
508 | logf("usb_core: SET_ADR %d", address); | 594 | logf("usb_core: SET_INTERFACE"); |
509 | if(ack_control(req)!=0) | 595 | ack_control(req); |
510 | break; | ||
511 | usb_drv_cancel_all_transfers(); | ||
512 | usb_address = address; | ||
513 | usb_drv_set_address(usb_address); | ||
514 | usb_state = ADDRESS; | ||
515 | break; | ||
516 | } | ||
517 | |||
518 | case USB_REQ_GET_STATUS: { | ||
519 | response_data[0]= 0; | ||
520 | response_data[1]= 0; | ||
521 | logf("usb_core: GET_STATUS"); | ||
522 | if(req->wIndex>0) { | ||
523 | if(usb_drv_stalled(req->wIndex&0xf,(req->wIndex&0x80)!=0)) | ||
524 | response_data[0] = 1; | ||
525 | } | ||
526 | logf("usb_core: %X %X",response_data[0],response_data[1]); | ||
527 | if(usb_drv_send(EP_CONTROL, response_data, 2)!=0) | ||
528 | break; | ||
529 | ack_control(req); | ||
530 | break; | ||
531 | } | ||
532 | |||
533 | case USB_REQ_GET_DESCRIPTOR: { | ||
534 | int index = req->wValue & 0xff; | ||
535 | int length = req->wLength; | ||
536 | int size; | ||
537 | const void* ptr = NULL; | ||
538 | logf("usb_core: GET_DESC %d", req->wValue >> 8); | ||
539 | |||
540 | switch (req->wValue >> 8) { /* type */ | ||
541 | case USB_DT_DEVICE: | ||
542 | ptr = &device_descriptor; | ||
543 | size = sizeof(struct usb_device_descriptor); | ||
544 | break; | 596 | break; |
545 | 597 | ||
546 | case USB_DT_OTHER_SPEED_CONFIG: | 598 | case USB_REQ_GET_INTERFACE: |
547 | case USB_DT_CONFIG: { | 599 | logf("usb_core: GET_INTERFACE"); |
548 | int max_packet_size; | 600 | response_data[0] = 0; |
549 | int interface_number=0; | 601 | if(usb_drv_send(EP_CONTROL, response_data, 1)!=0) |
550 | 602 | break; | |
551 | if(req->wValue >> 8 == USB_DT_CONFIG) { | 603 | ack_control(req); |
552 | if(usb_drv_port_speed()) { | ||
553 | max_packet_size=512; | ||
554 | } | ||
555 | else { | ||
556 | max_packet_size=64; | ||
557 | } | ||
558 | config_descriptor.bDescriptorType=USB_DT_CONFIG; | ||
559 | } | ||
560 | else { | ||
561 | if(usb_drv_port_speed()) { | ||
562 | max_packet_size=64; | ||
563 | } | ||
564 | else { | ||
565 | max_packet_size=512; | ||
566 | } | ||
567 | config_descriptor.bDescriptorType=USB_DT_OTHER_SPEED_CONFIG; | ||
568 | } | ||
569 | size = sizeof(struct usb_config_descriptor); | ||
570 | |||
571 | #ifdef USB_STORAGE | ||
572 | if(usb_core_storage_enabled){ | ||
573 | mass_storage_ep_in_descriptor.wMaxPacketSize=max_packet_size; | ||
574 | mass_storage_ep_out_descriptor.wMaxPacketSize=max_packet_size; | ||
575 | mass_storage_interface_descriptor.bInterfaceNumber=interface_number; | ||
576 | interface_number++; | ||
577 | |||
578 | memcpy(&response_data[size],&mass_storage_interface_descriptor,sizeof(struct usb_interface_descriptor)); | ||
579 | size += sizeof(struct usb_interface_descriptor); | ||
580 | memcpy(&response_data[size],&mass_storage_ep_in_descriptor,sizeof(struct usb_endpoint_descriptor)); | ||
581 | size += sizeof(struct usb_endpoint_descriptor); | ||
582 | memcpy(&response_data[size],&mass_storage_ep_out_descriptor,sizeof(struct usb_endpoint_descriptor)); | ||
583 | size += sizeof(struct usb_endpoint_descriptor); | ||
584 | } | ||
585 | #endif | ||
586 | #ifdef USB_SERIAL | ||
587 | if(usb_core_serial_enabled){ | ||
588 | serial_ep_in_descriptor.wMaxPacketSize=max_packet_size; | ||
589 | serial_ep_out_descriptor.wMaxPacketSize=max_packet_size; | ||
590 | serial_interface_descriptor.bInterfaceNumber=interface_number; | ||
591 | interface_number++; | ||
592 | |||
593 | memcpy(&response_data[size],&serial_interface_descriptor,sizeof(struct usb_interface_descriptor)); | ||
594 | size += sizeof(struct usb_interface_descriptor); | ||
595 | memcpy(&response_data[size],&serial_ep_in_descriptor,sizeof(struct usb_endpoint_descriptor)); | ||
596 | size += sizeof(struct usb_endpoint_descriptor); | ||
597 | memcpy(&response_data[size],&serial_ep_out_descriptor,sizeof(struct usb_endpoint_descriptor)); | ||
598 | size += sizeof(struct usb_endpoint_descriptor); | ||
599 | } | ||
600 | #endif | ||
601 | #ifdef USB_CHARGING_ONLY | ||
602 | if(usb_core_charging_enabled && interface_number == 0){ | ||
603 | charging_interface_descriptor.bInterfaceNumber=interface_number; | ||
604 | interface_number++; | ||
605 | memcpy(&response_data[size],&charging_interface_descriptor,sizeof(struct usb_interface_descriptor)); | ||
606 | size += sizeof(struct usb_interface_descriptor); | ||
607 | } | ||
608 | #endif | ||
609 | config_descriptor.bNumInterfaces=interface_number; | ||
610 | config_descriptor.wTotalLength = size; | ||
611 | memcpy(&response_data[0],&config_descriptor,sizeof(struct usb_config_descriptor)); | ||
612 | |||
613 | ptr = response_data; | ||
614 | break; | 604 | break; |
605 | case USB_REQ_CLEAR_FEATURE: | ||
606 | break; | ||
607 | case USB_REQ_SET_FEATURE: | ||
608 | break; | ||
609 | case USB_REQ_GET_STATUS: | ||
610 | response_data[0]= 0; | ||
611 | response_data[1]= 0; | ||
612 | if(usb_drv_send(EP_CONTROL, response_data, 2)!=0) | ||
613 | break; | ||
614 | ack_control(req); | ||
615 | break; | ||
616 | default: { | ||
617 | bool handled=false; | ||
618 | for(i=0;i<USB_NUM_DRIVERS;i++) { | ||
619 | if(drivers[i].enabled && | ||
620 | drivers[i].control_request && | ||
621 | drivers[i].usb_interface == (req->wIndex)) | ||
622 | { | ||
623 | handled = drivers[i].control_request(req); | ||
624 | } | ||
615 | } | 625 | } |
616 | 626 | if(!handled) { | |
617 | case USB_DT_STRING: | 627 | /* nope. flag error */ |
618 | logf("STRING %d",index); | 628 | logf("usb bad req %d", req->bRequest); |
619 | if ((unsigned)index < (sizeof(usb_strings)/sizeof(struct usb_string_descriptor*))) { | ||
620 | size = usb_strings[index]->bLength; | ||
621 | memcpy(&response_data[0],usb_strings[index],size); | ||
622 | ptr = response_data; | ||
623 | } | ||
624 | else { | ||
625 | logf("bad string id %d", index); | ||
626 | usb_drv_stall(EP_CONTROL, true,true); | 629 | usb_drv_stall(EP_CONTROL, true,true); |
630 | ack_control(req); | ||
627 | } | 631 | } |
628 | break; | 632 | break; |
629 | 633 | } | |
630 | case USB_DT_DEVICE_QUALIFIER: | 634 | } |
631 | ptr = &qualifier_descriptor; | 635 | break; |
632 | size = sizeof (struct usb_qualifier_descriptor); | 636 | case 2: /* Endpoint */ |
637 | switch (req->bRequest) { | ||
638 | case USB_REQ_CLEAR_FEATURE: | ||
639 | if (req->wValue == 0 ) /* ENDPOINT_HALT */ | ||
640 | usb_drv_stall(req->wIndex & 0xf, false, | ||
641 | (req->wIndex & 0x80) !=0); | ||
642 | ack_control(req); | ||
633 | break; | 643 | break; |
634 | 644 | case USB_REQ_SET_FEATURE: | |
635 | default: | 645 | if (req->wValue == 0 ) /* ENDPOINT_HALT */ |
636 | logf("bad desc %d", req->wValue >> 8); | 646 | usb_drv_stall(req->wIndex & 0xf, true, |
637 | usb_drv_stall(EP_CONTROL, true,true); | 647 | (req->wIndex & 0x80) !=0); |
648 | ack_control(req); | ||
638 | break; | 649 | break; |
639 | } | 650 | case USB_REQ_GET_STATUS: |
640 | 651 | response_data[0]= 0; | |
641 | if (ptr) { | 652 | response_data[1]= 0; |
642 | length = MIN(size, length); | 653 | logf("usb_core: GET_STATUS"); |
643 | if(usb_drv_send(EP_CONTROL, (void*)UNCACHED_ADDR(ptr), length)!=0) | 654 | if(req->wIndex>0) |
655 | response_data[0] = usb_drv_stalled(req->wIndex&0xf, | ||
656 | (req->wIndex&0x80)!=0); | ||
657 | if(usb_drv_send(EP_CONTROL, response_data, 2)!=0) | ||
658 | break; | ||
659 | ack_control(req); | ||
660 | break; | ||
661 | default: { | ||
662 | bool handled=false; | ||
663 | for(i=0;i<USB_NUM_DRIVERS;i++) { | ||
664 | if(drivers[i].enabled && | ||
665 | drivers[i].control_request && | ||
666 | drivers[i].usb_endpoint == (req->wIndex & 0xf)) | ||
667 | { | ||
668 | handled = drivers[i].control_request(req); | ||
669 | } | ||
670 | } | ||
671 | if(!handled) { | ||
672 | /* nope. flag error */ | ||
673 | logf("usb bad req %d", req->bRequest); | ||
674 | usb_drv_stall(EP_CONTROL, true,true); | ||
675 | ack_control(req); | ||
676 | } | ||
644 | break; | 677 | break; |
645 | } | ||
646 | ack_control(req); | ||
647 | break; | ||
648 | } /* USB_REQ_GET_DESCRIPTOR */ | ||
649 | |||
650 | default: { | ||
651 | bool handled=false; | ||
652 | if((req->bRequestType & 0x1f) == 1) /* Interface */ | ||
653 | { | ||
654 | #ifdef USB_STORAGE | ||
655 | /* does usb_storage know this request? */ | ||
656 | if(req->wIndex == mass_storage_interface_descriptor.bInterfaceNumber) | ||
657 | { | ||
658 | handled = usb_storage_control_request(req); | ||
659 | } | ||
660 | #endif | ||
661 | |||
662 | #ifdef USB_SERIAL | ||
663 | /* does usb_serial know this request? */ | ||
664 | if(req->wIndex == serial_interface_descriptor.bInterfaceNumber) | ||
665 | { | ||
666 | handled = usb_serial_control_request(req); | ||
667 | } | 678 | } |
668 | |||
669 | #endif | ||
670 | } | ||
671 | if(!handled) | ||
672 | { | ||
673 | /* nope. flag error */ | ||
674 | logf("usb bad req %d", req->bRequest); | ||
675 | usb_drv_stall(EP_CONTROL, true,true); | ||
676 | ack_control(req); | ||
677 | } | 679 | } |
678 | break; | ||
679 | } | ||
680 | } | 680 | } |
681 | logf("control handled"); | 681 | logf("control handled"); |
682 | } | 682 | } |
@@ -691,10 +691,6 @@ void usb_core_bus_reset(void) | |||
691 | /* called by usb_drv_transfer_completed() */ | 691 | /* called by usb_drv_transfer_completed() */ |
692 | void usb_core_transfer_complete(int endpoint, bool in, int status,int length) | 692 | void usb_core_transfer_complete(int endpoint, bool in, int status,int length) |
693 | { | 693 | { |
694 | #if defined(USB_CHARGING_ONLY) || defined(USB_STORAGE) | ||
695 | (void)in; | ||
696 | #endif | ||
697 | |||
698 | switch (endpoint) { | 694 | switch (endpoint) { |
699 | case EP_CONTROL: | 695 | case EP_CONTROL: |
700 | /* already handled */ | 696 | /* already handled */ |