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 
18 struct USB_request_st usb_setup_buffer;
19 static 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 
27 static uint16_t usb_device_status;
28 static uint8_t usb_configuration_value;
29 
30 static struct USBRequestHandlerHook *usb_request_handler_hooks = NULL;
31 
32 static const unsigned char zero_byte = 0;
33 static const unsigned short zero_word = 0;
34 
35 static unsigned char usb_flags = 0;
36 #define USB_FLAG_ADDRESS_PENDING 0x01
37 
38 static struct process *global_user_event_pocess = NULL;
39 static unsigned int global_user_events = 0;
40 
41 void
42 usb_set_global_event_process(struct process *p)
43 {
44  global_user_event_pocess = p;
45 }
46 unsigned int
47 usb_get_global_events(void)
48 {
49  unsigned int e = global_user_events;
50  global_user_events = 0;
51  return e;
52 }
53 
54 static void
55 notify_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 
63 void
64 usb_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 
82 static uint8_t error_stall = 0;
83 
84 void
85 usb_error_stall()
86 {
87  error_stall = 1;
88  usb_arch_control_stall(0);
89 }
90 
91 void
92 usb_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 
104 static usb_ctrl_data_callback data_callback = NULL;
105 
106 static uint8_t *ctrl_data = NULL;
107 
108 static unsigned int ctrl_data_len = 0;
109 
110 void
111 usb_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 
130 void
131 usb_set_user_process(struct process *p)
132 {
133  user_process = p;
134 }
135 #endif
136 
137 static void
138 get_device_descriptor()
139 {
140  usb_send_ctrl_response((unsigned char *)&device_descriptor,
141  sizeof(device_descriptor));
142 }
143 
144 static void
145 get_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 
196 static void
197 get_configuration_descriptor()
198 {
199  usb_send_ctrl_response((unsigned char *)configuration_head,
200  configuration_head->wTotalLength);
201 }
202 
203 static void
204 get_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 */
211 static int
212 set_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 
226 static void
227 get_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 
234 static void
235 get_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 
249 static void
250 get_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 
257 static void
258 get_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 
269 static unsigned int
270 handle_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 
419 static const struct USBRequestHandler standard_request_handler = {
420  0x00,
421  0x60,
422  0x00,
423  0x00,
424  handle_standard_requests
425 };
426 
427 static struct USBRequestHandlerHook standard_request_hook = {
428  NULL,
429  &standard_request_handler
430 };
431 
432 static void
433 submit_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 
444 PROCESS(usb_process, "USB");
445 
446 PROCESS_THREAD(usb_process, ev, data)
447 {
448  PROCESS_BEGIN();
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 
558 void
559 usb_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 
569 void
570 usb_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 
582 void
583 usb_prepend_request_handler(struct USBRequestHandlerHook *hook)
584 {
585  hook->next = usb_request_handler_hooks;
586  usb_request_handler_hooks = hook;
587 }
588 
589 
590 unsigned int
591 usb_get_current_configuration(void)
592 {
593  return usb_configuration_value;
594 }
595 
596 void
597 usb_setup_bulk_endpoint(unsigned char addr)
598 {
599  usb_arch_setup_bulk_endpoint(addr);
600 }
601 
602 void
603 usb_setup_interrupt_endpoint(unsigned char addr)
604 {
605  usb_arch_setup_interrupt_endpoint(addr);
606 }
607 
608 void
609 usb_disable_endpoint(uint8_t addr)
610 {
611  usb_arch_discard_all_buffers(addr);
612  usb_arch_disable_endpoint(addr);
613 }
614 
615 void
616 usb_discard_all_buffers(uint8_t addr)
617 {
618  usb_arch_discard_all_buffers(addr);
619 }
620 
621 void
622 usb_halt_endpoint(uint8_t addr, int halt)
623 {
624  usb_arch_halt_endpoint(addr, halt);
625 }
626 
627 int
628 usb_send_pending(uint8_t addr)
629 {
630  return usb_arch_send_pending(addr);
631 }
#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
static uip_ds6_addr_t * addr
Pointer to a nbr cache entry.
Definition: uip-nd6.c:107
#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_poll(struct process *p)
Request a process to be polled.
Definition: process.c:371
Header file for the Contiki process interface.
PROCESS_THREAD(cc2538_rf_process, ev, data)
Implementation of the cc2538 RF driver process.
Definition: cc2538-rf.c:1110
void process_start(struct process *p, process_data_t data)
Start a process.
Definition: process.c:99