From 659b3fb7d32981405e43116195e516856a22cc00 Mon Sep 17 00:00:00 2001 From: ksb Date: Sat, 11 Jul 2009 14:30:53 +0000 Subject: [PATCH] USB CDC-ACM class --- .../common/usb/cdc-acm/cdc-acm-descriptors.c | 126 +++++++++++ .../cdc-acm/cdc-acm-string-descriptors.xml | 19 ++ cpu/arm/common/usb/cdc-acm/cdc-acm.c | 110 +++++++++ cpu/arm/common/usb/cdc-acm/cdc-acm.h | 7 + cpu/arm/common/usb/cdc-acm/cdc.h | 214 ++++++++++++++++++ 5 files changed, 476 insertions(+) create mode 100644 cpu/arm/common/usb/cdc-acm/cdc-acm-descriptors.c create mode 100644 cpu/arm/common/usb/cdc-acm/cdc-acm-string-descriptors.xml create mode 100644 cpu/arm/common/usb/cdc-acm/cdc-acm.c create mode 100644 cpu/arm/common/usb/cdc-acm/cdc-acm.h create mode 100644 cpu/arm/common/usb/cdc-acm/cdc.h diff --git a/cpu/arm/common/usb/cdc-acm/cdc-acm-descriptors.c b/cpu/arm/common/usb/cdc-acm/cdc-acm-descriptors.c new file mode 100644 index 000000000..4e9902297 --- /dev/null +++ b/cpu/arm/common/usb/cdc-acm/cdc-acm-descriptors.c @@ -0,0 +1,126 @@ +#include "descriptors.h" +#include +#include +#include + +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/arm/common/usb/cdc-acm/cdc-acm-string-descriptors.xml b/cpu/arm/common/usb/cdc-acm/cdc-acm-string-descriptors.xml new file mode 100644 index 000000000..01d14f2c4 --- /dev/null +++ b/cpu/arm/common/usb/cdc-acm/cdc-acm-string-descriptors.xml @@ -0,0 +1,19 @@ + + + + 0x0409 + 0x041d + + + + Serial interface + Serieport + + + Fluffware + + + 0.01 + + + diff --git a/cpu/arm/common/usb/cdc-acm/cdc-acm.c b/cpu/arm/common/usb/cdc-acm/cdc-acm.c new file mode 100644 index 000000000..792313327 --- /dev/null +++ b/cpu/arm/common/usb/cdc-acm/cdc-acm.c @@ -0,0 +1,110 @@ +#include +#include +#include +#include +#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/arm/common/usb/cdc-acm/cdc-acm.h b/cpu/arm/common/usb/cdc-acm/cdc-acm.h new file mode 100644 index 000000000..4a85dc208 --- /dev/null +++ b/cpu/arm/common/usb/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/arm/common/usb/cdc-acm/cdc.h b/cpu/arm/common/usb/cdc-acm/cdc.h new file mode 100644 index 000000000..2d57abc2b --- /dev/null +++ b/cpu/arm/common/usb/cdc-acm/cdc.h @@ -0,0 +1,214 @@ +#ifndef __CDC_H__K1Q26ESJOC__ +#define __CDC_H__K1Q26ESJOC__ +#include +/* 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__ */