6 #include "descriptors.h"
7 #include "string-descriptors.h"
12 #define PRINTF(...) printf(__VA_ARGS__)
18 struct USB_request_st usb_setup_buffer;
19 static USBBuffer ctrl_buffer;
24 #define STATUS_OUT_ID 4
25 #define STATUS_IN_ID 5
27 static uint16_t usb_device_status;
28 static uint8_t usb_configuration_value;
30 static struct USBRequestHandlerHook *usb_request_handler_hooks =
NULL;
32 static const unsigned char zero_byte = 0;
33 static const unsigned short zero_word = 0;
35 static unsigned char usb_flags = 0;
36 #define USB_FLAG_ADDRESS_PENDING 0x01
38 static struct process *global_user_event_pocess =
NULL;
39 static unsigned int global_user_events = 0;
42 usb_set_global_event_process(
struct process *p)
44 global_user_event_pocess = p;
47 usb_get_global_events(
void)
49 unsigned int e = global_user_events;
50 global_user_events = 0;
55 notify_user(
unsigned int e)
57 global_user_events |= e;
58 if(global_user_event_pocess) {
64 usb_send_ctrl_response(
const uint8_t * data,
unsigned int len)
66 if(ctrl_buffer.flags & USB_BUFFER_SUBMITTED)
68 if(len >= usb_setup_buffer.wLength) {
69 len = usb_setup_buffer.wLength;
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;
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);
82 static uint8_t error_stall = 0;
88 usb_arch_control_stall(0);
92 usb_send_ctrl_status()
94 if(ctrl_buffer.flags & USB_BUFFER_SUBMITTED)
96 ctrl_buffer.flags = USB_BUFFER_NOTIFY | USB_BUFFER_IN;
97 ctrl_buffer.next =
NULL;
98 ctrl_buffer.data =
NULL;
100 ctrl_buffer.id = STATUS_IN_ID;
101 usb_submit_xmit_buffer(0, &ctrl_buffer);
104 static usb_ctrl_data_callback data_callback =
NULL;
106 static uint8_t *ctrl_data =
NULL;
108 static unsigned int ctrl_data_len = 0;
111 usb_get_ctrl_data(uint8_t * data,
unsigned int length,
112 usb_ctrl_data_callback cb)
114 if(ctrl_buffer.flags & USB_BUFFER_SUBMITTED)
116 PRINTF(
"usb_get_ctrl_data: %d\n", length);
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);
131 usb_set_user_process(
struct process *p)
138 get_device_descriptor()
140 usb_send_ctrl_response((
unsigned char *)&device_descriptor,
141 sizeof(device_descriptor));
145 get_string_descriptor()
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);
152 const struct usb_st_string_descriptor *descriptor;
156 const struct usb_st_string_descriptor *
const *table;
158 const struct usb_st_string_language_map *map;
160 if(
LOW_BYTE(usb_setup_buffer.wValue) > string_languages->max_index) {
164 l = string_languages->num_lang;
165 map = string_languages->map;
166 table = map->descriptors;
168 if(map->lang_id == usb_setup_buffer.wIndex) {
169 table = map->descriptors;
175 PRINTF(
"Lang id %04x = table %p\n", usb_setup_buffer.wIndex,
177 descriptor = table[
LOW_BYTE(usb_setup_buffer.wValue) - 1];
178 usb_send_ctrl_response((
const unsigned char *)descriptor,
179 descriptor->bLength);
182 const struct usb_st_string_descriptor *descriptor;
184 descriptor = (
struct usb_st_string_descriptor *)
185 usb_class_get_string_descriptor(usb_setup_buffer.wIndex,
191 usb_send_ctrl_response((
const unsigned char *)descriptor,
192 descriptor->bLength);
197 get_configuration_descriptor()
199 usb_send_ctrl_response((
unsigned char *)configuration_head,
200 configuration_head->wTotalLength);
206 usb_send_ctrl_response((
unsigned char *)&usb_configuration_value,
207 sizeof(usb_configuration_value));
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();
221 usb_send_ctrl_status();
229 PRINTF(
"get_device_status\n");
230 usb_send_ctrl_response((
const unsigned char *)&usb_device_status,
231 sizeof(usb_device_status));
235 get_endpoint_status()
237 static uint16_t status;
239 PRINTF(
"get_endpoint_status\n");
240 if((usb_setup_buffer.wIndex & 0x7f) == 0) {
241 usb_send_ctrl_response((
const unsigned char *)&zero_word,
244 status = usb_arch_get_ep_status(usb_setup_buffer.wIndex);
245 usb_send_ctrl_response((uint8_t *) & status,
sizeof(status));
250 get_interface_status()
252 PRINTF(
"get_interface_status\n");
253 usb_send_ctrl_response((
const unsigned char *)&zero_word,
260 PRINTF(
"get_interface\n");
261 if(usb_configuration_value == 0)
264 usb_send_ctrl_response(&zero_byte,
sizeof(zero_byte));
270 handle_standard_requests()
272 switch (usb_setup_buffer.bmRequestType) {
274 switch (usb_setup_buffer.bRequest) {
276 switch (
HIGH_BYTE(usb_setup_buffer.wValue)) {
278 get_device_descriptor();
281 get_configuration_descriptor();
284 get_string_descriptor();
291 case GET_CONFIGURATION:
305 switch (usb_setup_buffer.bRequest) {
307 get_interface_status();
311 switch (USB_setup_buffer.wValue.byte.high) {
313 get_report_descriptor();
323 switch (usb_setup_buffer.bRequest) {
325 get_endpoint_status();
332 switch (usb_setup_buffer.bRequest) {
334 PRINTF(
"Address: %d\n",
LOW_BYTE(usb_setup_buffer.wValue));
335 usb_flags |= USB_FLAG_ADDRESS_PENDING;
338 usb_send_ctrl_status();
340 #if SETABLE_STRING_DESCRIPTORS > 0
342 if(usb_setup_buffer.wValue.byte.high == STRING) {
343 set_string_descriptor();
349 case SET_CONFIGURATION:
350 if(set_configuration()) {
352 config_msg.data.config =
LOW_BYTE(usb_setup_buffer.wValue);
353 notify_user(&config_msg);
362 switch (usb_setup_buffer.bRequest) {
365 usb_send_ctrl_status();
372 switch (usb_setup_buffer.bRequest) {
375 if(usb_setup_buffer.wValue == ENDPOINT_HALT_FEATURE) {
376 usb_arch_halt_endpoint(usb_setup_buffer.wIndex,
378 usb_send_ctrl_status();
389 switch (USB_setup_buffer.bRequest) {
391 PRINTF(
"Get report\n");
392 send_ctrl_response((code u_int8_t *) & zero_byte,
sizeof(zero_byte));
395 PRINTF(
"Get idle\n");
396 send_ctrl_response((code u_int8_t *) & zero_byte,
sizeof(zero_byte));
403 switch (USB_setup_buffer.bRequest) {
405 PRINTF(
"Set idle\n");
419 static const struct USBRequestHandler standard_request_handler = {
424 handle_standard_requests
427 static struct USBRequestHandlerHook standard_request_hook = {
429 &standard_request_handler
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);
449 PRINTF(
"USB process started\n");
452 if(ev == PROCESS_EVENT_EXIT)
454 if(ev == PROCESS_EVENT_POLL) {
455 unsigned int events = usb_arch_get_global_events();
458 if(events & USB_EVENT_RESET) {
460 usb_configuration_value = 0;
461 notify_user(USB_EVENT_RESET);
463 if(events & USB_EVENT_SUSPEND) {
464 notify_user(USB_EVENT_SUSPEND);
466 if(events & USB_EVENT_RESUME) {
467 notify_user(USB_EVENT_RESUME);
471 events = usb_get_ep_events(0);
473 if((events & USB_EP_EVENT_NOTIFICATION)
474 && !(ctrl_buffer.flags & USB_BUFFER_SUBMITTED)) {
476 if(ctrl_buffer.flags & USB_BUFFER_FAILED) {
479 PRINTF(
"Discarded\n");
481 }
else if(ctrl_buffer.flags & USB_BUFFER_SETUP) {
482 struct USBRequestHandlerHook *hook = usb_request_handler_hooks;
488 for(i = 0; i < 8; i++)
489 PRINTF(
" %02x", ((
unsigned char *)&usb_setup_buffer)[i]);
494 const struct USBRequestHandler *handler = hook->handler;
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())
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);
521 if(ctrl_buffer.id == IN_ID) {
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");
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;
541 }
else if(ctrl_buffer.id == OUT_ID) {
544 data_callback(ctrl_data, ctrl_data_len - ctrl_buffer.left);
546 usb_send_ctrl_status();
563 usb_arch_set_global_event_process(&usb_process);
564 usb_set_ep_event_process(0, &usb_process);
566 usb_register_request_handler(&standard_request_hook);
570 usb_register_request_handler(
struct USBRequestHandlerHook *hook)
572 struct USBRequestHandlerHook **prevp = &usb_request_handler_hooks;
575 prevp = &(*prevp)->next;
583 usb_prepend_request_handler(
struct USBRequestHandlerHook *hook)
585 hook->next = usb_request_handler_hooks;
586 usb_request_handler_hooks = hook;
591 usb_get_current_configuration(
void)
593 return usb_configuration_value;
597 usb_setup_bulk_endpoint(
unsigned char addr)
599 usb_arch_setup_bulk_endpoint(addr);
603 usb_setup_interrupt_endpoint(
unsigned char addr)
605 usb_arch_setup_interrupt_endpoint(addr);
609 usb_disable_endpoint(uint8_t addr)
611 usb_arch_discard_all_buffers(addr);
612 usb_arch_disable_endpoint(addr);
616 usb_discard_all_buffers(uint8_t addr)
618 usb_arch_discard_all_buffers(addr);
624 usb_arch_halt_endpoint(addr, halt);
628 usb_send_pending(uint8_t addr)
630 return usb_arch_send_pending(addr);
void process_poll(struct process *p)
Request a process to be polled.
#define PROCESS_BEGIN()
Define the beginning of a process.
#define NULL
The null pointer.
#define LOW_BYTE(n)
Returns the low byte of the 16-bit value n as an uint8_t.
void usb_halt_endpoint(U8 ep_num)
usb_halt_endpoint.
#define PROCESS_THREAD(name, ev, data)
Define the body of a process.
#define PROCESS_END()
Define the end of a process.
#define HIGH_BYTE(n)
Returns the high byte of the 16-bit value n as an uint8_t.
#define PROCESS_WAIT_EVENT()
Wait for an event to be posted to the process.
#define PROCESS(name, strname)
Declare a process.
void process_start(struct process *p, process_data_t data)
Start a process.
#define CLEAR_FEATURE
see FEATURES below
Header file for the Contiki process interface.
#define SET_FEATURE
see FEATURES below