WIP: Introduce USB DFU code from my at91lib DFU port
diff --git a/firmware/atmel_softpack_libraries/usb/device/dfu/dfu.h b/firmware/atmel_softpack_libraries/usb/device/dfu/dfu.h
new file mode 100644
index 0000000..9033de6
--- /dev/null
+++ b/firmware/atmel_softpack_libraries/usb/device/dfu/dfu.h
@@ -0,0 +1,130 @@
+#ifndef _USB_DEV_DFU_H
+#define _USB_DEV_DFU_H
+
+#include <stdint.h>
+#include <board.h>
+#include <usb/include/USBDescriptors.h>
+#include <usb/include/USBDDriver.h>
+
+#if 0
+/* This is valid for CCID */
+#define CONFIG_DFU_NUM_APP_IF	1
+#define CONFIG_DFU_NUM_APP_STR	4
+#else
+/* This is valid for CDC-Serial */
+#define CONFIG_DFU_NUM_APP_IF	2
+#define CONFIG_DFU_NUM_APP_STR	2
+#endif
+
+struct USBStringDescriptor {
+	USBGenericDescriptor hdr;
+	unsigned short wData[];
+} __attribute__((packed));
+
+
+#ifdef BOARD_USB_DFU
+
+#include <usb/common/dfu/usb_dfu.h>
+
+/* for board-specific config */
+#include <board.h>
+
+struct dfu_desc {
+	USBConfigurationDescriptor ucfg;
+	USBInterfaceDescriptor uif[BOARD_DFU_NUM_IF];
+	struct usb_dfu_func_descriptor func_dfu;
+} __attribute__ ((packed));
+
+/* USB DFU functional descriptor */
+#define DFU_FUNC_DESC  {						\
+	.bLength		= USB_DT_DFU_SIZE,			\
+	.bDescriptorType	= USB_DT_DFU,				\
+	.bmAttributes		= USB_DFU_CAN_UPLOAD | USB_DFU_CAN_DOWNLOAD, \
+	.wDetachTimeOut		= 0xff00,				\
+	.wTransferSize		= BOARD_DFU_PAGE_SIZE,			\
+	.bcdDFUVersion		= 0x0100,				\
+}
+
+/* Number of DFU interface during runtime mode */
+#define DFURT_NUM_IF		1
+
+/* to be used by the runtime as part of its USB descriptor structure
+ * declaration */
+#define DFURT_IF_DESCRIPTOR_STRUCT		\
+	USBInterfaceDescriptor	dfu_rt;		\
+	struct usb_dfu_func_descriptor func_dfu;
+
+/* to be used by the runtime as part of its USB Dsecriptor structure
+ * definition */
+#define DFURT_IF_DESCRIPTOR(dfuIF, dfuSTR)					\
+	.dfu_rt = {								\
+		.bLength 		= sizeof(USBInterfaceDescriptor),	\
+		.bDescriptorType	= USBGenericDescriptor_INTERFACE,	\
+		.bInterfaceNumber	= dfuIF,				\
+		.bAlternateSetting	= 0,					\
+		.bNumEndpoints		= 0,					\
+		.bInterfaceClass	= 0xFE,					\
+		.bInterfaceSubClass	= 0x01,					\
+		.bInterfaceProtocol	= 0x01,					\
+		.iInterface		= dfuSTR,				\
+	},									\
+	.func_dfu = DFU_FUNC_DESC						\
+
+/* provided by dfu_desc.c */
+extern const struct dfu_desc dfu_cfg_descriptor;
+extern const USBDDriverDescriptors dfu_descriptors;
+
+#else /* BOARD_USB_DFU */
+
+/* no DFU bootloader is being used */
+#define DFURT_NUM_IF	0
+#define DFURT_IF_DESCRIPTOR_STRUCT(a, b)
+#define DFURT_IF_DESCRIPTOR
+
+#endif /* BOARD_USB_DFU */
+
+/* magic value we use during boot to detect if we should start in DFU
+ * mode or runtime mode */
+#define USB_DFU_MAGIC	0xDFDFDFDF
+/* RAM address for this magic value above */
+#define USB_DFU_MAGIC_ADDR	IRAM_ADDR
+
+/* The API between the core DFU handler and the board/soc specific code */
+
+struct dfudata {
+	uint8_t status;
+	uint32_t state;
+	int past_manifest;
+	unsigned int total_bytes;
+};
+
+extern struct dfudata g_dfu;
+
+void set_usb_serial_str(const uint8_t *serial_usbstr);
+
+void DFURT_SwitchToDFU(void);
+
+/* call-backs from DFU USB function driver to the board/SOC */
+extern int USBDFU_handle_dnload(uint8_t altif, unsigned int offset,
+				uint8_t *data, unsigned int len);
+extern int USBDFU_handle_upload(uint8_t altif, unsigned int offset,
+				uint8_t *data, unsigned int req_len);
+
+/* function to be called at end of EP0 handler during runtime */
+void USBDFU_Runtime_RequestHandler(const USBGenericRequest *request);
+
+/* function to be called at end of EP0 handler during DFU mode */
+void USBDFU_DFU_RequestHandler(const USBGenericRequest *request);
+
+/* initialization of USB DFU driver (in DFU mode */
+void USBDFU_Initialize(const USBDDriverDescriptors *pDescriptors);
+
+/* USBD tells us to switch from DFU mode to application mode */
+void USBDFU_SwitchToApp(void);
+
+/* Return values to be used by USBDFU_handle_{dn,up}load */
+#define DFU_RET_NOTHING	0
+#define DFU_RET_ZLP	1
+#define DFU_RET_STALL	2
+
+#endif