Add new Printer class USB bootloader.
authorDean Camera <dean@fourwalledcubicle.com>
Sun, 3 Mar 2013 13:35:46 +0000 (13:35 +0000)
committerDean Camera <dean@fourwalledcubicle.com>
Sun, 3 Mar 2013 13:35:46 +0000 (13:35 +0000)
Bootloaders/Printer/BootloaderPrinter.c [new file with mode: 0644]
Bootloaders/Printer/BootloaderPrinter.h [new file with mode: 0644]
Bootloaders/Printer/Config/LUFAConfig.h [new file with mode: 0644]
Bootloaders/Printer/Descriptors.c [new file with mode: 0644]
Bootloaders/Printer/Descriptors.h [new file with mode: 0644]
Bootloaders/Printer/makefile [new file with mode: 0644]
LUFA/DoxygenPages/ChangeLog.txt

diff --git a/Bootloaders/Printer/BootloaderPrinter.c b/Bootloaders/Printer/BootloaderPrinter.c
new file mode 100644 (file)
index 0000000..a913b33
--- /dev/null
@@ -0,0 +1,361 @@
+/*
+             LUFA Library
+     Copyright (C) Dean Camera, 2013.
+
+  dean [at] fourwalledcubicle [dot] com
+           www.lufa-lib.org
+*/
+
+/*
+  Copyright 2013  Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+  Permission to use, copy, modify, distribute, and sell this
+  software and its documentation for any purpose is hereby granted
+  without fee, provided that the above copyright notice appear in
+  all copies and that both that the copyright notice and this
+  permission notice and warranty disclaimer appear in supporting
+  documentation, and that the name of the author not be used in
+  advertising or publicity pertaining to distribution of the
+  software without specific, written prior permission.
+
+  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, 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.
+*/
+
+/** \file
+ *
+ *  Main source file for the Printer class bootloader. This file contains the complete bootloader logic.
+ */
+
+#include "BootloaderPrinter.h"
+
+/** Intel HEX parser state machine state information, to track the contents of
+ *  a HEX file streamed in as a sequence of arbitrary bytes.
+ */
+struct
+{
+       /** Current HEX parser state machine state. */
+       uint8_t  ParserState;
+       /** Previously decoded numerical byte of data. */
+       uint8_t  PrevData;
+       /** Currently decoded numerical byte of data. */
+       uint8_t  Data;
+       /** Indicates if both bytes that correspond to a single decoded numerical
+        *  byte of data (HEX encodes values in ASCII HEX, two characters per byte)
+        *  have been read.
+        */
+       bool     ReadMSB;
+       /** Intel HEX record type of the current Intel HEX record. */
+       uint8_t  RecordType;
+       /** Numerical bytes of data remaining to be read in the current record. */
+       uint8_t  DataRem;
+       /** Checksum of the current record received so far. */
+       uint8_t  Checksum;
+       /** Starting address of the last addressed FLASH page. */
+       uint32_t PageStartAddress;
+       /** Current 32-bit byte address in FLASH being targeted. */
+       uint32_t CurrAddress;
+} HEXParser =
+       {
+               .ParserState = HEX_PARSE_STATE_WAIT_LINE
+       };
+
+/** Indicates if there is data waiting to be written to a physical page of
+ *  memory in FLASH.
+ */
+static bool PageDirty = false;
+
+/**
+ * Determines if a given input byte of data is an ASCII encoded HEX value.
+ *
+ * \note Input HEX bytes are expected to be in uppercase only.
+ *
+ * \param[in] Byte  ASCII byte of data to check
+ *
+ * \return Boolean \c true if the input data is ASCII encoded HEX, false otherwise.
+ */
+static bool IsHex(const char Byte)
+{
+       return ((Byte >= 'A') && (Byte <= 'F')) ||
+              ((Byte >= '0') && (Byte <= '9'));
+}
+
+/**
+ * Converts a given input byte of data from an ASCII encoded HEX value to an integer value.
+ *
+ * \note Input HEX bytes are expected to be in uppercase only.
+ *
+ * \param[in] Byte  ASCII byte of data to convert
+ *
+ * \return Integer converted value of the input ASCII encoded HEX byte of data.
+ */
+static uint8_t HexToDecimal(const char Byte)
+{
+       if ((Byte >= 'A') && (Byte <= 'F'))
+         return (10 + (Byte - 'A'));
+       else if ((Byte >= '0') && (Byte <= '9'))
+         return (Byte - '0');
+
+       return 0;
+}
+
+/**
+ * Parses an input Intel HEX formatted stream one character at a time, loading
+ * the data contents into the device's internal FLASH memory.
+ *
+ * \param[in] ReadCharacter  Next input ASCII byte of data to parse
+ */
+static void ParseIntelHEXByte(const char ReadCharacter)
+{
+       if ((HEXParser.ParserState == HEX_PARSE_STATE_WAIT_LINE) || (ReadCharacter == ':'))
+       {
+               HEXParser.Checksum     = 0;
+               HEXParser.CurrAddress &= ~0xFFFF;
+               HEXParser.ParserState  = HEX_PARSE_STATE_WAIT_LINE;
+               HEXParser.ReadMSB      = false;
+
+               if (ReadCharacter == ':')
+                 HEXParser.ParserState = HEX_PARSE_STATE_BYTE_COUNT;
+
+               return;
+       }
+
+       if (!IsHex(ReadCharacter))
+         return;
+
+       HEXParser.Data    = (HEXParser.Data << 4) | HexToDecimal(ReadCharacter);
+       HEXParser.ReadMSB = !HEXParser.ReadMSB;
+
+       if (HEXParser.ReadMSB)
+         return;
+
+       if (HEXParser.ParserState != HEX_PARSE_STATE_CHECKSUM)
+         HEXParser.Checksum += HEXParser.Data;
+
+       switch (HEXParser.ParserState)
+       {
+               case HEX_PARSE_STATE_BYTE_COUNT:
+                       HEXParser.DataRem      = HEXParser.Data;
+                       HEXParser.ParserState  = HEX_PARSE_STATE_ADDRESS_HIGH;
+                       break;
+
+               case HEX_PARSE_STATE_ADDRESS_HIGH:
+                       HEXParser.CurrAddress |= ((uint16_t)HEXParser.Data << 8);
+                       HEXParser.ParserState  = HEX_PARSE_STATE_ADDRESS_LOW;
+                       break;
+
+               case HEX_PARSE_STATE_ADDRESS_LOW:
+                       HEXParser.CurrAddress |= HEXParser.Data;
+                       HEXParser.ParserState  = HEX_PARSE_STATE_RECORD_TYPE;
+                       break;
+
+               case HEX_PARSE_STATE_RECORD_TYPE:
+                       HEXParser.RecordType   = HEXParser.Data;
+                       HEXParser.ParserState  = (HEXParser.DataRem ? HEX_PARSE_STATE_READ_DATA : HEX_PARSE_STATE_CHECKSUM);
+                       break;
+
+               case HEX_PARSE_STATE_READ_DATA:
+                       HEXParser.DataRem--;
+
+                       if (HEXParser.DataRem & 0x01)
+                       {
+                               HEXParser.PrevData = HEXParser.Data;
+                               break;
+                       }
+
+                       switch (HEXParser.RecordType)
+                       {
+                               case HEX_RECORD_TYPE_Data:
+                                       if (!(PageDirty))
+                                       {
+                                               boot_page_erase(HEXParser.PageStartAddress);
+                                               boot_spm_busy_wait();
+
+                                               PageDirty = true;
+                                       }
+
+                                       boot_page_fill(HEXParser.CurrAddress, ((uint16_t)HEXParser.Data << 8) | HEXParser.PrevData);
+                                       HEXParser.CurrAddress += 2;
+
+                                       uint32_t NewPageStartAddress = (HEXParser.CurrAddress & ~(SPM_PAGESIZE - 1));
+                                       if (PageDirty && (HEXParser.PageStartAddress != NewPageStartAddress))
+                                       {
+                                               boot_page_write(HEXParser.PageStartAddress);
+                                               boot_spm_busy_wait();
+
+                                               HEXParser.PageStartAddress = NewPageStartAddress;
+
+                                               PageDirty = false;
+                                       }
+                                       break;
+
+                               case HEX_RECORD_TYPE_ExtendedLinearAddress:
+                                       HEXParser.CurrAddress |= (uint32_t)HEXParser.Data << (HEXParser.DataRem ? 24 : 16);
+                                       break;
+                       }
+
+                       if (!HEXParser.DataRem)
+                         HEXParser.ParserState = HEX_PARSE_STATE_CHECKSUM;
+                       break;
+
+               case HEX_PARSE_STATE_CHECKSUM:
+                       if (HEXParser.Data != ((~HEXParser.Checksum + 1) & 0xFF))
+                         break;
+
+                       uint32_t NewPageStartAddress = (HEXParser.CurrAddress & ~(SPM_PAGESIZE - 1));
+                       if (PageDirty && (HEXParser.PageStartAddress != NewPageStartAddress))
+                       {
+                               boot_page_write(HEXParser.PageStartAddress);
+                               boot_spm_busy_wait();
+
+                               HEXParser.PageStartAddress = NewPageStartAddress;
+
+                               PageDirty = false;
+                       }
+
+                       break;
+
+               default:
+                       HEXParser.ParserState = HEX_PARSE_STATE_WAIT_LINE;
+                       break;
+       }
+}
+
+/** Main program entry point. This routine configures the hardware required by the application, then
+ *  enters a loop to run the application tasks in sequence.
+ */
+int main(void)
+{
+       SetupHardware();
+
+       LEDs_SetAllLEDs(LEDMASK_USB_NOTREADY);
+       GlobalInterruptEnable();
+
+       for (;;)
+       {
+               USB_USBTask();
+
+               Endpoint_SelectEndpoint(PRINTER_OUT_EPADDR);
+
+               /* Check if we have received new printer data from the host */
+               if (Endpoint_IsOUTReceived()) {
+                       LEDs_ToggleLEDs(LEDMASK_USB_BUSY);
+
+                       /* Read all bytes of data from the host and parse them */
+                       while (Endpoint_IsReadWriteAllowed())
+                       {
+                               /* Feed the next byte of data to the HEX parser */
+                               ParseIntelHEXByte(Endpoint_Read_8());
+                       }
+
+                       /* Send an ACK to the host, ready for the next data packet */
+                       Endpoint_ClearOUT();
+
+                       LEDs_SetAllLEDs(LEDMASK_USB_READY);
+               }
+       }
+}
+
+/** Configures the board hardware and chip peripherals for the demo's functionality. */
+void SetupHardware(void)
+{
+       /* Disable watchdog if enabled by bootloader/fuses */
+       MCUSR &= ~(1 << WDRF);
+       wdt_disable();
+
+       /* Disable clock division */
+       clock_prescale_set(clock_div_1);
+
+       /* Relocate the interrupt vector table to the bootloader section */
+       MCUCR = (1 << IVCE);
+       MCUCR = (1 << IVSEL);
+
+       /* Hardware Initialization */
+       LEDs_Init();
+       USB_Init();
+}
+
+/** Event handler for the USB_Connect event. This indicates that the device is enumerating via the status LEDs. */
+void EVENT_USB_Device_Connect(void)
+{
+       /* Indicate USB enumerating */
+       LEDs_SetAllLEDs(LEDMASK_USB_ENUMERATING);
+}
+
+/** Event handler for the USB_Disconnect event. This indicates that the device is no longer connected to a host via
+ *  the status LEDs and stops the Mass Storage management task.
+ */
+void EVENT_USB_Device_Disconnect(void)
+{
+       /* Indicate USB not ready */
+       LEDs_SetAllLEDs(LEDMASK_USB_NOTREADY);
+}
+
+/** Event handler for the USB_ConfigurationChanged event. This is fired when the host set the current configuration
+ *  of the USB device after enumeration - the device endpoints are configured and the Mass Storage management task started.
+ */
+void EVENT_USB_Device_ConfigurationChanged(void)
+{
+       bool ConfigSuccess = true;
+
+       /* Setup Printer Data Endpoints */
+       ConfigSuccess &= Endpoint_ConfigureEndpoint(PRINTER_IN_EPADDR,  EP_TYPE_BULK, PRINTER_IO_EPSIZE, 1);
+       ConfigSuccess &= Endpoint_ConfigureEndpoint(PRINTER_OUT_EPADDR, EP_TYPE_BULK, PRINTER_IO_EPSIZE, 1);
+
+       /* Indicate endpoint configuration success or failure */
+       LEDs_SetAllLEDs(ConfigSuccess ? LEDMASK_USB_READY : LEDMASK_USB_ERROR);
+}
+
+/** Event handler for the USB_ControlRequest event. This is used to catch and process control requests sent to
+ *  the device from the USB host before passing along unhandled control requests to the library for processing
+ *  internally.
+ */
+void EVENT_USB_Device_ControlRequest(void)
+{
+       /* Process Printer specific control requests */
+       switch (USB_ControlRequest.bRequest)
+       {
+               case PRNT_REQ_GetDeviceID:
+                       if (USB_ControlRequest.bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE))
+                       {
+                               /* Generic printer IEEE 1284 identification string, will bind to an in-built driver on
+                                * Windows systems, and will fall-back to a text-only printer driver on *nix.
+                                */
+                               const char PrinterIDString[] =
+                                       "MFG:Generic;"
+                                       "MDL:Generic_/_Text_Only;"
+                                       "CMD:1284.4;"
+                                       "CLS:PRINTER";
+
+                               Endpoint_ClearSETUP();
+                               Endpoint_Write_16_BE(sizeof(PrinterIDString));
+                               Endpoint_Write_Control_Stream_LE(PrinterIDString, strlen(PrinterIDString));
+                               Endpoint_ClearStatusStage();
+                       }
+
+                       break;
+               case PRNT_REQ_GetPortStatus:
+                       if (USB_ControlRequest.bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE))
+                       {
+                               Endpoint_ClearSETUP();
+                               Endpoint_Write_8(PRNT_PORTSTATUS_NOTERROR | PRNT_PORTSTATUS_SELECT);
+                               Endpoint_ClearStatusStage();
+                       }
+
+                       break;
+               case PRNT_REQ_SoftReset:
+                       if (USB_ControlRequest.bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE))
+                       {
+                               Endpoint_ClearSETUP();
+                               Endpoint_ClearStatusStage();
+                       }
+
+                       break;
+       }
+}
diff --git a/Bootloaders/Printer/BootloaderPrinter.h b/Bootloaders/Printer/BootloaderPrinter.h
new file mode 100644 (file)
index 0000000..b99e763
--- /dev/null
@@ -0,0 +1,99 @@
+/*
+             LUFA Library
+     Copyright (C) Dean Camera, 2013.
+
+  dean [at] fourwalledcubicle [dot] com
+           www.lufa-lib.org
+*/
+
+/*
+  Copyright 2013  Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+  Permission to use, copy, modify, distribute, and sell this
+  software and its documentation for any purpose is hereby granted
+  without fee, provided that the above copyright notice appear in
+  all copies and that both that the copyright notice and this
+  permission notice and warranty disclaimer appear in supporting
+  documentation, and that the name of the author not be used in
+  advertising or publicity pertaining to distribution of the
+  software without specific, written prior permission.
+
+  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, 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.
+*/
+
+/** \file
+ *
+ *  Header file for Printer.c.
+ */
+
+#ifndef _PRINTER_H_
+#define _PRINTER_H_
+
+       /* Includes: */
+               #include <avr/io.h>
+               #include <avr/wdt.h>
+               #include <avr/power.h>
+               #include <avr/interrupt.h>
+
+               #include "Descriptors.h"
+
+               #include <LUFA/Drivers/USB/USB.h>
+               #include <LUFA/Drivers/Board/LEDs.h>
+
+       /* Macros: */
+               /** LED mask for the library LED driver, to indicate that the USB interface is not ready. */
+               #define LEDMASK_USB_NOTREADY       LEDS_LED1
+
+               /** LED mask for the library LED driver, to indicate that the USB interface is enumerating. */
+               #define LEDMASK_USB_ENUMERATING   (LEDS_LED2 | LEDS_LED3)
+
+               /** LED mask for the library LED driver, to indicate that the USB interface is ready. */
+               #define LEDMASK_USB_READY         (LEDS_LED2 | LEDS_LED4)
+
+               /** LED mask for the library LED driver, to indicate that an error has occurred in the USB interface. */
+               #define LEDMASK_USB_ERROR         (LEDS_LED1 | LEDS_LED3)
+
+               /** LED mask for the library LED driver, to indicate that the USB interface is busy. */
+               #define LEDMASK_USB_BUSY           LEDS_LED2
+
+       /* Enums: */
+               /** Intel HEX parser state machine states. */
+               enum HEX_Parser_States_t
+               {
+                       HEX_PARSE_STATE_WAIT_LINE,    /**< Parser is waiting for a HEX Start of Line character. */
+                       HEX_PARSE_STATE_BYTE_COUNT,   /**< Parser is waiting for a record byte count. */
+                       HEX_PARSE_STATE_ADDRESS_HIGH, /**< Parser is waiting for the MSB of a record address. */
+                       HEX_PARSE_STATE_ADDRESS_LOW,  /**< Parser is waiting for the LSB of a record address. */
+                       HEX_PARSE_STATE_RECORD_TYPE,  /**< Parser is waiting for the record type. */
+                       HEX_PARSE_STATE_READ_DATA,    /**< Parser is waiting for more data in the current record. */
+                       HEX_PARSE_STATE_CHECKSUM,     /**< Parser is waiting for the checksum of the current record. */
+               };
+
+               /** Intel HEX record types, used to indicate the type of record contained in a line of a HEX file. */
+               enum HEX_Record_Types_t
+               {
+                       HEX_RECORD_TYPE_Data                   = 0, /**< Record contains loadable data. */
+                       HEX_RECORD_TYPE_EndOfFile              = 1, /**< End of file record. */
+                       HEX_RECORD_TYPE_ExtendedSegmentAddress = 2, /**< Extended segment start record. */
+                       HEX_RECORD_TYPE_StartSegmentAddress    = 3, /**< Normal segment start record. */
+                       HEX_RECORD_TYPE_ExtendedLinearAddress  = 4, /**< Extended linear address start record. */
+                       HEX_RECORD_TYPE_StartLinearAddress     = 5, /**< Linear address start record. */
+               };
+
+       /* Function Prototypes: */
+               void SetupHardware(void);
+
+               void EVENT_USB_Device_Connect(void);
+               void EVENT_USB_Device_Disconnect(void);
+               void EVENT_USB_Device_ConfigurationChanged(void);
+               void EVENT_USB_Device_ControlRequest(void);
+
+#endif
+
diff --git a/Bootloaders/Printer/Config/LUFAConfig.h b/Bootloaders/Printer/Config/LUFAConfig.h
new file mode 100644 (file)
index 0000000..586bf7a
--- /dev/null
@@ -0,0 +1,93 @@
+/*
+             LUFA Library
+     Copyright (C) Dean Camera, 2013.
+
+  dean [at] fourwalledcubicle [dot] com
+           www.lufa-lib.org
+*/
+
+/*
+  Copyright 2013  Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+  Permission to use, copy, modify, distribute, and sell this
+  software and its documentation for any purpose is hereby granted
+  without fee, provided that the above copyright notice appear in
+  all copies and that both that the copyright notice and this
+  permission notice and warranty disclaimer appear in supporting
+  documentation, and that the name of the author not be used in
+  advertising or publicity pertaining to distribution of the
+  software without specific, written prior permission.
+
+  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, 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.
+*/
+
+/** \file
+ *  \brief LUFA Library Configuration Header File
+ *
+ *  This header file is used to configure LUFA's compile time options,
+ *  as an alternative to the compile time constants supplied through
+ *  a makefile.
+ *
+ *  For information on what each token does, refer to the LUFA
+ *  manual section "Summary of Compile Tokens".
+ */
+
+#ifndef _LUFA_CONFIG_H_
+#define _LUFA_CONFIG_H_
+
+       #if (ARCH == ARCH_AVR8)
+
+               /* Non-USB Related Configuration Tokens: */
+//             #define DISABLE_TERMINAL_CODES
+
+               /* USB Class Driver Related Tokens: */
+//             #define HID_HOST_BOOT_PROTOCOL_ONLY
+//             #define HID_STATETABLE_STACK_DEPTH       {Insert Value Here}
+//             #define HID_USAGE_STACK_DEPTH            {Insert Value Here}
+//             #define HID_MAX_COLLECTIONS              {Insert Value Here}
+//             #define HID_MAX_REPORTITEMS              {Insert Value Here}
+//             #define HID_MAX_REPORT_IDS               {Insert Value Here}
+//             #define NO_CLASS_DRIVER_AUTOFLUSH
+
+               /* General USB Driver Related Tokens: */
+               #define ORDERED_EP_CONFIG
+               #define USE_STATIC_OPTIONS               (USB_DEVICE_OPT_FULLSPEED | USB_OPT_REG_ENABLED | USB_OPT_AUTO_PLL)
+               #define USB_DEVICE_ONLY
+//             #define USB_HOST_ONLY
+//             #define USB_STREAM_TIMEOUT_MS            {Insert Value Here}
+//             #define NO_LIMITED_CONTROLLER_CONNECT
+               #define NO_SOF_EVENTS
+
+               /* USB Device Mode Driver Related Tokens: */
+               #define USE_RAM_DESCRIPTORS
+//             #define USE_FLASH_DESCRIPTORS
+//             #define USE_EEPROM_DESCRIPTORS
+               #define NO_INTERNAL_SERIAL
+               #define FIXED_CONTROL_ENDPOINT_SIZE      8
+               #define DEVICE_STATE_AS_GPIOR            0
+               #define FIXED_NUM_CONFIGURATIONS         1
+//             #define CONTROL_ONLY_DEVICE
+//             #define INTERRUPT_CONTROL_ENDPOINT
+               #define NO_DEVICE_REMOTE_WAKEUP
+               #define NO_DEVICE_SELF_POWER
+
+               /* USB Host Mode Driver Related Tokens: */
+//             #define HOST_STATE_AS_GPIOR              {Insert Value Here}
+//             #define USB_HOST_TIMEOUT_MS              {Insert Value Here}
+//             #define HOST_DEVICE_SETTLE_DELAY_MS          {Insert Value Here}
+//             #define NO_AUTO_VBUS_MANAGEMENT
+//             #define INVERTED_VBUS_ENABLE_LINE
+
+       #else
+
+               #error Unsupported architecture for this LUFA configuration file.
+
+       #endif
+#endif
diff --git a/Bootloaders/Printer/Descriptors.c b/Bootloaders/Printer/Descriptors.c
new file mode 100644 (file)
index 0000000..30fd364
--- /dev/null
@@ -0,0 +1,209 @@
+/*
+             LUFA Library
+     Copyright (C) Dean Camera, 2013.
+
+  dean [at] fourwalledcubicle [dot] com
+           www.lufa-lib.org
+*/
+
+/*
+  Copyright 2013  Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+  Permission to use, copy, modify, distribute, and sell this
+  software and its documentation for any purpose is hereby granted
+  without fee, provided that the above copyright notice appear in
+  all copies and that both that the copyright notice and this
+  permission notice and warranty disclaimer appear in supporting
+  documentation, and that the name of the author not be used in
+  advertising or publicity pertaining to distribution of the
+  software without specific, written prior permission.
+
+  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, 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.
+*/
+
+/** \file
+ *
+ *  USB Device Descriptors, for library use when in USB device mode. Descriptors are special
+ *  computer-readable structures which the host requests upon device enumeration, to determine
+ *  the device's capabilities and functions.
+ */
+
+#include "Descriptors.h"
+
+
+/** Device descriptor structure. This descriptor, located in FLASH memory, describes the overall
+ *  device characteristics, including the supported USB version, control endpoint size and the
+ *  number of device configurations. The descriptor is read out by the USB host when the enumeration
+ *  process begins.
+ */
+const USB_Descriptor_Device_t DeviceDescriptor =
+{
+       .Header                 = {.Size = sizeof(USB_Descriptor_Device_t), .Type = DTYPE_Device},
+
+       .USBSpecification       = VERSION_BCD(01.10),
+       .Class                  = USB_CSCP_NoDeviceClass,
+       .SubClass               = USB_CSCP_NoDeviceSubclass,
+       .Protocol               = USB_CSCP_NoDeviceProtocol,
+
+       .Endpoint0Size          = FIXED_CONTROL_ENDPOINT_SIZE,
+
+       .VendorID               = 0x03EB,
+       .ProductID              = 0xFFEF,
+       .ReleaseNumber          = VERSION_BCD(00.01),
+
+       .ManufacturerStrIndex   = 0x01,
+       .ProductStrIndex        = 0x02,
+       .SerialNumStrIndex      = NO_DESCRIPTOR,
+
+       .NumberOfConfigurations = FIXED_NUM_CONFIGURATIONS
+};
+
+/** Configuration descriptor structure. This descriptor, located in FLASH memory, describes the usage
+ *  of the device in one of its supported configurations, including information about any device interfaces
+ *  and endpoints. The descriptor is read out by the USB host during the enumeration process when selecting
+ *  a configuration so that the host may correctly communicate with the USB device.
+ */
+const USB_Descriptor_Configuration_t ConfigurationDescriptor =
+{
+       .Config =
+               {
+                       .Header                 = {.Size = sizeof(USB_Descriptor_Configuration_Header_t), .Type = DTYPE_Configuration},
+
+                       .TotalConfigurationSize = sizeof(USB_Descriptor_Configuration_t),
+                       .TotalInterfaces        = 1,
+
+                       .ConfigurationNumber    = 1,
+                       .ConfigurationStrIndex  = NO_DESCRIPTOR,
+
+                       .ConfigAttributes       = USB_CONFIG_ATTR_RESERVED,
+
+                       .MaxPowerConsumption    = USB_CONFIG_POWER_MA(100)
+               },
+
+       .Printer_Interface =
+               {
+                       .Header                 = {.Size = sizeof(USB_Descriptor_Interface_t), .Type = DTYPE_Interface},
+
+                       .InterfaceNumber        = 0,
+                       .AlternateSetting       = 0,
+
+                       .TotalEndpoints         = 2,
+
+                       .Class                  = PRNT_CSCP_PrinterClass,
+                       .SubClass               = PRNT_CSCP_PrinterSubclass,
+                       .Protocol               = PRNT_CSCP_BidirectionalProtocol,
+
+                       .InterfaceStrIndex      = NO_DESCRIPTOR
+               },
+
+       .Printer_DataInEndpoint =
+               {
+                       .Header                 = {.Size = sizeof(USB_Descriptor_Endpoint_t), .Type = DTYPE_Endpoint},
+
+                       .EndpointAddress        = PRINTER_IN_EPADDR,
+                       .Attributes             = (EP_TYPE_BULK | ENDPOINT_ATTR_NO_SYNC | ENDPOINT_USAGE_DATA),
+                       .EndpointSize           = PRINTER_IO_EPSIZE,
+                       .PollingIntervalMS      = 0x05
+               },
+
+       .Printer_DataOutEndpoint =
+               {
+                       .Header                 = {.Size = sizeof(USB_Descriptor_Endpoint_t), .Type = DTYPE_Endpoint},
+
+                       .EndpointAddress        = PRINTER_OUT_EPADDR,
+                       .Attributes             = (EP_TYPE_BULK | ENDPOINT_ATTR_NO_SYNC | ENDPOINT_USAGE_DATA),
+                       .EndpointSize           = PRINTER_IO_EPSIZE,
+                       .PollingIntervalMS      = 0x05
+               }
+};
+
+/** Language descriptor structure. This descriptor, located in FLASH memory, is returned when the host requests
+ *  the string descriptor with index 0 (the first index). It is actually an array of 16-bit integers, which indicate
+ *  via the language ID table available at USB.org what languages the device supports for its string descriptors.
+ */
+const USB_Descriptor_String_t LanguageString =
+{
+       .Header                 = {.Size = USB_STRING_LEN(1), .Type = DTYPE_String},
+
+       .UnicodeString          = {LANGUAGE_ID_ENG}
+};
+
+/** Manufacturer descriptor string. This is a Unicode string containing the manufacturer's details in human readable
+ *  form, and is read out upon request by the host when the appropriate string ID is requested, listed in the Device
+ *  Descriptor.
+ */
+const USB_Descriptor_String_t ManufacturerString =
+{
+       .Header                 = {.Size = USB_STRING_LEN(11), .Type = DTYPE_String},
+
+       .UnicodeString          = L"Dean Camera"
+};
+
+/** Product descriptor string. This is a Unicode string containing the product's details in human readable form,
+ *  and is read out upon request by the host when the appropriate string ID is requested, listed in the Device
+ *  Descriptor.
+ */
+const USB_Descriptor_String_t ProductString =
+{
+       .Header                 = {.Size = USB_STRING_LEN(23), .Type = DTYPE_String},
+
+       .UnicodeString          = L"LUFA Printer Bootloader"
+};
+
+/** This function is called by the library when in device mode, and must be overridden (see library "USB Descriptors"
+ *  documentation) by the application code so that the address and size of a requested descriptor can be given
+ *  to the USB library. When the device receives a Get Descriptor request on the control endpoint, this function
+ *  is called so that the descriptor details can be passed back and the appropriate descriptor sent back to the
+ *  USB host.
+ */
+uint16_t CALLBACK_USB_GetDescriptor(const uint16_t wValue,
+                                    const uint8_t wIndex,
+                                    const void** const DescriptorAddress)
+{
+       const uint8_t  DescriptorType   = (wValue >> 8);
+       const uint8_t  DescriptorNumber = (wValue & 0xFF);
+
+       const void* Address = NULL;
+       uint16_t    Size    = NO_DESCRIPTOR;
+
+       switch (DescriptorType)
+       {
+               case DTYPE_Device:
+                       Address = &DeviceDescriptor;
+                       Size    = sizeof(USB_Descriptor_Device_t);
+                       break;
+               case DTYPE_Configuration:
+                       Address = &ConfigurationDescriptor;
+                       Size    = sizeof(USB_Descriptor_Configuration_t);
+                       break;
+               case DTYPE_String:
+                       switch (DescriptorNumber)
+                       {
+                               case 0x00:
+                                       Address = &LanguageString;
+                                       Size    = pgm_read_byte(&LanguageString.Header.Size);
+                                       break;
+                               case 0x01:
+                                       Address = &ManufacturerString;
+                                       Size    = pgm_read_byte(&ManufacturerString.Header.Size);
+                                       break;
+                               case 0x02:
+                                       Address = &ProductString;
+                                       Size    = pgm_read_byte(&ProductString.Header.Size);
+                                       break;
+                       }
+
+                       break;
+       }
+
+       *DescriptorAddress = Address;
+       return Size;
+}
+
diff --git a/Bootloaders/Printer/Descriptors.h b/Bootloaders/Printer/Descriptors.h
new file mode 100644 (file)
index 0000000..5590c25
--- /dev/null
@@ -0,0 +1,77 @@
+/*
+             LUFA Library
+     Copyright (C) Dean Camera, 2013.
+
+  dean [at] fourwalledcubicle [dot] com
+           www.lufa-lib.org
+*/
+
+/*
+  Copyright 2013  Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+  Permission to use, copy, modify, distribute, and sell this
+  software and its documentation for any purpose is hereby granted
+  without fee, provided that the above copyright notice appear in
+  all copies and that both that the copyright notice and this
+  permission notice and warranty disclaimer appear in supporting
+  documentation, and that the name of the author not be used in
+  advertising or publicity pertaining to distribution of the
+  software without specific, written prior permission.
+
+  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, 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.
+*/
+
+/** \file
+ *
+ *  Header file for Descriptors.c.
+ */
+
+#ifndef _DESCRIPTORS_H_
+#define _DESCRIPTORS_H_
+
+       /* Includes: */
+               #include <LUFA/Drivers/USB/USB.h>
+               #include <LUFA/Drivers/USB/Class/Common/PrinterClassCommon.h>
+
+               #include <avr/pgmspace.h>
+
+       /* Macros: */
+               /** Endpoint address of the Printer device-to-host data IN endpoint. */
+               #define PRINTER_IN_EPADDR         (ENDPOINT_DIR_IN  | 3)
+
+               /** Endpoint address of the Printer host-to-device data OUT endpoint. */
+               #define PRINTER_OUT_EPADDR        (ENDPOINT_DIR_OUT | 4)
+
+               /** Size in bytes of the Printer data endpoints. */
+               #define PRINTER_IO_EPSIZE         64
+
+       /* Type Defines: */
+               /** Type define for the device configuration descriptor structure. This must be defined in the
+                *  application code, as the configuration descriptor contains several sub-descriptors which
+                *  vary between devices, and which describe the device's usage to the host.
+                */
+               typedef struct
+               {
+                       USB_Descriptor_Configuration_Header_t Config;
+
+                       // Printer Interface
+                       USB_Descriptor_Interface_t            Printer_Interface;
+                       USB_Descriptor_Endpoint_t             Printer_DataInEndpoint;
+                       USB_Descriptor_Endpoint_t             Printer_DataOutEndpoint;
+               } USB_Descriptor_Configuration_t;
+
+       /* Function Prototypes: */
+               uint16_t CALLBACK_USB_GetDescriptor(const uint16_t wValue,
+                                                   const uint8_t wIndex,
+                                                   const void** const DescriptorAddress)
+                                                   ATTR_WARN_UNUSED_RESULT ATTR_NON_NULL_PTR_ARG(3);
+
+#endif
+
diff --git a/Bootloaders/Printer/makefile b/Bootloaders/Printer/makefile
new file mode 100644 (file)
index 0000000..0deec3e
--- /dev/null
@@ -0,0 +1,48 @@
+#\r
+#             LUFA Library\r
+#     Copyright (C) Dean Camera, 2013.\r
+#\r
+#  dean [at] fourwalledcubicle [dot] com\r
+#           www.lufa-lib.org\r
+#\r
+# --------------------------------------\r
+#         LUFA Project Makefile.\r
+# --------------------------------------\r
+\r
+# Run "make help" for target help.\r
+\r
+MCU          = at90usb1287\r
+ARCH         = AVR8\r
+BOARD        = USBKEY\r
+F_CPU        = 8000000\r
+F_USB        = $(F_CPU)\r
+OPTIMIZATION = s\r
+TARGET       = BootloaderPrinter\r
+SRC          = $(TARGET).c Descriptors.c $(LUFA_SRC_USB)\r
+LUFA_PATH    = ../../LUFA\r
+CC_FLAGS     = -DUSE_LUFA_CONFIG_HEADER -IConfig/ -DBOOT_START_ADDR=$(BOOT_START_OFFSET)\r
+LD_FLAGS     = -Wl,--section-start=.text=$(BOOT_START_OFFSET) $(BOOT_API_LD_FLAGS)\r
+\r
+# Flash size and bootloader section sizes of the target, in KB. These must\r
+# match the target's total FLASH size and the bootloader size set in the\r
+# device's fuses.\r
+FLASH_SIZE_KB         = 128\r
+BOOT_SECTION_SIZE_KB  = 8\r
+\r
+# Bootloader address calculation formulas\r
+# Do not modify these macros, but rather modify the dependent values above.\r
+CALC_ADDRESS_IN_HEX   = $(shell printf "0x%X" $$(( $(1) )) )\r
+BOOT_START_OFFSET     = $(call CALC_ADDRESS_IN_HEX, ($(FLASH_SIZE_KB) - $(BOOT_SECTION_SIZE_KB)) * 1024 )\r
+BOOT_SEC_OFFSET       = $(call CALC_ADDRESS_IN_HEX, ($(FLASH_SIZE_KB) * 1024) - $(strip $(1)) )\r
+\r
+# Default target\r
+all:\r
+\r
+# Include LUFA build script makefiles\r
+include $(LUFA_PATH)/Build/lufa_core.mk\r
+include $(LUFA_PATH)/Build/lufa_sources.mk\r
+include $(LUFA_PATH)/Build/lufa_build.mk\r
+include $(LUFA_PATH)/Build/lufa_cppcheck.mk\r
+include $(LUFA_PATH)/Build/lufa_doxygen.mk\r
+include $(LUFA_PATH)/Build/lufa_avrdude.mk\r
+include $(LUFA_PATH)/Build/lufa_atprogram.mk\r
index 4a2fafe..1f84a3f 100644 (file)
@@ -7,7 +7,9 @@
  /** \page Page_ChangeLog Project Changelog
   *
   *  \section Sec_ChangeLogXXXXXX Version XXXXXX
-  *  No changes.
+  *  <b>New:</b>
+  *  - Library Applications:
+  *   - Added new Printer class bootloader
   *
   *  \section Sec_ChangeLog130303 Version 130303
   *  <b>New:</b>