Porting CDC to PluggableUSB

This commit is contained in:
Martino Facchin 2018-07-03 15:40:43 +02:00
parent 5c562e143d
commit 10432a3cbd
10 changed files with 287 additions and 269 deletions

View file

@ -130,4 +130,8 @@ void loop( void ) ;
#include "USB/USBAPI.h"
#include "USB/USB_host.h"
#ifdef __cplusplus
#include "USB/CDC.h"
#endif
#endif // Arduino_h

View file

@ -18,6 +18,8 @@
#include <Arduino.h>
#include <Reset.h> // Needed for auto-reset with 1200bps port touch
#include "CDC.h"
#include "SAMD21_USBDevice.h"
#include <stdlib.h>
#include <stdio.h>
@ -25,6 +27,8 @@
#ifdef CDC_ENABLED
extern USBDevice_SAMD21G18x usbd;
#define CDC_SERIAL_BUFFER_SIZE 256
/* For information purpose only since RTS is not always handled by the terminal application */
@ -51,46 +55,94 @@ static volatile LineInfo _usbLineInfo = {
};
static volatile int32_t breakValue = -1;
static CDCDescriptor _cdcInterface = {
D_IAD(0, 2, CDC_COMMUNICATION_INTERFACE_CLASS, CDC_ABSTRACT_CONTROL_MODEL, 0),
// CDC communication interface
D_INTERFACE(CDC_ACM_INTERFACE, 1, CDC_COMMUNICATION_INTERFACE_CLASS, CDC_ABSTRACT_CONTROL_MODEL, 0),
D_CDCCS(CDC_HEADER, CDC_V1_10 & 0xFF, (CDC_V1_10>>8) & 0x0FF), // Header (1.10 bcd)
D_CDCCS4(CDC_ABSTRACT_CONTROL_MANAGEMENT, 6), // SET_LINE_CODING, GET_LINE_CODING, SET_CONTROL_LINE_STATE supported
D_CDCCS(CDC_UNION, CDC_ACM_INTERFACE, CDC_DATA_INTERFACE), // Communication interface is master, data interface is slave 0
D_CDCCS(CDC_CALL_MANAGEMENT, 1, 1), // Device handles call management (not)
D_ENDPOINT(USB_ENDPOINT_IN(CDC_ENDPOINT_ACM), USB_ENDPOINT_TYPE_INTERRUPT, 0x10, 0x10),
// CDC data interface
D_INTERFACE(CDC_DATA_INTERFACE, 2, CDC_DATA_INTERFACE_CLASS, 0, 0),
D_ENDPOINT(USB_ENDPOINT_OUT(CDC_ENDPOINT_OUT), USB_ENDPOINT_TYPE_BULK, EPX_SIZE, 0),
D_ENDPOINT(USB_ENDPOINT_IN (CDC_ENDPOINT_IN ), USB_ENDPOINT_TYPE_BULK, EPX_SIZE, 0)
};
_Pragma("pack()")
const void* _CDC_GetInterface(void)
{
return &_cdcInterface;
}
// CDC
#define CDC_ACM_INTERFACE pluggedInterface // CDC ACM
#define CDC_DATA_INTERFACE pluggedInterface+1 // CDC Data
#define CDC_ENDPOINT_ACM pluggedEndpoint
#define CDC_ENDPOINT_OUT pluggedEndpoint+1
#define CDC_ENDPOINT_IN pluggedEndpoint+2
uint32_t _CDC_GetInterfaceLength(void)
{
return sizeof(_cdcInterface);
}
#define CDC_RX CDC_ENDPOINT_OUT
#define CDC_TX CDC_ENDPOINT_IN
int CDC_GetInterface(uint8_t* interfaceNum)
int Serial_::getInterface(uint8_t* interfaceNum)
{
interfaceNum[0] += 2; // uses 2
return USBDevice.sendControl(&_cdcInterface,sizeof(_cdcInterface));
CDCDescriptor _cdcInterface = {
D_IAD(pluggedInterface, 2, CDC_COMMUNICATION_INTERFACE_CLASS, CDC_ABSTRACT_CONTROL_MODEL, 0),
// CDC communication interface
D_INTERFACE(CDC_ACM_INTERFACE, 1, CDC_COMMUNICATION_INTERFACE_CLASS, CDC_ABSTRACT_CONTROL_MODEL, 0),
D_CDCCS(CDC_HEADER, CDC_V1_10 & 0xFF, (CDC_V1_10>>8) & 0x0FF), // Header (1.10 bcd)
D_CDCCS4(CDC_ABSTRACT_CONTROL_MANAGEMENT, 6), // SET_LINE_CODING, GET_LINE_CODING, SET_CONTROL_LINE_STATE supported
D_CDCCS(CDC_UNION, CDC_ACM_INTERFACE, CDC_DATA_INTERFACE), // Communication interface is master, data interface is slave 0
D_CDCCS(CDC_CALL_MANAGEMENT, 1, 1), // Device handles call management (not)
D_ENDPOINT(USB_ENDPOINT_IN(CDC_ENDPOINT_ACM), USB_ENDPOINT_TYPE_INTERRUPT, 0x10, 0x10),
// CDC data interface
D_INTERFACE(CDC_DATA_INTERFACE, 2, CDC_DATA_INTERFACE_CLASS, 0, 0),
D_ENDPOINT(USB_ENDPOINT_OUT(CDC_ENDPOINT_OUT), USB_ENDPOINT_TYPE_BULK, EPX_SIZE, 0),
D_ENDPOINT(USB_ENDPOINT_IN (CDC_ENDPOINT_IN), USB_ENDPOINT_TYPE_BULK, EPX_SIZE, 0)
};
return USBDevice.sendControl(&_cdcInterface, sizeof(_cdcInterface));
}
bool CDC_Setup(USBSetup& setup)
int Serial_::getDescriptor(USBSetup& setup)
{
return 0;
}
static void utox8(uint32_t val, char* s) {
for (int i = 0; i < 8; i++) {
int d = val & 0XF;
val = (val >> 4);
s[7 - i] = d > 9 ? 'A' + d - 10 : '0' + d;
}
}
uint8_t Serial_::getShortName(char* name) {
// from section 9.3.3 of the datasheet
#define SERIAL_NUMBER_WORD_0 *(volatile uint32_t*)(0x0080A00C)
#define SERIAL_NUMBER_WORD_1 *(volatile uint32_t*)(0x0080A040)
#define SERIAL_NUMBER_WORD_2 *(volatile uint32_t*)(0x0080A044)
#define SERIAL_NUMBER_WORD_3 *(volatile uint32_t*)(0x0080A048)
utox8(SERIAL_NUMBER_WORD_0, &name[0]);
utox8(SERIAL_NUMBER_WORD_1, &name[8]);
utox8(SERIAL_NUMBER_WORD_2, &name[16]);
utox8(SERIAL_NUMBER_WORD_3, &name[24]);
return 32;
}
void Serial_::handleEndpoint(int ep) {
if (ep == CDC_ENDPOINT_IN)
{
// NAK on endpoint IN, the bank is not yet filled in.
usbd.epBank1ResetReady(CDC_ENDPOINT_IN);
usbd.epBank1AckTransferComplete(CDC_ENDPOINT_IN);
}
if (ep == CDC_ENDPOINT_ACM)
{
// NAK on endpoint IN, the bank is not yet filled in.
usbd.epBank1ResetReady(CDC_ENDPOINT_ACM);
usbd.epBank1AckTransferComplete(CDC_ENDPOINT_ACM);
}
}
bool Serial_::setup(USBSetup& setup)
{
uint8_t requestType = setup.bmRequestType;
uint8_t r = setup.bRequest;
uint8_t i = setup.wIndex;
if (CDC_ACM_INTERFACE != i) {
return false;
}
if (requestType == REQUEST_DEVICETOHOST_CLASS_INTERFACE)
{
@ -103,6 +155,7 @@ bool CDC_Setup(USBSetup& setup)
if (requestType == REQUEST_HOSTTODEVICE_CLASS_INTERFACE)
{
if (r == CDC_SET_LINE_CODING)
{
USBDevice.recvControl((void*)&_usbLineInfo, 7);
@ -126,18 +179,32 @@ bool CDC_Setup(USBSetup& setup)
{
cancelReset();
}
return false;
USBDevice.sendZlp(0);
}
if (CDC_SEND_BREAK == r)
{
breakValue = ((uint16_t)setup.wValueH << 8) | setup.wValueL;
return false;
USBDevice.sendZlp(0);
}
return true;
}
return false;
}
Serial_::Serial_(USBDeviceClass &_usb) : PluggableUSBModule(3, 2, epType), usb(_usb), stalled(false)
{
epType[0] = USB_ENDPOINT_TYPE_INTERRUPT | USB_ENDPOINT_IN(0);
epType[1] = USB_ENDPOINT_TYPE_BULK | USB_ENDPOINT_OUT(0);
epType[2] = USB_ENDPOINT_TYPE_BULK | USB_ENDPOINT_IN(0);
PluggableUSB().plug(this);
}
void Serial_::enableInterrupt() {
usbd.epBank1EnableTransferComplete(CDC_ENDPOINT_ACM);
usbd.epBank0EnableTransferComplete(CDC_ENDPOINT_OUT);
}
void Serial_::begin(uint32_t /* baud_count */)
{
// uart config is ignored in USB-CDC

161
cores/arduino/USB/CDC.h Normal file
View file

@ -0,0 +1,161 @@
#ifndef __CDC_H__
#define __CDC_H__
#ifdef CDC_ENABLED
#include "USBDesc.h"
#include "USBAPI.h"
#include "PluggableUSB.h"
#define CDC_V1_10 0x0110
#define CDC_COMMUNICATION_INTERFACE_CLASS 0x02
#define CDC_CALL_MANAGEMENT 0x01
#define CDC_ABSTRACT_CONTROL_MODEL 0x02
#define CDC_HEADER 0x00
#define CDC_ABSTRACT_CONTROL_MANAGEMENT 0x02
#define CDC_UNION 0x06
#define CDC_CS_INTERFACE 0x24
#define CDC_CS_ENDPOINT 0x25
#define CDC_DATA_INTERFACE_CLASS 0x0A
// CDC CS interface descriptor
typedef struct
{
uint8_t len; // 5
uint8_t dtype; // 0x24
uint8_t subtype;
uint8_t d0;
uint8_t d1;
} CDCCSInterfaceDescriptor;
typedef struct
{
uint8_t len; // 4
uint8_t dtype; // 0x24
uint8_t subtype;
uint8_t d0;
} CDCCSInterfaceDescriptor4;
typedef struct
{
uint8_t len;
uint8_t dtype; // 0x24
uint8_t subtype; // 1
uint8_t bmCapabilities;
uint8_t bDataInterface;
} CMFunctionalDescriptor;
typedef struct
{
uint8_t len;
uint8_t dtype; // 0x24
uint8_t subtype; // 1
uint8_t bmCapabilities;
} ACMFunctionalDescriptor;
typedef struct
{
// IAD
IADDescriptor iad; // Only needed on compound device
// Control
InterfaceDescriptor cif;
CDCCSInterfaceDescriptor header;
ACMFunctionalDescriptor controlManagement; // ACM
CDCCSInterfaceDescriptor functionalDescriptor; // CDC_UNION
CMFunctionalDescriptor callManagement; // Call Management
EndpointDescriptor cifin;
// Data
InterfaceDescriptor dif;
EndpointDescriptor in;
EndpointDescriptor out;
} CDCDescriptor;
//================================================================================
// Serial over CDC (Serial1 is the physical port)
class Serial_ : public Stream, public PluggableUSBModule {
public:
Serial_(USBDeviceClass &_usb);
void begin(uint32_t baud_count);
void begin(unsigned long, uint8_t);
void end(void);
virtual int available(void);
virtual int availableForWrite(void);
virtual int peek(void);
virtual int read(void);
virtual void flush(void);
virtual size_t write(uint8_t);
virtual size_t write(const uint8_t *buffer, size_t size);
using Print::write; // pull in write(str) from Print
operator bool();
size_t readBytes(char *buffer, size_t length);
// This method allows processing "SEND_BREAK" requests sent by
// the USB host. Those requests indicate that the host wants to
// send a BREAK signal and are accompanied by a single uint16_t
// value, specifying the duration of the break. The value 0
// means to end any current break, while the value 0xffff means
// to start an indefinite break.
// readBreak() will return the value of the most recent break
// request, but will return it at most once, returning -1 when
// readBreak() is called again (until another break request is
// received, which is again returned once).
// This also mean that if two break requests are received
// without readBreak() being called in between, the value of the
// first request is lost.
// Note that the value returned is a long, so it can return
// 0-0xffff as well as -1.
int32_t readBreak();
// These return the settings specified by the USB host for the
// serial port. These aren't really used, but are offered here
// in case a sketch wants to act on these settings.
uint32_t baud();
uint8_t stopbits();
uint8_t paritytype();
uint8_t numbits();
bool dtr();
bool rts();
enum {
ONE_STOP_BIT = 0,
ONE_AND_HALF_STOP_BIT = 1,
TWO_STOP_BITS = 2,
};
enum {
NO_PARITY = 0,
ODD_PARITY = 1,
EVEN_PARITY = 2,
MARK_PARITY = 3,
SPACE_PARITY = 4,
};
protected:
// Implementation of the PUSBListNode
int getInterface(uint8_t* interfaceNum);
int getDescriptor(USBSetup& setup);
bool setup(USBSetup& setup);
uint8_t getShortName(char* name);
void handleEndpoint(int ep);
void enableInterrupt();
friend USBDeviceClass;
private:
int availableForStore(void);
USBDeviceClass &usb;
RingBuffer *_cdc_rx_buffer;
bool stalled;
uint32_t epType[3];
};
extern Serial_ SerialUSB;
#endif
#endif

View file

@ -76,6 +76,14 @@ bool PluggableUSB_::setup(USBSetup& setup)
return false;
}
void PluggableUSB_::handleEndpoint(int ep)
{
PluggableUSBModule* node;
for (node = rootNode; node; node = node->next) {
node->handleEndpoint(ep);
}
}
bool PluggableUSB_::plug(PluggableUSBModule *node)
{
if ((lastEp + node->numEndpoints) > USB_ENDPOINTS) {
@ -109,8 +117,8 @@ PluggableUSB_& PluggableUSB()
return obj;
}
PluggableUSB_::PluggableUSB_() : lastIf(CDC_ACM_INTERFACE + CDC_INTERFACE_COUNT),
lastEp(CDC_FIRST_ENDPOINT + CDC_ENPOINT_COUNT),
PluggableUSB_::PluggableUSB_() : lastIf(0),
lastEp(1),
rootNode(NULL)
{
// Empty

View file

@ -35,6 +35,7 @@ protected:
virtual bool setup(USBSetup& setup) = 0;
virtual int getInterface(uint8_t* interfaceCount) = 0;
virtual int getDescriptor(USBSetup& setup) = 0;
virtual void handleEndpoint(int ep) {/* Do nothing */}
virtual uint8_t getShortName(char *name) { name[0] = 'A'+pluggedInterface; return 1; }
uint8_t pluggedInterface;
@ -56,6 +57,7 @@ public:
int getInterface(uint8_t* interfaceCount);
int getDescriptor(USBSetup& setup);
bool setup(USBSetup& setup);
void handleEndpoint(int ep);
uint8_t getShortName(char *iSerialNum);
private:

View file

@ -36,7 +36,7 @@ public:
// ---------------------------
// Reset USB Device
void reset();
inline void reset();
// Enable
inline void enable() { usb.CTRLA.bit.ENABLE = 1; }
@ -79,7 +79,7 @@ public:
inline uint16_t frameNumber() { return usb.FNUM.bit.FNUM; }
// Load calibration values
void calibrate();
inline void calibrate();
// USB Device Endpoints function mapping
// -------------------------------------

View file

@ -108,76 +108,6 @@ private:
extern USBDeviceClass USBDevice;
//================================================================================
// Serial over CDC (Serial1 is the physical port)
class Serial_ : public Stream
{
public:
Serial_(USBDeviceClass &_usb) : usb(_usb), stalled(false) { }
void begin(uint32_t baud_count);
void begin(unsigned long, uint8_t);
void end(void);
virtual int available(void);
virtual int availableForWrite(void);
virtual int peek(void);
virtual int read(void);
virtual void flush(void);
virtual size_t write(uint8_t);
virtual size_t write(const uint8_t *buffer, size_t size);
using Print::write; // pull in write(str) from Print
operator bool();
size_t readBytes(char *buffer, size_t length);
// This method allows processing "SEND_BREAK" requests sent by
// the USB host. Those requests indicate that the host wants to
// send a BREAK signal and are accompanied by a single uint16_t
// value, specifying the duration of the break. The value 0
// means to end any current break, while the value 0xffff means
// to start an indefinite break.
// readBreak() will return the value of the most recent break
// request, but will return it at most once, returning -1 when
// readBreak() is called again (until another break request is
// received, which is again returned once).
// This also mean that if two break requests are received
// without readBreak() being called in between, the value of the
// first request is lost.
// Note that the value returned is a long, so it can return
// 0-0xffff as well as -1.
int32_t readBreak();
// These return the settings specified by the USB host for the
// serial port. These aren't really used, but are offered here
// in case a sketch wants to act on these settings.
uint32_t baud();
uint8_t stopbits();
uint8_t paritytype();
uint8_t numbits();
bool dtr();
bool rts();
enum {
ONE_STOP_BIT = 0,
ONE_AND_HALF_STOP_BIT = 1,
TWO_STOP_BITS = 2,
};
enum {
NO_PARITY = 0,
ODD_PARITY = 1,
EVEN_PARITY = 2,
MARK_PARITY = 3,
SPACE_PARITY = 4,
};
private:
int availableForStore(void);
USBDeviceClass &usb;
RingBuffer *_cdc_rx_buffer;
bool stalled;
};
extern Serial_ SerialUSB;
//================================================================================
//================================================================================
@ -188,15 +118,4 @@ uint32_t MSC_GetDescriptor(uint32_t i);
bool MSC_Setup(USBSetup& setup);
bool MSC_Data(uint8_t rx,uint8_t tx);
//================================================================================
//================================================================================
// CDC 'Driver'
int CDC_GetInterface(uint8_t* interfaceNum);
const void* _CDC_GetInterface(void);
uint32_t _CDC_GetInterfaceLength(void);
uint32_t CDC_GetOtherInterface(uint8_t* interfaceNum);
uint32_t CDC_GetDescriptor(uint32_t i);
bool CDC_Setup(USBSetup& setup);
#endif // __cplusplus

View file

@ -22,6 +22,7 @@
#include "SAMD21_USBDevice.h"
#include "PluggableUSB.h"
#include "CDC.h"
#include <stdlib.h>
#include <stdio.h>
@ -139,10 +140,6 @@ uint8_t USBDeviceClass::SendInterfaces(uint32_t* total)
{
uint8_t interfaces = 0;
#if defined(CDC_ENABLED)
total[0] += CDC_GetInterface(&interfaces);
#endif
#ifdef PLUGGABLE_USB_ENABLED
total[0] += PluggableUSB().getInterface(&interfaces);
#endif
@ -181,15 +178,6 @@ uint32_t USBDeviceClass::sendConfiguration(uint32_t maxlen)
return true;
}
static void utox8(uint32_t val, char* s) {
for (int i = 0; i < 8; i++) {
int d = val & 0XF;
val = (val >> 4);
s[7 - i] = d > 9 ? 'A' + d - 10 : '0' + d;
}
}
bool USBDeviceClass::sendDescriptor(USBSetup &setup)
{
uint8_t t = setup.wValueH;
@ -236,19 +224,6 @@ bool USBDeviceClass::sendDescriptor(USBSetup &setup)
char name[ISERIAL_MAX_LEN];
memset(name, 0, sizeof(name));
uint8_t idx = 0;
#ifdef CDC_ENABLED
// from section 9.3.3 of the datasheet
#define SERIAL_NUMBER_WORD_0 *(volatile uint32_t*)(0x0080A00C)
#define SERIAL_NUMBER_WORD_1 *(volatile uint32_t*)(0x0080A040)
#define SERIAL_NUMBER_WORD_2 *(volatile uint32_t*)(0x0080A044)
#define SERIAL_NUMBER_WORD_3 *(volatile uint32_t*)(0x0080A048)
utox8(SERIAL_NUMBER_WORD_0, &name[0]);
utox8(SERIAL_NUMBER_WORD_1, &name[8]);
utox8(SERIAL_NUMBER_WORD_2, &name[16]);
utox8(SERIAL_NUMBER_WORD_3, &name[24]);
idx += 32;
#endif
#ifdef PLUGGABLE_USB_ENABLED
idx += PluggableUSB().getShortName(&name[idx]);
#endif
@ -287,23 +262,8 @@ void USBDeviceClass::standby() {
void USBDeviceClass::handleEndpoint(uint8_t ep)
{
#if defined(CDC_ENABLED)
if (ep == CDC_ENDPOINT_IN)
{
// NAK on endpoint IN, the bank is not yet filled in.
usbd.epBank1ResetReady(CDC_ENDPOINT_IN);
usbd.epBank1AckTransferComplete(CDC_ENDPOINT_IN);
}
if (ep == CDC_ENDPOINT_ACM)
{
// NAK on endpoint IN, the bank is not yet filled in.
usbd.epBank1ResetReady(CDC_ENDPOINT_ACM);
usbd.epBank1AckTransferComplete(CDC_ENDPOINT_ACM);
}
#endif
#if defined(PLUGGABLE_USB_ENABLED)
// Empty
PluggableUSB().handleEndpoint(ep);
#endif
}
@ -402,25 +362,13 @@ bool USBDeviceClass::configured()
bool USBDeviceClass::handleClassInterfaceSetup(USBSetup& setup)
{
uint8_t i = setup.wIndex;
#if defined(CDC_ENABLED)
if (CDC_ACM_INTERFACE == i)
{
if (CDC_Setup(setup) == false) {
sendZlp(0);
}
return true;
}
#endif
#if defined(PLUGGABLE_USB_ENABLED)
#if defined(PLUGGABLE_USB_ENABLED)
bool ret = PluggableUSB().setup(setup);
if ( ret == false) {
sendZlp(0);
}
return ret;
#endif
#endif
return false;
}
@ -429,14 +377,11 @@ uint32_t EndPoints[] =
{
USB_ENDPOINT_TYPE_CONTROL,
#ifdef CDC_ENABLED
USB_ENDPOINT_TYPE_INTERRUPT | USB_ENDPOINT_IN(0), // CDC_ENDPOINT_ACM
USB_ENDPOINT_TYPE_BULK | USB_ENDPOINT_OUT(0), // CDC_ENDPOINT_OUT
USB_ENDPOINT_TYPE_BULK | USB_ENDPOINT_IN(0), // CDC_ENDPOINT_IN
#endif
#ifdef PLUGGABLE_USB_ENABLED
//allocate 6 endpoints and remove const so they can be changed by the user
//allocate 9 endpoints and remove const so they can be changed by the user
0,
0,
0,
0,
0,
0,
@ -844,10 +789,8 @@ bool USBDeviceClass::handleStandardSetup(USBSetup &setup)
initEndpoints();
_usbConfiguration = setup.wValueL;
#if defined(CDC_ENABLED)
// Enable interrupt for CDC reception from host (OUT packet)
usbd.epBank1EnableTransferComplete(CDC_ENDPOINT_ACM);
usbd.epBank0EnableTransferComplete(CDC_ENDPOINT_OUT);
#ifdef CDC_ENABLED
SerialUSB.enableInterrupt();
#endif
sendZlp(0);

View file

@ -104,18 +104,6 @@
#define USB_CONFIG_POWER (500)
#endif
#define CDC_V1_10 0x0110
#define CDC_COMMUNICATION_INTERFACE_CLASS 0x02
#define CDC_CALL_MANAGEMENT 0x01
#define CDC_ABSTRACT_CONTROL_MODEL 0x02
#define CDC_HEADER 0x00
#define CDC_ABSTRACT_CONTROL_MANAGEMENT 0x02
#define CDC_UNION 0x06
#define CDC_CS_INTERFACE 0x24
#define CDC_CS_ENDPOINT 0x25
#define CDC_DATA_INTERFACE_CLASS 0x0A
#define MSC_SUBCLASS_SCSI 0x06
#define MSC_PROTOCOL_BULK_ONLY 0x50
@ -192,59 +180,6 @@ typedef struct
uint8_t iInterface;
} IADDescriptor;
// CDC CS interface descriptor
typedef struct
{
uint8_t len; // 5
uint8_t dtype; // 0x24
uint8_t subtype;
uint8_t d0;
uint8_t d1;
} CDCCSInterfaceDescriptor;
typedef struct
{
uint8_t len; // 4
uint8_t dtype; // 0x24
uint8_t subtype;
uint8_t d0;
} CDCCSInterfaceDescriptor4;
typedef struct
{
uint8_t len;
uint8_t dtype; // 0x24
uint8_t subtype; // 1
uint8_t bmCapabilities;
uint8_t bDataInterface;
} CMFunctionalDescriptor;
typedef struct
{
uint8_t len;
uint8_t dtype; // 0x24
uint8_t subtype; // 1
uint8_t bmCapabilities;
} ACMFunctionalDescriptor;
typedef struct
{
// IAD
IADDescriptor iad; // Only needed on compound device
// Control
InterfaceDescriptor cif;
CDCCSInterfaceDescriptor header;
ACMFunctionalDescriptor controlManagement; // ACM
CDCCSInterfaceDescriptor functionalDescriptor; // CDC_UNION
CMFunctionalDescriptor callManagement; // Call Management
EndpointDescriptor cifin;
// Data
InterfaceDescriptor dif;
EndpointDescriptor in;
EndpointDescriptor out;
} CDCDescriptor;
typedef struct
{
InterfaceDescriptor msc;

View file

@ -28,27 +28,6 @@
#define PLUGGABLE_USB_ENABLED
#endif
#ifdef CDC_ENABLED
#define CDC_INTERFACE_COUNT 2
#define CDC_ENPOINT_COUNT 3
#else
#define CDC_INTERFACE_COUNT 0
#define CDC_ENPOINT_COUNT 0
#endif
// CDC
#define CDC_ACM_INTERFACE 0 // CDC ACM
#define CDC_DATA_INTERFACE 1 // CDC Data
#define CDC_FIRST_ENDPOINT 1
#define CDC_ENDPOINT_ACM 1
#define CDC_ENDPOINT_OUT 2
#define CDC_ENDPOINT_IN 3
#ifdef CDC_ENABLED
#define CDC_RX CDC_ENDPOINT_OUT
#define CDC_TX CDC_ENDPOINT_IN
#endif
#define ISERIAL_MAX_LEN 65
// Defined string description