From 0e55eb09479c2247b920d8b1db44988f8e621701 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20R=C3=A9tornaz?= Date: Tue, 7 Aug 2012 11:24:59 +0200 Subject: [PATCH] cc2531: Copy arm usb framework See Pull Request #18 --- cpu/cc253x/usb/Makefile.usb | 60 ++ cpu/cc253x/usb/cdc-acm-descriptors.c | 126 ++++ cpu/cc253x/usb/common/cdc-acm/cdc-acm.c | 111 ++++ cpu/cc253x/usb/common/cdc-acm/cdc-acm.h | 7 + cpu/cc253x/usb/common/cdc-acm/cdc.h | 203 +++++++ cpu/cc253x/usb/common/descriptors.h | 10 + cpu/cc253x/usb/common/string-descriptors.h | 20 + cpu/cc253x/usb/common/usb-api.h | 127 +++++ cpu/cc253x/usb/common/usb-arch.h | 77 +++ cpu/cc253x/usb/common/usb-core.c | 632 +++++++++++++++++++++ cpu/cc253x/usb/common/usb-core.h | 19 + cpu/cc253x/usb/common/usb.h | 185 ++++++ 12 files changed, 1577 insertions(+) create mode 100644 cpu/cc253x/usb/Makefile.usb create mode 100644 cpu/cc253x/usb/cdc-acm-descriptors.c create mode 100644 cpu/cc253x/usb/common/cdc-acm/cdc-acm.c create mode 100644 cpu/cc253x/usb/common/cdc-acm/cdc-acm.h create mode 100644 cpu/cc253x/usb/common/cdc-acm/cdc.h create mode 100644 cpu/cc253x/usb/common/descriptors.h create mode 100644 cpu/cc253x/usb/common/string-descriptors.h create mode 100644 cpu/cc253x/usb/common/usb-api.h create mode 100644 cpu/cc253x/usb/common/usb-arch.h create mode 100644 cpu/cc253x/usb/common/usb-core.c create mode 100644 cpu/cc253x/usb/common/usb-core.h create mode 100644 cpu/cc253x/usb/common/usb.h diff --git a/cpu/cc253x/usb/Makefile.usb b/cpu/cc253x/usb/Makefile.usb new file mode 100644 index 000000000..3286ca365 --- /dev/null +++ b/cpu/cc253x/usb/Makefile.usb @@ -0,0 +1,60 @@ +### Put generated sources in a separate directory +BUILTSRCDIR = src_$(TARGET) +ifeq (${wildcard $(BUILTSRCDIR)},) + DUMMY := ${shell mkdir $(BUILTSRCDIR)} +endif + +STRUCTGEN = structgen + +PROJECTDIRS += $(BUILTSRCDIR) + +USB_STRING_DESCRIPTORS ?= $(CONTIKI_CPU_ARM)/common/usb/cdc-acm/string-descriptors.xml + +XMLDIRS= + +USB = usb-arch.c usb-core.c + +ifdef USB_CDC_ACM_CLASS +CONTIKI_CPU_DIRS += ../common/usb/cdc-acm +USB += cdc-acm.c cdc-acm-descriptors.c cdc-acm-string-descriptors.c +XMLDIRS += $(CONTIKI_CPU_ARM)/common/usb/cdc-acm/ +endif + +ifdef USB_CDC_ETH_CLASS +CONTIKI_CPU_DIRS += ../common/usb/cdc-eth +USB += cdc-eth.c cdc-eth-descriptors.c cdc-eth-string-descriptors.c dhcps.c +XMLDIRS += $(CONTIKI_CPU_ARM)/common/usb/cdc-eth/ +endif + +ifdef USB_MASS_STORAGE_CLASS +CONTIKI_CPU_DIRS += ../common/usb/msc +USB += usb-msc-bulk.c usb-rbc.c msc-descriptors-consts.c msc-descriptors.c +XMLDIRS += $(CONTIKI_CPU_ARM)/common/usb/msc +endif + +ifdef USB_MSC_QIC157 +CONTIKI_CPU_DIRS += ../common/usb/msc +USB += usb-msc-bulk.c usb-qic157.c msc-qic157-descriptors.c msc-qic157-string-descriptors.c +XMLDIRS += $(CONTIKI_CPU_ARM)/common/usb/msc +endif + +ifdef USB_MSC_STREAMING +CONTIKI_CPU_DIRS += ../common/usb/msc +USB += usb-msc-bulk.c usb-streaming.c msc-scsi-streaming-descriptors-consts.c msc-scsi-streaming-descriptors.c +XMLDIRS += $(CONTIKI_CPU_ARM)/common/usb/msc +endif + +ifdef USB_MTP_CLASS +CONTIKI_CPU_DIRS += ../common/usb/mtp +USB += usb-mtp.c mtp-descriptors-consts.c mtp-descriptors.c +STRUCTGENDIRS += $(CONTIKI_CPU_ARM)/common/usb/mtp +endif + +vpath %.xml $(XMLDIRS) +vpath %.gen.c $(STRUCTGENDIRS) + +%.c: %.xml + $(XSLTPROC) $(CONTIKI_CPU_ARM)/common/usb/string-descriptors.xslt $^ >$(BUILTSRCDIR)/$@ + +%-consts.c: %.gen.c + $(CPP) -I$(CFLAGS) $< | $(STRUCTGEN) --output $(BUILTSRCDIR)/$*-consts.c \ No newline at end of file diff --git a/cpu/cc253x/usb/cdc-acm-descriptors.c b/cpu/cc253x/usb/cdc-acm-descriptors.c new file mode 100644 index 000000000..49246c96c --- /dev/null +++ b/cpu/cc253x/usb/cdc-acm-descriptors.c @@ -0,0 +1,126 @@ +#include "descriptors.h" +#include "contiki-conf.h" +#include "cdc.h" +#include "usb-arch.h" + +const struct usb_st_device_descriptor device_descriptor = + { + sizeof(struct usb_st_device_descriptor), + DEVICE, + 0x0210, + CDC, + 0, + 0, + CTRL_EP_SIZE, + 0xffff, + 0xffff, + 0x0030, + 2, + 1, + 3, + 1 + }; + +const struct configuration_st { + struct usb_st_configuration_descriptor configuration; + struct usb_st_interface_descriptor comm; + struct usb_cdc_header_func_descriptor header; + struct usb_cdc_abstract_ctrl_mgmnt_func_descriptor abstract_ctrl; + struct usb_cdc_union_func_descriptor union_descr; + struct usb_cdc_call_mgmnt_func_descriptor call_mgmt; +#if 1 + struct usb_st_endpoint_descriptor ep_notification; +#endif + struct usb_st_interface_descriptor data; + struct usb_st_endpoint_descriptor ep_in; + struct usb_st_endpoint_descriptor ep_out; +} BYTE_ALIGNED configuration_block = + { + /* Configuration */ + { + sizeof(configuration_block.configuration), + CONFIGURATION, + sizeof(configuration_block), + 2, + 1, + 0, + 0x80, + 50 + }, + { + sizeof(configuration_block.comm), + INTERFACE, + 0, + 0, + 1, + CDC, + ABSTRACT_CONTROL_MODEL, + V_25TER_PROTOCOL, + 0 + }, + { + sizeof(configuration_block.header), + CS_INTERFACE, + CDC_FUNC_DESCR_HEADER, + 0x0110 + }, + { + sizeof(configuration_block.abstract_ctrl), + CS_INTERFACE, + CDC_FUNC_DESCR_ABSTRACT_CTRL_MGMNT, + 0 + }, + { + sizeof(configuration_block.union_descr), + CS_INTERFACE, + CDC_FUNC_DESCR_UNION, + 0, /* Master */ + {1} /* Slave */ + }, + { + sizeof(configuration_block.call_mgmt), + CS_INTERFACE, + CDC_FUNC_DESCR_CALL_MGMNT, + 0x02, + 1 /* data interface */ + }, + { + sizeof(configuration_block.ep_notification), + ENDPOINT, + 0x83, + 0x03, + USB_EP3_SIZE, + 100 + }, + { + sizeof(configuration_block.data), + INTERFACE, + 1, + 0, + 2, + CDC_DATA, + 0, + TRANSPARENT_PROTOCOL, + 0 + }, + { + sizeof(configuration_block.ep_in), + ENDPOINT, + 0x81, + 0x02, + USB_EP1_SIZE, + 0 + }, + { + sizeof(configuration_block.ep_out), + ENDPOINT, + 0x02, + 0x02, + USB_EP2_SIZE, + 0 + } + + }; + +const struct usb_st_configuration_descriptor const *configuration_head = +(struct usb_st_configuration_descriptor const*)&configuration_block; diff --git a/cpu/cc253x/usb/common/cdc-acm/cdc-acm.c b/cpu/cc253x/usb/common/cdc-acm/cdc-acm.c new file mode 100644 index 000000000..f48d49663 --- /dev/null +++ b/cpu/cc253x/usb/common/cdc-acm/cdc-acm.c @@ -0,0 +1,111 @@ +#include "cdc-acm.h" +#include "cdc.h" +#include "usb-api.h" +#include "usb-core.h" + +#include + +static uint8_t usb_ctrl_data_buffer[32]; + +static void +encapsulated_command(uint8_t *data, unsigned int length) +{ + printf("Got CDC command: length %d\n", length); + usb_send_ctrl_status(); +} +static void +set_line_encoding(uint8_t *data, unsigned int length) +{ + if (length == 7) { + static const char parity_char[] = {'N', 'O', 'E', 'M', 'S'}; + static const char *stop_bits_str[] = {"1","1.5","2"}; + const struct usb_cdc_line_coding *coding = + (const struct usb_cdc_line_coding *)usb_ctrl_data_buffer; + char parity = ((coding->bParityType > 4) + ? '?' : parity_char[coding->bParityType]); + const char *stop_bits = ((coding->bCharFormat > 2) + ? "?" : stop_bits_str[coding->bCharFormat]); + printf("Got CDC line coding: %ld/%d/%c/%s\n", + coding->dwDTERate, coding->bDataBits, parity, stop_bits); + usb_send_ctrl_status(); + } else { + usb_error_stall(); + } +} + +static unsigned int +handle_cdc_acm_requests() +{ + printf("CDC request %02x %02x\n", usb_setup_buffer.bmRequestType, usb_setup_buffer.bRequest); + switch(usb_setup_buffer.bmRequestType) { + case 0x21: /* CDC interface OUT requests */ + /* Check if it's the right interface */ + if (usb_setup_buffer.wIndex != 0) return 0; + switch(usb_setup_buffer.bRequest) { + case SET_CONTROL_LINE_STATE: + if (usb_setup_buffer.wValue & 0x02) { + puts("Carrier on"); + } else { + puts("Carrier off"); + } + if (usb_setup_buffer.wValue & 0x01) { + puts("DTE on"); + } else { + puts("DTE off"); + } + usb_send_ctrl_status(); + return 1; + + case SEND_ENCAPSULATED_COMMAND: + { + unsigned int len = usb_setup_buffer.wLength; + if (len > sizeof(usb_ctrl_data_buffer)) + len = sizeof(usb_ctrl_data_buffer); + usb_get_ctrl_data(usb_ctrl_data_buffer, len, + encapsulated_command); + } + + return 1; + + + case SET_LINE_CODING: + { + unsigned int len = usb_setup_buffer.wLength; + if (len > sizeof(usb_ctrl_data_buffer)) + len = sizeof(usb_ctrl_data_buffer); + usb_get_ctrl_data(usb_ctrl_data_buffer, len, + set_line_encoding); + } + return 1; + } + break; + case 0xa1: /* CDC interface IN requests */ + if (usb_setup_buffer.wIndex != 0) return 0; + switch(usb_setup_buffer.bRequest) { + case GET_ENCAPSULATED_RESPONSE: + printf("CDC response"); + usb_send_ctrl_status(); + return 1; + } + } + return 0; +} + +static const struct USBRequestHandler cdc_acm_request_handler = + { + 0x21, 0x7f, + 0x00, 0x00, + handle_cdc_acm_requests + }; + +static struct USBRequestHandlerHook cdc_acm_request_hook = + { + NULL, + &cdc_acm_request_handler + }; + +void +usb_cdc_acm_setup() +{ + usb_register_request_handler(&cdc_acm_request_hook); +} diff --git a/cpu/cc253x/usb/common/cdc-acm/cdc-acm.h b/cpu/cc253x/usb/common/cdc-acm/cdc-acm.h new file mode 100644 index 000000000..4a85dc208 --- /dev/null +++ b/cpu/cc253x/usb/common/cdc-acm/cdc-acm.h @@ -0,0 +1,7 @@ +#ifndef __CDC_ACM_H__UFV6K50827__ +#define __CDC_ACM_H__UFV6K50827__ + +void +usb_cdc_acm_setup(); + +#endif /* __CDC_ACM_H__UFV6K50827__ */ diff --git a/cpu/cc253x/usb/common/cdc-acm/cdc.h b/cpu/cc253x/usb/common/cdc-acm/cdc.h new file mode 100644 index 000000000..d4bd987fc --- /dev/null +++ b/cpu/cc253x/usb/common/cdc-acm/cdc.h @@ -0,0 +1,203 @@ +#ifndef __CDC_H__K1Q26ESJOC__ +#define __CDC_H__K1Q26ESJOC__ +#include "usb.h" +/* Communication Class */ +/* Class code */ +#define CDC 0x02 + +/* Interface subclass codes */ +#define CDC_RESERVED 0x00 +#define DIRECT_LINE_CONTROL_MODEL 0x01 +#define ABSTRACT_CONTROL_MODEL 0x02 +#define TELEPHONE_CONTROL_MODEL 0x03 +#define MULTI_CHANNEL_CONTROL_MODEL 0x04 +#define CAPI_CONTROL_MODEL 0x05 +#define ETHERNET_NETWORKING_CONTROL_MODEL 0x06 +#define ATM_NETWORKING_CONTROL_MODEL 0x07 + +/* Protocols */ +#define V_25TER_PROTOCOL 0x01 + +/* Requests */ +#define SEND_ENCAPSULATED_COMMAND 0x00 +#define GET_ENCAPSULATED_RESPONSE 0x01 +#define SET_COMM_FEATURE 0x02 +#define GET_COMM_FEATURE 0x03 +#define CLEAR_COMM_FEATURE 0x04 + +#define SET_AUX_LINE_STATE 0x10 +#define SET_HOOK_STATE 0x11 +#define PULSE_SETUP 0x12 +#define SEND_PULSE 0x13 +#define SET_PULSE_TIME 0x14 +#define RING_AUX_JACK 0x15 + +#define SET_LINE_CODING 0x20 +#define GET_LINE_CODING 0x21 +#define SET_CONTROL_LINE_STATE 0x22 +#define SEND_BREAK 0x23 + +#define SET_RINGER_PARMS 0x30 +#define GET_RINGER_PARMS 0x31 +#define SET_OPERATION_PARMS 0x32 +#define GET_OPERATION_PARMS 0x33 +#define SET_LINE_PARMS 0x34 +#define GET_LINE_PARMS 0x35 +#define DIAL_DIGITS 0x36 + +#define SET_UNIT_PARAMETER 0x37 +#define GET_UNIT_PARAMETER 0x38 +#define CLEAR_UNIT_PARAMETER 0x39 + +#define GET_PROFILE 0x3a + +#define SET_ETHERNET_MULTICAST_FILTERS 0x40 +#define GET_ETHERNET_MULTICAST_FILTERS 0x41 +#define GET_ETHERNET_POWER_MANAGEMENT_PATTERN_FILTER 0x42 +#define SET_ETHERNET_POWER_MANAGEMENT_PATTERN_FILTER 0x43 +#define GET_ETHERNET_STATISTIC 0x44 + +#define SET_ATM_D ATA_FORMAT 0x50 +#define GET_ATM_DEVICE_STATISTICS 0x51 +#define SET_ATM_DEFAULT_VC 0x52 +#define GET_ATM_VC_STATISTICS 0x53 + + +/* Notifications */ +#define NETWORK_CONNECTION 0x00 +#define RESPONSE_AVAILABLE 0x01 + +#define AUX_JACK_HOOK_STATE 0x08 +#define RING_DETECT 0x09 + +#define SERIAL_STATE 0x20 + +#define CALL_STATE_CHANGE 0x28 +#define LINE_STATE_CHANGE 0x29 +#define CONNECTION_SPEED_CHANGE 0x2a + +/* Data interface */ + +/* Class code */ +#define CDC_DATA 0x0a + +/* Protocols */ +#define I_430_PROTOCOL 0x30 +#define ISO_IEC_3_1993_PROTOCOL 0x31 +#define TRANSPARENT_PROTOCOL 0x32 +#define Q_921M_PROTOCOL 0x50 +#define Q_921_PROTOCOL 0x51 +#define Q_921TM_PROTOCOL 0x52 +#define V_42BIS_PROTOCOL 0x90 +#define Q_931_PROTOCOL 0x91 +#define V_120_PROTOCOL 0x93 +#define CDC_PROTOCOL 0xfe + +/* Descriptor subtypes */ + +#define CDC_FUNC_DESCR_HEADER 0x00 +#define CDC_FUNC_DESCR_CALL_MGMNT 0x01 +#define CDC_FUNC_DESCR_ABSTRACT_CTRL_MGMNT 0x02 +#define CDC_FUNC_DESCR_DIRECT_LINE_MGMNT 0x03 +#define CDC_FUNC_DESCR_RINGER_MGMNT 0x04 +#define CDC_FUNC_DESCR_TEL_STATE 0x05 +#define CDC_FUNC_DESCR_UNION 0x06 +#define CDC_FUNC_DESCR_COUNTRY 0x07 +#define CDC_FUNC_DESCR_TEL_MODE 0x08 +#define CDC_FUNC_DESCR_USB_TERM 0x09 +#define CDC_FUNC_DESCR_NET_TERM 0x0a +#define CDC_FUNC_DESCR_PROTOCOL_UNIT 0x0b +#define CDC_FUNC_DESCR_EXTENSION_UNIT 0x0c +#define CDC_FUNC_DESCR_MULTICH_MGMNT 0x0d +#define CDC_FUNC_DESCR_CAPI_MGMNT 0x0e +#define CDC_FUNC_DESCR_ETHERNET 0x0f +#define CDC_FUNC_DESCR_ATM 0x10 + + + +struct usb_cdc_header_func_descriptor { + Uchar bLength; /* Size of this descriptor in bytes */ + Uchar bDescriptorType; /* CS_INTERFACE descriptor type */ + Uchar bDescriptorSubtype; /* CDC_FUNC_DESCR_HEADER subtype */ + Uint16 bcdCDC; /* Revision of class specification */ +} BYTE_ALIGNED; + +struct usb_cdc_call_mgmnt_func_descriptor { + Uchar bLength; /* Size of this descriptor in bytes */ + Uchar bDescriptorType; /* CS_INTERFACE descriptor type */ + Uchar bDescriptorSubtype; /* CDC_FUNC_DESCR_CALL_MGMNT subtype */ + Uchar bmCapabilities; /* Capabilities */ + Uchar bDataInterface; /* Management data interface */ +} BYTE_ALIGNED; + +struct usb_cdc_abstract_ctrl_mgmnt_func_descriptor { + Uchar bLength; /* Size of this descriptor in bytes */ + Uchar bDescriptorType; /* CS_INTERFACE descriptor type */ + Uchar bDescriptorSubtype; /* CDC_FUNC_DESCR_ABSTRACT_CTRL_MGMNT subtype */ + Uchar bmCapabilities; /* Capabilities */ +} BYTE_ALIGNED; + +struct usb_cdc_direct_line_mgmnt_func_descriptor { + Uchar bLength; /* Size of this descriptor in bytes */ + Uchar bDescriptorType; /* CS_INTERFACE descriptor type */ + Uchar bDescriptorSubtype; /* CDC_FUNC_DESCR_DIRECT_LINE_MGMNT subtype */ + Uchar bmCapabilities; /* Capabilities */ +} BYTE_ALIGNED; + +struct usb_cdc_ringer_mgmnt_func_descriptor { + Uchar bLength; /* Size of this descriptor in bytes */ + Uchar bDescriptorType; /* CS_INTERFACE descriptor type */ + Uchar bDescriptorSubtype; /* CDC_FUNC_DESCR_RINGER_MGMNT subtype */ + Uchar bRingerVolSteps; /* Ringer volume steps */ + Uchar bNumRingerPatterns; /* Number of ringer patterns supported */ +} BYTE_ALIGNED; + +struct usb_cdc_tel_mode_func_descriptor { + Uchar bLength; /* Size of this descriptor in bytes */ + Uchar bDescriptorType; /* CS_INTERFACE descriptor type */ + Uchar bDescriptorSubtype; /* CDC_FUNC_DESCR_TEL_MODE subtype */ + Uchar bmCapabilities; /* Capabilities */ +} BYTE_ALIGNED; + +struct usb_cdc_tel_state_func_descriptor { + Uchar bLength; /* Size of this descriptor in bytes */ + Uchar bDescriptorType; /* CS_INTERFACE descriptor type */ + Uchar bDescriptorSubtype; /* CDC_FUNC_DESCR_TEL_STATE subtype */ + Uchar bmCapabilities; /* Capabilities */ +} BYTE_ALIGNED; + +struct usb_cdc_union_func_descriptor { + Uchar bLength; /* Size of this descriptor in bytes */ + Uchar bDescriptorType; /* CS_INTERFACE descriptor type */ + Uchar bDescriptorSubtype; /* CDC_FUNC_DESCR_UNION subtype */ + Uchar bMasterInterface; /* Master interface for union */ + Uchar bSlaveInterface[1]; /* Slave interfaces in union */ +} BYTE_ALIGNED; + +struct usb_cdc_country_func_descriptor { + Uchar bLength; /* Size of this descriptor in bytes */ + Uchar bDescriptorType; /* CS_INTERFACE descriptor type */ + Uchar bDescriptorSubtype; /* CDC_FUNC_DESCR_COUNTRY subtype */ + Uchar iCountryCodeRelDate; /* Release date for country codes */ + Uint16 wCountryCode[1]; /* Country codes */ +} BYTE_ALIGNED; + +struct usb_cdc_ethernet_func_descriptor { + Uchar bLength; /* Size of this descriptor in bytes */ + Uchar bDescriptorType; /* CS_INTERFACE descriptor type */ + Uchar bDescriptorSubtype; /* CDC_FUNC_DESCR_ETHERNET subtype */ + Uchar iMACAddress; /* MAC address string descriptor */ + Uint32 bmEthernetStatistics; /* Supported statistics */ + Uint16 wMaxSegmentSize; + Uint16 wNumberMCFilters; /* Number of multicast filters */ + Uchar bNumberPowerFilters; /* Number of wake-up pattern filters */ +} BYTE_ALIGNED; + +struct usb_cdc_line_coding { + Uint32 dwDTERate; + Uchar bCharFormat; + Uchar bParityType; + Uchar bDataBits; +} BYTE_ALIGNED; + +#endif /* __CDC_H__K1Q26ESJOC__ */ diff --git a/cpu/cc253x/usb/common/descriptors.h b/cpu/cc253x/usb/common/descriptors.h new file mode 100644 index 000000000..30808f744 --- /dev/null +++ b/cpu/cc253x/usb/common/descriptors.h @@ -0,0 +1,10 @@ +#ifndef __DESCRIPTORS_H__RPFUB8O7OV__ +#define __DESCRIPTORS_H__RPFUB8O7OV__ + +#ifndef STRUCTGEN +#include "usb.h" +#endif + +extern const struct usb_st_device_descriptor device_descriptor; +extern const struct usb_st_configuration_descriptor const *configuration_head; +#endif /* __DESCRIPTORS_H__RPFUB8O7OV__ */ diff --git a/cpu/cc253x/usb/common/string-descriptors.h b/cpu/cc253x/usb/common/string-descriptors.h new file mode 100644 index 000000000..934d835b7 --- /dev/null +++ b/cpu/cc253x/usb/common/string-descriptors.h @@ -0,0 +1,20 @@ +#ifndef STRUCTGEN +#include "usb.h" +#endif +#include + +struct usb_st_string_language_map { + uint16_t lang_id; + const struct usb_st_string_descriptor *const *descriptors; +}; + +struct usb_st_string_languages { + uint8_t num_lang; + uint8_t max_index; + const struct usb_st_language_descriptor *lang_descr; + const struct usb_st_string_language_map map[1]; +}; + +extern const struct usb_st_string_languages *const string_languages; + +const uint8_t *usb_class_get_string_descriptor(uint16_t lang, uint8_t index); diff --git a/cpu/cc253x/usb/common/usb-api.h b/cpu/cc253x/usb/common/usb-api.h new file mode 100644 index 000000000..ac63a2d84 --- /dev/null +++ b/cpu/cc253x/usb/common/usb-api.h @@ -0,0 +1,127 @@ +#ifndef __USB_API_H__SYN81IFYBN__ +#define __USB_API_H__SYN81IFYBN__ + +#include "sys/process.h" + +typedef struct _USBBuffer USBBuffer; + +struct _USBBuffer { + USBBuffer *next; /* Pointer to next buffer in chain */ + uint8_t *data; /* Where to read/write data next */ + uint16_t left; /* Remaining length of buffer. */ + uint16_t flags; + uint32_t id; /* User data */ +}; + +/* Buffer owned by the USB code, cleared when done */ +#define USB_BUFFER_SUBMITTED 0x01 + +/* Write a short packet at end of buffer or release buffer when a + short packet is received. */ +#define USB_BUFFER_SHORT_END 0x02 + +/* Release buffer as soon as any received data has been written in it. */ +#define USB_BUFFER_PACKET_END 0x04 + +/* Notify the user when the buffer is released */ +#define USB_BUFFER_NOTIFY 0x08 + +/* Packet should be sent to host. */ +#define USB_BUFFER_IN 0x40 + +/* Used for receiving SETUP packets. If a SETUP packet is received and + the next buffers doesn't have this flag set, they will be skipped + until one is found. The associated buffer must be at least 8 bytes */ +#define USB_BUFFER_SETUP 0x20 + +/* HALT the endpoint at this point. Only valid for bulk and interrupt + endpoints */ +#define USB_BUFFER_HALT 0x100 + +/* Flags set by system */ + +/* The last packet written to this buffer was short. */ +#define USB_BUFFER_SHORT_PACKET 0x10 + +/* The operation associated with this buffer failed. I.e. it was discarded since it didn't match the received SETUP packet. */ +#define USB_BUFFER_FAILED 0x80 + +/* Architecture specific flags */ +#define USB_BUFFER_ARCH_FLAG_1 0x1000 +#define USB_BUFFER_ARCH_FLAG_2 0x2000 +#define USB_BUFFER_ARCH_FLAG_3 0x4000 +#define USB_BUFFER_ARCH_FLAG_4 0x8000 + +void usb_setup(void); + + +/* Read only */ +struct USBRequestHandler { + uint8_t request_type; + uint8_t request_type_mask; + uint8_t request; + uint8_t request_mask; + /* Returns true if it handled the request, if false let another handler try */ + unsigned int (*handler_func) (); +}; + +/* Must be writeable */ +struct USBRequestHandlerHook { + struct USBRequestHandlerHook *next; + const struct USBRequestHandler *const handler; +}; + +void usb_register_request_handler(struct USBRequestHandlerHook *hook); + +void usb_prepend_request_handler(struct USBRequestHandlerHook *hook); + +void usb_setup_bulk_endpoint(uint8_t addr); + +void usb_setup_interrupt_endpoint(uint8_t addr); + +/* Submit a chain of buffers to be filled with received data. Last + buffer must have next set to NULL. */ +void usb_submit_recv_buffer(uint8_t ep_addr, USBBuffer * buffer); + +/* Submit a chain of buffers to be sent. Last buffer must have next + set to NULL. When submitting packets to receive or send data in on + a control enpoint, all packets in the data stage must be submitted + at the same time. */ +void usb_submit_xmit_buffer(uint8_t ep_addr, USBBuffer * buffer); + +/* Return true if not all data has been sent to the host */ +int usb_send_pending(uint8_t ep_addr); + +/* Release all buffers submitted to the endpoint and discard any + buffered data. */ +void usb_discard_all_buffers(uint8_t ep_addr); + +void usb_disable_endpoint(uint8_t addr); + +/* Set or remove a HALT condition on an endpoint */ +void usb_halt_endpoint(uint8_t addr, int halt); + +/* Select what process should be polled when buffers with the + USB_BUFFER_NOTIFY flag set is released from the endpoint */ +void usb_set_ep_event_process(uint8_t addr, struct process *p); + +/* Select what process should be polled when a global event occurs */ +void usb_set_global_event_process(struct process *p); + +/* Global events */ +#define USB_EVENT_CONFIG 0x01 +#define USB_EVENT_SUSPEND 0x02 +#define USB_EVENT_RESUME 0x04 +#define USB_EVENT_RESET 0x08 + +/* Returns global events that has occured since last time this + function was called */ +unsigned int usb_get_global_events(void); + + +#define USB_EP_EVENT_NOTIFICATION 0x01 +unsigned int usb_get_ep_events(uint8_t addr); + +unsigned int usb_get_current_configuration(void); + +#endif /* __USB_API_H__SYN81IFYBN__ */ diff --git a/cpu/cc253x/usb/common/usb-arch.h b/cpu/cc253x/usb/common/usb-arch.h new file mode 100644 index 000000000..37f234ac2 --- /dev/null +++ b/cpu/cc253x/usb/common/usb-arch.h @@ -0,0 +1,77 @@ +#ifndef __USB_ARCH_H__0Z52ZDP0H6__ +#define __USB_ARCH_H__0Z52ZDP0H6__ + +#include "contiki-conf.h" +#include "usb-api.h" + + +/* Includes control endpoint 0 */ +#ifndef USB_MAX_ENDPOINTS +#define USB_MAX_ENDPOINTS 4 +#endif + +#ifndef CTRL_EP_SIZE +#define CTRL_EP_SIZE 8 +#endif + +#ifndef USB_EP1_SIZE +#define USB_EP1_SIZE 8 +#endif +#ifndef USB_EP2_SIZE +#define USB_EP2_SIZE 8 +#endif +#ifndef USB_EP3_SIZE +#define USB_EP3_SIZE 8 +#endif +#ifndef USB_EP4_SIZE +#define USB_EP4_SIZE 0 +#endif +#ifndef USB_EP5_SIZE +#define USB_EP5_SIZE 0 +#endif +#ifndef USB_EP6_SIZE +#define USB_EP6_SIZE 0 +#endif +#ifndef USB_EP7_SIZE +#define USB_EP7_SIZE 0 +#endif + + +#ifndef MAX_CTRL_DATA +#define MAX_CTRL_DATA 128 +#endif + +void usb_arch_setup(void); + +void usb_arch_setup_control_endpoint(uint8_t addr); + +void usb_arch_setup_bulk_endpoint(uint8_t addr); + +void usb_arch_setup_interrupt_endpoint(uint8_t addr); + +void usb_arch_disable_endpoint(uint8_t addr); + +void usb_arch_discard_all_buffers(uint8_t addr); + +/* Stall a control endpoint. The stall will be cleared when the next + * SETUP token arrives. */ +void usb_arch_control_stall(uint8_t addr); + +/* Set or remove a HALT condition on an endpoint */ +void usb_arch_halt_endpoint(uint8_t addr, int halt); + +void usb_arch_set_configuration(uint8_t usb_configuration_value); + +uint16_t usb_arch_get_ep_status(uint8_t addr); + +void usb_arch_set_address(uint8_t addr); + +/* Select what process should be polled when a global event occurs. Intended for the protocol handler. Applications should use usb_set_global_event_process */ +void usb_arch_set_global_event_process(struct process *p); + +unsigned int usb_arch_get_global_events(void); + +/* Return true if not all data has been sent to the host */ +int usb_arch_send_pending(uint8_t ep_addr); + +#endif /* __USB_ARCH_H__0Z52ZDP0H6__ */ diff --git a/cpu/cc253x/usb/common/usb-core.c b/cpu/cc253x/usb/common/usb-core.c new file mode 100644 index 000000000..22d09272c --- /dev/null +++ b/cpu/cc253x/usb/common/usb-core.c @@ -0,0 +1,632 @@ +#include "usb-core.h" +#include "usb.h" +#include "usb-arch.h" +#include "usb-api.h" +#include "sys/process.h" +#include "descriptors.h" +#include "string-descriptors.h" + +#include + +#define DEBUG +#ifdef DEBUG +#define PRINTF(...) printf(__VA_ARGS__) +#else +#define PRINTF(...) +#endif + + +struct USB_request_st usb_setup_buffer; +static USBBuffer ctrl_buffer; + +#define SETUP_ID 1 +#define OUT_ID 2 +#define IN_ID 3 +#define STATUS_OUT_ID 4 +#define STATUS_IN_ID 5 + +static uint16_t usb_device_status; +static uint8_t usb_configuration_value; + +static struct USBRequestHandlerHook *usb_request_handler_hooks = NULL; + +static const unsigned char zero_byte = 0; +static const unsigned short zero_word = 0; + +static unsigned char usb_flags = 0; +#define USB_FLAG_ADDRESS_PENDING 0x01 + +static struct process *global_user_event_pocess = NULL; +static unsigned int global_user_events = 0; + +void +usb_set_global_event_process(struct process *p) +{ + global_user_event_pocess = p; +} +unsigned int +usb_get_global_events(void) +{ + unsigned int e = global_user_events; + global_user_events = 0; + return e; +} + +static void +notify_user(unsigned int e) +{ + global_user_events |= e; + if(global_user_event_pocess) { + process_poll(global_user_event_pocess); + } +} + +void +usb_send_ctrl_response(const uint8_t * data, unsigned int len) +{ + if(ctrl_buffer.flags & USB_BUFFER_SUBMITTED) + return; + if(len >= usb_setup_buffer.wLength) { + len = usb_setup_buffer.wLength; /* Truncate if too long */ + } + ctrl_buffer.flags = USB_BUFFER_NOTIFY | USB_BUFFER_IN; + if(len < usb_setup_buffer.wLength) { + ctrl_buffer.flags |= USB_BUFFER_SHORT_END; + } + ctrl_buffer.next = NULL; + ctrl_buffer.data = (uint8_t *) data; + ctrl_buffer.left = len; + ctrl_buffer.id = IN_ID; + usb_submit_xmit_buffer(0, &ctrl_buffer); +} + +static uint8_t error_stall = 0; + +void +usb_error_stall() +{ + error_stall = 1; + usb_arch_control_stall(0); +} + +void +usb_send_ctrl_status() +{ + if(ctrl_buffer.flags & USB_BUFFER_SUBMITTED) + return; + ctrl_buffer.flags = USB_BUFFER_NOTIFY | USB_BUFFER_IN; + ctrl_buffer.next = NULL; + ctrl_buffer.data = NULL; + ctrl_buffer.left = 0; + ctrl_buffer.id = STATUS_IN_ID; + usb_submit_xmit_buffer(0, &ctrl_buffer); +} + +static usb_ctrl_data_callback data_callback = NULL; + +static uint8_t *ctrl_data = NULL; + +static unsigned int ctrl_data_len = 0; + +void +usb_get_ctrl_data(uint8_t * data, unsigned int length, + usb_ctrl_data_callback cb) +{ + if(ctrl_buffer.flags & USB_BUFFER_SUBMITTED) + return; + PRINTF("usb_get_ctrl_data: %d\n", length); + data_callback = cb; + ctrl_data = data; + ctrl_data_len = length; + ctrl_buffer.flags = USB_BUFFER_NOTIFY; + ctrl_buffer.next = NULL; + ctrl_buffer.data = data; + ctrl_buffer.left = length; + ctrl_buffer.id = OUT_ID; + usb_submit_recv_buffer(0, &ctrl_buffer); +} + +#if 0 + +void +usb_set_user_process(struct process *p) +{ + user_process = p; +} +#endif + +static void +get_device_descriptor() +{ + usb_send_ctrl_response((unsigned char *)&device_descriptor, + sizeof(device_descriptor)); +} + +static void +get_string_descriptor() +{ +#if OLD_STRING_DESCR + 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 { + const struct usb_st_string_descriptor *descriptor; + + unsigned char l; + + 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); + } +#else + const struct usb_st_string_descriptor *descriptor; + + descriptor = (struct usb_st_string_descriptor *) + usb_class_get_string_descriptor(usb_setup_buffer.wIndex, + LOW_BYTE(usb_setup_buffer.wValue)); + if(!descriptor) { + usb_error_stall(); + return; + } + usb_send_ctrl_response((const unsigned char *)descriptor, + descriptor->bLength); +#endif +} + +static void +get_configuration_descriptor() +{ + usb_send_ctrl_response((unsigned char *)configuration_head, + configuration_head->wTotalLength); +} + +static void +get_configuration() +{ + usb_send_ctrl_response((unsigned char *)&usb_configuration_value, + sizeof(usb_configuration_value)); +} + +/* Returns true if the configuration value changed */ +static int +set_configuration() +{ + notify_user(USB_EVENT_CONFIG); + if(usb_configuration_value != LOW_BYTE(usb_setup_buffer.wValue)) { + usb_configuration_value = LOW_BYTE(usb_setup_buffer.wValue); + usb_arch_set_configuration(usb_configuration_value); + usb_send_ctrl_status(); + return 1; + } else { + usb_send_ctrl_status(); + return 0; + } +} + +static void +get_device_status() +{ + PRINTF("get_device_status\n"); + usb_send_ctrl_response((const unsigned char *)&usb_device_status, + sizeof(usb_device_status)); +} + +static void +get_endpoint_status() +{ + static uint16_t status; + + PRINTF("get_endpoint_status\n"); + if((usb_setup_buffer.wIndex & 0x7f) == 0) { + usb_send_ctrl_response((const unsigned char *)&zero_word, + sizeof(zero_word)); + } else { + status = usb_arch_get_ep_status(usb_setup_buffer.wIndex); + usb_send_ctrl_response((uint8_t *) & status, sizeof(status)); + } +} + +static void +get_interface_status() +{ + PRINTF("get_interface_status\n"); + usb_send_ctrl_response((const unsigned char *)&zero_word, + sizeof(zero_word)); +} + +static void +get_interface() +{ + PRINTF("get_interface\n"); + if(usb_configuration_value == 0) + usb_error_stall(); + else { + usb_send_ctrl_response(&zero_byte, sizeof(zero_byte)); + } +} + + +static unsigned int +handle_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_flags |= USB_FLAG_ADDRESS_PENDING; + /* The actual setting of the address is done when the status packet + is sent. */ + 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()) { +#if 0 + config_msg.data.config = LOW_BYTE(usb_setup_buffer.wValue); + notify_user(&config_msg); +#endif + } + break; + default: + return 0; + } + break; + case 0x01: /* standard interface OUT requests */ + switch (usb_setup_buffer.bRequest) { + case SET_INTERFACE: + /* Change interface here if we support more than one */ + usb_send_ctrl_status(); + break; + default: + return 0; + } + break; + case 0x02: /* standard endpoint OUT requests */ + switch (usb_setup_buffer.bRequest) { + case SET_FEATURE: + case CLEAR_FEATURE: + if(usb_setup_buffer.wValue == ENDPOINT_HALT_FEATURE) { + usb_arch_halt_endpoint(usb_setup_buffer.wIndex, + usb_setup_buffer.bRequest == SET_FEATURE); + usb_send_ctrl_status(); + } 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: + PRINTF("Get report\n"); + send_ctrl_response((code u_int8_t *) & zero_byte, sizeof(zero_byte)); + break; + case GET_HID_IDLE: + PRINTF("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: + PRINTF("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 +}; + +static void +submit_setup(void) +{ + ctrl_buffer.next = NULL; + ctrl_buffer.data = (uint8_t *) & usb_setup_buffer; + ctrl_buffer.left = sizeof(usb_setup_buffer); + ctrl_buffer.flags = (USB_BUFFER_PACKET_END | USB_BUFFER_SETUP + | USB_BUFFER_NOTIFY); + ctrl_buffer.id = SETUP_ID; + usb_submit_recv_buffer(0, &ctrl_buffer); +} + +PROCESS(usb_process, "USB"); + +PROCESS_THREAD(usb_process, ev, data) +{ + PROCESS_BEGIN(); + PRINTF("USB process started\n"); + while(1) { + PROCESS_WAIT_EVENT(); + if(ev == PROCESS_EVENT_EXIT) + break; + if(ev == PROCESS_EVENT_POLL) { + unsigned int events = usb_arch_get_global_events(); + + if(events) { + if(events & USB_EVENT_RESET) { + submit_setup(); + usb_configuration_value = 0; + notify_user(USB_EVENT_RESET); + } + if(events & USB_EVENT_SUSPEND) { + notify_user(USB_EVENT_SUSPEND); + } + if(events & USB_EVENT_RESUME) { + notify_user(USB_EVENT_RESUME); + } + + } + events = usb_get_ep_events(0); + if(events) { + if((events & USB_EP_EVENT_NOTIFICATION) + && !(ctrl_buffer.flags & USB_BUFFER_SUBMITTED)) { + /* PRINTF("Endpoint 0\n"); */ + if(ctrl_buffer.flags & USB_BUFFER_FAILED) { + /* Something went wrong with the buffer, just wait for a + new SETUP packet */ + PRINTF("Discarded\n"); + submit_setup(); + } else if(ctrl_buffer.flags & USB_BUFFER_SETUP) { + struct USBRequestHandlerHook *hook = usb_request_handler_hooks; + + PRINTF("Setup\n"); + { + unsigned int i; + + for(i = 0; i < 8; i++) + PRINTF(" %02x", ((unsigned char *)&usb_setup_buffer)[i]); + PRINTF("\n"); + } + + 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(); + PRINTF("Unhandled setup: %02x %02x %04x %04x %04x\n", + usb_setup_buffer.bmRequestType, + usb_setup_buffer.bRequest, usb_setup_buffer.wValue, + usb_setup_buffer.wIndex, usb_setup_buffer.wLength); + } + /* Check if any handler stalled the pipe, if so prepare for + next setup */ + if(error_stall) { + error_stall = 0; + submit_setup(); + } + } else { + if(ctrl_buffer.id == IN_ID) { + /* Receive status stage */ + PRINTF("Status OUT\n"); + ctrl_buffer.flags = USB_BUFFER_NOTIFY; + ctrl_buffer.next = NULL; + ctrl_buffer.data = NULL; + ctrl_buffer.left = 0; + ctrl_buffer.id = STATUS_OUT_ID; + usb_submit_recv_buffer(0, &ctrl_buffer); + } else if(ctrl_buffer.id == STATUS_OUT_ID) { + PRINTF("Status OUT done\n"); + submit_setup(); + } else if(ctrl_buffer.id == STATUS_IN_ID) { + PRINTF("Status IN done\n"); + if(usb_flags & USB_FLAG_ADDRESS_PENDING) { + while(usb_send_pending(0)); + usb_arch_set_address(LOW_BYTE(usb_setup_buffer.wValue)); + usb_flags &= ~USB_FLAG_ADDRESS_PENDING; + } + submit_setup(); + } else if(ctrl_buffer.id == OUT_ID) { + PRINTF("OUT\n"); + if(data_callback) { + data_callback(ctrl_data, ctrl_data_len - ctrl_buffer.left); + } else { + usb_send_ctrl_status(); + } + } + } + } + } + } + } + PROCESS_END(); +} + + +void +usb_setup(void) +{ + usb_arch_setup(); + process_start(&usb_process, NULL); + usb_arch_set_global_event_process(&usb_process); + usb_set_ep_event_process(0, &usb_process); + + usb_register_request_handler(&standard_request_hook); +} + +void +usb_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; +} + +void +usb_prepend_request_handler(struct USBRequestHandlerHook *hook) +{ + hook->next = usb_request_handler_hooks; + usb_request_handler_hooks = hook; +} + + +unsigned int +usb_get_current_configuration(void) +{ + return usb_configuration_value; +} + +void +usb_setup_bulk_endpoint(unsigned char addr) +{ + usb_arch_setup_bulk_endpoint(addr); +} + +void +usb_setup_interrupt_endpoint(unsigned char addr) +{ + usb_arch_setup_interrupt_endpoint(addr); +} + +void +usb_disable_endpoint(uint8_t addr) +{ + usb_arch_discard_all_buffers(addr); + usb_arch_disable_endpoint(addr); +} + +void +usb_discard_all_buffers(uint8_t addr) +{ + usb_arch_discard_all_buffers(addr); +} + +void +usb_halt_endpoint(uint8_t addr, int halt) +{ + usb_arch_halt_endpoint(addr, halt); +} + +int +usb_send_pending(uint8_t addr) +{ + return usb_arch_send_pending(addr); +} diff --git a/cpu/cc253x/usb/common/usb-core.h b/cpu/cc253x/usb/common/usb-core.h new file mode 100644 index 000000000..aa925014a --- /dev/null +++ b/cpu/cc253x/usb/common/usb-core.h @@ -0,0 +1,19 @@ +#ifndef __USB_CORE_H__YIKJDA7S1X__ +#define __USB_CORE_H__YIKJDA7S1X__ + +#include + +extern struct USB_request_st usb_setup_buffer; + +void usb_send_ctrl_response(const uint8_t *data, unsigned int len); + +void usb_error_stall(); + +void usb_send_ctrl_status(); + +typedef void (*usb_ctrl_data_callback)(uint8_t *data, unsigned int length); + +void usb_get_ctrl_data(uint8_t *data, unsigned int length, + usb_ctrl_data_callback cb); + +#endif /* __USB_CORE_H__YIKJDA7S1X__ */ diff --git a/cpu/cc253x/usb/common/usb.h b/cpu/cc253x/usb/common/usb.h new file mode 100644 index 000000000..86dc3419a --- /dev/null +++ b/cpu/cc253x/usb/common/usb.h @@ -0,0 +1,185 @@ +#ifndef __USB_H__6PFTDPIMZM__ +#define __USB_H__6PFTDPIMZM__ +#include + +/* Adapted from usb_kbd_enum.h in c5131-usb-kbd-light-1_0_2 package from + Atmel */ + +/* These definitions assume a little endian architecture */ + +#ifdef __GNUC__ +#define BYTE_ALIGNED __attribute__ ((__packed__)) +#else +#define BYTE_ALIGNED +#endif + +#define LOW_BYTE(x) ((unsigned char)x) +#define HIGH_BYTE(x) ((unsigned char)(x>>8)) + +typedef uint8_t Uchar; +typedef uint16_t Uint16; +typedef uint32_t Uint32; + +/*_____ S T A N D A R D R E Q U E S T S __________________________________*/ + +#define GET_STATUS 0x00 +#define GET_DEVICE 0x01 +#define CLEAR_FEATURE 0x01 /* see FEATURES below */ +#define GET_STRING 0x03 +#define SET_FEATURE 0x03 /* see FEATURES below */ +#define SET_ADDRESS 0x05 +#define GET_DESCRIPTOR 0x06 +#define SET_DESCRIPTOR 0x07 +#define GET_CONFIGURATION 0x08 +#define SET_CONFIGURATION 0x09 +#define GET_INTERFACE 0x0A +#define SET_INTERFACE 0x0B +#define SYNCH_FRAME 0x0C + +#define GET_DEVICE_DESCRIPTOR 1 +#define GET_CONFIGURATION_DESCRIPTOR 4 + +#define REQUEST_DEVICE_STATUS 0x80 +#define REQUEST_INTERFACE_STATUS 0x81 +#define REQUEST_ENDPOINT_STATUS 0x82 +#define ZERO_TYPE 0x00 +#define INTERFACE_TYPE 0x01 +#define ENDPOINT_TYPE 0x02 + +/*_____ D E S C R I P T O R T Y P E S ____________________________________*/ + +#define DEVICE 0x01 +#define CONFIGURATION 0x02 +#define STRING 0x03 +#define INTERFACE 0x04 +#define ENDPOINT 0x05 + +/* HID specific */ +#define HID 0x21 +#define REPORT 0x22 +/* *** */ + +/*_____ S T A N D A R D F E A T U R E S __________________________________*/ + +#define DEVICE_REMOTE_WAKEUP_FEATURE 0x01 +#define ENDPOINT_HALT_FEATURE 0x00 + +/*_____ D E V I C E S T A T U S ___________________________________________*/ + +#define SELF_POWERED 1 + +/*_____ D E V I C E S T A T E _____________________________________________*/ + +#define ATTACHED 0 +#define POWERED 1 +#define DEFAULT 2 +#define ADDRESSED 3 +#define CONFIGURED 4 +#define SUSPENDED 5 + +#define USB_CONFIG_BUSPOWERED 0x80 +#define USB_CONFIG_SELFPOWERED 0x40 +#define USB_CONFIG_REMOTEWAKEUP 0x20 + +/* Class specific */ +#define CS_INTERFACE 0x24 +#define CS_ENDPOINT 0x25 + +/*_________________________________________________________ S T R U C T _____*/ +/*_____ U S B D E V I C E R E Q U E S T _________________________________*/ + +struct USB_request_st +{ + Uchar bmRequestType; /* Characteristics of the request */ + Uchar bRequest; /* Specific request */ + Uint16 wValue; + Uint16 wIndex; /* field that varies according to request */ + Uint16 wLength; /* Number of bytes to transfer if Data */ +}; + + +/*_____ U S B D E V I C E D E S C R I P T O R ___________________________*/ + +struct usb_st_device_descriptor +{ + Uchar bLength; /* Size of this descriptor in bytes */ + Uchar bDescriptorType; /* DEVICE descriptor type */ + Uint16 bscUSB; /* Binay Coded Decimal Spec. release */ + Uchar bDeviceClass; /* Class code assigned by the USB */ + Uchar bDeviceSubClass; /* Sub-class code assigned by the USB */ + Uchar bDeviceProtocol; /* Protocol code assigned by the USB */ + Uchar bMaxPacketSize0; /* Max packet size for EP0 */ + Uint16 idVendor; /* Vendor ID. ATMEL = 0x03EB */ + Uint16 idProduct; /* Product ID assigned by the manufacturer */ + Uint16 bcdDevice; /* Device release number */ + Uchar iManufacturer; /* Index of manu. string descriptor */ + Uchar iProduct; /* Index of prod. string descriptor */ + Uchar iSerialNumber; /* Index of S.N. string descriptor */ + Uchar bNumConfigurations; /* Number of possible configurations */ +} BYTE_ALIGNED; + + +/*_____ U S B C O N F I G U R A T I O N D E S C R I P T O R _____________*/ + +struct usb_st_configuration_descriptor +{ + Uchar bLength; /* size of this descriptor in bytes */ + Uchar bDescriptorType; /* CONFIGURATION descriptor type */ + Uint16 wTotalLength; /* total length of data returned */ + Uchar bNumInterfaces; /* number of interfaces for this conf. */ + Uchar bConfigurationValue; /* value for SetConfiguration resquest */ + Uchar iConfiguration; /* index of string descriptor */ + Uchar bmAttibutes; /* Configuration characteristics */ + Uchar MaxPower; /* maximum power consumption */ +} BYTE_ALIGNED; + + +/*_____ U S B I N T E R F A C E D E S C R I P T O R _____________________*/ + +struct usb_st_interface_descriptor +{ + Uchar bLength; /* size of this descriptor in bytes */ + Uchar bDescriptorType; /* INTERFACE descriptor type */ + Uchar bInterfaceNumber; /* Number of interface */ + Uchar bAlternateSetting; /* value to select alternate setting */ + Uchar bNumEndpoints; /* Number of EP except EP 0 */ + Uchar bInterfaceClass; /* Class code assigned by the USB */ + Uchar bInterfaceSubClass; /* Sub-class code assigned by the USB */ + Uchar bInterfaceProtocol; /* Protocol code assigned by the USB */ + Uchar iInterface; /* Index of string descriptor */ +} BYTE_ALIGNED; + + +/*_____ U S B E N D P O I N T D E S C R I P T O R _______________________*/ + +struct usb_st_endpoint_descriptor +{ + Uchar bLength; /* Size of this descriptor in bytes */ + Uchar bDescriptorType; /* ENDPOINT descriptor type */ + Uchar bEndpointAddress; /* Address of the endpoint */ + Uchar bmAttributes; /* Endpoint's attributes */ + Uint16 wMaxPacketSize; /* Maximum packet size for this EP */ + Uchar bInterval; /* Interval for polling EP in ms */ +/* Uchar bRefresh; */ +/* Uchar bSynchAddress; */ +} BYTE_ALIGNED; + + +/*_____ U S B S T R I N G D E S C R I P T O R _______________*/ + +struct usb_st_string_descriptor +{ + Uchar bLength; /* size of this descriptor in bytes */ + Uchar bDescriptorType; /* STRING descriptor type */ + Uint16 wstring[1];/* unicode characters */ +} BYTE_ALIGNED; + + +struct usb_st_language_descriptor +{ + Uchar bLength; /* size of this descriptor in bytes */ + Uchar bDescriptorType; /* STRING descriptor type */ + Uint16 wlangid[1]; /* language id */ +} BYTE_ALIGNED; + +#endif /* __USB_H__6PFTDPIMZM__ */