remove USBCore.cpp as no need anymore
Seems USB is handled better no so this patch is no more needed Before when you unpluged the usb cable when a connection with host was ongoing the printer freeze and then watchdog reset printer - now it is fine - so better to remove the patchdevt
rodzic
86da478994
commit
0769b917c3
|
@ -1,900 +0,0 @@
|
||||||
// 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>
|
|
||||||
#include "PluggableUSB.h"
|
|
||||||
#include <stdint.h>
|
|
||||||
|
|
||||||
//#define TRACE_CORE(x) x
|
|
||||||
#define TRACE_CORE(x)
|
|
||||||
|
|
||||||
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 PLUGGABLE_USB_ENABLED
|
|
||||||
//allocate 6 endpoints and remove const so they can be changed by the user
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
#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
|
|
||||||
#define USB_PRODUCT "Arduino Due"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
const uint8_t STRING_PRODUCT[] = USB_PRODUCT;
|
|
||||||
|
|
||||||
#ifndef USB_MANUFACTURER
|
|
||||||
#define USB_MANUFACTURER "Arduino LLC"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
const uint8_t STRING_MANUFACTURER[] = 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,USB_PID,0x100,IMANUFACTURER,IPRODUCT,ISERIAL,1);
|
|
||||||
|
|
||||||
const DeviceDescriptor USB_DeviceDescriptorA =
|
|
||||||
D_DEVICE(0xEF,0x02,0x01,64,USB_VID,USB_PID,0x100,IMANUFACTURER,IPRODUCT,ISERIAL,1);
|
|
||||||
|
|
||||||
const QualifierDescriptor 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 __attribute__ ((unused))) : 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)
|
|
||||||
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;
|
|
||||||
//USB PATCH to avoid dead loop
|
|
||||||
int count=0;
|
|
||||||
while( UOTGHS_DEVEPTISR_TXINI != (UOTGHS->UOTGHS_DEVEPTISR[ep & 0xF] & UOTGHS_DEVEPTISR_TXINI ))
|
|
||||||
{
|
|
||||||
count++;
|
|
||||||
if (count>10000) return len;
|
|
||||||
}
|
|
||||||
UDD_Send(ep & 0xF, data, n);
|
|
||||||
data += n;
|
|
||||||
}
|
|
||||||
//TXLED1; // light the TX LED
|
|
||||||
//TxLEDPulse = TX_RX_LED_PULSE_MS;
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint16_t _cmark;
|
|
||||||
uint16_t _cend;
|
|
||||||
|
|
||||||
void USBD_InitControl(int end)
|
|
||||||
{
|
|
||||||
_cmark = 0;
|
|
||||||
_cend = end;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Clipped by _cmark/_cend
|
|
||||||
int USBD_SendControl(uint8_t flags __attribute__ ((unused)), 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) {
|
|
||||||
if (wLength < 2)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
uint8_t buffer[wLength];
|
|
||||||
buffer[0] = strlen((const char*)string) * 2 + 2;
|
|
||||||
buffer[1] = 0x03;
|
|
||||||
|
|
||||||
uint8_t i;
|
|
||||||
for (i = 2; i < wLength && *string; i++) {
|
|
||||||
buffer[i++] = *string++;
|
|
||||||
if (i == wLength) break;
|
|
||||||
buffer[i] = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
return USBD_SendControl(0, (uint8_t*)buffer, i);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 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(USBSetup& 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 PLUGGABLE_USB_ENABLED
|
|
||||||
return PluggableUSB().setup(setup);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8_t USBD_SendInterfaces(void)
|
|
||||||
{
|
|
||||||
uint8_t interfaces = 0;
|
|
||||||
|
|
||||||
#ifdef CDC_ENABLED
|
|
||||||
CDC_GetInterface(&interfaces);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef PLUGGABLE_USB_ENABLED
|
|
||||||
PluggableUSB().getInterface(&interfaces);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
TRACE_CORE(printf("=> USBD_SendInterfaces, interfaces=%d\r\n", interfaces);)
|
|
||||||
return interfaces;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8_t USBD_SendOtherInterfaces(void)
|
|
||||||
{
|
|
||||||
uint8_t interfaces = 0;
|
|
||||||
|
|
||||||
#ifdef CDC_ENABLED
|
|
||||||
CDC_GetOtherInterface(&interfaces);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef PLUGGABLE_USB_ENABLED
|
|
||||||
PluggableUSB().getInterface(&interfaces);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
TRACE_CORE(printf("=> USBD_SendInterfaces, interfaces=%d\r\n", 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);)
|
|
||||||
uint8_t 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);)
|
|
||||||
uint8_t 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(USBSetup& setup)
|
|
||||||
{
|
|
||||||
uint8_t t = setup.wValueH;
|
|
||||||
uint8_t desc_length = 0;
|
|
||||||
int ret = 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 PLUGGABLE_USB_ENABLED
|
|
||||||
ret = PluggableUSB().getDescriptor(setup);
|
|
||||||
if (ret != 0) {
|
|
||||||
return (ret > 0 ? true : false);
|
|
||||||
}
|
|
||||||
#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 if (setup.wValueL == ISERIAL) {
|
|
||||||
#ifdef PLUGGABLE_USB_ENABLED
|
|
||||||
char name[ISERIAL_MAX_LEN];
|
|
||||||
PluggableUSB().getShortName(name);
|
|
||||||
return USB_SendStringDescriptor((uint8_t*)name, setup.wLength);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
USBSetup 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);)
|
|
||||||
|
|
||||||
uint32_t num_endpoints = 0;
|
|
||||||
while (EndPoints[num_endpoints] != 0) {
|
|
||||||
num_endpoints++;
|
|
||||||
}
|
|
||||||
UDD_InitEndpoints(EndPoints, num_endpoints);
|
|
||||||
_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()
|
|
||||||
{
|
|
||||||
}
|
|
Ładowanie…
Reference in New Issue