From 0ecdd723cf88cf6675998d19f69d212f8ddc8c7a Mon Sep 17 00:00:00 2001 From: Zach Eveland Date: Thu, 11 Aug 2011 10:31:39 -0400 Subject: [PATCH] diskloader source and binary for 32u4 --- hardware/arduino/boards.txt | 2 +- .../diskloader/Arduino_Leonardo.inf | 106 ++++ .../bootloaders/diskloader/DiskLoader.hex | 95 ++++ .../arduino/bootloaders/diskloader/Makefile | 99 ++++ .../bootloaders/diskloader/src/DiskLoader.cpp | 246 +++++++++ .../bootloaders/diskloader/src/Platform.h | 69 +++ .../bootloaders/diskloader/src/SCSI.cpp | 213 ++++++++ .../bootloaders/diskloader/src/ThinFAT.cpp | 130 +++++ .../bootloaders/diskloader/src/USBCore.cpp | 513 ++++++++++++++++++ .../bootloaders/diskloader/src/USBCore.h | 261 +++++++++ .../bootloaders/diskloader/src/USBDesc.cpp | 88 +++ .../bootloaders/diskloader/src/USBDesc.h | 81 +++ 12 files changed, 1902 insertions(+), 1 deletion(-) create mode 100644 hardware/arduino/bootloaders/diskloader/Arduino_Leonardo.inf create mode 100644 hardware/arduino/bootloaders/diskloader/DiskLoader.hex create mode 100644 hardware/arduino/bootloaders/diskloader/Makefile create mode 100644 hardware/arduino/bootloaders/diskloader/src/DiskLoader.cpp create mode 100644 hardware/arduino/bootloaders/diskloader/src/Platform.h create mode 100644 hardware/arduino/bootloaders/diskloader/src/SCSI.cpp create mode 100644 hardware/arduino/bootloaders/diskloader/src/ThinFAT.cpp create mode 100644 hardware/arduino/bootloaders/diskloader/src/USBCore.cpp create mode 100644 hardware/arduino/bootloaders/diskloader/src/USBCore.h create mode 100644 hardware/arduino/bootloaders/diskloader/src/USBDesc.cpp create mode 100644 hardware/arduino/bootloaders/diskloader/src/USBDesc.h diff --git a/hardware/arduino/boards.txt b/hardware/arduino/boards.txt index 8ffc8d71b..4c847a9e6 100644 --- a/hardware/arduino/boards.txt +++ b/hardware/arduino/boards.txt @@ -8,7 +8,7 @@ leonardo.bootloader.low_fuses=0xde leonardo.bootloader.high_fuses=0xd8 leonardo.bootloader.extended_fuses=0xf3 leonardo.bootloader.path=diskloader -leonardo.bootloader.file=diskloader_atmega32u4.hex +leonardo.bootloader.file=DiskLoader.hex leonardo.bootloader.unlock_bits=0x3F leonardo.bootloader.lock_bits=0x0F leonardo.build.mcu=atmega32u4 diff --git a/hardware/arduino/bootloaders/diskloader/Arduino_Leonardo.inf b/hardware/arduino/bootloaders/diskloader/Arduino_Leonardo.inf new file mode 100644 index 000000000..8c3feb35f --- /dev/null +++ b/hardware/arduino/bootloaders/diskloader/Arduino_Leonardo.inf @@ -0,0 +1,106 @@ +;************************************************************ +; Windows USB CDC ACM Setup File +; Copyright (c) 2000 Microsoft Corporation + + +[Version] +Signature="$Windows NT$" +Class=Ports +ClassGuid={4D36E978-E325-11CE-BFC1-08002BE10318} +Provider=%MFGNAME% +LayoutFile=layout.inf +CatalogFile=%MFGFILENAME%.cat +DriverVer=11/15/2007,5.1.2600.0 + +[Manufacturer] +%MFGNAME%=DeviceList, NTamd64 + +[DestinationDirs] +DefaultDestDir=12 + + +;------------------------------------------------------------------------------ +; Windows 2000/XP/Vista-32bit Sections +;------------------------------------------------------------------------------ + +[DriverInstall.nt] +include=mdmcpq.inf +CopyFiles=DriverCopyFiles.nt +AddReg=DriverInstall.nt.AddReg + +[DriverCopyFiles.nt] +usbser.sys,,,0x20 + +[DriverInstall.nt.AddReg] +HKR,,DevLoader,,*ntkern +HKR,,NTMPDriver,,%DRIVERFILENAME%.sys +HKR,,EnumPropPages32,,"MsPorts.dll,SerialPortPropPageProvider" + +[DriverInstall.nt.Services] +AddService=usbser, 0x00000002, DriverService.nt + +[DriverService.nt] +DisplayName=%SERVICE% +ServiceType=1 +StartType=3 +ErrorControl=1 +ServiceBinary=%12%\%DRIVERFILENAME%.sys + +;------------------------------------------------------------------------------ +; Vista-64bit Sections +;------------------------------------------------------------------------------ + +[DriverInstall.NTamd64] +include=mdmcpq.inf +CopyFiles=DriverCopyFiles.NTamd64 +AddReg=DriverInstall.NTamd64.AddReg + +[DriverCopyFiles.NTamd64] +%DRIVERFILENAME%.sys,,,0x20 + +[DriverInstall.NTamd64.AddReg] +HKR,,DevLoader,,*ntkern +HKR,,NTMPDriver,,%DRIVERFILENAME%.sys +HKR,,EnumPropPages32,,"MsPorts.dll,SerialPortPropPageProvider" + +[DriverInstall.NTamd64.Services] +AddService=usbser, 0x00000002, DriverService.NTamd64 + +[DriverService.NTamd64] +DisplayName=%SERVICE% +ServiceType=1 +StartType=3 +ErrorControl=1 +ServiceBinary=%12%\%DRIVERFILENAME%.sys + + +;------------------------------------------------------------------------------ +; Vendor and Product ID Definitions +;------------------------------------------------------------------------------ +; When developing your USB device, the VID and PID used in the PC side +; application program and the firmware on the microcontroller must match. +; Modify the below line to use your VID and PID. Use the format as shown below. +; Note: One INF file can be used for multiple devices with different VID and PIDs. +; For each supported device, append ",USB\VID_xxxx&PID_yyyy" to the end of the line. +;------------------------------------------------------------------------------ +[SourceDisksFiles] +[SourceDisksNames] +[DeviceList] +%DESCRIPTION%=DriverInstall, USB\VID_2341&PID_0020&MI_00 + +[DeviceList.NTamd64] +%DESCRIPTION%=DriverInstall, USB\VID_2341&PID_0020&MI_00 + + +;------------------------------------------------------------------------------ +; String Definitions +;------------------------------------------------------------------------------ +;Modify these strings to customize your device +;------------------------------------------------------------------------------ +[Strings] +MFGFILENAME="CDC_vista" +DRIVERFILENAME ="usbser" +MFGNAME="Arduino LLC (www.arduino.cc)" +INSTDISK="Arduino Leonardo Driver Installer" +DESCRIPTION="Arduino Lenonardo" +SERVICE="USB RS-232 Emulation Driver" \ No newline at end of file diff --git a/hardware/arduino/bootloaders/diskloader/DiskLoader.hex b/hardware/arduino/bootloaders/diskloader/DiskLoader.hex new file mode 100644 index 000000000..cf484d035 --- /dev/null +++ b/hardware/arduino/bootloaders/diskloader/DiskLoader.hex @@ -0,0 +1,95 @@ +:1078000011241FBECFEFDAE0DEBFCDBFC4C04101FF +:1078100042144505560455026403740300001E9586 +:1078200087020110030000C18081C106C0FF0A0069 +:107830000CA10185037508150026FF00954009017C +:107840008102954009029102C0040309041A033021 +:1078500000300030003000300030003000300031A7 +:1078600000370030003100120100020200004041E8 +:1078700023200000010000010112010002000000AD +:1078800040412320000001000001010902640003BF +:1078900001008032080B000202020100090400000E +:1078A0000102020000052400100105240101010469 +:1078B0002402020524060001070581031000400987 +:1078C000040100020A000000070502024000000750 +:1078D00005830240000009040200010300000009C2 +:1078E0002101010001221E00070584034000400021 +:1078F00080918A0190918B01019690938B018093E6 +:107900008A01089581E08093E0001092E200EE2762 +:10791000FF27099408950F931F93CF93DF93982F18 +:10792000EB01042F10E088E76030780730F411E0B5 +:1079300083E0FB0180935700E895892F68E071E0B0 +:10794000402FCED0112311F107B600FCFDCF402F00 +:107950004695FE01A8E0B1E020E031E009C08D913C +:107960009D910C0130935700E895112432962F5FBA +:107970002417A8F385E0FE0180935700E89507B629 +:1079800000FCFDCF81E180935700E895DF91CF9116 +:107990001F910F9108958BD084E18093880180E13D +:1079A00080938901E0E0F0E0859194918F5F9F4F93 +:1079B00019F081E080938D01EE24FF24DD24D3941F +:1079C000D6D1082F8EE098E7FC01249131960296DB +:1079D0004491201711F02223B9F710928F011092D1 +:1079E0008E0182E068E071E07BD0013479F460912F +:1079F00008016058633028F0683111F064E001C07C +:107A000063E0C62FD0E0CF5DD74808C0063579F4D3 +:107A100080910801803321F0C5E2D8E711E029C048 +:107A200080910A01C82FD0E0C25ED748F7CF053752 +:107A300021F4CEE1D8E713E01CC0053539F4E0901D +:107A40000801F0900901EE0CFF1C0AC0043631F465 +:107A500082E0B701409109015EDF02C0043721F0E6 +:107A6000C5E2D8E710E005C010910901E701E10E79 +:107A7000F11C7DD18097B1F483E068E871E041E0CA +:107A800050E044D0112329F0412F50E083E8BE019B +:107A90003DD083E469E871E041E050E037D0013542 +:107AA00009F08ECFD0928D01EE24FF2489CF109261 +:107AB0008F0110928E0110928C0110928D0181E045 +:107AC0008093D70080EA8093D80082E189BD09B411 +:107AD00000FEFDCF80E98093D8001092E000089569 +:107AE000FB018093E9009BE60EC08091E80085FFD2 +:107AF000FCCF8091F10081938091E80085FD02C068 +:107B00009093E8004150442381F70895982FFB019A +:107B1000282F207287708093E9003AE314C0809187 +:107B2000E80085FFFCCF97FF02C0849101C08081EF +:107B30003196211180E08093F1008091E80085FD6D +:107B400002C03093E800415050408FEF4F3F58073C +:107B500031F796FF03C08AE38093E800089580918F +:107B60009101813279F420E030E003C0808180937C +:107B7000F100F901E050FF4F2F5F3F4F28303105F2 +:107B8000A9F71EC08032B1F48091E80082FFFCCFDB +:107B900020E030E003C08091F1008083F901E050E3 +:107BA000FF4F2F5F3F4F28303105A9F78BEF8093B0 +:107BB000E80006C0823221F480919201809307018F +:107BC00081E0089520919301223231F1213081F436 +:107BD0008091960190919701089711F42093980154 +:107BE00080919801882309F03AC0E9E7F8E739C0A5 +:107BF000223021F484E6EBE8F8E711C0233069F580 +:107C000080919201882319F4E9E4F8E72AC08130D1 +:107C100021F5EDE4F8E725C081E0EBE2F8E790918B +:107C20009601282F981708F4292F90E03EEF8091B5 +:107C3000E8008570E1F38091E80082FD0EC09F5F4F +:107C400084918093F100892F8F7311F43093E800B1 +:107C50003196921760F381E0089580E00895E7E699 +:107C6000F8E78491DCCF1092E9008091E80083FF6F +:107C70005FC0E0E9F1E003C08091F100819381E011 +:107C8000E839F807C9F782EF8093E8008091900106 +:107C900087FF05C08091E80080FFFCCF03C08EEF16 +:107CA0008093E80080919101853051F48091E80043 +:107CB00080FFFCCF8091920180688093E30031C007 +:107CC0008930E1F48091920180938C01E7E2F8E73A +:107CD00091E031E026E39093E9003093EB0084914A +:107CE0008093EC002093ED009F5F3196953099F7DB +:107CF0008EE78093EA001092EA0013C0883029F4DE +:107D000080918C018093F1000CC0882319F41092AB +:107D1000F10007C0863011F455DF01C020DF882351 +:107D200021F08EEF8093E800089581E28093EB00CC +:107D300008958091E1001092E100282F83FF0CC08C +:107D40001092E90081E08093EB001092EC0082E356 +:107D50008093ED0010928C0122FF08C080918D016C +:107D6000882321F410928F0110928E0108951F93A1 +:107D700012E079DFDEDF1093E9008091E80085FFF3 +:107D80000DC09091F1008091E80085FD03C08BE665 +:107D90008093E800892F90E01F91089580918E01D3 +:107DA00090918F01019790938F0180938E01809124 +:107DB0008E0190918F01892B09F4A4DD99DDD9CF33 +:087DC00000E1000000000000DA +:040000030000780081 +:00000001FF diff --git a/hardware/arduino/bootloaders/diskloader/Makefile b/hardware/arduino/bootloaders/diskloader/Makefile new file mode 100644 index 000000000..ca6e11e33 --- /dev/null +++ b/hardware/arduino/bootloaders/diskloader/Makefile @@ -0,0 +1,99 @@ +############################################################################### +# Makefile for DiskLoader +############################################################################### + +## General Flags +PROJECT = DiskLoader +TARGET = DiskLoader.elf +CC = avr-gcc + +# BOARD2 +MCU = atmega32u4 +AVR_FREQ = 16000000L + + +# Change if your programmer is different +AVRDUDE_PROGRAMMER = avrispmkII +AVRDUDE_PORT = usb + +# program name should not be changed... +PROGRAM = DiskLoader + +AVRDUDE = avrdude +AVRDUDE_FLAGS = -p $(MCU) -P $(AVRDUDE_PORT) -c $(AVRDUDE_PROGRAMMER) -p $(MCU) + +## Options common to compile, link and assembly rules +COMMON = -mmcu=$(MCU) + +override CFLAGS = -g -Wall -Os -mmcu=$(MCU) -DF_CPU=$(AVR_FREQ) $(DEFS) -ffunction-sections -gdwarf-2 -fdata-sections -fno-split-wide-types + +## Assembly specific flags +ASMFLAGS = $(COMMON) +ASMFLAGS += $(CFLAGS) +ASMFLAGS += -x assembler-with-cpp -Wa,-gdwarf2 + +## Linker flags +LDFLAGS = $(COMMON) +LDFLAGS += -Wl,-gc-sections,-Map=DiskLoader.map,--section-start=.text=0x7800,--relax +LDFLAGS += -nodefaultlibs -nostartfiles + + +## Intel Hex file production flags +HEX_EEPROM_FLAGS = -j .eeprom +HEX_EEPROM_FLAGS += --set-section-flags=.eeprom="alloc,load" +HEX_EEPROM_FLAGS += --change-section-lma .eeprom=0 --no-change-warnings + +## Objects explicitly added by the user +LINKONLYOBJECTS = + +MODULES := . +SRC_DIR := $(addprefix src/,$(MODULES)) +BUILD_DIR := $(addprefix build/,$(MODULES)) + +SRC := $(foreach sdir,$(SRC_DIR),$(wildcard $(sdir)/*.cpp)) +OBJ := $(patsubst src/%.cpp,build/%.o,$(SRC)) +DEP := $(OBJ:%.o=%.d) +INCLUDES := $(addprefix -I,$(SRC_DIR)) + +vpath %.cpp $(SRC_DIR) + +.PHONY: all checkdirs clean + +all: checkdirs $(TARGET) DiskLoader.hex DiskLoader.lss size + +-include $(DEP) + +checkdirs: $(BUILD_DIR) + +$(BUILD_DIR): + @mkdir -p $@ + +clean: + @rm -rf build/ + @rm -f *.hex + @rm -f *.elf + @rm -f *.lss + @rm -f *.map + +define make-goal +$1/%.o: %.cpp + $(CC) $(INCLUDES) $(CFLAGS) -c $$< -MD -o $$@ +endef + +$(foreach bdir,$(BUILD_DIR),$(eval $(call make-goal,$(bdir)))) + +$(TARGET): $(OBJ) + $(CC) $(LDFLAGS) $(LINKONLYOBJECTS) $(LIBDIRS) $(LIBS) $^ -o $@ + +%.hex: $(TARGET) + avr-objcopy -O ihex $(HEX_FLASH_FLAGS) $< $@ + +%.lss: $(TARGET) + avr-objdump -h -S $< > $@ + +size: $(TARGET) + @echo +# @avr-size -C --mcu=${MCU} ${TARGET}.elf + +program: $(TARGET).hex + $(AVRDUDE) $(AVRDUDE_FLAGS) -B 5 -u -U flash:w:$(TARGET).hex \ No newline at end of file diff --git a/hardware/arduino/bootloaders/diskloader/src/DiskLoader.cpp b/hardware/arduino/bootloaders/diskloader/src/DiskLoader.cpp new file mode 100644 index 000000000..3cb5caaeb --- /dev/null +++ b/hardware/arduino/bootloaders/diskloader/src/DiskLoader.cpp @@ -0,0 +1,246 @@ + + +#include "Platform.h" + +// This bootloader creates a composite Serial/Mass storage device +// +// The serial interface supports a STK500v1 protocol that is very similar to optiboot +// The mass storage interface emulates a disk image that is used to read or write firmware.bin files +// Delete firmware.bin and copy a new binary (not .hex) file to flash the firmware i.e: +// +// cp firmware.bin f:/. -f +// +// Ejecting the disk will run the firmware +// +// The bootloader will timeout and start the firmware after a few hundred milliseconds +// if a usb connection is not detected. +// +// The tweakier code is to keep the bootloader below 2k (no interrupt table, for example) + +extern "C" +void entrypoint(void) __attribute__ ((naked)) __attribute__ ((section (".vectors"))); +void entrypoint(void) +{ + asm volatile ( + "eor r1, r1\n" // Zero register + "out 0x3F, r1\n" // SREG + "ldi r28, 0xFF\n" + "ldi r29, 0x0A\n" + "out 0x3E, r29\n" // SPH + "out 0x3D, r28\n" // SPL + "rjmp main" // Stack is all set up, start the main code + ::); +} + +u8 _flashbuf[128]; +u8 _inSync; +u8 _ok; +extern volatile u8 _ejected; +extern volatile u16 _timeout; + +void Program(u8 ep, u16 page, u8 count) +{ + u8 write = page < 30*1024; // Don't write over firmware please + if (write) + boot_page_erase(page); + + Recv(ep,_flashbuf,count); // Read while page is erasing + + if (!write) + return; + + boot_spm_busy_wait(); // Wait until the memory is erased. + + count >>= 1; + u16* p = (u16*)page; + u16* b = (u16*)_flashbuf; + for (u8 i = 0; i < count; i++) + boot_page_fill(p++, b[i]); + + boot_page_write(page); + boot_spm_busy_wait(); + boot_rww_enable (); +} + + +int USBGetChar(); +#define getch USBGetChar + +#define HW_VER 0x02 +#define SW_MAJOR 0x01 +#define SW_MINOR 0x10 + +#define STK_OK 0x10 +#define STK_INSYNC 0x14 // ' ' +#define CRC_EOP 0x20 // 'SPACE' +#define STK_GET_SYNC 0x30 // '0' + +#define STK_GET_PARAMETER 0x41 // 'A' +#define STK_SET_DEVICE 0x42 // 'B' +#define STK_SET_DEVICE_EXT 0x45 // 'E' +#define STK_LOAD_ADDRESS 0x55 // 'U' +#define STK_UNIVERSAL 0x56 // 'V' +#define STK_PROG_PAGE 0x64 // 'd' +#define STK_READ_PAGE 0x74 // 't' +#define STK_READ_SIGN 0x75 // 'u' + +extern const u8 _readSize[] PROGMEM; +const u8 _readSize[] = +{ + STK_GET_PARAMETER, 1, + STK_SET_DEVICE, 20, + STK_SET_DEVICE_EXT, 5, + STK_UNIVERSAL, 4, + STK_LOAD_ADDRESS, 2, + STK_PROG_PAGE, 3, + STK_READ_PAGE, 3, + 0,0 +}; + +extern const u8 _consts[] PROGMEM; +const u8 _consts[] = +{ + SIGNATURE_0, + SIGNATURE_1, + SIGNATURE_2, + HW_VER, // Hardware version + SW_MAJOR, // Software major version + SW_MINOR, // Software minor version + 0x03, // Unknown but seems to be required by avr studio 3.56 + 0x00, // +}; + + +void USBInit(void); +extern u8 _sector3[512]; + +int main(void) __attribute__ ((naked)); + +// STK500v1 main loop, very similar to optiboot in protocol and implementation +int main() +{ + BOARD_INIT(); + USBInit(); + +#ifdef WRITABLE_DIRECTORY + _sector3[0] = 0; +#endif + + _inSync = STK_INSYNC; + _ok = STK_OK; +#ifndef MSC_ENABLED + if (pgm_read_word(0) != -1) + _ejected = 1; +#endif + for(;;) + { + u8* packet = _flashbuf; + u16 address = 0; + for (;;) + { + u8 cmd = getch(); + + // Read packet contents + u8 len; + const u8* rs = _readSize; + for(;;) + { + u8 c = pgm_read_byte(rs++); + len = pgm_read_byte(rs++); + if (c == cmd || c == 0) + break; + } +#ifndef MSC_ENABLED + _timeout = 0; +#endif + // Read params + Recv(CDC_RX,packet,len); + + // Send a response + u8 send = 0; + const u8* pgm = _consts+7; // 0 + if (STK_GET_PARAMETER == cmd) + { + u8 i = packet[0] - 0x80; + if (i > 2) + i = (i == 0x18) ? 3 : 4; // 0x80:HW_VER,0x81:SW_MAJOR,0x82:SW_MINOR,0x18:3 or 0 + pgm = _consts + i + 3; + send = 1; + } + + else if (STK_UNIVERSAL == cmd) + { + if (packet[0] == 0x30) + pgm = _consts + packet[2]; // read signature + send = 1; + } + + // Read signature bytes + else if (STK_READ_SIGN == cmd) + { + pgm = _consts; + send = 3; + } + + else if (STK_LOAD_ADDRESS == cmd) + { + address = *((u16*)packet); // word addresses + address += address; + } + + else if (STK_PROG_PAGE == cmd) + { + Program(CDC_RX,address,packet[1]); + } + + else if (STK_READ_PAGE == cmd) + { + send = packet[1]; + pgm = (const u8*)address; + address += send; // not sure of this is required + } + + // Check sync + if (getch() != ' ') + break; + Transfer(CDC_TX,&_inSync,1); + + // Send result + if (send) + Transfer(CDC_TX|TRANSFER_PGM,pgm,send); // All from pgm memory + + // Send ok + Transfer(CDC_TX|TRANSFER_RELEASE,&_ok,1); + + if (cmd == 'Q') + break; + } + _ejected = 1; + } +} + +// Nice breathing LED indicates we are in the firmware +u16 _pulse; +void LEDPulse() +{ + _pulse++; + u8 p = _pulse >> 8; + if (p > 127) + p = 255-p; + p += p; + if (((u8)_pulse) > p) + LED0; + else + LED1; +} + +void Reboot() +{ + UDCON = 1; // Detatch USB + UDIEN = 0; + asm volatile ( // Reset vector to run firmware + "clr r30\n" + "clr r31\n" + "ijmp\n" + ::); +} diff --git a/hardware/arduino/bootloaders/diskloader/src/Platform.h b/hardware/arduino/bootloaders/diskloader/src/Platform.h new file mode 100644 index 000000000..8e4ae3ab1 --- /dev/null +++ b/hardware/arduino/bootloaders/diskloader/src/Platform.h @@ -0,0 +1,69 @@ + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +typedef unsigned char u8; +typedef unsigned short u16; +typedef unsigned long u32; + +//#define MICROTOUCH + +//#define WRITABLE_DIRECTORY // undef saved 56 + 512 RAM + +#define FAT_DISK_LABEL 'b','o','o','t','l','o','a','d','e','r',' ' // 11 chars (undef saves 12) +#define FAT_FILE_NAME 'F','I','R','M','W','A','R','E','B','I','N' // 11 chars +#define MSC_DISK_SERIAL '0','0','0','0','0','0','0','0','1','7','0','1' // 12 chars + + +#define CPU_PRESCALE(n) (CLKPR = 0x80, CLKPR = (n)) +#define DISABLE_JTAG() MCUCR = (1 << JTD) | (1 << IVCE) | (0 << PUD); MCUCR = (1 << JTD) | (0 << IVSEL) | (0 << IVCE) | (0 << PUD); + + +#ifdef MICROTOUCH + +#define USB_VID 0x239A // Adafruit vid +#define USB_PID 0x2001 // sorry dave sprach zarathustra + +#define FAT_OEM_NAME 'r','o','s','s','u','m','u','r' // 8 chars +#define BOARD_INIT() DDRC = 0xFF; CPU_PRESCALE(0); DISABLE_JTAG(); +#define LED0 PORTC &= ~(1<<7) +#define LED1 PORTC |= (1<<7) +#define BACKLIGHT0 PORTC &= ~(1<<6) +#define BACKLIGHT1 PORTC |= (1<<6) + +#else + +#define USB_VID 0x2341 // arduino LLC vid +#define USB_PID 0x0020 // educated guess + +#define FAT_OEM_NAME 'l','e','o','n','a','r','d','o' // 8 chars +#define BOARD_INIT() // etc +#define LED0 +#define LED1 + +#endif + +#define TRANSFER_PGM 0x80 +#define TRANSFER_RELEASE 0x40 +#define TRANSFER_ZERO 0x20 + +void Transfer(u8 ep, const u8* data, int len); +void Recv(u8 ep, u8* dst, u8 len); +void Program(u8 ep, u16 page, u8 count); + +#define CDC_ENABLED +//#define MSC_ENABLED +//#define MSC_NO_MEDIA // MSC is enabled but not media inserted + +#include "USBCore.h" +#include "USBDesc.h" + + diff --git a/hardware/arduino/bootloaders/diskloader/src/SCSI.cpp b/hardware/arduino/bootloaders/diskloader/src/SCSI.cpp new file mode 100644 index 000000000..dbbf9cf6e --- /dev/null +++ b/hardware/arduino/bootloaders/diskloader/src/SCSI.cpp @@ -0,0 +1,213 @@ + + +/* 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 "Platform.h" + +#ifdef MSC_ENABLED + +// SCSI Commands +#define TEST_UNIT_READY 0x00 +#define REQUEST_SENSE 0x03 +#define FORMAT_UNIT 0x04 +#define INQUIRY 0x12 +#define MODE_SENSE 0x1A +#define START_STOP_UNIT 0x1B +#define MEDIA_REMOVAL 0x1E +#define READ_FORMAT_CAPACITIES 0x23 +#define READ_CAPACITY 0x25 +#define READ10 0x28 +#define WRITE10 0x2A +#define VERIFY10 0x2F + + +// In FakeFAT +void SendSector(u8 b); +void RecvSector(u8 b); + +// In USBCore +u8 RecvPacket(u8 ep, u8* dst, u8 len); +u8 SendPacket(u8 ep, const u8* src, u8 len); +void Reboot(); + +#define MSC_TX MSC_ENDPOINT_IN +#define MSC_RX MSC_ENDPOINT_OUT + +extern const u8 P_Inquiry[36] PROGMEM; +extern const u8 P_RequestSense[18] PROGMEM; +extern const u8 P_ReadCapacity[8-3] PROGMEM; +extern const u8 P_ModeSense[4] PROGMEM; + +typedef struct +{ + u8 signature[4]; + u8 tag[4]; + u32 transferLength; + u8 flags; + u8 lun; + u8 cblength; + u8 cb[16]; +} CBW; + +const u8 P_Inquiry[36] = +{ + 0x00, // Direct Access Device + 0x80, // Removable Medium + 0x00, // Version + 0x01, + + 36-4, // Additional Length + 0x80, // Storage Controller Component + 0x00, + 0x00, + + 'r','o','s','s','u','m','u','r', // Vendor + + 'm','i','c','r','o','t','o','u', // Product + 'c','h',' ',' ',' ',' ',' ',' ', + + '2','.','4',' ' // Revision +}; + +const u8 P_RequestSense[18] = +{ + 0x70, // Response Code + 0x00, +// 0x02, // Sense Key + 0x00, + 0x00, + + 0x00, + 0x00, + 0x00, + 0x0A, // Additional Length + + 0x00, + 0x00, + 0x00, + 0x00, + + 0x30, // ASC + 0x01, // ASCQ + + 0x00, + 0x00, + 0x00, + 0x00 +}; + +// Save 3 bytes if merging +const u8 P_ReadCapacity[8-3] = +{ +// 0x00, +// 0x00, +// 0x00, // Steal 3 zero bytes from end of P_RequestSense + 64+4, // block count 64 + 4 + 0x00, + 0x00, + 0x02, // block size = 512 + 0x00 +}; + +const u8 P_ModeSense[4] = +{ + 0x03, + 0x00, + 0x00, + 0x00 +}; + +extern volatile u8 _ejected; + +void SCSI(CBW& cbw) +{ + const u8* pgm = 0; + u8 status = 0; + u8 blen = 0; + + u8 cmd = cbw.cb[0]; + if (START_STOP_UNIT == cmd) + { + _ejected = 1; // Stopped; going away + } + else if (TEST_UNIT_READY == cmd || MEDIA_REMOVAL == cmd) + { +#ifdef MSC_NO_MEDIA + status = 1; +#else + status = _ejected; +#endif + } + else if (REQUEST_SENSE == cmd) + { + pgm = P_RequestSense; + blen = sizeof(P_RequestSense); + } + else if (INQUIRY == cmd) + { + pgm = P_Inquiry; + blen = sizeof(P_Inquiry); + } + else if (WRITE10 == cmd || READ10 == cmd) + { + // Write 10 byte form + // Read 10 byte form + { + u8 lba = cbw.cb[5]; + u8 count = cbw.cb[8]; + u8 read = READ10 == cbw.cb[0]; + while (count--) + { + if (read) + SendSector(lba); + else + RecvSector(lba); + lba++; + cbw.transferLength -= 512; // 24 bytes + } + } + } + else if (MODE_SENSE == cmd) + { + pgm = P_ModeSense; + blen = 4; + } + else + { + pgm = P_ReadCapacity-3; + blen = 8; + if (READ_CAPACITY != cmd) + status = 1; // Faking a data phase for unknown commands + } + + if (pgm) + Transfer(MSC_TX | TRANSFER_PGM | TRANSFER_RELEASE,pgm,blen); + + cbw.flags = status; + cbw.transferLength -= blen; + cbw.signature[3] = 'S'; + Transfer(MSC_TX | TRANSFER_RELEASE,(u8*)&cbw,13); +} + +CBW cbw; // 38 byte savings by making this global +void SCSITask() +{ + Recv(MSC_RX,(u8*)&cbw,sizeof(CBW)); + SCSI(cbw); +} + +#endif \ No newline at end of file diff --git a/hardware/arduino/bootloaders/diskloader/src/ThinFAT.cpp b/hardware/arduino/bootloaders/diskloader/src/ThinFAT.cpp new file mode 100644 index 000000000..c23874170 --- /dev/null +++ b/hardware/arduino/bootloaders/diskloader/src/ThinFAT.cpp @@ -0,0 +1,130 @@ + + +/* Copyright (c) 2011, 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 "Platform.h" + +#ifdef MSC_ENABLED + +extern const u8 Sector_0[] PROGMEM; +extern const u8 Sector_1[] PROGMEM; +extern const u8 Sector_2[] PROGMEM; +extern const u8 Sector_3[] PROGMEM; +extern const u8 Sector_Size[] PROGMEM; + + +const u8 Sector_0[27] = +{ + 0xEB,0x3C,0x90, + FAT_OEM_NAME, + 0x00,0x02, // Bytes per sector 512 + 0x40, // Sectors per Cluster 32k per cluster + 0x01,0x00, // Reserved sectors + 0x02, // FATSs + 0x10,0x00, // root entries + 4+64,0x00, // number of sectors: 30k file + 0xF8, // Media type fixed + 0x01,0x00, // Sectors per FAT + 0x01,0x00, // Sectors per head + 0x01,//0x00, // Heads per cylinder + //0x00,0x00,0x00,0x00, // Hidden + //0x00,0x00,0x00,0x00, // long number of sectors + //0x00,0x00, // Ext flags + // 38 bytes +}; + +// FAT12 clusters for 32k file +const u8 Sector_1[] = +{ +#if 0 + 0xF8,0xFF,0xFF, + 0xFF,0x0F//,0x00 +#endif +}; + +const u8 Sector_2[] = +{ +}; + +const u8 Sector_3[] = +{ +#if 0 + FAT_FILE_NAME, 0x00,0x00,0x00,0x00,0x00, // Uppercase name please + 0x43,0x3E,0x43,0x3E,0x00,0x00,0xAB,0x8C,0x40,0x3E,0x02,0x00,0x00,0x80,//0x00,0x00 + // 0x00,0x00, +#endif + +#ifdef FAT_DISK_LABEL + FAT_DISK_LABEL,0x28 +#endif +}; + +#if 0 +const u8 Sector_Size[] = +{ + 0, + sizeof(Sector_0), + sizeof(Sector_0) + sizeof(Sector_1), + sizeof(Sector_0) + sizeof(Sector_1) + sizeof(Sector_2), + sizeof(Sector_0) + sizeof(Sector_1) + sizeof(Sector_2) + sizeof(Sector_3) +}; +#endif + +const u8* LBAToROM(u8 b) +{ + b -= 4; + return (const u8*)(b << 9); +} + +void SendSector(u8 b) +{ + if (b == 0) + { + u8 n = sizeof(Sector_0); + Transfer(MSC_TX | TRANSFER_PGM,Sector_0,n); + Transfer(MSC_TX | TRANSFER_ZERO,0,512-n); + return; + } + + if ((b < 4) || (b >= 64)) + { + Transfer(MSC_TX | TRANSFER_ZERO,0,512); + return; + } + + // Copy body of file from ROM + Transfer(MSC_TX | TRANSFER_PGM,LBAToROM(b),512); +} + +#define GENERATE_INVALID_ROM_ADDRESS 60 + +void RecvSector(u8 lba) +{ + if ((lba < 4) || (lba >= 64)) + lba = GENERATE_INVALID_ROM_ADDRESS; // Only care about the first 30k + + // Write sectors to flash + u16 addr = (u16)LBAToROM(lba); // may generate out of range addresses, Program will fix + u8 i = 4; // 4x128 is a sector + while (i--) + { + Program(MSC_RX,addr,128); + addr += 128; + } +} + +#endif \ No newline at end of file diff --git a/hardware/arduino/bootloaders/diskloader/src/USBCore.cpp b/hardware/arduino/bootloaders/diskloader/src/USBCore.cpp new file mode 100644 index 000000000..b6f8c44dc --- /dev/null +++ b/hardware/arduino/bootloaders/diskloader/src/USBCore.cpp @@ -0,0 +1,513 @@ + + +/* 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 "Platform.h" + +#define MSC_TX MSC_ENDPOINT_IN +#define MSC_RX MSC_ENDPOINT_OUT +#define CDC_TX CDC_ENDPOINT_IN +#define CDC_RX CDC_ENDPOINT_OUT + +#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 + +void Reboot(); + +//================================================================== +//================================================================== + +typedef struct +{ + u32 dwDTERate; + u8 bCharFormat; + u8 bParityType; + u8 bDataBits; + u8 lineState; +} LineInfo; + +static volatile LineInfo _usbLineInfo = { 57600, 0x00, 0x00, 0x00, 0x00 }; + +//================================================================== +//================================================================== + +// 4 bytes of RAM +volatile u8 _usbConfiguration; +volatile u8 _ejected; +volatile u16 _timeout; + +static inline void WaitIN(void) +{ + while (!(UEINTX & (1<> 8) + +#define RAWHID_USAGE_PAGE 0xFFC0 +#define RAWHID_USAGE 0x0C00 +#define RAWHID_TX_SIZE 64 +#define RAWHID_RX_SIZE 64 + +const u8 _rawHID[] = +{ + // RAW HID + 0x06, LSB(RAWHID_USAGE_PAGE), MSB(RAWHID_USAGE_PAGE), // 30 + 0x0A, LSB(RAWHID_USAGE), MSB(RAWHID_USAGE), + + 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 + + 0x95, 64, // report count TX + 0x09, 0x01, // usage + 0x81, 0x02, // Input (array) + + 0x95, 64, // report count RX + 0x09, 0x02, // usage + 0x91, 0x02, // Output (array) + 0xC0 // end collection +}; + +u8 _cdcComposite = 0; + +bool SendDescriptor() +{ + Setup& setup = _setup; + 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 (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) + desc_addr = (const u8*)&STRING_LANGUAGE; + else if (setup.wValueL == ISERIAL) + desc_addr = (const u8*)&STRING_SERIAL; + else + return false; + } else + 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); + return true; +} + +void USBSetupInterrupt() +{ + SetEP(0); + if (!ReceivedSetupInt()) + return; + + Setup& setup = _setup; // global saves ~30 bytes + Recv((u8*)&setup,8); + ClearSetupInt(); + + if (setup.bmRequestType & DEVICETOHOST) + WaitIN(); + else + ClearIN(); + + bool ok = true; + u8 r = setup.bRequest; + if (SET_ADDRESS == r) + { + WaitIN(); + UDADDR = setup.wValueL | (1<> 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 + + + +// Device +typedef struct { + u8 len; // 18 + u8 dtype; // 1 USB_DEVICE_DESCRIPTOR_TYPE + u16 usbVersion; // 0x200 + u8 deviceClass; + u8 deviceSubClass; + u8 deviceProtocol; + u8 packetSize0; // Packet 0 + u16 idVendor; + u16 idProduct; + u16 deviceVersion; // 0x100 + u8 iManufacturer; + u8 iProduct; + u8 iSerialNumber; + u8 bNumConfigurations; +} DeviceDescriptor; + +// Config +typedef struct { + u8 len; // 9 + u8 dtype; // 2 + u16 clen; // total length + u8 numInterfaces; + u8 config; + u8 iconfig; + u8 attributes; + u8 maxPower; +} ConfigDescriptor; + +// String + +// Interface +typedef struct +{ + u8 len; // 9 + u8 dtype; // 4 + u8 number; + u8 alternate; + u8 numEndpoints; + u8 interfaceClass; + u8 interfaceSubClass; + u8 protocol; + u8 iInterface; +} InterfaceDescriptor; + +// Endpoint +typedef struct +{ + u8 len; // 7 + u8 dtype; // 5 + u8 addr; + u8 attr; + u16 packetSize; + 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 +{ + IADDescriptor iad; // Only needed on compound device + + // Control + InterfaceDescriptor cif; // + CDCCSInterfaceDescriptor header; + CDCCSInterfaceDescriptor callManagement; + CDCCSInterfaceDescriptor4 controlManagement; + CDCCSInterfaceDescriptor functionalDescriptor; + EndpointDescriptor cifin; + + // Data + InterfaceDescriptor dif; + EndpointDescriptor in; + EndpointDescriptor out; +} CDCDescriptor; + +typedef struct +{ + InterfaceDescriptor msc; + EndpointDescriptor in; + EndpointDescriptor out; +} MSCDescriptor; + +typedef struct +{ + u8 len; // 9 + u8 dtype; // 0x21 + u8 addr; + u8 versionL; // 0x101 + u8 versionH; // 0x101 + u8 country; + u8 desctype; // 0x22 report + u8 descLenL; + u8 descLenH; +} HIDDescDescriptor; + +typedef struct +{ + InterfaceDescriptor hid; + HIDDescDescriptor desc; + EndpointDescriptor in; +} HIDDescriptor; + +#define D_DEVICE(_class,_subClass,_proto,_packetSize0,_vid,_pid,_version,_im,_ip,_is,_configs) \ + { 18, 1, 0x200, _class,_subClass,_proto,_packetSize0,_vid,_pid,_version,_im,_ip,_is,_configs } + +#define D_CONFIG(_totalLength,_interfaces) \ + { 9, 2, _totalLength,_interfaces, 1, 0, USB_CONFIG_BUS_POWERED, USB_CONFIG_POWER_MA(100) } + +#define D_INTERFACE(_n,_numEndpoints,_class,_subClass,_protocol) \ + { 9, 4, _n, 0, _numEndpoints, _class,_subClass, _protocol, 0 } + +#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_HIDREPORT(_descriptorLength) \ + { 9, 0x21, 0x1, 0x1, 0, 1, 0x22, _descriptorLength, 0 } + +#define D_CDCCS(_subtype,_d0,_d1) { 5, 0x24, _subtype, _d0, _d1 } +#define D_CDCCS4(_subtype,_d0) { 4, 0x24, _subtype, _d0 } + +#endif \ No newline at end of file diff --git a/hardware/arduino/bootloaders/diskloader/src/USBDesc.cpp b/hardware/arduino/bootloaders/diskloader/src/USBDesc.cpp new file mode 100644 index 000000000..dfde01da6 --- /dev/null +++ b/hardware/arduino/bootloaders/diskloader/src/USBDesc.cpp @@ -0,0 +1,88 @@ + + +/* Copyright (c) 2011, 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 "Platform.h" + +//==================================================================================================== +//==================================================================================================== +// Actual device descriptors + +const u16 STRING_LANGUAGE[2] = { + (3<<8) | (2+2), + 0x0409 // English +}; + +#if 0 +const u16 STRING_PRODUCT[] = { + (3<<8) | (2+2*10), + 'M','i','c','r','o','t','o','u','c','h' +}; +#endif + +const u16 STRING_SERIAL[13] = { + (3<<8) | (2+2*12), + MSC_DISK_SERIAL +}; + + +//#ifdef CDC_ENABLED +DeviceDescriptor USB_DeviceDescriptorA = D_DEVICE(0X02,0X00,0X00,64,USB_VID,USB_PID,0x100,0,IPRODUCT,ISERIAL,1); +//#else +DeviceDescriptor USB_DeviceDescriptor = D_DEVICE(0x00,0x00,0x00,64,USB_VID,USB_PID,0x100,0,IPRODUCT,ISERIAL,1); +//#endif + +Config USB_ConfigDescriptor = +{ + D_CONFIG(sizeof(Config),INTERFACE_COUNT), + +#ifdef CDC_ENABLED + // CDC + { + D_IAD(0,2,CDC_COMMUNICATION_INTERFACE_CLASS,CDC_ABSTRACT_CONTROL_MODEL,1), + + // 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 + D_CDCCS4(CDC_ABSTRACT_CONTROL_MANAGEMENT,2), // 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,0x40,0), + D_ENDPOINT(USB_ENDPOINT_IN (CDC_ENDPOINT_IN ),USB_ENDPOINT_TYPE_BULK,0x40,0) + }, +#endif + // HID + { + D_INTERFACE(HID_INTERFACE,1,3,0,0), + D_HIDREPORT(30), + D_ENDPOINT(USB_ENDPOINT_IN (HID_ENDPOINT_INT),USB_ENDPOINT_TYPE_INTERRUPT,0x40,0x40) + }, + +#ifdef MSC_ENABLED + // Mass Storage + { + D_INTERFACE(MSC_INTERFACE,2,USB_DEVICE_CLASS_STORAGE,MSC_SUBCLASS_SCSI,MSC_PROTOCOL_BULK_ONLY), + D_ENDPOINT(USB_ENDPOINT_OUT(MSC_ENDPOINT_OUT),USB_ENDPOINT_TYPE_BULK,0x40,0), + D_ENDPOINT(USB_ENDPOINT_IN (MSC_ENDPOINT_IN ),USB_ENDPOINT_TYPE_BULK,0x40,0) + } +#endif +}; + diff --git a/hardware/arduino/bootloaders/diskloader/src/USBDesc.h b/hardware/arduino/bootloaders/diskloader/src/USBDesc.h new file mode 100644 index 000000000..a551d6992 --- /dev/null +++ b/hardware/arduino/bootloaders/diskloader/src/USBDesc.h @@ -0,0 +1,81 @@ + + +/* Copyright (c) 2011, 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. +*/ + + +#ifndef CDC_ENABLED + +#define MSC_INTERFACE 0 // MSC Interface +#define MSC_ENDPOINT_OUT 1 +#define MSC_ENDPOINT_IN 2 + +#define INTERFACE_COUNT 1 // 1 for msc + +#else + +#define CDC_ACM_INTERFACE 0 // CDC ACM +#define CDC_DATA_INTERFACE 1 // CDC Data +#define CDC_ENDPOINT_ACM 1 +#define CDC_ENDPOINT_OUT 2 +#define CDC_ENDPOINT_IN 3 + +#define HID_INTERFACE 2 // HID Interface +#define HID_ENDPOINT_INT 4 + +#ifdef MSC_ENABLED + +#define MSC_INTERFACE 3 // MSC Interface +#define MSC_ENDPOINT_OUT 5 +#define MSC_ENDPOINT_IN 6 +#define INTERFACE_COUNT 4 // 2 for cdc + 1 for hid + 1 for msc + +#else + +#define INTERFACE_COUNT 3 // 2 for cdc + 1 for hid + +#endif + +#endif + +typedef struct +{ + ConfigDescriptor config; +#ifdef CDC_ENABLED + CDCDescriptor cdc; +#endif + HIDDescriptor hid; +#ifdef MSC_ENABLED + MSCDescriptor msc; +#endif +} Config; + +extern Config USB_ConfigDescriptor PROGMEM; +extern DeviceDescriptor USB_DeviceDescriptor PROGMEM; +extern DeviceDescriptor USB_DeviceDescriptorA PROGMEM; + +extern const u16 STRING_LANGUAGE[2] PROGMEM; +extern const u16 STRING_SERIAL[13] PROGMEM; + +#define IMANUFACTURER 0 +#define IPRODUCT 0 +#define ISERIAL 1 // Only need this for MSC + + +#define MSC_TX MSC_ENDPOINT_IN +#define MSC_RX MSC_ENDPOINT_OUT +#define CDC_TX CDC_ENDPOINT_IN +#define CDC_RX CDC_ENDPOINT_OUT \ No newline at end of file