From da03595c32f3822d0b8c96ab61ec7b65131196ee Mon Sep 17 00:00:00 2001 From: Zach Eveland Date: Thu, 27 Oct 2011 10:23:06 -0400 Subject: brought nuevo_diskloader changes over to diskloader Moved nuevo_diskloader files into diskloader directory. Changed back to real PID for Leonardo --- bootloaders/diskloader/src/USBCore.cpp | 609 +++++++++++++++++++++------------ 1 file changed, 385 insertions(+), 224 deletions(-) (limited to 'bootloaders/diskloader/src/USBCore.cpp') diff --git a/bootloaders/diskloader/src/USBCore.cpp b/bootloaders/diskloader/src/USBCore.cpp index ca74721..56944e5 100644 --- a/bootloaders/diskloader/src/USBCore.cpp +++ b/bootloaders/diskloader/src/USBCore.cpp @@ -17,9 +17,10 @@ */ #include "Platform.h" +#include "USBAPI.h" +#include "USBDesc.h" -#define CDC_TX CDC_ENDPOINT_IN -#define CDC_RX CDC_ENDPOINT_OUT +#if defined(USBCON) #define EP_TYPE_CONTROL 0x00 #define EP_TYPE_BULK_IN 0x81 @@ -31,32 +32,54 @@ /** Pulse generation counters to keep track of the number of milliseconds remaining for each pulse type */ #define TX_RX_LED_PULSE_MS 100 -u8 TxLEDPulse; /**< Milliseconds remaining for data Tx LED pulse */ -u8 RxLEDPulse; /**< Milliseconds remaining for data Rx LED pulse */ - -void Reboot(); +volatile u8 TxLEDPulse; /**< Milliseconds remaining for data Tx LED pulse */ +volatile u8 RxLEDPulse; /**< Milliseconds remaining for data Rx LED pulse */ //================================================================== //================================================================== -typedef struct -{ - u32 dwDTERate; - u8 bCharFormat; - u8 bParityType; - u8 bDataBits; - u8 lineState; -} LineInfo; +extern const u16 STRING_LANGUAGE[] PROGMEM; +extern const u16 STRING_IPRODUCT[] PROGMEM; +extern const u16 STRING_IMANUFACTURER[] PROGMEM; +extern const DeviceDescriptor USB_DeviceDescriptor PROGMEM; +extern const DeviceDescriptor USB_DeviceDescriptorA PROGMEM; + +const u16 STRING_LANGUAGE[2] = { + (3<<8) | (2+2), + 0x0409 // English +}; + +const u16 STRING_IPRODUCT[17] = { + (3<<8) | (2+2*16), +#if USB_PID == USB_PID_LEONARDO + 'A','r','d','u','i','n','o',' ','L','e','o','n','a','r','d','o' +#elif USB_PID == USB_PID_MICRO + 'A','r','d','u','i','n','o',' ','M','i','c','r','o',' ',' ',' ' +#endif +}; -static volatile LineInfo _usbLineInfo = { 57600, 0x00, 0x00, 0x00, 0x00 }; +const u16 STRING_IMANUFACTURER[12] = { + (3<<8) | (2+2*11), + 'A','r','d','u','i','n','o',' ','L','L','C' +}; + +#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,0,1); + +const DeviceDescriptor USB_DeviceDescriptorA = + D_DEVICE(DEVICE_CLASS,0x00,0x00,64,USB_VID,USB_PID,0x100,IMANUFACTURER,IPRODUCT,0,1); //================================================================== //================================================================== -// 4 bytes of RAM -volatile u8 _usbConfiguration; -volatile u8 _ejected; -volatile u16 _timeout; +volatile u8 _usbConfiguration = 0; static inline void WaitIN(void) { @@ -86,34 +109,25 @@ static inline void ClearOUT(void) UEINTX = ~(1< len) + n = len; + len -= n; + { + LockEP lock(ep); + if (ep & TRANSFER_ZERO) + { + while (n--) + Send8(0); + } + else if (ep & TRANSFER_PGM) + { + while (n--) + Send8(pgm_read_byte(data++)); + } + else + { + while (n--) + Send8(*data++); + } + if (!ReadWriteAllowed() || ((len == 0) && (ep & TRANSFER_RELEASE))) // Release full buffer + ReleaseTX(); + } } if (ep & TRANSFER_RELEASE) ReleaseTX(); + + TX_LED_ON(); + TxLEDPulse = TX_RX_LED_PULSE_MS; + return r; } extern const u8 _initEndpoints[] PROGMEM; const u8 _initEndpoints[] = { 0, - + #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 - EP_TYPE_INTERRUPT_IN, // HID_ENDPOINT_INT +#ifdef HID_ENABLED + EP_TYPE_INTERRUPT_IN // HID_ENDPOINT_INT +#endif }; -static void InitEndpoints() +#define EP_SINGLE_64 0x32 // EP0 +#define EP_DOUBLE_64 0x36 // Other endpoints + +static +void InitEP(u8 index, u8 type, u8 size) +{ + UENUM = index; + UECONX = 1; + UECFG0X = type; + UECFG1X = size; +} + +static +void InitEndpoints() { for (u8 i = 1; i < sizeof(_initEndpoints); i++) { @@ -277,99 +365,123 @@ static void InitEndpoints() UERST = 0; } -typedef struct +// Handle CLASS_INTERFACE requests +static +bool ClassInterfaceRequest(Setup& setup) { - u8 bmRequestType; - u8 bRequest; - u8 wValueL; - u8 wValueH; - u16 wIndex; - u16 wLength; -} Setup; -Setup _setup; + u8 i = setup.wIndex; -//bool USBHook(Setup& setup) -bool USBHook() -{ - Setup& setup = _setup; - u8 r = setup.bRequest; +#ifdef CDC_ENABLED + if (CDC_ACM_INTERFACE == i) + return CDC_Setup(setup); +#endif - // CDC Requests - if (CDC_GET_LINE_CODING == r) - { - Send((const volatile u8*)&_usbLineInfo,7); - } + return false; +} - else if (CDC_SET_LINE_CODING == r) +int _cmark; +int _cend; +void InitControl(int end) +{ + SetEP(0); + _cmark = 0; + _cend = end; +} + +static +bool SendControl(u8 d) +{ + if (_cmark < _cend) { - WaitOUT(); - Recv((volatile u8*)&_usbLineInfo,7); - ClearOUT(); + if (!WaitForINOrOUT()) + return false; + Send8(d); + if (!((_cmark + 1) & 0x3F)) + ClearIN(); // Fifo is full, release this packet } + _cmark++; + return true; +}; - else if (CDC_SET_CONTROL_LINE_STATE == r) +// Clipped by _cmark/_cend +int USB_SendControl(u8 flags, const void* d, int len) +{ + int sent = len; + const u8* data = (const u8*)d; + bool pgm = flags & TRANSFER_PGM; + while (len--) { - _usbLineInfo.lineState = setup.wValueL; + u8 c = pgm ? pgm_read_byte(data++) : *data++; + if (!SendControl(c)) + return -1; } - - return true; + return sent; } -extern const u8 _rawHID[] PROGMEM; -#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 +// Does not timeout or cross fifo boundaries +// Will only work for transfers <= 64 bytes +// TODO +int USB_RecvControl(void* d, int len) +{ + WaitOUT(); + Recv((u8*)d,len); + ClearOUT(); + return len; +} -const u8 _rawHID[] = +int SendInterfaces() { - // RAW HID - 0x06, LSB(RAWHID_USAGE_PAGE), MSB(RAWHID_USAGE_PAGE), // 30 - 0x0A, LSB(RAWHID_USAGE), MSB(RAWHID_USAGE), + int total = 0; + u8 interfaces = 0; - 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 +#ifdef CDC_ENABLED + total = CDC_GetInterface(&interfaces); +#endif - 0x95, 64, // report count TX - 0x09, 0x01, // usage - 0x81, 0x02, // Input (array) + return interfaces; +} - 0x95, 64, // report count RX - 0x09, 0x02, // usage - 0x91, 0x02, // Output (array) - 0xC0 // end collection -}; +// Construct a dynamic configuration descriptor +// This really needs dynamic endpoint allocation etc +// TODO +static +bool SendConfiguration(int maxlen) +{ + // Count and measure interfaces + InitControl(0); + int interfaces = SendInterfaces(); + ConfigDescriptor config = D_CONFIG(_cmark + sizeof(ConfigDescriptor),interfaces); + + // Now send them + InitControl(maxlen); + USB_SendControl(0,&config,sizeof(ConfigDescriptor)); + SendInterfaces(); + return true; +} u8 _cdcComposite = 0; -bool SendDescriptor() +static +bool SendDescriptor(Setup& setup) { - Setup& setup = _setup; + u8 t = setup.wValueH; + if (USB_CONFIGURATION_DESCRIPTOR_TYPE == t) + return SendConfiguration(setup.wLength); + + InitControl(setup.wLength); +#ifdef HID_ENABLED + if (HID_REPORT_DESCRIPTOR_TYPE == t) + return HID_GetDescriptor(t); +#endif + u8 desc_length = 0; const u8* desc_addr = 0; - - u8 t = setup.wValueH; - if (0x22 == t) - { - desc_addr = _rawHID; - desc_length = sizeof(desc_length); - } else if (USB_DEVICE_DESCRIPTOR_TYPE == t) + if (USB_DEVICE_DESCRIPTOR_TYPE == t) { if (setup.wLength == 8) _cdcComposite = 1; desc_addr = _cdcComposite ? (const u8*)&USB_DeviceDescriptorA : (const u8*)&USB_DeviceDescriptor; } - else if (USB_CONFIGURATION_DESCRIPTOR_TYPE == t) - { - desc_addr = (const u8*)&USB_ConfigDescriptor; - desc_length = sizeof(USB_ConfigDescriptor); - } else if (USB_STRING_DESCRIPTOR_TYPE == t) { if (setup.wValueL == 0) @@ -380,81 +492,106 @@ bool SendDescriptor() desc_addr = (const u8*)&STRING_IMANUFACTURER; else return false; - } else - return false; + } + if (desc_addr == 0) + return false; if (desc_length == 0) desc_length = pgm_read_byte(desc_addr); - if ((u8)setup.wLength < desc_length) // bit of a cheat limiting to 255 bytes TODO (saved 8 bytes) - desc_length = (u8)setup.wLength; - - // Send descriptor - // EP0 is 64 bytes long - // RWAL and FIFOCON don't work on EP0 - u8 n = 0; - do - { - if (!WaitForINOrOUT()) - return false; - Send8(pgm_read_byte(&desc_addr[n++])); - u8 clr = n & 0x3F; - if (!clr) - ClearIN(); // Fifo is full, release this packet - } while (n < desc_length); + + USB_SendControl(TRANSFER_PGM,desc_addr,desc_length); return true; } -void USBSetupInterrupt() +// Endpoint 0 interrupt +ISR(USB_COM_vect) { SetEP(0); if (!ReceivedSetupInt()) return; - Setup& setup = _setup; // global saves ~30 bytes + Setup setup; Recv((u8*)&setup,8); ClearSetupInt(); - if (setup.bmRequestType & DEVICETOHOST) + u8 requestType = setup.bmRequestType; + if (requestType & REQUEST_DEVICETOHOST) WaitIN(); else ClearIN(); bool ok = true; - u8 r = setup.bRequest; - if (SET_ADDRESS == r) - { - WaitIN(); - UDADDR = setup.wValueL | (1<