Skip to content

USB-Core Fixes #3562

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 4 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
69 changes: 64 additions & 5 deletions hardware/arduino/avr/cores/arduino/CDC.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -49,8 +49,8 @@ const CDCDescriptor _cdcInterface =

// 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,0x40,0),
D_ENDPOINT(USB_ENDPOINT_IN (CDC_ENDPOINT_IN ),USB_ENDPOINT_TYPE_BULK,0x40,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)
};

int CDC_GetInterface(u8* interfaceNum)
Expand Down Expand Up @@ -78,11 +78,13 @@ bool CDC_Setup(USBSetup& setup)
if (CDC_SET_LINE_CODING == r)
{
USB_RecvControl((void*)&_usbLineInfo,7);
CDC_LineEncodingEvent();
}

if (CDC_SET_CONTROL_LINE_STATE == r)
{
_usbLineInfo.lineState = setup.wValueL;
CDC_LineStateEvent();
}

if (CDC_SET_LINE_CODING == r || CDC_SET_CONTROL_LINE_STATE == r)
Expand All @@ -92,11 +94,25 @@ bool CDC_Setup(USBSetup& setup)
// with a relatively long period so it can finish housekeeping tasks
// like servicing endpoints before the sketch ends

#ifndef MAGIC_KEY
#define MAGIC_KEY 0x7777
#endif
#ifndef MAGIC_KEY_POS
#define MAGIC_KEY_POS (uint16_t *)0x0800
#endif
// NO_MAGIC_KEY_BACKUP can be used if you want to store the key in the safer RAMEND directly, so no backup is needed

// We check DTR state to determine if host port is open (bit 0 of lineState).
if (1200 == _usbLineInfo.dwDTERate && (_usbLineInfo.lineState & 0x01) == 0)
{
*(uint16_t *)(RAMEND-1) = *(uint16_t *)0x0800;
*(uint16_t *)0x0800 = 0x7777;
#if !defined(NO_MAGIC_KEY_BACKUP)
*(uint16_t *)(RAMEND-1) = *MAGIC_KEY_POS;
*MAGIC_KEY_POS = MAGIC_KEY;
#else
// for future boards save the key in the inproblematic RAMEND
// which is reserved for the main() return value (which will never return)
*MAGIC_KEY_POS = MAGIC_KEY;
#endif
wdt_enable(WDTO_120MS);
}
else
Expand All @@ -108,14 +124,27 @@ bool CDC_Setup(USBSetup& setup)

wdt_disable();
wdt_reset();
*(uint16_t *)0x0800 = *(uint16_t *)(RAMEND-1);
#if !defined(NO_MAGIC_KEY_BACKUP)
*MAGIC_KEY_POS = *(uint16_t *)(RAMEND-1);
#else
*MAGIC_KEY_POS = 0x0000;
#endif
}
}
return true;
}
return false;
}

void WEAK CDC_LineEncodingEvent(void)
{
// has to be implemented by the user
}

void WEAK CDC_LineStateEvent(void)
{
// has to be implemented by the user
}

void Serial_::begin(unsigned long /* baud_count */)
{
Expand Down Expand Up @@ -190,6 +219,36 @@ size_t Serial_::write(const uint8_t *buffer, size_t size)
return 0;
}

uint32_t Serial_::baud(void)
{
return _usbLineInfo.dwDTERate;
}

uint8_t Serial_::stopbits(void)
{
return _usbLineInfo.bCharFormat;
}

uint8_t Serial_::paritytype(void)
{
return _usbLineInfo.bParityType;
}

uint8_t Serial_::numbits(void)
{
return _usbLineInfo.bDataBits;
}

bool Serial_::dtr(void)
{
return (_usbLineInfo.lineState & CDC_CONTROL_LINE_OUT_DTR) ? true : false;
}

bool Serial_::rts(void)
{
return (_usbLineInfo.lineState & CDC_CONTROL_LINE_OUT_RTS) ? true : false;
}

// 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
Expand Down
30 changes: 22 additions & 8 deletions hardware/arduino/avr/cores/arduino/USBAPI.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,18 @@
#include <avr/interrupt.h>
#include <util/delay.h>

typedef unsigned char u8;
typedef unsigned char u8; //TODO remove
typedef unsigned short u16;
typedef unsigned long u32;

#include "Arduino.h"

// this definitions is usefull if you want to reduce the EP_SIZE to 16
// at the moment only 64 and 16 as EP_SIZE for all EPs are supported except the control endpoint
#ifndef USB_EP_SIZE
#define USB_EP_SIZE 64
#endif

#if defined(USBCON)

#include "USBDesc.h"
Expand All @@ -41,13 +47,13 @@ typedef unsigned long u32;
//================================================================================
// USB

#define EP_TYPE_CONTROL 0x00
#define EP_TYPE_BULK_IN 0x81
#define EP_TYPE_BULK_OUT 0x80
#define EP_TYPE_INTERRUPT_IN 0xC1
#define EP_TYPE_INTERRUPT_OUT 0xC0
#define EP_TYPE_ISOCHRONOUS_IN 0x41
#define EP_TYPE_ISOCHRONOUS_OUT 0x40
#define EP_TYPE_CONTROL (0x00)
#define EP_TYPE_BULK_IN ((1<<EPTYPE1) | (1<<EPDIR))
#define EP_TYPE_BULK_OUT (1<<EPTYPE1)
#define EP_TYPE_INTERRUPT_IN ((1<<EPTYPE1) | (1<<EPTYPE0) | (1<<EPDIR))
#define EP_TYPE_INTERRUPT_OUT ((1<<EPTYPE1) | (1<<EPTYPE0))
#define EP_TYPE_ISOCHRONOUS_IN ((1<<EPTYPE0) | (1<<EPDIR))
#define EP_TYPE_ISOCHRONOUS_OUT (1<<EPTYPE0)

class USBDevice_
{
Expand Down Expand Up @@ -96,6 +102,12 @@ class Serial_ : public Stream
virtual size_t write(uint8_t);
virtual size_t write(const uint8_t*, size_t);
using Print::write; // pull in write(str) and write(buf, size) from Print
uint32_t baud(void);
uint8_t stopbits(void);
uint8_t paritytype(void);
uint8_t numbits(void);
bool dtr(void);
bool rts(void);
operator bool();

volatile uint8_t _rx_buffer_head;
Expand Down Expand Up @@ -136,6 +148,8 @@ bool MSC_Data(uint8_t rx,uint8_t tx);
int CDC_GetInterface(uint8_t* interfaceNum);
int CDC_GetDescriptor(int i);
bool CDC_Setup(USBSetup& setup);
void CDC_LineEncodingEvent(void);
void CDC_LineStateEvent(void);

//================================================================================
//================================================================================
Expand Down
69 changes: 50 additions & 19 deletions hardware/arduino/avr/cores/arduino/USBCore.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,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;
Expand Down Expand Up @@ -253,7 +253,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
Expand Down Expand Up @@ -326,6 +326,7 @@ u8 _initEndpoints[] =

#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)
Expand All @@ -344,7 +345,13 @@ void InitEndpoints()
UENUM = i;
UECONX = (1<<EPEN);
UECFG0X = _initEndpoints[i];
UECFG1X = EP_DOUBLE_64;
#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;
Expand Down Expand Up @@ -620,63 +627,87 @@ void USB_Flush(u8 ep)

static inline void USB_ClockDisable()
{
USBCON = (USBCON & ~(1<<OTGPADE)) | (1<<FRZCLK); // freeze clock and disable VBUS Pad
PLLCSR &= ~(1<<PLLE); // stop PLL
#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()
{
UHWCON |= (1<<UVREGE); // power internal reg
USBCON = (1<<USBE) | (1<<FRZCLK); // clock frozen, usb enabled
#if defined(UHWCON)
UHWCON |= (1 << UVREGE); // power internal reg
#endif
USBCON = (1 << USBE) | (1 << FRZCLK); // clock frozen, usb enabled

// ATmega32U4
// ATmega32U4
#if defined(PINDIV)
#if F_CPU == 16000000UL
PLLCSR |= (1<<PINDIV); // Need 16 MHz xtal
PLLCSR |= (1 << PINDIV); // Need 16 MHz xtal
#elif F_CPU == 8000000UL
PLLCSR &= ~(1<<PINDIV); // Need 8 MHz xtal
PLLCSR &= ~(1 << PINDIV); // Need 8 MHz xtal
#else
#error "Clock rate of F_CPU not supported"
#endif

// AT90USB646, AT90USB647, AT90USB1286, AT90USB1287
#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
#if defined(__AVR_AT90USB1286__) || defined(__AVR_AT90USB1287__)
// For Atmel AT90USB128x only. Do not use with Atmel AT90USB64x.
PLLCSR = (PLLCSR & ~(1<<PLLP1)) | ((1<<PLLP2) | (1<<PLLP0)); // Need 16 MHz xtal
PLLCSR = (PLLCSR & ~(1 << PLLP1)) | ((1 << PLLP2) | (1 << PLLP0)); // Need 16 MHz xtal
#elif defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB647__)
// For AT90USB64x only. Do not use with AT90USB128x.
PLLCSR = (PLLCSR & ~(1<<PLLP0)) | ((1<<PLLP2) | (1<<PLLP1)); // Need 16 MHz xtal
PLLCSR = (PLLCSR & ~(1 << PLLP0)) | ((1 << PLLP2) | (1 << PLLP1)); // Need 16 MHz xtal
#else
#error "USB Chip not supported, please defined method of USB PLL initialization"
#endif
#elif F_CPU == 8000000UL
// for Atmel AT90USB128x and AT90USB64x
PLLCSR = (PLLCSR & ~(1<<PLLP2)) | ((1<<PLLP1) | (1<<PLLP0)); // Need 8 MHz xtal
PLLCSR = (PLLCSR & ~(1 << PLLP2)) | ((1 << PLLP1) | (1 << PLLP0)); // Need 8 MHz xtal
#else
#error "Clock rate of F_CPU not supported"
#endif
#else
#error "USB Chip not supported, please defined method of USB PLL initialization"
#endif

PLLCSR |= (1<<PLLE);
while (!(PLLCSR & (1<<PLOCK))) // wait for lock pll
PLLCSR |= (1 << PLLE);
while (!(PLLCSR & (1 << PLOCK))) // wait for lock pll
{
}

// Some tests on specific versions of macosx (10.7.3), reported some
// strange behaviors when the board is reset using the serial
// port touch at 1200 bps. This delay fixes this behavior.
delay(1);
USBCON = (USBCON & ~(1<<FRZCLK)) | (1<<OTGPADE); // start USB clock, enable VBUS Pad
#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)
UDCON &= ~((1<<RSTCPU) | (1<<LSM) | (1<<RMWKUP) | (1<<DETACH)); // enable attach resistor, set full speed mode
#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
UDCON &= ~((1 << LSM) | (1 << RMWKUP) | (1 << DETACH)); // enable attach resistor, set full speed mode
#endif
}

Expand Down
19 changes: 18 additions & 1 deletion hardware/arduino/avr/cores/arduino/USBCore.h
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,9 @@
#define CDC_GET_LINE_CODING 0x21
#define CDC_SET_CONTROL_LINE_STATE 0x22

#define CDC_CONTROL_LINE_OUT_DTR (1 << 0)
#define CDC_CONTROL_LINE_OUT_RTS (1 << 1)

#define MSC_RESET 0xFF
#define MSC_GET_MAX_LUN 0xFE

Expand Down Expand Up @@ -88,6 +91,20 @@
#define USB_DEVICE_CLASS_STORAGE 0x08
#define USB_DEVICE_CLASS_VENDOR_SPECIFIC 0xFF

// added new definitions for correct USB descriptors
// there are even more, these are the ones we need
#define USB_DEVICE_CLASS_IAD 0xEF
#define USB_DEVICE_SUB_CLASS_IAD 0x02
#define USB_DEVICE_PROTOCOL_IAD 0x01

#define USB_DEVICE_CDC_CLASS 0x02
#define USB_DEVICE_CDC_SUB_CLASS 0x00
#define USB_DEVICE_CDC_PROTOCOL 0x00 // NoSpecific Protocol

#define USB_DEVICE_NO_CLASS 0x00
#define USB_DEVICE_NO_SUB_CLASS 0x00
#define USB_DEVICE_NO_PROTOCOL 0x00

#define USB_CONFIG_POWERED_MASK 0x40
#define USB_CONFIG_BUS_POWERED 0x80
#define USB_CONFIG_SELF_POWERED 0xC0
Expand Down Expand Up @@ -276,4 +293,4 @@ typedef struct
#define D_CDCCS4(_subtype,_d0) { 4, 0x24, _subtype, _d0 }


#endif
#endif
2 changes: 1 addition & 1 deletion hardware/arduino/avr/libraries/HID/HID.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ int HID_GetInterface(u8* interfaceNum)
{
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)
D_ENDPOINT(USB_ENDPOINT_IN (HID_ENDPOINT_INT),USB_ENDPOINT_TYPE_INTERRUPT, USB_EP_SIZE ,0x01)
};
return USB_SendControl(0,&_hidInterface,sizeof(_hidInterface));
}
Expand Down
4 changes: 2 additions & 2 deletions hardware/arduino/avr/libraries/HID/HID.h
Original file line number Diff line number Diff line change
Expand Up @@ -88,10 +88,10 @@ typedef struct
#define HID_TX HID_ENDPOINT_INT

#define D_HIDREPORT(_descriptorLength) \
{ 9, 0x21, 0x1, 0x1, 0, 1, 0x22, _descriptorLength, 0 }
{ 9, 0x21, 0x1, 0x1, 0, 1, 0x22, _descriptorLength, _descriptorLength >> 8 }

#define WEAK __attribute__ ((weak))

#endif

#endif
#endif