Contiki-NG
usb-core.c
1#include "usb-core.h"
2#include "usb.h"
3#include "usb-arch.h"
4#include "usb-api.h"
5#include "sys/process.h"
6#include "descriptors.h"
7#include "string-descriptors.h"
8
9#include <stdio.h>
10
11#ifdef DEBUG
12#define PRINTF(...) printf(__VA_ARGS__)
13#else
14#define PRINTF(...)
15#endif
16
17
18struct USB_request_st usb_setup_buffer;
19static USBBuffer ctrl_buffer;
20
21#define SETUP_ID 1
22#define OUT_ID 2
23#define IN_ID 3
24#define STATUS_OUT_ID 4
25#define STATUS_IN_ID 5
26
27static uint16_t usb_device_status;
28static uint8_t usb_configuration_value;
29
30static struct USBRequestHandlerHook *usb_request_handler_hooks = NULL;
31
32static const unsigned char zero_byte = 0;
33static const unsigned short zero_word = 0;
34
35static unsigned char usb_flags = 0;
36#define USB_FLAG_ADDRESS_PENDING 0x01
37
38static struct process *global_user_event_pocess = NULL;
39static unsigned int global_user_events = 0;
40
41void
42usb_set_global_event_process(struct process *p)
43{
44 global_user_event_pocess = p;
45}
46unsigned int
47usb_get_global_events(void)
48{
49 unsigned int e = global_user_events;
50 global_user_events = 0;
51 return e;
52}
53
54static void
55notify_user(unsigned int e)
56{
57 global_user_events |= e;
58 if(global_user_event_pocess) {
59 process_poll(global_user_event_pocess);
60 }
61}
62
63void
64usb_send_ctrl_response(const uint8_t * data, unsigned int len)
65{
66 if(ctrl_buffer.flags & USB_BUFFER_SUBMITTED)
67 return;
68 if(len >= usb_setup_buffer.wLength) {
69 len = usb_setup_buffer.wLength; /* Truncate if too long */
70 }
71 ctrl_buffer.flags = USB_BUFFER_NOTIFY | USB_BUFFER_IN;
72 if(len < usb_setup_buffer.wLength) {
73 ctrl_buffer.flags |= USB_BUFFER_SHORT_END;
74 }
75 ctrl_buffer.next = NULL;
76 ctrl_buffer.data = (uint8_t *) data;
77 ctrl_buffer.left = len;
78 ctrl_buffer.id = IN_ID;
79 usb_submit_xmit_buffer(0, &ctrl_buffer);
80}
81
82static uint8_t error_stall = 0;
83
84void
85usb_error_stall()
86{
87 error_stall = 1;
88 usb_arch_control_stall(0);
89}
90
91void
92usb_send_ctrl_status()
93{
94 if(ctrl_buffer.flags & USB_BUFFER_SUBMITTED)
95 return;
96 ctrl_buffer.flags = USB_BUFFER_NOTIFY | USB_BUFFER_IN;
97 ctrl_buffer.next = NULL;
98 ctrl_buffer.data = NULL;
99 ctrl_buffer.left = 0;
100 ctrl_buffer.id = STATUS_IN_ID;
101 usb_submit_xmit_buffer(0, &ctrl_buffer);
102}
103
104static usb_ctrl_data_callback data_callback = NULL;
105
106static uint8_t *ctrl_data = NULL;
107
108static unsigned int ctrl_data_len = 0;
109
110void
111usb_get_ctrl_data(uint8_t * data, unsigned int length,
112 usb_ctrl_data_callback cb)
113{
114 if(ctrl_buffer.flags & USB_BUFFER_SUBMITTED)
115 return;
116 PRINTF("usb_get_ctrl_data: %d\n", length);
117 data_callback = cb;
118 ctrl_data = data;
119 ctrl_data_len = length;
120 ctrl_buffer.flags = USB_BUFFER_NOTIFY;
121 ctrl_buffer.next = NULL;
122 ctrl_buffer.data = data;
123 ctrl_buffer.left = length;
124 ctrl_buffer.id = OUT_ID;
125 usb_submit_recv_buffer(0, &ctrl_buffer);
126}
127
128#if 0
129
130void
131usb_set_user_process(struct process *p)
132{
133 user_process = p;
134}
135#endif
136
137static void
138get_device_descriptor()
139{
140 usb_send_ctrl_response((unsigned char *)&device_descriptor,
141 sizeof(device_descriptor));
142}
143
144static void
145get_string_descriptor()
146{
147#if OLD_STRING_DESCR
148 if(LOW_BYTE(usb_setup_buffer.wValue) == 0) {
149 usb_send_ctrl_response((const unsigned char *)string_languages->
150 lang_descr, string_languages->lang_descr->bLength);
151 } else {
152 const struct usb_st_string_descriptor *descriptor;
153
154 unsigned char l;
155
156 const struct usb_st_string_descriptor *const *table;
157
158 const struct usb_st_string_language_map *map;
159
160 if(LOW_BYTE(usb_setup_buffer.wValue) > string_languages->max_index) {
161 usb_error_stall();
162 return;
163 }
164 l = string_languages->num_lang;
165 map = string_languages->map;
166 table = map->descriptors; /* Use first table if language not found */
167 while(l > 0) {
168 if(map->lang_id == usb_setup_buffer.wIndex) {
169 table = map->descriptors;
170 break;
171 }
172 map++;
173 l--;
174 }
175 PRINTF("Lang id %04x = table %p\n", usb_setup_buffer.wIndex,
176 (void *)table);
177 descriptor = table[LOW_BYTE(usb_setup_buffer.wValue) - 1];
178 usb_send_ctrl_response((const unsigned char *)descriptor,
179 descriptor->bLength);
180 }
181#else
182 const struct usb_st_string_descriptor *descriptor;
183
184 descriptor = (struct usb_st_string_descriptor *)
185 usb_class_get_string_descriptor(usb_setup_buffer.wIndex,
186 LOW_BYTE(usb_setup_buffer.wValue));
187 if(!descriptor) {
188 usb_error_stall();
189 return;
190 }
191 usb_send_ctrl_response((const unsigned char *)descriptor,
192 descriptor->bLength);
193#endif
194}
195
196static void
197get_configuration_descriptor()
198{
199 usb_send_ctrl_response((unsigned char *)configuration_head,
200 configuration_head->wTotalLength);
201}
202
203static void
204get_configuration()
205{
206 usb_send_ctrl_response((unsigned char *)&usb_configuration_value,
207 sizeof(usb_configuration_value));
208}
209
210/* Returns true if the configuration value changed */
211static int
212set_configuration()
213{
214 notify_user(USB_EVENT_CONFIG);
215 if(usb_configuration_value != LOW_BYTE(usb_setup_buffer.wValue)) {
216 usb_configuration_value = LOW_BYTE(usb_setup_buffer.wValue);
217 usb_arch_set_configuration(usb_configuration_value);
218 usb_send_ctrl_status();
219 return 1;
220 } else {
221 usb_send_ctrl_status();
222 return 0;
223 }
224}
225
226static void
227get_device_status()
228{
229 PRINTF("get_device_status\n");
230 usb_send_ctrl_response((const unsigned char *)&usb_device_status,
231 sizeof(usb_device_status));
232}
233
234static void
235get_endpoint_status()
236{
237 static uint16_t status;
238
239 PRINTF("get_endpoint_status\n");
240 if((usb_setup_buffer.wIndex & 0x7f) == 0) {
241 usb_send_ctrl_response((const unsigned char *)&zero_word,
242 sizeof(zero_word));
243 } else {
244 status = usb_arch_get_ep_status(usb_setup_buffer.wIndex);
245 usb_send_ctrl_response((uint8_t *) & status, sizeof(status));
246 }
247}
248
249static void
250get_interface_status()
251{
252 PRINTF("get_interface_status\n");
253 usb_send_ctrl_response((const unsigned char *)&zero_word,
254 sizeof(zero_word));
255}
256
257static void
258get_interface()
259{
260 PRINTF("get_interface\n");
261 if(usb_configuration_value == 0)
262 usb_error_stall();
263 else {
264 usb_send_ctrl_response(&zero_byte, sizeof(zero_byte));
265 }
266}
267
268
269static unsigned int
270handle_standard_requests()
271{
272 switch (usb_setup_buffer.bmRequestType) {
273 case 0x80: /* standard device IN requests */
274 switch (usb_setup_buffer.bRequest) {
275 case GET_DESCRIPTOR:
276 switch (HIGH_BYTE(usb_setup_buffer.wValue)) {
277 case DEVICE:
278 get_device_descriptor();
279 break;
280 case CONFIGURATION:
281 get_configuration_descriptor();
282 break;
283 case STRING:
284 get_string_descriptor();
285 break;
286 default:
287 /* Unknown descriptor */
288 return 0;
289 }
290 break;
291 case GET_CONFIGURATION:
292 get_configuration();
293 break;
294 case GET_STATUS:
295 get_device_status();
296 break;
297 case GET_INTERFACE:
298 get_interface();
299 break;
300 default:
301 return 0;
302 }
303 break;
304 case 0x81: /* standard interface IN requests */
305 switch (usb_setup_buffer.bRequest) {
306 case GET_STATUS:
307 get_interface_status();
308 break;
309#ifdef HID_ENABLED
310 case GET_DESCRIPTOR:
311 switch (USB_setup_buffer.wValue.byte.high) {
312 case REPORT:
313 get_report_descriptor();
314 break;
315 }
316 break;
317#endif
318 default:
319 return 0;
320 }
321 break;
322 case 0x82: /* standard endpoint IN requests */
323 switch (usb_setup_buffer.bRequest) {
324 case GET_STATUS:
325 get_endpoint_status();
326 break;
327 default:
328 return 0;
329 }
330 break;
331 case 0x00: /* standard device OUT requests */
332 switch (usb_setup_buffer.bRequest) {
333 case SET_ADDRESS:
334 PRINTF("Address: %d\n", LOW_BYTE(usb_setup_buffer.wValue));
335 usb_flags |= USB_FLAG_ADDRESS_PENDING;
336 /* The actual setting of the address is done when the status packet
337 is sent. */
338 usb_send_ctrl_status();
339 break;
340#if SETABLE_STRING_DESCRIPTORS > 0
341 case SET_DESCRIPTOR:
342 if(usb_setup_buffer.wValue.byte.high == STRING) {
343 set_string_descriptor();
344 } else {
345 return 0;
346 }
347 break;
348#endif
349 case SET_CONFIGURATION:
350 if(set_configuration()) {
351#if 0
352 config_msg.data.config = LOW_BYTE(usb_setup_buffer.wValue);
353 notify_user(&config_msg);
354#endif
355 }
356 break;
357 default:
358 return 0;
359 }
360 break;
361 case 0x01: /* standard interface OUT requests */
362 switch (usb_setup_buffer.bRequest) {
363 case SET_INTERFACE:
364 /* Change interface here if we support more than one */
365 usb_send_ctrl_status();
366 break;
367 default:
368 return 0;
369 }
370 break;
371 case 0x02: /* standard endpoint OUT requests */
372 switch (usb_setup_buffer.bRequest) {
373 case SET_FEATURE:
374 case CLEAR_FEATURE:
375 if(usb_setup_buffer.wValue == ENDPOINT_HALT_FEATURE) {
376 usb_arch_halt_endpoint(usb_setup_buffer.wIndex,
377 usb_setup_buffer.bRequest == SET_FEATURE);
378 usb_send_ctrl_status();
379 } else {
380 usb_error_stall();
381 }
382 break;
383 default:
384 return 0;
385 }
386 break;
387#ifdef HID_ENABLED
388 case 0xa1: /* class specific interface IN request */
389 switch (USB_setup_buffer.bRequest) {
390 case GET_HID_REPORT:
391 PRINTF("Get report\n");
392 send_ctrl_response((code u_int8_t *) & zero_byte, sizeof(zero_byte));
393 break;
394 case GET_HID_IDLE:
395 PRINTF("Get idle\n");
396 send_ctrl_response((code u_int8_t *) & zero_byte, sizeof(zero_byte));
397 break;
398 default:
399 return 0;
400 }
401 break;
402 case 0x21: /* class specific interface OUT request */
403 switch (USB_setup_buffer.bRequest) {
404 case SET_HID_IDLE:
405 PRINTF("Set idle\n");
406 send_ctrl_status();
407 break;
408 default:
409 return 0;
410 }
411 break;
412#endif
413 default:
414 return 0;
415 }
416 return 1;
417}
418
419static const struct USBRequestHandler standard_request_handler = {
420 0x00,
421 0x60,
422 0x00,
423 0x00,
424 handle_standard_requests
425};
426
427static struct USBRequestHandlerHook standard_request_hook = {
428 NULL,
429 &standard_request_handler
430};
431
432static void
433submit_setup(void)
434{
435 ctrl_buffer.next = NULL;
436 ctrl_buffer.data = (uint8_t *) & usb_setup_buffer;
437 ctrl_buffer.left = sizeof(usb_setup_buffer);
438 ctrl_buffer.flags = (USB_BUFFER_PACKET_END | USB_BUFFER_SETUP
439 | USB_BUFFER_NOTIFY);
440 ctrl_buffer.id = SETUP_ID;
441 usb_submit_recv_buffer(0, &ctrl_buffer);
442}
443
444PROCESS(usb_process, "USB");
445
446PROCESS_THREAD(usb_process, ev, data)
447{
449 PRINTF("USB process started\n");
450 while(1) {
452 if(ev == PROCESS_EVENT_EXIT)
453 break;
454 if(ev == PROCESS_EVENT_POLL) {
455 unsigned int events = usb_arch_get_global_events();
456
457 if(events) {
458 if(events & USB_EVENT_RESET) {
459 submit_setup();
460 usb_configuration_value = 0;
461 notify_user(USB_EVENT_RESET);
462 }
463 if(events & USB_EVENT_SUSPEND) {
464 notify_user(USB_EVENT_SUSPEND);
465 }
466 if(events & USB_EVENT_RESUME) {
467 notify_user(USB_EVENT_RESUME);
468 }
469
470 }
471 events = usb_get_ep_events(0);
472 if(events) {
473 if((events & USB_EP_EVENT_NOTIFICATION)
474 && !(ctrl_buffer.flags & USB_BUFFER_SUBMITTED)) {
475 /* PRINTF("Endpoint 0\n"); */
476 if(ctrl_buffer.flags & USB_BUFFER_FAILED) {
477 /* Something went wrong with the buffer, just wait for a
478 new SETUP packet */
479 PRINTF("Discarded\n");
480 submit_setup();
481 } else if(ctrl_buffer.flags & USB_BUFFER_SETUP) {
482 struct USBRequestHandlerHook *hook = usb_request_handler_hooks;
483
484 PRINTF("Setup\n");
485 {
486 unsigned int i;
487
488 for(i = 0; i < 8; i++)
489 PRINTF(" %02x", ((unsigned char *)&usb_setup_buffer)[i]);
490 PRINTF("\n");
491 }
492
493 while(hook) {
494 const struct USBRequestHandler *handler = hook->handler;
495
496 /* Check if the handler matches the request */
497 if(((handler->request_type ^ usb_setup_buffer.bmRequestType)
498 & handler->request_type_mask) == 0
499 && ((handler->request ^ usb_setup_buffer.bRequest)
500 & handler->request_mask) == 0) {
501 if(handler->handler_func())
502 break;
503 }
504 hook = hook->next;
505 }
506 if(!hook) {
507 /* No handler found */
508 usb_error_stall();
509 PRINTF("Unhandled setup: %02x %02x %04x %04x %04x\n",
510 usb_setup_buffer.bmRequestType,
511 usb_setup_buffer.bRequest, usb_setup_buffer.wValue,
512 usb_setup_buffer.wIndex, usb_setup_buffer.wLength);
513 }
514 /* Check if any handler stalled the pipe, if so prepare for
515 next setup */
516 if(error_stall) {
517 error_stall = 0;
518 submit_setup();
519 }
520 } else {
521 if(ctrl_buffer.id == IN_ID) {
522 /* Receive status stage */
523 PRINTF("Status OUT\n");
524 ctrl_buffer.flags = USB_BUFFER_NOTIFY;
525 ctrl_buffer.next = NULL;
526 ctrl_buffer.data = NULL;
527 ctrl_buffer.left = 0;
528 ctrl_buffer.id = STATUS_OUT_ID;
529 usb_submit_recv_buffer(0, &ctrl_buffer);
530 } else if(ctrl_buffer.id == STATUS_OUT_ID) {
531 PRINTF("Status OUT done\n");
532 submit_setup();
533 } else if(ctrl_buffer.id == STATUS_IN_ID) {
534 PRINTF("Status IN done\n");
535 if(usb_flags & USB_FLAG_ADDRESS_PENDING) {
536 while(usb_send_pending(0));
537 usb_arch_set_address(LOW_BYTE(usb_setup_buffer.wValue));
538 usb_flags &= ~USB_FLAG_ADDRESS_PENDING;
539 }
540 submit_setup();
541 } else if(ctrl_buffer.id == OUT_ID) {
542 PRINTF("OUT\n");
543 if(data_callback) {
544 data_callback(ctrl_data, ctrl_data_len - ctrl_buffer.left);
545 } else {
546 usb_send_ctrl_status();
547 }
548 }
549 }
550 }
551 }
552 }
553 }
554 PROCESS_END();
555}
556
557
558void
559usb_setup(void)
560{
561 usb_arch_setup();
562 process_start(&usb_process, NULL);
563 usb_arch_set_global_event_process(&usb_process);
564 usb_set_ep_event_process(0, &usb_process);
565
566 usb_register_request_handler(&standard_request_hook);
567}
568
569void
570usb_register_request_handler(struct USBRequestHandlerHook *hook)
571{
572 struct USBRequestHandlerHook **prevp = &usb_request_handler_hooks;
573 /* Find last hook */
574 while(*prevp) {
575 prevp = &(*prevp)->next;
576 }
577 /* Add last */
578 *prevp = hook;
579 hook->next = NULL;
580}
581
582void
583usb_prepend_request_handler(struct USBRequestHandlerHook *hook)
584{
585 hook->next = usb_request_handler_hooks;
586 usb_request_handler_hooks = hook;
587}
588
589
590unsigned int
591usb_get_current_configuration(void)
592{
593 return usb_configuration_value;
594}
595
596void
597usb_setup_bulk_endpoint(unsigned char addr)
598{
599 usb_arch_setup_bulk_endpoint(addr);
600}
601
602void
603usb_setup_interrupt_endpoint(unsigned char addr)
604{
605 usb_arch_setup_interrupt_endpoint(addr);
606}
607
608void
609usb_disable_endpoint(uint8_t addr)
610{
611 usb_arch_discard_all_buffers(addr);
612 usb_arch_disable_endpoint(addr);
613}
614
615void
616usb_discard_all_buffers(uint8_t addr)
617{
618 usb_arch_discard_all_buffers(addr);
619}
620
621void
622usb_halt_endpoint(uint8_t addr, int halt)
623{
624 usb_arch_halt_endpoint(addr, halt);
625}
626
627int
628usb_send_pending(uint8_t addr)
629{
630 return usb_arch_send_pending(addr);
631}
PROCESS_THREAD(cc2538_rf_process, ev, data)
Implementation of the cc2538 RF driver process.
Definition: cc2538-rf.c:1154
#define PROCESS(name, strname)
Declare a process.
Definition: process.h:307
#define PROCESS_WAIT_EVENT()
Wait for an event to be posted to the process.
Definition: process.h:141
#define PROCESS_BEGIN()
Define the beginning of a process.
Definition: process.h:120
#define PROCESS_END()
Define the end of a process.
Definition: process.h:131
void process_start(struct process *p, process_data_t data)
Start a process.
Definition: process.c:99
void process_poll(struct process *p)
Request a process to be polled.
Definition: process.c:371
USB header file for the nRF.
Header file for the Contiki process interface.
static uip_ds6_addr_t * addr
Pointer to a nbr cache entry.
Definition: uip-nd6.c:107