Contiki 2.6

usb-core.c

00001 #include <usb-core.h>
00002 #include <usb.h>
00003 #include <usb-arch.h>
00004 #include <usb-api.h>
00005 #include <stdio.h>
00006 #include <sys/process.h>
00007 #include <stdio.h>
00008 #include <descriptors.h>
00009 #include <string-descriptors.h>
00010 
00011 #define DEBUG 
00012 #ifdef DEBUG
00013 #define PRINTF(...) printf(__VA_ARGS__)
00014 #else
00015 #define PRINTF(...)
00016 #endif
00017 
00018 
00019 struct USB_request_st usb_setup_buffer;
00020 static USBBuffer ctrl_buffer;
00021 
00022 #define SETUP_ID 1
00023 #define OUT_ID 2
00024 #define IN_ID 3
00025 #define STATUS_OUT_ID 4
00026 #define STATUS_IN_ID 5
00027 
00028 static uint16_t usb_device_status;
00029 static uint8_t usb_configuration_value;
00030 
00031 static struct USBRequestHandlerHook *usb_request_handler_hooks = NULL;
00032 
00033 static const unsigned char zero_byte = 0;
00034 static const unsigned short zero_word = 0;
00035 
00036 static unsigned char usb_flags = 0;
00037 #define USB_FLAG_ADDRESS_PENDING 0x01
00038 
00039 static struct process *global_user_event_pocess = NULL;
00040 static unsigned int global_user_events = 0;
00041 
00042 void
00043 usb_set_global_event_process(struct process *p)
00044 {
00045   global_user_event_pocess = p;
00046 }
00047 unsigned int
00048 usb_get_global_events(void)
00049 {
00050   unsigned int e = global_user_events;
00051   global_user_events = 0;
00052   return e;
00053 }
00054 
00055 static void
00056 notify_user(unsigned int e)
00057 {
00058   global_user_events |= e;
00059   if (global_user_event_pocess) {
00060     process_poll(global_user_event_pocess);
00061   }
00062 }
00063 
00064 void
00065 usb_send_ctrl_response(const uint8_t *data, unsigned int len)
00066 {
00067   if (ctrl_buffer.flags & USB_BUFFER_SUBMITTED) return;
00068   if (len >= usb_setup_buffer.wLength) {
00069     len = usb_setup_buffer.wLength;     /* Truncate if too long */
00070   }
00071   ctrl_buffer.flags = USB_BUFFER_NOTIFY | USB_BUFFER_IN;
00072   if (len < usb_setup_buffer.wLength) {
00073     ctrl_buffer.flags |= USB_BUFFER_SHORT_END;
00074   }
00075   ctrl_buffer.next = NULL;
00076   ctrl_buffer.data = (uint8_t*)data;
00077   ctrl_buffer.left = len;
00078   ctrl_buffer.id = IN_ID;
00079   usb_submit_xmit_buffer(0,&ctrl_buffer);
00080 }
00081 
00082 static uint8_t error_stall = 0;
00083 
00084 void
00085 usb_error_stall()
00086 {
00087   error_stall = 1;
00088   usb_arch_control_stall(0);
00089 }
00090 
00091 void
00092 usb_send_ctrl_status()
00093 {
00094   if (ctrl_buffer.flags & USB_BUFFER_SUBMITTED) return;
00095   ctrl_buffer.flags = USB_BUFFER_NOTIFY | USB_BUFFER_IN;
00096   ctrl_buffer.next = NULL;
00097   ctrl_buffer.data = NULL;
00098   ctrl_buffer.left = 0;
00099   ctrl_buffer.id = STATUS_IN_ID;
00100   usb_submit_xmit_buffer(0,&ctrl_buffer);
00101 }
00102 
00103 static usb_ctrl_data_callback data_callback = NULL;
00104 static uint8_t *ctrl_data = NULL;
00105 static unsigned int ctrl_data_len = 0;
00106 void
00107 usb_get_ctrl_data(uint8_t *data, unsigned int length,
00108                   usb_ctrl_data_callback cb)
00109 {
00110   if (ctrl_buffer.flags & USB_BUFFER_SUBMITTED) return;
00111   PRINTF("usb_get_ctrl_data: %d\n",length);
00112   data_callback = cb;
00113   ctrl_data = data;
00114   ctrl_data_len = length;
00115   ctrl_buffer.flags = USB_BUFFER_NOTIFY;
00116   ctrl_buffer.next = NULL;
00117   ctrl_buffer.data = data;
00118   ctrl_buffer.left = length;
00119   ctrl_buffer.id = OUT_ID;
00120   usb_submit_recv_buffer(0,&ctrl_buffer);
00121 }
00122 
00123 #if 0
00124 
00125 void
00126 usb_set_user_process(struct process *p)
00127 {
00128   user_process = p;
00129 }
00130 #endif
00131 
00132 static void
00133 get_device_descriptor()
00134 {
00135   usb_send_ctrl_response((unsigned char*)&device_descriptor, sizeof(device_descriptor));
00136 }
00137 
00138 static void
00139 get_string_descriptor()
00140 {
00141 #if OLD_STRING_DESCR
00142   if (LOW_BYTE(usb_setup_buffer.wValue) == 0) {
00143     usb_send_ctrl_response((const unsigned char*)string_languages->lang_descr,
00144                            string_languages->lang_descr->bLength);
00145   } else {
00146     const struct usb_st_string_descriptor *descriptor;
00147     unsigned char l;
00148     const struct usb_st_string_descriptor * const *table;
00149     const struct usb_st_string_language_map *map;
00150     if (LOW_BYTE(usb_setup_buffer.wValue) > string_languages->max_index) {
00151       usb_error_stall();
00152       return;
00153     }
00154     l = string_languages->num_lang;
00155     map = string_languages->map;
00156     table = map->descriptors; /* Use first table if language not found */
00157     while (l > 0) {
00158       if (map->lang_id == usb_setup_buffer.wIndex) {
00159         table = map->descriptors;
00160         break;
00161       }
00162       map++;
00163       l--;
00164     }
00165     PRINTF("Lang id %04x = table %p\n", usb_setup_buffer.wIndex, (void*)table);
00166     descriptor = table[LOW_BYTE(usb_setup_buffer.wValue) - 1];
00167     usb_send_ctrl_response((const unsigned char*)descriptor,
00168                            descriptor->bLength);
00169   }
00170 #else
00171   const struct usb_st_string_descriptor *descriptor;
00172   descriptor = (struct usb_st_string_descriptor*)
00173     usb_class_get_string_descriptor(usb_setup_buffer.wIndex,
00174                                     LOW_BYTE(usb_setup_buffer.wValue));
00175   if (!descriptor) {
00176     usb_error_stall();
00177     return;
00178   }
00179   usb_send_ctrl_response((const unsigned char*)descriptor,
00180                            descriptor->bLength);
00181 #endif
00182 }
00183 
00184 static void
00185 get_configuration_descriptor()
00186 {
00187   usb_send_ctrl_response((unsigned char*)configuration_head,
00188                          configuration_head->wTotalLength);
00189 }
00190 
00191 static void
00192 get_configuration()
00193 {
00194   usb_send_ctrl_response((unsigned char*)&usb_configuration_value,
00195                          sizeof(usb_configuration_value));
00196 }
00197 
00198 /* Returns true if the configuration value changed */
00199 static int
00200 set_configuration()
00201 {
00202   notify_user(USB_EVENT_CONFIG);
00203   if (usb_configuration_value != LOW_BYTE(usb_setup_buffer.wValue)) {
00204     usb_configuration_value = LOW_BYTE(usb_setup_buffer.wValue);
00205     usb_arch_set_configuration(usb_configuration_value);
00206     usb_send_ctrl_status();
00207     return 1;
00208   } else {
00209     usb_send_ctrl_status();
00210     return 0;
00211   }
00212 }
00213 
00214 static void
00215 get_device_status()
00216 {
00217   PRINTF("get_device_status\n");
00218   usb_send_ctrl_response((const unsigned char*)&usb_device_status,
00219                      sizeof(usb_device_status));
00220 }
00221 
00222 static void
00223 get_endpoint_status()
00224 {
00225   static uint16_t status;
00226   PRINTF("get_endpoint_status\n");
00227   if ((usb_setup_buffer.wIndex & 0x7f) == 0) {
00228     usb_send_ctrl_response((const unsigned char*)&zero_word,
00229                        sizeof(zero_word));
00230   } else {
00231     status = usb_arch_get_ep_status(usb_setup_buffer.wIndex);
00232     usb_send_ctrl_response((uint8_t*)&status, sizeof(status));
00233   }
00234 }
00235 
00236 static void
00237 get_interface_status()
00238 {
00239   PRINTF("get_interface_status\n");
00240   usb_send_ctrl_response((const unsigned char*)&zero_word,
00241                          sizeof(zero_word));
00242 }
00243 
00244 static void
00245 get_interface()
00246 {
00247   PRINTF("get_interface\n");
00248   if (usb_configuration_value == 0) usb_error_stall();
00249   else {
00250     usb_send_ctrl_response(&zero_byte,
00251                        sizeof(zero_byte));
00252   }
00253 }
00254 
00255 
00256 static unsigned int
00257 handle_standard_requests()
00258 {
00259   switch(usb_setup_buffer.bmRequestType) {
00260   case 0x80: /* standard device IN requests */
00261     switch(usb_setup_buffer.bRequest) {
00262     case GET_DESCRIPTOR:
00263       switch (HIGH_BYTE(usb_setup_buffer.wValue)) {
00264       case DEVICE:
00265         get_device_descriptor();
00266         break;
00267       case CONFIGURATION:
00268         get_configuration_descriptor();
00269         break;
00270       case STRING:
00271         get_string_descriptor();
00272         break;
00273       default:
00274         /* Unknown descriptor */
00275         return 0;
00276       }
00277       break;
00278     case GET_CONFIGURATION:
00279       get_configuration();
00280       break;
00281     case GET_STATUS:
00282       get_device_status();
00283       break;
00284     case GET_INTERFACE:
00285       get_interface();
00286       break;
00287     default:
00288       return 0;
00289     }
00290     break;
00291   case 0x81: /* standard interface IN requests */
00292     switch(usb_setup_buffer.bRequest) {
00293     case GET_STATUS:
00294       get_interface_status();
00295       break;
00296 #ifdef HID_ENABLED
00297       case GET_DESCRIPTOR:
00298         switch (USB_setup_buffer.wValue.byte.high) {
00299         case REPORT:
00300           get_report_descriptor();
00301           break;
00302         }
00303         break;
00304 #endif  
00305     default:
00306       return 0;
00307     }
00308     break;
00309   case 0x82: /* standard endpoint IN requests */
00310     switch(usb_setup_buffer.bRequest) {
00311     case GET_STATUS:
00312       get_endpoint_status();
00313       break;
00314     default:
00315       return 0;
00316     }
00317     break;
00318   case 0x00: /* standard device OUT requests */
00319     switch(usb_setup_buffer.bRequest) {
00320     case SET_ADDRESS:
00321       PRINTF("Address: %d\n", LOW_BYTE(usb_setup_buffer.wValue));
00322       usb_flags |= USB_FLAG_ADDRESS_PENDING;
00323       /* The actual setting of the address is done when the status packet
00324          is sent. */
00325       usb_send_ctrl_status();
00326       break;
00327 #if SETABLE_STRING_DESCRIPTORS > 0
00328     case SET_DESCRIPTOR:
00329       if (usb_setup_buffer.wValue.byte.high == STRING) {
00330         set_string_descriptor();
00331       } else {
00332         return 0;
00333       }
00334       break;
00335 #endif
00336     case SET_CONFIGURATION:
00337       if (set_configuration()) {
00338 #if 0
00339         config_msg.data.config = LOW_BYTE(usb_setup_buffer.wValue);
00340         notify_user(&config_msg);
00341 #endif
00342       }
00343       break;
00344     default:
00345       return 0;
00346     }
00347     break;
00348   case 0x01: /* standard interface OUT requests */
00349     switch(usb_setup_buffer.bRequest) {
00350     case SET_INTERFACE:
00351       /* Change interface here if we support more than one */
00352       usb_send_ctrl_status();
00353       break;
00354     default:
00355       return 0;
00356     }
00357     break;
00358   case 0x02: /* standard endpoint OUT requests */
00359     switch(usb_setup_buffer.bRequest) {
00360     case SET_FEATURE:
00361     case CLEAR_FEATURE:
00362       if (usb_setup_buffer.wValue == ENDPOINT_HALT_FEATURE) {
00363         usb_arch_halt_endpoint(usb_setup_buffer.wIndex, usb_setup_buffer.bRequest== SET_FEATURE);
00364         usb_send_ctrl_status();
00365       } else {
00366         usb_error_stall();
00367       }
00368       break;
00369     default:
00370       return 0;
00371     }
00372     break;
00373 #ifdef HID_ENABLED
00374   case 0xa1: /* class specific interface IN request*/
00375     switch(USB_setup_buffer.bRequest) {
00376     case GET_HID_REPORT:
00377       PRINTF("Get report\n");
00378       send_ctrl_response((code u_int8_t*)&zero_byte,
00379                            sizeof(zero_byte));
00380       break;
00381     case GET_HID_IDLE:
00382       PRINTF("Get idle\n");
00383       send_ctrl_response((code u_int8_t*)&zero_byte,
00384                          sizeof(zero_byte));
00385       break;
00386     default:
00387       return 0;
00388       }
00389     break;
00390   case 0x21: /* class specific interface OUT request*/
00391     switch(USB_setup_buffer.bRequest) {
00392     case SET_HID_IDLE:
00393       PRINTF("Set idle\n");
00394       send_ctrl_status();
00395       break;
00396     default:
00397       return 0;
00398     }
00399     break;
00400 #endif
00401   default:
00402     return 0;
00403   }
00404   return 1;
00405 }
00406 
00407 static const struct USBRequestHandler standard_request_handler =
00408   {
00409     0x00, 0x60,
00410     0x00, 0x00,
00411     handle_standard_requests
00412   };
00413 
00414 static struct USBRequestHandlerHook standard_request_hook =
00415   {
00416     NULL,
00417     &standard_request_handler
00418   };
00419 
00420 static void
00421 submit_setup(void)
00422 {
00423   ctrl_buffer.next = NULL;
00424   ctrl_buffer.data = (uint8_t*)&usb_setup_buffer;
00425   ctrl_buffer.left = sizeof(usb_setup_buffer);
00426   ctrl_buffer.flags = (USB_BUFFER_PACKET_END | USB_BUFFER_SETUP
00427                        | USB_BUFFER_NOTIFY);
00428   ctrl_buffer.id = SETUP_ID;
00429   usb_submit_recv_buffer(0, &ctrl_buffer);
00430 }
00431 
00432 PROCESS(usb_process, "USB");
00433 
00434 PROCESS_THREAD(usb_process, ev , data)
00435 {
00436   PROCESS_BEGIN();
00437   PRINTF("USB process started\n");
00438   while(1) {
00439     PROCESS_WAIT_EVENT();
00440     if (ev == PROCESS_EVENT_EXIT) break;
00441     if (ev == PROCESS_EVENT_POLL) {
00442       unsigned int events = usb_arch_get_global_events();
00443       if (events) {
00444         if (events & USB_EVENT_RESET) {
00445           submit_setup();
00446           usb_configuration_value = 0;
00447           notify_user(USB_EVENT_RESET);
00448         }
00449         if (events & USB_EVENT_SUSPEND) {
00450           notify_user(USB_EVENT_SUSPEND);
00451         }
00452         if (events & USB_EVENT_RESUME) {
00453           notify_user(USB_EVENT_RESUME);
00454         }
00455         
00456       }
00457       events = usb_get_ep_events(0);
00458       if (events) {
00459         if ((events & USB_EP_EVENT_NOTIFICATION)
00460             && !(ctrl_buffer.flags & USB_BUFFER_SUBMITTED)) {
00461           /* PRINTF("Endpoint 0\n"); */
00462           if (ctrl_buffer.flags & USB_BUFFER_FAILED) {
00463             /* Something went wrong with the buffer, just wait for a
00464                new SETUP packet */
00465             PRINTF("Discarded\n");
00466             submit_setup();
00467           } else if (ctrl_buffer.flags & USB_BUFFER_SETUP) {
00468             struct USBRequestHandlerHook *hook = usb_request_handler_hooks;
00469 
00470             PRINTF("Setup\n");
00471             {
00472             unsigned int i;
00473             for (i = 0; i< 8; i++) PRINTF(" %02x", ((unsigned char*)&usb_setup_buffer)[i]);
00474             PRINTF("\n");
00475             }
00476             
00477             while(hook) {
00478               const struct USBRequestHandler *handler = hook->handler;
00479               /* Check if the handler matches the request */
00480               if (((handler->request_type ^ usb_setup_buffer.bmRequestType)
00481                    & handler->request_type_mask) == 0
00482                   && ((handler->request ^ usb_setup_buffer.bRequest)
00483                       & handler->request_mask) == 0) {
00484                 if (handler->handler_func()) break;
00485               }
00486               hook = hook->next;
00487             }
00488             if (!hook) {
00489               /* No handler found */
00490               usb_error_stall();
00491               PRINTF("Unhandled setup: %02x %02x %04x %04x %04x\n",
00492                      usb_setup_buffer.bmRequestType, usb_setup_buffer.bRequest,
00493                      usb_setup_buffer.wValue, usb_setup_buffer.wIndex,
00494                      usb_setup_buffer.wLength);
00495             }
00496             /* Check if any handler stalled the pipe, if so prepare for
00497                next setup */
00498             if (error_stall) {
00499               error_stall = 0;
00500               submit_setup();
00501             }
00502           } else {
00503             if (ctrl_buffer.id == IN_ID) {
00504               /* Receive status stage */
00505               PRINTF("Status OUT\n");
00506               ctrl_buffer.flags =  USB_BUFFER_NOTIFY;
00507               ctrl_buffer.next = NULL;
00508               ctrl_buffer.data = NULL;
00509               ctrl_buffer.left = 0;
00510               ctrl_buffer.id = STATUS_OUT_ID;
00511               usb_submit_recv_buffer(0,&ctrl_buffer);
00512             } else if (ctrl_buffer.id == STATUS_OUT_ID) {
00513               PRINTF("Status OUT done\n");
00514               submit_setup();
00515             } else if (ctrl_buffer.id == STATUS_IN_ID) {
00516               PRINTF("Status IN done\n");
00517               if (usb_flags & USB_FLAG_ADDRESS_PENDING) {
00518                 while(usb_send_pending(0));
00519                 usb_arch_set_address(LOW_BYTE(usb_setup_buffer.wValue));
00520                 usb_flags &= ~USB_FLAG_ADDRESS_PENDING;
00521               }
00522               submit_setup();
00523             } else if (ctrl_buffer.id == OUT_ID) {
00524               PRINTF("OUT\n");
00525               if (data_callback) {
00526                 data_callback(ctrl_data, ctrl_data_len- ctrl_buffer.left);
00527               } else {
00528                 usb_send_ctrl_status();
00529               }
00530             }
00531           }
00532         }
00533       }
00534     }
00535   }
00536   PROCESS_END();
00537 }
00538 
00539 
00540 void
00541 usb_setup(void)
00542 {
00543   usb_arch_setup();
00544   process_start(&usb_process, NULL);
00545   usb_arch_set_global_event_process(&usb_process);
00546   usb_set_ep_event_process(0, &usb_process);
00547 
00548   usb_register_request_handler(&standard_request_hook);
00549 }
00550 
00551 void
00552 usb_register_request_handler(struct USBRequestHandlerHook *hook)
00553 {
00554   struct USBRequestHandlerHook **prevp = &usb_request_handler_hooks;
00555   /* Find last hook */
00556   while(*prevp) {
00557     prevp = &(*prevp)->next;
00558   }
00559   /* Add last */
00560   *prevp = hook;
00561   hook->next = NULL;
00562 }
00563 
00564 void
00565 usb_prepend_request_handler(struct USBRequestHandlerHook *hook)
00566 {
00567   hook->next = usb_request_handler_hooks;
00568   usb_request_handler_hooks = hook;
00569 }
00570 
00571 
00572 unsigned int
00573 usb_get_current_configuration(void)
00574 {
00575   return usb_configuration_value;
00576 }
00577 
00578 void
00579 usb_setup_bulk_endpoint(unsigned char addr)
00580 {
00581   usb_arch_setup_bulk_endpoint(addr);
00582 }
00583 
00584 void
00585 usb_setup_interrupt_endpoint(unsigned char addr)
00586 {
00587   usb_arch_setup_interrupt_endpoint(addr);
00588 }
00589 
00590 void
00591 usb_disable_endpoint(uint8_t addr)
00592 {
00593   usb_arch_discard_all_buffers(addr);
00594   usb_arch_disable_endpoint(addr);
00595 }
00596 
00597 void
00598 usb_discard_all_buffers(uint8_t addr)
00599 {
00600   usb_arch_discard_all_buffers(addr);
00601 }
00602 
00603 void
00604 usb_halt_endpoint(uint8_t addr, int halt)
00605 {
00606   usb_arch_halt_endpoint(addr, halt);
00607 }
00608 
00609 int
00610 usb_send_pending(uint8_t addr)
00611 {
00612   return usb_arch_send_pending(addr);
00613 }
00614