📄 usb-handler.c
字号:
#include <AT91SAM7S64.h>#include <interrupt-utils.h>#include <usb-interrupt.h>#include <usb-proto.h>#include <usb-api.h>#include <stdio.h>#include <sys/process.h>#include <stdio.h>#include <descriptors.h>#include <string-descriptors.h>#define USB_PULLUP_PIN AT91C_PIO_PA16static unsigned short usb_device_status;static unsigned char usb_configuration_value;static struct process * user_process = NULL;static struct USBRequestHandlerHook *usb_request_handler_hooks = NULL;static const unsigned char zero_byte = 0;static const unsigned short zero_word = 0;static voidnotify_user(struct usb_user_msg* msg){ if (user_process) { process_post(user_process, PROCESS_EVENT_MSG, msg); }}voidusb_set_user_process(struct process *p){ user_process = p;}static voidget_device_descriptor(){ usb_send_ctrl_response((unsigned char*)&device_descriptor, sizeof(device_descriptor));}static voidget_string_descriptor(){ if (LOW_BYTE(usb_setup_buffer.wValue) == 0) { usb_send_ctrl_response((const unsigned char*)string_languages->lang_descr, string_languages->lang_descr->bLength); } else { unsigned char l; const struct usb_st_string_descriptor *descriptor; const struct usb_st_string_descriptor * const *table; const struct usb_st_string_language_map *map; if (LOW_BYTE(usb_setup_buffer.wValue) > string_languages->max_index) { usb_error_stall(); return; } l = string_languages->num_lang; map = string_languages->map; table = map->descriptors; /* Use first table if language not found */ while (l > 0) { if (map->lang_id == usb_setup_buffer.wIndex) { table = map->descriptors; break; } map++; l--; } printf("Lang id %04x = table %p\n", usb_setup_buffer.wIndex, (void*)table); descriptor = table[LOW_BYTE(usb_setup_buffer.wValue) - 1]; usb_send_ctrl_response((const unsigned char*)descriptor, descriptor->bLength); }}static voidget_configuration_descriptor(){ usb_send_ctrl_response((unsigned char*)configuration_head, configuration_head->wTotalLength);}static voidget_configuration(){ usb_send_ctrl_response((unsigned char*)&usb_configuration_value, sizeof(usb_configuration_value));}/* Returns true if the configuration value changed */static intset_configuration(){ if (usb_configuration_value != LOW_BYTE(usb_setup_buffer.wValue)) { usb_configuration_value = LOW_BYTE(usb_setup_buffer.wValue); if (usb_configuration_value > 0) { *AT91C_UDP_GLBSTATE |= AT91C_UDP_CONFG; } else { *AT91C_UDP_GLBSTATE &= ~AT91C_UDP_CONFG; } usb_send_ctrl_status(); return 1; } else { usb_send_ctrl_status(); return 0; }}static voidget_device_status(){ puts("get_device_status"); usb_send_ctrl_response((const unsigned char*)&usb_device_status, sizeof(usb_device_status));}static voidget_endpoint_status(){ puts("get_endpoint_status"); if ((usb_setup_buffer.wIndex & 0x7f) == 0) { usb_send_ctrl_response((const unsigned char*)&zero_word, sizeof(zero_word)); } else { volatile USBEndpoint *ec; ec = usb_find_endpoint(usb_setup_buffer.wIndex); if (ec) { usb_send_ctrl_response((const unsigned char*)&ec->status, sizeof(ec->status)); } else { usb_error_stall(); } }}static voidget_interface_status(){ puts("get_interface_status"); usb_send_ctrl_response((const unsigned char*)&zero_word, sizeof(zero_word));}static voidget_interface(){ puts("get_interface"); if (usb_configuration_value == 0) usb_error_stall(); else { usb_send_ctrl_response(&zero_byte, sizeof(zero_byte)); }} static struct usb_user_msg config_msg = {USB_USER_MSG_TYPE_CONFIG};static struct usb_user_msg io_msg[3];static unsigned inthandle_standard_requests(){ switch(usb_setup_buffer.bmRequestType) { case 0x80: /* standard device IN requests */ switch(usb_setup_buffer.bRequest) { case GET_DESCRIPTOR: switch (HIGH_BYTE(usb_setup_buffer.wValue)) { case DEVICE: get_device_descriptor(); break; case CONFIGURATION: get_configuration_descriptor(); break; case STRING: get_string_descriptor(); break; default: /* Unknown descriptor */ return 0; } break; case GET_CONFIGURATION: get_configuration(); break; case GET_STATUS: get_device_status(); break; case GET_INTERFACE: get_interface(); break; default: return 0; } break; case 0x81: /* standard interface IN requests */ switch(usb_setup_buffer.bRequest) { case GET_STATUS: get_interface_status(); break;#ifdef HID_ENABLED case GET_DESCRIPTOR: switch (USB_setup_buffer.wValue.byte.high) { case REPORT: get_report_descriptor(); break; } break;#endif default: return 0; } break; case 0x82: /* standard endpoint IN requests */ switch(usb_setup_buffer.bRequest) { case GET_STATUS: get_endpoint_status(); break; default: return 0; } break; case 0x00: /* standard device OUT requests */ switch(usb_setup_buffer.bRequest) { case SET_ADDRESS: printf("Address: %d\n", LOW_BYTE(usb_setup_buffer.wValue)); usb_set_address(); usb_send_ctrl_status(); break;#if SETABLE_STRING_DESCRIPTORS > 0 case SET_DESCRIPTOR: if (usb_setup_buffer.wValue.byte.high == STRING) { set_string_descriptor(); } else { return 0; } break;#endif case SET_CONFIGURATION: if (set_configuration()) { config_msg.data.config = LOW_BYTE(usb_setup_buffer.wValue); notify_user(&config_msg); } break; default: return 0; } break; case 0x02: switch(usb_setup_buffer.bRequest) { case SET_FEATURE: case CLEAR_FEATURE: if (usb_setup_buffer.wValue == ENDPOINT_HALT_FEATURE) { volatile USBEndpoint *ep = usb_find_endpoint(usb_setup_buffer.wIndex); if (ep) { usb_halt_endpoint(ep->addr, usb_setup_buffer.bRequest== SET_FEATURE); usb_send_ctrl_status(); } else { usb_error_stall(); } } else { usb_error_stall(); } break; default: return 0; } break;#ifdef HID_ENABLED case 0xa1: /* class specific interface IN request*/ switch(USB_setup_buffer.bRequest) { case GET_HID_REPORT: puts("Get report\n"); send_ctrl_response((code u_int8_t*)&zero_byte, sizeof(zero_byte)); break; case GET_HID_IDLE: puts("Get idle\n"); send_ctrl_response((code u_int8_t*)&zero_byte, sizeof(zero_byte)); break; default: return 0; } break; case 0x21: /* class specific interface OUT request*/ switch(USB_setup_buffer.bRequest) { case SET_HID_IDLE: puts("Set idle\n"); send_ctrl_status(); break; default: return 0; } break;#endif default: return 0; } return 1;}static const struct USBRequestHandler standard_request_handler = { 0x00, 0x60, 0x00, 0x00, handle_standard_requests };static struct USBRequestHandlerHook standard_request_hook = { NULL, &standard_request_handler };PROCESS(usb_process, "USB process");PROCESS_THREAD(usb_process, ev , data){ PROCESS_BEGIN(); puts("USB process started"); while(1) { PROCESS_WAIT_EVENT(); if (ev == PROCESS_EVENT_EXIT) break; if (ev == PROCESS_EVENT_POLL) { if (usb_events & USB_EVENT_RESET) { printf("Reset\n"); usb_clear_events(USB_EVENT_RESET); } if (usb_events & USB_EVENT_EP(0)) { /* puts("Endpoint 0"); */ if (usb_endpoint_events[0] & USB_EP_EVENT_SETUP) { struct USBRequestHandlerHook *hook = usb_request_handler_hooks;#if 0 puts("Setup"); { unsigned int i; for (i = 0; i< 8; i++) printf(" %02x", ((unsigned char*)&usb_setup_buffer)[i]); putchar('\n'); }#endif while(hook) { const struct USBRequestHandler *handler = hook->handler; /* Check if the handler matches the request */ if (((handler->request_type ^ usb_setup_buffer.bmRequestType) & handler->request_type_mask) == 0 && ((handler->request ^ usb_setup_buffer.bRequest) & handler->request_mask) == 0) { if (handler->handler_func()) break; } hook = hook->next; } if (!hook) { /* No handler found */ usb_error_stall(); } usb_clear_ep_events(0, USB_EP_EVENT_SETUP); } usb_clear_events(USB_EVENT_EP(0)); } { unsigned int e; for (e = 1; e <= 3; e++) { if (usb_events & USB_EVENT_EP(e)) { if (usb_endpoint_events[e] & (USB_EP_EVENT_OUT|USB_EP_EVENT_IN)) { volatile USBEndpoint *ep = usb_find_endpoint(e); struct usb_user_msg *msg = &io_msg[e-1]; if (usb_endpoint_events[e] & USB_EP_EVENT_OUT) { msg->type = USB_USER_MSG_TYPE_EP_OUT(e); msg->data.length = ep->buf_len; } else { msg->type = USB_USER_MSG_TYPE_EP_IN(e); msg->data.length = ep->buf_size_mask + 1 - ep->buf_len; } notify_user(msg); usb_clear_ep_events(e, USB_EP_EVENT_OUT|USB_EP_EVENT_IN); usb_clear_events(USB_EVENT_EP(ep->addr)); } } } } } } PROCESS_END();}voidusb_setup(void){ /* Assume 96MHz PLL frequency */ *AT91C_CKGR_PLLR = ((*AT91C_CKGR_PLLR & ~AT91C_CKGR_USBDIV) | AT91C_CKGR_USBDIV_1); /* Enable 48MHz USB clock */ *AT91C_PMC_SCER = AT91C_PMC_UDP; /* Enable USB main clock */ *AT91C_PMC_PCER = (1 << AT91C_ID_UDP); /* Enable pullup */ *AT91C_PIOA_PER = USB_PULLUP_PIN; *AT91C_PIOA_OER = USB_PULLUP_PIN; *AT91C_PIOA_CODR = USB_PULLUP_PIN; usb_register_request_handler(&standard_request_hook); process_start(&usb_process, NULL); usb_handler_process = &usb_process; /* Enable usb_interrupt */ AT91C_AIC_SMR[AT91C_ID_UDP] = AT91C_AIC_SRCTYPE_INT_HIGH_LEVEL | 4; AT91C_AIC_SVR[AT91C_ID_UDP] = (unsigned long) usb_int; *AT91C_AIC_IECR = (1 << AT91C_ID_UDP); usb_init_endpoints();}voidusb_register_request_handler(struct USBRequestHandlerHook *hook){ struct USBRequestHandlerHook **prevp = &usb_request_handler_hooks; /* Find last hook */ while(*prevp) { prevp = &(*prevp)->next; } /* Add last */ *prevp = hook; hook->next = NULL;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -