mirror of
https://github.com/digistump/DigistumpArduino.git
synced 2025-11-03 04:54:47 -08:00
switch to setup for Arduino Boards Manager
This commit is contained in:
301
digistump-sam/cores/digix/USB/CDC.cpp
Normal file
301
digistump-sam/cores/digix/USB/CDC.cpp
Normal file
@@ -0,0 +1,301 @@
|
||||
/* Copyright (c) 2011, Peter Barrett
|
||||
**
|
||||
** Permission to use, copy, modify, and/or distribute this software for
|
||||
** any purpose with or without fee is hereby granted, provided that the
|
||||
** above copyright notice and this permission notice appear in all copies.
|
||||
**
|
||||
** THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
|
||||
** WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
|
||||
** WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR
|
||||
** BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES
|
||||
** OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
|
||||
** WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
|
||||
** ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
|
||||
** SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "Arduino.h"
|
||||
#include "USBAPI.h"
|
||||
#include "Reset.h"
|
||||
|
||||
#ifdef CDC_ENABLED
|
||||
|
||||
#define CDC_SERIAL_BUFFER_SIZE 512
|
||||
|
||||
/* For information purpose only since RTS is not always handled by the terminal application */
|
||||
#define CDC_LINESTATE_DTR 0x01 // Data Terminal Ready
|
||||
#define CDC_LINESTATE_RTS 0x02 // Ready to Send
|
||||
|
||||
#define CDC_LINESTATE_READY (CDC_LINESTATE_RTS | CDC_LINESTATE_DTR)
|
||||
|
||||
struct ring_buffer
|
||||
{
|
||||
uint8_t buffer[CDC_SERIAL_BUFFER_SIZE];
|
||||
volatile uint32_t head;
|
||||
volatile uint32_t tail;
|
||||
};
|
||||
|
||||
ring_buffer cdc_rx_buffer = { { 0 }, 0, 0};
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint32_t dwDTERate;
|
||||
uint8_t bCharFormat;
|
||||
uint8_t bParityType;
|
||||
uint8_t bDataBits;
|
||||
uint8_t lineState;
|
||||
} LineInfo;
|
||||
|
||||
static volatile LineInfo _usbLineInfo = {
|
||||
57600, // dWDTERate
|
||||
0x00, // bCharFormat
|
||||
0x00, // bParityType
|
||||
0x08, // bDataBits
|
||||
0x00 // lineState
|
||||
};
|
||||
|
||||
_Pragma("pack(1)")
|
||||
static const CDCDescriptor _cdcInterface =
|
||||
{
|
||||
D_IAD(0,2,CDC_COMMUNICATION_INTERFACE_CLASS,CDC_ABSTRACT_CONTROL_MODEL,1),
|
||||
|
||||
// CDC communication interface
|
||||
D_INTERFACE(CDC_ACM_INTERFACE,1,CDC_COMMUNICATION_INTERFACE_CLASS,CDC_ABSTRACT_CONTROL_MODEL,0),
|
||||
D_CDCCS(CDC_HEADER,0x10,0x01), // Header (1.10 bcd)
|
||||
D_CDCCS(CDC_CALL_MANAGEMENT,1,1), // Device handles call management (not)
|
||||
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_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,512,0),
|
||||
D_ENDPOINT(USB_ENDPOINT_IN (CDC_ENDPOINT_IN ),USB_ENDPOINT_TYPE_BULK,512,0)
|
||||
};
|
||||
static const CDCDescriptor _cdcOtherInterface =
|
||||
{
|
||||
D_IAD(0,2,CDC_COMMUNICATION_INTERFACE_CLASS,CDC_ABSTRACT_CONTROL_MODEL,1),
|
||||
|
||||
// CDC communication interface
|
||||
D_INTERFACE(CDC_ACM_INTERFACE,1,CDC_COMMUNICATION_INTERFACE_CLASS,CDC_ABSTRACT_CONTROL_MODEL,0),
|
||||
D_CDCCS(CDC_HEADER,0x10,0x01), // Header (1.10 bcd)
|
||||
D_CDCCS(CDC_CALL_MANAGEMENT,1,1), // Device handles call management (not)
|
||||
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_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,64,0),
|
||||
D_ENDPOINT(USB_ENDPOINT_IN (CDC_ENDPOINT_IN ),USB_ENDPOINT_TYPE_BULK,64,0)
|
||||
};
|
||||
_Pragma("pack()")
|
||||
|
||||
int WEAK CDC_GetInterface(uint8_t* interfaceNum)
|
||||
{
|
||||
interfaceNum[0] += 2; // uses 2
|
||||
return USBD_SendControl(0,&_cdcInterface,sizeof(_cdcInterface));
|
||||
}
|
||||
|
||||
int WEAK CDC_GetOtherInterface(uint8_t* interfaceNum)
|
||||
{
|
||||
interfaceNum[0] += 2; // uses 2
|
||||
return USBD_SendControl(0,&_cdcOtherInterface,sizeof(_cdcOtherInterface));
|
||||
}
|
||||
|
||||
bool WEAK CDC_Setup(Setup& setup)
|
||||
{
|
||||
uint8_t r = setup.bRequest;
|
||||
uint8_t requestType = setup.bmRequestType;
|
||||
|
||||
if (REQUEST_DEVICETOHOST_CLASS_INTERFACE == requestType)
|
||||
{
|
||||
if (CDC_GET_LINE_CODING == r)
|
||||
{
|
||||
USBD_SendControl(0,(void*)&_usbLineInfo,7);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if (REQUEST_HOSTTODEVICE_CLASS_INTERFACE == requestType)
|
||||
{
|
||||
if (CDC_SET_LINE_CODING == r)
|
||||
{
|
||||
USBD_RecvControl((void*)&_usbLineInfo,7);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (CDC_SET_CONTROL_LINE_STATE == r)
|
||||
{
|
||||
_usbLineInfo.lineState = setup.wValueL;
|
||||
// auto-reset into the bootloader is triggered when the port, already
|
||||
// open at 1200 bps, is closed.
|
||||
if (1200 == _usbLineInfo.dwDTERate)
|
||||
{
|
||||
// We check DTR state to determine if host port is open (bit 0 of lineState).
|
||||
if ((_usbLineInfo.lineState & 0x01) == 0)
|
||||
initiateReset(250);
|
||||
else
|
||||
cancelReset();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
int _serialPeek = -1;
|
||||
void Serial_::begin(uint32_t baud_count)
|
||||
{
|
||||
}
|
||||
|
||||
void Serial_::begin(uint32_t baud_count, uint8_t config)
|
||||
{
|
||||
}
|
||||
|
||||
void Serial_::end(void)
|
||||
{
|
||||
}
|
||||
|
||||
void Serial_::accept(void)
|
||||
{
|
||||
static uint32_t guard = 0;
|
||||
|
||||
// synchronized access to guard
|
||||
do {
|
||||
if (__LDREXW(&guard) != 0) {
|
||||
__CLREX();
|
||||
return; // busy
|
||||
}
|
||||
} while (__STREXW(1, &guard) != 0); // retry until write succeed
|
||||
|
||||
ring_buffer *buffer = &cdc_rx_buffer;
|
||||
uint32_t i = (uint32_t)(buffer->head+1) % CDC_SERIAL_BUFFER_SIZE;
|
||||
|
||||
// if we should be storing the received character into the location
|
||||
// just before the tail (meaning that the head would advance to the
|
||||
// current location of the tail), we're about to overflow the buffer
|
||||
// and so we don't write the character or advance the head.
|
||||
while (i != buffer->tail) {
|
||||
uint32_t c;
|
||||
if (!USBD_Available(CDC_RX)) {
|
||||
udd_ack_fifocon(CDC_RX);
|
||||
break;
|
||||
}
|
||||
c = USBD_Recv(CDC_RX);
|
||||
// c = UDD_Recv8(CDC_RX & 0xF);
|
||||
buffer->buffer[buffer->head] = c;
|
||||
buffer->head = i;
|
||||
|
||||
i = (i + 1) % CDC_SERIAL_BUFFER_SIZE;
|
||||
}
|
||||
|
||||
// release the guard
|
||||
guard = 0;
|
||||
}
|
||||
|
||||
int Serial_::available(void)
|
||||
{
|
||||
ring_buffer *buffer = &cdc_rx_buffer;
|
||||
return (unsigned int)(CDC_SERIAL_BUFFER_SIZE + buffer->head - buffer->tail) % CDC_SERIAL_BUFFER_SIZE;
|
||||
}
|
||||
|
||||
int Serial_::peek(void)
|
||||
{
|
||||
ring_buffer *buffer = &cdc_rx_buffer;
|
||||
|
||||
if (buffer->head == buffer->tail)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
return buffer->buffer[buffer->tail];
|
||||
}
|
||||
}
|
||||
|
||||
int Serial_::read(void)
|
||||
{
|
||||
ring_buffer *buffer = &cdc_rx_buffer;
|
||||
|
||||
// if the head isn't ahead of the tail, we don't have any characters
|
||||
if (buffer->head == buffer->tail)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
unsigned char c = buffer->buffer[buffer->tail];
|
||||
buffer->tail = (unsigned int)(buffer->tail + 1) % CDC_SERIAL_BUFFER_SIZE;
|
||||
if (USBD_Available(CDC_RX))
|
||||
accept();
|
||||
return c;
|
||||
}
|
||||
}
|
||||
|
||||
void Serial_::flush(void)
|
||||
{
|
||||
USBD_Flush(CDC_TX);
|
||||
}
|
||||
|
||||
size_t Serial_::write(const uint8_t *buffer, size_t size)
|
||||
{
|
||||
/* only try to send bytes if the high-level CDC connection itself
|
||||
is open (not just the pipe) - the OS should set lineState when the port
|
||||
is opened and clear lineState when the port is closed.
|
||||
bytes sent before the user opens the connection or after
|
||||
the connection is closed are lost - just like with a UART. */
|
||||
|
||||
// TODO - ZE - check behavior on different OSes and test what happens if an
|
||||
// open connection isn't broken cleanly (cable is yanked out, host dies
|
||||
// or locks up, or host virtual serial port hangs)
|
||||
if (_usbLineInfo.lineState > 0)
|
||||
{
|
||||
int r = USBD_Send(CDC_TX, buffer, size);
|
||||
|
||||
if (r > 0)
|
||||
{
|
||||
return r;
|
||||
} else
|
||||
{
|
||||
setWriteError();
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
setWriteError();
|
||||
return 0;
|
||||
}
|
||||
|
||||
size_t Serial_::write(uint8_t c) {
|
||||
return write(&c, 1);
|
||||
}
|
||||
|
||||
// This operator is a convenient way for a sketch to check whether the
|
||||
// port has actually been configured and opened by the host (as opposed
|
||||
// to just being connected to the host). It can be used, for example, in
|
||||
// setup() before printing to ensure that an application on the host is
|
||||
// actually ready to receive and display the data.
|
||||
// We add a short delay before returning to fix a bug observed by Federico
|
||||
// where the port is configured (lineState != 0) but not quite opened.
|
||||
Serial_::operator bool()
|
||||
{
|
||||
// this is here to avoid spurious opening after upload
|
||||
if (millis() < 500)
|
||||
return false;
|
||||
|
||||
bool result = false;
|
||||
|
||||
if (_usbLineInfo.lineState > 0)
|
||||
{
|
||||
result = true;
|
||||
}
|
||||
|
||||
delay(10);
|
||||
return result;
|
||||
}
|
||||
|
||||
Serial_ SerialUSB;
|
||||
Serial_ Serial;
|
||||
|
||||
|
||||
#endif
|
||||
518
digistump-sam/cores/digix/USB/HID.cpp
Normal file
518
digistump-sam/cores/digix/USB/HID.cpp
Normal file
@@ -0,0 +1,518 @@
|
||||
/* Copyright (c) 2011, Peter Barrett
|
||||
**
|
||||
** Permission to use, copy, modify, and/or distribute this software for
|
||||
** any purpose with or without fee is hereby granted, provided that the
|
||||
** above copyright notice and this permission notice appear in all copies.
|
||||
**
|
||||
** THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
|
||||
** WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
|
||||
** WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR
|
||||
** BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES
|
||||
** OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
|
||||
** WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
|
||||
** ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
|
||||
** SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "Arduino.h"
|
||||
|
||||
#ifdef HID_ENABLED
|
||||
|
||||
//#define RAWHID_ENABLED
|
||||
|
||||
// Singletons for mouse and keyboard
|
||||
|
||||
Mouse_ Mouse;
|
||||
Keyboard_ Keyboard;
|
||||
|
||||
//================================================================================
|
||||
//================================================================================
|
||||
|
||||
// HID report descriptor
|
||||
|
||||
#define LSB(_x) ((_x) & 0xFF)
|
||||
#define MSB(_x) ((_x) >> 8)
|
||||
|
||||
#define RAWHID_USAGE_PAGE 0xFFC0
|
||||
#define RAWHID_USAGE 0x0C00
|
||||
#define RAWHID_TX_SIZE 64
|
||||
#define RAWHID_RX_SIZE 64
|
||||
|
||||
extern const uint8_t _hidReportDescriptor[] = {
|
||||
// Mouse
|
||||
0x05, 0x01, // USAGE_PAGE (Generic Desktop) // 54
|
||||
0x09, 0x02, // USAGE (Mouse)
|
||||
0xa1, 0x01, // COLLECTION (Application)
|
||||
0x09, 0x01, // USAGE (Pointer)
|
||||
0xa1, 0x00, // COLLECTION (Physical)
|
||||
0x85, 0x01, // REPORT_ID (1)
|
||||
0x05, 0x09, // USAGE_PAGE (Button)
|
||||
0x19, 0x01, // USAGE_MINIMUM (Button 1)
|
||||
0x29, 0x03, // USAGE_MAXIMUM (Button 3)
|
||||
0x15, 0x00, // LOGICAL_MINIMUM (0)
|
||||
0x25, 0x01, // LOGICAL_MAXIMUM (1)
|
||||
0x95, 0x03, // REPORT_COUNT (3)
|
||||
0x75, 0x01, // REPORT_SIZE (1)
|
||||
0x81, 0x02, // INPUT (Data,Var,Abs)
|
||||
0x95, 0x01, // REPORT_COUNT (1)
|
||||
0x75, 0x05, // REPORT_SIZE (5)
|
||||
0x81, 0x03, // INPUT (Cnst,Var,Abs)
|
||||
0x05, 0x01, // USAGE_PAGE (Generic Desktop)
|
||||
0x09, 0x30, // USAGE (X)
|
||||
0x09, 0x31, // USAGE (Y)
|
||||
0x09, 0x38, // USAGE (Wheel)
|
||||
0x15, 0x81, // LOGICAL_MINIMUM (-127)
|
||||
0x25, 0x7f, // LOGICAL_MAXIMUM (127)
|
||||
0x75, 0x08, // REPORT_SIZE (8)
|
||||
0x95, 0x03, // REPORT_COUNT (3)
|
||||
0x81, 0x06, // INPUT (Data,Var,Rel)
|
||||
0xc0, // END_COLLECTION
|
||||
0xc0, // END_COLLECTION
|
||||
|
||||
// Keyboard
|
||||
0x05, 0x01, // USAGE_PAGE (Generic Desktop) // 47
|
||||
0x09, 0x06, // USAGE (Keyboard)
|
||||
0xa1, 0x01, // COLLECTION (Application)
|
||||
0x85, 0x02, // REPORT_ID (2)
|
||||
0x05, 0x07, // USAGE_PAGE (Keyboard)
|
||||
|
||||
0x19, 0xe0, // USAGE_MINIMUM (Keyboard LeftControl)
|
||||
0x29, 0xe7, // USAGE_MAXIMUM (Keyboard Right GUI)
|
||||
0x15, 0x00, // LOGICAL_MINIMUM (0)
|
||||
0x25, 0x01, // LOGICAL_MAXIMUM (1)
|
||||
0x75, 0x01, // REPORT_SIZE (1)
|
||||
|
||||
0x95, 0x08, // REPORT_COUNT (8)
|
||||
0x81, 0x02, // INPUT (Data,Var,Abs)
|
||||
0x95, 0x01, // REPORT_COUNT (1)
|
||||
0x75, 0x08, // REPORT_SIZE (8)
|
||||
0x81, 0x03, // INPUT (Cnst,Var,Abs)
|
||||
|
||||
0x95, 0x06, // REPORT_COUNT (6)
|
||||
0x75, 0x08, // REPORT_SIZE (8)
|
||||
0x15, 0x00, // LOGICAL_MINIMUM (0)
|
||||
0x25, 0x65, // LOGICAL_MAXIMUM (101)
|
||||
0x05, 0x07, // USAGE_PAGE (Keyboard)
|
||||
|
||||
0x19, 0x00, // USAGE_MINIMUM (Reserved (no event indicated))
|
||||
0x29, 0x65, // USAGE_MAXIMUM (Keyboard Application)
|
||||
0x81, 0x00, // INPUT (Data,Ary,Abs)
|
||||
0xc0, // END_COLLECTION
|
||||
|
||||
#ifdef RAWHID_ENABLED
|
||||
// RAW HID
|
||||
0x06, LSB(RAWHID_USAGE_PAGE), MSB(RAWHID_USAGE_PAGE), // 30
|
||||
0x0A, LSB(RAWHID_USAGE), MSB(RAWHID_USAGE),
|
||||
|
||||
0xA1, 0x01, // Collection 0x01
|
||||
0x85, 0x03, // REPORT_ID (3)
|
||||
0x75, 0x08, // report size = 8 bits
|
||||
0x15, 0x00, // logical minimum = 0
|
||||
0x26, 0xFF, 0x00, // logical maximum = 255
|
||||
|
||||
0x95, 64, // report count TX
|
||||
0x09, 0x01, // usage
|
||||
0x81, 0x02, // Input (array)
|
||||
|
||||
0x95, 64, // report count RX
|
||||
0x09, 0x02, // usage
|
||||
0x91, 0x02, // Output (array)
|
||||
0xC0 // end collection
|
||||
#endif
|
||||
};
|
||||
|
||||
_Pragma("pack(1)")
|
||||
extern const HIDDescriptor _hidInterface =
|
||||
{
|
||||
D_INTERFACE(HID_INTERFACE,1,3,0,0),
|
||||
D_HIDREPORT(sizeof(_hidReportDescriptor)),
|
||||
D_ENDPOINT(USB_ENDPOINT_IN(HID_ENDPOINT_INT),USB_ENDPOINT_TYPE_INTERRUPT,0x40,0x01)
|
||||
};
|
||||
_Pragma("pack()")
|
||||
|
||||
//================================================================================
|
||||
//================================================================================
|
||||
// Driver
|
||||
|
||||
uint8_t _hid_protocol = 1;
|
||||
uint8_t _hid_idle = 1;
|
||||
|
||||
#define WEAK __attribute__ ((weak))
|
||||
|
||||
int WEAK HID_GetInterface(uint8_t* interfaceNum)
|
||||
{
|
||||
interfaceNum[0] += 1; // uses 1
|
||||
return USBD_SendControl(0,&_hidInterface,sizeof(_hidInterface));
|
||||
}
|
||||
|
||||
int WEAK HID_GetDescriptor(int i)
|
||||
{
|
||||
return USBD_SendControl(0,_hidReportDescriptor,sizeof(_hidReportDescriptor));
|
||||
}
|
||||
|
||||
void WEAK HID_SendReport(uint8_t id, const void* data, uint32_t len)
|
||||
{
|
||||
uint8_t p[64];
|
||||
const uint8_t *d = reinterpret_cast<const uint8_t *>(data);
|
||||
|
||||
p[0] = id;
|
||||
for (uint32_t i=0; i<len; i++)
|
||||
p[i+1] = d[i];
|
||||
USBD_Send(HID_TX, p, len+1);
|
||||
}
|
||||
|
||||
bool WEAK HID_Setup(Setup& setup)
|
||||
{
|
||||
uint8_t r = setup.bRequest;
|
||||
uint8_t requestType = setup.bmRequestType;
|
||||
|
||||
if (REQUEST_DEVICETOHOST_CLASS_INTERFACE == requestType)
|
||||
{
|
||||
if (HID_GET_REPORT == r)
|
||||
{
|
||||
//HID_GetReport();
|
||||
return true;
|
||||
}
|
||||
if (HID_GET_PROTOCOL == r)
|
||||
{
|
||||
//Send8(_hid_protocol); // TODO
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if (REQUEST_HOSTTODEVICE_CLASS_INTERFACE == requestType)
|
||||
{
|
||||
if (HID_SET_PROTOCOL == r)
|
||||
{
|
||||
_hid_protocol = setup.wValueL;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (HID_SET_IDLE == r)
|
||||
{
|
||||
_hid_idle = setup.wValueL;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
//================================================================================
|
||||
//================================================================================
|
||||
// Mouse
|
||||
|
||||
Mouse_::Mouse_(void) : _buttons(0)
|
||||
{
|
||||
}
|
||||
|
||||
void Mouse_::begin(void)
|
||||
{
|
||||
}
|
||||
|
||||
void Mouse_::end(void)
|
||||
{
|
||||
}
|
||||
|
||||
void Mouse_::click(uint8_t b)
|
||||
{
|
||||
_buttons = b;
|
||||
move(0,0,0);
|
||||
_buttons = 0;
|
||||
move(0,0,0);
|
||||
}
|
||||
|
||||
void Mouse_::move(signed char x, signed char y, signed char wheel)
|
||||
{
|
||||
uint8_t m[4];
|
||||
m[0] = _buttons;
|
||||
m[1] = x;
|
||||
m[2] = y;
|
||||
m[3] = wheel;
|
||||
HID_SendReport(1,m,4);
|
||||
}
|
||||
|
||||
void Mouse_::buttons(uint8_t b)
|
||||
{
|
||||
if (b != _buttons)
|
||||
{
|
||||
_buttons = b;
|
||||
move(0,0,0);
|
||||
}
|
||||
}
|
||||
|
||||
void Mouse_::press(uint8_t b)
|
||||
{
|
||||
buttons(_buttons | b);
|
||||
}
|
||||
|
||||
void Mouse_::release(uint8_t b)
|
||||
{
|
||||
buttons(_buttons & ~b);
|
||||
}
|
||||
|
||||
bool Mouse_::isPressed(uint8_t b)
|
||||
{
|
||||
if ((b & _buttons) > 0)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
//================================================================================
|
||||
//================================================================================
|
||||
// Keyboard
|
||||
|
||||
Keyboard_::Keyboard_(void)
|
||||
{
|
||||
}
|
||||
|
||||
void Keyboard_::begin(void)
|
||||
{
|
||||
}
|
||||
|
||||
void Keyboard_::end(void)
|
||||
{
|
||||
}
|
||||
|
||||
void Keyboard_::sendReport(KeyReport* keys)
|
||||
{
|
||||
HID_SendReport(2,keys,sizeof(KeyReport));
|
||||
}
|
||||
|
||||
#define SHIFT 0x80
|
||||
extern const uint8_t _asciimap[128] =
|
||||
{
|
||||
0x00, // NUL
|
||||
0x00, // SOH
|
||||
0x00, // STX
|
||||
0x00, // ETX
|
||||
0x00, // EOT
|
||||
0x00, // ENQ
|
||||
0x00, // ACK
|
||||
0x00, // BEL
|
||||
0x2a, // BS Backspace
|
||||
0x2b, // TAB Tab
|
||||
0x28, // LF Enter
|
||||
0x00, // VT
|
||||
0x00, // FF
|
||||
0x00, // CR
|
||||
0x00, // SO
|
||||
0x00, // SI
|
||||
0x00, // DEL
|
||||
0x00, // DC1
|
||||
0x00, // DC2
|
||||
0x00, // DC3
|
||||
0x00, // DC4
|
||||
0x00, // NAK
|
||||
0x00, // SYN
|
||||
0x00, // ETB
|
||||
0x00, // CAN
|
||||
0x00, // EM
|
||||
0x00, // SUB
|
||||
0x00, // ESC
|
||||
0x00, // FS
|
||||
0x00, // GS
|
||||
0x00, // RS
|
||||
0x00, // US
|
||||
|
||||
0x2c, // ' '
|
||||
0x1e|SHIFT, // !
|
||||
0x34|SHIFT, // "
|
||||
0x20|SHIFT, // #
|
||||
0x21|SHIFT, // $
|
||||
0x22|SHIFT, // %
|
||||
0x24|SHIFT, // &
|
||||
0x34, // '
|
||||
0x26|SHIFT, // (
|
||||
0x27|SHIFT, // )
|
||||
0x25|SHIFT, // *
|
||||
0x2e|SHIFT, // +
|
||||
0x36, // ,
|
||||
0x2d, // -
|
||||
0x37, // .
|
||||
0x38, // /
|
||||
0x27, // 0
|
||||
0x1e, // 1
|
||||
0x1f, // 2
|
||||
0x20, // 3
|
||||
0x21, // 4
|
||||
0x22, // 5
|
||||
0x23, // 6
|
||||
0x24, // 7
|
||||
0x25, // 8
|
||||
0x26, // 9
|
||||
0x33|SHIFT, // :
|
||||
0x33, // ;
|
||||
0x36|SHIFT, // <
|
||||
0x2e, // =
|
||||
0x37|SHIFT, // >
|
||||
0x38|SHIFT, // ?
|
||||
0x1f|SHIFT, // @
|
||||
0x04|SHIFT, // A
|
||||
0x05|SHIFT, // B
|
||||
0x06|SHIFT, // C
|
||||
0x07|SHIFT, // D
|
||||
0x08|SHIFT, // E
|
||||
0x09|SHIFT, // F
|
||||
0x0a|SHIFT, // G
|
||||
0x0b|SHIFT, // H
|
||||
0x0c|SHIFT, // I
|
||||
0x0d|SHIFT, // J
|
||||
0x0e|SHIFT, // K
|
||||
0x0f|SHIFT, // L
|
||||
0x10|SHIFT, // M
|
||||
0x11|SHIFT, // N
|
||||
0x12|SHIFT, // O
|
||||
0x13|SHIFT, // P
|
||||
0x14|SHIFT, // Q
|
||||
0x15|SHIFT, // R
|
||||
0x16|SHIFT, // S
|
||||
0x17|SHIFT, // T
|
||||
0x18|SHIFT, // U
|
||||
0x19|SHIFT, // V
|
||||
0x1a|SHIFT, // W
|
||||
0x1b|SHIFT, // X
|
||||
0x1c|SHIFT, // Y
|
||||
0x1d|SHIFT, // Z
|
||||
0x2f, // [
|
||||
0x31, // bslash
|
||||
0x30, // ]
|
||||
0x23|SHIFT, // ^
|
||||
0x2d|SHIFT, // _
|
||||
0x35, // `
|
||||
0x04, // a
|
||||
0x05, // b
|
||||
0x06, // c
|
||||
0x07, // d
|
||||
0x08, // e
|
||||
0x09, // f
|
||||
0x0a, // g
|
||||
0x0b, // h
|
||||
0x0c, // i
|
||||
0x0d, // j
|
||||
0x0e, // k
|
||||
0x0f, // l
|
||||
0x10, // m
|
||||
0x11, // n
|
||||
0x12, // o
|
||||
0x13, // p
|
||||
0x14, // q
|
||||
0x15, // r
|
||||
0x16, // s
|
||||
0x17, // t
|
||||
0x18, // u
|
||||
0x19, // v
|
||||
0x1a, // w
|
||||
0x1b, // x
|
||||
0x1c, // y
|
||||
0x1d, // z
|
||||
0x2f|SHIFT, //
|
||||
0x31|SHIFT, // |
|
||||
0x30|SHIFT, // }
|
||||
0x35|SHIFT, // ~
|
||||
0 // DEL
|
||||
};
|
||||
|
||||
uint8_t USBPutChar(uint8_t c);
|
||||
|
||||
// press() adds the specified key (printing, non-printing, or modifier)
|
||||
// to the persistent key report and sends the report. Because of the way
|
||||
// USB HID works, the host acts like the key remains pressed until we
|
||||
// call release(), releaseAll(), or otherwise clear the report and resend.
|
||||
size_t Keyboard_::press(uint8_t k)
|
||||
{
|
||||
uint8_t i;
|
||||
if (k >= 136) { // it's a non-printing key (not a modifier)
|
||||
k = k - 136;
|
||||
} else if (k >= 128) { // it's a modifier key
|
||||
_keyReport.modifiers |= (1<<(k-128));
|
||||
k = 0;
|
||||
} else { // it's a printing key
|
||||
k = _asciimap[k];
|
||||
if (!k) {
|
||||
setWriteError();
|
||||
return 0;
|
||||
}
|
||||
if (k & 0x80) { // it's a capital letter or other character reached with shift
|
||||
_keyReport.modifiers |= 0x02; // the left shift modifier
|
||||
k &= 0x7F;
|
||||
}
|
||||
}
|
||||
|
||||
// Add k to the key report only if it's not already present
|
||||
// and if there is an empty slot.
|
||||
if (_keyReport.keys[0] != k && _keyReport.keys[1] != k &&
|
||||
_keyReport.keys[2] != k && _keyReport.keys[3] != k &&
|
||||
_keyReport.keys[4] != k && _keyReport.keys[5] != k) {
|
||||
|
||||
for (i=0; i<6; i++) {
|
||||
if (_keyReport.keys[i] == 0x00) {
|
||||
_keyReport.keys[i] = k;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (i == 6) {
|
||||
setWriteError();
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
sendReport(&_keyReport);
|
||||
return 1;
|
||||
}
|
||||
|
||||
// release() takes the specified key out of the persistent key report and
|
||||
// sends the report. This tells the OS the key is no longer pressed and that
|
||||
// it shouldn't be repeated any more.
|
||||
size_t Keyboard_::release(uint8_t k)
|
||||
{
|
||||
uint8_t i;
|
||||
if (k >= 136) { // it's a non-printing key (not a modifier)
|
||||
k = k - 136;
|
||||
} else if (k >= 128) { // it's a modifier key
|
||||
_keyReport.modifiers &= ~(1<<(k-128));
|
||||
k = 0;
|
||||
} else { // it's a printing key
|
||||
k = _asciimap[k];
|
||||
if (!k) {
|
||||
return 0;
|
||||
}
|
||||
if (k & 0x80) { // it's a capital letter or other character reached with shift
|
||||
_keyReport.modifiers &= ~(0x02); // the left shift modifier
|
||||
k &= 0x7F;
|
||||
}
|
||||
}
|
||||
|
||||
// Test the key report to see if k is present. Clear it if it exists.
|
||||
// Check all positions in case the key is present more than once (which it shouldn't be)
|
||||
for (i=0; i<6; i++) {
|
||||
if (0 != k && _keyReport.keys[i] == k) {
|
||||
_keyReport.keys[i] = 0x00;
|
||||
}
|
||||
}
|
||||
|
||||
sendReport(&_keyReport);
|
||||
return 1;
|
||||
}
|
||||
|
||||
void Keyboard_::releaseAll(void)
|
||||
{
|
||||
_keyReport.keys[0] = 0;
|
||||
_keyReport.keys[1] = 0;
|
||||
_keyReport.keys[2] = 0;
|
||||
_keyReport.keys[3] = 0;
|
||||
_keyReport.keys[4] = 0;
|
||||
_keyReport.keys[5] = 0;
|
||||
_keyReport.modifiers = 0;
|
||||
sendReport(&_keyReport);
|
||||
}
|
||||
|
||||
size_t Keyboard_::write(uint8_t c)
|
||||
{
|
||||
uint8_t p = 0;
|
||||
|
||||
p = press(c); // Keydown
|
||||
release(c); // Keyup
|
||||
|
||||
return (p); // Just return the result of press() since release() almost always returns 1
|
||||
}
|
||||
|
||||
#endif
|
||||
222
digistump-sam/cores/digix/USB/USBAPI.h
Normal file
222
digistump-sam/cores/digix/USB/USBAPI.h
Normal file
@@ -0,0 +1,222 @@
|
||||
/*
|
||||
Copyright (c) 2012 Arduino. All right reserved.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef __USBAPI__
|
||||
#define __USBAPI__
|
||||
|
||||
#if defined __cplusplus
|
||||
|
||||
#include "RingBuffer.h"
|
||||
|
||||
//================================================================================
|
||||
//================================================================================
|
||||
// USB
|
||||
|
||||
class USBDevice_
|
||||
{
|
||||
public:
|
||||
USBDevice_();
|
||||
bool configured();
|
||||
|
||||
bool attach();
|
||||
bool detach(); // Serial port goes down too...
|
||||
void poll();
|
||||
};
|
||||
extern USBDevice_ USBDevice;
|
||||
|
||||
//================================================================================
|
||||
//================================================================================
|
||||
// Serial over CDC (Serial1 is the physical port)
|
||||
|
||||
class Serial_ : public Stream
|
||||
{
|
||||
private:
|
||||
RingBuffer *_cdc_rx_buffer;
|
||||
public:
|
||||
void begin(uint32_t baud_count);
|
||||
void begin(uint32_t baud_count, uint8_t config);
|
||||
void end(void);
|
||||
|
||||
virtual int available(void);
|
||||
virtual void accept(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();
|
||||
};
|
||||
extern Serial_ SerialUSB;
|
||||
extern Serial_ Serial;
|
||||
|
||||
//================================================================================
|
||||
//================================================================================
|
||||
// Mouse
|
||||
|
||||
#define MOUSE_LEFT 1
|
||||
#define MOUSE_RIGHT 2
|
||||
#define MOUSE_MIDDLE 4
|
||||
#define MOUSE_ALL (MOUSE_LEFT | MOUSE_RIGHT | MOUSE_MIDDLE)
|
||||
|
||||
class Mouse_
|
||||
{
|
||||
private:
|
||||
uint8_t _buttons;
|
||||
void buttons(uint8_t b);
|
||||
public:
|
||||
Mouse_(void);
|
||||
void begin(void);
|
||||
void end(void);
|
||||
void click(uint8_t b = MOUSE_LEFT);
|
||||
void move(signed char x, signed char y, signed char wheel = 0);
|
||||
void press(uint8_t b = MOUSE_LEFT); // press LEFT by default
|
||||
void release(uint8_t b = MOUSE_LEFT); // release LEFT by default
|
||||
bool isPressed(uint8_t b = MOUSE_ALL); // check all buttons by default
|
||||
};
|
||||
extern Mouse_ Mouse;
|
||||
|
||||
//================================================================================
|
||||
//================================================================================
|
||||
// Keyboard
|
||||
|
||||
#define KEY_LEFT_CTRL 0x80
|
||||
#define KEY_LEFT_SHIFT 0x81
|
||||
#define KEY_LEFT_ALT 0x82
|
||||
#define KEY_LEFT_GUI 0x83
|
||||
#define KEY_RIGHT_CTRL 0x84
|
||||
#define KEY_RIGHT_SHIFT 0x85
|
||||
#define KEY_RIGHT_ALT 0x86
|
||||
#define KEY_RIGHT_GUI 0x87
|
||||
|
||||
#define KEY_UP_ARROW 0xDA
|
||||
#define KEY_DOWN_ARROW 0xD9
|
||||
#define KEY_LEFT_ARROW 0xD8
|
||||
#define KEY_RIGHT_ARROW 0xD7
|
||||
#define KEY_BACKSPACE 0xB2
|
||||
#define KEY_TAB 0xB3
|
||||
#define KEY_RETURN 0xB0
|
||||
#define KEY_ESC 0xB1
|
||||
#define KEY_INSERT 0xD1
|
||||
#define KEY_DELETE 0xD4
|
||||
#define KEY_PAGE_UP 0xD3
|
||||
#define KEY_PAGE_DOWN 0xD6
|
||||
#define KEY_HOME 0xD2
|
||||
#define KEY_END 0xD5
|
||||
#define KEY_CAPS_LOCK 0xC1
|
||||
#define KEY_F1 0xC2
|
||||
#define KEY_F2 0xC3
|
||||
#define KEY_F3 0xC4
|
||||
#define KEY_F4 0xC5
|
||||
#define KEY_F5 0xC6
|
||||
#define KEY_F6 0xC7
|
||||
#define KEY_F7 0xC8
|
||||
#define KEY_F8 0xC9
|
||||
#define KEY_F9 0xCA
|
||||
#define KEY_F10 0xCB
|
||||
#define KEY_F11 0xCC
|
||||
#define KEY_F12 0xCD
|
||||
|
||||
// Low level key report: up to 6 keys and shift, ctrl etc at once
|
||||
typedef struct
|
||||
{
|
||||
uint8_t modifiers;
|
||||
uint8_t reserved;
|
||||
uint8_t keys[6];
|
||||
} KeyReport;
|
||||
|
||||
class Keyboard_ : public Print
|
||||
{
|
||||
private:
|
||||
KeyReport _keyReport;
|
||||
void sendReport(KeyReport* keys);
|
||||
public:
|
||||
Keyboard_(void);
|
||||
void begin(void);
|
||||
void end(void);
|
||||
virtual size_t write(uint8_t k);
|
||||
virtual size_t press(uint8_t k);
|
||||
virtual size_t release(uint8_t k);
|
||||
virtual void releaseAll(void);
|
||||
};
|
||||
extern Keyboard_ Keyboard;
|
||||
|
||||
//================================================================================
|
||||
//================================================================================
|
||||
// Low level API
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint8_t bmRequestType;
|
||||
uint8_t bRequest;
|
||||
uint8_t wValueL;
|
||||
uint8_t wValueH;
|
||||
uint16_t wIndex;
|
||||
uint16_t wLength;
|
||||
} Setup;
|
||||
|
||||
//================================================================================
|
||||
//================================================================================
|
||||
// HID 'Driver'
|
||||
|
||||
int HID_GetInterface(uint8_t* interfaceNum);
|
||||
int HID_GetDescriptor(int i);
|
||||
bool HID_Setup(Setup& setup);
|
||||
void HID_SendReport(uint8_t id, const void* data, uint32_t len);
|
||||
|
||||
//================================================================================
|
||||
//================================================================================
|
||||
// MSC 'Driver'
|
||||
|
||||
int MSC_GetInterface(uint8_t* interfaceNum);
|
||||
int MSC_GetDescriptor(int i);
|
||||
bool MSC_Setup(Setup& setup);
|
||||
bool MSC_Data(uint8_t rx,uint8_t tx);
|
||||
|
||||
//================================================================================
|
||||
//================================================================================
|
||||
// CSC 'Driver'
|
||||
|
||||
int CDC_GetInterface(uint8_t* interfaceNum);
|
||||
int CDC_GetOtherInterface(uint8_t* interfaceNum);
|
||||
int CDC_GetDescriptor(int i);
|
||||
bool CDC_Setup(Setup& setup);
|
||||
|
||||
//================================================================================
|
||||
//================================================================================
|
||||
|
||||
#define TRANSFER_RELEASE 0x40
|
||||
#define TRANSFER_ZERO 0x20
|
||||
|
||||
void USBD_InitControl(int end);
|
||||
int USBD_SendControl(uint8_t flags, const void* d, uint32_t len);
|
||||
int USBD_RecvControl(void* d, uint32_t len);
|
||||
int USBD_SendInterfaces(void);
|
||||
bool USBD_ClassInterfaceRequest(Setup& setup);
|
||||
|
||||
|
||||
uint32_t USBD_Available(uint32_t ep);
|
||||
uint32_t USBD_SendSpace(uint32_t ep);
|
||||
uint32_t USBD_Send(uint32_t ep, const void* d, uint32_t len);
|
||||
uint32_t USBD_Recv(uint32_t ep, void* data, uint32_t len); // non-blocking
|
||||
uint32_t USBD_Recv(uint32_t ep); // non-blocking
|
||||
void USBD_Flush(uint32_t ep);
|
||||
uint32_t USBD_Connected(void);
|
||||
|
||||
#endif
|
||||
#endif
|
||||
882
digistump-sam/cores/digix/USB/USBCore.cpp
Normal file
882
digistump-sam/cores/digix/USB/USBCore.cpp
Normal file
@@ -0,0 +1,882 @@
|
||||
// Copyright (c) 2010, Peter Barrett
|
||||
/*
|
||||
** Permission to use, copy, modify, and/or distribute this software for
|
||||
** any purpose with or without fee is hereby granted, provided that the
|
||||
** above copyright notice and this permission notice appear in all copies.
|
||||
**
|
||||
** THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
|
||||
** WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
|
||||
** WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR
|
||||
** BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES
|
||||
** OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
|
||||
** WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
|
||||
** ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
|
||||
** SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "Arduino.h"
|
||||
#include "USBAPI.h"
|
||||
#include "Reset.h"
|
||||
#include <stdio.h>
|
||||
|
||||
//#define TRACE_CORE(x) x
|
||||
#define TRACE_CORE(x)
|
||||
|
||||
static const uint32_t EndPoints[] =
|
||||
{
|
||||
EP_TYPE_CONTROL,
|
||||
|
||||
#ifdef CDC_ENABLED
|
||||
EP_TYPE_INTERRUPT_IN, // CDC_ENDPOINT_ACM
|
||||
EP_TYPE_BULK_OUT, // CDC_ENDPOINT_OUT
|
||||
EP_TYPE_BULK_IN, // CDC_ENDPOINT_IN
|
||||
#endif
|
||||
|
||||
#ifdef HID_ENABLED
|
||||
EP_TYPE_INTERRUPT_IN_HID // HID_ENDPOINT_INT
|
||||
#endif
|
||||
};
|
||||
|
||||
/** Pulse generation counters to keep track of the number of milliseconds remaining for each pulse type */
|
||||
#define TX_RX_LED_PULSE_MS 100
|
||||
volatile uint8_t TxLEDPulse; /**< Milliseconds remaining for data Tx LED pulse */
|
||||
volatile uint8_t RxLEDPulse; /**< Milliseconds remaining for data Rx LED pulse */
|
||||
static char isRemoteWakeUpEnabled = 0;
|
||||
static char isEndpointHalt = 0;
|
||||
//==================================================================
|
||||
//==================================================================
|
||||
|
||||
extern const uint16_t STRING_LANGUAGE[];
|
||||
extern const uint8_t STRING_PRODUCT[];
|
||||
extern const uint8_t STRING_MANUFACTURER[];
|
||||
extern const DeviceDescriptor USB_DeviceDescriptor;
|
||||
extern const DeviceDescriptor USB_DeviceDescriptorA;
|
||||
|
||||
const uint16_t STRING_LANGUAGE[2] = {
|
||||
(3<<8) | (2+2),
|
||||
0x0409 // English
|
||||
};
|
||||
|
||||
#ifndef USB_PRODUCT
|
||||
// Use a hardcoded product name if none is provided
|
||||
#if USB_PID == USB_PID_DUE
|
||||
#define USB_PRODUCT "Arduino Due"
|
||||
#elif USB_PID == USB_PID_DIGIX
|
||||
#define USB_PRODUCT "Digistump DigiX"
|
||||
#else
|
||||
#define USB_PRODUCT "USB IO Board"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
const uint8_t STRING_PRODUCT[] = USB_PRODUCT;
|
||||
|
||||
|
||||
#define USB_MANUFACTURER "Digistump"
|
||||
|
||||
|
||||
const uint8_t STRING_MANUFACTURER[12] = USB_MANUFACTURER;
|
||||
|
||||
#ifdef CDC_ENABLED
|
||||
#define DEVICE_CLASS 0x02
|
||||
#else
|
||||
#define DEVICE_CLASS 0x00
|
||||
#endif
|
||||
|
||||
// DEVICE DESCRIPTOR
|
||||
const DeviceDescriptor USB_DeviceDescriptor =
|
||||
D_DEVICE(0x00,0x00,0x00,64,USB_VID_DIGIX,USB_PID,0x100,IMANUFACTURER,IPRODUCT,0,1);
|
||||
|
||||
const DeviceDescriptor USB_DeviceDescriptorA =
|
||||
D_DEVICE(DEVICE_CLASS,0x00,0x00,64,USB_VID_DIGIX,USB_PID,0x100,IMANUFACTURER,IPRODUCT,0,1);
|
||||
|
||||
const DeviceDescriptor USB_DeviceQualifier =
|
||||
D_QUALIFIER(0x00,0x00,0x00,64,1);
|
||||
|
||||
//! 7.1.20 Test Mode Support
|
||||
static const unsigned char test_packet_buffer[] = {
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // JKJKJKJK * 9
|
||||
0xAA,0xAA,0xAA,0xAA,0xAA,0xAA,0xAA,0xAA, // JJKKJJKK * 8
|
||||
0xEE,0xEE,0xEE,0xEE,0xEE,0xEE,0xEE,0xEE, // JJJJKKKK * 8
|
||||
0xFE,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, // JJJJJJJKKKKKKK * 8
|
||||
0x7F,0xBF,0xDF,0xEF,0xF7,0xFB,0xFD, // JJJJJJJK * 8
|
||||
0xFC,0x7E,0xBF,0xDF,0xEF,0xF7,0xFB,0xFD,0x7E // {JKKKKKKK * 10}, JK
|
||||
};
|
||||
|
||||
//==================================================================
|
||||
//==================================================================
|
||||
|
||||
volatile uint32_t _usbConfiguration = 0;
|
||||
volatile uint32_t _usbInitialized = 0;
|
||||
uint32_t _usbSetInterface = 0;
|
||||
uint32_t _cdcComposite = 0;
|
||||
|
||||
//==================================================================
|
||||
//==================================================================
|
||||
|
||||
#define USB_RECV_TIMEOUT
|
||||
class LockEP
|
||||
{
|
||||
irqflags_t flags;
|
||||
public:
|
||||
LockEP(uint32_t ep) : flags(cpu_irq_save())
|
||||
{
|
||||
}
|
||||
~LockEP()
|
||||
{
|
||||
cpu_irq_restore(flags);
|
||||
}
|
||||
};
|
||||
|
||||
// Number of bytes, assumes a rx endpoint
|
||||
uint32_t USBD_Available(uint32_t ep)
|
||||
{
|
||||
LockEP lock(ep);
|
||||
return UDD_FifoByteCount(ep & 0xF);
|
||||
}
|
||||
|
||||
// Non Blocking receive
|
||||
// Return number of bytes read
|
||||
uint32_t USBD_Recv(uint32_t ep, void* d, uint32_t len)
|
||||
{
|
||||
if (!_usbConfiguration || len < 0)
|
||||
return -1;
|
||||
|
||||
LockEP lock(ep);
|
||||
uint32_t n = UDD_FifoByteCount(ep & 0xF);
|
||||
len = min(n,len);
|
||||
n = len;
|
||||
uint8_t* dst = (uint8_t*)d;
|
||||
while (n--)
|
||||
*dst++ = UDD_Recv8(ep & 0xF);
|
||||
if (len && !UDD_FifoByteCount(ep & 0xF)) // release empty buffer
|
||||
UDD_ReleaseRX(ep & 0xF);
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
// Recv 1 byte if ready
|
||||
uint32_t USBD_Recv(uint32_t ep)
|
||||
{
|
||||
uint8_t c;
|
||||
if (USBD_Recv(ep & 0xF, &c, 1) != 1)
|
||||
return -1;
|
||||
else
|
||||
return c;
|
||||
}
|
||||
|
||||
// Space in send EP
|
||||
//uint32_t USBD_SendSpace(uint32_t ep)
|
||||
//{
|
||||
//LockEP lock(ep);
|
||||
//// if (!UDD_ReadWriteAllowed(ep & 0xF))
|
||||
////{
|
||||
////printf("pb "); // UOTGHS->UOTGHS_DEVEPTISR[%d]=0x%X\n\r", ep, UOTGHS->UOTGHS_DEVEPTISR[ep]);
|
||||
////return 0;
|
||||
////}
|
||||
|
||||
//if(ep==0) return 64 - UDD_FifoByteCount(ep & 0xF); // EP0_SIZE jcb
|
||||
//else return 512 - UDD_FifoByteCount(ep & 0xF); // EPX_SIZE jcb
|
||||
//}
|
||||
|
||||
// Blocking Send of data to an endpoint
|
||||
uint32_t USBD_Send(uint32_t ep, const void* d, uint32_t len)
|
||||
{
|
||||
uint32_t n;
|
||||
int r = len;
|
||||
const uint8_t* data = (const uint8_t*)d;
|
||||
|
||||
if (!_usbConfiguration)
|
||||
{
|
||||
TRACE_CORE(printf("pb conf\n\r");)
|
||||
return -1;
|
||||
}
|
||||
|
||||
while (len)
|
||||
{
|
||||
if(ep==0) n = EP0_SIZE;
|
||||
else n = EPX_SIZE;
|
||||
if (n > len)
|
||||
n = len;
|
||||
len -= n;
|
||||
|
||||
UDD_Send(ep & 0xF, data, n);
|
||||
data += n;
|
||||
}
|
||||
//TXLED1; // light the TX LED
|
||||
//TxLEDPulse = TX_RX_LED_PULSE_MS;
|
||||
return r;
|
||||
}
|
||||
|
||||
int _cmark;
|
||||
int _cend;
|
||||
|
||||
void USBD_InitControl(int end)
|
||||
{
|
||||
_cmark = 0;
|
||||
_cend = end;
|
||||
}
|
||||
|
||||
// Clipped by _cmark/_cend
|
||||
int USBD_SendControl(uint8_t flags, const void* d, uint32_t len)
|
||||
{
|
||||
const uint8_t* data = (const uint8_t*)d;
|
||||
uint32_t length = len;
|
||||
uint32_t sent = 0;
|
||||
uint32_t pos = 0;
|
||||
|
||||
TRACE_CORE(printf("=> USBD_SendControl TOTAL len=%lu\r\n", len);)
|
||||
|
||||
if (_cmark < _cend)
|
||||
{
|
||||
while (len > 0)
|
||||
{
|
||||
sent = UDD_Send(EP0, data + pos, len);
|
||||
TRACE_CORE(printf("=> USBD_SendControl sent=%lu\r\n", sent);)
|
||||
pos += sent;
|
||||
len -= sent;
|
||||
}
|
||||
}
|
||||
|
||||
_cmark += length;
|
||||
|
||||
return length;
|
||||
}
|
||||
|
||||
// Send a USB descriptor string. The string is stored as a
|
||||
// plain ASCII string but is sent out as UTF-16 with the
|
||||
// correct 2-byte prefix
|
||||
static bool USB_SendStringDescriptor(const uint8_t *string, int wLength) {
|
||||
uint16_t buff[64];
|
||||
int l = 1;
|
||||
wLength-=2;
|
||||
while (*string && wLength>0) {
|
||||
buff[l++] = (uint8_t)(*string++);
|
||||
wLength-=2;
|
||||
}
|
||||
buff[0] = (3<<8) | (l*2);
|
||||
return USBD_SendControl(0, (uint8_t*)buff, l*2);
|
||||
}
|
||||
|
||||
// Does not timeout or cross fifo boundaries
|
||||
// Will only work for transfers <= 64 bytes
|
||||
// TODO
|
||||
int USBD_RecvControl(void* d, uint32_t len)
|
||||
{
|
||||
UDD_WaitOUT();
|
||||
UDD_Recv(EP0, (uint8_t*)d, len);
|
||||
UDD_ClearOUT();
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
// Handle CLASS_INTERFACE requests
|
||||
bool USBD_ClassInterfaceRequest(Setup& setup)
|
||||
{
|
||||
uint8_t i = setup.wIndex;
|
||||
|
||||
TRACE_CORE(printf("=> USBD_ClassInterfaceRequest\r\n");)
|
||||
|
||||
#ifdef CDC_ENABLED
|
||||
if (CDC_ACM_INTERFACE == i)
|
||||
{
|
||||
return CDC_Setup(setup);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef HID_ENABLED
|
||||
if (HID_INTERFACE == i)
|
||||
{
|
||||
return HID_Setup(setup);
|
||||
}
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
int USBD_SendInterfaces(void)
|
||||
{
|
||||
int total = 0;
|
||||
uint8_t interfaces = 0;
|
||||
|
||||
#ifdef CDC_ENABLED
|
||||
total = CDC_GetInterface(&interfaces);
|
||||
#endif
|
||||
|
||||
#ifdef HID_ENABLED
|
||||
total += HID_GetInterface(&interfaces);
|
||||
#endif
|
||||
|
||||
total = total; // Get rid of compiler warning
|
||||
TRACE_CORE(printf("=> USBD_SendInterfaces, total=%d interfaces=%d\r\n", total, interfaces);)
|
||||
return interfaces;
|
||||
}
|
||||
|
||||
int USBD_SendOtherInterfaces(void)
|
||||
{
|
||||
int total = 0;
|
||||
uint8_t interfaces = 0;
|
||||
|
||||
#ifdef CDC_ENABLED
|
||||
total = CDC_GetOtherInterface(&interfaces);
|
||||
#endif
|
||||
|
||||
#ifdef HID_ENABLED
|
||||
total += HID_GetInterface(&interfaces);
|
||||
#endif
|
||||
|
||||
total = total; // Get rid of compiler warning
|
||||
TRACE_CORE(printf("=> USBD_SendInterfaces, total=%d interfaces=%d\r\n", total, interfaces);)
|
||||
return interfaces;
|
||||
}
|
||||
|
||||
// Construct a dynamic configuration descriptor
|
||||
// This really needs dynamic endpoint allocation etc
|
||||
// TODO
|
||||
static bool USBD_SendConfiguration(int maxlen)
|
||||
{
|
||||
// Count and measure interfaces
|
||||
USBD_InitControl(0);
|
||||
//TRACE_CORE(printf("=> USBD_SendConfiguration _cmark1=%d\r\n", _cmark);)
|
||||
int interfaces = USBD_SendInterfaces();
|
||||
//TRACE_CORE(printf("=> USBD_SendConfiguration _cmark2=%d\r\n", _cmark);)
|
||||
//TRACE_CORE(printf("=> USBD_SendConfiguration sizeof=%d\r\n", sizeof(ConfigDescriptor));)
|
||||
|
||||
_Pragma("pack(1)")
|
||||
ConfigDescriptor config = D_CONFIG(_cmark + sizeof(ConfigDescriptor),interfaces);
|
||||
_Pragma("pack()")
|
||||
//TRACE_CORE(printf("=> USBD_SendConfiguration clen=%d\r\n", config.clen);)
|
||||
|
||||
//TRACE_CORE(printf("=> USBD_SendConfiguration maxlen=%d\r\n", maxlen);)
|
||||
|
||||
// Now send them
|
||||
USBD_InitControl(maxlen);
|
||||
USBD_SendControl(0,&config,sizeof(ConfigDescriptor));
|
||||
USBD_SendInterfaces();
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool USBD_SendOtherConfiguration(int maxlen)
|
||||
{
|
||||
// Count and measure interfaces
|
||||
USBD_InitControl(0);
|
||||
//TRACE_CORE(printf("=> USBD_SendConfiguration _cmark1=%d\r\n", _cmark);)
|
||||
int interfaces = USBD_SendOtherInterfaces();
|
||||
//TRACE_CORE(printf("=> USBD_SendConfiguration _cmark2=%d\r\n", _cmark);)
|
||||
//TRACE_CORE(printf("=> USBD_SendConfiguration sizeof=%d\r\n", sizeof(ConfigDescriptor));)
|
||||
|
||||
_Pragma("pack(1)")
|
||||
ConfigDescriptor config = D_OTHERCONFIG(_cmark + sizeof(ConfigDescriptor),interfaces);
|
||||
_Pragma("pack()")
|
||||
//TRACE_CORE(printf("=> USBD_SendConfiguration clen=%d\r\n", config.clen);)
|
||||
|
||||
//TRACE_CORE(printf("=> USBD_SendConfiguration maxlen=%d\r\n", maxlen);)
|
||||
|
||||
// Now send them
|
||||
USBD_InitControl(maxlen);
|
||||
USBD_SendControl(0,&config,sizeof(ConfigDescriptor));
|
||||
USBD_SendOtherInterfaces();
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool USBD_SendDescriptor(Setup& setup)
|
||||
{
|
||||
uint8_t t = setup.wValueH;
|
||||
uint8_t desc_length = 0;
|
||||
const uint8_t* desc_addr = 0;
|
||||
|
||||
if (USB_CONFIGURATION_DESCRIPTOR_TYPE == t)
|
||||
{
|
||||
TRACE_CORE(printf("=> USBD_SendDescriptor : USB_CONFIGURATION_DESCRIPTOR_TYPE length=%d\r\n", setup.wLength);)
|
||||
return USBD_SendConfiguration(setup.wLength);
|
||||
}
|
||||
|
||||
USBD_InitControl(setup.wLength);
|
||||
#ifdef HID_ENABLED
|
||||
if (HID_REPORT_DESCRIPTOR_TYPE == t)
|
||||
{
|
||||
TRACE_CORE(puts("=> USBD_SendDescriptor : HID_REPORT_DESCRIPTOR_TYPE\r\n");)
|
||||
return HID_GetDescriptor(t);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (USB_DEVICE_DESCRIPTOR_TYPE == t)
|
||||
{
|
||||
TRACE_CORE(puts("=> USBD_SendDescriptor : USB_DEVICE_DESCRIPTOR_TYPE\r\n");)
|
||||
if (setup.wLength == 8)
|
||||
{
|
||||
_cdcComposite = 1;
|
||||
}
|
||||
desc_addr = _cdcComposite ? (const uint8_t*)&USB_DeviceDescriptorA : (const uint8_t*)&USB_DeviceDescriptor;
|
||||
if( *desc_addr > setup.wLength ) {
|
||||
desc_length = setup.wLength;
|
||||
}
|
||||
}
|
||||
else if (USB_STRING_DESCRIPTOR_TYPE == t)
|
||||
{
|
||||
TRACE_CORE(puts("=> USBD_SendDescriptor : USB_STRING_DESCRIPTOR_TYPE\r\n");)
|
||||
if (setup.wValueL == 0) {
|
||||
desc_addr = (const uint8_t*)&STRING_LANGUAGE;
|
||||
}
|
||||
else if (setup.wValueL == IPRODUCT) {
|
||||
return USB_SendStringDescriptor(STRING_PRODUCT, setup.wLength);
|
||||
}
|
||||
else if (setup.wValueL == IMANUFACTURER) {
|
||||
return USB_SendStringDescriptor(STRING_MANUFACTURER, setup.wLength);
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
if( *desc_addr > setup.wLength ) {
|
||||
desc_length = setup.wLength;
|
||||
}
|
||||
}
|
||||
else if (USB_DEVICE_QUALIFIER == t)
|
||||
{
|
||||
// Device qualifier descriptor requested
|
||||
desc_addr = (const uint8_t*)&USB_DeviceQualifier;
|
||||
if( *desc_addr > setup.wLength ) {
|
||||
desc_length = setup.wLength;
|
||||
}
|
||||
}
|
||||
else if (USB_OTHER_SPEED_CONFIGURATION == t)
|
||||
{
|
||||
// Other configuration descriptor requested
|
||||
return USBD_SendOtherConfiguration(setup.wLength);
|
||||
}
|
||||
else
|
||||
{
|
||||
//printf("Device ERROR");
|
||||
}
|
||||
|
||||
if (desc_addr == 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (desc_length == 0)
|
||||
{
|
||||
desc_length = *desc_addr;
|
||||
}
|
||||
|
||||
TRACE_CORE(printf("=> USBD_SendDescriptor : desc_addr=%p desc_length=%d\r\n", desc_addr, desc_length);)
|
||||
USBD_SendControl(0, desc_addr, desc_length);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
static void USB_SendZlp( void )
|
||||
{
|
||||
while( UOTGHS_DEVEPTISR_TXINI != (UOTGHS->UOTGHS_DEVEPTISR[0] & UOTGHS_DEVEPTISR_TXINI ) )
|
||||
{
|
||||
if((UOTGHS->UOTGHS_DEVISR & UOTGHS_DEVISR_SUSP) == UOTGHS_DEVISR_SUSP)
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
UOTGHS->UOTGHS_DEVEPTICR[0] = UOTGHS_DEVEPTICR_TXINIC;
|
||||
}
|
||||
|
||||
|
||||
static void Test_Mode_Support( uint8_t wIndex )
|
||||
{
|
||||
uint8_t i;
|
||||
uint8_t *ptr_dest = (uint8_t *) &udd_get_endpoint_fifo_access8(2);
|
||||
|
||||
switch( wIndex )
|
||||
{
|
||||
case 4:
|
||||
//Test mode Test_Packet:
|
||||
//Upon command, a port must repetitively transmit the following test packet until
|
||||
//the exit action is taken. This enables the testing of rise and fall times, eye
|
||||
//patterns, jitter, and any other dynamic waveform specifications.
|
||||
//The test packet is made up by concatenating the following strings.
|
||||
//(Note: For J/K NRZI data, and for NRZ data, the bit on the left is the first one
|
||||
//transmitted. "S" indicates that a bit stuff occurs, which inserts an "extra" NRZI data bit.
|
||||
//"* N" is used to indicate N occurrences of a string of bits or symbols.)
|
||||
//A port in Test_Packet mode must send this packet repetitively. The inter-packet timing
|
||||
//must be no less than the minimum allowable inter-packet gap as defined in Section 7.1.18 and
|
||||
//no greater than 125 us.
|
||||
|
||||
// Send ZLP
|
||||
USB_SendZlp();
|
||||
|
||||
UOTGHS->UOTGHS_DEVDMA[0].UOTGHS_DEVDMACONTROL = 0; // raz
|
||||
UOTGHS->UOTGHS_DEVDMA[1].UOTGHS_DEVDMACONTROL = 0; // raz
|
||||
|
||||
// Configure endpoint 2, 64 bytes, direction IN, type BULK, 1 bank
|
||||
UOTGHS->UOTGHS_DEVEPTCFG[2] = UOTGHS_DEVEPTCFG_EPSIZE_64_BYTE
|
||||
| UOTGHS_DEVEPTCFG_EPDIR_IN
|
||||
| UOTGHS_DEVEPTCFG_EPTYPE_BLK
|
||||
| UOTGHS_DEVEPTCFG_EPBK_1_BANK;
|
||||
// Check if the configuration is ok
|
||||
UOTGHS->UOTGHS_DEVEPTCFG[2] |= UOTGHS_DEVEPTCFG_ALLOC;
|
||||
while((UOTGHS->UOTGHS_DEVEPTISR[2]&UOTGHS_DEVEPTISR_CFGOK)==0) {}
|
||||
UOTGHS->UOTGHS_DEVEPT |= UOTGHS_DEVEPT_EPEN2;
|
||||
// Write FIFO
|
||||
for( i=0; i<sizeof(test_packet_buffer); i++)
|
||||
{
|
||||
ptr_dest[i] = test_packet_buffer[i];;
|
||||
}
|
||||
// Tst PACKET
|
||||
UOTGHS->UOTGHS_DEVCTRL |= UOTGHS_DEVCTRL_TSTPCKT;
|
||||
// Send packet
|
||||
UOTGHS->UOTGHS_DEVEPTICR[2] = UOTGHS_DEVEPTICR_TXINIC;
|
||||
UOTGHS->UOTGHS_DEVEPTIDR[2] = UOTGHS_DEVEPTIDR_FIFOCONC;
|
||||
for(;;);
|
||||
// break;
|
||||
|
||||
case 1:
|
||||
//Test mode Test_J:
|
||||
//Upon command, a port's transceiver must enter the high-speed J state and remain in that
|
||||
//state until the exit action is taken. This enables the testing of the high output drive
|
||||
//level on the D+ line.
|
||||
// Send a ZLP
|
||||
USB_SendZlp();
|
||||
UOTGHS->UOTGHS_DEVCTRL |= UOTGHS_DEVCTRL_TSTJ;
|
||||
for(;;);
|
||||
// break;
|
||||
|
||||
case 2:
|
||||
//Test mode Test_K:
|
||||
//Upon command, a port's transceiver must enter the high-speed K state and remain in
|
||||
//that state until the exit action is taken. This enables the testing of the high output drive
|
||||
//level on the D- line.
|
||||
// Send a ZLP
|
||||
USB_SendZlp();
|
||||
UOTGHS->UOTGHS_DEVCTRL |= UOTGHS_DEVCTRL_TSTK;
|
||||
for(;;);
|
||||
// break;
|
||||
|
||||
case 3:
|
||||
//Test mode Test_SE0_NAK:
|
||||
//Upon command, a port's transceiver must enter the high-speed receive mode
|
||||
//and remain in that mode until the exit action is taken. This enables the testing
|
||||
//of output impedance, low level output voltage, and loading characteristics.
|
||||
//In addition, while in this mode, upstream facing ports (and only upstream facing ports)
|
||||
//must respond to any IN token packet with a NAK handshake (only if the packet CRC is
|
||||
//determined to be correct) within the normal allowed device response time. This enables testing of
|
||||
//the device squelch level circuitry and, additionally, provides a general purpose stimulus/response
|
||||
//test for basic functional testing.
|
||||
|
||||
// Send a ZLP
|
||||
USB_SendZlp();
|
||||
UOTGHS->UOTGHS_DEVIDR = UOTGHS_DEVIDR_SUSPEC
|
||||
| UOTGHS_DEVIDR_MSOFEC
|
||||
| UOTGHS_DEVIDR_SOFEC
|
||||
| UOTGHS_DEVIDR_EORSTEC
|
||||
| UOTGHS_DEVIDR_WAKEUPEC
|
||||
| UOTGHS_DEVIDR_EORSMEC
|
||||
| UOTGHS_DEVIDR_UPRSMEC
|
||||
| UOTGHS_DEVIDR_PEP_0
|
||||
| UOTGHS_DEVIDR_PEP_1
|
||||
| UOTGHS_DEVIDR_PEP_2
|
||||
| UOTGHS_DEVIDR_PEP_3
|
||||
| UOTGHS_DEVIDR_PEP_4
|
||||
| UOTGHS_DEVIDR_PEP_5
|
||||
| UOTGHS_DEVIDR_PEP_6
|
||||
| UOTGHS_DEVIDR_DMA_1
|
||||
| UOTGHS_DEVIDR_DMA_2
|
||||
| UOTGHS_DEVIDR_DMA_3
|
||||
| UOTGHS_DEVIDR_DMA_4
|
||||
| UOTGHS_DEVIDR_DMA_5
|
||||
| UOTGHS_DEVIDR_DMA_6;
|
||||
for(;;);
|
||||
// break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//unsigned int iii=0;
|
||||
// Endpoint 0 interrupt
|
||||
static void USB_ISR(void)
|
||||
{
|
||||
// printf("ISR=0x%X\n\r", UOTGHS->UOTGHS_DEVISR); // jcb
|
||||
// if( iii++ > 1500 ) while(1); // jcb
|
||||
// End of bus reset
|
||||
if (Is_udd_reset())
|
||||
{
|
||||
TRACE_CORE(printf(">>> End of Reset\r\n");)
|
||||
|
||||
// Reset USB address to 0
|
||||
udd_configure_address(0);
|
||||
udd_enable_address();
|
||||
|
||||
// Configure EP 0
|
||||
UDD_InitEP(0, EP_TYPE_CONTROL);
|
||||
udd_enable_setup_received_interrupt(0);
|
||||
udd_enable_endpoint_interrupt(0);
|
||||
|
||||
_usbConfiguration = 0;
|
||||
udd_ack_reset();
|
||||
}
|
||||
|
||||
#ifdef CDC_ENABLED
|
||||
if (Is_udd_endpoint_interrupt(CDC_RX))
|
||||
{
|
||||
udd_ack_out_received(CDC_RX);
|
||||
|
||||
// Handle received bytes
|
||||
if (USBD_Available(CDC_RX))
|
||||
SerialUSB.accept();
|
||||
}
|
||||
|
||||
if (Is_udd_sof())
|
||||
{
|
||||
udd_ack_sof();
|
||||
// USBD_Flush(CDC_TX); // jcb
|
||||
}
|
||||
#endif
|
||||
|
||||
// EP 0 Interrupt
|
||||
if (Is_udd_endpoint_interrupt(0) )
|
||||
{
|
||||
if (!UDD_ReceivedSetupInt())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Setup setup;
|
||||
UDD_Recv(EP0, (uint8_t*)&setup, 8);
|
||||
UDD_ClearSetupInt();
|
||||
|
||||
uint8_t requestType = setup.bmRequestType;
|
||||
if (requestType & REQUEST_DEVICETOHOST)
|
||||
{
|
||||
TRACE_CORE(puts(">>> EP0 Int: IN Request\r\n");)
|
||||
UDD_WaitIN();
|
||||
}
|
||||
else
|
||||
{
|
||||
TRACE_CORE(puts(">>> EP0 Int: OUT Request\r\n");)
|
||||
UDD_ClearIN();
|
||||
}
|
||||
|
||||
bool ok = true;
|
||||
if (REQUEST_STANDARD == (requestType & REQUEST_TYPE))
|
||||
{
|
||||
// Standard Requests
|
||||
uint8_t r = setup.bRequest;
|
||||
if (GET_STATUS == r)
|
||||
{
|
||||
if( setup.bmRequestType == 0 ) // device
|
||||
{
|
||||
// Send the device status
|
||||
TRACE_CORE(puts(">>> EP0 Int: GET_STATUS\r\n");)
|
||||
// Check current configuration for power mode (if device is configured)
|
||||
// TODO
|
||||
// Check if remote wake-up is enabled
|
||||
// TODO
|
||||
UDD_Send8(EP0, 0); // TODO
|
||||
UDD_Send8(EP0, 0);
|
||||
}
|
||||
// if( setup.bmRequestType == 2 ) // Endpoint:
|
||||
else
|
||||
{
|
||||
// Send the endpoint status
|
||||
// Check if the endpoint if currently halted
|
||||
if( isEndpointHalt == 1 )
|
||||
UDD_Send8(EP0, 1); // TODO
|
||||
else
|
||||
UDD_Send8(EP0, 0); // TODO
|
||||
UDD_Send8(EP0, 0);
|
||||
}
|
||||
}
|
||||
else if (CLEAR_FEATURE == r)
|
||||
{
|
||||
// Check which is the selected feature
|
||||
if( setup.wValueL == 1) // DEVICEREMOTEWAKEUP
|
||||
{
|
||||
// Enable remote wake-up and send a ZLP
|
||||
if( isRemoteWakeUpEnabled == 1 )
|
||||
UDD_Send8(EP0, 1);
|
||||
else
|
||||
UDD_Send8(EP0, 0);
|
||||
UDD_Send8(EP0, 0);
|
||||
}
|
||||
else // if( setup.wValueL == 0) // ENDPOINTHALT
|
||||
{
|
||||
isEndpointHalt = 0; // TODO
|
||||
UDD_Send8(EP0, 0);
|
||||
UDD_Send8(EP0, 0);
|
||||
}
|
||||
|
||||
}
|
||||
else if (SET_FEATURE == r)
|
||||
{
|
||||
// Check which is the selected feature
|
||||
if( setup.wValueL == 1) // DEVICEREMOTEWAKEUP
|
||||
{
|
||||
// Enable remote wake-up and send a ZLP
|
||||
isRemoteWakeUpEnabled = 1;
|
||||
UDD_Send8(EP0, 0);
|
||||
}
|
||||
if( setup.wValueL == 0) // ENDPOINTHALT
|
||||
{
|
||||
// Halt endpoint
|
||||
isEndpointHalt = 1;
|
||||
//USBD_Halt(USBGenericRequest_GetEndpointNumber(pRequest));
|
||||
UDD_Send8(EP0, 0);
|
||||
}
|
||||
if( setup.wValueL == 2) // TEST_MODE
|
||||
{
|
||||
// 7.1.20 Test Mode Support, 9.4.9 SetFeature
|
||||
if( (setup.bmRequestType == 0 /*USBGenericRequest_DEVICE*/) &&
|
||||
((setup.wIndex & 0x000F) == 0) )
|
||||
{
|
||||
// the lower byte of wIndex must be zero
|
||||
// the most significant byte of wIndex is used to specify the specific test mode
|
||||
|
||||
UOTGHS->UOTGHS_DEVIDR &= ~UOTGHS_DEVIDR_SUSPEC;
|
||||
UOTGHS->UOTGHS_DEVCTRL |= UOTGHS_DEVCTRL_SPDCONF_HIGH_SPEED; // remove suspend ?
|
||||
|
||||
Test_Mode_Support( (setup.wIndex & 0xFF00)>>8 );
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (SET_ADDRESS == r)
|
||||
{
|
||||
TRACE_CORE(puts(">>> EP0 Int: SET_ADDRESS\r\n");)
|
||||
UDD_WaitIN();
|
||||
UDD_SetAddress(setup.wValueL);
|
||||
}
|
||||
else if (GET_DESCRIPTOR == r)
|
||||
{
|
||||
TRACE_CORE(puts(">>> EP0 Int: GET_DESCRIPTOR\r\n");)
|
||||
ok = USBD_SendDescriptor(setup);
|
||||
}
|
||||
else if (SET_DESCRIPTOR == r)
|
||||
{
|
||||
TRACE_CORE(puts(">>> EP0 Int: SET_DESCRIPTOR\r\n");)
|
||||
ok = false;
|
||||
}
|
||||
else if (GET_CONFIGURATION == r)
|
||||
{
|
||||
TRACE_CORE(puts(">>> EP0 Int: GET_CONFIGURATION\r\n");)
|
||||
UDD_Send8(EP0, _usbConfiguration);
|
||||
}
|
||||
else if (SET_CONFIGURATION == r)
|
||||
{
|
||||
if (REQUEST_DEVICE == (requestType & REQUEST_RECIPIENT))
|
||||
{
|
||||
TRACE_CORE(printf(">>> EP0 Int: SET_CONFIGURATION REQUEST_DEVICE %d\r\n", setup.wValueL);)
|
||||
|
||||
UDD_InitEndpoints(EndPoints, (sizeof(EndPoints) / sizeof(EndPoints[0])));
|
||||
_usbConfiguration = setup.wValueL;
|
||||
|
||||
#ifdef CDC_ENABLED
|
||||
// Enable interrupt for CDC reception from host (OUT packet)
|
||||
udd_enable_out_received_interrupt(CDC_RX);
|
||||
udd_enable_endpoint_interrupt(CDC_RX);
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
TRACE_CORE(puts(">>> EP0 Int: SET_CONFIGURATION failed!\r\n");)
|
||||
ok = false;
|
||||
}
|
||||
}
|
||||
else if (GET_INTERFACE == r)
|
||||
{
|
||||
TRACE_CORE(puts(">>> EP0 Int: GET_INTERFACE\r\n");)
|
||||
UDD_Send8(EP0, _usbSetInterface);
|
||||
}
|
||||
else if (SET_INTERFACE == r)
|
||||
{
|
||||
_usbSetInterface = setup.wValueL;
|
||||
TRACE_CORE(puts(">>> EP0 Int: SET_INTERFACE\r\n");)
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
TRACE_CORE(puts(">>> EP0 Int: ClassInterfaceRequest\r\n");)
|
||||
|
||||
UDD_WaitIN(); // Workaround: need tempo here, else CDC serial won't open correctly
|
||||
|
||||
USBD_InitControl(setup.wLength); // Max length of transfer
|
||||
ok = USBD_ClassInterfaceRequest(setup);
|
||||
}
|
||||
|
||||
if (ok)
|
||||
{
|
||||
TRACE_CORE(puts(">>> EP0 Int: Send packet\r\n");)
|
||||
UDD_ClearIN();
|
||||
}
|
||||
else
|
||||
{
|
||||
TRACE_CORE(puts(">>> EP0 Int: Stall\r\n");)
|
||||
UDD_Stall();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void USBD_Flush(uint32_t ep)
|
||||
{
|
||||
if (UDD_FifoByteCount(ep))
|
||||
UDD_ReleaseTX(ep);
|
||||
}
|
||||
|
||||
// VBUS or counting frames
|
||||
// Any frame counting?
|
||||
uint32_t USBD_Connected(void)
|
||||
{
|
||||
uint8_t f = UDD_GetFrameNumber();
|
||||
|
||||
delay(3);
|
||||
|
||||
return f != UDD_GetFrameNumber();
|
||||
}
|
||||
|
||||
|
||||
//=======================================================================
|
||||
//=======================================================================
|
||||
|
||||
USBDevice_ USBDevice;
|
||||
|
||||
USBDevice_::USBDevice_()
|
||||
{
|
||||
UDD_SetStack(&USB_ISR);
|
||||
|
||||
if (UDD_Init() == 0UL)
|
||||
{
|
||||
_usbInitialized=1UL;
|
||||
}
|
||||
}
|
||||
|
||||
bool USBDevice_::attach(void)
|
||||
{
|
||||
if (_usbInitialized != 0UL)
|
||||
{
|
||||
UDD_Attach();
|
||||
_usbConfiguration = 0;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool USBDevice_::detach(void)
|
||||
{
|
||||
if (_usbInitialized != 0UL)
|
||||
{
|
||||
UDD_Detach();
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Check for interrupts
|
||||
// TODO: VBUS detection
|
||||
bool USBDevice_::configured()
|
||||
{
|
||||
return _usbConfiguration;
|
||||
}
|
||||
|
||||
void USBDevice_::poll()
|
||||
{
|
||||
}
|
||||
311
digistump-sam/cores/digix/USB/USBCore.h
Normal file
311
digistump-sam/cores/digix/USB/USBCore.h
Normal file
@@ -0,0 +1,311 @@
|
||||
// Copyright (c) 2010, Peter Barrett
|
||||
/*
|
||||
** Permission to use, copy, modify, and/or distribute this software for
|
||||
** any purpose with or without fee is hereby granted, provided that the
|
||||
** above copyright notice and this permission notice appear in all copies.
|
||||
**
|
||||
** THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
|
||||
** WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
|
||||
** WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR
|
||||
** BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES
|
||||
** OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
|
||||
** WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
|
||||
** ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
|
||||
** SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef __USBCORE_H__
|
||||
#define __USBCORE_H__
|
||||
|
||||
// Standard requests
|
||||
#define GET_STATUS 0
|
||||
#define CLEAR_FEATURE 1
|
||||
#define SET_FEATURE 3
|
||||
#define SET_ADDRESS 5
|
||||
#define GET_DESCRIPTOR 6
|
||||
#define SET_DESCRIPTOR 7
|
||||
#define GET_CONFIGURATION 8
|
||||
#define SET_CONFIGURATION 9
|
||||
#define GET_INTERFACE 10
|
||||
#define SET_INTERFACE 11
|
||||
|
||||
|
||||
// bmRequestType
|
||||
#define REQUEST_HOSTTODEVICE 0x00
|
||||
#define REQUEST_DEVICETOHOST 0x80
|
||||
#define REQUEST_DIRECTION 0x80
|
||||
|
||||
#define REQUEST_STANDARD 0x00
|
||||
#define REQUEST_CLASS 0x20
|
||||
#define REQUEST_VENDOR 0x40
|
||||
#define REQUEST_TYPE 0x60
|
||||
|
||||
#define REQUEST_DEVICE 0x00
|
||||
#define REQUEST_INTERFACE 0x01
|
||||
#define REQUEST_ENDPOINT 0x02
|
||||
#define REQUEST_OTHER 0x03
|
||||
#define REQUEST_RECIPIENT 0x1F
|
||||
|
||||
#define REQUEST_DEVICETOHOST_CLASS_INTERFACE (REQUEST_DEVICETOHOST + REQUEST_CLASS + REQUEST_INTERFACE)
|
||||
#define REQUEST_HOSTTODEVICE_CLASS_INTERFACE (REQUEST_HOSTTODEVICE + REQUEST_CLASS + REQUEST_INTERFACE)
|
||||
|
||||
// Class requests
|
||||
|
||||
#define CDC_SET_LINE_CODING 0x20
|
||||
#define CDC_GET_LINE_CODING 0x21
|
||||
#define CDC_SET_CONTROL_LINE_STATE 0x22
|
||||
|
||||
#define MSC_RESET 0xFF
|
||||
#define MSC_GET_MAX_LUN 0xFE
|
||||
|
||||
#define HID_GET_REPORT 0x01
|
||||
#define HID_GET_IDLE 0x02
|
||||
#define HID_GET_PROTOCOL 0x03
|
||||
#define HID_SET_REPORT 0x09
|
||||
#define HID_SET_IDLE 0x0A
|
||||
#define HID_SET_PROTOCOL 0x0B
|
||||
|
||||
// Descriptors
|
||||
|
||||
#define USB_DEVICE_DESC_SIZE 18
|
||||
#define USB_CONFIGUARTION_DESC_SIZE 9
|
||||
#define USB_INTERFACE_DESC_SIZE 9
|
||||
#define USB_ENDPOINT_DESC_SIZE 7
|
||||
|
||||
#define USB_DEVICE_DESCRIPTOR_TYPE 1
|
||||
#define USB_CONFIGURATION_DESCRIPTOR_TYPE 2
|
||||
#define USB_STRING_DESCRIPTOR_TYPE 3
|
||||
#define USB_INTERFACE_DESCRIPTOR_TYPE 4
|
||||
#define USB_ENDPOINT_DESCRIPTOR_TYPE 5
|
||||
#define USB_DEVICE_QUALIFIER 6
|
||||
#define USB_OTHER_SPEED_CONFIGURATION 7
|
||||
|
||||
#define USB_DEVICE_CLASS_COMMUNICATIONS 0x02
|
||||
#define USB_DEVICE_CLASS_HUMAN_INTERFACE 0x03
|
||||
#define USB_DEVICE_CLASS_STORAGE 0x08
|
||||
#define USB_DEVICE_CLASS_VENDOR_SPECIFIC 0xFF
|
||||
|
||||
#define USB_CONFIG_POWERED_MASK 0x40
|
||||
#define USB_CONFIG_BUS_POWERED 0x80
|
||||
#define USB_CONFIG_SELF_POWERED 0xC0
|
||||
#define USB_CONFIG_REMOTE_WAKEUP 0x20
|
||||
|
||||
// bMaxPower in Configuration Descriptor
|
||||
#define USB_CONFIG_POWER_MA(mA) ((mA)/2)
|
||||
|
||||
// bEndpointAddress in Endpoint Descriptor
|
||||
#define USB_ENDPOINT_DIRECTION_MASK 0x80
|
||||
#define USB_ENDPOINT_OUT(addr) ((addr) | 0x00)
|
||||
#define USB_ENDPOINT_IN(addr) ((addr) | 0x80)
|
||||
|
||||
#define USB_ENDPOINT_TYPE_MASK 0x03
|
||||
#define USB_ENDPOINT_TYPE_CONTROL 0x00
|
||||
#define USB_ENDPOINT_TYPE_ISOCHRONOUS 0x01
|
||||
#define USB_ENDPOINT_TYPE_BULK 0x02
|
||||
#define USB_ENDPOINT_TYPE_INTERRUPT 0x03
|
||||
|
||||
#define TOBYTES(x) ((x) & 0xFF),(((x) >> 8) & 0xFF)
|
||||
|
||||
#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
|
||||
|
||||
#define HID_HID_DESCRIPTOR_TYPE 0x21
|
||||
#define HID_REPORT_DESCRIPTOR_TYPE 0x22
|
||||
#define HID_PHYSICAL_DESCRIPTOR_TYPE 0x23
|
||||
|
||||
_Pragma("pack(1)")
|
||||
|
||||
// Device
|
||||
typedef struct {
|
||||
uint8_t len; // 18
|
||||
uint8_t dtype; // 1 USB_DEVICE_DESCRIPTOR_TYPE
|
||||
uint16_t usbVersion; // 0x200
|
||||
uint8_t deviceClass;
|
||||
uint8_t deviceSubClass;
|
||||
uint8_t deviceProtocol;
|
||||
uint8_t packetSize0; // Packet 0
|
||||
uint16_t idVendor;
|
||||
uint16_t idProduct;
|
||||
uint16_t deviceVersion; // 0x100
|
||||
uint8_t iManufacturer;
|
||||
uint8_t iProduct;
|
||||
uint8_t iSerialNumber;
|
||||
uint8_t bNumConfigurations;
|
||||
} DeviceDescriptor;
|
||||
|
||||
// Config
|
||||
typedef struct {
|
||||
uint8_t len; // 9
|
||||
uint8_t dtype; // 2
|
||||
uint16_t clen; // total length
|
||||
uint8_t numInterfaces;
|
||||
uint8_t config;
|
||||
uint8_t iconfig;
|
||||
uint8_t attributes;
|
||||
uint8_t maxPower;
|
||||
} ConfigDescriptor;
|
||||
|
||||
// String
|
||||
|
||||
// Interface
|
||||
typedef struct
|
||||
{
|
||||
uint8_t len; // 9
|
||||
uint8_t dtype; // 4
|
||||
uint8_t number;
|
||||
uint8_t alternate;
|
||||
uint8_t numEndpoints;
|
||||
uint8_t interfaceClass;
|
||||
uint8_t interfaceSubClass;
|
||||
uint8_t protocol;
|
||||
uint8_t iInterface;
|
||||
} InterfaceDescriptor;
|
||||
|
||||
// Endpoint
|
||||
typedef struct
|
||||
{
|
||||
uint8_t len; // 7
|
||||
uint8_t dtype; // 5
|
||||
uint8_t addr;
|
||||
uint8_t attr;
|
||||
uint16_t packetSize;
|
||||
uint8_t interval;
|
||||
} EndpointDescriptor;
|
||||
|
||||
// Interface Association Descriptor
|
||||
// Used to bind 2 interfaces together in CDC compostite device
|
||||
typedef struct
|
||||
{
|
||||
uint8_t len; // 8
|
||||
uint8_t dtype; // 11
|
||||
uint8_t firstInterface;
|
||||
uint8_t interfaceCount;
|
||||
uint8_t functionClass;
|
||||
uint8_t funtionSubClass;
|
||||
uint8_t functionProtocol;
|
||||
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;
|
||||
CMFunctionalDescriptor callManagement; // Call Management
|
||||
ACMFunctionalDescriptor controlManagement; // ACM
|
||||
CDCCSInterfaceDescriptor functionalDescriptor; // CDC_UNION
|
||||
EndpointDescriptor cifin;
|
||||
|
||||
// Data
|
||||
InterfaceDescriptor dif;
|
||||
EndpointDescriptor in;
|
||||
EndpointDescriptor out;
|
||||
} CDCDescriptor;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
InterfaceDescriptor msc;
|
||||
EndpointDescriptor in;
|
||||
EndpointDescriptor out;
|
||||
} MSCDescriptor;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint8_t len; // 9
|
||||
uint8_t dtype; // 0x21
|
||||
uint8_t addr;
|
||||
uint8_t versionL; // 0x101
|
||||
uint8_t versionH; // 0x101
|
||||
uint8_t country;
|
||||
uint8_t desctype; // 0x22 report
|
||||
uint8_t descLenL;
|
||||
uint8_t descLenH;
|
||||
} HIDDescDescriptor;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
InterfaceDescriptor hid;
|
||||
HIDDescDescriptor desc;
|
||||
EndpointDescriptor in;
|
||||
} HIDDescriptor;
|
||||
|
||||
_Pragma("pack()")
|
||||
|
||||
#define D_DEVICE(_class,_subClass,_proto,_packetSize0,_vid,_pid,_version,_im,_ip,_is,_configs) \
|
||||
{ 18, 1, 0x200, _class,_subClass,_proto,_packetSize0,_vid,_pid,_version,_im,_ip,_is,_configs }
|
||||
|
||||
#define D_CONFIG(_totalLength,_interfaces) \
|
||||
{ 9, 2, _totalLength,_interfaces, 1, 0, USB_CONFIG_SELF_POWERED, USB_CONFIG_POWER_MA(500) }
|
||||
|
||||
#define D_OTHERCONFIG(_totalLength,_interfaces) \
|
||||
{ 9, 7, _totalLength,_interfaces, 1, 0, USB_CONFIG_SELF_POWERED, USB_CONFIG_POWER_MA(500) }
|
||||
|
||||
#define D_INTERFACE(_n,_numEndpoints,_class,_subClass,_protocol) \
|
||||
{ 9, 4, _n, 0, _numEndpoints, _class,_subClass, _protocol, 0 }
|
||||
|
||||
#define D_ENDPOINT(_addr,_attr,_packetSize, _interval) \
|
||||
{ 7, 5, _addr,_attr,_packetSize, _interval }
|
||||
|
||||
#define D_QUALIFIER(_class,_subClass,_proto,_packetSize0,_configs) \
|
||||
{ 10, 6, 0x200, _class,_subClass,_proto,_packetSize0,_configs }
|
||||
|
||||
#define D_IAD(_firstInterface, _count, _class, _subClass, _protocol) \
|
||||
{ 8, 11, _firstInterface, _count, _class, _subClass, _protocol, 0 }
|
||||
|
||||
#define D_HIDREPORT(_descriptorLength) \
|
||||
{ 9, 0x21, 0x1, 0x1, 0, 1, 0x22, _descriptorLength, 0 }
|
||||
|
||||
#define D_CDCCS(_subtype,_d0,_d1) { 5, 0x24, _subtype, _d0, _d1 }
|
||||
#define D_CDCCS4(_subtype,_d0) { 4, 0x24, _subtype, _d0 }
|
||||
|
||||
#endif
|
||||
64
digistump-sam/cores/digix/USB/USBDesc.h
Normal file
64
digistump-sam/cores/digix/USB/USBDesc.h
Normal file
@@ -0,0 +1,64 @@
|
||||
// Copyright (c) 2010, Peter Barrett
|
||||
/*
|
||||
** Permission to use, copy, modify, and/or distribute this software for
|
||||
** any purpose with or without fee is hereby granted, provided that the
|
||||
** above copyright notice and this permission notice appear in all copies.
|
||||
**
|
||||
** THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
|
||||
** WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
|
||||
** WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR
|
||||
** BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES
|
||||
** OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
|
||||
** WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
|
||||
** ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
|
||||
** SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef __USBDESC_H__
|
||||
#define __USBDESC_H__
|
||||
|
||||
#define CDC_ENABLED
|
||||
#define HID_ENABLED
|
||||
|
||||
#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
|
||||
|
||||
#ifdef HID_ENABLED
|
||||
#define HID_INTERFACE_COUNT 1
|
||||
#define HID_ENPOINT_COUNT 1
|
||||
#else
|
||||
#define HID_INTERFACE_COUNT 0
|
||||
#define HID_ENPOINT_COUNT 0
|
||||
#endif
|
||||
|
||||
#define CDC_ACM_INTERFACE 0 // CDC ACM
|
||||
#define CDC_DATA_INTERFACE 1 // CDC Data
|
||||
#define CDC_FIRST_ENDPOINT 1
|
||||
#define CDC_ENDPOINT_ACM (CDC_FIRST_ENDPOINT) // CDC First
|
||||
#define CDC_ENDPOINT_OUT (CDC_FIRST_ENDPOINT+1)
|
||||
#define CDC_ENDPOINT_IN (CDC_FIRST_ENDPOINT+2)
|
||||
|
||||
#define HID_INTERFACE (CDC_ACM_INTERFACE + CDC_INTERFACE_COUNT) // HID Interface
|
||||
#define HID_FIRST_ENDPOINT (CDC_FIRST_ENDPOINT + CDC_ENPOINT_COUNT)
|
||||
#define HID_ENDPOINT_INT (HID_FIRST_ENDPOINT)
|
||||
|
||||
#define INTERFACE_COUNT (MSC_INTERFACE + MSC_INTERFACE_COUNT)
|
||||
|
||||
#ifdef CDC_ENABLED
|
||||
#define CDC_RX CDC_ENDPOINT_OUT
|
||||
#define CDC_TX CDC_ENDPOINT_IN
|
||||
#endif
|
||||
|
||||
#ifdef HID_ENABLED
|
||||
#define HID_TX HID_ENDPOINT_INT
|
||||
#endif
|
||||
|
||||
#define IMANUFACTURER 1
|
||||
#define IPRODUCT 2
|
||||
|
||||
#endif /* __USBDESC_H__ */
|
||||
Reference in New Issue
Block a user