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