Add more const-ness to the stream endpoint/pipe functions where possible.
[pub/USBasp.git] / Bootloaders / DFU / BootloaderDFU.c
index d7bec1f..717c934 100644 (file)
@@ -1,13 +1,13 @@
 /*
              LUFA Library
-     Copyright (C) Dean Camera, 2010.
+     Copyright (C) Dean Camera, 2011.
 
   dean [at] fourwalledcubicle [dot] com
-      www.fourwalledcubicle.com
+           www.lufa-lib.org
 */
 
 /*
-  Copyright 2010  Dean Camera (dean [at] fourwalledcubicle [dot] com)
+  Copyright 2011  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
 
 /** Flag to indicate if the bootloader is currently running in secure mode, disallowing memory operations
  *  other than erase. This is initially set to the value set by SECURE_MODE, and cleared by the bootloader
- *  once a memory erase has completed.
+ *  once a memory erase has completed in a bootloader session.
  */
-bool IsSecure      = SECURE_MODE;
+static bool IsSecure = SECURE_MODE;
 
 /** Flag to indicate if the bootloader should be running, or should exit and allow the application code to run
  *  via a soft reset. When cleared, the bootloader will abort, the USB interface will shut down and the application
  *  jumped to via an indirect jump to location 0x0000 (or other location specified by the host).
  */
-bool RunBootloader = true;
+static bool RunBootloader = true;
 
 /** Flag to indicate if the bootloader is waiting to exit. When the host requests the bootloader to exit and
  *  jump to the application address it specifies, it sends two sequential commands which must be properly
  *  acknowledged. Upon reception of the first the RunBootloader flag is cleared and the WaitForExit flag is set,
  *  causing the bootloader to wait for the final exit command before shutting down.
  */
-bool WaitForExit = false;
+static bool WaitForExit = false;
 
 /** Current DFU state machine state, one of the values in the DFU_State_t enum. */
-uint8_t DFU_State = dfuIDLE;
+static uint8_t DFU_State = dfuIDLE;
 
 /** Status code of the last executed DFU command. This is set to one of the values in the DFU_Status_t enum after
  *  each operation, and returned to the host when a Get Status DFU request is issued.
  */
-uint8_t DFU_Status = OK;
+static uint8_t DFU_Status = OK;
 
 /** Data containing the DFU command sent from the host. */
-DFU_Command_t SentCommand;
+static DFU_Command_t SentCommand;
 
 /** Response to the last issued Read Data DFU command. Unlike other DFU commands, the read command
  *  requires a single byte response from the bootloader containing the read data when the next DFU_UPLOAD command
  *  is issued by the host.
  */
-uint8_t ResponseByte;
+static uint8_t ResponseByte;
 
 /** Pointer to the start of the user application. By default this is 0x0000 (the reset vector), however the host
  *  may specify an alternate address when issuing the application soft-start command.
  */
-AppPtr_t AppStartPtr = (AppPtr_t)0x0000;
+static AppPtr_t AppStartPtr = (AppPtr_t)0x0000;
 
 /** 64-bit flash page number. This is concatenated with the current 16-bit address on USB AVRs containing more than
  *  64KB of flash memory.
  */
-uint8_t Flash64KBPage = 0;
+static uint8_t Flash64KBPage = 0;
 
 /** Memory start address, indicating the current address in the memory being addressed (either FLASH or EEPROM
  *  depending on the issued command from the host).
  */
-uint16_t StartAddr = 0x0000;
+static uint16_t StartAddr = 0x0000;
 
 /** Memory end address, indicating the end address to read to/write from in the memory being addressed (either FLASH
  *  of EEPROM depending on the issued command from the host).
  */
-uint16_t EndAddr = 0x0000;
+static uint16_t EndAddr = 0x0000;
 
 
 /** Main program entry point. This routine configures the hardware required by the bootloader, then continuously
@@ -102,6 +102,23 @@ int main(void)
        /* Configure hardware required by the bootloader */
        SetupHardware();
 
+       #if ((BOARD == BOARD_XPLAIN) || (BOARD == BOARD_XPLAIN_REV1))
+       /* Disable JTAG debugging */
+       MCUCR |= (1 << JTD);
+       MCUCR |= (1 << JTD);
+
+       /* Enable pull-up on the JTAG TCK pin so we can use it to select the mode */
+       PORTF |= (1 << 4);
+       _delay_ms(10);
+
+       /* If the TCK pin is not jumpered to ground, start the user application instead */
+       RunBootloader = (!(PINF & (1 << 4)));
+       
+       /* Re-enable JTAG debugging */
+       MCUCR &= ~(1 << JTD);
+       MCUCR &= ~(1 << JTD);   
+       #endif
+
        /* Enable global interrupts so that the USB stack can function */
        sei();
 
@@ -138,25 +155,32 @@ void SetupHardware(void)
 void ResetHardware(void)
 {
        /* Shut down the USB subsystem */
-       USB_ShutDown();
+       USB_Disable();
 
        /* Relocate the interrupt vector table back to the application section */
        MCUCR = (1 << IVCE);
        MCUCR = 0;
 }
 
-/** Event handler for the USB_UnhandledControlRequest event. This is used to catch standard and class specific
- *  control requests that are not handled internally by the USB library (including the DFU commands, which are
- *  all issued via the control endpoint), so that they can be handled appropriately for the application.
+/** 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_UnhandledControlRequest(void)
+void EVENT_USB_Device_ControlRequest(void)
 {
        /* Get the size of the command and data from the wLength value */
        SentCommand.DataSize = USB_ControlRequest.wLength;
+       
+       /* Ignore any requests that aren't directed to the DFU interface */
+       if ((USB_ControlRequest.bmRequestType & (CONTROL_REQTYPE_TYPE | CONTROL_REQTYPE_RECIPIENT)) !=
+           (REQTYPE_CLASS | REQREC_INTERFACE))
+       {
+               return;
+       }
 
        switch (USB_ControlRequest.bRequest)
        {
-               case REQ_DFU_DNLOAD:
+               case DFU_REQ_DNLOAD:
                        Endpoint_ClearSETUP();
 
                        /* Check if bootloader is waiting to terminate */
@@ -309,7 +333,7 @@ void EVENT_USB_Device_UnhandledControlRequest(void)
                        Endpoint_ClearStatusStage();
 
                        break;
-               case REQ_DFU_UPLOAD:
+               case DFU_REQ_UPLOAD:
                        Endpoint_ClearSETUP();
 
                        while (!(Endpoint_IsINReady()))
@@ -408,7 +432,7 @@ void EVENT_USB_Device_UnhandledControlRequest(void)
 
                        Endpoint_ClearStatusStage();
                        break;
-               case REQ_DFU_GETSTATUS:
+               case DFU_REQ_GETSTATUS:
                        Endpoint_ClearSETUP();
 
                        /* Write 8-bit status value */
@@ -428,7 +452,7 @@ void EVENT_USB_Device_UnhandledControlRequest(void)
 
                        Endpoint_ClearStatusStage();
                        break;
-               case REQ_DFU_CLRSTATUS:
+               case DFU_REQ_CLRSTATUS:
                        Endpoint_ClearSETUP();
 
                        /* Reset the status value variable to the default OK status */
@@ -436,7 +460,7 @@ void EVENT_USB_Device_UnhandledControlRequest(void)
 
                        Endpoint_ClearStatusStage();
                        break;
-               case REQ_DFU_GETSTATE:
+               case DFU_REQ_GETSTATE:
                        Endpoint_ClearSETUP();
 
                        /* Write the current device state to the endpoint */
@@ -446,7 +470,7 @@ void EVENT_USB_Device_UnhandledControlRequest(void)
 
                        Endpoint_ClearStatusStage();
                        break;
-               case REQ_DFU_ABORT:
+               case DFU_REQ_ABORT:
                        Endpoint_ClearSETUP();
 
                        /* Reset the current state variable to the default idle state */