aboutsummaryrefslogtreecommitdiff
path: root/cores/arduino/USBCore.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'cores/arduino/USBCore.cpp')
-rw-r--r--cores/arduino/USBCore.cpp89
1 files changed, 62 insertions, 27 deletions
diff --git a/cores/arduino/USBCore.cpp b/cores/arduino/USBCore.cpp
index 8237ccb..3c6610c 100644
--- a/cores/arduino/USBCore.cpp
+++ b/cores/arduino/USBCore.cpp
@@ -18,6 +18,7 @@
#include "USBAPI.h"
#include "PluggableUSB.h"
+#include <stdlib.h>
#if defined(USBCON)
@@ -69,10 +70,10 @@ const u8 STRING_MANUFACTURER[] PROGMEM = USB_MANUFACTURER;
// DEVICE DESCRIPTOR
const DeviceDescriptor USB_DeviceDescriptor =
- D_DEVICE(0x00,0x00,0x00,64,USB_VID,USB_PID,0x100,IMANUFACTURER,IPRODUCT,0,1);
+ D_DEVICE(0x00,0x00,0x00,64,USB_VID,USB_PID,0x100,IMANUFACTURER,IPRODUCT,ISERIAL,1);
const DeviceDescriptor USB_DeviceDescriptorB =
- D_DEVICE(0xEF,0x02,0x01,64,USB_VID,USB_PID,0x100,IMANUFACTURER,IPRODUCT,0,1);
+ D_DEVICE(0xEF,0x02,0x01,64,USB_VID,USB_PID,0x100,IMANUFACTURER,IPRODUCT,ISERIAL,1);
//==================================================================
//==================================================================
@@ -110,7 +111,7 @@ static inline void ClearOUT(void)
UEINTX = ~(1<<RXOUTI);
}
-void Recv(volatile u8* data, u8 count)
+static inline void Recv(volatile u8* data, u8 count)
{
while (count--)
*data++ = UEDATX;
@@ -253,7 +254,7 @@ u8 USB_SendSpace(u8 ep)
LockEP lock(ep);
if (!ReadWriteAllowed())
return 0;
- return 64 - FifoByteCount();
+ return USB_EP_SIZE - FifoByteCount();
}
// Blocking Send of data to an endpoint
@@ -308,24 +309,20 @@ int USB_Send(u8 ep, const void* d, int len)
return r;
}
-u8 _initEndpoints[] =
+u8 _initEndpoints[USB_ENDPOINTS] =
{
- 0,
+ 0, // Control Endpoint
- EP_TYPE_INTERRUPT_IN, // CDC_ENDPOINT_ACM
- EP_TYPE_BULK_OUT, // CDC_ENDPOINT_OUT
- EP_TYPE_BULK_IN, // CDC_ENDPOINT_IN
+ EP_TYPE_INTERRUPT_IN, // CDC_ENDPOINT_ACM
+ EP_TYPE_BULK_OUT, // CDC_ENDPOINT_OUT
+ EP_TYPE_BULK_IN, // CDC_ENDPOINT_IN
-#ifdef PLUGGABLE_USB_ENABLED
- //allocate 3 endpoints and remove const so they can be changed by the user
- 0,
- 0,
- 0,
-#endif
+ // 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
void InitEP(u8 index, u8 type, u8 size)
@@ -344,7 +341,13 @@ void InitEndpoints()
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;
@@ -360,13 +363,13 @@ bool ClassInterfaceRequest(USBSetup& setup)
return CDC_Setup(setup);
#ifdef PLUGGABLE_USB_ENABLED
- return PUSB_Setup(setup, i);
+ return PluggableUSB().setup(setup);
#endif
return false;
}
-int _cmark;
-int _cend;
+static int _cmark;
+static int _cend;
void InitControl(int end)
{
SetEP(0);
@@ -407,11 +410,12 @@ int USB_SendControl(u8 flags, const void* d, int len)
// Send a USB descriptor string. The string is stored in PROGMEM as a
// plain ASCII string but is sent out as UTF-16 with the correct 2-byte
// prefix
-static bool USB_SendStringDescriptor(const u8*string_P, u8 string_len) {
+static bool USB_SendStringDescriptor(const u8*string_P, u8 string_len, uint8_t flags) {
SendControl(2 + string_len * 2);
SendControl(3);
+ bool pgm = flags & TRANSFER_PGM;
for(u8 i = 0; i < string_len; i++) {
- bool r = SendControl(pgm_read_byte(&string_P[i]));
+ bool r = SendControl(pgm ? pgm_read_byte(&string_P[i]) : string_P[i]);
r &= SendControl(0); // high byte
if(!r) {
return false;
@@ -431,14 +435,14 @@ int USB_RecvControl(void* d, int len)
return len;
}
-int SendInterfaces()
+static u8 SendInterfaces()
{
u8 interfaces = 0;
CDC_GetInterface(&interfaces);
#ifdef PLUGGABLE_USB_ENABLED
- PUSB_GetInterface(&interfaces);
+ PluggableUSB().getInterface(&interfaces);
#endif
return interfaces;
@@ -452,7 +456,7 @@ bool SendConfiguration(int maxlen)
{
// Count and measure interfaces
InitControl(0);
- int interfaces = SendInterfaces();
+ u8 interfaces = SendInterfaces();
ConfigDescriptor config = D_CONFIG(_cmark + sizeof(ConfigDescriptor),interfaces);
// Now send them
@@ -462,7 +466,7 @@ bool SendConfiguration(int maxlen)
return true;
}
-u8 _cdcComposite = 0;
+static u8 _cdcComposite = 0;
static
bool SendDescriptor(USBSetup& setup)
@@ -474,7 +478,7 @@ bool SendDescriptor(USBSetup& setup)
InitControl(setup.wLength);
#ifdef PLUGGABLE_USB_ENABLED
- ret = PUSB_GetDescriptor(t);
+ ret = PluggableUSB().getDescriptor(setup);
if (ret != 0) {
return (ret > 0 ? true : false);
}
@@ -493,10 +497,17 @@ bool SendDescriptor(USBSetup& setup)
desc_addr = (const u8*)&STRING_LANGUAGE;
}
else if (setup.wValueL == IPRODUCT) {
- return USB_SendStringDescriptor(STRING_PRODUCT, strlen(USB_PRODUCT));
+ return USB_SendStringDescriptor(STRING_PRODUCT, strlen(USB_PRODUCT), TRANSFER_PGM);
}
else if (setup.wValueL == IMANUFACTURER) {
- return USB_SendStringDescriptor(STRING_MANUFACTURER, strlen(USB_MANUFACTURER));
+ return USB_SendStringDescriptor(STRING_MANUFACTURER, strlen(USB_MANUFACTURER), TRANSFER_PGM);
+ }
+ else if (setup.wValueL == ISERIAL) {
+#ifdef PLUGGABLE_USB_ENABLED
+ char name[ISERIAL_MAX_LEN];
+ PluggableUSB().getShortName(name);
+ return USB_SendStringDescriptor((uint8_t*)name, strlen(name), 0);
+#endif
}
else
return false;
@@ -620,13 +631,19 @@ void USB_Flush(u8 ep)
static inline void USB_ClockDisable()
{
+#if defined(OTGPADE)
USBCON = (USBCON & ~(1<<OTGPADE)) | (1<<FRZCLK); // freeze clock and disable VBUS Pad
+#else // u2 Series
+ USBCON = (1 << FRZCLK); // freeze clock
+#endif
PLLCSR &= ~(1<<PLLE); // stop PLL
}
static inline void USB_ClockEnable()
{
+#if defined(UHWCON)
UHWCON |= (1<<UVREGE); // power internal reg
+#endif
USBCON = (1<<USBE) | (1<<FRZCLK); // clock frozen, usb enabled
// ATmega32U4
@@ -639,6 +656,16 @@ static inline void USB_ClockEnable()
#error "Clock rate of F_CPU not supported"
#endif
+#elif defined(__AVR_AT90USB82__) || defined(__AVR_AT90USB162__) || defined(__AVR_ATmega32U2__) || defined(__AVR_ATmega16U2__) || defined(__AVR_ATmega8U2__)
+ // for the u2 Series the datasheet is confusing. On page 40 its called PINDIV and on page 290 its called PLLP0
+#if F_CPU == 16000000UL
+ // Need 16 MHz xtal
+ PLLCSR |= (1 << PLLP0);
+#elif F_CPU == 8000000UL
+ // Need 8 MHz xtal
+ PLLCSR &= ~(1 << PLLP0);
+#endif
+
// AT90USB646, AT90USB647, AT90USB1286, AT90USB1287
#elif defined(PLLP2)
#if F_CPU == 16000000UL
@@ -670,10 +697,18 @@ static inline void USB_ClockEnable()
// strange behaviors when the board is reset using the serial
// port touch at 1200 bps. This delay fixes this behavior.
delay(1);
+#if defined(OTGPADE)
USBCON = (USBCON & ~(1<<FRZCLK)) | (1<<OTGPADE); // start USB clock, enable VBUS Pad
+#else
+ USBCON &= ~(1 << FRZCLK); // start USB clock
+#endif
#if defined(RSTCPU)
+#if defined(LSM)
UDCON &= ~((1<<RSTCPU) | (1<<LSM) | (1<<RMWKUP) | (1<<DETACH)); // enable attach resistor, set full speed mode
+#else // u2 Series
+ UDCON &= ~((1 << RSTCPU) | (1 << RMWKUP) | (1 << DETACH)); // enable attach resistor, set full speed mode
+#endif
#else
// AT90USB64x and AT90USB128x don't have RSTCPU
UDCON &= ~((1<<LSM) | (1<<RMWKUP) | (1<<DETACH)); // enable attach resistor, set full speed mode