Contiki 2.5
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 
19 struct USB_request_st usb_setup_buffer;
20 static 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 
28 static uint16_t usb_device_status;
29 static uint8_t usb_configuration_value;
30 
31 static struct USBRequestHandlerHook *usb_request_handler_hooks = NULL;
32 
33 static const unsigned char zero_byte = 0;
34 static const unsigned short zero_word = 0;
35 
36 static unsigned char usb_flags = 0;
37 #define USB_FLAG_ADDRESS_PENDING 0x01
38 
39 static struct process *global_user_event_pocess = NULL;
40 static unsigned int global_user_events = 0;
41 
42 void
43 usb_set_global_event_process(struct process *p)
44 {
45  global_user_event_pocess = p;
46 }
47 unsigned int
48 usb_get_global_events(void)
49 {
50  unsigned int e = global_user_events;
51  global_user_events = 0;
52  return e;
53 }
54 
55 static void
56 notify_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 
64 void
65 usb_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 
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) 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 
103 static usb_ctrl_data_callback data_callback = NULL;
104 static uint8_t *ctrl_data = NULL;
105 static unsigned int ctrl_data_len = 0;
106 void
107 usb_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 
125 void
126 usb_set_user_process(struct process *p)
127 {
128  user_process = p;
129 }
130 #endif
131 
132 static void
133 get_device_descriptor()
134 {
135  usb_send_ctrl_response((unsigned char*)&device_descriptor, sizeof(device_descriptor));
136 }
137 
138 static void
139 get_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 
184 static void
185 get_configuration_descriptor()
186 {
187  usb_send_ctrl_response((unsigned char*)configuration_head,
188  configuration_head->wTotalLength);
189 }
190 
191 static void
192 get_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 */
199 static int
200 set_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 
214 static void
215 get_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 
222 static void
223 get_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 
236 static void
237 get_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 
244 static void
245 get_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 
256 static unsigned int
257 handle_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 
407 static const struct USBRequestHandler standard_request_handler =
408  {
409  0x00, 0x60,
410  0x00, 0x00,
411  handle_standard_requests
412  };
413 
414 static struct USBRequestHandlerHook standard_request_hook =
415  {
416  NULL,
417  &standard_request_handler
418  };
419 
420 static void
421 submit_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 
432 PROCESS(usb_process, "USB");
433 
434 PROCESS_THREAD(usb_process, ev , data)
435 {
436  PROCESS_BEGIN();
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 
540 void
541 usb_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 
551 void
552 usb_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 
564 void
565 usb_prepend_request_handler(struct USBRequestHandlerHook *hook)
566 {
567  hook->next = usb_request_handler_hooks;
568  usb_request_handler_hooks = hook;
569 }
570 
571 
572 unsigned int
573 usb_get_current_configuration(void)
574 {
575  return usb_configuration_value;
576 }
577 
578 void
579 usb_setup_bulk_endpoint(unsigned char addr)
580 {
581  usb_arch_setup_bulk_endpoint(addr);
582 }
583 
584 void
585 usb_setup_interrupt_endpoint(unsigned char addr)
586 {
587  usb_arch_setup_interrupt_endpoint(addr);
588 }
589 
590 void
591 usb_disable_endpoint(uint8_t addr)
592 {
593  usb_arch_discard_all_buffers(addr);
594  usb_arch_disable_endpoint(addr);
595 }
596 
597 void
598 usb_discard_all_buffers(uint8_t addr)
599 {
600  usb_arch_discard_all_buffers(addr);
601 }
602 
603 void
604 usb_halt_endpoint(uint8_t addr, int halt)
605 {
606  usb_arch_halt_endpoint(addr, halt);
607 }
608 
609 int
610 usb_send_pending(uint8_t addr)
611 {
612  return usb_arch_send_pending(addr);
613 }
614