diff options
Diffstat (limited to 'cores')
| -rw-r--r-- | cores/arduino/CDC.cpp | 277 | ||||
| -rw-r--r-- | cores/arduino/USBAPI.h | 66 | ||||
| -rw-r--r-- | cores/arduino/USBCore.cpp | 125 | ||||
| -rw-r--r-- | cores/arduino/USBCore.h | 107 | ||||
| -rw-r--r-- | cores/arduino/USBDesc.h | 19 | ||||
| -rw-r--r-- | cores/arduino/xinput/USB_XInput_API.cpp | 57 | ||||
| -rw-r--r-- | cores/arduino/xinput/USB_XInput_API.h | 51 | ||||
| -rw-r--r-- | cores/arduino/xinput/USB_XInput_Descriptors.cpp | 210 | ||||
| -rw-r--r-- | cores/arduino/xinput/USB_XInput_Descriptors.h | 53 | 
9 files changed, 443 insertions, 522 deletions
| diff --git a/cores/arduino/CDC.cpp b/cores/arduino/CDC.cpp index 4ff6b9b..a6bce17 100644 --- a/cores/arduino/CDC.cpp +++ b/cores/arduino/CDC.cpp @@ -17,286 +17,9 @@  */  #include "USBAPI.h" -#include <avr/wdt.h> -#include <util/atomic.h>  #if defined(USBCON) -typedef struct -{ -	u32	dwDTERate; -	u8	bCharFormat; -	u8 	bParityType; -	u8 	bDataBits; -	u8	lineState; -} LineInfo; - -static volatile LineInfo _usbLineInfo = { 57600, 0x00, 0x00, 0x00, 0x00 }; -static volatile int32_t breakValue = -1; - -static u8 wdtcsr_save; - -#define WEAK __attribute__ ((weak)) - -extern const CDCDescriptor _cdcInterface PROGMEM; -const 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,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,0x40), - -	//	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,USB_EP_SIZE,0), -	D_ENDPOINT(USB_ENDPOINT_IN (CDC_ENDPOINT_IN ),USB_ENDPOINT_TYPE_BULK,USB_EP_SIZE,0) -}; - -bool isLUFAbootloader() -{ -	return pgm_read_word(FLASHEND - 1) == NEW_LUFA_SIGNATURE; -} - -int CDC_GetInterface(u8* interfaceNum) -{ -	interfaceNum[0] += 2;	// uses 2 -	return USB_SendControl(TRANSFER_PGM,&_cdcInterface,sizeof(_cdcInterface)); -} - -bool CDC_Setup(USBSetup& setup) -{ -	u8 r = setup.bRequest; -	u8 requestType = setup.bmRequestType; - -	if (REQUEST_DEVICETOHOST_CLASS_INTERFACE == requestType) -	{ -		if (CDC_GET_LINE_CODING == r) -		{ -			USB_SendControl(0,(void*)&_usbLineInfo,7); -			return true; -		} -	} - -	if (REQUEST_HOSTTODEVICE_CLASS_INTERFACE == requestType) -	{ -		if (CDC_SEND_BREAK == r) -		{ -			breakValue = ((uint16_t)setup.wValueH << 8) | setup.wValueL; -		} - -		if (CDC_SET_LINE_CODING == r) -		{ -			USB_RecvControl((void*)&_usbLineInfo,7); -		} - -		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.  this is the signal to start the watchdog -			// with a relatively long period so it can finish housekeeping tasks -			// like servicing endpoints before the sketch ends - -			uint16_t magic_key_pos = MAGIC_KEY_POS; - -// If we don't use the new RAMEND directly, check manually if we have a newer bootloader. -// This is used to keep compatible with the old leonardo bootloaders. -// You are still able to set the magic key position manually to RAMEND-1 to save a few bytes for this check. -#if MAGIC_KEY_POS != (RAMEND-1) -			// For future boards save the key in the inproblematic RAMEND -			// Which is reserved for the main() return value (which will never return) -			if (isLUFAbootloader()) { -				// horray, we got a new bootloader! -				magic_key_pos = (RAMEND-1); -			} -#endif - -			// We check DTR state to determine if host port is open (bit 0 of lineState). -			if (1200 == _usbLineInfo.dwDTERate && (_usbLineInfo.lineState & 0x01) == 0) -			{ -#if MAGIC_KEY_POS != (RAMEND-1) -				// Backup ram value if its not a newer bootloader and it hasn't already been saved. -				// This should avoid memory corruption at least a bit, not fully -				if (magic_key_pos != (RAMEND-1) && *(uint16_t *)magic_key_pos != MAGIC_KEY) { -					*(uint16_t *)(RAMEND-1) = *(uint16_t *)magic_key_pos; -				} -#endif -				// Store boot key -				*(uint16_t *)magic_key_pos = MAGIC_KEY; -				// Save the watchdog state in case the reset is aborted. -				wdtcsr_save = WDTCSR; -				wdt_enable(WDTO_120MS); -			} -			else if (*(uint16_t *)magic_key_pos == MAGIC_KEY) -			{ -				// Most OSs do some intermediate steps when configuring ports and DTR can -				// twiggle more than once before stabilizing. -				// To avoid spurious resets we set the watchdog to 120ms and eventually -				// cancel if DTR goes back high. -				// Cancellation is only done if an auto-reset was started, which is -				// indicated by the magic key having been set. - -				wdt_reset(); -				// Restore the watchdog state in case the sketch was using it. -				WDTCSR |= (1<<WDCE) | (1<<WDE); -				WDTCSR = wdtcsr_save; -#if MAGIC_KEY_POS != (RAMEND-1) -				// Restore backed up (old bootloader) magic key data -				if (magic_key_pos != (RAMEND-1)) { -					*(uint16_t *)magic_key_pos = *(uint16_t *)(RAMEND-1); -				} else -#endif -				{ -				// Clean up RAMEND key -					*(uint16_t *)magic_key_pos = 0x0000; -				} -			} -		} -		return true; -	} -	return false; -} - - -void Serial_::begin(unsigned long /* baud_count */) -{ -	peek_buffer = -1; -} - -void Serial_::begin(unsigned long /* baud_count */, byte /* config */) -{ -	peek_buffer = -1; -} - -void Serial_::end(void) -{ -} - -int Serial_::available(void) -{ -	if (peek_buffer >= 0) { -		return 1 + USB_Available(CDC_RX); -	} -	return USB_Available(CDC_RX); -} - -int Serial_::peek(void) -{ -	if (peek_buffer < 0) -		peek_buffer = USB_Recv(CDC_RX); -	return peek_buffer; -} - -int Serial_::read(void) -{ -	if (peek_buffer >= 0) { -		int c = peek_buffer; -		peek_buffer = -1; -		return c; -	} -	return USB_Recv(CDC_RX); -} - -int Serial_::availableForWrite(void) -{ -	return USB_SendSpace(CDC_TX); -} - -void Serial_::flush(void) -{ -	USB_Flush(CDC_TX); -} - -size_t Serial_::write(uint8_t c) -{ -	return write(&c, 1); -} - -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 = USB_Send(CDC_TX,buffer,size); -		if (r > 0) { -			return r; -		} else { -			setWriteError(); -			return 0; -		} -	} -	setWriteError(); -	return 0; -} - -// 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() { -	bool result = false; -	if (_usbLineInfo.lineState > 0)  -		result = true; -	delay(10); -	return result; -} - -unsigned long Serial_::baud() { -	// Disable interrupts while reading a multi-byte value -	uint32_t baudrate; -	ATOMIC_BLOCK(ATOMIC_RESTORESTATE) { -		baudrate =  _usbLineInfo.dwDTERate; -	} -	return baudrate; -} - -uint8_t Serial_::stopbits() { -	return _usbLineInfo.bCharFormat; -} - -uint8_t Serial_::paritytype() { -	return _usbLineInfo.bParityType; -} - -uint8_t Serial_::numbits() { -	return _usbLineInfo.bDataBits; -} - -bool Serial_::dtr() { -	return _usbLineInfo.lineState & 0x1; -} - -bool Serial_::rts() { -	return _usbLineInfo.lineState & 0x2; -} - -int32_t Serial_::readBreak() { -	int32_t ret; -	// Disable IRQs while reading and clearing breakValue to make -	// sure we don't overwrite a value just set by the ISR. -	ATOMIC_BLOCK(ATOMIC_RESTORESTATE) { -		ret = breakValue; -		breakValue = -1; -	} -	return ret; -} -  Serial_ Serial;  #endif /* if defined(USBCON) */ diff --git a/cores/arduino/USBAPI.h b/cores/arduino/USBAPI.h index 701a14f..47221b8 100644 --- a/cores/arduino/USBAPI.h +++ b/cores/arduino/USBAPI.h @@ -42,6 +42,7 @@ typedef unsigned long u32;  #include "USBDesc.h"  #include "USBCore.h" +#include "xinput/USB_XInput_Descriptors.h"  //================================================================================  //================================================================================ @@ -89,27 +90,21 @@ struct ring_buffer;  class Serial_ : public Stream  { -private: -	int peek_buffer;  public: -	Serial_() { peek_buffer = -1; }; -	void begin(unsigned long); -	void begin(unsigned long, uint8_t); -	void end(void); - -	virtual int available(void); -	virtual int peek(void); -	virtual int read(void); -	virtual int availableForWrite(void); -	virtual void flush(void); -	virtual size_t write(uint8_t); -	virtual size_t write(const uint8_t*, size_t); +	Serial_() {}; +	void begin(unsigned long) {} +	void begin(unsigned long, uint8_t) {} +	void end(void) {} + +	virtual int available(void) { return -1; } +	virtual int peek(void) { return -1; } +	virtual int read(void) { return -1; } +	virtual int availableForWrite(void) { return 0; } +	virtual void flush(void) {} +	virtual size_t write(uint8_t) { return 1; } +	virtual size_t write(const uint8_t*, size_t n) { return n; }  	using Print::write; // pull in write(str) and write(buf, size) from Print -	operator bool(); - -	volatile uint8_t _rx_buffer_head; -	volatile uint8_t _rx_buffer_tail; -	unsigned char _rx_buffer[SERIAL_BUFFER_SIZE]; +	operator bool() { return true; }  	// This method allows processing "SEND_BREAK" requests sent by  	// the USB host. Those requests indicate that the host wants to @@ -126,17 +121,17 @@ public:  	// 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(); +	int32_t readBreak() { return -1; };  	// 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(); +	uint32_t baud() { return 0; } +	uint8_t stopbits() { return 1; } +	uint8_t paritytype() { return 0; } +	uint8_t numbits() { return 8; } +	bool dtr() { return true; } +	bool rts() { return true; }  	enum {  		ONE_STOP_BIT = 0,  		ONE_AND_HALF_STOP_BIT = 1, @@ -171,23 +166,6 @@ typedef struct  //================================================================================  //================================================================================ -//	MSC 'Driver' - -int		MSC_GetInterface(uint8_t* interfaceNum); -int		MSC_GetDescriptor(int i); -bool	MSC_Setup(USBSetup& setup); -bool	MSC_Data(uint8_t rx,uint8_t tx); - -//================================================================================ -//================================================================================ -//	CSC 'Driver' - -int		CDC_GetInterface(uint8_t* interfaceNum); -int		CDC_GetDescriptor(int i); -bool	CDC_Setup(USBSetup& setup); - -//================================================================================ -//================================================================================  #define TRANSFER_PGM		0x80  #define TRANSFER_RELEASE	0x40 @@ -204,6 +182,8 @@ int USB_Recv(uint8_t ep, void* data, int len);		// non-blocking  int USB_Recv(uint8_t ep);							// non-blocking  void USB_Flush(uint8_t ep); +#include "xinput/USB_XInput_API.h" +  #endif  #endif /* if defined(USBCON) */ diff --git a/cores/arduino/USBCore.cpp b/cores/arduino/USBCore.cpp index dc6bc38..b384984 100644 --- a/cores/arduino/USBCore.cpp +++ b/cores/arduino/USBCore.cpp @@ -34,7 +34,6 @@ volatile u8 RxLEDPulse; /**< Milliseconds remaining for data Rx LED pulse */  extern const u16 STRING_LANGUAGE[] PROGMEM;  extern const u8 STRING_PRODUCT[] PROGMEM;  extern const u8 STRING_MANUFACTURER[] PROGMEM; -extern const DeviceDescriptor USB_DeviceDescriptorIAD PROGMEM;  const u16 STRING_LANGUAGE[2] = {  	(3<<8) | (2+2), @@ -65,13 +64,6 @@ const u8 STRING_PRODUCT[] PROGMEM = USB_PRODUCT;  const u8 STRING_MANUFACTURER[] PROGMEM = USB_MANUFACTURER; - -#define DEVICE_CLASS 0x02 - -//	DEVICE DESCRIPTOR -const DeviceDescriptor USB_DeviceDescriptorIAD = -	D_DEVICE(0xEF,0x02,0x01,64,USB_VID,USB_PID,0x100,IMANUFACTURER,IPRODUCT,ISERIAL,1); -  //==================================================================  //================================================================== @@ -325,63 +317,52 @@ int USB_Send(u8 ep, const void* d, int len)  	return r;  } -u8 _initEndpoints[USB_ENDPOINTS] = -{ -	0,                      // Control Endpoint -	 -	EP_TYPE_INTERRUPT_IN,   // CDC_ENDPOINT_ACM -	EP_TYPE_BULK_OUT,       // CDC_ENDPOINT_OUT -	EP_TYPE_BULK_IN,        // CDC_ENDPOINT_IN - -	// Following endpoints are automatically initialized to 0 -}; -  #define EP_SINGLE_64 0x32	// EP0  #define EP_DOUBLE_64 0x36	// Other endpoints  #define EP_SINGLE_16 0x12 -static +static inline +u8 BankSizeMask(const uint8_t nbytes) +{ +	uint8_t mask = 0; +	for (uint8_t size = 8; size < 64; size <<= 1) { +		if (nbytes <= size) break; +		mask++; +	} + +	return (mask << EPSIZE0); +} + +static inline  void InitEP(u8 index, u8 type, u8 size)  { -	UENUM = index; -	UECONX = (1<<EPEN); -	UECFG0X = type; -	UECFG1X = size; +	UENUM = index;       // Select endpoint +	UECONX = (1<<EPEN);  // Enable endpoint +	UECFG0X = type;      // Direction and transmission type +	UECFG1X = size;      // Memory allocation, # of data banks, and bank size  } -static -void InitEndpoints() +static inline +bool InitEPSize(const u8 index, const u8 type, const u8 nbanks, const u8 banksize)  { -	for (u8 i = 1; i < sizeof(_initEndpoints) && _initEndpoints[i] != 0; i++) -	{ -		UENUM = i; -		UECONX = (1<<EPEN); -		UECFG0X = _initEndpoints[i]; -#if USB_EP_SIZE == 16 -		UECFG1X = EP_SINGLE_16; -#elif USB_EP_SIZE == 64 -		UECFG1X = EP_DOUBLE_64; -#else -#error Unsupported value for USB_EP_SIZE -#endif -	} -	UERST = 0x7E;	// And reset them -	UERST = 0; +	if (index >= USB_ENDPOINTS) return false; +	uint8_t size = ((1 << ALLOC) | ((nbanks > 1) ? (1 << EPBK0) : 0) | BankSizeMask(banksize)); +	InitEP(index, type, size); +	return UESTA0X & (1 << CFGOK);  // Success  } -//	Handle CLASS_INTERFACE requests  static -bool ClassInterfaceRequest(USBSetup& setup) +void InitEndpoints()  { -	u8 i = setup.wIndex; +	InitEPSize(XINPUT_TX_ENDPOINT, EP_TYPE_INTERRUPT_IN,  1, 32);  // Control Data Send +	InitEPSize(XINPUT_RX_ENDPOINT, EP_TYPE_INTERRUPT_OUT, 2, 32);  // Control Data Receive +	InitEPSize(5, EP_TYPE_INTERRUPT_IN,  1, 32);  // Expansion Interface NACK (avoid config reset) -	if (CDC_ACM_INTERFACE == i) -		return CDC_Setup(setup); +	UERST = 0x7E;  // Reset endpoints +	UERST = 0;     // End reset -#ifdef PLUGGABLE_USB_ENABLED -	return PluggableUSB().setup(setup); -#endif -	return false; +	SetEP(XINPUT_RX_ENDPOINT);  // Select XInput RX endpoint (OUT) +	UEIENX |= (1 << RXOUTE);  // Enable received "OUT" interrupt  }  static int _cmark; @@ -462,34 +443,14 @@ int USB_RecvControl(void* d, int len)  	return len;  } -static u8 SendInterfaces() -{ -	u8 interfaces = 0; - -	CDC_GetInterface(&interfaces); - -#ifdef PLUGGABLE_USB_ENABLED -	PluggableUSB().getInterface(&interfaces); -#endif - -	return interfaces; -} -  //	Construct a dynamic configuration descriptor  //	This really needs dynamic endpoint allocation etc  //	TODO  static  bool SendConfiguration(int maxlen)  { -	//	Count and measure interfaces -	InitControl(0); -	u8 interfaces = SendInterfaces(); -	ConfigDescriptor config = D_CONFIG(_cmark + sizeof(ConfigDescriptor),interfaces); - -	//	Now send them  	InitControl(maxlen); -	USB_SendControl(0,&config,sizeof(ConfigDescriptor)); -	SendInterfaces(); +	USB_SendControl(TRANSFER_PGM, &USB_ConfigDescriptor, USB_ConfigDescriptorSize);  	return true;  } @@ -511,7 +472,7 @@ bool SendDescriptor(USBSetup& setup)  	const u8* desc_addr = 0;  	if (USB_DEVICE_DESCRIPTOR_TYPE == t)  	{ -		desc_addr = (const u8*)&USB_DeviceDescriptorIAD; +		desc_addr = (const u8*) &USB_DeviceDescriptor;  	}  	else if (USB_STRING_DESCRIPTOR_TYPE == t)  	{ @@ -529,8 +490,13 @@ bool SendDescriptor(USBSetup& setup)  			char name[ISERIAL_MAX_LEN];  			PluggableUSB().getShortName(name);  			return USB_SendStringDescriptor((uint8_t*)name, strlen(name), 0); +#else +			return USB_SendStringDescriptor(STRING_SERIAL, strlen((char*)STRING_SERIAL), TRANSFER_PGM);  #endif  		} +		else if (setup.wValueL == ISECURITY) { +			return USB_SendStringDescriptor(STRING_SECURITY, strlen((char*)STRING_SECURITY), TRANSFER_PGM); +		}  		else  			return false;  	} @@ -543,9 +509,17 @@ bool SendDescriptor(USBSetup& setup)  	return true;  } -//	Endpoint 0 interrupt +//	Endpoint interrupt  ISR(USB_COM_vect)  { +	SetEP(XINPUT_RX_ENDPOINT);  // Select XInput RX endpoint (OUT) +	if (UEINTX & (1 << RXOUTI)) {  // If data received... +		UEINTX &= ~(1 << RXOUTI);  // Clear interrupt flag +		if (XInputUSB::RecvCallback != nullptr) { +			XInputUSB::RecvCallback();  // Call callback function if it exists +		} +	} +      SetEP(0);  	if (!ReceivedSetupInt())  		return; @@ -632,8 +606,7 @@ ISR(USB_COM_vect)  	}  	else  	{ -		InitControl(setup.wLength);		//	Max length of transfer -		ok = ClassInterfaceRequest(setup); +		ok = true;  	}  	if (ok) @@ -754,8 +727,6 @@ ISR(USB_GEN_vect)  	//	Start of Frame - happens every millisecond so we use it for TX and RX LED one-shot timing, too  	if (udint & (1<<SOFI))  	{ -		USB_Flush(CDC_TX);				// Send a tx frame if found -		  		// check whether the one-shot period has elapsed.  if so, turn off the LED  		if (TxLEDPulse && !(--TxLEDPulse))  			TXLED0; diff --git a/cores/arduino/USBCore.h b/cores/arduino/USBCore.h index 0c63c2b..578e1b8 100644 --- a/cores/arduino/USBCore.h +++ b/cores/arduino/USBCore.h @@ -53,16 +53,6 @@  #define REQUEST_HOSTTODEVICE_CLASS_INTERFACE    (REQUEST_HOSTTODEVICE | REQUEST_CLASS | REQUEST_INTERFACE)  #define REQUEST_DEVICETOHOST_STANDARD_INTERFACE (REQUEST_DEVICETOHOST | REQUEST_STANDARD | REQUEST_INTERFACE) -//	Class requests - -#define CDC_SET_LINE_CODING			0x20 -#define CDC_GET_LINE_CODING			0x21 -#define CDC_SET_CONTROL_LINE_STATE	0x22 -#define CDC_SEND_BREAK				0x23 - -#define MSC_RESET					0xFF -#define MSC_GET_MAX_LUN				0xFE -  //	Descriptors  #define USB_DEVICE_DESC_SIZE 18 @@ -114,21 +104,6 @@  #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  -  #ifndef USB_VERSION  #define USB_VERSION 0x200  #endif @@ -190,82 +165,6 @@ typedef struct  	u8 interval;  } EndpointDescriptor; -// Interface Association Descriptor -// Used to bind 2 interfaces together in CDC compostite device -typedef struct -{ -	u8 len;				// 8 -	u8 dtype;			// 11 -	u8 firstInterface; -	u8 interfaceCount; -	u8 functionClass; -	u8 funtionSubClass; -	u8 functionProtocol; -	u8 iInterface; -} IADDescriptor; - -//	CDC CS interface descriptor -typedef struct -{ -	u8 len;		// 5 -	u8 dtype;	// 0x24 -	u8 subtype; -	u8 d0; -	u8 d1; -} CDCCSInterfaceDescriptor; - -typedef struct -{ -	u8 len;		// 4 -	u8 dtype;	// 0x24 -	u8 subtype; -	u8 d0; -} CDCCSInterfaceDescriptor4; - -typedef struct  -{ -    u8	len; -    u8 	dtype;		// 0x24 -    u8 	subtype;	// 1 -    u8 	bmCapabilities; -    u8 	bDataInterface; -} CMFunctionalDescriptor; -	 -typedef struct  -{ -    u8	len; -    u8 	dtype;		// 0x24 -    u8 	subtype;	// 1 -    u8 	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; - -  #define D_DEVICE(_class,_subClass,_proto,_packetSize0,_vid,_pid,_version,_im,_ip,_is,_configs) \  	{ 18, 1, USB_VERSION, _class,_subClass,_proto,_packetSize0,_vid,_pid,_version,_im,_ip,_is,_configs } @@ -278,12 +177,6 @@ typedef struct  #define D_ENDPOINT(_addr,_attr,_packetSize, _interval) \  	{ 7, 5, _addr,_attr,_packetSize, _interval } -#define D_IAD(_firstInterface, _count, _class, _subClass, _protocol) \ -	{ 8, 11, _firstInterface, _count, _class, _subClass, _protocol, 0 } - -#define D_CDCCS(_subtype,_d0,_d1)	{ 5, 0x24, _subtype, _d0, _d1 } -#define D_CDCCS4(_subtype,_d0)		{ 4, 0x24, _subtype, _d0 } -  // Bootloader related fields  // Old Caterina bootloader places the MAGIC key into unsafe RAM locations (it can be rewritten  // by the running sketch before to actual reboot). diff --git a/cores/arduino/USBDesc.h b/cores/arduino/USBDesc.h index c0dce07..fe1af92 100644 --- a/cores/arduino/USBDesc.h +++ b/cores/arduino/USBDesc.h @@ -16,7 +16,7 @@     SOFTWARE.   */ -#define PLUGGABLE_USB_ENABLED +// #define PLUGGABLE_USB_ENABLED  // Not compatible with XInput  #if defined(EPRST6)  #define USB_ENDPOINTS 7 // AtMegaxxU4 @@ -24,23 +24,6 @@  #define USB_ENDPOINTS 5 // AtMegaxxU2  #endif -#define ISERIAL_MAX_LEN     20 - -#define CDC_INTERFACE_COUNT	2 -#define CDC_ENPOINT_COUNT	3 - -#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 INTERFACE_COUNT		(MSC_INTERFACE + MSC_INTERFACE_COUNT) - -#define CDC_RX CDC_ENDPOINT_OUT -#define CDC_TX CDC_ENDPOINT_IN -  #define IMANUFACTURER   1  #define IPRODUCT        2  #define ISERIAL         3
\ No newline at end of file diff --git a/cores/arduino/xinput/USB_XInput_API.cpp b/cores/arduino/xinput/USB_XInput_API.cpp new file mode 100644 index 0000000..ffd818c --- /dev/null +++ b/cores/arduino/xinput/USB_XInput_API.cpp @@ -0,0 +1,57 @@ +/* + *  Project     Arduino XInput - AVR Core + *  @author     David Madison + *  @link       github.com/dmadison/ArduinoXInput_AVR + *  @license    MIT - Copyright (c) 2019 David Madison + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + */ + +#include "USB_XInput_API.h" + +#ifdef USB_XINPUT + +void (*XInputUSB::RecvCallback)(void) = nullptr; + +boolean XInputUSB::connected() { +	return USBDevice.configured(); +} + +uint8_t XInputUSB::available() { +	return USB_Available(XINPUT_RX_ENDPOINT); +} + +int XInputUSB::recv(void *buffer, uint8_t nbytes) { +	return USB_Recv(XINPUT_RX_ENDPOINT, buffer, nbytes); +} + +int XInputUSB::send(const void *buffer, uint8_t nbytes) { +	int result = USB_Send(XINPUT_TX_ENDPOINT, buffer, nbytes); +	if (result > 0) { +		USB_Flush(XINPUT_TX_ENDPOINT); +	} +	return result; +} + +void XInputUSB::setRecvCallback(void(*callback)(void)) { +	XInputUSB::RecvCallback = callback; +} + +#endif /* ifdef USB_XINPUT */ diff --git a/cores/arduino/xinput/USB_XInput_API.h b/cores/arduino/xinput/USB_XInput_API.h new file mode 100644 index 0000000..11fa100 --- /dev/null +++ b/cores/arduino/xinput/USB_XInput_API.h @@ -0,0 +1,51 @@ +/* + *  Project     Arduino XInput - AVR Core + *  @author     David Madison + *  @link       github.com/dmadison/ArduinoXInput_AVR + *  @license    MIT - Copyright (c) 2019 David Madison + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + */ + +#include "USBAPI.h" + +#ifndef USB_XINPUT_API_H +#define USB_XINPUT_API_H + +#ifdef USBCON + +#define USB_XINPUT + +class XInputUSB { +public: +	// API +	static bool connected(void); +	static uint8_t available(void); +	static int send(const void *buffer, uint8_t nbytes); +	static int recv(void *buffer, uint8_t nbytes); +	static void setRecvCallback(void(*callback)(void)); + +	// Non-API Data +	static void (*RecvCallback)(void); +}; + +#endif /* if defined(USBCON) */ + +#endif /* ifndef USB_XINPUT_API_H */ diff --git a/cores/arduino/xinput/USB_XInput_Descriptors.cpp b/cores/arduino/xinput/USB_XInput_Descriptors.cpp new file mode 100644 index 0000000..f57c700 --- /dev/null +++ b/cores/arduino/xinput/USB_XInput_Descriptors.cpp @@ -0,0 +1,210 @@ +/* + *  Project     Arduino XInput - AVR Core + *  @author     David Madison + *  @link       github.com/dmadison/ArduinoXInput_AVR + *  @license    MIT - Copyright (c) 2019 David Madison + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + */ + +#include "USB_XInput_Descriptors.h" + +#if defined(USBCON) + +const DeviceDescriptor USB_DeviceDescriptor = { +	0x12,           // bLength (18) +	0x01,           // bDescriptorType (DEVICE) +	USB_VERSION,    // bcdUSB (2.0) +	0xFF,           // bDeviceClass +	0xFF,           // bDeviceSubClass +	0xFF,           // bDeviceProtocol +	0x40,           // bMaxPacketSize0 +	USB_VID,        // idEVendor +	USB_PID,        // idProduct +	0x114,          // bcdDevice +	IMANUFACTURER,  // iManufacturer +	IPRODUCT,       // iProduct +	ISERIAL,        // iSerialNumber +	0x01,           // bNumConfigurations +}; + +const u8 USB_ConfigDescriptor[] = { +	// Configuration Descriptor +	0x09,        // bLength +	0x02,        // bDescriptorType (CONFIGURATION) +	0x99, 0x00,  // wTotalLength (153) +	0x04,        // bNumInterfaces +	0x01,        // bConfigurationValue +	0x00,        // iConfiguration +	0xA0,        // bmAttributes +	0xFA,        // bMaxPower + +	/* ---------------------------------------------------- */ +	// Interface 0: Control Data +	0x09,        // bLength +	0x04,        // bDescriptorType (INTERFACE) +	0x00,        // bInterfaceNumber +	0x00,        // bAlternateSetting +	0x02,        // bNumEndpoints +	0xFF,        // bInterfaceClass +	0x5D,        // bInterfaceSubClass +	0x01,        // bInterfaceProtocol +	0x00,        // iInterface + +	// Unknown Descriptor (If0) +	0x11,        // bLength +	0x21,        // bDescriptorType +	0x00, 0x01, 0x01, 0x25,  // ??? +	0x81,        // bEndpointAddress (IN, 1) +	0x14,        // bMaxDataSize +	0x00, 0x00, 0x00, 0x00, 0x13,  // ??? +	0x02,        // bEndpointAddress (OUT, 2) +	0x08,        // bMaxDataSize +	0x00, 0x00,  // ??? + +	// Endpoint 1: Control Surface Send +	0x07,        // bLength +	0x05,        // bDescriptorType (ENDPOINT) +	0x81,        // bEndpointAddress (IN, 1) +	0x03,        // bmAttributes +	0x20, 0x00,  // wMaxPacketSize +	0x04,        // bInterval + +	// Endpoint 1: Control Surface Receive +	0x07,        // bLength +	0x05,        // bDescriptorType (ENDPOINT) +	0x02,        // bEndpointAddress (OUT, 2) +	0x03,        // bmAttributes +	0x20, 0x00,  // wMaxPacketSize +	0x08,        // bInterval + +	/* ---------------------------------------------------- */ +	// Interface 1: Headset (and Expansion Port?) +	0x09,        // bLength +	0x04,        // bDescriptorType (INTERFACE) +	0x01,        // bInterfaceNumber +	0x00,        // bAlternateSetting +	0x04,        // bNumEndpoints +	0xFF,        // bInterfaceClass +	0x5D,        // bInterfaceSubClass +	0x03,        // bInterfaceProtocol +	0x00,        // iInterface + +	// Unknown Descriptor (If1) +	0x1B,        // bLength +	0x21,        // bDescriptorType +	0x00, 0x01, 0x01, 0x01,  // ??? +	0x83,        // bEndpointAddress (IN, 3) +	0x40,        // bMaxDataSize +	0x01,        // ??? +	0x04,        // bEndpointAddress (OUT, 4) +	0x20,        // bMaxDataSize +	0x16,        // ??? +	0x85,        // bEndpointAddress (IN, 5) +	0x00,        // bMaxDataSize +	0x00, 0x00, 0x00, 0x00, 0x00, 0x16,  // ??? +	0x05,        // bEndpointAddress (OUT, 5) +	0x00,        // bMaxDataSize +	0x00, 0x00, 0x00, 0x00, 0x00,  // ??? + +	// Endpoint 2: Microphone Data Send +	0x07,        // bLength +	0x05,        // bDescriptorType (ENDPOINT) +	0x83,        // bEndpointAddress (IN, 3) +	0x03,        // bmAttributes +	0x20, 0x00,  // wMaxPacketSize +	0x02,        // bInterval + +	// Endpoint 2: Headset Audio Receive +	0x07,        // bLength +	0x05,        // bDescriptorType (ENDPOINT) +	0x04,        // bEndpointAddress (OUT, 4) +	0x03,        // bmAttributes +	0x20, 0x00,  // wMaxPacketSize +	0x04,        // bInterval + +	// Endpoint 3: Unknown, Send +	0x07,        // bLength +	0x05,        // bDescriptorType (ENDPOINT) +	0x85,        // bEndpointAddress (IN, 5) +	0x03,        // bmAttributes +	0x20, 0x00,  // wMaxPacketSize +	0x40,        // bInterval + +	// Endpoint 3: Unknown, Receive +	0x07,        // bLength +	0x05,        // bDescriptorType (ENDPOINT) +	0x05,        // bEndpointAddress (OUT, 5) +	0x03,        // bmAttributes +	0x20, 0x00,  // wMaxPacketSize +	0x10,        // bInterval + +	/* ---------------------------------------------------- */ +	// Interface 2: Unknown +	0x09,        // bLength +	0x04,        // bDescriptorType (INTERFACE) +	0x02,        // bInterfaceNumber +	0x00,        // bAlternateSetting +	0x01,        // bNumEndpoints +	0xFF,        // bInterfaceClass +	0x5D,        // bInterfaceSubClass +	0x02,        // bInterfaceProtocol +	0x00,        // iInterface + +	// Unknown Descriptor (If2) +	0x09,        // bLength +	0x21,        // bDescriptorType +	0x00, 0x01, 0x01, 0x22,  // ??? +	0x86,        // bEndpointAddress (IN, 6) +	0x07,        // bMaxDataSize +	0x00,        // ??? + +	// Endpoint 4: Unknown, Send +	0x07,        // bLength +	0x05,        // bDescriptorType (ENDPOINT) +	0x86,        // bEndpointAddress (IN, 6) +	0x03,        // bmAttributes +	0x20, 0x00,  // wMaxPacketSize +	0x10,        // bInterval + +	/* ---------------------------------------------------- */ +	// Interface 3: Security Method +	0x09,        // bLength +	0x04,        // bDescriptorType (INTERFACE) +	0x03,        // bInterfaceNumber +	0x00,        // bAlternateSetting +	0x00,        // bNumEndpoints +	0xFF,        // bInterfaceClass +	0xFD,        // bInterfaceSubClass +	0x13,        // bInterfaceProtocol +	0x04,        // iInterface + +	// Unknown Descriptor (If3) +	0x06,        // bLength +	0x41,        // bDescriptorType +	0x00, 0x01, 0x01, 0x03,  // ??? +}; + +const u16 USB_ConfigDescriptorSize = sizeof(USB_ConfigDescriptor); + +const u8 STRING_SERIAL[] = "Arduino XInput AVR"; +const u8 STRING_SECURITY[] = "Xbox Security Method 3, Version 1.00, \xA9 2005 Microsoft Corporation. All rights reserved."; + +#endif /* if defined(USBCON) */ diff --git a/cores/arduino/xinput/USB_XInput_Descriptors.h b/cores/arduino/xinput/USB_XInput_Descriptors.h new file mode 100644 index 0000000..976fe56 --- /dev/null +++ b/cores/arduino/xinput/USB_XInput_Descriptors.h @@ -0,0 +1,53 @@ +/* + *  Project     Arduino XInput - AVR Core + *  @author     David Madison + *  @link       github.com/dmadison/ArduinoXInput_AVR + *  @license    MIT - Copyright (c) 2019 David Madison + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + */ + +#include "USBAPI.h" + +#ifndef USB_XINPUT_DESCRIPTORS_H +#define USB_XINPUT_DESCRIPTORS_H + +#if defined(USBCON) + +// Device Descriptor +extern const DeviceDescriptor USB_DeviceDescriptor PROGMEM; + +// Config Descriptor +extern const u8  USB_ConfigDescriptor[] PROGMEM; +extern const u16 USB_ConfigDescriptorSize PROGMEM; + +// String Descriptors +extern const u8 STRING_SERIAL[] PROGMEM; +extern const u8 STRING_SECURITY[] PROGMEM; + +#define ISECURITY 4 + +// Endpoint Numbers +#define XINPUT_TX_ENDPOINT	1 +#define XINPUT_RX_ENDPOINT	2 + +#endif /* if defined(USBCON) */ + +#endif /* ifndef USB_XINPUT_DESCRIPTORS_H */ | 
