Porting CDC to PluggableUSB
This commit is contained in:
parent
5c562e143d
commit
10432a3cbd
10 changed files with 287 additions and 269 deletions
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
161
cores/arduino/USB/CDC.h
Normal 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
|
||||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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
|
||||
// -------------------------------------
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
Loading…
Reference in a new issue