#include "usb_device.h" #include #include #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 __attribute__((packed)) { 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 __attribute__((packed)) { CS_INTERFACE = 0x24, CS_ENDPOINT = 0x25 } usb_cdc_functional_descriptor_type_t; typedef enum __attribute__((packed)) { 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"); typedef uint16_t (*cdc_receive_callback_t)(usb_device_t* device, uint8_t* data, uint16_t count); typedef uint8_t* (*cdc_receive_location_callback_t)(usb_device_t* device, uint16_t count); /* typedef enum { */ /* CDC_STATE_NONE, */ /* CDC_STATE_GOT_DATA, */ /* CDC_STATE_FULL_FIFO, */ /* } cdc_rx_state_t; */ typedef enum { CDC_TX_STATE_NONE, CDC_TX_STATE_SENDING, CDC_TX_STATE_, } cdc_tx_state_t; #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; cdc_receive_callback_t receive_callback; cdc_receive_location_callback_t receive_location_callback; // Internal state. queue_t* rx_buffer; cdc_tx_state_t tx_state; uint8_t got_setup; bool endpoint_nak; uint32_t lost_data; bool reenabled_endpoint; } usb_device_cdc_t; /** * @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. * @param[in] rx_queue_size The size, in bytes, of the rx queue. When the queue is full, data cannot be received. There should not be any data lost, but it's not a 100% guarantee for now. */ void cdc_acm_configure(usb_device_t *device, uint16_t rx_queue_size); void cdc_data_set_receive_callback(usb_device_t *device, cdc_receive_callback_t callback); void cdc_data_set_receive_location_callback(usb_device_t *device, cdc_receive_location_callback_t callback); int32_t cdc_data_send_blocking(usb_device_t *device, uint8_t *data, uint16_t size); int32_t cdc_data_send(usb_device_t* device, uint8_t* data, uint16_t size); uint16_t cdc_data_receive(usb_device_t* device, uint8_t* buffer, uint16_t max_size); bool cdc_got_params(usb_device_t* device); #endif // USB_DEVICE_CDC_H