#include "usb_device.h"
#ifndef USB_DEVICE_CDC_H
#define USB_DEVICE_CDC_H
#define USB_CLASS_CDC_CODE 0x02
#define USB_CLASS_DATA_CODE 0x0A
#define USB_SUBCLASS_CDC_ACM_CODE 0x02
/**
* @var USB_CLASS_CDC_ACM
* @brief Vtable of usb cdc acm class.
* @see usb_cdc_acm_configure to call after usb_device_init call to configure all descriptors.
* The usb cdc class is a standard usb class for communications and data transfer.
* acm stands for Abstract Control Model. It is used mainly in older modems to convert uart
* to usb. Here cdc acm is used since it is widely supported on computers, but there are no
* supported cdc acm commands. AT commands are not handled.
*/
extern usb_class_vtable_t USB_CLASS_CDC_ACM;
typedef enum {
SEND_ENCAPSULATED_COMMAND = 0,
GET_ENCAPSULATED_RESPONSE = 1,
/* SET_COMM_FEATURE = 2, */
/* GET_COMM_FEATURE = 3, */
/* CLEAR_COMM_FEATURE = 4, */
/* SET_AUX_LINE_STATE = 0x10, */
/* SET_HOOK_STATE = 0x11, */
/* PULSE_SETUP = 0x12, */
/* SEND_PULSE = 0x13, */
/* SET_PULSE_TIME = 0x14, */
/* RING_AUX_JACK = 0x15, */
/* SET_LINE_CODING = 0x20, */
/* GET_LINE_CODING = 0x21, */
} usb_cdc_request_code_type_t;
typedef enum {
CS_INTERFACE = 0x24,
CS_ENDPOINT = 0x25
} usb_cdc_functional_descriptor_type_t;
typedef enum {
HEADER_FUNCTIONAL_DESCRIPTOR_FUNCTIONAL_DESCRIPTOR = 0x00,
CALL_MANAGEMENT_FUNCTIONAL_FUNCTIONAL_DESCRIPTOR = 0x01,
ABSTRACT_CONTROL_MANAGEMENT_FUNCTIONAL_DESCRIPTOR = 0x02,
DIRECT_LINE_MANAGEMENT_FUNCTIONAL_DESCRIPTOR = 0x03,
TELEPHONE_RINGER_FUNCTIONAL_DESCRIPTOR = 0x04,
TELEPHONE_CALL_AND_LINE_STATE_REPORTING_CAPABILITIES_FUNCTIONAL_DESCRIPTOR = 0x05,
UNION_FUNCTIONAL_DESCRIPTOR = 0x06,
CONTRY_SELECTION_FUNCTIONAL_DESCRIPTOR = 0x07,
TELEPHONE_OPERATIONAL_MODES_FUNCTIONAL_DESCRIPTOR = 0x08,
USB_TERMINAL_FUNCTIONAL_DESCRIPTOR = 0x09,
NETWORK_CHANNEL_FUNCTIONAL_DESCRIPTOR = 0x0A,
PROTOCOL_UNIT_FUNCTIONAL_DESCRIPTOR = 0x0B,
EXTENSION_UNIT_FUNCTIONAL_DESCRIPTOR = 0x0C,
MULTI_CHANNEL_MANAGEMENT_FUNCTIONAL_DESCRIPTOR = 0x0D,
CAPI_CONTROL_MANAGEMENT_FUNCTIONAL_DESCRIPTOR = 0x0E,
ETHERNET_NETWORKING_FUNCTIONAL_DESCRIPTOR = 0x0F,
ATM_NETWORKING_FUNCTIONAL_DESCRIPTOR = 0x10,
WIRELESS_HANDSET_CONTROL_MODEL_FUNCTIONAL_DESCRIPTOR = 0x11,
} usb_cdc_functional_descriptor_subtype_t;
#pragma GCC diagnostic error "-Wpadded"
typedef struct __attribute__((packed)) {
uint8_t bFunctionLength;
usb_cdc_functional_descriptor_type_t bDescriptorType;
usb_cdc_functional_descriptor_subtype_t bDescriptorSubType;
} usb_cdc_functional_descriptor_header_t;
_Static_assert(sizeof(usb_cdc_functional_descriptor_header_t) == 3, "Size check");
typedef struct __attribute__((packed)) {
usb_cdc_functional_descriptor_header_t header;
uint16_t bcdCDC;
} usb_cdc_header_functional_decriptor_t;
_Static_assert(sizeof(usb_cdc_header_functional_decriptor_t) == 5, "Size check");
typedef struct {
usb_cdc_functional_descriptor_header_t header;
uint8_t bmCapabilities;
} usb_cdc_acm_functional_decriptor_t;
_Static_assert(sizeof(usb_cdc_acm_functional_decriptor_t) == 4, "Size check");
typedef struct {
usb_cdc_functional_descriptor_header_t header;
uint8_t bControlInterface;
uint8_t bSubordinateInterface0;
} usb_cdc_union_functional_decriptor_t;
_Static_assert(sizeof(usb_cdc_union_functional_decriptor_t) == 5, "Size check");
typedef struct {
usb_cdc_functional_descriptor_header_t header;
uint8_t bmCapabilities;
uint8_t bDataInterface;
} usb_cdc_call_management_functional_decriptor_t;
_Static_assert(sizeof(usb_cdc_call_management_functional_decriptor_t) == 5, "Size check");
#pragma GCC diagnostic ignored "-Wpadded"
typedef struct {
usb_class_header_t header;
uint8_t functional_descriptors_count;
usb_cdc_functional_descriptor_header_t** functional_descriptors;
} usb_device_cdc_t;
usb_class_header_t* usb_device_cdc_init(usb_device_t *device,
uint16_t id_vendor, uint16_t id_product,
char *vendor_name, char *product_name,
uint16_t serial_number, char* serial_name);
task_result_t usb_device_cdc_send_configuration(usb_device_t* device, usb_setup_command_t* cmd);
task_result_t usb_device_cdc_setup_packet_callback(usb_device_t* device, usb_setup_command_t* cmd);
void usb_device_cdc_enumeration_done_callback(usb_device_t* device);
void usb_device_cdc_txfifo_empty_callback(usb_device_t* device, uint8_t endpoint);
void usb_device_cdc_rxfifo_empty_callback(usb_device_t* device, uint8_t endpoint);
void usb_device_cdc_transmit_done_callback(usb_device_t* device, uint8_t endpoint);
void usb_device_cdc_nak_callback(usb_device_t* device, uint8_t endpoint);
void usb_device_cdc_nyet_callback(usb_device_t* device, uint8_t endpoint);
/**
* @brief Configures cdc acm descriptors
* @details All the descriptors for cdc acm device are initialized here.
* That means that after call to this function, usb_device_setup can be safely
* called, and all setup commands handled.
* @param[in,out] device The usb device.
*/
void usb_device_cdc_acm_configure(usb_device_t *device);
#endif // USB_DEVICE_CDC_H