re-arrange m-stack as per distribution. this makes the build
author"Darron Broad" <darron@kewl.org>
Sat, 18 Feb 2017 16:14:32 +0000
changeset 17 96d6863a1180
parent 16 5fcd9c241c4c
child 18 f73c91611afb
re-arrange m-stack as per distribution. this makes the build
more complicated but it's easier to upgrade m-stack this way.
Makefile.mx250_ckpi
Makefile.mx270_ckpi
Makefile.sdxl
mindy.h
usb/include/usb.h
usb/include/usb_cdc.h
usb/include/usb_ch9.h
usb/include/usb_hid.h
usb/include/usb_microsoft.h
usb/src/usb.c
usb/src/usb_cdc.c
usb/src/usb_hal.h
usb/src/usb_winusb.c
usb/src/usb_winusb.h
usb/usb.c
usb/usb.h
usb/usb_cdc.c
usb/usb_cdc.h
usb/usb_ch9.h
usb/usb_hal.h
usb/usb_hid.h
usb/usb_microsoft.h
usb/usb_winusb.c
usb/usb_winusb.h
--- a/Makefile.mx250_ckpi	Wed Feb 17 05:54:21 2016 +0000
+++ b/Makefile.mx250_ckpi	Sat Feb 18 16:14:32 2017 +0000
@@ -51,13 +51,16 @@
 OBJECT  := $(foreach F,$(OBJECT),$(PLATFORM)/$(F))
 
 # m-stack USB
-HEADER  += usb/usb_cdc.h usb/usb_ch9.h usb/usb_config.h usb/usb.h usb/usb_hal.h usb/usb_hid.h usb/usb_microsoft.h usb/usb_winusb.h
+HEADER  += usb/include/usb_cdc.h usb/include/usb_ch9.h usb/include/usb.h
+HEADER  += usb/include/usb_hid.h usb/include/usb_microsoft.h
+HEADER  += usb/src/usb_hal.h usb/src/usb_winusb.h
+HEADER  += usb/usb_config.h 
 OBJECT  += $(PLATFORM)/usb.o $(PLATFORM)/usb_cdc.o $(PLATFORM)/usb_descriptors.o
 
 ELF     := $(PLATFORM)/$(TARGET:.hex=.elf)
 MAP     := $(PLATFORM)/$(TARGET:.hex=.map)
 
-CFLAGS  := -mprocessor=$(CPU) -DMINDY_$(PLATFORM) -D__XC32__ -mips16 -Os -std=gnu99 -fverbose-asm -save-temps=obj -mdebugger -Iusb
+CFLAGS  := -mprocessor=$(CPU) -DMINDY_$(PLATFORM) -D__XC32__ -mips16 -Os -std=gnu99 -fverbose-asm -save-temps=obj -mdebugger -Iusb -Iusb/include -I/usr/src
 CLINK   := -mno-peripheral-libs -Wl,-T$(LKR1),-T$(LKR2),-Map=$(MAP),--defsym,_min_heap_size=$(HEAP),--defsym,_min_stack_size=$(STACK)
 
 # <plib.h> either use -fgnu89-inline for gcc or --allow-multiple-definition for ld
@@ -102,3 +105,5 @@
 # m-stack USB
 $(PLATFORM)/%.o:usb/%.c
 		$(CC) $(CFLAGS) -fno-strict-aliasing $(CPPFLAGS) -c $< -o $@
+$(PLATFORM)/%.o:usb/src/%.c
+		$(CC) $(CFLAGS) -fno-strict-aliasing $(CPPFLAGS) -c $< -o $@
--- a/Makefile.mx270_ckpi	Wed Feb 17 05:54:21 2016 +0000
+++ b/Makefile.mx270_ckpi	Sat Feb 18 16:14:32 2017 +0000
@@ -51,13 +51,16 @@
 OBJECT  := $(foreach F,$(OBJECT),$(PLATFORM)/$(F))
 
 # m-stack USB
-HEADER  += usb/usb_cdc.h usb/usb_ch9.h usb/usb_config.h usb/usb.h usb/usb_hal.h usb/usb_hid.h usb/usb_microsoft.h usb/usb_winusb.h
+HEADER  += usb/include/usb_cdc.h usb/include/usb_ch9.h usb/include/usb.h
+HEADER  += usb/include/usb_hid.h usb/include/usb_microsoft.h
+HEADER  += usb/src/usb_hal.h usb/src/usb_winusb.h
+HEADER  += usb/usb_config.h
 OBJECT  += $(PLATFORM)/usb.o $(PLATFORM)/usb_cdc.o $(PLATFORM)/usb_descriptors.o
 
 ELF     := $(PLATFORM)/$(TARGET:.hex=.elf)
 MAP     := $(PLATFORM)/$(TARGET:.hex=.map)
 
-CFLAGS  := -mprocessor=$(CPU) -DMINDY_$(PLATFORM) -D__XC32__ -mips16 -Os -std=gnu99 -fverbose-asm -save-temps=obj -mdebugger -Iusb
+CFLAGS  := -mprocessor=$(CPU) -DMINDY_$(PLATFORM) -D__XC32__ -mips16 -Os -std=gnu99 -fverbose-asm -save-temps=obj -mdebugger -Iusb -Iusb/include -I/usr/src
 CLINK   := -mno-peripheral-libs -Wl,-T$(LKR1),-T$(LKR2),-Map=$(MAP),--defsym,_min_heap_size=$(HEAP),--defsym,_min_stack_size=$(STACK)
 
 # <plib.h> either use -fgnu89-inline for gcc or --allow-multiple-definition for ld
@@ -102,3 +105,5 @@
 # m-stack USB
 $(PLATFORM)/%.o:usb/%.c
 		$(CC) $(CFLAGS) -fno-strict-aliasing $(CPPFLAGS) -c $< -o $@
+$(PLATFORM)/%.o:usb/src/%.c
+		$(CC) $(CFLAGS) -fno-strict-aliasing $(CPPFLAGS) -c $< -o $@
--- a/Makefile.sdxl	Wed Feb 17 05:54:21 2016 +0000
+++ b/Makefile.sdxl	Sat Feb 18 16:14:32 2017 +0000
@@ -51,13 +51,16 @@
 OBJECT  := $(foreach F,$(OBJECT),$(PLATFORM)/$(F))
 
 # m-stack USB
-HEADER  += usb/usb_cdc.h usb/usb_ch9.h usb/usb_config.h usb/usb.h usb/usb_hal.h usb/usb_hid.h usb/usb_microsoft.h usb/usb_winusb.h
+HEADER  += usb/include/usb_cdc.h usb/include/usb_ch9.h usb/include/usb.h
+HEADER  += usb/include/usb_hid.h usb/include/usb_microsoft.h
+HEADER  += usb/src/usb_hal.h usb/src/usb_winusb.h
+HEADER  += usb/usb_config.h
 OBJECT  += $(PLATFORM)/usb.o $(PLATFORM)/usb_cdc.o $(PLATFORM)/usb_descriptors.o
 
 ELF     := $(PLATFORM)/$(TARGET:.hex=.elf)
 MAP     := $(PLATFORM)/$(TARGET:.hex=.map)
 
-CFLAGS  := -mprocessor=$(CPU) -DMINDY_$(PLATFORM) -D__XC32__ -mips16 -Os -std=gnu99 -fverbose-asm -save-temps=obj -mdebugger -Iusb
+CFLAGS  := -mprocessor=$(CPU) -DMINDY_$(PLATFORM) -D__XC32__ -mips16 -Os -std=gnu99 -fverbose-asm -save-temps=obj -mdebugger -Iusb -Iusb/include -I/usr/src
 CLINK   := -mno-peripheral-libs -Wl,-T$(LKR1),-T$(LKR2),-Map=$(MAP),--defsym,_min_heap_size=$(HEAP),--defsym,_min_stack_size=$(STACK)
 
 # <plib.h> either use -fgnu89-inline for gcc or --allow-multiple-definition for ld
@@ -102,3 +105,5 @@
 # m-stack USB
 $(PLATFORM)/%.o:usb/%.c
 		$(CC) $(CFLAGS) -fno-strict-aliasing $(CPPFLAGS) -c $< -o $@
+$(PLATFORM)/%.o:usb/src/%.c
+		$(CC) $(CFLAGS) -fno-strict-aliasing $(CPPFLAGS) -c $< -o $@
--- a/mindy.h	Wed Feb 17 05:54:21 2016 +0000
+++ b/mindy.h	Sat Feb 18 16:14:32 2017 +0000
@@ -28,10 +28,10 @@
 #include <xc.h>
 #include <plib.h>
 
-#include "usb/usb.h"
-#include "usb/usb_config.h"
-#include "usb/usb_ch9.h"
-#include "usb/usb_cdc.h"
+#include "usb.h"
+#include "usb_config.h"
+#include "usb_ch9.h"
+#include "usb_cdc.h"
 
 #define LOW  (0)
 #define HIGH (1)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usb/include/usb.h	Sat Feb 18 16:14:32 2017 +0000
@@ -0,0 +1,594 @@
+/*
+ *  M-Stack Public API Header File
+ *  Copyright (C) 2013 Alan Ott <alan@signal11.us>
+ *  Copyright (C) 2013 Signal 11 Software
+ *
+ *  3-12-2008
+ *
+ *  M-Stack is free software: you can redistribute it and/or modify it under
+ *  the terms of the GNU Lesser General Public License as published by the
+ *  Free Software Foundation, version 3; or the Apache License, version 2.0
+ *  as published by the Apache Software Foundation.  If you have purchased a
+ *  commercial license for this software from Signal 11 Software, your
+ *  commerical license superceeds the information in this header.
+ *
+ *  M-Stack is distributed in the hope that it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
+ *  License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public License
+ *  along with this software.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ *  You should have received a copy of the Apache License, verion 2.0 along
+ *  with this software.  If not, see <http://www.apache.org/licenses/>.
+ */
+
+#ifndef USB_H_
+#define USB_H_
+
+/** @file usb.h
+ *  @brief M-Stack
+ *  @defgroup public_api Public API
+ */
+
+/** @addtogroup public_api
+ *  @{
+ */
+
+#include <stdint.h>
+#include <stdbool.h>
+#include <stdlib.h>
+
+#include "usb_config.h"
+
+/* setup_packet is defined in usb_ch9.h */
+struct setup_packet;
+
+/** @defgroup descriptor_items   Descriptor Items
+ *  @brief Items defined by the application which are involved in
+ *  the enumeration of the device.
+ *
+ *  The items listed in this section are macro names. An application needs
+ *  to define these macro names in usb_config.h to whatever actual C names
+ *  are used in the application for these items (typically in
+ *  usb_descriptors.c).
+ *
+ *  It is required that the application #define these items in the
+ *  application's @p usb_config.h so the USB stack can retrieve the Chapter
+ *  9 descriptors to send to the host.
+ *
+ *  While this sounds complex, it is not. See the example programs and their
+ *  usb_descriptors.c that come with the USB stack for an example of what is
+ *  required and how to easily implement it.
+ *
+ *  @addtogroup descriptor_items
+ *  @{
+ */
+
+
+/** String Descriptor Function
+ *
+ * The USB stack will call this function to retrieve string descriptors from
+ * the application. This allows the flexibility for the application to read
+ * some strings (like serial numbers) from non-const locations (like EEPROM).
+ *
+ * @param string_number   The string number requested
+ * @param ptr             A pointer to a pointer which should be set to the
+ *                        requested string descriptor by this function.
+ * @returns
+ *   Return the length of the string descriptor in bytes or -1 if the string
+ *   requested does not exist.
+ */
+extern int16_t USB_STRING_DESCRIPTOR_FUNC(uint8_t string_number, const void **ptr);
+
+/** Device Descriptor
+ *
+ * This is the device's device descriptor as defined by the USB
+ * specification, chapter 9.  @p USB_DEVICE_DESCRIPTOR must be defined in
+ * usb_config.h to be the name of the device descriptor structure, which
+ * will often be located in the application's usb_descriptors.c.
+ */
+extern const struct device_descriptor USB_DEVICE_DESCRIPTOR;
+
+/** Configuration Descriptor
+ *
+ * This is an array of the device's configuration descriptors, as defined by
+ * the USB specification, chapter 9.  USB_CONFIG_DESCRIPTOR_MAP must be
+ * defined to be the name of an array of pointers to
+ * configuration_descriptor objects, often in the application's
+ * usb_descriptors.c.  The order is not important because the @p
+ * bConfigurationValue field is used by the USB stack to determine the
+ * configuration number for each configuration descriptor.  It is important
+ * that wTotalLength in each configuration descriptor be correct, as this is
+ * used by the USB stack to determine the number of bytes to use (It is
+ * recommended to use the sizeof() operator for this field).
+ *
+ * See the example programs that come with the USB stack (specificallyl
+ * usb_descriptors.c) for a simple example of what is required.
+ */
+extern const struct configuration_descriptor *USB_CONFIG_DESCRIPTOR_MAP[];
+
+
+/* Doxygen end-of-group for descriptor_items */
+/** @}*/
+
+
+
+ /** @defgroup static_callbacks Static Callbacks
+  *  @brief Optional static callback macros to be defined in the
+  *  application's usb_config.h.
+  *
+  *  If desired, #define these callback functions in your application's
+  *  @p usb_config.h to receive notification about specific events which
+  *  happen during enumeration and otherwise. While these are not strictly
+  *  required for all devices, they may be required depending on your
+  *  device configuration.
+  *
+  *  @addtogroup static_callbacks
+  *  @{
+  */
+
+#ifdef SET_CONFIGURATION_CALLBACK
+/** @brief Callback for SET_CONFIGURATION requests
+ *
+ * SET_CONFIGURATION_CALLBACK() is called whenever a @a SET_CONFIGURATION
+ * request is received from the host.  The configuration parameter is the
+ * new configuration the host requests.  If configuration is zero, then the
+ * device is to enter the @a ADDRESS state.  If it is non-zero then the device
+ * is to enter the @a CONFIGURED state.
+ *
+ * There's no way to reject this request. The host commands a configuration
+ * be set, and it shall be done.
+ */
+void SET_CONFIGURATION_CALLBACK(uint8_t configuration);
+#endif
+
+#ifdef GET_DEVICE_STATUS_CALLBACK
+/** @brief Callback for GET_STATUS requests
+ *
+ * GET_DEVICE_STATUS_CALLBACK() is called when a @a GET_STATUS request is
+ * received from the host for the device (not the interface or the endpoint).
+ * The callback is to return the status of the device as a 16-bit
+ * unsigned integer per section 9.4.5 of the USB 2.0 specification.
+ *   Bit 0 (LSB) - 0=bus_powered, 1=self_powered
+ *   Bit 1       - 0=no_remote_wakeup, 1=remote_wakeup
+ *   Bits 2-15   - reserved, set to zero.
+ */
+uint16_t GET_DEVICE_STATUS_CALLBACK();
+#endif
+
+#ifdef ENDPOINT_HALT_CALLBACK
+/** @brief Callback for SET_FEATURE or CLEAR_FEATURE with ENDPOINT_HALT
+ *
+ * ENDPOINT_HALT_CALLBACK() is called when a @a SET_FEATURE or @a
+ * CLEAR_FEATURE is received from the host changing the endpoint halt value.
+ * This is a notification only.  There is no way to reject this request.
+ *
+ * @brief endpoint   The endpoint identifier of the affected endpoint
+ *                   (direction and number, e.g.: 0x81 means EP 1 IN).
+ * @brief halted     1=endpoint_halted (set), 0=endpoint_not_halted (clear)
+ */
+void ENDPOINT_HALT_CALLBACK(uint8_t endpoint, bool halted);
+#endif
+
+#ifdef SET_INTERFACE_CALLBACK
+/** @brief Callback for the SET_INTERFACE request
+ *
+ * SET_INTERFACE_CALLBACK() is called when a @a SET_INTERFACE request is
+ * received from the host.  @a SET_INTERFACE is used to set the alternate
+ * setting for the specified interface.  The parameters @p interface and @p
+ * alt_setting come directly from the device request (from the host).  The
+ * callback should return 0 if the new alternate setting can be set or -1 if
+ * it cannot.  This callback is completely unnecessary if you only have one
+ * alternate setting (alternate setting zero) for each interface.
+ *
+ * @param interface     The interface on which to set the alternate setting
+ * @param alt_setting   The alternate setting
+ * @returns
+ *   Return 0 for success and -1 for error (will send a STALL to the host)
+ */
+int8_t SET_INTERFACE_CALLBACK(uint8_t interface, uint8_t alt_setting);
+#endif
+
+#ifdef GET_INTERFACE_CALLBACK
+/** @brief Callback for the GET_INTERFACE request
+ *
+ * GET_INTERFACE_CALLBACK() is called when a @a GET_INTERFACE request is
+ * received from the host.  @a GET_INTERFACE is a request for the current
+ * alternate setting selected for a given interface.  The application should
+ * return the interface's current alternate setting from this callback
+ * function.  If this callback is not present, zero will be returned as the
+ * current alternate setting for all interfaces.
+ *
+ * @param interface   The interface queried for current altertate setting
+ * @returns
+ *   Return the current alternate setting for the interface requested or -1
+ *   if the interface does not exist.
+ */
+int8_t GET_INTERFACE_CALLBACK(uint8_t interface);
+#endif
+
+#ifdef OUT_TRANSACTION_CALLBACK
+/** @brief Callback for an OUT transaction
+ *
+ * OUT_TRANSACTION_CALLBACK() is called when a transaction has completed
+ * on an endpoint numbered 1 through 15, that is when data has been received
+ * from the host. The application may then get the data received by calling
+ * @p usb_get_out_buffer(), and can then re-arm the endpoint by calling @p
+ * usb_arm_out_endpoint(). The application may choose to not re-arm the
+ * endpoint if the application intends to do it at a later time.
+ *
+ * This function is called from interrupt context and should not block.
+ *
+ * @param endpoint   The endpoint on which the transfer completed
+ */
+void OUT_TRANSACTION_CALLBACK(uint8_t endpoint);
+#endif
+
+
+#ifdef IN_TRANSACTION_COMPLETE_CALLBACK
+/** @brief Callback for an IN transaction
+ *
+ * IN_TRANSACTION_COMPLETE_CALLBACK() is called when an IN transaction has
+ * completed on an endpoint numbered 1 through 15, meaning the transaction
+ * has successfully been delivered to the host. The application may send
+ * another transaction to the host using @p usb_get_in_buffer() and @p
+ * usb_send_in_buffer() from this callback if desired.
+ *
+ * This function is called from interrupt context and should not block.
+ *
+ * @param endpoint   The endpoint on which the transfer completed
+ */
+void IN_TRANSACTION_COMPLETE_CALLBACK(uint8_t endpoint);
+#endif
+
+#ifdef UNKNOWN_SETUP_REQUEST_CALLBACK
+/** @brief Callback for an unrecognized SETUP request
+ *
+ * UNKNOWN_SETUP_REQUEST_CALLBACK() is called when a SETUP packet is
+ * received with a request (bmRequestType,bRequest) which is unknown to the
+ * the USB stack.  This could be because it is a vendor-defined request or
+ * because it is some other request which is not supported, for example if
+ * you were implementing a device class in your application.  There are four
+ * ways to handle this:
+ *
+ * 0. For unknown requests, return -1. This will send a STALL to the host.
+ * 1. For requests which have no data stage, the callback should call
+ *    @p usb_send_data_stage() with a length of zero to send a zero-length
+ *    packet back to the host.
+ * 2. For requests which expect an IN data stage, the callback should call
+ *    @p usb_send_data_stage() with the data to be sent, and a callback
+ *    which will get called when the data stage is complete.  The callback
+ *    is required, and the data buffer passed to @p usb_send_data_stage()
+ *    must remain valid until the callback is called.
+ * 3. For requests which will come with an OUT data stage, the callback
+ *    should call @p usb_start_receive_ep0_data_stage() and provide a
+ *    buffer and a callback which will get called when the data stage has
+ *    completed.  The callback is required, and the data in the buffer
+ *    passed to usb_start_receive_ep0_data_stage() is not valid until the
+ *    callback is called.
+ *
+ * It is worth noting that only one control transfer can be active at any
+ * given time.  Once UNKNOWN_SETUP_REQUEST_CALLBACK() has been called, it
+ * will not be called again until the next transfer, meaning that if the
+ * application-provided UNKNOWN_SETUP_REQUEST_CALLBACK() function performs
+ * one of options 1-3 above, the callback function passed to @p
+ * usb_send_data_stage() or @p usb_start_receive_ep0_data_stage() will be
+ * called before UNKNOWN_SETUP_REQUEST_CALLBACK() can be called again.
+ * Thus, it is safe to use the same buffer for all control transfers if
+ * desired.
+ *
+ * Make sure to include @p usb_ch9.h in order to use the @p setup_packet
+ * structure.
+ *
+ * @param pkt   The SETUP packet
+ * @returns
+ *   Return 0 if the SETUP can be handled or -1 if it cannot. Returning -1
+ *   will cause STALL to be returned to the host.
+ */
+int8_t UNKNOWN_SETUP_REQUEST_CALLBACK(const struct setup_packet *pkt);
+#endif
+
+#ifdef UNKNOWN_GET_DESCRIPTOR_CALLBACK
+/** @brief Callback for a GET_DESCRIPTOR request for an unknown descriptor
+ *
+ * UNKNOWN_GET_DESCRIPTOR_CALLBACK() is called when a @a GET_DESCRIPTOR
+ * request is received from the host for a descriptor which is unrecognized
+ * by the USB stack.  This could be because it is a vendor-defined
+ * descriptor or because it is some other descriptor which is not supported,
+ * for example if you were implementing a device class in your application.
+ * The callback function should set the @p descriptor pointer and return the
+ * number of bytes in the descriptor.  If the descriptor is not supported,
+ * the callback should return -1, which will cause a STALL to be sent to the
+ * host.
+ *
+ * Make sure to include @p usb_ch9.h in order to use the @p setup_packet
+ * structure.
+ *
+ * @param pkt          The SETUP packet with the request in it.
+ * @param descriptor   a pointer to a pointer which should be set to the
+ *                     descriptor data.
+ * @returns
+ *   Return the length of the descriptor pointed to by @p *descriptor, or -1
+ *   if the descriptor does not exist.
+ */
+int16_t UNKNOWN_GET_DESCRIPTOR_CALLBACK(const struct setup_packet *pkt, const void **descriptor);
+#endif
+
+#ifdef START_OF_FRAME_CALLBACK
+/** @brief Callback for USB Start of Frame event
+ *
+ * START_OF_FRAME_CALLBACK() is called when a USB Start-of-Frame packet is
+ * received from the host.  For full-speed devices, this happens every 1
+ * millisecond.  For high-speed devices, this happens every 125
+ * microseconds.  Low-speed devices do not receive a Start-of-Frame packet.
+ */
+void START_OF_FRAME_CALLBACK(void);
+#endif
+
+#ifdef USB_RESET_CALLBACK
+/** @brief USB Reset Callback
+ *
+ * USB_RESET_CALLBACK() is called when a reset event is detected on the bus.
+ * Two bus resets are part of the normal enumeration sequence.  This
+ * function is called before the USB stack does any re-initialization.
+ */
+void USB_RESET_CALLBACK(void);
+#endif
+
+/* Doxygen end-of-group for static_callbacks */
+/** @}*/
+
+/** @brief Initialize the USB library and hardware
+ *
+ * Call this function at the beginning of execution. This function initializes
+ * the USB peripheral hardware and software library. After calling this
+ * funciton, the library will handle enumeration automatically when attached
+ * to a host.
+ */
+void usb_init(void);
+
+/** @brief Update the USB library and hardware
+ *
+ * This function services the USB peripheral's interrupts and handles all
+ * tasks related to enumeration and transfers. It is non-blocking. Whether an
+ * application should call this function depends on the @p USB_USE_INTERRUPTS
+ * #define. If @p USB_USE_INTERRUPTS is not defined, this function should be
+ * called periodically from the main application. If @p USB_USE_INTERRUPTS is
+ * defined, it should be called from interrupt context. On PIC24, this will
+ * happen automatically, as the interrupt handler is embedded in usb.c. On
+ * 8-bit PIC since the interrupt handlers are shared, this function will need
+ * to be called from the application's interrupt handler.
+ */
+void usb_service(void);
+
+/** @brief Get the device configuration
+ *
+ * Get the device configuration as set by the host. If the device is not
+ * in the CONFIGURED state, 0 will be returned.
+ *
+ * @see usb_is_configured()
+ * @returns
+ *   Return the device configuration or 0 if the device is not configured.
+ */
+uint8_t usb_get_configuration(void);
+
+/** @brief Determine whether the device is in the Configured state
+ *
+ * Return whether the device is in the configured state. During enumeration,
+ * the device will start at the DEFAULT state, transition through ADDRESS,
+ * and eventually reach CONFIGURED.  The host can also command the device
+ * out of the configured state (and back into ADDRESS).  The application
+ * shouldn't use any of the endpoints unless in the CONFIGURED state.
+ *
+ * @see usb_get_configuration()
+ */
+#define usb_is_configured() (usb_get_configuration() != 0)
+
+/** @brief Get a pointer to an endpoint's input buffer
+ *
+ * This function returns a pointer to an endpoint's input buffer. Call this
+ * to get a location to copy IN data to in order to send it to the host.
+ * Remember that IN data is data which goes from the device to the host.
+ * The maximum length of this buffer is defined by the application in
+ * usb_config.h (eg: @p EP_1_IN_LEN).  It is wise to call
+ * @p usb_in_endpoint_busy() before calling this function.
+ *
+ * @param endpoint   The endpoint requested
+ * @returns
+ *   Return a pointer to the endpoint's buffer.
+ */
+unsigned char *usb_get_in_buffer(uint8_t endpoint);
+
+/** @brief Send an endpoint's IN buffer to the host
+ *
+ * Send the data in the IN buffer for the specified endpoint to the host.
+ * Since USB is a polled bus, this only queues the data for sending. It will
+ * actually be sent when the device receives an IN token for the specified
+ * endpoint. To check later whether the data has been sent, call
+ * @p usb_in_endpoint_busy(). If the endpoint is busy, a transmission is
+ * pending, but has not been actually transmitted yet.
+ *
+ * @param endpoint   The endpoint on which to send data
+ * @param len        The amount of data to send
+ */
+void usb_send_in_buffer(uint8_t endpoint, size_t len);
+
+/** @brief Check whether an IN endpoint is busy
+ *
+ * An IN endpoint is said to be busy if there is data in its buffer and it
+ * is waiting for an IN token from the host in order to send it (or if it is
+ * in the process of sending the data).
+ *
+ * @param endpoint   The endpoint requested
+ * @returns
+ *    Return true if the endpoint is busy, or false if it is not.
+ */
+bool usb_in_endpoint_busy(uint8_t endpoint);
+
+/** @brief Halt an IN endpoint
+ *
+ * Set the ENDPOINT_HALT condition on an IN endpoint. Do not call this on
+ * endpoint zero.
+ *
+ * @param endpoint   The endpoint requested
+ * @returns
+ *    Return 0 if the endpoint can be halted, or -1 if the endpoint number
+ *    is invalid.
+*/
+uint8_t usb_halt_ep_in(uint8_t ep);
+
+/** @brief Check whether an endpoint is halted
+ *
+ * Check if an endpoint has been halted by the host. If an endpoint is
+ * halted, don't call usb_send_in_buffer().
+ *
+ * @see ENDPOINT_HALT_CALLBACK.
+ *
+ * @param endpoint   The endpoint requested
+ * @returns
+ *   Return true if the endpointed is halted, or false if it is not.
+ */
+bool usb_in_endpoint_halted(uint8_t endpoint);
+
+/** @brief Check whether an OUT endpoint has received data
+ *
+ * Check if an OUT endpoint has completed a transaction and has received
+ * data from the host.  If it has, the application should call @p
+ * usb_get_out_buffer() to get the data and then call @p
+ * usb_arm_out_endpoint() to enable reception of the next transaction.
+ *
+ * @param endpoint   The endpoint requested
+ * @returns
+ *   Return true if the endpoint has received data, false if it has not.
+ */
+bool usb_out_endpoint_has_data(uint8_t endpoint);
+
+/** @brief Re-enable reception on an OUT endpoint
+ *
+ * Re-enable reception on the specified endpoint. Call this function after
+ * @p usb_out_endpoint_has_data() indicated that there was data available,
+ * and after the application has dealt with the data.  Calling this function
+ * gives the specified OUT endpoint's buffer back to the USB stack to
+ * receive the next transaction.
+ *
+ * @param endpoint   The endpoint requested
+ */
+void usb_arm_out_endpoint(uint8_t endpoint);
+
+/** @brief Halt an OUT endpoint
+ *
+ * Set the ENDPOINT_HALT condition on an OUT endpoint. Do not call this on
+ * endpoint zero.
+ *
+ * @param endpoint   The endpoint requested
+ * @returns
+ *    Return 0 if the endpoint can be halted, or -1 if the endpoint number
+ *    is invalid.
+ */
+uint8_t usb_halt_ep_out(uint8_t ep);
+
+/** @brief Check whether an OUT endpoint is halted
+ *
+ * Check if an endpoint has been halted by the host. If an OUT endpoint is
+ * halted, the USB stack will automatically return STALL in response to any
+ * OUT tokens.
+ *
+ * @see ENDPOINT_HALT_CALLBACK.
+ *
+ * @param endpoint   The endpoint requested
+ * @returns
+ *   Return true if the endpointed is halted, or false if it is not.
+ */
+bool usb_out_endpoint_halted(uint8_t endpoint);
+
+/** @brief Get a pointer to an endpoint's OUT buffer
+ *
+ * Call this function to get a pointer to an endpoint's OUT buffer after
+ * @p usb_out_endpoint_has_data() returns @p true (indicating that
+ * an OUT transaction has been received). Do not call this function if
+ * @p usb_out_endpoint_has_data() does not return true.
+ *
+ * @param endpoint   The endpoint requested
+ * @param buffer     A pointer to a pointer which will be set to the
+ *                   endpoint's OUT buffer.
+ * @returns
+ *   Return the number of bytes received.
+ */
+uint8_t usb_get_out_buffer(uint8_t endpoint, const unsigned char **buffer);
+
+/** @brief Endpoint 0 data stage callback definition
+ *
+ * This is the callback function type expected to be passed to @p
+ * usb_start_receive_ep0_data_stage() and @p usb_send_data_stage().
+ * Callback functions will be called by the stack when the event for which
+ * they are registered occurs.
+ *
+ * @param transfer_ok   @a true if transaction completed successfully, or
+ *                      @a false if there was an error
+ * @param context       A pointer to application-provided context data
+ */
+typedef void (*usb_ep0_data_stage_callback)(bool transfer_ok, void *context);
+
+/** @brief Start the data stage of an OUT control transfer
+ *
+ * Start the data stage of a control transfer for a transfer which has an
+ * OUT data stage.  Call this from @p UNKNOWN_SETUP_REQUEST_CALLBACK for OUT
+ * control transfers which being handled by the application.  Once the
+ * transfer has completed, @p callback will be called with the @p context
+ * pointer provided.  The @p buffer should be considered to be owned by the
+ * USB stack until the @p callback is called and should not be modified by the
+ * application until this time.
+ *
+ * @see UNKNOWN_SETUP_REQUEST_CALLBACK
+ *
+ * @param buffer     A buffer in which to place the data
+ * @param len        The number of bytes to expect. This must be less than or
+ *                   equal to the number of bytes in the buffer, and for
+ *                   proper setup packets will be the wLength parameter.
+ * @param callback   A callback function to call when the transfer completes.
+ *                   This parameter is mandatory. Once the callback is
+ *                   called, the transfer is over, and the buffer can be
+ *                   considered to be owned by the application again.
+ * @param context    A pointer to be passed to the callback.  The USB stack
+ *                   does not dereference this pointer
+ */
+void usb_start_receive_ep0_data_stage(char *buffer, size_t len,
+	usb_ep0_data_stage_callback callback, void *context);
+
+/** @brief Start the data stage of an IN control transfer
+ *
+ * Start the data stage of a control transfer for a transfer which has an IN
+ * data stage.  Call this from @p UNKNOWN_SETUP_REQUEST_CALLBACK for IN
+ * control transfers which are being handled by the application.  Once the
+ * transfer has completed, @p callback will be called with the @p context
+ * pointer provided.  The @p buffer should be considered to be owned by the
+ * USB stack until the callback is called and should not be modified by the
+ * application until this time.  Do not pass in a buffer which is on the
+ * stack.  The data will automatically be split into as many transactions as
+ * necessary to complete the transfer.
+ *
+ * @see UNKNOWN_SETUP_REQUEST_CALLBACK
+ *
+ * @param buffer     A buffer containing the data to send. This should be a
+ *                   buffer capable of having an arbitrary lifetime.  Do not
+ *                   use a stack variable for this buffer, and do not free
+ *                   this buffer until the callback has been called.
+ * @param len        The number of bytes to send
+ * @param callback   A callback function to call when the transfer completes.
+ *                   This parameter is mandatory. Once the callback is
+ *                   called, the transfer is over, and the buffer can be
+ *                   considered to be owned by the application again.
+ * @paramcontext     A pointer to be passed to the callback. The USB stack
+ *                   does not dereference this pointer.
+ */
+void usb_send_data_stage(char *buffer, size_t len,
+	usb_ep0_data_stage_callback callback, void *context);
+
+
+/* Doxygen end-of-group for public_api */
+/** @}*/
+
+#endif /* USB_H_ */
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usb/include/usb_cdc.h	Sat Feb 18 16:14:32 2017 +0000
@@ -0,0 +1,501 @@
+/*
+ *  M-Stack USB CDC Device Class Structures
+ *  Copyright (C) 2013 Alan Ott <alan@signal11.us>
+ *  Copyright (C) 2013 Signal 11 Software
+ *
+ *  2013-09-27
+ *
+ *  M-Stack is free software: you can redistribute it and/or modify it under
+ *  the terms of the GNU Lesser General Public License as published by the
+ *  Free Software Foundation, version 3; or the Apache License, version 2.0
+ *  as published by the Apache Software Foundation.  If you have purchased a
+ *  commercial license for this software from Signal 11 Software, your
+ *  commerical license superceeds the information in this header.
+ *
+ *  M-Stack is distributed in the hope that it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
+ *  License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public License
+ *  along with this software.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ *  You should have received a copy of the Apache License, verion 2.0 along
+ *  with this software.  If not, see <http://www.apache.org/licenses/>.
+ */
+
+#ifndef USB_CDC_H__
+#define USB_CDC_H__
+
+/** @file usb_cdc.h
+ *  @brief USB CDC Class Enumerations and Structures
+ *  @defgroup public_api Public API
+ */
+
+/** @addtogroup public_api
+ *  @{
+ */
+
+#include <stdint.h>
+#include "usb_config.h"
+
+#if defined(__XC16__) || defined(__XC32__)
+#pragma pack(push, 1)
+#elif __XC8
+#else
+#error "Compiler not supported"
+#endif
+
+/** @defgroup cdc_items USB CDC Class Enumerations and Descriptors
+ *  @brief Packet structs, constants, and callback functions implementing
+ *  the "Universal Serial Bus Class Definitions for Communication Devices"
+ *  (commonly the USB CDC Specification), version 1.1.
+ *
+ *  For more information, see the above referenced document, available from
+ *  http://www.usb.org .
+ *  @addtogroup cdc_items
+ *  @{
+ */
+
+/* CDC Specification 1.1 document sections are listed in the comments */
+#define CDC_DEVICE_CLASS 0x02 /* 4.1 */
+#define CDC_COMMUNICATION_INTERFACE_CLASS 0x02 /* 4.2 */
+#define CDC_COMMUNICATION_INTERFACE_CLASS_ACM_SUBCLASS 0x02 /* 4.3 */
+/* Many of the subclass codes (section 4.3) are omitted here. Get in
+ * contact with Signal 11 if you need something specific. */
+
+#define CDC_DATA_INTERFACE_CLASS 0x0a /* 4.5 */
+#define CDC_DATA_INTERFACE_CLASS_PROTOCOL_NONE 0x0 /* 4.7 */
+#define CDC_DATA_INTERFACE_CLASS_PROTOCOL_VENDOR 0xff /* 4.7 */
+/* Many of the protocol codes (section 4.7) are omitted here. Get in
+ * contact with Signal 11 if you need something specific. */
+
+/** CDC Descriptor types: 5.2.3 */
+enum CDCDescriptorTypes {
+	DESC_CS_INTERFACE = 0x24,
+	DESC_CS_ENDPOINT  = 0x25,
+};
+
+/* Descriptor subtypes: 5.2.3 */
+enum CDCFunctionalDescriptorSubtypes {
+	CDC_FUNCTIONAL_DESCRIPTOR_SUBTYPE_HEADER = 0x0,
+	CDC_FUNCTIONAL_DESCRIPTOR_SUBTYPE_ACM = 0x2,
+	CDC_FUNCTIONAL_DESCRIPTOR_SUBTYPE_UNION = 0x6,
+};
+/* Many of the descriptor subtypes (section 5.2.3, table 25) are omitted
+ * here.  Get in contact with Signal 11 if you need something specific. */
+
+/** Abstract Control Management (ACM) capabilities
+ *
+ * See section 5.2.3.3 of the CDC Specification, version 1.1.
+ */
+enum CDCACMCapabilities {
+	CDC_ACM_CAPABILITY_COMM_FEATURES = 0x1,
+	CDC_ACM_CAPABILITY_LINE_CODINGS = 0x2,
+	CDC_ACM_CAPABILITY_SEND_BREAK = 0x4,
+	CDC_ACM_CAPABILITY_NETWORK_CONNECTION = 0x8,
+};
+
+/** CDC ACM Class Requests
+ *
+ * These are the class requests needed for ACM (see section 6.2, table 45).
+ * Others are omitted.  Get in contact with Signal 11 if you need something
+ * specific.
+ */
+enum CDCRequests {
+	CDC_SEND_ENCAPSULATED_COMMAND = 0x0,
+	CDC_GET_ENCAPSULATED_RESPONSE = 0x1,
+	CDC_SET_COMM_FEATURE = 0x2,
+	CDC_GET_COMM_FEATURE = 0x3,
+	CDC_CLEAR_COMM_FEATURE = 0x4,
+	CDC_SET_LINE_CODING = 0x20,
+	CDC_GET_LINE_CODING = 0x21,
+	CDC_SET_CONTROL_LINE_STATE = 0x22,
+	CDC_SEND_BREAK = 0x23,
+};
+
+/** CDC Communication Feature Selector Codes
+ *
+ * See section 6.2.4, Table 47 of the CDC Specification, version 1.1.
+ */
+enum CDCCommFeatureSelector {
+	CDC_FEATURE_ABSTRACT_STATE = 0x1,
+	CDC_FEATURE_COUNTRY_SETTING = 0x2,
+};
+
+/** CDC Character Format
+ *
+ * These values are used in the bCharFormat field of the GET_LINE_CODING and
+ * SET_LINE_CODING requests.  See section 6.2.13 (table 50) of the CDC
+ * Specification, version 1.1.
+ */
+enum CDCCharFormat {
+	CDC_CHAR_FORMAT_1_STOP_BIT = 0,
+	CDC_CHAR_FORMAT_1_POINT_5_STOP_BITS = 1,
+	CDC_CHAR_FORMAT_2_STOP_BITS = 2,
+};
+
+/** CDC Parity Type
+ *
+ * These values are used in the bParityType field of the GET_LINE_CODING and
+ * SET_LINE_CODING requests.  See section 6.2.13 (table 50) of the CDC
+ * Specification, version 1.1.
+ */
+enum CDCParityType {
+	CDC_PARITY_NONE  = 0,
+	CDC_PARITY_ODD   = 1,
+	CDC_PARITY_EVEN  = 2,
+	CDC_PARITY_MARK  = 3,
+	CDC_PARITY_SPACE = 4,
+};
+
+/** CDC Class-Specific Notification Codes
+ *
+ * See section 6.3 (table 68) of the CDC Specification, version 1.1.
+ */
+enum CDCNotifications {
+	CDC_NETWORK_CONNECTION = 0x0,
+	CDC_RESPONSE_AVAILABLE = 0x1,
+	CDC_SERIAL_STATE = 0x20,
+};
+/* Many of the CDC Notifications are omitted here.  Get in contact with
+ * Signal 11 if you need something specific.  */
+
+/** CDC Functional Descriptor Header.
+ *
+ * See section 5.2.3.1 of the CDC Specification, version 1.1.
+ */
+struct cdc_functional_descriptor_header {
+	uint8_t bFunctionLength; /**< Size of this functional  descriptor (5) */
+	uint8_t bDescriptorType; /**< Use DESC_CS_INTERFACE */
+	uint8_t bDescriptorSubtype; /**< CDC_DESCRIPTOR_SUBTYPE_HEADER */
+	uint16_t bcdCDC; /**< CDC version in BCD format. Use 0x0101 (1.1). */
+};
+
+/** CDC Abstract Control Management Functional Descriptor
+ *
+ * See Section 5.2.3.3 of the CDC Specification, version 1.1.
+ */
+struct cdc_acm_functional_descriptor {
+	uint8_t bFunctionLength; /**< Size of this functional descriptor (4) */
+	uint8_t bDescriptorType; /**< Use DESC_CS_INTERFACE */
+	uint8_t bDescriptorSubtype; /**< CDC_DESCRIPTOR_SUBTYPE_ACM */
+	uint8_t bmCapabilities; /**< See CDC_ACM_CAPABILITY* definitions */
+};
+
+/** CDC Union Functional Registor
+ *
+ * See Section 5.2.3.8 of the CDC Specification, version 1.1.
+ */
+struct cdc_union_functional_descriptor {
+	uint8_t bFunctionLength; /**< Size of this functional descriptor */
+	uint8_t bDescriptorType; /**< Use DESC_CS_INTERFACE */
+	uint8_t bDescriptorSubtype; /**< CDC_DESCRIPTOR_SUBTYPE_ACM */
+	uint8_t bMasterInterface;
+	uint8_t bSlaveInterface0;
+	/* More bSlaveInterfaces cound go here, but you'll have to pack them
+	 * yourself into the configuration descriptor, and make sure
+	 * bFunctionLength covers them all. */
+};
+
+/* CDC Notification Header
+ *
+ * CDC Notifications all share this same header. It's very similar to a
+ * @p setup_packet .
+ */
+struct cdc_notification_header {
+	union {
+		struct {
+			uint8_t destination : 5; /**< @see enum DestinationType */
+			uint8_t type : 2;        /**< @see enum RequestType */
+			uint8_t direction : 1;   /**< 0=out, 1=in */
+		};
+		uint8_t bmRequestType;
+	} REQUEST;
+	uint8_t bNotification;  /**< @see enum CDCNotifications */
+	uint16_t wValue;
+	uint16_t wIndex;
+	uint16_t wLength;
+};
+
+
+/* CDC Serial State Notification
+ *
+ * See Section 6.3.5 of the CDC Specification, version 1.1.
+ */
+struct cdc_serial_state_notification {
+	struct cdc_notification_header header;
+	union {
+		struct {
+			uint16_t bRxCarrier : 1; /**< Indicates DCD */
+			uint16_t bTxCarrier : 1; /**< Indicates DSR */
+			uint16_t bBreak : 1;
+			uint16_t bRingSignal : 1;
+			uint16_t bFraming : 1;
+			uint16_t bParity : 1;
+			uint16_t bOverrun : 1;
+			uint16_t : 1;
+			uint16_t : 8; /* XC8 can't handle a 9-bit bitfield */
+		} bits;
+		uint16_t serial_state;
+	} data;
+};
+
+/* Many functional descriptors are omitted here. Get in contact with
+ * Signal 11 if you need something specific. */
+
+/* Message Structures */
+
+/** CDC Line Coding Structure
+ *
+ * See Section 6.2.13 of the CDC Specification, version 1.1.
+ */
+struct cdc_line_coding {
+	uint32_t dwDTERate; /**< Data Terminal Rate (bits per second) */
+	uint8_t bCharFormat; /**< Stop bits: @see CDCCharFormat */
+	uint8_t bParityType; /**< Parity Type: @see CDCParityType */
+	uint8_t bDataBits; /**< Data Bits: 5, 6, 7, 8 or 16 */
+};
+
+
+/** Process CDC Setup Request
+ *
+ * Process a setup request which has been unhandled as if it is potentially
+ * a CDC setup request. This function will then call appropriate callbacks
+ * into the appliction if the setup packet is one recognized by the CDC
+ * specification.
+ *
+ * @param setup          A setup packet to handle
+ *
+ * @returns
+ *   Returns 0 if the setup packet could be processed or -1 if it could not.
+ */
+uint8_t process_cdc_setup_request(const struct setup_packet *setup);
+
+/** CDC SEND_ENCAPSULATED_COMMAND callback
+ *
+ * The USB Stack will call this function when a GET_ENCAPSULATED_COMMAND
+ * request has been received from the host.  There are two ways to handle
+ * this:
+ *
+ * 1. If the request can't be handled, return -1. This will send a STALL
+ *    to the host.
+ * 2. If the request can be handled, call @p
+ *    usb_start_receive_ep0_data_stage() with a buffer to be filled with the
+ *    command data and a callback which will get called when the data stage
+ *    is complete.  The callback is required, and the command data buffer
+ *    passed to @p usb_start_receive_ep0_data_stage() must remain valid
+ *    until the callback is called.
+ *
+ * It is worth noting that only one control transfer can be active at any
+ * given time.  Once HID_SET_REPORT_CALLBACK() has been called, it will not
+ * be called again until the next transfer, meaning that if the
+ * application-provided HID_SET_REPORT_CALLBACK() function performs option 1
+ * above, the callback function passed to @p
+ * usb_start_receive_ep0_data_stage() will be called before any other setup
+ * transfer can happen again.  Thus, it is safe to use the same buffer for
+ * all control transfers if desired.
+ *
+ *
+ * @param interface      The interface for which the command is intended
+ * @param length         The length of the command which will be present
+ *                       in the data stage.
+ * @returns
+ *   Return 0 if the request can be handled or -1 if it cannot. Returning -1
+ *   will cause STALL to be returned to the host.
+ */
+extern int8_t CDC_SEND_ENCAPSULATED_COMMAND_CALLBACK(uint8_t interface,
+                                                     uint16_t length);
+
+#ifdef CDC_GET_ENCAPSULATED_RESPONSE_CALLBACK
+/** CDC GET_ENCAPSULATED_RESPONSE callback
+ *
+ * The USB Stack will call this function when a GET_ENCAPSULATED_RESPONSE
+ * request has been received from the host.  This function should set the @p
+ * response pointer to a buffer containing the response data and return the
+ * length of the response.  Once the transfer has completed, @p callback will
+ * be called with the @p context pointer provided.  The buffer pointed to by
+ * @p response should be considered to be owned by the USB stack until the @p
+ * callback is called and should not be modified by the application until
+ * that time.
+ *
+ *
+ * @param interface      The interface for which the report is requested
+ * @param length         The length of the response requested by the host
+ * @param response       A pointer to a pointer which should be set to the
+ *                       response data.
+ * @param callback       A callback function to call when the transfer
+ *                       completes.  This parameter is mandatory.  Once the
+ *                       callback is called, the transfer is over, and the
+ *                       buffer can be considered to be owned by the
+ *                       application again.
+ * @param context        A pointer to be passed to the callback.  The USB
+ *                       stack does not dereference this pointer.
+ *
+ * @returns
+ *   Return 0 if the request can be handled or -1 if it cannot. Returning -1
+ *   will cause STALL to be returned to the host.
+ */
+extern int16_t CDC_GET_ENCAPSULATED_RESPONSE_CALLBACK(uint8_t interface,
+                               uint16_t length, const void **response,
+                               usb_ep0_data_stage_callback *callback,
+                               void **context);
+#endif
+
+#ifdef CDC_SET_COMM_FEATURE_CALLBACK
+/** CDC SET_COMM_FEATURE callback
+ *
+ * The USB Stack will call this function when a SET_COMM_FEATURE request has
+ * been received from the host.  The device should set the idle setting
+ * and/or data multiplexed state if requested.  There is no way to refuse
+ * this message.  If this message is not supported by the device, simply do
+ * not define CDC_SET_COMM_FEATURE_CALLBACK.
+ *
+ * @param interface      The interface for which the command is intended
+ * @param idle_setting   Whether to set the idle setting. True = clear
+ *                       the idle setting.
+ * @param data_multiplexed_state  Whether to set the data multiplexed
+ *                                state. True = clear the multiplexed state.
+ */
+extern void CDC_SET_COMM_FEATURE_CALLBACK(uint8_t interface,
+                                            bool idle_setting,
+                                            bool data_multiplexed_state);
+#endif
+
+#ifdef CDC_CLEAR_COMM_FEATURE_CALLBACK
+/** CDC CLEAR_COMM_FEATURE callback
+ *
+ * The USB Stack will call this function when a CLEAR_COMM_FEATURE request
+ * has been received from the host.  The device should clear the idle
+ * setting and/or data multiplexed state if requested.  There is no way to
+ * refuse this message.  If this message is not supported by the device,
+ * simply do not define CDC_CLEAR_COMM_FEATURE_CALLBACK.
+ *
+ * @param interface      The interface for which the command is intended
+ * @param idle_setting   Whether to clear the idle setting. True = clear
+ *                       the idle setting.
+ * @param data_multiplexed_state  Whether to clear the data multiplexed
+ *                                state. True = clear the multiplexed state.
+ */
+extern void CDC_CLEAR_COMM_FEATURE_CALLBACK(uint8_t interface,
+                                            bool idle_setting,
+                                            bool data_multiplexed_state);
+#endif
+
+#ifdef CDC_GET_COMM_FEATURE_CALLBACK
+/** CDC GET_COMM_FEATURE callback
+ *
+ * The USB Stack will call this function when a GET_COMM_FEATURE request has
+ * been received from the host.  This function should set the @p
+ * idle_setting and @p multiplexed_state pointers to their current values.
+ *
+ * @param interface      The interface for which the report is requested
+ * @param idle_setting   Set to the current value of the idle setting.
+ * @param multiplexed_state   Set to the current value of the multiplexed
+ *                            state.
+ *
+ * @returns
+ *   Return 0 if the request can be handled or -1 if it cannot. Returning -1
+ *   will cause STALL to be returned to the host.
+ */
+extern int8_t CDC_GET_COMM_FEATURE_CALLBACK(
+                               uint8_t interface,
+                               bool *idle_setting,
+                               bool *data_multiplexed_state);
+#endif
+
+#ifdef CDC_SET_LINE_CODING_CALLBACK
+/** CDC SET_LINE_CODING callback
+ *
+ * The USB Stack will call this function when a SET_LINE_CODING
+ * request has been received from the host. The device should then set
+ * the line coding to the specified values. There is no way to refuse
+ * this message. If this message is not supported by the device, simply
+ * do not define CDC_SET_LINE_CODING_CALLBACK.
+ *
+ * @param interface      The interface for which the command is intended
+ * @param coding         The new line coding set by the host
+ *
+ */
+extern void CDC_SET_LINE_CODING_CALLBACK(uint8_t interface,
+                                         const struct cdc_line_coding *coding);
+#endif
+
+#ifdef CDC_GET_LINE_CODING_CALLBACK
+/** CDC GET_LINE_CODING callback
+ *
+ * The USB Stack will call this function when a GET_LINE_CODING request has
+ * been received from the host.  This function should set the @p values in
+ * the structure pointed to by @p coding to the current line coding values.
+ *
+ * @param interface      The interface for which the report is requested
+ * @param coding         Pointer to a structure which must be filled with
+ *                       the current line coding values.
+ * @param callback       A callback function to call when the transfer
+ *                       completes.  This parameter is mandatory.  Once the
+ *                       callback is called, the transfer is over, and the
+ *                       buffer can be considered to be owned by the
+ *                       application again.
+ * @param context        A pointer to be passed to the callback.  The USB stack
+ *                       does not dereference this pointer.
+ *
+ * @returns
+ *   Return 0 if the request can be handled or -1 if it cannot. Returning -1
+ *   will cause STALL to be returned to the host.
+ */
+extern int8_t CDC_GET_LINE_CODING_CALLBACK(uint8_t interface,
+                                           struct cdc_line_coding *coding);
+#endif
+
+#ifdef CDC_SET_CONTROL_LINE_STATE_CALLBACK
+/** CDC SET_CONTROL_LINE_STATE callback
+ *
+ * The USB Stack will call this function when a SET_CONTROL_LINE_STATE
+ * request has been received from the host.  The device should then set the
+ * control lines as requested.
+ *
+ * @param interface      The interface for which the command is intended
+ * @param dtr            The state of the DTR line. True = activated.
+ * @param rts            The state of the RTS line. True = activated.
+ *
+ * @returns
+ *   Return 0 if the request can be handled or -1 if it cannot. Returning -1
+ *   will cause STALL to be returned to the host.
+ */
+extern int8_t CDC_SET_CONTROL_LINE_STATE_CALLBACK(uint8_t interface,
+                                                  bool dtr, bool dts);
+#endif
+
+#ifdef CDC_SEND_BREAK_CALLBACK
+/** CDC SEND_BREAK callback
+ *
+ * The USB Stack will call this function when a SEND_BREAK request has been
+ * received from the host.  The device should then assert a break condition
+ * for the specified number of milliseconds.
+ *
+ * @param interface      The interface for which the command is intended
+ * @param duration       The duration of the break in milliseconds
+ *
+ * @returns
+ *   Return 0 if the request can be handled or -1 if it cannot. Returning -1
+ *   will cause STALL to be returned to the host.
+ */
+extern int8_t CDC_SEND_BREAK_CALLBACK(uint8_t interface, uint16_t duration);
+#endif
+
+
+/* Doxygen end-of-group for cdc_items */
+/** @}*/
+
+
+#if defined(__XC16__) || defined(__XC32__)
+#pragma pack(pop)
+#elif __XC8
+#else
+#error "Compiler not supported"
+#endif
+
+/* Doxygen end-of-group for public_api */
+/** @}*/
+
+#endif /* USB_CDC_H__ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usb/include/usb_ch9.h	Sat Feb 18 16:14:32 2017 +0000
@@ -0,0 +1,286 @@
+/*
+ *  M-Stack USB Chapter 9 Structures
+ *  Copyright (C) 2013 Alan Ott <alan@signal11.us>
+ *  Copyright (C) 2013 Signal 11 Software
+ *
+ *  2013-04-26
+ *
+ *  M-Stack is free software: you can redistribute it and/or modify it under
+ *  the terms of the GNU Lesser General Public License as published by the
+ *  Free Software Foundation, version 3; or the Apache License, version 2.0
+ *  as published by the Apache Software Foundation.  If you have purchased a
+ *  commercial license for this software from Signal 11 Software, your
+ *  commerical license superceeds the information in this header.
+ *
+ *  M-Stack is distributed in the hope that it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
+ *  License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public License
+ *  along with this software.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ *  You should have received a copy of the Apache License, verion 2.0 along
+ *  with this software.  If not, see <http://www.apache.org/licenses/>.
+ */
+
+#ifndef USB_CH9_H__
+#define USB_CH9_H__
+
+/** @file usb.h
+ *  @brief USB Chapter 9 Enumerations and Structures
+ *  @defgroup public_api Public API
+ */
+
+/** @addtogroup public_api
+ *  @{
+ */
+
+#include <stdint.h>
+
+#if defined(__XC16__) || defined(__XC32__)
+#pragma pack(push, 1)
+#elif __XC8
+#else
+#error "Compiler not supported"
+#endif
+
+/** @defgroup ch9_items USB Chapter 9 Enumerations and Descriptors
+ *  @brief Packet structs from Chapter 9 of the USB spec which deals with
+ *  device enumeration.
+ *
+ *  For more information about these structures, see Chapter 9 of the USB
+ *  specification, available from http://www.usb.org .
+ *  @addtogroup ch9_items
+ *  @{
+ */
+
+/** USB PIDs */
+enum PID {
+	PID_OUT = 0x01,
+	PID_IN  = 0x09,
+	PID_SOF = 0x05,
+	PID_SETUP = 0x0D,
+	PID_DATA0 = 0x03,
+	PID_DATA1 = 0x0B,
+	PID_DATA2 = 0x07,
+	PID_MDATA = 0x0F,
+	PID_ACK   = 0x02,
+	PID_NAK   = 0x0A,
+	PID_STALL = 0x0E,
+	PID_NYET  = 0x06,
+	PID_PRE   = 0x0C,
+	PID_ERR   = 0x0C,
+	PID_SPLIT = 0x08,
+	PID_PING  = 0x04,
+	PID_RESERVED = 0x00,
+};
+
+/** Destination type
+ *
+ * This is present in the SETUP packet's bmRequestType field as Direction.
+ */
+enum DestinationType {
+	DEST_DEVICE = 0,
+	DEST_INTERFACE = 1,
+	DEST_ENDPOINT = 2,
+	DEST_OTHER_ELEMENT = 3,
+};
+
+/** Request type
+ *
+ * These are present in the SETUP packet's bmRequestType field as Type.
+ */
+enum RequestType {
+	REQUEST_TYPE_STANDARD = 0,
+	REQUEST_TYPE_CLASS    = 1,
+	REQUEST_TYPE_VENDOR   = 2,
+	REQUEST_TYPE_RESERVED = 3,
+};
+
+/** Control Request
+ *
+ * These are requests sent in the SETUP packet's bRequest field.
+ */
+enum StandardControlRequest {
+	GET_STATUS = 0x0,
+	CLEAR_FEATURE = 0x1,
+	SET_FEATURE = 0x3,
+	SET_ADDRESS = 0x5,
+	GET_DESCRIPTOR = 0x6,
+	SET_DESCRIPTOR = 0x7,
+	GET_CONFIGURATION = 0x8,
+	SET_CONFIGURATION = 0x9,
+	GET_INTERFACE = 0xA,
+	SET_INTERFACE = 0xB,
+	SYNCH_FRAME = 0xC,
+};
+
+/** Standard Descriptor Types */
+enum DescriptorTypes {
+	DESC_DEVICE = 0x1,
+	DESC_CONFIGURATION = 0x2,
+	DESC_STRING = 0x3,
+	DESC_INTERFACE = 0x4,
+	DESC_ENDPOINT = 0x5,
+	DESC_DEVICE_QUALIFIER = 0x6,
+	DESC_OTHER_SPEED_CONFIGURATION = 0x7,
+	DESC_INTERFACE_POWER = 0x8,
+	DESC_OTG = 0x9,
+	DESC_DEBUG = 0xA,
+	DESC_INTERFACE_ASSOCIATION = 0xB,
+};
+
+/** Device Classes
+ *
+ * Some Device class constants which don't correspond to actual
+ * classes.
+ *
+ * Device class codes which correspond to actual device classes are
+ * defined in that device class's header file (for M-Stack supported
+ * device classes).
+ */
+enum DeviceClassCodes {
+	DEVICE_CLASS_DEFINED_AT_INTERFACE_LEVEL = 0x0,
+	DEVICE_CLASS_MISC = 0xef,
+	DEVICE_CLASS_APPLICATION_SPECIFIC = 0xfe,
+	DEVICE_CLASS_VENDOR_SPECIFIC = 0xff,
+};
+
+/** Endpoint Attributes */
+enum EndpointAttributes {
+	EP_CONTROL = 0x0,
+	EP_ISOCHRONOUS = 0x1,
+	EP_BULK = 0x2,
+	EP_INTERRUPT = 0x3,
+
+	/* More bits here for ISO endpoints only. */
+};
+
+/** The SETUP packet, as defined by the USB specification.
+ *
+ * The contents of the packet sent from the host during the SETUP stage of
+ * every control transfer
+ */
+struct setup_packet {
+	union {
+		struct {
+			uint8_t destination : 5; /**< @see enum DestinationType */
+			uint8_t type : 2;        /**< @see enum RequestType */
+			uint8_t direction : 1;   /**< 0=out, 1=in */
+		};
+		uint8_t bmRequestType;
+	} REQUEST;
+	uint8_t bRequest;  /**< Dependent on @p type. @see enum StandardControlRequest */
+	uint16_t wValue;
+	uint16_t wIndex;
+	uint16_t wLength;
+};
+
+/** Device Descriptor */
+struct device_descriptor {
+	uint8_t bLength;
+	uint8_t bDescriptorType; /**< set to DESC_DEVICE */
+	uint16_t bcdUSB; /**< Set to 0x0200 for USB 2.0 */
+	uint8_t bDeviceClass;
+	uint8_t bDeviceSubclass;
+	uint8_t bDeviceProtocol;
+	uint8_t bMaxPacketSize0; /**< Max packet size for ep 0. Must be 8, 16, 32, or 64. */
+	uint16_t idVendor;
+	uint16_t idProduct;
+	uint16_t bcdDevice;
+	uint8_t  iManufacturer; /**< index of manufacturer string descriptor */
+	uint8_t  iProduct;      /**< index of product string descriptor */
+	uint8_t  iSerialNumber; /**< index of serial number string descriptor */
+	uint8_t  bNumConfigurations;
+};
+
+/** Configuration Descriptor */
+struct configuration_descriptor {
+	uint8_t bLength;
+	uint8_t bDescriptorType; /**< Set to DESC_CONFIGURATION */
+	uint16_t wTotalLength;
+	uint8_t bNumInterfaces;
+	uint8_t bConfigurationValue;
+	uint8_t iConfiguration; /**< index of string descriptor */
+	uint8_t bmAttributes;
+	uint8_t bMaxPower; /**< one-half the max power required by this device. */
+};
+
+/** Interface Descriptor */
+struct interface_descriptor {
+	uint8_t bLength;
+	uint8_t bDescriptorType; /**< Set to DESC_INTERFACE */
+	uint8_t bInterfaceNumber;
+	uint8_t bAlternateSetting;
+	uint8_t bNumEndpoints;
+	uint8_t bInterfaceClass;
+	uint8_t bInterfaceSubclass;
+	uint8_t bInterfaceProtocol;
+	uint8_t iInterface;
+};
+
+/** Endpoint Descriptor */
+struct endpoint_descriptor {
+	// ...
+	uint8_t bLength;
+	uint8_t bDescriptorType; /**< Set to DESC_ENDPOINT */
+	uint8_t bEndpointAddress;
+	uint8_t bmAttributes;
+	uint16_t wMaxPacketSize;
+	uint8_t bInterval;
+};
+
+/** String Descriptor */
+struct string_descriptor {
+	uint8_t bLength;
+	uint8_t bDescriptorType; /**< Set to DESC_STRING */
+	uint16_t chars[];
+};
+
+/** Interface Association Descriptor
+ *
+ * See the Interface Association Descriptors Engineering Change Note (ECN)
+ * available from www.usb.org .
+ */
+struct interface_association_descriptor {
+	uint8_t bLength;         /**< Set to 8 bytes */
+	uint8_t bDescriptorType; /**< Set to DESC_INTERFACE_ASSOCIATION = 0xB */
+	uint8_t bFirstInterface;
+	uint8_t bInterfaceCount;
+	uint8_t bFunctionClass;
+	uint8_t bFunctionSubClass;
+	uint8_t bFunctionProtocol;
+	uint8_t iFunction; /**< String Descriptor Index */
+};
+
+/* Doxygen end-of-group for ch9_items */
+/** @}*/
+
+
+/** @cond INTERNAL */
+
+/* So far this is the best place for these macros because they are used in
+ * usb.c and also in the application's usb_descriptors.c.  Most applications
+ * will not need to include this file outside their usb_descriptors.c, so
+ * there isn't much namespace pollution.
+ */
+#define USB_ARRAYLEN(X) (sizeof(X)/sizeof(*X))
+#define STATIC_SIZE_CHECK_EQUAL(X,Y) typedef char USB_CONCAT(STATIC_SIZE_CHECK_LINE_,__LINE__) [(X==Y)?1:-1]
+#define USB_CONCAT(X,Y)  USB_CONCAT_HIDDEN(X,Y)
+#define USB_CONCAT_HIDDEN(X,Y) X ## Y
+
+/** @endcond */
+
+
+#if defined(__XC16__) || defined(__XC32__)
+#pragma pack(pop)
+#elif __XC8
+#else
+#error "Compiler not supported"
+#endif
+
+/* Doxygen end-of-group for public_api */
+/** @}*/
+
+#endif /* USB_CH9_H__ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usb/include/usb_hid.h	Sat Feb 18 16:14:32 2017 +0000
@@ -0,0 +1,346 @@
+/*
+ *  M-Stack USB Chapter 9 Structures
+ *  Copyright (C) 2013 Alan Ott <alan@signal11.us>
+ *  Copyright (C) 2013 Signal 11 Software
+ *
+ *  2013-08-13
+ *
+ *  M-Stack is free software: you can redistribute it and/or modify it under
+ *  the terms of the GNU Lesser General Public License as published by the
+ *  Free Software Foundation, version 3; or the Apache License, version 2.0
+ *  as published by the Apache Software Foundation.  If you have purchased a
+ *  commercial license for this software from Signal 11 Software, your
+ *  commerical license superceeds the information in this header.
+ *
+ *  M-Stack is distributed in the hope that it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
+ *  License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public License
+ *  along with this software.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ *  You should have received a copy of the Apache License, verion 2.0 along
+ *  with this software.  If not, see <http://www.apache.org/licenses/>.
+ */
+
+#ifndef USB_HID_H__
+#define USB_HID_H__
+
+/** @file usb_hid.h
+ *  @brief USB HID Class Enumerations and Structures
+ *  @defgroup public_api Public API
+ */
+
+/** @addtogroup public_api
+ *  @{
+ */
+
+#include <stdint.h>
+#include "usb_config.h"
+
+#if defined(__XC16__) || defined(__XC32__)
+#pragma pack(push, 1)
+#elif __XC8
+#else
+#error "Compiler not supported"
+#endif
+
+/** @defgroup hid_items USB HID Class Enumerations and Descriptors
+ *  @brief Packet structs from the Device Class Definition for Human
+ *  Interface Devices (commonly the USB HID Specification), version 1.11,
+ *  chapter 6.
+ *
+ *  For more information about these structures, see the above referenced
+ *  document, available from http://www.usb.org .
+ *  @addtogroup hid_items
+ *  @{
+ */
+
+#define HID_INTERFACE_CLASS 0x03
+
+/** HID Class Descriptor Tyes */
+enum HIDDescriptorTypes {
+	DESC_HID = 0x21,
+	DESC_REPORT = 0x22,
+	DESC_PHYSICAL = 0x23,
+};
+
+/** HID Class Requests */
+enum HIDRequests {
+	HID_GET_REPORT = 0x1,
+	HID_GET_IDLE = 0x2,
+	HID_GET_PROTOCOL = 0x3,
+	HID_SET_REPORT = 0x9,
+	HID_SET_IDLE = 0xa,
+	HID_SET_PROTOCOL = 0xb,
+};
+
+/** HID Report Types */
+enum HIDReportTypes {
+	HID_INPUT = 0x1,
+	HID_OUTPUT = 0x2,
+	HID_FEATURE = 0x3,
+};
+
+/** HID Protocols */
+enum HIDProtocols {
+	HID_PROTO_BOOT = 0,
+	HID_PROTO_REPORT = 1,
+};
+
+struct hid_descriptor {
+	uint8_t bLength; /**< Size of this struct plus any optional descriptors */
+	uint8_t bDescriptorType; /**< Set to DESC_HID */
+	uint16_t bcdHID; /**< HID Version in BCD. (0x0100 is 1.00) */
+	uint8_t bCountryCode;
+	uint8_t bNumDescriptors; /**< Number of class descriptors (always at least 1) */
+	uint8_t bDescriptorType2; /**< Set to DESC_REPORT */
+	uint16_t wDescriptorLength; /**< Set to size of report descriptor */
+};
+
+struct hid_optional_descriptor {
+	uint8_t bDescriptorType;
+	uint16_t wDescriptorLength;
+};
+
+/** HID Descriptor Function
+ *
+ * The USB Stack will call this function to retrieve the HID descriptor for
+ * each HID interface when requested by the host. This function is mandatory
+ * for HID devices.
+ *
+ * @param interface  The interface for which the descriptor is requested
+ * @param ptr        A Pointer to a pointer which should be set to the
+ *                   requested HID descriptor by this function.
+ *
+ * @returns
+ *   Return the length of the HID descriptor in bytes or -1 if the descriptor
+ *   does not exist.
+ */
+extern int16_t USB_HID_DESCRIPTOR_FUNC(uint8_t interface, const void **ptr);
+
+/** HID Report Descriptor Function
+ *
+ * The USB Stack will call this function to retrieve the HID report
+ * descriptor for each HID interface when requested by the host.  This
+ * function is mandatory for HID devices.
+ *
+ * @param interface  The interface for which the descriptor is requested
+ * @param ptr        A Pointer to a pointer which should be set to the
+ *                   requested HID report descriptor by this function.
+ *
+ * @returns
+ *   Return the length of the HID report descriptor in bytes or -1 if the
+ *   descriptor does not exist.
+ */
+extern int16_t USB_HID_REPORT_DESCRIPTOR_FUNC(uint8_t interface, const void **ptr);
+
+#ifdef USB_HID_PHYSICAL_DESCRIPTOR_FUNC
+/** HID Physical Descriptor Function
+ *
+ * The USB Stack will call this function to retrieve the physical
+ * descriptor for each HID interface when requested by the host.  This
+ * function, and physical descriptors, are optional.
+ *
+ * @param interface  The interface for which the descriptor is requested
+ * @param index      The physical descriptor set to return. Index zero
+ *                   requests a special descriptor describing the number of
+ *                   descriptor sets and their sizes. See the HID
+ *                   specification, version 1.11, section 7.1.1.
+ * @param ptr        A Pointer to a pointer which should be set to the
+ *                   requested physical descriptor by this function
+ *
+ * @returns
+ *   Return the length of the physical descriptor in bytes or -1 if the
+ *   descriptor does not exist.
+ */
+extern int16_t USB_HID_PHYSICAL_DESCRIPTOR_FUNC(uint8_t interface, uint8_t index, const void **ptr);
+#endif
+
+#ifdef HID_GET_REPORT_CALLBACK
+/** HID Get_Report request callback
+ *
+ * The USB Stack will call this function when a Get_Report request has been
+ * received from the host.  This function should set the @p report pointer
+ * to a buffer containing the report data and return the length of the
+ * report.  Once the transfer has completed, @p callback will be called with
+ * the @p context pointer provided.  The buffer pointed to by @p report
+ * should be considered to be owned by the USB stack until the @p callback
+ * is called and should not be modified by the application until that time.
+ *
+ *
+ * @param interface      The interface for which the report is requested
+ * @param report_type    The type of report, either @p HID_INPUT,
+ *                       @p HID_OUTPUT, or @p HID_FEATURE.
+ * @param report_id      The report index requested. This will be zero if the
+ *                       device does not use numbered reports.
+ * @param report         A pointer to a pointer which should be set to the
+ *                       report data.
+ * @param callback       A callback function to call when the transfer
+ *                       completes.  This parameter is mandatory.  Once the
+ *                       callback is called, the transfer is over, and the
+ *                       buffer can be considered to be owned by the
+ *                       application again.
+ * @param context        A pointer to be passed to the callback.  The USB stack
+ *                       does not dereference this pointer.
+ *
+ * @returns
+ *   Return 0 if the request can be handled or -1 if it cannot. Returning -1
+ *   will cause STALL to be returned to the host.
+ */
+extern int16_t HID_GET_REPORT_CALLBACK(uint8_t interface, uint8_t report_type,
+                                       uint8_t report_id, const void **report,
+                                       usb_ep0_data_stage_callback *callback,
+                                       void **context);
+#endif
+
+
+#ifdef HID_SET_REPORT_CALLBACK
+/** HID Set_Report request callback
+ *
+ * The USB Stack will call this function when a Set_Report request has been
+ * received from the host. There are two ways to handle this:
+ *
+ * 0. For unknown requests, return -1. This will send a STALL to the host. 
+ * 1. For known requests the callback should call
+ *    @p usb_start_receive_ep0_data_stage() with a buffer to be filled with
+ *    the report data and a callback which will get called when the data
+ *    stage is complete.  The callback is required, and the data buffer
+ *    passed to @p usb_start_receive_ep0_data_stage() must remain valid
+ *    until the callback is called.
+ *
+ * It is worth noting that only one control transfer can be active at any
+ * given time.  Once HID_SET_REPORT_CALLBACK() has been called, it will not
+ * be called again until the next transfer, meaning that if the
+ * application-provided HID_SET_REPORT_CALLBACK() function performs option 1
+ * above, the callback function passed to @p
+ * usb_start_receive_ep0_data_stage() will be called before any other setup
+ * transfer can happen again.  Thus, it is safe to use the same buffer
+ * for all control transfers if desired.
+ *
+ *
+ * @param interface      The interface for which the report is provided
+ * @param report_type    The type of report, either @p HID_INPUT,
+ *                       @p HID_OUTPUT, or @p HID_FEATURE.
+ * @param report_id      The report index requested. This will be zero if the
+ *                       device does not use numbered reports.
+ * @returns
+ *   Return 0 if the request can be handled or -1 if it cannot. Returning -1
+ *   will cause STALL to be returned to the host.
+ */
+extern int8_t HID_SET_REPORT_CALLBACK(uint8_t interface, uint8_t report_type,
+                                      uint8_t report_id);
+#endif
+
+#ifdef HID_GET_IDLE_CALLBACK
+/** HID Get_Idle request callback
+ *
+ * The USB Stack will call this function when a Get_Idle request has been
+ * received from the host. The application should return the current idle
+ * rate.
+ *
+ * @param interface      The interface for which the report is provided
+ * @param report_id      The report index requested.
+ *
+ * @returns
+ *   Return the current idle rate.
+ */
+extern uint8_t HID_GET_IDLE_CALLBACK(uint8_t interface, uint8_t report_id);
+#endif
+
+#ifdef HID_SET_IDLE_CALLBACK
+/** HID Set_Idle request callback
+ *
+ * The USB Stack will call this function when a Set_Idle request has been
+ * received from the host. The application should use the provided value
+ * as the idle rate.
+ *
+ * @param interface      The interface for which the report is provided
+ * @param report_id      The report index requested. Zero means all reports.
+ * @param idle_rate      The idle rate to set, in multiples of 4 milliseconds.
+ *
+ * @returns
+ *   Return 0 on success and -1 on failure.
+ */
+extern int8_t HID_SET_IDLE_CALLBACK(uint8_t interface, uint8_t report_id,
+                                    uint8_t idle_rate);
+#endif
+
+#ifdef HID_GET_PROTOCOL_CALLBACK
+/** HID Get_Protocol request callback
+ *
+ * The USB Stack will call this function when a Get_Protocol request has
+ * been received from the host.  The application should return the current
+ * protocol.
+ *
+ * @param interface      The interface for which the report is provided
+ *
+ * @returns
+ *   Return the current protocol (@p HID_PROTO_BOOT, @p HID_PROTO_REPORT) or
+ *   -1 on failure.
+ */
+extern int8_t HID_GET_PROTOCOL_CALLBACK(uint8_t interface);
+#endif
+
+#ifdef HID_SET_PROTOCOL_CALLBACK
+/** HID Set_Protocol request callback
+ *
+ * The USB Stack will call this function when a Set_Protocol request has
+ * been received from the host, and will provide the protocol to set as
+ * either @p HID_PROTO_BOOT, or @p HID_PROTO_REPORT.
+ *
+ * @param interface      The interface for which the report is provided
+ * @param protocol       The protocol to set. Either @p HID_PROTO_BOOT, or
+ *                       @p HID_PROTO_REPORT.
+ *
+ * @returns
+ *   Return 0 on success or -1 on failure.
+ */
+extern int8_t HID_SET_PROTOCOL_CALLBACK(uint8_t interface, uint8_t protocol);
+#endif
+
+#ifdef MULTI_CLASS_DEVICE
+/** Set the list of HID interfaces on this device
+ *
+ * Provide a list to the HID class implementation of the interfaces on this
+ * device which should be treated as HID devices.  This is only necessary
+ * for multi-class composite devices to make sure that requests are not
+ * confused between interfaces.  It should be called before usb_init().
+ *
+ * @param interfaces      An array of interfaces which are HID class.
+ * @param num_interfaces  The size of the @p interfaces array.
+ */
+void hid_set_interface_list(uint8_t *interfaces, uint8_t num_interfaces);
+#endif
+
+/** Process HID Setup Request
+ *
+ * Process a setup request which has been unhandled as if it is potentially
+ * a HID setup request. This function will then call appropriate callbacks
+ * into the appliction if the setup packet is one recognized by the HID
+ * specification.
+ *
+ * @param setup          A setup packet to handle
+ *
+ * @returns
+ *   Returns 0 if the setup packet could be processed or -1 if it could not.
+ */
+uint8_t process_hid_setup_request(const struct setup_packet *setup);
+
+
+/* Doxygen end-of-group for hid_items */
+/** @}*/
+
+
+#if defined(__XC16__) || defined(__XC32__)
+#pragma pack(pop)
+#elif __XC8
+#else
+#error "Compiler not supported"
+#endif
+
+/* Doxygen end-of-group for public_api */
+/** @}*/
+
+#endif /* USB_HID_H__ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usb/include/usb_microsoft.h	Sat Feb 18 16:14:32 2017 +0000
@@ -0,0 +1,184 @@
+/*
+ *  M-Stack Microsoft-Specific OS Descriptors
+ *  Copyright (C) 2013 Alan Ott <alan@signal11.us>
+ *  Copyright (C) 2013 Signal 11 Software
+ *
+ *  2013-08-27
+ *
+ *  M-Stack is free software: you can redistribute it and/or modify it under
+ *  the terms of the GNU Lesser General Public License as published by the
+ *  Free Software Foundation, version 3; or the Apache License, version 2.0
+ *  as published by the Apache Software Foundation.  If you have purchased a
+ *  commercial license for this software from Signal 11 Software, your
+ *  commerical license superceeds the information in this header.
+ *
+ *  M-Stack is distributed in the hope that it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
+ *  License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public License
+ *  along with this software.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ *  You should have received a copy of the Apache License, verion 2.0 along
+ *  with this software.  If not, see <http://www.apache.org/licenses/>.
+ */
+
+#ifndef USB_MICROSOFT_H__
+#define USB_MICROSOFT_H__
+
+/** @file usb.h
+ *  @brief Microsoft-Specific OS Descriptors
+ *  @defgroup public_api Public API
+ */
+
+/** @addtogroup public_api
+ *  @{
+ */
+
+#include <stdint.h>
+
+#if defined(__XC16__) || defined(__XC32__)
+#pragma pack(push, 1)
+#elif __XC8
+#else
+#error "Compiler not supported"
+#endif
+
+/** @defgroup microsoft_items Microsoft-Specific Descriptors
+ *  @brief Packet structs from Microsoft's documentation which deal with
+ *  the Microsoft OS String Descriptor and the Extended Compat Descriptors.
+ *
+ *  For more information about these structures, see the Microsoft
+ *  documentation at http://msdn.microsoft.com/library/windows/hardware/gg463182
+ *  or search for "Microsoft OS Descriptors" on http://msdn.microsoft.com .
+ *  Also see docs/winusb.txt in the M-Stack distribution.
+ *
+ *  @addtogroup microsoft_items
+ *  @{
+ */
+
+/** OS String Descriptor
+ *
+ * This is the first descriptor Windows will request, as string number 0xee.
+ */
+struct microsoft_os_descriptor {
+	uint8_t bLength;         /**< set to 0x12 */
+	uint8_t bDescriptorType; /**< set to 0x3 */
+	uint16_t qwSignature[7]; /**< set to "MSFT100" (Unicode) (no NULL) */
+	uint8_t bMS_VendorCode;  /**< Set to the bRequest by which the host
+	                              should ask for the Compat ID and
+	                              Property descriptors. */
+	uint8_t bPad;            /**< Set to 0x0 */
+};
+
+/** Extended Compat ID Header
+ *
+ * This is the header for the Extended Compat ID Descriptor
+ */
+struct microsoft_extended_compat_header {
+	uint32_t dwLength;   /**< Total length of descriptor (header + functions) */
+	uint16_t bcdVersion; /**< Descriptor version number, 0x0100. */
+	uint16_t wIndex;     /**< This OS feature descriptor; set to 0x04. */
+	uint8_t  bCount;     /**< Number of custom property sections */
+	uint8_t  reserved[7];
+};
+
+/** Extended Compat ID Function
+ *
+ * This is the function struct for the Extended Compat ID Descriptor
+ */
+struct microsoft_extended_compat_function {
+	uint8_t bFirstInterfaceNumber; /**< The interface or function number */
+	uint8_t reserved;
+	uint8_t compatibleID[8];       /**< Compatible String */
+	uint8_t subCompatibleID[8];    /**< Subcompatible String */
+	uint8_t reserved2[6];
+};
+
+/** Extended Properties Header
+ *
+ * This is the header for the Extended Properties Descriptor
+ */
+struct microsoft_extended_properties_header {
+	uint32_t dwLength;   /**< Total length of descriptor (header + functions) */
+	uint16_t bcdVersion; /**< Descriptor version number, 0x0100. */
+	uint16_t wIndex;     /**< This OS feature descriptor; set to 0x04. */
+	uint16_t bCount;     /**< Number of custom property sections */
+};
+
+/** Extended Property Section header
+ *
+ * This is the first part of the Extended Property Section, which is a
+ * variable-length descriptor. The Variable-length types must be packed
+ * manually after this section header.
+ *
+ */
+struct microsoft_extended_property_section_header {
+	uint32_t dwSize; /**< Size of this section (this struct + data) */
+	uint32_t dwPropertyDataType; /**< Property Data Format */
+
+/* Variable-length fields and lengths:
+	uint16_t wPropertyNameLength;
+	uint16_t bPropertyName[];
+	uint32_t dwPropertyDataLength;
+	uint8_t  bPropertyData[];
+ */
+};
+
+#ifdef MICROSOFT_COMPAT_ID_DESCRIPTOR_FUNC
+/** @brief Callback for the GET_MS_DESCRIPTOR/CompatID request
+ *
+ * MICROSOFT_COMPAT_ID_DESCRIPTOR_FUNC() is called when a @p
+ * GET_MS_DESCRIPTOR request is received from the host with a wIndex of 0x0004.
+ * The value of MS_GET_DESCRIPTOR request is defined by
+ * MICROSOFT_OS_DESC_VENDOR_CODE which is set in usb_config.h, and reported to
+ * the host as part of the @p microsoft_os_descriptor. See the MSDN
+ * documentation on "Microsoft OS Descriptors" for more information.
+ *
+ * @param interface      The interface for which the descriptor is queried
+ * @param descriptor     a pointer to a pointer which should be set to the
+ *                       descriptor data.
+ * @returns
+ *   Return the length of the descriptor pointed to by @p *descriptor, or -1
+ *   if the descriptor does not exist.
+ */
+uint16_t MICROSOFT_COMPAT_ID_DESCRIPTOR_FUNC(uint8_t interface,
+                                              const void **descriptor);
+#endif
+
+#ifdef MICROSOFT_CUSTOM_PROPERTY_DESCRIPTOR_FUNC
+/** @brief Callback for the GET_MS_DESCRIPTOR/Custom_Property request
+ *
+ * MICROSOFT_CUSTOM_PROPERTY_DESCRIPTOR_FUNC() is called when a @p
+ * GET_MS_DESCRIPTOR request with a wIndex of 0x0005 is received from the host.
+ * The value of the MS_GET_DESCRIPTOR request is defined by
+ * MICROSOFT_OS_DESC_VENDOR_CODE which is set in usb_config.h, and reported to
+ * the host as part of the @p microsoft_os_descriptor. See the MSDN
+ * documentation on "Microsoft OS Descriptors" for more information.
+ *
+ * @param interface      The interface for which the descriptor is queried
+ * @param descriptor     a pointer to a pointer which should be set to the
+ *                       descriptor data.
+ * @returns
+ *   Return the length of the descriptor pointed to by @p *descriptor, or -1
+ *   if the descriptor does not exist.
+ */
+uint16_t MICROSOFT_CUSTOM_PROPERTY_DESCRIPTOR_FUNC(uint8_t interface,
+                                                   const void **descriptor);
+#endif
+
+/* Doxygen end-of-group for microsoft_items */
+/** @}*/
+
+#if defined(__XC16__) || defined(__XC32__)
+#pragma pack(pop)
+#elif __XC8
+#else
+#error "Compiler not supported"
+#endif
+
+/* Doxygen end-of-group for public_api */
+/** @}*/
+
+#endif /* USB_MICROSOFT_H__ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usb/src/usb.c	Sat Feb 18 16:14:32 2017 +0000
@@ -0,0 +1,1713 @@
+/*
+ *  M-Stack USB Device Stack Implementation
+ *  Copyright (C) 2013 Alan Ott <alan@signal11.us>
+ *  Copyright (C) 2013 Signal 11 Software
+ *
+ *  Initial version for PIC18, 2008-02-24
+ *  PIC24 port, 2013-04-08
+ *
+ *  M-Stack is free software: you can redistribute it and/or modify it under
+ *  the terms of the GNU Lesser General Public License as published by the
+ *  Free Software Foundation, version 3; or the Apache License, version 2.0
+ *  as published by the Apache Software Foundation.  If you have purchased a
+ *  commercial license for this software from Signal 11 Software, your
+ *  commerical license superceeds the information in this header.
+ *
+ *  M-Stack is distributed in the hope that it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
+ *  License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public License
+ *  along with this software.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ *  You should have received a copy of the Apache License, verion 2.0 along
+ *  with this software.  If not, see <http://www.apache.org/licenses/>.
+ */
+
+#ifdef __XC32__
+#include <xc.h>
+#include <sys/kmem.h>
+#elif __XC16__
+#include <libpic30.h>
+#include <xc.h>
+#elif __C18
+#include <p18f4550.h>
+#include <delays.h>
+#elif __XC8
+#include <xc.h>
+#else
+#error "Compiler not supported"
+#endif
+
+#include <string.h>
+
+#include "usb_config.h"
+#include "usb.h"
+#include "usb_hal.h"
+#include "usb_ch9.h"
+#include "usb_microsoft.h"
+#include "usb_winusb.h"
+
+#if _PIC14E && __XC8
+	/* This is necessary to avoid a warning about ep0_data_stage_callback
+	 * never being assigned to anything other than NULL. Since this is a
+	 * library, it's possible (and likely) that the application will not
+	 * make use of data stage callbacks, or control transfers at all. This
+	 * is only an issue on PIC16F parts (so far) on XC8.
+	 */
+	#pragma warning disable 1088
+#endif
+
+#ifdef __XC8
+	/* XC8 gives bogus warnings (at least on PIC18) about
+	 * ep0_data_stage_callback() being called when NULL. The code does
+	 * check for NULL, and is safe. */
+	#pragma warning disable 1471
+#endif
+
+#define MIN(x,y) (((x)<(y))?(x):(y))
+
+/* Even though they're the same, It's convenient below (for the buffer
+ * macros) to have separate #defines for IN and OUT EP 0 lengths which
+ * match the format of the other endpoint length #defines. */
+#define EP_0_OUT_LEN EP_0_LEN
+#define EP_0_IN_LEN  EP_0_LEN
+
+#ifndef PPB_MODE
+	#error "PPB_MODE not defined. Define it to one of the four PPB_* macros in usb_hal.h"
+#endif
+
+#ifdef USB_FULL_PING_PONG_ONLY
+	#if PPB_MODE != PPB_ALL
+		#error "This hardware only supports PPB_ALL"
+	#endif
+#endif
+
+
+#if PPB_MODE == PPB_EPO_OUT_ONLY
+	#define PPB_EP0_OUT
+	#undef  PPB_EP0_IN
+	#undef  PPB_EPn
+#elif PPB_MODE == PPB_EPN_ONLY
+	#undef  PPB_EP0_OUT
+	#undef  PPB_EP0_IN
+	#define PPB_EPn
+#elif PPB_MODE == PPB_NONE
+	#undef PPB_EP0_OUT
+	#undef PPB_EP0_IN
+	#undef PPB_EPn
+#elif PPB_MODE == PPB_ALL
+	#define PPB_EP0_OUT
+	#define PPB_EP0_IN
+	#define PPB_EPn
+#else
+	#error "Must select a valid PPB_MODE"
+#endif
+
+STATIC_SIZE_CHECK_EQUAL(sizeof(struct endpoint_descriptor), 7);
+STATIC_SIZE_CHECK_EQUAL(sizeof(struct interface_descriptor), 9);
+STATIC_SIZE_CHECK_EQUAL(sizeof(struct configuration_descriptor), 9);
+STATIC_SIZE_CHECK_EQUAL(sizeof(struct device_descriptor), 18);
+STATIC_SIZE_CHECK_EQUAL(sizeof(struct interface_association_descriptor), 8);
+STATIC_SIZE_CHECK_EQUAL(sizeof(struct setup_packet), 8);
+STATIC_SIZE_CHECK_EQUAL(sizeof(struct microsoft_os_descriptor), 18);
+STATIC_SIZE_CHECK_EQUAL(sizeof(struct microsoft_extended_compat_header), 16);
+STATIC_SIZE_CHECK_EQUAL(sizeof(struct microsoft_extended_compat_function), 24);
+STATIC_SIZE_CHECK_EQUAL(sizeof(struct microsoft_extended_properties_header), 10);
+STATIC_SIZE_CHECK_EQUAL(sizeof(struct microsoft_extended_property_section_header), 8);
+#ifdef __XC32__
+STATIC_SIZE_CHECK_EQUAL(sizeof(struct buffer_descriptor), 8);
+#else
+STATIC_SIZE_CHECK_EQUAL(sizeof(struct buffer_descriptor), 4);
+#endif
+
+#ifdef __C18
+/* The buffer descriptors. Per the PIC18F4550 Data sheet, when _not_ using
+   ping-pong buffering, these must be laid out sequentially starting at
+   address 0x0400 in the following order, ep0_out, ep0_in,ep1_out, ep1_in,
+   etc. These must be initialized prior to use. */
+#pragma udata buffer_descriptors=BD_ADDR
+#endif
+
+
+/* Calculate the number of Buffer Descriptor pairs, which depends on the
+   ping-pong modes active and the number of endpoints used. */
+#if defined(PPB_EP0_IN) && defined(PPB_EP0_OUT)
+	#define NUM_BD_0 4
+#elif !defined(PPB_EP0_IN) && defined(PPB_EP0_OUT)
+	#define NUM_BD_0 3
+#elif !defined(PPB_EP0_IN) && !defined(PPB_EP0_OUT)
+	#define NUM_BD_0 2
+#else
+	#error "Nonsense condition detected"
+#endif
+
+#ifdef PPB_EPn
+	#define NUM_BD (4 * (NUM_ENDPOINT_NUMBERS) + NUM_BD_0)
+#else
+	#define NUM_BD (2 * (NUM_ENDPOINT_NUMBERS) + NUM_BD_0)
+#endif
+
+/* Macros to access a specific buffer descriptor, which depends on the
+   ping-pong modes active. Since EP 0 can have a different ping-pong mode
+   than the other endpoints, EP0's buffer descriptor should be accessed through
+   BDS0OUT() and BDS0IN() only. It is not valid to call BDSnOUT(0,oe), for
+   example*/
+#if PPB_MODE == PPB_EPO_OUT_ONLY
+	#define BDS0OUT(oe) bds[0 + oe]
+	#define BDS0IN(oe) bds[2]
+	#define BDSnOUT(EP,oe) bds[(EP) * 2 + 1]
+	#define BDSnIN(EP,oe) bds[(EP) * 2 + 2]
+#elif PPB_MODE == PPB_EPN_ONLY
+	#define BDS0OUT(oe) bds[0]
+	#define BDS0IN(oe) bds[1]
+	#define BDSnOUT(EP,oe) bds[(EP) * 4 - 2 + (oe)]
+	#define BDSnIN(EP,oe) bds[(EP) * 4 + (oe)]
+#elif PPB_MODE == PPB_NONE
+	#define BDS0OUT(oe) bds[0]
+	#define BDS0IN(oe) bds[1]
+	#define BDSnOUT(EP,oe) bds[(EP) * 2]
+	#define BDSnIN(EP,oe) bds[(EP) * 2 + 1]
+#elif PPB_MODE == PPB_ALL
+	#define BDS0OUT(oe) bds[0 + oe]
+	#define BDS0IN(oe) bds[2 + oe]
+	#define BDSnOUT(EP,oe) bds[(EP) * 4 + (oe)]
+	#define BDSnIN(EP,oe) bds[(EP) * 4 + 2 + (oe)]
+#else
+#error "Must select a valid PPB_MODE"
+#endif
+
+#if defined(AUTOMATIC_WINUSB_SUPPORT) && !defined(MICROSOFT_OS_DESC_VENDOR_CODE)
+#error "Must define a MICROSOFT_OS_DESC_VENDOR_CODE for Automatic WinUSB"
+#endif
+
+#ifdef AUTOMATIC_WINUSB_SUPPORT
+	/* Make sure the Microsoft descriptor functions aren't defined */
+	#ifdef MICROSOFT_COMPAT_ID_DESCRIPTOR_FUNC
+		#error "Must not define MICROSOFT_COMPAT_ID_DESCRIPTOR_FUNC when using Automatic WinUSB"
+	#endif
+	#ifdef MICROSOFT_CUSTOM_PROPERTY_DESCRIPTOR_FUNC
+		#error "Must not define MICROSOFT_CUSTOM_PROPERTY_DESCRIPTOR_FUNC when using Automatic WinUSB"
+	#endif
+
+	/* Define the Microsoft descriptor functions to the handlers
+	 * implemented in usb_winusb.c */
+	#define MICROSOFT_COMPAT_ID_DESCRIPTOR_FUNC m_stack_winusb_get_microsoft_compat
+	#define MICROSOFT_CUSTOM_PROPERTY_DESCRIPTOR_FUNC m_stack_winusb_get_microsoft_property
+#endif
+
+static struct buffer_descriptor bds[NUM_BD] BD_ATTR_TAG;
+
+#ifdef __C18
+/* The actual buffers to and from which the data is transferred from the SIE
+   (from the USB bus). These buffers must fully be located between addresses
+   0x400 and 0x7FF per the datasheet.*/
+/* This addr is for the PIC18F4550 */
+#pragma udata usb_buffers=0x500
+#elif defined(__XC16__) || defined(__XC32__)
+	/* Buffers can go anywhere on PIC24/PIC32 parts which are supported
+	   (so far). */
+#elif __XC8
+	/* Addresses are set by BD_ADDR and BUF_ADDR below. */
+#else
+	#error compiler not supported
+#endif
+
+static struct {
+/* Set up the EP_BUF() macro for EP0 */
+#if defined(PPB_EP0_IN) && defined(PPB_EP0_OUT)
+	#define EP_BUF(n) \
+		unsigned char ep_##n##_out_buf[2][EP_##n##_OUT_LEN]; \
+		unsigned char ep_##n##_in_buf[2][EP_##n##_IN_LEN];
+#elif !defined(PPB_EP0_IN) && defined(PPB_EP0_OUT)
+	#define EP_BUF(n) \
+		unsigned char ep_##n##_out_buf[2][EP_##n##_OUT_LEN]; \
+		unsigned char ep_##n##_in_buf[1][EP_##n##_IN_LEN];
+#elif !defined(PPB_EP0_IN) && !defined(PPB_EP0_OUT)
+	#define EP_BUF(n) \
+		unsigned char ep_##n##_out_buf[1][EP_##n##_OUT_LEN]; \
+		unsigned char ep_##n##_in_buf[1][EP_##n##_IN_LEN];
+#else
+	#error "Nonsense condition detected"
+#endif
+
+#if NUM_ENDPOINT_NUMBERS >= 0
+	EP_BUF(0)
+#endif
+
+/* Re-setup the EP_BUF() macro for the rest of the endpoints */
+#undef EP_BUF
+#ifdef PPB_EPn
+	#define EP_BUF(n) \
+		unsigned char ep_##n##_out_buf[2][EP_##n##_OUT_LEN]; \
+		unsigned char ep_##n##_in_buf[2][EP_##n##_IN_LEN];
+#else
+	#define EP_BUF(n) \
+		unsigned char ep_##n##_out_buf[1][EP_##n##_OUT_LEN]; \
+		unsigned char ep_##n##_in_buf[1][EP_##n##_IN_LEN];
+#endif
+
+#if NUM_ENDPOINT_NUMBERS >= 1
+	EP_BUF(1)
+#endif
+#if NUM_ENDPOINT_NUMBERS >= 2
+	EP_BUF(2)
+#endif
+#if NUM_ENDPOINT_NUMBERS >= 3
+	EP_BUF(3)
+#endif
+#if NUM_ENDPOINT_NUMBERS >= 4
+	EP_BUF(4)
+#endif
+#if NUM_ENDPOINT_NUMBERS >= 5
+	EP_BUF(5)
+#endif
+#if NUM_ENDPOINT_NUMBERS >= 6
+	EP_BUF(6)
+#endif
+#if NUM_ENDPOINT_NUMBERS >= 7
+	EP_BUF(7)
+#endif
+#if NUM_ENDPOINT_NUMBERS >= 8
+	EP_BUF(8)
+#endif
+#if NUM_ENDPOINT_NUMBERS >= 9
+	EP_BUF(9)
+#endif
+#if NUM_ENDPOINT_NUMBERS >= 10
+	EP_BUF(10)
+#endif
+#if NUM_ENDPOINT_NUMBERS >= 11
+	EP_BUF(11)
+#endif
+#if NUM_ENDPOINT_NUMBERS >= 12
+	EP_BUF(12)
+#endif
+#if NUM_ENDPOINT_NUMBERS >= 13
+	EP_BUF(13)
+#endif
+#if NUM_ENDPOINT_NUMBERS >= 14
+	EP_BUF(14)
+#endif
+#if NUM_ENDPOINT_NUMBERS >= 15
+	EP_BUF(15)
+#endif
+
+#undef EP_BUF
+} ep_buffers XC8_BUFFER_ADDR_TAG;
+
+struct ep_buf {
+	unsigned char * const out; /* buffers for the even buffer descriptor */
+	unsigned char * const in;  /* ie: ppbi = 0 */
+#ifdef PPB_EPn
+	unsigned char * const out1; /* buffers for the odd buffer descriptor */
+	unsigned char * const in1;  /* ie: ppbi = 1 */
+#endif
+	const uint8_t out_len;
+	const uint8_t in_len;
+
+#define EP_OUT_HALT_FLAG 0x1
+#define EP_IN_HALT_FLAG 0x2
+#define EP_RX_DTS 0x4  /* The DTS of the _next_ packet */
+#define EP_TX_DTS 0x8
+#define EP_RX_PPBI 0x10 /* Represents the next buffer which will be need to be
+                           reset and given back to the SIE. */
+#define EP_TX_PPBI 0x20 /* Represents the _next_ buffer to write into. */
+	uint8_t flags;
+};
+
+struct ep0_buf {
+	unsigned char * const out; /* buffers for the even buffer descriptor */
+	unsigned char * const in;  /* ie: ppbi = 0 */
+#ifdef PPB_EP0_OUT
+	unsigned char * const out1; /* buffer for the odd buffer descriptor */
+#endif
+#ifdef PPB_EP0_IN
+	unsigned char * const in1;  /* buffer for the odd buffer descriptor */
+#endif
+
+	/* Use the EP_* flags from ep_buf for flags */
+	uint8_t flags;
+};
+
+#ifdef __C18
+#pragma idata
+#endif
+
+#if defined(PPB_EP0_IN) && defined(PPB_EP0_OUT)
+	#define EP_BUFS0() { ep_buffers.ep_0_out_buf[0], \
+	                     ep_buffers.ep_0_in_buf[0], \
+	                     ep_buffers.ep_0_out_buf[1], \
+	                     ep_buffers.ep_0_in_buf[1] }
+
+#elif !defined(PPB_EP0_IN) && defined(PPB_EP0_OUT)
+	#define EP_BUFS0() { ep_buffers.ep_0_out_buf[0], \
+	                     ep_buffers.ep_0_in_buf[0], \
+	                     ep_buffers.ep_0_out_buf[1] }
+
+#elif !defined(PPB_EP0_IN) && !defined(PPB_EP0_OUT)
+	#define EP_BUFS0() { ep_buffers.ep_0_out_buf[0], \
+	                     ep_buffers.ep_0_in_buf[0] }
+
+#else
+	#error "Nonsense condition detected"
+#endif
+
+
+#ifdef PPB_EPn
+	#define EP_BUFS(n) { ep_buffers.ep_##n##_out_buf[0], \
+	                     ep_buffers.ep_##n##_in_buf[0], \
+	                     ep_buffers.ep_##n##_out_buf[1], \
+	                     ep_buffers.ep_##n##_in_buf[1], \
+	                     EP_##n##_OUT_LEN, \
+	                     EP_##n##_IN_LEN },
+#else
+	#define EP_BUFS(n) { ep_buffers.ep_##n##_out_buf[0], \
+	                     ep_buffers.ep_##n##_in_buf[0], \
+	                     EP_##n##_OUT_LEN, \
+	                     EP_##n##_IN_LEN },
+#endif
+
+static struct ep0_buf ep0_buf = EP_BUFS0();
+
+static struct ep_buf ep_buf[NUM_ENDPOINT_NUMBERS+1] = {
+#if NUM_ENDPOINT_NUMBERS >= 0
+	{ NULL, NULL },
+	/* TODO wasted space here */
+#endif
+#if NUM_ENDPOINT_NUMBERS >= 1
+	EP_BUFS(1)
+#endif
+#if NUM_ENDPOINT_NUMBERS >= 2
+	EP_BUFS(2)
+#endif
+#if NUM_ENDPOINT_NUMBERS >= 3
+	EP_BUFS(3)
+#endif
+#if NUM_ENDPOINT_NUMBERS >= 4
+	EP_BUFS(4)
+#endif
+#if NUM_ENDPOINT_NUMBERS >= 5
+	EP_BUFS(5)
+#endif
+#if NUM_ENDPOINT_NUMBERS >= 6
+	EP_BUFS(6)
+#endif
+#if NUM_ENDPOINT_NUMBERS >= 7
+	EP_BUFS(7)
+#endif
+#if NUM_ENDPOINT_NUMBERS >= 8
+	EP_BUFS(8)
+#endif
+#if NUM_ENDPOINT_NUMBERS >= 9
+	EP_BUFS(9)
+#endif
+#if NUM_ENDPOINT_NUMBERS >= 10
+	EP_BUFS(10)
+#endif
+#if NUM_ENDPOINT_NUMBERS >= 11
+	EP_BUFS(11)
+#endif
+#if NUM_ENDPOINT_NUMBERS >= 12
+	EP_BUFS(12)
+#endif
+#if NUM_ENDPOINT_NUMBERS >= 13
+	EP_BUFS(13)
+#endif
+#if NUM_ENDPOINT_NUMBERS >= 14
+	EP_BUFS(14)
+#endif
+#if NUM_ENDPOINT_NUMBERS >= 15
+	EP_BUFS(15)
+#endif
+
+};
+#undef EP_BUFS
+#undef EP_BUFS0
+
+/* Global data */
+static bool addr_pending;
+static uint8_t addr;
+static uint8_t g_configuration;
+static bool control_need_zlp;
+static bool returning_short;
+
+/* Data associated with multi-packet control transfers */
+static usb_ep0_data_stage_callback ep0_data_stage_callback;
+static char   *ep0_data_stage_in_buffer; /* XC8 v1.12 fails if this is const on PIC16 */
+static char   *ep0_data_stage_out_buffer;
+static size_t  ep0_data_stage_buf_remaining;
+static void   *ep0_data_stage_context;
+static uint8_t ep0_data_stage_direc; /*1=IN, 0=OUT, Same as USB spec.*/
+
+#ifdef _PIC14E
+/* Convert a pointer, which can be a normal banked pointer or a linear
+ * pointer, to a linear pointer.
+ *
+ * The USB buffer descriptors need linear addresses. The XC8 compiler will
+ * generate banked (not linear) addresses for the arrays in ep_buffers if
+ * ep_buffers can fit within a single bank. This is good for code size, but
+ * the buffer descriptors cannot take banked addresses, so they must be
+ * generated from the banked addresses.
+ *
+ * See section 3.6.2 of the PIC16F1459 datasheet for details.
+ */
+static uint16_t pic16_linear_addr(void *ptr)
+{
+	uint8_t high, low;
+	uint16_t addr = (uint16_t) ptr;
+
+	/* Addresses over 0x2000 are already linear addresses. */
+	if (addr >= 0x2000)
+		return addr;
+
+	high = (addr & 0xff00) >> 8;
+	low  = addr & 0x00ff;
+
+	return 0x2000 +
+	       (low & 0x7f) - 0x20 +
+	       ((high << 1) + (low & 0x80)? 1: 0) * 0x50;
+}
+#endif
+
+static void reset_ep0_data_stage()
+{
+	ep0_data_stage_in_buffer = NULL;
+	ep0_data_stage_out_buffer = NULL;
+	ep0_data_stage_buf_remaining = 0;
+	ep0_data_stage_callback = NULL;
+
+	/* There's no need to reset the following because no decisions are
+	   made based on them:
+	     ep0_data_stage_context,
+	     ep0_data_stage_direc
+	 */
+}
+
+#define SERIAL(x)
+#define SERIAL_VAL(x)
+
+/* Initialize or reset all of the endpoints. This is done:
+ *   1. at startup,
+ *   2. following a USB reset, and
+ *   3. whenever a SET_CONFIGURATION transfer is received. */
+static void init_endpoints(void)
+{
+	uint8_t i;
+
+	/* Hold ping-pong in reset for the whole time the endpoints
+	   are being configured */
+	SFR_USB_PING_PONG_RESET = 1;
+	/* Reset the flags */
+	ep0_buf.flags = 0;
+	for (i = 0; i <= NUM_ENDPOINT_NUMBERS; i++) {
+#ifdef PPB_EPn
+		ep_buf[i].flags = 0;
+#else
+		ep_buf[i].flags = EP_RX_DTS;
+#endif
+	}
+
+	/* Clear all the buffer-descriptors and re-initialize */
+	memset(bds, 0x0, sizeof(bds));
+
+	/* Setup endpoint 0 Output buffer descriptor.
+	   Input and output are from the HOST perspective. */
+	BDS0OUT(0).BDnADR = (BDNADR_TYPE) PHYS_ADDR(ep0_buf.out);
+	SET_BDN(BDS0OUT(0), BDNSTAT_UOWN, EP_0_LEN);
+
+#ifdef PPB_EP0_OUT
+	BDS0OUT(1).BDnADR = (BDNADR_TYPE) PHYS_ADDR(ep0_buf.out1);
+	SET_BDN(BDS0OUT(1), BDNSTAT_UOWN, EP_0_LEN);
+#endif
+
+	/* Setup endpoint 0 Input buffer descriptor.
+	   Input and output are from the HOST perspective. */
+	BDS0IN(0).BDnADR = (BDNADR_TYPE) PHYS_ADDR(ep0_buf.in);
+	SET_BDN(BDS0IN(0), 0, EP_0_LEN);
+#ifdef PPB_EP0_IN
+	BDS0IN(1).BDnADR = (BDNADR_TYPE) PHYS_ADDR(ep0_buf.in1);
+	SET_BDN(BDS0IN(1), 0, EP_0_LEN);
+#endif
+
+	for (i = 1; i <= NUM_ENDPOINT_NUMBERS; i++) {
+		/* Setup endpoint 1 Output buffer descriptor.
+		   Input and output are from the HOST perspective. */
+		BDSnOUT(i,0).BDnADR = (BDNADR_TYPE) PHYS_ADDR(ep_buf[i].out);
+		SET_BDN(BDSnOUT(i,0), BDNSTAT_UOWN|BDNSTAT_DTSEN, ep_buf[i].out_len);
+#ifdef PPB_EPn
+		/* Initialize EVEN buffers when in ping-pong mode. */
+		BDSnOUT(i,1).BDnADR = (BDNADR_TYPE) PHYS_ADDR(ep_buf[i].out1);
+		SET_BDN(BDSnOUT(i,1), BDNSTAT_UOWN|BDNSTAT_DTSEN|BDNSTAT_DTS, ep_buf[i].out_len);
+#endif
+		/* Setup endpoint 1 Input buffer descriptor.
+		   Input and output are from the HOST perspective. */
+		BDSnIN(i,0).BDnADR = (BDNADR_TYPE) PHYS_ADDR(ep_buf[i].in);
+		SET_BDN(BDSnIN(i,0), 0, ep_buf[i].in_len);
+#ifdef PPB_EPn
+		/* Initialize EVEN buffers when in ping-pong mode. */
+		BDSnIN(i,1).BDnADR = (BDNADR_TYPE) PHYS_ADDR(ep_buf[i].in1);
+		SET_BDN(BDSnIN(i,1), 0, ep_buf[i].in_len);
+#endif
+	}
+
+	SFR_USB_PING_PONG_RESET = 0;
+}
+
+/* usb_init() is called at powerup time, and when the device gets
+   the reset signal from the USB bus (D+ and D- both held low) indicated
+   by interrput bit URSTIF. */
+void usb_init(void)
+{
+	uint8_t i;
+
+	/* Initialize the USB. 18.4 of PIC24FJ64GB004 datasheet */
+#ifndef USB_FULL_PING_PONG_ONLY
+	SET_PING_PONG_MODE(PPB_MODE);
+#endif
+#if PPB_MODE != PPB_NONE
+	SFR_USB_PING_PONG_RESET = 1;
+	SFR_USB_PING_PONG_RESET = 0;
+#endif
+	SFR_USB_INTERRUPT_EN = 0x0;
+	SFR_USB_EXTENDED_INTERRUPT_EN = 0x0;
+	
+	SFR_USB_EN = 1; /* enable USB module */
+
+#ifdef USE_OTG
+	SFR_OTGEN = 1;
+#endif
+
+	
+#ifdef NEEDS_PULL
+	SFR_PULL_EN = 1;  /* pull-up enable */
+#endif
+
+#ifdef HAS_ON_CHIP_XCVR_DIS
+	SFR_ON_CHIP_XCVR_DIS = 0; /* on-chip transceiver Disable */
+#endif
+
+#ifdef HAS_LOW_SPEED
+	SFR_FULL_SPEED_EN = 1;   /* Full-speed enable */
+#endif
+
+	CLEAR_USB_TOKEN_IF();   /* Clear 4 times to clear out USTAT FIFO */
+	CLEAR_USB_TOKEN_IF();
+	CLEAR_USB_TOKEN_IF();
+	CLEAR_USB_TOKEN_IF();
+
+	CLEAR_ALL_USB_IF();
+
+#ifdef USB_USE_INTERRUPTS
+	SFR_TRANSFER_IE = 1; /* USB Transfer Interrupt Enable */
+	SFR_STALL_IE = 1;    /* USB Stall Interrupt Enable */
+	SFR_RESET_IE = 1;    /* USB Reset Interrupt Enable */
+#ifdef START_OF_FRAME_CALLBACK
+	SFR_SOF_IE = 1;      /* USB Start-Of-Frame Interrupt Enable */
+#endif
+#endif
+
+#ifdef USB_NEEDS_SET_BD_ADDR_REG
+#ifdef __XC16__
+	union WORD {
+		struct {
+			uint8_t lb;
+			uint8_t hb;
+		};
+		uint16_t w;
+		void *ptr;
+	};
+	union WORD w;
+	w.ptr = bds;
+
+	SFR_BD_ADDR_REG = w.hb;
+
+#elif __XC32__
+	union WORD {
+		struct {
+			uint8_t lb;
+			uint8_t hb;
+			uint8_t ub;
+			uint8_t eb;
+		};
+		uint32_t w;
+		void *ptr;
+	};
+	union WORD w;
+	w.w = KVA_TO_PA(bds);
+
+	SFR_BD_ADDR_REG1 = w.hb & 0xFE;
+	SFR_BD_ADDR_REG2 = w.ub;
+	SFR_BD_ADDR_REG3 = w.eb;
+#endif
+#endif
+
+	/* These are the UEP/U1EP endpoint management registers. */
+	
+	/* Clear them all out. This is important because a bootloader
+	   could have set them to non-zero */
+	memset(SFR_EP_MGMT(0), 0x0, sizeof(*SFR_EP_MGMT(0)) * 16);
+	
+	/* Set up Endpoint zero */
+	SFR_EP_MGMT(0)->SFR_EP_MGMT_HANDSHAKE = 1; /* Endpoint handshaking enable */
+	SFR_EP_MGMT(0)->SFR_EP_MGMT_CON_DIS = 0; /* 1=Disable control operations */
+	SFR_EP_MGMT(0)->SFR_EP_MGMT_OUT_EN = 1; /* Endpoint Out Transaction Enable */
+	SFR_EP_MGMT(0)->SFR_EP_MGMT_IN_EN = 1; /* Endpoint In Transaction Enable */
+	SFR_EP_MGMT(0)->SFR_EP_MGMT_STALL = 0; /* Stall */
+
+	for (i = 1; i <= NUM_ENDPOINT_NUMBERS; i++) {
+		volatile SFR_EP_MGMT_TYPE *ep = SFR_EP_MGMT(i);
+		ep->SFR_EP_MGMT_HANDSHAKE = 1; /* Endpoint handshaking enable */
+		ep->SFR_EP_MGMT_CON_DIS = 1; /* 1=Disable control operations */
+		ep->SFR_EP_MGMT_OUT_EN = 1; /* Endpoint Out Transaction Enable */
+		ep->SFR_EP_MGMT_IN_EN = 1; /* Endpoint In Transaction Enable */
+		ep->SFR_EP_MGMT_STALL = 0; /* Stall */
+	}
+
+	/* Reset the Address. */
+	SFR_USB_ADDR = 0x0;
+	addr_pending = 0;
+	g_configuration = 0;
+
+	init_endpoints();
+
+	#ifdef USB_NEEDS_POWER_ON
+	SFR_USB_POWER = 1;
+	#endif
+
+#ifdef USE_OTG
+	SFR_DPPULUP = 1;
+#endif
+
+	reset_ep0_data_stage();
+
+#ifdef USB_USE_INTERRUPTS
+	SFR_USB_IE = 1;     /* USB Interrupt enable */
+#endif
+	
+	//UIRbits.URSTIF = 0; /* Clear USB Reset on Start */
+}
+
+static void reset_bd0_out(void)
+{
+	/* Clean up the Buffer Descriptors.
+	 * Set the length and hand it back to the SIE.
+	 * The Address stays the same. */
+#ifdef PPB_EP0_OUT
+	SET_BDN(BDS0OUT(SFR_USB_STATUS_PPBI), BDNSTAT_UOWN, EP_0_LEN);
+#else
+	SET_BDN(BDS0OUT(0), BDNSTAT_UOWN, EP_0_LEN);
+#endif
+}
+
+static void stall_ep0(void)
+{
+	/* Stall Endpoint 0. It's important that DTSEN and DTS are zero. */
+#ifdef PPB_EP0_IN
+	uint8_t ppbi = (ep0_buf.flags & EP_TX_PPBI)? 1: 0;
+	SET_BDN(BDS0IN(ppbi), BDNSTAT_UOWN|BDNSTAT_BSTALL, EP_0_LEN);
+	/* The PPBI does not advance for STALL. */
+#else
+	SET_BDN(BDS0IN(0), BDNSTAT_UOWN|BDNSTAT_BSTALL, EP_0_LEN);
+#endif
+}
+
+#ifdef NEEDS_CLEAR_STALL
+static void clear_ep0_stall(void)
+{
+	/* Clear Endpoint 0 Stall and UOWN. This is supposed to be done by
+	 * the hardware, but it isn't on PIC16 and PIC18. */
+#ifdef PPB_EP0_IN
+	uint8_t ppbi = (ep0_buf.flags & EP_TX_PPBI)? 1: 0;
+	SET_BDN(BDS0IN(ppbi), 0, EP_0_LEN);
+	/* The PPBI does not advance for STALL. */
+#else
+	SET_BDN(BDS0IN(0), 0, EP_0_LEN);
+#endif
+}
+#endif
+
+static void stall_ep_in(uint8_t ep)
+{
+	/* Stall Endpoint. It's important that DTSEN and DTS are zero.
+	 * Although the datasheet doesn't stay it, the only safe way to do this
+	 * is to set BSTALL on BOTH buffers when in ping-pong mode. */
+	SET_BDN(BDSnIN(ep, 0), BDNSTAT_UOWN|BDNSTAT_BSTALL, ep_buf[ep].in_len);
+#ifdef PPB_EPn
+	SET_BDN(BDSnIN(ep, 1), BDNSTAT_UOWN|BDNSTAT_BSTALL, ep_buf[ep].in_len);
+#endif
+}
+
+static void stall_ep_out(uint8_t ep)
+{
+	/* Stall Endpoint. It's important that DTSEN and DTS are zero.
+	 * Although the datasheet doesn't stay it, the only safe way to do this
+	 * is to set BSTALL on BOTH buffers when in ping-pong mode. */
+	SET_BDN(BDSnOUT(ep, 0), BDNSTAT_UOWN|BDNSTAT_BSTALL , 0);
+#ifdef PPB_EPn
+	SET_BDN(BDSnOUT(ep, 1), BDNSTAT_UOWN|BDNSTAT_BSTALL , 0);
+#endif
+}
+
+static void send_zero_length_packet_ep0()
+{
+#ifdef PPB_EP0_IN
+	uint8_t ppbi = (ep0_buf.flags & EP_TX_PPBI)? 1: 0;
+	BDS0IN(ppbi).STAT.BDnSTAT = 0;
+	SET_BDN(BDS0IN(ppbi), BDNSTAT_UOWN|BDNSTAT_DTS|BDNSTAT_DTSEN, 0);
+	ep0_buf.flags ^= EP_TX_PPBI;
+#else
+	BDS0IN(0).STAT.BDnSTAT = 0;
+	SET_BDN(BDS0IN(0), BDNSTAT_UOWN|BDNSTAT_DTS|BDNSTAT_DTSEN, 0);
+#endif
+}
+
+static void usb_send_in_buffer_0(size_t len)
+{
+	if (!usb_in_endpoint_halted(0)) {
+#ifdef PPB_EP0_IN
+		struct buffer_descriptor *bd;
+		uint8_t ppbi = (ep0_buf.flags & EP_TX_PPBI)? 1: 0;
+		uint8_t pid = (ep0_buf.flags & EP_TX_DTS)? 1 : 0;
+		bd = &BDS0IN(ppbi);
+		bd->STAT.BDnSTAT = 0;
+
+		if (pid)
+			SET_BDN(*bd,
+				BDNSTAT_UOWN|BDNSTAT_DTS|BDNSTAT_DTSEN, len);
+		else
+			SET_BDN(*bd,
+				BDNSTAT_UOWN|BDNSTAT_DTSEN, len);
+
+		ep0_buf.flags ^= EP_TX_PPBI;
+		ep0_buf.flags ^= EP_TX_DTS;
+#else
+		uint8_t pid;
+		pid = (ep0_buf.flags & EP_TX_DTS)? 1 : 0;
+		BDS0IN(0).STAT.BDnSTAT = 0;
+
+		if (pid)
+			SET_BDN(BDS0IN(0),
+				BDNSTAT_UOWN|BDNSTAT_DTS|BDNSTAT_DTSEN, len);
+		else
+			SET_BDN(BDS0IN(0),
+				BDNSTAT_UOWN|BDNSTAT_DTSEN, len);
+
+		ep0_buf.flags ^= EP_TX_DTS;
+#endif
+	}
+}
+
+/* Copy Data to Endpoint 0's IN Buffer
+ *
+ * Copy len bytes from ptr into endpoint 0's current IN
+ * buffer, taking into account the ping-pong state.
+ */
+#ifdef PPB_EP0_IN
+static void copy_to_ep0_in_buf(const void *ptr, size_t len)
+{
+	uint8_t ppbi = (ep0_buf.flags & EP_TX_PPBI)? 1: 0;
+	if (ppbi)
+		memcpy_from_rom(ep0_buf.in1, ptr, len);
+	else
+		memcpy_from_rom(ep0_buf.in, ptr, len);
+}
+#else
+	#define copy_to_ep0_in_buf(PTR, LEN) memcpy_from_rom(ep0_buf.in, PTR, LEN);
+#endif
+
+/* Start Control Return
+ *
+ * Start the data stage of an IN control transfer. This is primarily used
+ * for sending descriptors and other chapter 9 data back to the host, but it
+ * is also called from usb_send_data_stage() for handling control transfers
+ * handled by the application.
+ *
+ * This function sets up the global state variables necessary to do a
+ * multi-transaction IN data stage and sends the first transaction.
+ *
+ * Params:
+ *   ptr             - a pointer to the data to send
+ *   len             - the size of the data which can be sent (ie: the size
+ *                     of the entire descriptor)
+ *   bytes_asked_for - the number of bytes asked for by the host in
+ *                     the SETUP phase
+ */
+static void start_control_return(const void *ptr, size_t len, size_t bytes_asked_for)
+{
+	uint8_t bytes_to_send = MIN(len, EP_0_IN_LEN);
+	bytes_to_send = MIN(bytes_to_send, bytes_asked_for);
+	returning_short = len < bytes_asked_for;
+	copy_to_ep0_in_buf(ptr, bytes_to_send);
+	ep0_data_stage_in_buffer = ((char*)ptr) + bytes_to_send;
+	ep0_data_stage_buf_remaining = MIN(bytes_asked_for, len) - bytes_to_send;
+
+	/* Send back the first transaction */
+	ep0_buf.flags |= EP_TX_DTS;
+	usb_send_in_buffer_0(bytes_to_send);
+}
+
+static inline int8_t handle_standard_control_request()
+{
+	FAR struct setup_packet *setup;
+	int8_t res = 0;
+
+#ifdef PPB_EP0_OUT
+	if (SFR_USB_STATUS_PPBI)
+		setup = (struct setup_packet*) ep0_buf.out1;
+	else
+		setup = (struct setup_packet*) ep0_buf.out;
+#else
+	setup = (struct setup_packet*) ep0_buf.out;
+#endif
+
+	if (setup->bRequest == GET_DESCRIPTOR &&
+	    setup->REQUEST.bmRequestType == 0x80 /* Section 9.4, Table 9-3 */) {
+		char descriptor = ((setup->wValue >> 8) & 0x00ff);
+		uint8_t descriptor_index = setup->wValue & 0x00ff;
+
+		if (descriptor == DESC_DEVICE) {
+			SERIAL("Get Descriptor for DEVICE");
+
+			/* Return Device Descriptor */
+			start_control_return(&USB_DEVICE_DESCRIPTOR, USB_DEVICE_DESCRIPTOR.bLength, setup->wLength);
+		}
+		else if (descriptor == DESC_CONFIGURATION) {
+			const struct configuration_descriptor *desc;
+			if (descriptor_index >= NUMBER_OF_CONFIGURATIONS)
+				stall_ep0();
+			else {
+				desc = USB_CONFIG_DESCRIPTOR_MAP[descriptor_index];
+				start_control_return(desc, desc->wTotalLength, setup->wLength);
+			}
+		}
+		else if (descriptor == DESC_STRING) {
+#ifdef MICROSOFT_OS_DESC_VENDOR_CODE
+			if (descriptor_index == 0xee) {
+				/* Microsoft descriptor Requested */
+				#ifdef __XC8
+				/* static is better in all cases on XC8. On
+				 * XC16/32, non-static uses less RAM. */
+				static
+				#endif
+				struct microsoft_os_descriptor os_descriptor =
+				{
+					0x12,                          /* bLength */
+					0x3,                           /* bDescriptorType */
+					{'M','S','F','T','1','0','0'}, /* qwSignature */
+					MICROSOFT_OS_DESC_VENDOR_CODE, /* bMS_VendorCode */
+					0x0,                           /* bPad */
+				};
+
+				start_control_return(&os_descriptor, sizeof(os_descriptor), setup->wLength);
+			}
+			else
+#endif
+			{
+#ifdef USB_STRING_DESCRIPTOR_FUNC
+				const void *desc;
+				int16_t len;
+				{
+					len = USB_STRING_DESCRIPTOR_FUNC(descriptor_index, &desc);
+					if (len < 0) {
+						stall_ep0();
+						SERIAL("Unsupported string descriptor requested");
+					}
+					else
+						start_control_return(desc, len, setup->wLength);
+				}
+#else
+				/* Strings are not supported on this device. */
+				stall_ep0();
+#endif
+			}
+		}
+		else {
+#ifdef UNKNOWN_GET_DESCRIPTOR_CALLBACK
+			int16_t len;
+			const void *desc;
+			len = UNKNOWN_GET_DESCRIPTOR_CALLBACK(setup, &desc);
+			if (len < 0) {
+				stall_ep0();
+				SERIAL("Unsupported descriptor requested");
+			}
+			else
+				start_control_return(desc, len, setup->wLength);
+#else
+			/* Unknown Descriptor. Stall the endpoint. */
+			stall_ep0();
+			SERIAL("Unknown Descriptor");
+			SERIAL_VAL(descriptor);
+#endif
+		}
+	}
+	else if (setup->bRequest == SET_ADDRESS) {
+		/* Mark the ADDR as pending. The address gets set only
+		   after the transaction is complete. */
+		addr_pending = 1;
+		addr = setup->wValue;
+
+		send_zero_length_packet_ep0();
+	}
+	else if (setup->bRequest == SET_CONFIGURATION) {
+		/* Set the configuration. wValue is the configuration.
+		 * A value of 0 means to un-set the configuration and
+		 * go back to the ADDRESS state. */
+		uint8_t req = setup->wValue & 0x00ff;
+#ifdef SET_CONFIGURATION_CALLBACK
+		SET_CONFIGURATION_CALLBACK(req);
+#endif
+		/* Re-initialize the endpoints. USB 2.0 section 9.1.1.5
+		 * requires that all endpoint data toggles be reset to DATA0
+		 * when SET_CONFIGURATION is received. With ping-ponging
+		 * involved, the only way to properly reset the data toggles
+		 * is to reset all the endpoints. */
+		init_endpoints();
+
+		send_zero_length_packet_ep0();
+		g_configuration = req;
+
+		SERIAL("Set configuration to");
+		SERIAL_VAL(req);
+	}
+	else if (setup->bRequest == GET_CONFIGURATION) {
+		/* Return the current Configuration. */
+		SERIAL("Get Configuration. Returning:");
+		SERIAL_VAL(g_configuration);
+
+		start_control_return(&g_configuration, 1, setup->wLength);
+	}
+	else if (setup->bRequest == GET_STATUS) {
+
+		SERIAL("Get Status (dst, index):");
+		SERIAL_VAL(setup->REQUEST.destination);
+		SERIAL_VAL(setup->wIndex);
+
+		if (setup->REQUEST.destination == 0 /*0=device*/) {
+			/* Status for the DEVICE requested
+			   Return as a single byte in the return packet. */
+			uint16_t ret;
+#ifdef GET_DEVICE_STATUS_CALLBACK
+			ret = GET_DEVICE_STATUS_CALLBACK();
+#else
+			ret = 0x0000;
+#endif
+			start_control_return(&ret, 2, setup->wLength);
+		}
+		else if (setup->REQUEST.destination == 2 /*2=endpoint*/) {
+			/* Status of endpoint */
+			uint8_t ep_num = setup->wIndex & 0x0f;
+			if (ep_num <= NUM_ENDPOINT_NUMBERS) {
+				uint8_t flags = ep_buf[ep_num].flags;
+				uint8_t ret[2];
+				ret[0] = ((setup->wIndex & 0x80) ?
+					flags & EP_IN_HALT_FLAG :
+					flags & EP_OUT_HALT_FLAG) != 0;
+				ret[1] = 0;
+				start_control_return(ret, 2, setup->wLength);
+			}
+			else {
+				/* Endpoint doesn't exist. STALL. */
+				stall_ep0();
+			}
+		}
+		else {
+			stall_ep0();
+			SERIAL("Stalling. Status Requested for destination:");
+			SERIAL_VAL(setup->REQUEST.destination);
+		}
+
+	}
+	else if (setup->bRequest == SET_INTERFACE) {
+		/* Set the alternate setting for an interface.
+		 * wIndex is the interface.
+		 * wValue is the alternate setting. */
+#ifdef SET_INTERFACE_CALLBACK
+		int8_t res;
+		res = SET_INTERFACE_CALLBACK(setup->wIndex, setup->wValue);
+		if (res < 0) {
+			stall_ep0();
+		}
+		else
+			send_zero_length_packet_ep0();
+#else
+		/* If there's no callback, then assume that
+		 * we only have one alternate setting per
+		 * interface. */
+		send_zero_length_packet_ep0();
+#endif
+	}
+	else if (setup->bRequest == GET_INTERFACE) {
+		int8_t ret;
+		SERIAL("Get Interface");
+		SERIAL_VAL(setup->bRequest);
+		SERIAL_VAL(setup->REQUEST.destination);
+		SERIAL_VAL(setup->REQUEST.type);
+		SERIAL_VAL(setup->REQUEST.direction);
+#ifdef GET_INTERFACE_CALLBACK
+		ret = GET_INTERFACE_CALLBACK(setup->wIndex);
+		if (ret < 0)
+			stall_ep0();
+		else {
+			/* Return the current alternate setting
+			   as a single byte in the return packet. */
+			start_control_return(&ret, 1, setup->wLength);
+		}
+#else
+		/* If there's no callback, then assume that
+		 * we only have one alternate setting per
+		 * interface and return zero as that
+		 * alternate setting. */
+		ret = 0;
+		start_control_return(&ret, 1, setup->wLength);
+#endif
+	}
+	else if (setup->bRequest == CLEAR_FEATURE || setup->bRequest == SET_FEATURE) {
+		uint8_t stall = 1;
+		if (setup->REQUEST.destination == 0/*0=device*/) {
+			SERIAL("Set/Clear feature for device");
+			/* TODO Remote Wakeup flag */
+		}
+
+		if (setup->REQUEST.destination == 2/*2=endpoint*/) {
+			if (setup->wValue == 0/*0=ENDPOINT_HALT*/) {
+				uint8_t ep_num = setup->wIndex & 0x0f;
+				uint8_t ep_dir = setup->wIndex & 0x80;
+				if (ep_num <= NUM_ENDPOINT_NUMBERS) {
+					if (setup->bRequest == SET_FEATURE) {
+						/* Set Endpoint Halt Feature.
+						   Stall the affected endpoint. */
+						if (ep_dir) {
+							usb_halt_ep_in(ep_num);
+						}
+						else {
+							usb_halt_ep_out(ep_num);
+						}
+					}
+					else {
+						/* Clear Endpoint Halt Feature.
+						   Clear the STALL on the affected endpoint. */
+						if (ep_dir) {
+#ifdef PPB_EPn
+							SET_BDN(BDSnIN(ep_num, 0), 0, ep_buf[ep_num].in_len);
+							SET_BDN(BDSnIN(ep_num, 1), 0, ep_buf[ep_num].in_len);
+#else
+							SET_BDN(BDSnIN(ep_num, 0), 0, ep_buf[ep_num].in_len);
+#endif
+							/* Clear DTS. Next packet to be sent will be DATA0. */
+							ep_buf[ep_num].flags &= ~EP_TX_DTS;
+
+							ep_buf[ep_num].flags &= ~(EP_IN_HALT_FLAG);
+						}
+						else {
+#ifdef PPB_EPn
+							uint8_t ppbi = (ep_buf[ep_num].flags & EP_RX_PPBI)? 1 : 0;
+							/* Put the current buffer at DTS 0, and the next (opposite) buffer at DTS 1 */
+							SET_BDN(BDSnOUT(ep_num, ppbi), BDNSTAT_UOWN|BDNSTAT_DTSEN, ep_buf[ep_num].out_len);
+							SET_BDN(BDSnOUT(ep_num, !ppbi), BDNSTAT_UOWN|BDNSTAT_DTSEN|BDNSTAT_DTS, ep_buf[ep_num].out_len);
+
+							/* Clear DTS */
+							ep_buf[ep_num].flags &= ~EP_RX_DTS;
+#else
+							SET_BDN(BDSnOUT(ep_num, 0), BDNSTAT_UOWN|BDNSTAT_DTSEN, ep_buf[ep_num].out_len);
+
+							/* Set DTS */
+							ep_buf[ep_num].flags |= EP_RX_DTS;
+#endif
+							ep_buf[ep_num].flags &= ~(EP_OUT_HALT_FLAG);
+						}
+					}
+#ifdef ENDPOINT_HALT_CALLBACK
+					ENDPOINT_HALT_CALLBACK(setup->wIndex, (setup->bRequest == SET_FEATURE));
+#endif
+					stall = 0;
+				}
+			}
+		}
+
+		if (!stall) {
+			send_zero_length_packet_ep0();
+		}
+		else
+			stall_ep0();
+	}
+	else {
+		res = -1;
+
+		SERIAL("unsupported request (req, dest, type, dir) ");
+		SERIAL_VAL(setup->bRequest);
+		SERIAL_VAL(setup->REQUEST.destination);
+		SERIAL_VAL(setup->REQUEST.type);
+		SERIAL_VAL(setup->REQUEST.direction);
+	}
+
+	return res;
+}
+
+static inline void handle_ep0_setup()
+{
+	FAR struct setup_packet *setup;
+#ifdef PPB_EP0_OUT
+	if (SFR_USB_STATUS_PPBI)
+		setup = (struct setup_packet*) ep0_buf.out1;
+	else
+		setup = (struct setup_packet*) ep0_buf.out;
+#else
+	setup = (struct setup_packet*) ep0_buf.out;
+#endif
+
+	ep0_data_stage_direc = setup->REQUEST.direction;
+	int8_t res;
+
+#ifdef NEEDS_CLEAR_STALL
+	/* The datasheets say the MCU will clear BSTALL and UOWN when
+	 * a SETUP packet is received. This does not seem to happen on
+	 * PIC16 or PIC18, so clear the stall explicitly. */
+	clear_ep0_stall();
+#endif
+
+	/* Receiving a Setup packet cancels any control transfer which was
+	 * in progress and thus invalidates any IN transactions which were
+	 * pending for a previous control transfer. Cancel any of these IN
+	 * transactions which were pending. */
+#ifdef PPB_EP0_OUT
+	/* For ping-pong mode on EP 0, note below that ppbi is the next
+	 * ping-pong buffer which would be written to, meaning that !ppbi is
+	 * the buffer which would have an IN transaction pending (if any).
+	 *
+	 * Only one ping-pong buffer is cleared (instead of both) because
+	 * M-Stack only puts one transfer at a time on the control IN endpoint.
+	 */
+	uint8_t ppbi = (ep0_buf.flags & EP_TX_PPBI)? 1: 0;
+	if (BDS0IN(!ppbi).STAT.UOWN) {
+		SET_BDN(BDS0IN(!ppbi), 0, EP_0_LEN);
+		ep0_buf.flags ^= EP_TX_PPBI;
+	}
+#else
+	if (BDS0IN(0).STAT.UOWN) {
+		SET_BDN(BDS0IN(0), 0, EP_0_LEN);
+	}
+#endif
+
+	if (ep0_data_stage_buf_remaining) {
+		/* A SETUP transaction has been received while waiting
+		 * for a DATA stage to complete; something is broken.
+		 * If this was an application-controlled transfer (and
+		 * there's a callback), notify the application of this. */
+		if (ep0_data_stage_callback)
+			ep0_data_stage_callback(0/*fail*/, ep0_data_stage_context);
+
+		reset_ep0_data_stage();
+	}
+
+	if (setup->REQUEST.type == REQUEST_TYPE_STANDARD) {
+		res = handle_standard_control_request();
+		if (res < 0)
+			goto handle_unknown;
+	}
+#ifdef MICROSOFT_OS_DESC_VENDOR_CODE
+	else if (setup->bRequest == MICROSOFT_OS_DESC_VENDOR_CODE) {
+		const void *desc;
+		int16_t len = -1;
+
+		if (setup->REQUEST.bmRequestType == 0xC0 &&
+		    setup->wIndex == 0x0004) {
+			len = MICROSOFT_COMPAT_ID_DESCRIPTOR_FUNC(
+				setup->wValue,
+				&desc);
+		}
+		else if (setup->REQUEST.bmRequestType == 0xC1 &&
+		         setup->wIndex == 0x0005) {
+			len = MICROSOFT_CUSTOM_PROPERTY_DESCRIPTOR_FUNC(
+				setup->wValue,
+				&desc);
+		}
+
+		if (len < 0)
+			stall_ep0();
+		else
+			start_control_return(desc, len, setup->wLength);
+	}
+#endif
+	else
+		goto handle_unknown;
+
+	goto out;
+
+handle_unknown:
+
+#ifdef UNKNOWN_SETUP_REQUEST_CALLBACK
+	res = UNKNOWN_SETUP_REQUEST_CALLBACK(setup);
+	if (res < 0)
+		stall_ep0();
+	else {
+		/* If the application has handled this request, it
+		 * will have already set up whatever needs to be set
+		 * up for the data stage. */
+	}
+#else
+	/* Unsupported Request. Stall the Endpoint. */
+	stall_ep0();
+#endif
+
+out:
+	/* SETUP packet sets PKTDIS which disables
+	 * future SETUP packet reception. Turn it off
+	 * afer we've processed the current SETUP
+	 * packet to avoid a race condition. */
+	SFR_USB_PKT_DIS = 0;
+}
+
+static inline void handle_ep0_out()
+{
+#ifdef PPB_EP0_OUT
+	uint8_t pkt_len = BDN_LENGTH(BDS0OUT(SFR_USB_STATUS_PPBI));
+#else
+	uint8_t pkt_len = BDN_LENGTH(BDS0OUT(0));
+#endif
+	if (ep0_data_stage_direc == 1/*1=IN*/) {
+		/* An empty OUT packet on an IN control transfer
+		 * means the STATUS stage of the control
+		 * transfer has completed (possibly early). */
+
+		/* Notify the application (if applicable) */
+		if (ep0_data_stage_callback)
+			ep0_data_stage_callback(1/*true*/, ep0_data_stage_context);
+		reset_ep0_data_stage();
+	}
+	else {
+		/* A packet received as part of the data stage of
+		 * a control transfer. Pack what data we received
+		 * into the application's buffer (if it has
+		 * provided one). When all the data has been
+		 * received, call the application-provided callback.
+		 */
+
+		if (ep0_data_stage_out_buffer) {
+			uint8_t bytes_to_copy = MIN(pkt_len, ep0_data_stage_buf_remaining);
+#ifdef PPB_EP0_OUT
+			if (SFR_USB_STATUS_PPBI)
+				memcpy(ep0_data_stage_out_buffer, ep0_buf.out1, bytes_to_copy);
+			else
+				memcpy(ep0_data_stage_out_buffer, ep0_buf.out, bytes_to_copy);
+#else
+			memcpy(ep0_data_stage_out_buffer, ep0_buf.out, bytes_to_copy);
+#endif
+			ep0_data_stage_out_buffer += bytes_to_copy;
+			ep0_data_stage_buf_remaining -= bytes_to_copy;
+
+			/* It's possible that bytes_to_copy is less than pkt_len
+			 * here because the application provided too small a buffer. */
+
+			if (pkt_len < EP_0_OUT_LEN || ep0_data_stage_buf_remaining == 0) {
+				/* Short packet or we've received the expected length.
+				 * All data has been transferred (or all the data
+				 * has been received which can be received). */
+
+				if (bytes_to_copy < pkt_len) {
+					/* The buffer provided by the application was too short */
+					stall_ep0();
+					if (ep0_data_stage_callback)
+						ep0_data_stage_callback(0/*false*/, ep0_data_stage_context);
+					reset_ep0_data_stage();
+				}
+				else {
+					/* The data stage has completed. Set up the status stage. */
+					send_zero_length_packet_ep0();
+				}
+			}
+		}
+	}
+}
+
+static inline void handle_ep0_in()
+{
+	if (addr_pending) {
+		SFR_USB_ADDR =  addr;
+		addr_pending = 0;
+	}
+
+	if (ep0_data_stage_buf_remaining) {
+		/* There's already a multi-transaction transfer in process. */
+		uint8_t bytes_to_send = MIN(ep0_data_stage_buf_remaining, EP_0_IN_LEN);
+
+		copy_to_ep0_in_buf(ep0_data_stage_in_buffer, bytes_to_send);
+		ep0_data_stage_buf_remaining -= bytes_to_send;
+		ep0_data_stage_in_buffer += bytes_to_send;
+
+		/* If we hit the end with a full-length packet, set up
+		   to send a zero-length packet at the next IN token, but only
+		   if we are returning less data than was requested. */
+		if (ep0_data_stage_buf_remaining == 0 &&
+		    bytes_to_send == EP_0_IN_LEN &&
+		    returning_short)
+			control_need_zlp = 1;
+
+		usb_send_in_buffer_0(bytes_to_send);
+	}
+	else if (control_need_zlp) {
+		usb_send_in_buffer_0(0);
+		control_need_zlp = 0;
+		reset_ep0_data_stage();
+	}
+	else {
+		if (ep0_data_stage_direc == 0/*OUT*/) {
+			/* An IN on the control endpoint with no data pending
+			 * and during an OUT transfer means the STATUS stage
+			 * of the control transfer has completed. Notify the
+			 * application, if applicable. */
+			if (ep0_data_stage_callback)
+				ep0_data_stage_callback(1/*true*/, ep0_data_stage_context);
+			reset_ep0_data_stage();
+		}
+	}
+}
+
+/* checkUSB() is called repeatedly to check for USB interrupts
+   and service USB requests */
+void usb_service(void)
+{
+	if (SFR_USB_RESET_IF) {
+		/* A Reset was detected on the wire. Re-init the SIE. */
+#ifdef USB_RESET_CALLBACK
+		USB_RESET_CALLBACK();
+#endif
+		usb_init();
+		CLEAR_USB_RESET_IF();
+		SERIAL("USB Reset");
+	}
+	
+	if (SFR_USB_STALL_IF) {
+		/* On PIC24/32, EPSTALL bits must be cleared, or else the
+		 * stalled endpoint's opposite direction (eg: EP1 IN => EP1
+		 * OUT) will also stall (incorrectly). There is no way to
+		 * determine which endpoint generated this interrupt, so all
+		 * the endpoints' EPSTALL bits must be checked and cleared. */
+		int i;
+		for (i = 1; i <= NUM_ENDPOINT_NUMBERS; i++) {
+			volatile SFR_EP_MGMT_TYPE *ep = SFR_EP_MGMT(i);
+			ep->SFR_EP_MGMT_STALL = 0;
+		}
+
+		CLEAR_USB_STALL_IF();
+	}
+
+
+#ifdef USB_USE_INTERRUPTS
+	if (SFR_USB_TOKEN_IF && SFR_TRANSFER_IE) {
+#else
+	if (SFR_USB_TOKEN_IF) {
+#endif
+
+		//struct ustat_bits ustat = *((struct ustat_bits*)&USTAT);
+
+		if (SFR_USB_STATUS_EP == 0 && SFR_USB_STATUS_DIR == 0/*OUT*/) {
+			/* An OUT or SETUP transaction has completed on
+			 * Endpoint 0.  Handle the data that was received.
+			 */
+#ifdef PPB_EP0_OUT
+			uint8_t pid = BDS0OUT(SFR_USB_STATUS_PPBI).STAT.PID;
+#else
+			uint8_t pid = BDS0OUT(0).STAT.PID;
+#endif
+			if (pid == PID_SETUP) {
+				handle_ep0_setup();
+			}
+			else if (pid == PID_IN) {
+				/* Nonsense condition:
+				   (PID IN on SFR_USB_STATUS_DIR == OUT) */
+			}
+			else if (pid == PID_OUT) {
+				handle_ep0_out();
+			}
+			else {
+				/* Unsupported PID. Stall the Endpoint. */
+				SERIAL("Unsupported PID. Stall.");
+				stall_ep0();
+			}
+
+			reset_bd0_out();
+		}
+		else if (SFR_USB_STATUS_EP == 0 && SFR_USB_STATUS_DIR == 1/*1=IN*/) {
+			/* An IN transaction has completed. The endpoint
+			 * needs to be re-loaded with the next transaction's
+			 * data if there is any.
+			 */
+			handle_ep0_in();
+		}
+		else if (SFR_USB_STATUS_EP > 0 && SFR_USB_STATUS_EP <= NUM_ENDPOINT_NUMBERS) {
+			if (SFR_USB_STATUS_DIR == 1 /*1=IN*/) {
+				/* An IN transaction has completed. */
+				SERIAL("IN transaction completed on non-EP0.");
+				if (ep_buf[SFR_USB_STATUS_EP].flags & EP_IN_HALT_FLAG)
+					stall_ep_in(SFR_USB_STATUS_EP);
+				else {
+#ifdef IN_TRANSACTION_COMPLETE_CALLBACK
+					IN_TRANSACTION_COMPLETE_CALLBACK(SFR_USB_STATUS_EP);
+#endif
+				}
+			}
+			else {
+				/* An OUT transaction has completed. */
+				SERIAL("OUT transaction received on non-EP0");
+				if (ep_buf[SFR_USB_STATUS_EP].flags & EP_OUT_HALT_FLAG)
+					stall_ep_out(SFR_USB_STATUS_EP);
+				else {
+#ifdef OUT_TRANSACTION_CALLBACK
+					OUT_TRANSACTION_CALLBACK(SFR_USB_STATUS_EP);
+#endif
+				}
+			}
+		}
+		else {
+			/* Transaction completed on an endpoint not used.
+			 * This should never happen. */
+			SERIAL("Transaction completed for unknown endpoint");
+		}
+
+		CLEAR_USB_TOKEN_IF();
+	}
+	
+	/* Check for Start-of-Frame interrupt. */
+	if (SFR_USB_SOF_IF) {
+#ifdef START_OF_FRAME_CALLBACK
+		START_OF_FRAME_CALLBACK();
+#endif
+		CLEAR_USB_SOF_IF();
+	}
+
+	/* Check for USB Interrupt. */
+	if (SFR_USB_IF) {
+		SFR_USB_IF = 0;
+	}
+}
+
+uint8_t usb_get_configuration(void)
+{
+	return g_configuration;
+}
+
+unsigned char *usb_get_in_buffer(uint8_t endpoint)
+{
+#ifdef PPB_EPn
+	if (ep_buf[endpoint].flags & EP_TX_PPBI /*odd*/)
+		return ep_buf[endpoint].in1;
+	else
+		return ep_buf[endpoint].in;
+#else
+	return ep_buf[endpoint].in;
+#endif
+}
+
+void usb_send_in_buffer(uint8_t endpoint, size_t len)
+{
+#ifdef DEBUG
+	if (endpoint == 0)
+		error();
+#endif
+	if (g_configuration > 0 && !usb_in_endpoint_halted(endpoint)) {
+		uint8_t pid;
+		struct buffer_descriptor *bd;
+#ifdef PPB_EPn
+		uint8_t ppbi = (ep_buf[endpoint].flags & EP_TX_PPBI)? 1 : 0;
+
+		bd = &BDSnIN(endpoint,ppbi);
+		pid = (ep_buf[endpoint].flags & EP_TX_DTS)? 1 : 0;
+		bd->STAT.BDnSTAT = 0;
+
+		if (pid)
+			SET_BDN(BDSnIN(endpoint,ppbi),
+				BDNSTAT_UOWN|BDNSTAT_DTS|BDNSTAT_DTSEN, len);
+		else
+			SET_BDN(BDSnIN(endpoint,ppbi),
+				BDNSTAT_UOWN|BDNSTAT_DTSEN, len);
+
+		ep_buf[endpoint].flags ^= EP_TX_PPBI;
+		ep_buf[endpoint].flags ^= EP_TX_DTS;
+#else
+		bd = &BDSnIN(endpoint,0);
+		pid = (ep_buf[endpoint].flags & EP_TX_DTS)? 1 : 0;
+		bd->STAT.BDnSTAT = 0;
+
+		if (pid)
+			SET_BDN(*bd,
+				BDNSTAT_UOWN|BDNSTAT_DTS|BDNSTAT_DTSEN, len);
+		else
+			SET_BDN(*bd,
+				BDNSTAT_UOWN|BDNSTAT_DTSEN, len);
+
+		ep_buf[endpoint].flags ^= EP_TX_DTS;
+#endif
+	}
+}
+
+bool usb_in_endpoint_busy(uint8_t endpoint)
+{
+#ifdef PPB_EPn
+	uint8_t ppbi = (ep_buf[endpoint].flags & EP_TX_PPBI)? 1: 0;
+	return BDSnIN(endpoint, ppbi).STAT.UOWN;
+#else
+	return BDSnIN(endpoint,0).STAT.UOWN;
+#endif
+}
+
+uint8_t usb_halt_ep_in(uint8_t ep)
+{
+	if (ep == 0 || ep > NUM_ENDPOINT_NUMBERS)
+		return -1;
+
+	ep_buf[ep].flags |= EP_IN_HALT_FLAG;
+	stall_ep_in(ep);
+
+	return 0;
+}
+
+bool usb_in_endpoint_halted(uint8_t endpoint)
+{
+	return ep_buf[endpoint].flags & EP_IN_HALT_FLAG;
+}
+
+uint8_t usb_get_out_buffer(uint8_t endpoint, const unsigned char **buf)
+{
+#ifdef PPB_EPn
+	uint8_t ppbi = (ep_buf[endpoint].flags & EP_RX_PPBI)? 1: 0;
+
+	if (ppbi /*odd*/)
+		*buf = ep_buf[endpoint].out1;
+	else
+		*buf = ep_buf[endpoint].out;
+
+	return BDN_LENGTH(BDSnOUT(endpoint, ppbi));
+#else
+	*buf = ep_buf[endpoint].out;
+	return BDN_LENGTH(BDSnOUT(endpoint, 0));
+#endif
+}
+
+bool usb_out_endpoint_has_data(uint8_t endpoint)
+{
+#ifdef PPB_EPn
+	uint8_t ppbi = (ep_buf[endpoint].flags & EP_RX_PPBI)? 1: 0;
+	return !BDSnOUT(endpoint,ppbi).STAT.UOWN;
+#else
+	return !BDSnOUT(endpoint,0).STAT.UOWN;
+#endif
+}
+
+void usb_arm_out_endpoint(uint8_t endpoint)
+{
+#ifdef PPB_EPn
+	uint8_t ppbi = (ep_buf[endpoint].flags & EP_RX_PPBI)? 1: 0;
+	uint8_t pid = (ep_buf[endpoint].flags & EP_RX_DTS)? 1: 0;
+
+	if (pid)
+		SET_BDN(BDSnOUT(endpoint,ppbi),
+			BDNSTAT_UOWN|BDNSTAT_DTSEN|BDNSTAT_DTS,
+			ep_buf[endpoint].out_len);
+	else
+		SET_BDN(BDSnOUT(endpoint,ppbi),
+			BDNSTAT_UOWN|BDNSTAT_DTSEN,
+			ep_buf[endpoint].out_len);
+
+	/* Alternate the PPBI */
+	ep_buf[endpoint].flags ^= EP_RX_PPBI;
+	ep_buf[endpoint].flags ^= EP_RX_DTS;
+
+#else
+	uint8_t pid = (ep_buf[endpoint].flags & EP_RX_DTS)? 1: 0;
+	if (pid)
+		SET_BDN(BDSnOUT(endpoint,0),
+			BDNSTAT_UOWN|BDNSTAT_DTS|BDNSTAT_DTSEN,
+			ep_buf[endpoint].out_len);
+	else
+		SET_BDN(BDSnOUT(endpoint,0),
+			BDNSTAT_UOWN|BDNSTAT_DTSEN,
+			ep_buf[endpoint].out_len);
+
+	ep_buf[endpoint].flags ^= EP_RX_DTS;
+#endif
+
+}
+
+uint8_t usb_halt_ep_out(uint8_t ep)
+{
+	if (ep == 0 || ep > NUM_ENDPOINT_NUMBERS)
+		return -1;
+
+	ep_buf[ep].flags |= EP_OUT_HALT_FLAG;
+	stall_ep_out(ep);
+
+	return 0;
+}
+
+bool usb_out_endpoint_halted(uint8_t endpoint)
+{
+	return ep_buf[endpoint].flags & EP_OUT_HALT_FLAG;
+}
+
+void usb_start_receive_ep0_data_stage(char *buffer, size_t len,
+                                      usb_ep0_data_stage_callback callback, void *context)
+{
+	reset_ep0_data_stage();
+
+	ep0_data_stage_callback = callback;
+	ep0_data_stage_out_buffer = buffer;
+	ep0_data_stage_buf_remaining = len;
+	ep0_data_stage_context = context;
+}
+
+void usb_send_data_stage(char *buffer, size_t len,
+	usb_ep0_data_stage_callback callback, void *context)
+{
+	/* Start sending the first block. Subsequent blocks will be sent
+	   when IN tokens are received on endpoint zero. */
+	ep0_data_stage_callback = callback;
+	ep0_data_stage_context = context;
+	start_control_return(buffer, len, len);
+}
+
+/* Private Functions */
+
+#ifdef USB_USE_INTERRUPTS
+/* Manipulate the transaction (token) interrupt.  There is no stack or
+ * counter used to keep track of enable/disable calls, so care must be used
+ * to ensure that calls to these functions are not nested.  */
+void usb_disable_transaction_interrupt()
+{
+	SFR_TRANSFER_IE = 0;
+}
+void usb_enable_transaction_interrupt()
+{
+	SFR_TRANSFER_IE = 1;
+}
+#endif
+
+
+#ifdef USB_USE_INTERRUPTS
+#ifdef __XC16__
+
+void _ISR __attribute((auto_psv)) _USB1Interrupt()
+{
+	usb_service();
+}
+
+#elif __XC32__
+
+/* No parameter for interrupt() means to use IPL=RIPL and to detect whether
+   to use shadow registers or not. This is the safest option, but if a user
+   wanted maximum performance, they could use IPL7SRS and set the USBIP to 7.
+   IPL 7 is the only time the shadow register set can be used on PIC32MX. */
+void __attribute__((vector(_USB_1_VECTOR), interrupt(), nomips16)) _USB1Interrupt()
+{
+	usb_service();
+}
+
+#elif __C18
+#elif __XC8
+	/* On these systems, interupt handlers are shared. An interrupt
+	 * handler from the application must call usb_service(). */
+#else
+#error Compiler not supported yet
+#endif
+#endif
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usb/src/usb_cdc.c	Sat Feb 18 16:14:32 2017 +0000
@@ -0,0 +1,306 @@
+/*
+ *  M-Stack USB Device Stack Implementation
+ *  Copyright (C) 2013 Alan Ott <alan@signal11.us>
+ *  Copyright (C) 2013 Signal 11 Software
+ *
+ *  2014-05-12
+ *
+ *  M-Stack is free software: you can redistribute it and/or modify it under
+ *  the terms of the GNU Lesser General Public License as published by the
+ *  Free Software Foundation, version 3; or the Apache License, version 2.0
+ *  as published by the Apache Software Foundation.  If you have purchased a
+ *  commercial license for this software from Signal 11 Software, your
+ *  commerical license superceeds the information in this header.
+ *
+ *  M-Stack is distributed in the hope that it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
+ *  License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public License
+ *  along with this software.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ *  You should have received a copy of the Apache License, verion 2.0 along
+ *  with this software.  If not, see <http://www.apache.org/licenses/>.
+ */
+
+#include <usb_config.h>
+
+#include <usb_ch9.h>
+#include <usb.h>
+#include <usb_cdc.h>
+
+#define MIN(x,y) (((x)<(y))?(x):(y))
+
+STATIC_SIZE_CHECK_EQUAL(sizeof(struct cdc_functional_descriptor_header), 5);
+STATIC_SIZE_CHECK_EQUAL(sizeof(struct cdc_acm_functional_descriptor), 4);
+STATIC_SIZE_CHECK_EQUAL(sizeof(struct cdc_union_functional_descriptor), 5);
+STATIC_SIZE_CHECK_EQUAL(sizeof(struct cdc_line_coding), 7);
+STATIC_SIZE_CHECK_EQUAL(sizeof(struct cdc_notification_header), 8);
+STATIC_SIZE_CHECK_EQUAL(sizeof(struct cdc_serial_state_notification), 10);
+
+
+#ifdef MULTI_CLASS_DEVICE
+static uint8_t *cdc_interfaces;
+static uint8_t num_cdc_interfaces;
+
+void cdc_set_interface_list(uint8_t *interfaces, uint8_t num_interfaces)
+{
+	cdc_interfaces = interfaces;
+	num_cdc_interfaces = num_interfaces;
+}
+
+static bool interface_is_cdc(uint8_t interface)
+{
+	uint8_t i;
+	for (i = 0; i < num_cdc_interfaces; i++) {
+		if (interface == cdc_interfaces[i])
+			break;
+	}
+
+	/* Return if interface is not in the list of CDC interfaces. */
+	if (i == num_cdc_interfaces)
+		return false;
+
+	return true;
+}
+#endif
+
+static uint8_t transfer_interface;
+static union transfer_data {
+	#if defined(CDC_SET_COMM_FEATURE_CALLBACK) || \
+	    defined(CDC_CLEAR_COMM_FEATURE_CALLBACK) || \
+	    defined(CDC_GET_COMM_FEATURE_CALLBACK)
+	uint16_t comm_feature;
+	#endif
+
+	#if defined(CDC_SET_LINE_CODING_CALLBACK) || defined(CDC_GET_LINE_CODING_CALLBACK)
+	struct cdc_line_coding line_coding;
+	#endif
+} transfer_data;
+
+#if defined(CDC_SET_COMM_FEATURE_CALLBACK) || defined(CDC_CLEAR_COMM_FEATURE_CALLBACK)
+static uint8_t set_or_clear_request;
+static void set_or_clear_comm_feature_callback(bool transfer_ok, void *context)
+{
+	/* Only ABSTRACT_STATE is supported here. */
+
+	if (!transfer_ok)
+		return;
+
+	bool idle_setting = (transfer_data.comm_feature & 1) != 0;
+	bool data_multiplexed_state = (transfer_data.comm_feature & 2) != 0;
+
+	if (set_or_clear_request == CDC_SET_COMM_FEATURE) {
+		CDC_SET_COMM_FEATURE_CALLBACK(transfer_interface,
+		                              idle_setting,
+		                              data_multiplexed_state);
+	}
+	else {
+		/* request == CDC_CLEAR_COMM_FEATURE */
+		CDC_CLEAR_COMM_FEATURE_CALLBACK(transfer_interface,
+		                                idle_setting,
+		                                data_multiplexed_state);
+	}
+}
+#endif
+
+#if defined(CDC_SET_LINE_CODING_CALLBACK)
+static void set_line_coding(bool transfer_ok, void *context) {
+	if (!transfer_ok)
+		return;
+
+	CDC_SET_LINE_CODING_CALLBACK(transfer_interface,
+	                             &transfer_data.line_coding);
+}
+#endif
+
+
+uint8_t process_cdc_setup_request(const struct setup_packet *setup)
+{
+	/* The following comes from the CDC spec 1.1, chapter 6. */
+
+	uint8_t interface = setup->wIndex;
+
+#ifdef MULTI_CLASS_DEVICE
+	/* Check the interface first to make sure the destination is a
+	 * CDC interface. Multi-class devices will need to call
+	 * cdc_set_interface_list() first.
+	 */
+	if (!interface_is_cdc(interface))
+		return -1;
+#endif
+
+#ifdef CDC_SEND_ENCAPSULATED_COMMAND_CALLBACK
+	if (setup->bRequest == CDC_SEND_ENCAPSULATED_COMMAND &&
+	    setup->REQUEST.bmRequestType == 0x21) {
+		int8_t res;
+		res = CDC_SEND_ENCAPSULATED_COMMAND_CALLBACK(interface,
+                                                             setup->wLength);
+		if (res < 0)
+			return -1;
+		return 0;
+	}
+#endif
+
+#ifdef CDC_GET_ENCAPSULATED_RESPONSE_CALLBACK
+	if (setup->bRequest == CDC_GET_ENCAPSULATED_RESPONSE &&
+	    setup->REQUEST.bmRequestType == 0xa1) {
+		const void *response;
+		int16_t len;
+		usb_ep0_data_stage_callback callback;
+		void *context;
+
+		len = CDC_GET_ENCAPSULATED_RESPONSE_CALLBACK(
+		                                interface, setup->wLength,
+		                                &response, &callback,
+		                                &context);
+		if (len < 0)
+			return -1;
+
+		usb_send_data_stage((void*)response,
+		                    MIN(len, setup->wLength),
+		                    callback, context);
+		return 0;
+	}
+#endif
+
+#ifdef CDC_SET_COMM_FEATURE_CALLBACK
+	if (setup->bRequest == CDC_SET_COMM_FEATURE &&
+	    setup->REQUEST.bmRequestType == 0x21) {
+
+		/* Only ABSTRACT_STATE feature is supported. If you need
+		 * something else here, get in contact with Signal 11. */
+		if (setup->wValue != CDC_FEATURE_ABSTRACT_STATE)
+			return -1;
+
+		transfer_interface = interface;
+		set_or_clear_request = setup->bRequest;
+		usb_start_receive_ep0_data_stage((char*) &transfer_data.comm_feature,
+		                                 sizeof(transfer_data.comm_feature),
+		                                 set_or_clear_comm_feature_callback,
+		                                 NULL);
+		return 0;
+	}
+#endif
+
+#ifdef CDC_CLEAR_COMM_FEATURE_CALLBACK
+	if (setup->bRequest == CDC_CLEAR_COMM_FEATURE &&
+	    setup->REQUEST.bmRequestType == 0x21) {
+
+		/* Only ABSTRACT_STATE feature is supported. If you need
+		 * something else here, get in contact with Signal 11. */
+		if (setup->wValue != CDC_FEATURE_ABSTRACT_STATE)
+			return -1;
+
+		transfer_interface = interface;
+		set_or_clear_request = setup->bRequest;
+		usb_start_receive_ep0_data_stage((char*)&transfer_data.comm_feature,
+		                                 sizeof(transfer_data.comm_feature),
+		                                 set_or_clear_comm_feature_callback,
+		                                 NULL);
+		return 0;
+	}
+#endif
+
+#ifdef CDC_GET_COMM_FEATURE_CALLBACK
+	if (setup->bRequest == CDC_GET_COMM_FEATURE &&
+	    setup->REQUEST.bmRequestType == 0xa1) {
+		bool idle_setting;
+		bool data_multiplexed_state;
+		int8_t res;
+
+		/* Only ABSTRACT_STATE feature is supported. If you need
+		 * something else here, get in contact with Signal 11. */
+		if (setup->wValue != CDC_FEATURE_ABSTRACT_STATE)
+			return -1;
+
+		res = CDC_GET_COMM_FEATURE_CALLBACK(
+		                                interface,
+		                                &idle_setting,
+		                                &data_multiplexed_state);
+		if (res < 0)
+			return -1;
+
+		transfer_data.comm_feature =
+			(uint16_t) idle_setting |
+				(uint16_t) data_multiplexed_state << 1;
+
+		usb_send_data_stage((char*)&transfer_data.comm_feature,
+		                    MIN(setup->wLength,
+		                        sizeof(transfer_data.comm_feature)),
+		                    NULL/*callback*/, NULL);
+		return 0;
+	}
+#endif
+
+#ifdef CDC_SET_LINE_CODING_CALLBACK
+	if (setup->bRequest == CDC_SET_LINE_CODING &&
+	    setup->REQUEST.bmRequestType == 0x21) {
+
+		transfer_interface = interface;
+		usb_start_receive_ep0_data_stage(
+		                      (char*)&transfer_data.line_coding,
+		                      MIN(setup->wLength,
+		                          sizeof(transfer_data.line_coding)),
+		                      set_line_coding, NULL);
+		return 0;
+	}
+#endif
+
+#ifdef CDC_GET_LINE_CODING_CALLBACK
+	if (setup->bRequest == CDC_GET_LINE_CODING &&
+	    setup->REQUEST.bmRequestType == 0xa1) {
+		int8_t res;
+
+		res = CDC_GET_LINE_CODING_CALLBACK(
+		                                interface,
+		                                &transfer_data.line_coding);
+		if (res < 0)
+			return -1;
+
+		usb_send_data_stage((char*)&transfer_data.line_coding,
+		                    MIN(setup->wLength,
+		                        sizeof(transfer_data.line_coding)),
+		                    /*callback*/NULL, NULL);
+		return 0;
+	}
+#endif
+
+#ifdef CDC_SET_CONTROL_LINE_STATE_CALLBACK
+	if (setup->bRequest == CDC_SET_CONTROL_LINE_STATE &&
+	    setup->REQUEST.bmRequestType == 0x21) {
+		int8_t res;
+		bool dtr = (setup->wValue & 0x1) != 0;
+		bool rts = (setup->wValue & 0x2) != 0;
+
+		res = CDC_SET_CONTROL_LINE_STATE_CALLBACK(interface, dtr, rts);
+		if (res < 0)
+			return -1;
+
+		/* Return zero-length packet. No data stage. */
+		usb_send_data_stage(NULL, 0, NULL, NULL);
+
+		return 0;
+	}
+#endif
+
+#ifdef CDC_SEND_BREAK_CALLBACK
+	if (setup->bRequest == CDC_SEND_BREAK &&
+	    setup->REQUEST.bmRequestType == 0x21) {
+		int8_t res;
+
+		res = CDC_SEND_BREAK_CALLBACK(interface,
+		                              setup->wValue /*duration*/);
+		if (res < 0)
+			return -1;
+
+		/* Return zero-length packet. No data stage. */
+		usb_send_data_stage(NULL, 0, NULL, NULL);
+
+		return 0;
+	}
+#endif
+
+	return -1;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usb/src/usb_hal.h	Sat Feb 18 16:14:32 2017 +0000
@@ -0,0 +1,580 @@
+/*
+ *  M-Stack Hardware Abstraction
+ *  Copyright (C) 2013 Alan Ott <alan@signal11.us>
+ *  Copyright (C) 2013 Signal 11 Software
+ *
+ *  2013-04-08
+ *
+ *  M-Stack is free software: you can redistribute it and/or modify it under
+ *  the terms of the GNU Lesser General Public License as published by the
+ *  Free Software Foundation, version 3; or the Apache License, version 2.0
+ *  as published by the Apache Software Foundation.  If you have purchased a
+ *  commercial license for this software from Signal 11 Software, your
+ *  commerical license superceeds the information in this header.
+ *
+ *  M-Stack is distributed in the hope that it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
+ *  License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public License
+ *  along with this software.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ *  You should have received a copy of the Apache License, verion 2.0 along
+ *  with this software.  If not, see <http://www.apache.org/licenses/>.
+ */
+
+#ifndef USB_HAL_H__
+#define UAB_HAL_H__
+
+#ifdef _PIC14E
+#define NEEDS_PULL /* Whether to pull up D+/D- with SFR_PULL_EN. */
+#define HAS_LOW_SPEED
+#define NEEDS_CLEAR_STALL
+
+#define BDNADR_TYPE              uint16_t
+#define PHYS_ADDR(VIRTUAL_ADDR)  pic16_linear_addr(VIRTUAL_ADDR)
+
+#define SFR_FULL_SPEED_EN        UCFGbits.FSEN
+#define SFR_PULL_EN              UCFGbits.UPUEN
+#define SET_PING_PONG_MODE(n)    do { UCFGbits.PPB0 = n & 1; UCFGbits.PPB1 = (n & 2)? 1: 0; } while (0)
+
+#define SFR_USB_INTERRUPT_FLAGS  UIR
+#define SFR_USB_RESET_IF         UIRbits.URSTIF
+#define SFR_USB_STALL_IF         UIRbits.STALLIF
+#define SFR_USB_TOKEN_IF         UIRbits.TRNIF
+#define SFR_USB_SOF_IF           UIRbits.SOFIF
+#define SFR_USB_IF               PIR2bits.USBIF
+
+#define SFR_USB_INTERRUPT_EN     UIE
+#define SFR_TRANSFER_IE          UIEbits.TRNIE
+#define SFR_STALL_IE             UIEbits.STALLIE
+#define SFR_RESET_IE             UIEbits.URSTIE
+#define SFR_SOF_IE               UIEbits.SOFIE
+#define SFR_USB_IE               PIE2bits.USBIE
+
+#define SFR_USB_EXTENDED_INTERRUPT_EN UEIE
+
+#define SFR_EP_MGMT_TYPE         UEP1bits_t /* TODO test */
+#define UEP_REG_STRIDE 1
+#define SFR_EP_MGMT(ep)          ((SFR_EP_MGMT_TYPE*) (&UEP0 + UEP_REG_STRIDE * (ep)))
+#define SFR_EP_MGMT_HANDSHAKE    EPHSHK
+#define SFR_EP_MGMT_STALL        EPSTALL
+#define SFR_EP_MGMT_OUT_EN       EPOUTEN
+#define SFR_EP_MGMT_IN_EN        EPINEN
+#define SFR_EP_MGMT_CON_DIS      EPCONDIS /* disable control transfers */
+
+#define SFR_USB_ADDR             UADDR
+#define SFR_USB_EN               UCONbits.USBEN
+#define SFR_USB_PKT_DIS          UCONbits.PKTDIS
+#define SFR_USB_PING_PONG_RESET  UCONbits.PPBRST
+
+#define SFR_USB_STATUS           USTAT
+#define SFR_USB_STATUS_EP        USTATbits.ENDP
+#define SFR_USB_STATUS_DIR       USTATbits.DIR
+#define SFR_USB_STATUS_PPBI      USTATbits.PPBI
+
+#define CLEAR_ALL_USB_IF()       SFR_USB_INTERRUPT_FLAGS = 0 /*TODO TEST!*/
+#define CLEAR_USB_RESET_IF()     SFR_USB_RESET_IF = 0
+#define CLEAR_USB_STALL_IF()     SFR_USB_STALL_IF = 0
+#define CLEAR_USB_TOKEN_IF()     SFR_USB_TOKEN_IF = 0
+#define CLEAR_USB_SOF_IF()       SFR_USB_SOF_IF = 0
+
+/* Buffer Descriptor BDnSTAT flags. On Some MCUs, apparently, when handing
+ * a buffer descriptor to the SIE, there's a race condition that can happen
+ * if you don't set the BDnSTAT byte as a single operation. This was observed
+ * on the PIC18F46J50 when sending 8-byte IN-transactions while doing control
+ * transfers. */
+#define BDNSTAT_UOWN   0x80
+#define BDNSTAT_DTS    0x40
+#define BDNSTAT_DTSEN  0x08
+#define BDNSTAT_BSTALL 0x04
+#define BDNCNT_MASK    0x03ff /* 10 bits of BDnCNT in BDnSTAT_CNT */
+
+/* Buffer Descriptor
+ *
+ * This represents the Buffer Descriptor as laid out in the PIC18F4550
+ * Datasheet.  A buffer descriptor contains data about either an in or out
+ * endpoint buffer.  Bufffer descriptors are almost the same on all 8-bit
+ * parts, best I've so far been able to tell.  The fields that aren't in the
+ * newer datasheets like KEN and INCDIS aren't used, so it doesn't hurt to
+ * have them here on those parts.
+ *
+ * While the layout is very similar on 16-bit parts, a different struct is
+ * required on 16-bit for several reasons, including endianness (the 8-bit
+ * BC/BDnSTAT bits are effectively big-endian), and the ability to optimize
+ * for each platform (eg: writing BDnSTAT/BDnCNT as a 16-bit word on 16-bit
+ * platforms).
+ */
+struct buffer_descriptor {
+	union {
+		struct {
+			/* When receiving from the SIE. (USB Mode) */
+			uint8_t BC8 : 1;
+			uint8_t BC9 : 1;
+			uint8_t PID : 4; /* See enum PID */
+			uint8_t reserved: 1;
+			uint8_t UOWN : 1;
+		};
+		struct {
+			/* When giving to the SIE (CPU Mode) */
+			uint8_t /*BC8*/ : 1;
+			uint8_t /*BC9*/ : 1;
+			uint8_t BSTALL : 1;
+			uint8_t DTSEN : 1;
+			uint8_t INCDIS : 1;
+			uint8_t KEN : 1;
+			uint8_t DTS : 1;
+			uint8_t /*UOWN*/ : 1;
+		};
+		uint8_t BDnSTAT;
+	} STAT;
+	uint8_t BDnCNT;
+	BDNADR_TYPE BDnADR; /* BDnADRL and BDnADRH; */
+};
+
+#ifdef LARGE_EP
+#define SET_BDN(REG, FLAGS, CNT) do { (REG).BDnCNT = (CNT); \
+           (REG).STAT.BDnSTAT = (FLAGS) | ((CNT) & 0x300) >> 8; } while(0)
+#define BDN_LENGTH(REG) ( ((REG).STAT.BDnSTAT & 0x03) << 8 | (REG).BDnCNT )
+#else
+#define SET_BDN(REG, FLAGS, CNT) do { (REG).BDnCNT = (CNT); \
+                                      (REG).STAT.BDnSTAT = (FLAGS); } while(0)
+#define BDN_LENGTH(REG) (REG.BDnCNT)
+#endif
+
+#if defined(_16F1459) || defined(_16F1454)
+#define BD_ADDR 0x2000
+#define BUFFER_ADDR 0x2080
+#else
+#error "CPU not supported yet"
+#endif
+
+#define PPB_NONE         0
+#define PPB_EPO_OUT_ONLY 1
+#define PPB_ALL          2
+#define PPB_EPN_ONLY     3
+
+#if defined __XC8
+	#define memcpy_from_rom(x,y,z) memcpy(x,y,z)
+	#define FAR
+	#define BD_ATTR_TAG @##BD_ADDR
+	#ifdef BUFFER_ADDR
+		#define XC8_BUFFER_ADDR_TAG @##BUFFER_ADDR
+	#else
+		#define XC8_BUFFER_ADDR_TAG
+	#endif
+#endif
+
+#elif _PIC18
+
+#define NEEDS_PULL /* Whether to pull up D+/D- with SFR_PULL_EN. */
+#define HAS_LOW_SPEED
+#define HAS_ON_CHIP_XCVR_DIS
+#define NEEDS_CLEAR_STALL
+
+#define BDNADR_TYPE              uint16_t
+#define PHYS_ADDR(VIRTUAL_ADDR)  (VIRTUAL_ADDR)
+
+#define SFR_FULL_SPEED_EN        UCFGbits.FSEN
+#define SFR_PULL_EN              UCFGbits.UPUEN
+#define SFR_ON_CHIP_XCVR_DIS     UCFGbits.UTRDIS
+#define SET_PING_PONG_MODE(n)    do { UCFGbits.PPB0 = n & 1; UCFGbits.PPB1 = (n & 2)? 1: 0; } while (0)
+
+#define SFR_USB_INTERRUPT_FLAGS  UIR
+#define SFR_USB_RESET_IF         UIRbits.URSTIF
+#define SFR_USB_STALL_IF         UIRbits.STALLIF
+#define SFR_USB_TOKEN_IF         UIRbits.TRNIF
+#define SFR_USB_SOF_IF           UIRbits.SOFIF
+#define SFR_USB_IF               PIR2bits.USBIF
+
+#define SFR_USB_INTERRUPT_EN     UIE
+#define SFR_TRANSFER_IE          UIEbits.TRNIE
+#define SFR_STALL_IE             UIEbits.STALLIE
+#define SFR_RESET_IE             UIEbits.URSTIE
+#define SFR_SOF_IE               UIEbits.SOFIE
+#define SFR_USB_IE               PIE2bits.USBIE
+
+#define SFR_USB_EXTENDED_INTERRUPT_EN UEIE
+
+#define SFR_EP_MGMT_TYPE         UEP1bits_t /* TODO test */
+#define UEP_REG_STRIDE 1
+#define SFR_EP_MGMT(ep)          ((SFR_EP_MGMT_TYPE*) (&UEP0 + UEP_REG_STRIDE * (ep)))
+#define SFR_EP_MGMT_HANDSHAKE    EPHSHK
+#define SFR_EP_MGMT_STALL        EPSTALL
+#define SFR_EP_MGMT_OUT_EN       EPOUTEN
+#define SFR_EP_MGMT_IN_EN        EPINEN
+#define SFR_EP_MGMT_CON_DIS      EPCONDIS /* disable control transfers */
+
+#define SFR_USB_ADDR             UADDR
+#define SFR_USB_EN               UCONbits.USBEN
+#define SFR_USB_PKT_DIS          UCONbits.PKTDIS
+#define SFR_USB_PING_PONG_RESET  UCONbits.PPBRST
+
+#define SFR_USB_STATUS           USTAT
+#define SFR_USB_STATUS_EP        USTATbits.ENDP
+#define SFR_USB_STATUS_DIR       USTATbits.DIR
+#define SFR_USB_STATUS_PPBI      USTATbits.PPBI
+
+#define CLEAR_ALL_USB_IF()       SFR_USB_INTERRUPT_FLAGS = 0 /*TODO TEST!*/
+#define CLEAR_USB_RESET_IF()     SFR_USB_RESET_IF = 0
+#define CLEAR_USB_STALL_IF()     SFR_USB_STALL_IF = 0
+#define CLEAR_USB_TOKEN_IF()     SFR_USB_TOKEN_IF = 0
+#define CLEAR_USB_SOF_IF()       SFR_USB_SOF_IF = 0
+
+/* Buffer Descriptor BDnSTAT flags. On Some MCUs, apparently, when handing
+ * a buffer descriptor to the SIE, there's a race condition that can happen
+ * if you don't set the BDnSTAT byte as a single operation. This was observed
+ * on the PIC18F46J50 when sending 8-byte IN-transactions while doing control
+ * transfers. */
+#define BDNSTAT_UOWN   0x80
+#define BDNSTAT_DTS    0x40
+#define BDNSTAT_DTSEN  0x08
+#define BDNSTAT_BSTALL 0x04
+#define BDNCNT_MASK    0x03ff /* 10 bits of BDnCNT in BDnSTAT_CNT */
+
+/* Buffer Descriptor
+ *
+ * This represents the Buffer Descriptor as laid out in the PIC18F4550
+ * Datasheet.  A buffer descriptor contains data about either an in or out
+ * endpoint buffer.  Bufffer descriptors are almost the same on all 8-bit
+ * parts, best I've so far been able to tell.  The fields that aren't in the
+ * newer datasheets like KEN and INCDIS aren't used, so it doesn't hurt to
+ * have them here on those parts.
+ *
+ * While the layout is very similar on 16-bit parts, a different struct is
+ * required on 16-bit for several reasons, including endianness (the 8-bit
+ * BC/BDnSTAT bits are effectively big-endian), and the ability to optimize
+ * for each platform (eg: writing BDnSTAT/BDnCNT as a 16-bit word on 16-bit
+ * platforms).
+ */
+struct buffer_descriptor {
+	union {
+		struct {
+			/* When receiving from the SIE. (USB Mode) */
+			uint8_t BC8 : 1;
+			uint8_t BC9 : 1;
+			uint8_t PID : 4; /* See enum PID */
+			uint8_t reserved: 1;
+			uint8_t UOWN : 1;
+		};
+		struct {
+			/* When giving to the SIE (CPU Mode) */
+			uint8_t /*BC8*/ : 1;
+			uint8_t /*BC9*/ : 1;
+			uint8_t BSTALL : 1;
+			uint8_t DTSEN : 1;
+			uint8_t INCDIS : 1;
+			uint8_t KEN : 1;
+			uint8_t DTS : 1;
+			uint8_t /*UOWN*/ : 1;
+		};
+		uint8_t BDnSTAT;
+	} STAT;
+	uint8_t BDnCNT;
+	BDNADR_TYPE BDnADR; /* BDnADRL and BDnADRH; */
+};
+
+#ifdef LARGE_EP
+#define SET_BDN(REG, FLAGS, CNT) do { (REG).BDnCNT = (CNT); \
+           (REG).STAT.BDnSTAT = (FLAGS) | ((CNT) & 0x300) >> 8; } while(0)
+#define BDN_LENGTH(REG) ( ((REG).STAT.BDnSTAT & 0x03) << 8 | (REG).BDnCNT )
+#else
+#define SET_BDN(REG, FLAGS, CNT) do { (REG).BDnCNT = (CNT); \
+                                      (REG).STAT.BDnSTAT = (FLAGS); } while(0)
+#define BDN_LENGTH(REG) (REG.BDnCNT)
+#endif
+
+#ifdef _18F46J50
+#define BD_ADDR 0x400
+//#undef BUFFER_ADDR
+#else
+#error "CPU not supported yet"
+#endif
+
+#define PPB_NONE         0
+#define PPB_EPO_OUT_ONLY 1
+#define PPB_ALL          2
+#define PPB_EPN_ONLY     3
+
+/* Compiler stuff. Probably should be somewhere else. */
+#ifdef __C18
+	#define FAR far
+	#define memcpy_from_rom(x,y,z) memcpypgm2ram(x,(rom void*)y,z)
+	#define BD_ATTR_TAG
+	#define XC8_BUFFER_ADDR_TAG
+#elif defined __XC8
+	#define memcpy_from_rom(x,y,z) memcpy(x,y,z)
+	#define FAR
+	#define BD_ATTR_TAG @##BD_ADDR
+	#ifdef BUFFER_ADDR
+		#define XC8_BUFFER_ADDR_TAG @##BUFFER_ADDR
+	#else
+		#define XC8_BUFFER_ADDR_TAG
+	#endif
+#endif
+
+#elif __XC16__
+
+#define USB_NEEDS_POWER_ON
+#define USB_NEEDS_SET_BD_ADDR_REG
+#define HAS_ON_CHIP_XCVR_DIS
+
+#define BDNADR_TYPE              void *
+#define PHYS_ADDR(VIRTUAL_ADDR)  (VIRTUAL_ADDR)
+
+#define SFR_PULL_EN              /* Not used on PIC24 */
+#define SFR_ON_CHIP_XCVR_DIS     U1CNFG2bits.UTRDIS
+#define SET_PING_PONG_MODE(n)    U1CNFG1bits.PPB = n
+
+#define SFR_USB_INTERRUPT_FLAGS  U1IR
+#define SFR_USB_RESET_IF         U1IRbits.URSTIF
+#define SFR_USB_STALL_IF         U1IRbits.STALLIF
+#define SFR_USB_TOKEN_IF         U1IRbits.TRNIF
+#define SFR_USB_SOF_IF           U1IRbits.SOFIF
+#define SFR_USB_IF               IFS5bits.USB1IF
+
+#define SFR_USB_INTERRUPT_EN     U1IE
+#define SFR_TRANSFER_IE          U1IEbits.TRNIE
+#define SFR_STALL_IE             U1IEbits.STALLIE
+#define SFR_RESET_IE             U1IEbits.URSTIE
+#define SFR_SOF_IE               U1IEbits.SOFIE
+#define SFR_USB_IE               IEC5bits.USB1IE
+
+#define SFR_USB_EXTENDED_INTERRUPT_EN U1EIE
+
+#define SFR_EP_MGMT_TYPE         U1EP1BITS
+#define UEP_REG_STRIDE 1
+#define SFR_EP_MGMT(ep)          ((SFR_EP_MGMT_TYPE*) (&U1EP0 + UEP_REG_STRIDE * (ep)))
+#define SFR_EP_MGMT_HANDSHAKE    EPHSHK
+#define SFR_EP_MGMT_STALL        EPSTALL
+#define SFR_EP_MGMT_IN_EN        EPTXEN   /* In/out from HOST perspective */
+#define SFR_EP_MGMT_OUT_EN       EPRXEN
+#define SFR_EP_MGMT_CON_DIS      EPCONDIS /* disable control transfers */
+                                 /* Ignoring RETRYDIS and LSPD for now */
+#define SFR_USB_ADDR             U1ADDR
+#define SFR_USB_EN               U1CONbits.USBEN
+#define SFR_USB_PKT_DIS          U1CONbits.PKTDIS
+#define SFR_USB_PING_PONG_RESET  U1CONbits.PPBRST
+
+
+#define SFR_USB_STATUS           U1STAT
+#define SFR_USB_STATUS_EP        U1STATbits.ENDPT
+#define SFR_USB_STATUS_DIR       U1STATbits.DIR
+#define SFR_USB_STATUS_PPBI      U1STATbits.PPBI
+
+#define SFR_USB_POWER            U1PWRCbits.USBPWR
+#define SFR_BD_ADDR_REG          U1BDTP1
+
+#define BDnCNT                   STAT.BDnCNT_byte /* buffer descriptor */
+
+#define SFR_OTGEN                U1OTGCONbits.OTGEN
+#define SFR_DPPULUP              U1OTGCONbits.DPPULUP
+
+#define CLEAR_ALL_USB_IF()       do { SFR_USB_INTERRUPT_FLAGS = 0xff; U1EIR = 0xff; } while(0)
+#define CLEAR_USB_RESET_IF()     SFR_USB_INTERRUPT_FLAGS = 0x1
+#define CLEAR_USB_STALL_IF()     SFR_USB_INTERRUPT_FLAGS = 0x80
+#define CLEAR_USB_TOKEN_IF()     SFR_USB_INTERRUPT_FLAGS = 0x08
+#define CLEAR_USB_SOF_IF()       SFR_USB_INTERRUPT_FLAGS = 0x4
+
+#define BDNSTAT_UOWN   0x8000
+#define BDNSTAT_DTS    0x4000
+#define BDNSTAT_DTSEN  0x0800
+#define BDNSTAT_BSTALL 0x0400
+
+/* Buffer Descriptor
+ *
+ * This struct represents BDnSTAT in the datasheet. See the comment in the
+ * 8-bit section above for more information on buffer descriptors.
+ */
+struct buffer_descriptor {
+	union {
+		struct {
+			/* When receiving from the SIE. (USB Mode) */
+			uint16_t BC : 10;
+			uint16_t PID : 4; /* See enum PID */
+			uint16_t DTS: 1;
+			uint16_t UOWN : 1;
+		};
+		struct {
+			/* When giving to the SIE (CPU Mode) */
+			uint16_t /*BC*/ : 10;
+			uint16_t BSTALL : 1;
+			uint16_t DTSEN : 1;
+			uint16_t reserved : 2;
+			uint16_t DTS : 1;
+			uint16_t /*UOWN*/ : 1;
+		};
+		struct {
+			uint8_t BDnSTAT_lsb;
+			uint8_t BDnSTAT; /* High byte, where the flags are */
+		};
+		uint16_t BDnSTAT_CNT; /* BDnSTAT and BDnCNT as a 16-bit */
+	}STAT;
+	BDNADR_TYPE BDnADR;
+};
+
+#define SET_BDN(REG, FLAGS, CNT) \
+                     do { (REG).STAT.BDnSTAT_CNT = (FLAGS) | (CNT); } while(0)
+
+#ifdef LARGE_EP
+	#define BDN_LENGTH(REG) (REG.STAT.BC)
+#else
+	#define BDN_LENGTH(REG) (REG.STAT.BDnSTAT_lsb)
+#endif
+
+#define BD_ADDR
+#define BUFFER_ADDR
+#define BD_ATTR_TAG __attribute__((aligned(512)))
+#define XC8_BUFFER_ADDR_TAG
+
+#define PPB_NONE         0
+#define PPB_EPO_OUT_ONLY 1
+#define PPB_ALL          2
+#define PPB_EPN_ONLY     3
+
+/* Compiler stuff. Probably should be somewhere else. */
+#define FAR
+#define memcpy_from_rom(x,y,z) memcpy(x,y,z)
+
+#elif __XC32__
+
+#define USB_NEEDS_POWER_ON
+#define USB_NEEDS_SET_BD_ADDR_REG
+#define USB_FULL_PING_PONG_ONLY
+
+#define BDNADR_TYPE              uint32_t /* physical address */
+#define PHYS_ADDR(VIRTUAL_ADDR)  KVA_TO_PA(VIRTUAL_ADDR)
+
+#define SFR_PULL_EN              /* Not used on PIC32MX */
+#define SFR_ON_CHIP_XCVR_DIS     U1CNFG2bits.UTRDIS
+#define SET_PING_PONG_MODE(n)    U1CNFG1bits.PPB = n
+
+#define SFR_USB_INTERRUPT_FLAGS  U1IR
+#define SFR_USB_RESET_IF         U1IRbits.URSTIF
+#define SFR_USB_STALL_IF         U1IRbits.STALLIF
+#define SFR_USB_TOKEN_IF         U1IRbits.TRNIF
+#define SFR_USB_SOF_IF           U1IRbits.SOFIF
+#define SFR_USB_IF               IFS1bits.USBIF
+
+#define SFR_USB_INTERRUPT_EN     U1IE
+#define SFR_TRANSFER_IE          U1IEbits.TRNIE
+#define SFR_STALL_IE             U1IEbits.STALLIE
+#define SFR_RESET_IE             U1IEbits.URSTIE
+#define SFR_SOF_IE               U1IEbits.SOFIE
+#define SFR_USB_IE               IEC1bits.USBIE
+
+#define SFR_USB_EXTENDED_INTERRUPT_EN U1EIE
+
+#define SFR_EP_MGMT_TYPE         __U1EP1bits_t
+#define UEP_REG_STRIDE           4
+#define SFR_EP_MGMT(ep)          ((SFR_EP_MGMT_TYPE*) (&U1EP0 + UEP_REG_STRIDE * (ep)))
+#define SFR_EP_MGMT_HANDSHAKE    EPHSHK
+#define SFR_EP_MGMT_STALL        EPSTALL
+#define SFR_EP_MGMT_IN_EN        EPTXEN   /* In/out from HOST perspective */
+#define SFR_EP_MGMT_OUT_EN       EPRXEN
+#define SFR_EP_MGMT_CON_DIS      EPCONDIS /* disable control transfers */
+                                 /* Ignoring RETRYDIS and LSPD for now */
+#define SFR_USB_ADDR             U1ADDR
+#define SFR_USB_EN               U1CONbits.USBEN
+#define SFR_USB_PKT_DIS          U1CONbits.PKTDIS
+#define SFR_USB_PING_PONG_RESET  U1CONbits.PPBRST
+
+
+#define SFR_USB_STATUS           U1STAT
+#define SFR_USB_STATUS_EP        U1STATbits.ENDPT
+#define SFR_USB_STATUS_DIR       U1STATbits.DIR
+#define SFR_USB_STATUS_PPBI      U1STATbits.PPBI
+
+#define SFR_USB_POWER            U1PWRCbits.USBPWR
+#define SFR_BD_ADDR_REG1         U1BDTP1
+#define SFR_BD_ADDR_REG2         U1BDTP2
+#define SFR_BD_ADDR_REG3         U1BDTP3
+
+#define SFR_OTGEN                U1OTGCONbits.OTGEN
+#define SFR_DPPULUP              U1OTGCONbits.DPPULUP
+
+#define CLEAR_ALL_USB_IF()       do { SFR_USB_INTERRUPT_FLAGS = 0xff; U1EIR = 0xff; } while(0)
+#define CLEAR_USB_RESET_IF()     SFR_USB_INTERRUPT_FLAGS = 0x1
+#define CLEAR_USB_STALL_IF()     SFR_USB_INTERRUPT_FLAGS = 0x80
+#define CLEAR_USB_TOKEN_IF()     SFR_USB_INTERRUPT_FLAGS = 0x08
+#define CLEAR_USB_SOF_IF()       SFR_USB_INTERRUPT_FLAGS = 0x4
+
+#define BDNSTAT_UOWN   0x0080
+#define BDNSTAT_DTS    0x0040
+#define BDNSTAT_DTSEN  0x0008
+#define BDNSTAT_BSTALL 0x0004
+
+/* Buffer Descriptor
+ *
+ * This struct represents BDnSTAT in the datasheet. See the comment in the
+ * 8-bit section above for more information on buffer descriptors.
+ */
+struct buffer_descriptor {
+	union {
+		struct {
+			/* When receiving from the SIE. (USB Mode) */
+			uint32_t : 2;
+			uint32_t PID : 4; /* See enum PID */
+			uint32_t DTS: 1;
+			uint32_t UOWN : 1;
+
+			uint32_t : 8;
+			uint32_t BDnCNT : 10;
+			uint32_t : 6;
+
+		};
+		struct {
+			/* When giving to the SIE (CPU Mode) */
+			uint32_t : 2;
+			uint32_t BSTALL : 1;
+			uint32_t DTSEN : 1;    /* DTS in datasheet */
+			uint32_t reserved : 2; /* NINC, KEEP */
+			uint32_t DTS : 1;      /* DATA0/1 in datasheet */
+			uint32_t /*UOWN*/ : 1;
+
+			uint32_t : 8;
+			uint32_t /*BDnCNT*/ : 10;
+			uint32_t :6;
+		};
+		struct {
+			uint16_t : 16;
+			uint16_t BDnSTAT; /* Low word, where the flags are */
+		};
+		uint32_t BDnSTAT_CNT; /* BDnSTAT and BDnCNT as a 16-bit */
+	}STAT;
+	BDNADR_TYPE BDnADR;
+};
+
+#define SET_BDN(REG, FLAGS, CNT) \
+                     do { (REG).STAT.BDnSTAT_CNT = (FLAGS) | ((CNT)<<16); } while(0)
+
+#ifdef LARGE_EP
+	#define BDN_LENGTH(REG) (REG.STAT.BDnCNT)
+#else
+	#define BDN_LENGTH(REG) (REG.STAT.BDnCNT)
+#endif
+
+
+#define BD_ADDR
+#define BUFFER_ADDR
+#define BD_ATTR_TAG __attribute__((aligned(512), coherent))
+#define XC8_BUFFER_ADDR_TAG __attribute__((coherent))
+
+#define PPB_NONE         0 /* Unused on PIC32 */
+#define PPB_EPO_OUT_ONLY 1 /* Unused on PIC32 */
+#define PPB_ALL          2 /* Unused on PIC32 */
+#define PPB_EPN_ONLY     3
+
+/* Compiler stuff. Probably should be somewhere else. */
+#define FAR
+#define memcpy_from_rom(x,y,z) memcpy(x,y,z)
+
+
+#else
+	#error "Your architecture is not supported"
+#endif
+
+
+
+#endif /* USB_HAL_H__ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usb/src/usb_winusb.c	Sat Feb 18 16:14:32 2017 +0000
@@ -0,0 +1,88 @@
+/*
+ *  M-Stack Automatic WinUSB Support
+ *  Copyright (C) 2013 Alan Ott <alan@signal11.us>
+ *  Copyright (C) 2013 Signal 11 Software
+ *
+ *  2013-10-12
+ *
+ *  M-Stack is free software: you can redistribute it and/or modify it under
+ *  the terms of the GNU Lesser General Public License as published by the
+ *  Free Software Foundation, version 3; or the Apache License, version 2.0
+ *  as published by the Apache Software Foundation.  If you have purchased a
+ *  commercial license for this software from Signal 11 Software, your
+ *  commerical license superceeds the information in this header.
+ *
+ *  M-Stack is distributed in the hope that it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
+ *  License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public License
+ *  along with this software.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ *  You should have received a copy of the Apache License, verion 2.0 along
+ *  with this software.  If not, see <http://www.apache.org/licenses/>.
+ */
+
+#include <stdint.h>
+#include "usb_config.h"
+#include "usb_microsoft.h"
+#include "usb_winusb.h"
+
+#ifdef AUTOMATIC_WINUSB_SUPPORT
+
+/* Microsoft-specific descriptors for automatic binding of the WinUSB driver.
+ * See docs/winusb.txt for details. */
+struct extended_compat_descriptor_packet {
+	struct microsoft_extended_compat_header header;
+	struct microsoft_extended_compat_function function;
+};
+
+static struct extended_compat_descriptor_packet
+	this_extended_compat_descriptor =
+{
+	/* Header */
+	{
+	sizeof(struct extended_compat_descriptor_packet), /* dwLength */
+	0x0100, /* dwVersion*/
+	0x0004, /* wIndex: 0x0004 = Extended Compat ID */
+	1,      /* bCount, number of custom property sections */
+	{0},    /* reserved[7] */
+	},
+
+	/* Function */
+	{
+	0x0,      /* bFirstInterfaceNumber */
+	0x1,      /* reserved. Set to 1 in the Microsoft example */
+	"WINUSB", /* compatibleID[8] */
+	"",       /* subCompatibleID[8] */
+	{0},      /* reserved2[6] */
+	},
+};
+
+static struct microsoft_extended_properties_header
+				interface_0_property_descriptor =
+{
+	sizeof(interface_0_property_descriptor), /* dwLength */
+	0x0100, /* bcdVersion */
+	0x0005, /* wIndex, Extended Properties descriptor */
+	0x0,    /* bCount, Number of custom property sections */
+};
+
+uint16_t m_stack_winusb_get_microsoft_compat(uint8_t interface,
+                                              const void **descriptor)
+{
+	/* Check the interface here for composite devices. */
+	*descriptor = &this_extended_compat_descriptor;
+	return sizeof(this_extended_compat_descriptor);
+}
+
+uint16_t m_stack_winusb_get_microsoft_property(uint8_t interface,
+                                                const void **descriptor)
+{
+	/* Check the interface here for composite devices. */
+	*descriptor = &interface_0_property_descriptor;
+	return sizeof(interface_0_property_descriptor);
+}
+
+#endif /* AUTOMATIC_WINUSB_SUPPORT */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usb/src/usb_winusb.h	Sat Feb 18 16:14:32 2017 +0000
@@ -0,0 +1,40 @@
+/*
+ *  M-Stack Automatic WinUSB Support
+ *  Copyright (C) 2013 Alan Ott <alan@signal11.us>
+ *  Copyright (C) 2013 Signal 11 Software
+ *
+ *  2013-10-12
+ *
+ *  M-Stack is free software: you can redistribute it and/or modify it under
+ *  the terms of the GNU Lesser General Public License as published by the
+ *  Free Software Foundation, version 3; or the Apache License, version 2.0
+ *  as published by the Apache Software Foundation.  If you have purchased a
+ *  commercial license for this software from Signal 11 Software, your
+ *  commerical license superceeds the information in this header.
+ *
+ *  M-Stack is distributed in the hope that it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
+ *  License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public License
+ *  along with this software.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ *  You should have received a copy of the Apache License, verion 2.0 along
+ *  with this software.  If not, see <http://www.apache.org/licenses/>.
+ */
+
+#ifndef USB_WINUSB_H__
+#define USB_WINUSB_H__
+
+#include <stdint.h>
+
+/* Functions for automatic WinUSB support */
+
+uint16_t m_stack_winusb_get_microsoft_compat(uint8_t interface,
+                                              const void **descriptor);
+
+uint16_t m_stack_winusb_get_microsoft_property(uint8_t interface,
+                                                const void **descriptor);
+
+#endif /* USB_WINUSB_H__ */
--- a/usb/usb.c	Wed Feb 17 05:54:21 2016 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1713 +0,0 @@
-/*
- *  M-Stack USB Device Stack Implementation
- *  Copyright (C) 2013 Alan Ott <alan@signal11.us>
- *  Copyright (C) 2013 Signal 11 Software
- *
- *  Initial version for PIC18, 2008-02-24
- *  PIC24 port, 2013-04-08
- *
- *  M-Stack is free software: you can redistribute it and/or modify it under
- *  the terms of the GNU Lesser General Public License as published by the
- *  Free Software Foundation, version 3; or the Apache License, version 2.0
- *  as published by the Apache Software Foundation.  If you have purchased a
- *  commercial license for this software from Signal 11 Software, your
- *  commerical license superceeds the information in this header.
- *
- *  M-Stack is distributed in the hope that it will be useful, but WITHOUT
- *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
- *  License for more details.
- *
- *  You should have received a copy of the GNU Lesser General Public License
- *  along with this software.  If not, see <http://www.gnu.org/licenses/>.
- *
- *  You should have received a copy of the Apache License, verion 2.0 along
- *  with this software.  If not, see <http://www.apache.org/licenses/>.
- */
-
-#ifdef __XC32__
-#include <xc.h>
-#include <sys/kmem.h>
-#elif __XC16__
-#include <libpic30.h>
-#include <xc.h>
-#elif __C18
-#include <p18f4550.h>
-#include <delays.h>
-#elif __XC8
-#include <xc.h>
-#else
-#error "Compiler not supported"
-#endif
-
-#include <string.h>
-
-#include "usb_config.h"
-#include "usb.h"
-#include "usb_hal.h"
-#include "usb_ch9.h"
-#include "usb_microsoft.h"
-#include "usb_winusb.h"
-
-#if _PIC14E && __XC8
-	/* This is necessary to avoid a warning about ep0_data_stage_callback
-	 * never being assigned to anything other than NULL. Since this is a
-	 * library, it's possible (and likely) that the application will not
-	 * make use of data stage callbacks, or control transfers at all. This
-	 * is only an issue on PIC16F parts (so far) on XC8.
-	 */
-	#pragma warning disable 1088
-#endif
-
-#ifdef __XC8
-	/* XC8 gives bogus warnings (at least on PIC18) about
-	 * ep0_data_stage_callback() being called when NULL. The code does
-	 * check for NULL, and is safe. */
-	#pragma warning disable 1471
-#endif
-
-#define MIN(x,y) (((x)<(y))?(x):(y))
-
-/* Even though they're the same, It's convenient below (for the buffer
- * macros) to have separate #defines for IN and OUT EP 0 lengths which
- * match the format of the other endpoint length #defines. */
-#define EP_0_OUT_LEN EP_0_LEN
-#define EP_0_IN_LEN  EP_0_LEN
-
-#ifndef PPB_MODE
-	#error "PPB_MODE not defined. Define it to one of the four PPB_* macros in usb_hal.h"
-#endif
-
-#ifdef USB_FULL_PING_PONG_ONLY
-	#if PPB_MODE != PPB_ALL
-		#error "This hardware only supports PPB_ALL"
-	#endif
-#endif
-
-
-#if PPB_MODE == PPB_EPO_OUT_ONLY
-	#define PPB_EP0_OUT
-	#undef  PPB_EP0_IN
-	#undef  PPB_EPn
-#elif PPB_MODE == PPB_EPN_ONLY
-	#undef  PPB_EP0_OUT
-	#undef  PPB_EP0_IN
-	#define PPB_EPn
-#elif PPB_MODE == PPB_NONE
-	#undef PPB_EP0_OUT
-	#undef PPB_EP0_IN
-	#undef PPB_EPn
-#elif PPB_MODE == PPB_ALL
-	#define PPB_EP0_OUT
-	#define PPB_EP0_IN
-	#define PPB_EPn
-#else
-	#error "Must select a valid PPB_MODE"
-#endif
-
-STATIC_SIZE_CHECK_EQUAL(sizeof(struct endpoint_descriptor), 7);
-STATIC_SIZE_CHECK_EQUAL(sizeof(struct interface_descriptor), 9);
-STATIC_SIZE_CHECK_EQUAL(sizeof(struct configuration_descriptor), 9);
-STATIC_SIZE_CHECK_EQUAL(sizeof(struct device_descriptor), 18);
-STATIC_SIZE_CHECK_EQUAL(sizeof(struct interface_association_descriptor), 8);
-STATIC_SIZE_CHECK_EQUAL(sizeof(struct setup_packet), 8);
-STATIC_SIZE_CHECK_EQUAL(sizeof(struct microsoft_os_descriptor), 18);
-STATIC_SIZE_CHECK_EQUAL(sizeof(struct microsoft_extended_compat_header), 16);
-STATIC_SIZE_CHECK_EQUAL(sizeof(struct microsoft_extended_compat_function), 24);
-STATIC_SIZE_CHECK_EQUAL(sizeof(struct microsoft_extended_properties_header), 10);
-STATIC_SIZE_CHECK_EQUAL(sizeof(struct microsoft_extended_property_section_header), 8);
-#ifdef __XC32__
-STATIC_SIZE_CHECK_EQUAL(sizeof(struct buffer_descriptor), 8);
-#else
-STATIC_SIZE_CHECK_EQUAL(sizeof(struct buffer_descriptor), 4);
-#endif
-
-#ifdef __C18
-/* The buffer descriptors. Per the PIC18F4550 Data sheet, when _not_ using
-   ping-pong buffering, these must be laid out sequentially starting at
-   address 0x0400 in the following order, ep0_out, ep0_in,ep1_out, ep1_in,
-   etc. These must be initialized prior to use. */
-#pragma udata buffer_descriptors=BD_ADDR
-#endif
-
-
-/* Calculate the number of Buffer Descriptor pairs, which depends on the
-   ping-pong modes active and the number of endpoints used. */
-#if defined(PPB_EP0_IN) && defined(PPB_EP0_OUT)
-	#define NUM_BD_0 4
-#elif !defined(PPB_EP0_IN) && defined(PPB_EP0_OUT)
-	#define NUM_BD_0 3
-#elif !defined(PPB_EP0_IN) && !defined(PPB_EP0_OUT)
-	#define NUM_BD_0 2
-#else
-	#error "Nonsense condition detected"
-#endif
-
-#ifdef PPB_EPn
-	#define NUM_BD (4 * (NUM_ENDPOINT_NUMBERS) + NUM_BD_0)
-#else
-	#define NUM_BD (2 * (NUM_ENDPOINT_NUMBERS) + NUM_BD_0)
-#endif
-
-/* Macros to access a specific buffer descriptor, which depends on the
-   ping-pong modes active. Since EP 0 can have a different ping-pong mode
-   than the other endpoints, EP0's buffer descriptor should be accessed through
-   BDS0OUT() and BDS0IN() only. It is not valid to call BDSnOUT(0,oe), for
-   example*/
-#if PPB_MODE == PPB_EPO_OUT_ONLY
-	#define BDS0OUT(oe) bds[0 + oe]
-	#define BDS0IN(oe) bds[2]
-	#define BDSnOUT(EP,oe) bds[(EP) * 2 + 1]
-	#define BDSnIN(EP,oe) bds[(EP) * 2 + 2]
-#elif PPB_MODE == PPB_EPN_ONLY
-	#define BDS0OUT(oe) bds[0]
-	#define BDS0IN(oe) bds[1]
-	#define BDSnOUT(EP,oe) bds[(EP) * 4 - 2 + (oe)]
-	#define BDSnIN(EP,oe) bds[(EP) * 4 + (oe)]
-#elif PPB_MODE == PPB_NONE
-	#define BDS0OUT(oe) bds[0]
-	#define BDS0IN(oe) bds[1]
-	#define BDSnOUT(EP,oe) bds[(EP) * 2]
-	#define BDSnIN(EP,oe) bds[(EP) * 2 + 1]
-#elif PPB_MODE == PPB_ALL
-	#define BDS0OUT(oe) bds[0 + oe]
-	#define BDS0IN(oe) bds[2 + oe]
-	#define BDSnOUT(EP,oe) bds[(EP) * 4 + (oe)]
-	#define BDSnIN(EP,oe) bds[(EP) * 4 + 2 + (oe)]
-#else
-#error "Must select a valid PPB_MODE"
-#endif
-
-#if defined(AUTOMATIC_WINUSB_SUPPORT) && !defined(MICROSOFT_OS_DESC_VENDOR_CODE)
-#error "Must define a MICROSOFT_OS_DESC_VENDOR_CODE for Automatic WinUSB"
-#endif
-
-#ifdef AUTOMATIC_WINUSB_SUPPORT
-	/* Make sure the Microsoft descriptor functions aren't defined */
-	#ifdef MICROSOFT_COMPAT_ID_DESCRIPTOR_FUNC
-		#error "Must not define MICROSOFT_COMPAT_ID_DESCRIPTOR_FUNC when using Automatic WinUSB"
-	#endif
-	#ifdef MICROSOFT_CUSTOM_PROPERTY_DESCRIPTOR_FUNC
-		#error "Must not define MICROSOFT_CUSTOM_PROPERTY_DESCRIPTOR_FUNC when using Automatic WinUSB"
-	#endif
-
-	/* Define the Microsoft descriptor functions to the handlers
-	 * implemented in usb_winusb.c */
-	#define MICROSOFT_COMPAT_ID_DESCRIPTOR_FUNC m_stack_winusb_get_microsoft_compat
-	#define MICROSOFT_CUSTOM_PROPERTY_DESCRIPTOR_FUNC m_stack_winusb_get_microsoft_property
-#endif
-
-static struct buffer_descriptor bds[NUM_BD] BD_ATTR_TAG;
-
-#ifdef __C18
-/* The actual buffers to and from which the data is transferred from the SIE
-   (from the USB bus). These buffers must fully be located between addresses
-   0x400 and 0x7FF per the datasheet.*/
-/* This addr is for the PIC18F4550 */
-#pragma udata usb_buffers=0x500
-#elif defined(__XC16__) || defined(__XC32__)
-	/* Buffers can go anywhere on PIC24/PIC32 parts which are supported
-	   (so far). */
-#elif __XC8
-	/* Addresses are set by BD_ADDR and BUF_ADDR below. */
-#else
-	#error compiler not supported
-#endif
-
-static struct {
-/* Set up the EP_BUF() macro for EP0 */
-#if defined(PPB_EP0_IN) && defined(PPB_EP0_OUT)
-	#define EP_BUF(n) \
-		unsigned char ep_##n##_out_buf[2][EP_##n##_OUT_LEN]; \
-		unsigned char ep_##n##_in_buf[2][EP_##n##_IN_LEN];
-#elif !defined(PPB_EP0_IN) && defined(PPB_EP0_OUT)
-	#define EP_BUF(n) \
-		unsigned char ep_##n##_out_buf[2][EP_##n##_OUT_LEN]; \
-		unsigned char ep_##n##_in_buf[1][EP_##n##_IN_LEN];
-#elif !defined(PPB_EP0_IN) && !defined(PPB_EP0_OUT)
-	#define EP_BUF(n) \
-		unsigned char ep_##n##_out_buf[1][EP_##n##_OUT_LEN]; \
-		unsigned char ep_##n##_in_buf[1][EP_##n##_IN_LEN];
-#else
-	#error "Nonsense condition detected"
-#endif
-
-#if NUM_ENDPOINT_NUMBERS >= 0
-	EP_BUF(0)
-#endif
-
-/* Re-setup the EP_BUF() macro for the rest of the endpoints */
-#undef EP_BUF
-#ifdef PPB_EPn
-	#define EP_BUF(n) \
-		unsigned char ep_##n##_out_buf[2][EP_##n##_OUT_LEN]; \
-		unsigned char ep_##n##_in_buf[2][EP_##n##_IN_LEN];
-#else
-	#define EP_BUF(n) \
-		unsigned char ep_##n##_out_buf[1][EP_##n##_OUT_LEN]; \
-		unsigned char ep_##n##_in_buf[1][EP_##n##_IN_LEN];
-#endif
-
-#if NUM_ENDPOINT_NUMBERS >= 1
-	EP_BUF(1)
-#endif
-#if NUM_ENDPOINT_NUMBERS >= 2
-	EP_BUF(2)
-#endif
-#if NUM_ENDPOINT_NUMBERS >= 3
-	EP_BUF(3)
-#endif
-#if NUM_ENDPOINT_NUMBERS >= 4
-	EP_BUF(4)
-#endif
-#if NUM_ENDPOINT_NUMBERS >= 5
-	EP_BUF(5)
-#endif
-#if NUM_ENDPOINT_NUMBERS >= 6
-	EP_BUF(6)
-#endif
-#if NUM_ENDPOINT_NUMBERS >= 7
-	EP_BUF(7)
-#endif
-#if NUM_ENDPOINT_NUMBERS >= 8
-	EP_BUF(8)
-#endif
-#if NUM_ENDPOINT_NUMBERS >= 9
-	EP_BUF(9)
-#endif
-#if NUM_ENDPOINT_NUMBERS >= 10
-	EP_BUF(10)
-#endif
-#if NUM_ENDPOINT_NUMBERS >= 11
-	EP_BUF(11)
-#endif
-#if NUM_ENDPOINT_NUMBERS >= 12
-	EP_BUF(12)
-#endif
-#if NUM_ENDPOINT_NUMBERS >= 13
-	EP_BUF(13)
-#endif
-#if NUM_ENDPOINT_NUMBERS >= 14
-	EP_BUF(14)
-#endif
-#if NUM_ENDPOINT_NUMBERS >= 15
-	EP_BUF(15)
-#endif
-
-#undef EP_BUF
-} ep_buffers XC8_BUFFER_ADDR_TAG;
-
-struct ep_buf {
-	unsigned char * const out; /* buffers for the even buffer descriptor */
-	unsigned char * const in;  /* ie: ppbi = 0 */
-#ifdef PPB_EPn
-	unsigned char * const out1; /* buffers for the odd buffer descriptor */
-	unsigned char * const in1;  /* ie: ppbi = 1 */
-#endif
-	const uint8_t out_len;
-	const uint8_t in_len;
-
-#define EP_OUT_HALT_FLAG 0x1
-#define EP_IN_HALT_FLAG 0x2
-#define EP_RX_DTS 0x4  /* The DTS of the _next_ packet */
-#define EP_TX_DTS 0x8
-#define EP_RX_PPBI 0x10 /* Represents the next buffer which will be need to be
-                           reset and given back to the SIE. */
-#define EP_TX_PPBI 0x20 /* Represents the _next_ buffer to write into. */
-	uint8_t flags;
-};
-
-struct ep0_buf {
-	unsigned char * const out; /* buffers for the even buffer descriptor */
-	unsigned char * const in;  /* ie: ppbi = 0 */
-#ifdef PPB_EP0_OUT
-	unsigned char * const out1; /* buffer for the odd buffer descriptor */
-#endif
-#ifdef PPB_EP0_IN
-	unsigned char * const in1;  /* buffer for the odd buffer descriptor */
-#endif
-
-	/* Use the EP_* flags from ep_buf for flags */
-	uint8_t flags;
-};
-
-#ifdef __C18
-#pragma idata
-#endif
-
-#if defined(PPB_EP0_IN) && defined(PPB_EP0_OUT)
-	#define EP_BUFS0() { ep_buffers.ep_0_out_buf[0], \
-	                     ep_buffers.ep_0_in_buf[0], \
-	                     ep_buffers.ep_0_out_buf[1], \
-	                     ep_buffers.ep_0_in_buf[1] }
-
-#elif !defined(PPB_EP0_IN) && defined(PPB_EP0_OUT)
-	#define EP_BUFS0() { ep_buffers.ep_0_out_buf[0], \
-	                     ep_buffers.ep_0_in_buf[0], \
-	                     ep_buffers.ep_0_out_buf[1] }
-
-#elif !defined(PPB_EP0_IN) && !defined(PPB_EP0_OUT)
-	#define EP_BUFS0() { ep_buffers.ep_0_out_buf[0], \
-	                     ep_buffers.ep_0_in_buf[0] }
-
-#else
-	#error "Nonsense condition detected"
-#endif
-
-
-#ifdef PPB_EPn
-	#define EP_BUFS(n) { ep_buffers.ep_##n##_out_buf[0], \
-	                     ep_buffers.ep_##n##_in_buf[0], \
-	                     ep_buffers.ep_##n##_out_buf[1], \
-	                     ep_buffers.ep_##n##_in_buf[1], \
-	                     EP_##n##_OUT_LEN, \
-	                     EP_##n##_IN_LEN },
-#else
-	#define EP_BUFS(n) { ep_buffers.ep_##n##_out_buf[0], \
-	                     ep_buffers.ep_##n##_in_buf[0], \
-	                     EP_##n##_OUT_LEN, \
-	                     EP_##n##_IN_LEN },
-#endif
-
-static struct ep0_buf ep0_buf = EP_BUFS0();
-
-static struct ep_buf ep_buf[NUM_ENDPOINT_NUMBERS+1] = {
-#if NUM_ENDPOINT_NUMBERS >= 0
-	{ NULL, NULL },
-	/* TODO wasted space here */
-#endif
-#if NUM_ENDPOINT_NUMBERS >= 1
-	EP_BUFS(1)
-#endif
-#if NUM_ENDPOINT_NUMBERS >= 2
-	EP_BUFS(2)
-#endif
-#if NUM_ENDPOINT_NUMBERS >= 3
-	EP_BUFS(3)
-#endif
-#if NUM_ENDPOINT_NUMBERS >= 4
-	EP_BUFS(4)
-#endif
-#if NUM_ENDPOINT_NUMBERS >= 5
-	EP_BUFS(5)
-#endif
-#if NUM_ENDPOINT_NUMBERS >= 6
-	EP_BUFS(6)
-#endif
-#if NUM_ENDPOINT_NUMBERS >= 7
-	EP_BUFS(7)
-#endif
-#if NUM_ENDPOINT_NUMBERS >= 8
-	EP_BUFS(8)
-#endif
-#if NUM_ENDPOINT_NUMBERS >= 9
-	EP_BUFS(9)
-#endif
-#if NUM_ENDPOINT_NUMBERS >= 10
-	EP_BUFS(10)
-#endif
-#if NUM_ENDPOINT_NUMBERS >= 11
-	EP_BUFS(11)
-#endif
-#if NUM_ENDPOINT_NUMBERS >= 12
-	EP_BUFS(12)
-#endif
-#if NUM_ENDPOINT_NUMBERS >= 13
-	EP_BUFS(13)
-#endif
-#if NUM_ENDPOINT_NUMBERS >= 14
-	EP_BUFS(14)
-#endif
-#if NUM_ENDPOINT_NUMBERS >= 15
-	EP_BUFS(15)
-#endif
-
-};
-#undef EP_BUFS
-#undef EP_BUFS0
-
-/* Global data */
-static bool addr_pending;
-static uint8_t addr;
-static uint8_t g_configuration;
-static bool control_need_zlp;
-static bool returning_short;
-
-/* Data associated with multi-packet control transfers */
-static usb_ep0_data_stage_callback ep0_data_stage_callback;
-static char   *ep0_data_stage_in_buffer; /* XC8 v1.12 fails if this is const on PIC16 */
-static char   *ep0_data_stage_out_buffer;
-static size_t  ep0_data_stage_buf_remaining;
-static void   *ep0_data_stage_context;
-static uint8_t ep0_data_stage_direc; /*1=IN, 0=OUT, Same as USB spec.*/
-
-#ifdef _PIC14E
-/* Convert a pointer, which can be a normal banked pointer or a linear
- * pointer, to a linear pointer.
- *
- * The USB buffer descriptors need linear addresses. The XC8 compiler will
- * generate banked (not linear) addresses for the arrays in ep_buffers if
- * ep_buffers can fit within a single bank. This is good for code size, but
- * the buffer descriptors cannot take banked addresses, so they must be
- * generated from the banked addresses.
- *
- * See section 3.6.2 of the PIC16F1459 datasheet for details.
- */
-static uint16_t pic16_linear_addr(void *ptr)
-{
-	uint8_t high, low;
-	uint16_t addr = (uint16_t) ptr;
-
-	/* Addresses over 0x2000 are already linear addresses. */
-	if (addr >= 0x2000)
-		return addr;
-
-	high = (addr & 0xff00) >> 8;
-	low  = addr & 0x00ff;
-
-	return 0x2000 +
-	       (low & 0x7f) - 0x20 +
-	       ((high << 1) + (low & 0x80)? 1: 0) * 0x50;
-}
-#endif
-
-static void reset_ep0_data_stage()
-{
-	ep0_data_stage_in_buffer = NULL;
-	ep0_data_stage_out_buffer = NULL;
-	ep0_data_stage_buf_remaining = 0;
-	ep0_data_stage_callback = NULL;
-
-	/* There's no need to reset the following because no decisions are
-	   made based on them:
-	     ep0_data_stage_context,
-	     ep0_data_stage_direc
-	 */
-}
-
-#define SERIAL(x)
-#define SERIAL_VAL(x)
-
-/* Initialize or reset all of the endpoints. This is done:
- *   1. at startup,
- *   2. following a USB reset, and
- *   3. whenever a SET_CONFIGURATION transfer is received. */
-static void init_endpoints(void)
-{
-	uint8_t i;
-
-	/* Hold ping-pong in reset for the whole time the endpoints
-	   are being configured */
-	SFR_USB_PING_PONG_RESET = 1;
-	/* Reset the flags */
-	ep0_buf.flags = 0;
-	for (i = 0; i <= NUM_ENDPOINT_NUMBERS; i++) {
-#ifdef PPB_EPn
-		ep_buf[i].flags = 0;
-#else
-		ep_buf[i].flags = EP_RX_DTS;
-#endif
-	}
-
-	/* Clear all the buffer-descriptors and re-initialize */
-	memset(bds, 0x0, sizeof(bds));
-
-	/* Setup endpoint 0 Output buffer descriptor.
-	   Input and output are from the HOST perspective. */
-	BDS0OUT(0).BDnADR = (BDNADR_TYPE) PHYS_ADDR(ep0_buf.out);
-	SET_BDN(BDS0OUT(0), BDNSTAT_UOWN, EP_0_LEN);
-
-#ifdef PPB_EP0_OUT
-	BDS0OUT(1).BDnADR = (BDNADR_TYPE) PHYS_ADDR(ep0_buf.out1);
-	SET_BDN(BDS0OUT(1), BDNSTAT_UOWN, EP_0_LEN);
-#endif
-
-	/* Setup endpoint 0 Input buffer descriptor.
-	   Input and output are from the HOST perspective. */
-	BDS0IN(0).BDnADR = (BDNADR_TYPE) PHYS_ADDR(ep0_buf.in);
-	SET_BDN(BDS0IN(0), 0, EP_0_LEN);
-#ifdef PPB_EP0_IN
-	BDS0IN(1).BDnADR = (BDNADR_TYPE) PHYS_ADDR(ep0_buf.in1);
-	SET_BDN(BDS0IN(1), 0, EP_0_LEN);
-#endif
-
-	for (i = 1; i <= NUM_ENDPOINT_NUMBERS; i++) {
-		/* Setup endpoint 1 Output buffer descriptor.
-		   Input and output are from the HOST perspective. */
-		BDSnOUT(i,0).BDnADR = (BDNADR_TYPE) PHYS_ADDR(ep_buf[i].out);
-		SET_BDN(BDSnOUT(i,0), BDNSTAT_UOWN|BDNSTAT_DTSEN, ep_buf[i].out_len);
-#ifdef PPB_EPn
-		/* Initialize EVEN buffers when in ping-pong mode. */
-		BDSnOUT(i,1).BDnADR = (BDNADR_TYPE) PHYS_ADDR(ep_buf[i].out1);
-		SET_BDN(BDSnOUT(i,1), BDNSTAT_UOWN|BDNSTAT_DTSEN|BDNSTAT_DTS, ep_buf[i].out_len);
-#endif
-		/* Setup endpoint 1 Input buffer descriptor.
-		   Input and output are from the HOST perspective. */
-		BDSnIN(i,0).BDnADR = (BDNADR_TYPE) PHYS_ADDR(ep_buf[i].in);
-		SET_BDN(BDSnIN(i,0), 0, ep_buf[i].in_len);
-#ifdef PPB_EPn
-		/* Initialize EVEN buffers when in ping-pong mode. */
-		BDSnIN(i,1).BDnADR = (BDNADR_TYPE) PHYS_ADDR(ep_buf[i].in1);
-		SET_BDN(BDSnIN(i,1), 0, ep_buf[i].in_len);
-#endif
-	}
-
-	SFR_USB_PING_PONG_RESET = 0;
-}
-
-/* usb_init() is called at powerup time, and when the device gets
-   the reset signal from the USB bus (D+ and D- both held low) indicated
-   by interrput bit URSTIF. */
-void usb_init(void)
-{
-	uint8_t i;
-
-	/* Initialize the USB. 18.4 of PIC24FJ64GB004 datasheet */
-#ifndef USB_FULL_PING_PONG_ONLY
-	SET_PING_PONG_MODE(PPB_MODE);
-#endif
-#if PPB_MODE != PPB_NONE
-	SFR_USB_PING_PONG_RESET = 1;
-	SFR_USB_PING_PONG_RESET = 0;
-#endif
-	SFR_USB_INTERRUPT_EN = 0x0;
-	SFR_USB_EXTENDED_INTERRUPT_EN = 0x0;
-	
-	SFR_USB_EN = 1; /* enable USB module */
-
-#ifdef USE_OTG
-	SFR_OTGEN = 1;
-#endif
-
-	
-#ifdef NEEDS_PULL
-	SFR_PULL_EN = 1;  /* pull-up enable */
-#endif
-
-#ifdef HAS_ON_CHIP_XCVR_DIS
-	SFR_ON_CHIP_XCVR_DIS = 0; /* on-chip transceiver Disable */
-#endif
-
-#ifdef HAS_LOW_SPEED
-	SFR_FULL_SPEED_EN = 1;   /* Full-speed enable */
-#endif
-
-	CLEAR_USB_TOKEN_IF();   /* Clear 4 times to clear out USTAT FIFO */
-	CLEAR_USB_TOKEN_IF();
-	CLEAR_USB_TOKEN_IF();
-	CLEAR_USB_TOKEN_IF();
-
-	CLEAR_ALL_USB_IF();
-
-#ifdef USB_USE_INTERRUPTS
-	SFR_TRANSFER_IE = 1; /* USB Transfer Interrupt Enable */
-	SFR_STALL_IE = 1;    /* USB Stall Interrupt Enable */
-	SFR_RESET_IE = 1;    /* USB Reset Interrupt Enable */
-#ifdef START_OF_FRAME_CALLBACK
-	SFR_SOF_IE = 1;      /* USB Start-Of-Frame Interrupt Enable */
-#endif
-#endif
-
-#ifdef USB_NEEDS_SET_BD_ADDR_REG
-#ifdef __XC16__
-	union WORD {
-		struct {
-			uint8_t lb;
-			uint8_t hb;
-		};
-		uint16_t w;
-		void *ptr;
-	};
-	union WORD w;
-	w.ptr = bds;
-
-	SFR_BD_ADDR_REG = w.hb;
-
-#elif __XC32__
-	union WORD {
-		struct {
-			uint8_t lb;
-			uint8_t hb;
-			uint8_t ub;
-			uint8_t eb;
-		};
-		uint32_t w;
-		void *ptr;
-	};
-	union WORD w;
-	w.w = KVA_TO_PA(bds);
-
-	SFR_BD_ADDR_REG1 = w.hb & 0xFE;
-	SFR_BD_ADDR_REG2 = w.ub;
-	SFR_BD_ADDR_REG3 = w.eb;
-#endif
-#endif
-
-	/* These are the UEP/U1EP endpoint management registers. */
-	
-	/* Clear them all out. This is important because a bootloader
-	   could have set them to non-zero */
-	memset(SFR_EP_MGMT(0), 0x0, sizeof(*SFR_EP_MGMT(0)) * 16);
-	
-	/* Set up Endpoint zero */
-	SFR_EP_MGMT(0)->SFR_EP_MGMT_HANDSHAKE = 1; /* Endpoint handshaking enable */
-	SFR_EP_MGMT(0)->SFR_EP_MGMT_CON_DIS = 0; /* 1=Disable control operations */
-	SFR_EP_MGMT(0)->SFR_EP_MGMT_OUT_EN = 1; /* Endpoint Out Transaction Enable */
-	SFR_EP_MGMT(0)->SFR_EP_MGMT_IN_EN = 1; /* Endpoint In Transaction Enable */
-	SFR_EP_MGMT(0)->SFR_EP_MGMT_STALL = 0; /* Stall */
-
-	for (i = 1; i <= NUM_ENDPOINT_NUMBERS; i++) {
-		volatile SFR_EP_MGMT_TYPE *ep = SFR_EP_MGMT(i);
-		ep->SFR_EP_MGMT_HANDSHAKE = 1; /* Endpoint handshaking enable */
-		ep->SFR_EP_MGMT_CON_DIS = 1; /* 1=Disable control operations */
-		ep->SFR_EP_MGMT_OUT_EN = 1; /* Endpoint Out Transaction Enable */
-		ep->SFR_EP_MGMT_IN_EN = 1; /* Endpoint In Transaction Enable */
-		ep->SFR_EP_MGMT_STALL = 0; /* Stall */
-	}
-
-	/* Reset the Address. */
-	SFR_USB_ADDR = 0x0;
-	addr_pending = 0;
-	g_configuration = 0;
-
-	init_endpoints();
-
-	#ifdef USB_NEEDS_POWER_ON
-	SFR_USB_POWER = 1;
-	#endif
-
-#ifdef USE_OTG
-	SFR_DPPULUP = 1;
-#endif
-
-	reset_ep0_data_stage();
-
-#ifdef USB_USE_INTERRUPTS
-	SFR_USB_IE = 1;     /* USB Interrupt enable */
-#endif
-	
-	//UIRbits.URSTIF = 0; /* Clear USB Reset on Start */
-}
-
-static void reset_bd0_out(void)
-{
-	/* Clean up the Buffer Descriptors.
-	 * Set the length and hand it back to the SIE.
-	 * The Address stays the same. */
-#ifdef PPB_EP0_OUT
-	SET_BDN(BDS0OUT(SFR_USB_STATUS_PPBI), BDNSTAT_UOWN, EP_0_LEN);
-#else
-	SET_BDN(BDS0OUT(0), BDNSTAT_UOWN, EP_0_LEN);
-#endif
-}
-
-static void stall_ep0(void)
-{
-	/* Stall Endpoint 0. It's important that DTSEN and DTS are zero. */
-#ifdef PPB_EP0_IN
-	uint8_t ppbi = (ep0_buf.flags & EP_TX_PPBI)? 1: 0;
-	SET_BDN(BDS0IN(ppbi), BDNSTAT_UOWN|BDNSTAT_BSTALL, EP_0_LEN);
-	/* The PPBI does not advance for STALL. */
-#else
-	SET_BDN(BDS0IN(0), BDNSTAT_UOWN|BDNSTAT_BSTALL, EP_0_LEN);
-#endif
-}
-
-#ifdef NEEDS_CLEAR_STALL
-static void clear_ep0_stall(void)
-{
-	/* Clear Endpoint 0 Stall and UOWN. This is supposed to be done by
-	 * the hardware, but it isn't on PIC16 and PIC18. */
-#ifdef PPB_EP0_IN
-	uint8_t ppbi = (ep0_buf.flags & EP_TX_PPBI)? 1: 0;
-	SET_BDN(BDS0IN(ppbi), 0, EP_0_LEN);
-	/* The PPBI does not advance for STALL. */
-#else
-	SET_BDN(BDS0IN(0), 0, EP_0_LEN);
-#endif
-}
-#endif
-
-static void stall_ep_in(uint8_t ep)
-{
-	/* Stall Endpoint. It's important that DTSEN and DTS are zero.
-	 * Although the datasheet doesn't stay it, the only safe way to do this
-	 * is to set BSTALL on BOTH buffers when in ping-pong mode. */
-	SET_BDN(BDSnIN(ep, 0), BDNSTAT_UOWN|BDNSTAT_BSTALL, ep_buf[ep].in_len);
-#ifdef PPB_EPn
-	SET_BDN(BDSnIN(ep, 1), BDNSTAT_UOWN|BDNSTAT_BSTALL, ep_buf[ep].in_len);
-#endif
-}
-
-static void stall_ep_out(uint8_t ep)
-{
-	/* Stall Endpoint. It's important that DTSEN and DTS are zero.
-	 * Although the datasheet doesn't stay it, the only safe way to do this
-	 * is to set BSTALL on BOTH buffers when in ping-pong mode. */
-	SET_BDN(BDSnOUT(ep, 0), BDNSTAT_UOWN|BDNSTAT_BSTALL , 0);
-#ifdef PPB_EPn
-	SET_BDN(BDSnOUT(ep, 1), BDNSTAT_UOWN|BDNSTAT_BSTALL , 0);
-#endif
-}
-
-static void send_zero_length_packet_ep0()
-{
-#ifdef PPB_EP0_IN
-	uint8_t ppbi = (ep0_buf.flags & EP_TX_PPBI)? 1: 0;
-	BDS0IN(ppbi).STAT.BDnSTAT = 0;
-	SET_BDN(BDS0IN(ppbi), BDNSTAT_UOWN|BDNSTAT_DTS|BDNSTAT_DTSEN, 0);
-	ep0_buf.flags ^= EP_TX_PPBI;
-#else
-	BDS0IN(0).STAT.BDnSTAT = 0;
-	SET_BDN(BDS0IN(0), BDNSTAT_UOWN|BDNSTAT_DTS|BDNSTAT_DTSEN, 0);
-#endif
-}
-
-static void usb_send_in_buffer_0(size_t len)
-{
-	if (!usb_in_endpoint_halted(0)) {
-#ifdef PPB_EP0_IN
-		struct buffer_descriptor *bd;
-		uint8_t ppbi = (ep0_buf.flags & EP_TX_PPBI)? 1: 0;
-		uint8_t pid = (ep0_buf.flags & EP_TX_DTS)? 1 : 0;
-		bd = &BDS0IN(ppbi);
-		bd->STAT.BDnSTAT = 0;
-
-		if (pid)
-			SET_BDN(*bd,
-				BDNSTAT_UOWN|BDNSTAT_DTS|BDNSTAT_DTSEN, len);
-		else
-			SET_BDN(*bd,
-				BDNSTAT_UOWN|BDNSTAT_DTSEN, len);
-
-		ep0_buf.flags ^= EP_TX_PPBI;
-		ep0_buf.flags ^= EP_TX_DTS;
-#else
-		uint8_t pid;
-		pid = (ep0_buf.flags & EP_TX_DTS)? 1 : 0;
-		BDS0IN(0).STAT.BDnSTAT = 0;
-
-		if (pid)
-			SET_BDN(BDS0IN(0),
-				BDNSTAT_UOWN|BDNSTAT_DTS|BDNSTAT_DTSEN, len);
-		else
-			SET_BDN(BDS0IN(0),
-				BDNSTAT_UOWN|BDNSTAT_DTSEN, len);
-
-		ep0_buf.flags ^= EP_TX_DTS;
-#endif
-	}
-}
-
-/* Copy Data to Endpoint 0's IN Buffer
- *
- * Copy len bytes from ptr into endpoint 0's current IN
- * buffer, taking into account the ping-pong state.
- */
-#ifdef PPB_EP0_IN
-static void copy_to_ep0_in_buf(const void *ptr, size_t len)
-{
-	uint8_t ppbi = (ep0_buf.flags & EP_TX_PPBI)? 1: 0;
-	if (ppbi)
-		memcpy_from_rom(ep0_buf.in1, ptr, len);
-	else
-		memcpy_from_rom(ep0_buf.in, ptr, len);
-}
-#else
-	#define copy_to_ep0_in_buf(PTR, LEN) memcpy_from_rom(ep0_buf.in, PTR, LEN);
-#endif
-
-/* Start Control Return
- *
- * Start the data stage of an IN control transfer. This is primarily used
- * for sending descriptors and other chapter 9 data back to the host, but it
- * is also called from usb_send_data_stage() for handling control transfers
- * handled by the application.
- *
- * This function sets up the global state variables necessary to do a
- * multi-transaction IN data stage and sends the first transaction.
- *
- * Params:
- *   ptr             - a pointer to the data to send
- *   len             - the size of the data which can be sent (ie: the size
- *                     of the entire descriptor)
- *   bytes_asked_for - the number of bytes asked for by the host in
- *                     the SETUP phase
- */
-static void start_control_return(const void *ptr, size_t len, size_t bytes_asked_for)
-{
-	uint8_t bytes_to_send = MIN(len, EP_0_IN_LEN);
-	bytes_to_send = MIN(bytes_to_send, bytes_asked_for);
-	returning_short = len < bytes_asked_for;
-	copy_to_ep0_in_buf(ptr, bytes_to_send);
-	ep0_data_stage_in_buffer = ((char*)ptr) + bytes_to_send;
-	ep0_data_stage_buf_remaining = MIN(bytes_asked_for, len) - bytes_to_send;
-
-	/* Send back the first transaction */
-	ep0_buf.flags |= EP_TX_DTS;
-	usb_send_in_buffer_0(bytes_to_send);
-}
-
-static inline int8_t handle_standard_control_request()
-{
-	FAR struct setup_packet *setup;
-	int8_t res = 0;
-
-#ifdef PPB_EP0_OUT
-	if (SFR_USB_STATUS_PPBI)
-		setup = (struct setup_packet*) ep0_buf.out1;
-	else
-		setup = (struct setup_packet*) ep0_buf.out;
-#else
-	setup = (struct setup_packet*) ep0_buf.out;
-#endif
-
-	if (setup->bRequest == GET_DESCRIPTOR &&
-	    setup->REQUEST.bmRequestType == 0x80 /* Section 9.4, Table 9-3 */) {
-		char descriptor = ((setup->wValue >> 8) & 0x00ff);
-		uint8_t descriptor_index = setup->wValue & 0x00ff;
-
-		if (descriptor == DESC_DEVICE) {
-			SERIAL("Get Descriptor for DEVICE");
-
-			/* Return Device Descriptor */
-			start_control_return(&USB_DEVICE_DESCRIPTOR, USB_DEVICE_DESCRIPTOR.bLength, setup->wLength);
-		}
-		else if (descriptor == DESC_CONFIGURATION) {
-			const struct configuration_descriptor *desc;
-			if (descriptor_index >= NUMBER_OF_CONFIGURATIONS)
-				stall_ep0();
-			else {
-				desc = USB_CONFIG_DESCRIPTOR_MAP[descriptor_index];
-				start_control_return(desc, desc->wTotalLength, setup->wLength);
-			}
-		}
-		else if (descriptor == DESC_STRING) {
-#ifdef MICROSOFT_OS_DESC_VENDOR_CODE
-			if (descriptor_index == 0xee) {
-				/* Microsoft descriptor Requested */
-				#ifdef __XC8
-				/* static is better in all cases on XC8. On
-				 * XC16/32, non-static uses less RAM. */
-				static
-				#endif
-				struct microsoft_os_descriptor os_descriptor =
-				{
-					0x12,                          /* bLength */
-					0x3,                           /* bDescriptorType */
-					{'M','S','F','T','1','0','0'}, /* qwSignature */
-					MICROSOFT_OS_DESC_VENDOR_CODE, /* bMS_VendorCode */
-					0x0,                           /* bPad */
-				};
-
-				start_control_return(&os_descriptor, sizeof(os_descriptor), setup->wLength);
-			}
-			else
-#endif
-			{
-#ifdef USB_STRING_DESCRIPTOR_FUNC
-				const void *desc;
-				int16_t len;
-				{
-					len = USB_STRING_DESCRIPTOR_FUNC(descriptor_index, &desc);
-					if (len < 0) {
-						stall_ep0();
-						SERIAL("Unsupported string descriptor requested");
-					}
-					else
-						start_control_return(desc, len, setup->wLength);
-				}
-#else
-				/* Strings are not supported on this device. */
-				stall_ep0();
-#endif
-			}
-		}
-		else {
-#ifdef UNKNOWN_GET_DESCRIPTOR_CALLBACK
-			int16_t len;
-			const void *desc;
-			len = UNKNOWN_GET_DESCRIPTOR_CALLBACK(setup, &desc);
-			if (len < 0) {
-				stall_ep0();
-				SERIAL("Unsupported descriptor requested");
-			}
-			else
-				start_control_return(desc, len, setup->wLength);
-#else
-			/* Unknown Descriptor. Stall the endpoint. */
-			stall_ep0();
-			SERIAL("Unknown Descriptor");
-			SERIAL_VAL(descriptor);
-#endif
-		}
-	}
-	else if (setup->bRequest == SET_ADDRESS) {
-		/* Mark the ADDR as pending. The address gets set only
-		   after the transaction is complete. */
-		addr_pending = 1;
-		addr = setup->wValue;
-
-		send_zero_length_packet_ep0();
-	}
-	else if (setup->bRequest == SET_CONFIGURATION) {
-		/* Set the configuration. wValue is the configuration.
-		 * A value of 0 means to un-set the configuration and
-		 * go back to the ADDRESS state. */
-		uint8_t req = setup->wValue & 0x00ff;
-#ifdef SET_CONFIGURATION_CALLBACK
-		SET_CONFIGURATION_CALLBACK(req);
-#endif
-		/* Re-initialize the endpoints. USB 2.0 section 9.1.1.5
-		 * requires that all endpoint data toggles be reset to DATA0
-		 * when SET_CONFIGURATION is received. With ping-ponging
-		 * involved, the only way to properly reset the data toggles
-		 * is to reset all the endpoints. */
-		init_endpoints();
-
-		send_zero_length_packet_ep0();
-		g_configuration = req;
-
-		SERIAL("Set configuration to");
-		SERIAL_VAL(req);
-	}
-	else if (setup->bRequest == GET_CONFIGURATION) {
-		/* Return the current Configuration. */
-		SERIAL("Get Configuration. Returning:");
-		SERIAL_VAL(g_configuration);
-
-		start_control_return(&g_configuration, 1, setup->wLength);
-	}
-	else if (setup->bRequest == GET_STATUS) {
-
-		SERIAL("Get Status (dst, index):");
-		SERIAL_VAL(setup->REQUEST.destination);
-		SERIAL_VAL(setup->wIndex);
-
-		if (setup->REQUEST.destination == 0 /*0=device*/) {
-			/* Status for the DEVICE requested
-			   Return as a single byte in the return packet. */
-			uint16_t ret;
-#ifdef GET_DEVICE_STATUS_CALLBACK
-			ret = GET_DEVICE_STATUS_CALLBACK();
-#else
-			ret = 0x0000;
-#endif
-			start_control_return(&ret, 2, setup->wLength);
-		}
-		else if (setup->REQUEST.destination == 2 /*2=endpoint*/) {
-			/* Status of endpoint */
-			uint8_t ep_num = setup->wIndex & 0x0f;
-			if (ep_num <= NUM_ENDPOINT_NUMBERS) {
-				uint8_t flags = ep_buf[ep_num].flags;
-				uint8_t ret[2];
-				ret[0] = ((setup->wIndex & 0x80) ?
-					flags & EP_IN_HALT_FLAG :
-					flags & EP_OUT_HALT_FLAG) != 0;
-				ret[1] = 0;
-				start_control_return(ret, 2, setup->wLength);
-			}
-			else {
-				/* Endpoint doesn't exist. STALL. */
-				stall_ep0();
-			}
-		}
-		else {
-			stall_ep0();
-			SERIAL("Stalling. Status Requested for destination:");
-			SERIAL_VAL(setup->REQUEST.destination);
-		}
-
-	}
-	else if (setup->bRequest == SET_INTERFACE) {
-		/* Set the alternate setting for an interface.
-		 * wIndex is the interface.
-		 * wValue is the alternate setting. */
-#ifdef SET_INTERFACE_CALLBACK
-		int8_t res;
-		res = SET_INTERFACE_CALLBACK(setup->wIndex, setup->wValue);
-		if (res < 0) {
-			stall_ep0();
-		}
-		else
-			send_zero_length_packet_ep0();
-#else
-		/* If there's no callback, then assume that
-		 * we only have one alternate setting per
-		 * interface. */
-		send_zero_length_packet_ep0();
-#endif
-	}
-	else if (setup->bRequest == GET_INTERFACE) {
-		int8_t ret;
-		SERIAL("Get Interface");
-		SERIAL_VAL(setup->bRequest);
-		SERIAL_VAL(setup->REQUEST.destination);
-		SERIAL_VAL(setup->REQUEST.type);
-		SERIAL_VAL(setup->REQUEST.direction);
-#ifdef GET_INTERFACE_CALLBACK
-		ret = GET_INTERFACE_CALLBACK(setup->wIndex);
-		if (ret < 0)
-			stall_ep0();
-		else {
-			/* Return the current alternate setting
-			   as a single byte in the return packet. */
-			start_control_return(&ret, 1, setup->wLength);
-		}
-#else
-		/* If there's no callback, then assume that
-		 * we only have one alternate setting per
-		 * interface and return zero as that
-		 * alternate setting. */
-		ret = 0;
-		start_control_return(&ret, 1, setup->wLength);
-#endif
-	}
-	else if (setup->bRequest == CLEAR_FEATURE || setup->bRequest == SET_FEATURE) {
-		uint8_t stall = 1;
-		if (setup->REQUEST.destination == 0/*0=device*/) {
-			SERIAL("Set/Clear feature for device");
-			/* TODO Remote Wakeup flag */
-		}
-
-		if (setup->REQUEST.destination == 2/*2=endpoint*/) {
-			if (setup->wValue == 0/*0=ENDPOINT_HALT*/) {
-				uint8_t ep_num = setup->wIndex & 0x0f;
-				uint8_t ep_dir = setup->wIndex & 0x80;
-				if (ep_num <= NUM_ENDPOINT_NUMBERS) {
-					if (setup->bRequest == SET_FEATURE) {
-						/* Set Endpoint Halt Feature.
-						   Stall the affected endpoint. */
-						if (ep_dir) {
-							usb_halt_ep_in(ep_num);
-						}
-						else {
-							usb_halt_ep_out(ep_num);
-						}
-					}
-					else {
-						/* Clear Endpoint Halt Feature.
-						   Clear the STALL on the affected endpoint. */
-						if (ep_dir) {
-#ifdef PPB_EPn
-							SET_BDN(BDSnIN(ep_num, 0), 0, ep_buf[ep_num].in_len);
-							SET_BDN(BDSnIN(ep_num, 1), 0, ep_buf[ep_num].in_len);
-#else
-							SET_BDN(BDSnIN(ep_num, 0), 0, ep_buf[ep_num].in_len);
-#endif
-							/* Clear DTS. Next packet to be sent will be DATA0. */
-							ep_buf[ep_num].flags &= ~EP_TX_DTS;
-
-							ep_buf[ep_num].flags &= ~(EP_IN_HALT_FLAG);
-						}
-						else {
-#ifdef PPB_EPn
-							uint8_t ppbi = (ep_buf[ep_num].flags & EP_RX_PPBI)? 1 : 0;
-							/* Put the current buffer at DTS 0, and the next (opposite) buffer at DTS 1 */
-							SET_BDN(BDSnOUT(ep_num, ppbi), BDNSTAT_UOWN|BDNSTAT_DTSEN, ep_buf[ep_num].out_len);
-							SET_BDN(BDSnOUT(ep_num, !ppbi), BDNSTAT_UOWN|BDNSTAT_DTSEN|BDNSTAT_DTS, ep_buf[ep_num].out_len);
-
-							/* Clear DTS */
-							ep_buf[ep_num].flags &= ~EP_RX_DTS;
-#else
-							SET_BDN(BDSnOUT(ep_num, 0), BDNSTAT_UOWN|BDNSTAT_DTSEN, ep_buf[ep_num].out_len);
-
-							/* Set DTS */
-							ep_buf[ep_num].flags |= EP_RX_DTS;
-#endif
-							ep_buf[ep_num].flags &= ~(EP_OUT_HALT_FLAG);
-						}
-					}
-#ifdef ENDPOINT_HALT_CALLBACK
-					ENDPOINT_HALT_CALLBACK(setup->wIndex, (setup->bRequest == SET_FEATURE));
-#endif
-					stall = 0;
-				}
-			}
-		}
-
-		if (!stall) {
-			send_zero_length_packet_ep0();
-		}
-		else
-			stall_ep0();
-	}
-	else {
-		res = -1;
-
-		SERIAL("unsupported request (req, dest, type, dir) ");
-		SERIAL_VAL(setup->bRequest);
-		SERIAL_VAL(setup->REQUEST.destination);
-		SERIAL_VAL(setup->REQUEST.type);
-		SERIAL_VAL(setup->REQUEST.direction);
-	}
-
-	return res;
-}
-
-static inline void handle_ep0_setup()
-{
-	FAR struct setup_packet *setup;
-#ifdef PPB_EP0_OUT
-	if (SFR_USB_STATUS_PPBI)
-		setup = (struct setup_packet*) ep0_buf.out1;
-	else
-		setup = (struct setup_packet*) ep0_buf.out;
-#else
-	setup = (struct setup_packet*) ep0_buf.out;
-#endif
-
-	ep0_data_stage_direc = setup->REQUEST.direction;
-	int8_t res;
-
-#ifdef NEEDS_CLEAR_STALL
-	/* The datasheets say the MCU will clear BSTALL and UOWN when
-	 * a SETUP packet is received. This does not seem to happen on
-	 * PIC16 or PIC18, so clear the stall explicitly. */
-	clear_ep0_stall();
-#endif
-
-	/* Receiving a Setup packet cancels any control transfer which was
-	 * in progress and thus invalidates any IN transactions which were
-	 * pending for a previous control transfer. Cancel any of these IN
-	 * transactions which were pending. */
-#ifdef PPB_EP0_OUT
-	/* For ping-pong mode on EP 0, note below that ppbi is the next
-	 * ping-pong buffer which would be written to, meaning that !ppbi is
-	 * the buffer which would have an IN transaction pending (if any).
-	 *
-	 * Only one ping-pong buffer is cleared (instead of both) because
-	 * M-Stack only puts one transfer at a time on the control IN endpoint.
-	 */
-	uint8_t ppbi = (ep0_buf.flags & EP_TX_PPBI)? 1: 0;
-	if (BDS0IN(!ppbi).STAT.UOWN) {
-		SET_BDN(BDS0IN(!ppbi), 0, EP_0_LEN);
-		ep0_buf.flags ^= EP_TX_PPBI;
-	}
-#else
-	if (BDS0IN(0).STAT.UOWN) {
-		SET_BDN(BDS0IN(0), 0, EP_0_LEN);
-	}
-#endif
-
-	if (ep0_data_stage_buf_remaining) {
-		/* A SETUP transaction has been received while waiting
-		 * for a DATA stage to complete; something is broken.
-		 * If this was an application-controlled transfer (and
-		 * there's a callback), notify the application of this. */
-		if (ep0_data_stage_callback)
-			ep0_data_stage_callback(0/*fail*/, ep0_data_stage_context);
-
-		reset_ep0_data_stage();
-	}
-
-	if (setup->REQUEST.type == REQUEST_TYPE_STANDARD) {
-		res = handle_standard_control_request();
-		if (res < 0)
-			goto handle_unknown;
-	}
-#ifdef MICROSOFT_OS_DESC_VENDOR_CODE
-	else if (setup->bRequest == MICROSOFT_OS_DESC_VENDOR_CODE) {
-		const void *desc;
-		int16_t len = -1;
-
-		if (setup->REQUEST.bmRequestType == 0xC0 &&
-		    setup->wIndex == 0x0004) {
-			len = MICROSOFT_COMPAT_ID_DESCRIPTOR_FUNC(
-				setup->wValue,
-				&desc);
-		}
-		else if (setup->REQUEST.bmRequestType == 0xC1 &&
-		         setup->wIndex == 0x0005) {
-			len = MICROSOFT_CUSTOM_PROPERTY_DESCRIPTOR_FUNC(
-				setup->wValue,
-				&desc);
-		}
-
-		if (len < 0)
-			stall_ep0();
-		else
-			start_control_return(desc, len, setup->wLength);
-	}
-#endif
-	else
-		goto handle_unknown;
-
-	goto out;
-
-handle_unknown:
-
-#ifdef UNKNOWN_SETUP_REQUEST_CALLBACK
-	res = UNKNOWN_SETUP_REQUEST_CALLBACK(setup);
-	if (res < 0)
-		stall_ep0();
-	else {
-		/* If the application has handled this request, it
-		 * will have already set up whatever needs to be set
-		 * up for the data stage. */
-	}
-#else
-	/* Unsupported Request. Stall the Endpoint. */
-	stall_ep0();
-#endif
-
-out:
-	/* SETUP packet sets PKTDIS which disables
-	 * future SETUP packet reception. Turn it off
-	 * afer we've processed the current SETUP
-	 * packet to avoid a race condition. */
-	SFR_USB_PKT_DIS = 0;
-}
-
-static inline void handle_ep0_out()
-{
-#ifdef PPB_EP0_OUT
-	uint8_t pkt_len = BDN_LENGTH(BDS0OUT(SFR_USB_STATUS_PPBI));
-#else
-	uint8_t pkt_len = BDN_LENGTH(BDS0OUT(0));
-#endif
-	if (ep0_data_stage_direc == 1/*1=IN*/) {
-		/* An empty OUT packet on an IN control transfer
-		 * means the STATUS stage of the control
-		 * transfer has completed (possibly early). */
-
-		/* Notify the application (if applicable) */
-		if (ep0_data_stage_callback)
-			ep0_data_stage_callback(1/*true*/, ep0_data_stage_context);
-		reset_ep0_data_stage();
-	}
-	else {
-		/* A packet received as part of the data stage of
-		 * a control transfer. Pack what data we received
-		 * into the application's buffer (if it has
-		 * provided one). When all the data has been
-		 * received, call the application-provided callback.
-		 */
-
-		if (ep0_data_stage_out_buffer) {
-			uint8_t bytes_to_copy = MIN(pkt_len, ep0_data_stage_buf_remaining);
-#ifdef PPB_EP0_OUT
-			if (SFR_USB_STATUS_PPBI)
-				memcpy(ep0_data_stage_out_buffer, ep0_buf.out1, bytes_to_copy);
-			else
-				memcpy(ep0_data_stage_out_buffer, ep0_buf.out, bytes_to_copy);
-#else
-			memcpy(ep0_data_stage_out_buffer, ep0_buf.out, bytes_to_copy);
-#endif
-			ep0_data_stage_out_buffer += bytes_to_copy;
-			ep0_data_stage_buf_remaining -= bytes_to_copy;
-
-			/* It's possible that bytes_to_copy is less than pkt_len
-			 * here because the application provided too small a buffer. */
-
-			if (pkt_len < EP_0_OUT_LEN || ep0_data_stage_buf_remaining == 0) {
-				/* Short packet or we've received the expected length.
-				 * All data has been transferred (or all the data
-				 * has been received which can be received). */
-
-				if (bytes_to_copy < pkt_len) {
-					/* The buffer provided by the application was too short */
-					stall_ep0();
-					if (ep0_data_stage_callback)
-						ep0_data_stage_callback(0/*false*/, ep0_data_stage_context);
-					reset_ep0_data_stage();
-				}
-				else {
-					/* The data stage has completed. Set up the status stage. */
-					send_zero_length_packet_ep0();
-				}
-			}
-		}
-	}
-}
-
-static inline void handle_ep0_in()
-{
-	if (addr_pending) {
-		SFR_USB_ADDR =  addr;
-		addr_pending = 0;
-	}
-
-	if (ep0_data_stage_buf_remaining) {
-		/* There's already a multi-transaction transfer in process. */
-		uint8_t bytes_to_send = MIN(ep0_data_stage_buf_remaining, EP_0_IN_LEN);
-
-		copy_to_ep0_in_buf(ep0_data_stage_in_buffer, bytes_to_send);
-		ep0_data_stage_buf_remaining -= bytes_to_send;
-		ep0_data_stage_in_buffer += bytes_to_send;
-
-		/* If we hit the end with a full-length packet, set up
-		   to send a zero-length packet at the next IN token, but only
-		   if we are returning less data than was requested. */
-		if (ep0_data_stage_buf_remaining == 0 &&
-		    bytes_to_send == EP_0_IN_LEN &&
-		    returning_short)
-			control_need_zlp = 1;
-
-		usb_send_in_buffer_0(bytes_to_send);
-	}
-	else if (control_need_zlp) {
-		usb_send_in_buffer_0(0);
-		control_need_zlp = 0;
-		reset_ep0_data_stage();
-	}
-	else {
-		if (ep0_data_stage_direc == 0/*OUT*/) {
-			/* An IN on the control endpoint with no data pending
-			 * and during an OUT transfer means the STATUS stage
-			 * of the control transfer has completed. Notify the
-			 * application, if applicable. */
-			if (ep0_data_stage_callback)
-				ep0_data_stage_callback(1/*true*/, ep0_data_stage_context);
-			reset_ep0_data_stage();
-		}
-	}
-}
-
-/* checkUSB() is called repeatedly to check for USB interrupts
-   and service USB requests */
-void usb_service(void)
-{
-	if (SFR_USB_RESET_IF) {
-		/* A Reset was detected on the wire. Re-init the SIE. */
-#ifdef USB_RESET_CALLBACK
-		USB_RESET_CALLBACK();
-#endif
-		usb_init();
-		CLEAR_USB_RESET_IF();
-		SERIAL("USB Reset");
-	}
-	
-	if (SFR_USB_STALL_IF) {
-		/* On PIC24/32, EPSTALL bits must be cleared, or else the
-		 * stalled endpoint's opposite direction (eg: EP1 IN => EP1
-		 * OUT) will also stall (incorrectly). There is no way to
-		 * determine which endpoint generated this interrupt, so all
-		 * the endpoints' EPSTALL bits must be checked and cleared. */
-		int i;
-		for (i = 1; i <= NUM_ENDPOINT_NUMBERS; i++) {
-			volatile SFR_EP_MGMT_TYPE *ep = SFR_EP_MGMT(i);
-			ep->SFR_EP_MGMT_STALL = 0;
-		}
-
-		CLEAR_USB_STALL_IF();
-	}
-
-
-#ifdef USB_USE_INTERRUPTS
-	if (SFR_USB_TOKEN_IF && SFR_TRANSFER_IE) {
-#else
-	if (SFR_USB_TOKEN_IF) {
-#endif
-
-		//struct ustat_bits ustat = *((struct ustat_bits*)&USTAT);
-
-		if (SFR_USB_STATUS_EP == 0 && SFR_USB_STATUS_DIR == 0/*OUT*/) {
-			/* An OUT or SETUP transaction has completed on
-			 * Endpoint 0.  Handle the data that was received.
-			 */
-#ifdef PPB_EP0_OUT
-			uint8_t pid = BDS0OUT(SFR_USB_STATUS_PPBI).STAT.PID;
-#else
-			uint8_t pid = BDS0OUT(0).STAT.PID;
-#endif
-			if (pid == PID_SETUP) {
-				handle_ep0_setup();
-			}
-			else if (pid == PID_IN) {
-				/* Nonsense condition:
-				   (PID IN on SFR_USB_STATUS_DIR == OUT) */
-			}
-			else if (pid == PID_OUT) {
-				handle_ep0_out();
-			}
-			else {
-				/* Unsupported PID. Stall the Endpoint. */
-				SERIAL("Unsupported PID. Stall.");
-				stall_ep0();
-			}
-
-			reset_bd0_out();
-		}
-		else if (SFR_USB_STATUS_EP == 0 && SFR_USB_STATUS_DIR == 1/*1=IN*/) {
-			/* An IN transaction has completed. The endpoint
-			 * needs to be re-loaded with the next transaction's
-			 * data if there is any.
-			 */
-			handle_ep0_in();
-		}
-		else if (SFR_USB_STATUS_EP > 0 && SFR_USB_STATUS_EP <= NUM_ENDPOINT_NUMBERS) {
-			if (SFR_USB_STATUS_DIR == 1 /*1=IN*/) {
-				/* An IN transaction has completed. */
-				SERIAL("IN transaction completed on non-EP0.");
-				if (ep_buf[SFR_USB_STATUS_EP].flags & EP_IN_HALT_FLAG)
-					stall_ep_in(SFR_USB_STATUS_EP);
-				else {
-#ifdef IN_TRANSACTION_COMPLETE_CALLBACK
-					IN_TRANSACTION_COMPLETE_CALLBACK(SFR_USB_STATUS_EP);
-#endif
-				}
-			}
-			else {
-				/* An OUT transaction has completed. */
-				SERIAL("OUT transaction received on non-EP0");
-				if (ep_buf[SFR_USB_STATUS_EP].flags & EP_OUT_HALT_FLAG)
-					stall_ep_out(SFR_USB_STATUS_EP);
-				else {
-#ifdef OUT_TRANSACTION_CALLBACK
-					OUT_TRANSACTION_CALLBACK(SFR_USB_STATUS_EP);
-#endif
-				}
-			}
-		}
-		else {
-			/* Transaction completed on an endpoint not used.
-			 * This should never happen. */
-			SERIAL("Transaction completed for unknown endpoint");
-		}
-
-		CLEAR_USB_TOKEN_IF();
-	}
-	
-	/* Check for Start-of-Frame interrupt. */
-	if (SFR_USB_SOF_IF) {
-#ifdef START_OF_FRAME_CALLBACK
-		START_OF_FRAME_CALLBACK();
-#endif
-		CLEAR_USB_SOF_IF();
-	}
-
-	/* Check for USB Interrupt. */
-	if (SFR_USB_IF) {
-		SFR_USB_IF = 0;
-	}
-}
-
-uint8_t usb_get_configuration(void)
-{
-	return g_configuration;
-}
-
-unsigned char *usb_get_in_buffer(uint8_t endpoint)
-{
-#ifdef PPB_EPn
-	if (ep_buf[endpoint].flags & EP_TX_PPBI /*odd*/)
-		return ep_buf[endpoint].in1;
-	else
-		return ep_buf[endpoint].in;
-#else
-	return ep_buf[endpoint].in;
-#endif
-}
-
-void usb_send_in_buffer(uint8_t endpoint, size_t len)
-{
-#ifdef DEBUG
-	if (endpoint == 0)
-		error();
-#endif
-	if (g_configuration > 0 && !usb_in_endpoint_halted(endpoint)) {
-		uint8_t pid;
-		struct buffer_descriptor *bd;
-#ifdef PPB_EPn
-		uint8_t ppbi = (ep_buf[endpoint].flags & EP_TX_PPBI)? 1 : 0;
-
-		bd = &BDSnIN(endpoint,ppbi);
-		pid = (ep_buf[endpoint].flags & EP_TX_DTS)? 1 : 0;
-		bd->STAT.BDnSTAT = 0;
-
-		if (pid)
-			SET_BDN(BDSnIN(endpoint,ppbi),
-				BDNSTAT_UOWN|BDNSTAT_DTS|BDNSTAT_DTSEN, len);
-		else
-			SET_BDN(BDSnIN(endpoint,ppbi),
-				BDNSTAT_UOWN|BDNSTAT_DTSEN, len);
-
-		ep_buf[endpoint].flags ^= EP_TX_PPBI;
-		ep_buf[endpoint].flags ^= EP_TX_DTS;
-#else
-		bd = &BDSnIN(endpoint,0);
-		pid = (ep_buf[endpoint].flags & EP_TX_DTS)? 1 : 0;
-		bd->STAT.BDnSTAT = 0;
-
-		if (pid)
-			SET_BDN(*bd,
-				BDNSTAT_UOWN|BDNSTAT_DTS|BDNSTAT_DTSEN, len);
-		else
-			SET_BDN(*bd,
-				BDNSTAT_UOWN|BDNSTAT_DTSEN, len);
-
-		ep_buf[endpoint].flags ^= EP_TX_DTS;
-#endif
-	}
-}
-
-bool usb_in_endpoint_busy(uint8_t endpoint)
-{
-#ifdef PPB_EPn
-	uint8_t ppbi = (ep_buf[endpoint].flags & EP_TX_PPBI)? 1: 0;
-	return BDSnIN(endpoint, ppbi).STAT.UOWN;
-#else
-	return BDSnIN(endpoint,0).STAT.UOWN;
-#endif
-}
-
-uint8_t usb_halt_ep_in(uint8_t ep)
-{
-	if (ep == 0 || ep > NUM_ENDPOINT_NUMBERS)
-		return -1;
-
-	ep_buf[ep].flags |= EP_IN_HALT_FLAG;
-	stall_ep_in(ep);
-
-	return 0;
-}
-
-bool usb_in_endpoint_halted(uint8_t endpoint)
-{
-	return ep_buf[endpoint].flags & EP_IN_HALT_FLAG;
-}
-
-uint8_t usb_get_out_buffer(uint8_t endpoint, const unsigned char **buf)
-{
-#ifdef PPB_EPn
-	uint8_t ppbi = (ep_buf[endpoint].flags & EP_RX_PPBI)? 1: 0;
-
-	if (ppbi /*odd*/)
-		*buf = ep_buf[endpoint].out1;
-	else
-		*buf = ep_buf[endpoint].out;
-
-	return BDN_LENGTH(BDSnOUT(endpoint, ppbi));
-#else
-	*buf = ep_buf[endpoint].out;
-	return BDN_LENGTH(BDSnOUT(endpoint, 0));
-#endif
-}
-
-bool usb_out_endpoint_has_data(uint8_t endpoint)
-{
-#ifdef PPB_EPn
-	uint8_t ppbi = (ep_buf[endpoint].flags & EP_RX_PPBI)? 1: 0;
-	return !BDSnOUT(endpoint,ppbi).STAT.UOWN;
-#else
-	return !BDSnOUT(endpoint,0).STAT.UOWN;
-#endif
-}
-
-void usb_arm_out_endpoint(uint8_t endpoint)
-{
-#ifdef PPB_EPn
-	uint8_t ppbi = (ep_buf[endpoint].flags & EP_RX_PPBI)? 1: 0;
-	uint8_t pid = (ep_buf[endpoint].flags & EP_RX_DTS)? 1: 0;
-
-	if (pid)
-		SET_BDN(BDSnOUT(endpoint,ppbi),
-			BDNSTAT_UOWN|BDNSTAT_DTSEN|BDNSTAT_DTS,
-			ep_buf[endpoint].out_len);
-	else
-		SET_BDN(BDSnOUT(endpoint,ppbi),
-			BDNSTAT_UOWN|BDNSTAT_DTSEN,
-			ep_buf[endpoint].out_len);
-
-	/* Alternate the PPBI */
-	ep_buf[endpoint].flags ^= EP_RX_PPBI;
-	ep_buf[endpoint].flags ^= EP_RX_DTS;
-
-#else
-	uint8_t pid = (ep_buf[endpoint].flags & EP_RX_DTS)? 1: 0;
-	if (pid)
-		SET_BDN(BDSnOUT(endpoint,0),
-			BDNSTAT_UOWN|BDNSTAT_DTS|BDNSTAT_DTSEN,
-			ep_buf[endpoint].out_len);
-	else
-		SET_BDN(BDSnOUT(endpoint,0),
-			BDNSTAT_UOWN|BDNSTAT_DTSEN,
-			ep_buf[endpoint].out_len);
-
-	ep_buf[endpoint].flags ^= EP_RX_DTS;
-#endif
-
-}
-
-uint8_t usb_halt_ep_out(uint8_t ep)
-{
-	if (ep == 0 || ep > NUM_ENDPOINT_NUMBERS)
-		return -1;
-
-	ep_buf[ep].flags |= EP_OUT_HALT_FLAG;
-	stall_ep_out(ep);
-
-	return 0;
-}
-
-bool usb_out_endpoint_halted(uint8_t endpoint)
-{
-	return ep_buf[endpoint].flags & EP_OUT_HALT_FLAG;
-}
-
-void usb_start_receive_ep0_data_stage(char *buffer, size_t len,
-                                      usb_ep0_data_stage_callback callback, void *context)
-{
-	reset_ep0_data_stage();
-
-	ep0_data_stage_callback = callback;
-	ep0_data_stage_out_buffer = buffer;
-	ep0_data_stage_buf_remaining = len;
-	ep0_data_stage_context = context;
-}
-
-void usb_send_data_stage(char *buffer, size_t len,
-	usb_ep0_data_stage_callback callback, void *context)
-{
-	/* Start sending the first block. Subsequent blocks will be sent
-	   when IN tokens are received on endpoint zero. */
-	ep0_data_stage_callback = callback;
-	ep0_data_stage_context = context;
-	start_control_return(buffer, len, len);
-}
-
-/* Private Functions */
-
-#ifdef USB_USE_INTERRUPTS
-/* Manipulate the transaction (token) interrupt.  There is no stack or
- * counter used to keep track of enable/disable calls, so care must be used
- * to ensure that calls to these functions are not nested.  */
-void usb_disable_transaction_interrupt()
-{
-	SFR_TRANSFER_IE = 0;
-}
-void usb_enable_transaction_interrupt()
-{
-	SFR_TRANSFER_IE = 1;
-}
-#endif
-
-
-#ifdef USB_USE_INTERRUPTS
-#ifdef __XC16__
-
-void _ISR __attribute((auto_psv)) _USB1Interrupt()
-{
-	usb_service();
-}
-
-#elif __XC32__
-
-/* No parameter for interrupt() means to use IPL=RIPL and to detect whether
-   to use shadow registers or not. This is the safest option, but if a user
-   wanted maximum performance, they could use IPL7SRS and set the USBIP to 7.
-   IPL 7 is the only time the shadow register set can be used on PIC32MX. */
-void __attribute__((vector(_USB_1_VECTOR), interrupt(), nomips16)) _USB1Interrupt()
-{
-	usb_service();
-}
-
-#elif __C18
-#elif __XC8
-	/* On these systems, interupt handlers are shared. An interrupt
-	 * handler from the application must call usb_service(). */
-#else
-#error Compiler not supported yet
-#endif
-#endif
\ No newline at end of file
--- a/usb/usb.h	Wed Feb 17 05:54:21 2016 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,594 +0,0 @@
-/*
- *  M-Stack Public API Header File
- *  Copyright (C) 2013 Alan Ott <alan@signal11.us>
- *  Copyright (C) 2013 Signal 11 Software
- *
- *  3-12-2008
- *
- *  M-Stack is free software: you can redistribute it and/or modify it under
- *  the terms of the GNU Lesser General Public License as published by the
- *  Free Software Foundation, version 3; or the Apache License, version 2.0
- *  as published by the Apache Software Foundation.  If you have purchased a
- *  commercial license for this software from Signal 11 Software, your
- *  commerical license superceeds the information in this header.
- *
- *  M-Stack is distributed in the hope that it will be useful, but WITHOUT
- *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
- *  License for more details.
- *
- *  You should have received a copy of the GNU Lesser General Public License
- *  along with this software.  If not, see <http://www.gnu.org/licenses/>.
- *
- *  You should have received a copy of the Apache License, verion 2.0 along
- *  with this software.  If not, see <http://www.apache.org/licenses/>.
- */
-
-#ifndef USB_H_
-#define USB_H_
-
-/** @file usb.h
- *  @brief M-Stack
- *  @defgroup public_api Public API
- */
-
-/** @addtogroup public_api
- *  @{
- */
-
-#include <stdint.h>
-#include <stdbool.h>
-#include <stdlib.h>
-
-#include "usb_config.h"
-
-/* setup_packet is defined in usb_ch9.h */
-struct setup_packet;
-
-/** @defgroup descriptor_items   Descriptor Items
- *  @brief Items defined by the application which are involved in
- *  the enumeration of the device.
- *
- *  The items listed in this section are macro names. An application needs
- *  to define these macro names in usb_config.h to whatever actual C names
- *  are used in the application for these items (typically in
- *  usb_descriptors.c).
- *
- *  It is required that the application #define these items in the
- *  application's @p usb_config.h so the USB stack can retrieve the Chapter
- *  9 descriptors to send to the host.
- *
- *  While this sounds complex, it is not. See the example programs and their
- *  usb_descriptors.c that come with the USB stack for an example of what is
- *  required and how to easily implement it.
- *
- *  @addtogroup descriptor_items
- *  @{
- */
-
-
-/** String Descriptor Function
- *
- * The USB stack will call this function to retrieve string descriptors from
- * the application. This allows the flexibility for the application to read
- * some strings (like serial numbers) from non-const locations (like EEPROM).
- *
- * @param string_number   The string number requested
- * @param ptr             A pointer to a pointer which should be set to the
- *                        requested string descriptor by this function.
- * @returns
- *   Return the length of the string descriptor in bytes or -1 if the string
- *   requested does not exist.
- */
-extern int16_t USB_STRING_DESCRIPTOR_FUNC(uint8_t string_number, const void **ptr);
-
-/** Device Descriptor
- *
- * This is the device's device descriptor as defined by the USB
- * specification, chapter 9.  @p USB_DEVICE_DESCRIPTOR must be defined in
- * usb_config.h to be the name of the device descriptor structure, which
- * will often be located in the application's usb_descriptors.c.
- */
-extern const struct device_descriptor USB_DEVICE_DESCRIPTOR;
-
-/** Configuration Descriptor
- *
- * This is an array of the device's configuration descriptors, as defined by
- * the USB specification, chapter 9.  USB_CONFIG_DESCRIPTOR_MAP must be
- * defined to be the name of an array of pointers to
- * configuration_descriptor objects, often in the application's
- * usb_descriptors.c.  The order is not important because the @p
- * bConfigurationValue field is used by the USB stack to determine the
- * configuration number for each configuration descriptor.  It is important
- * that wTotalLength in each configuration descriptor be correct, as this is
- * used by the USB stack to determine the number of bytes to use (It is
- * recommended to use the sizeof() operator for this field).
- *
- * See the example programs that come with the USB stack (specificallyl
- * usb_descriptors.c) for a simple example of what is required.
- */
-extern const struct configuration_descriptor *USB_CONFIG_DESCRIPTOR_MAP[];
-
-
-/* Doxygen end-of-group for descriptor_items */
-/** @}*/
-
-
-
- /** @defgroup static_callbacks Static Callbacks
-  *  @brief Optional static callback macros to be defined in the
-  *  application's usb_config.h.
-  *
-  *  If desired, #define these callback functions in your application's
-  *  @p usb_config.h to receive notification about specific events which
-  *  happen during enumeration and otherwise. While these are not strictly
-  *  required for all devices, they may be required depending on your
-  *  device configuration.
-  *
-  *  @addtogroup static_callbacks
-  *  @{
-  */
-
-#ifdef SET_CONFIGURATION_CALLBACK
-/** @brief Callback for SET_CONFIGURATION requests
- *
- * SET_CONFIGURATION_CALLBACK() is called whenever a @a SET_CONFIGURATION
- * request is received from the host.  The configuration parameter is the
- * new configuration the host requests.  If configuration is zero, then the
- * device is to enter the @a ADDRESS state.  If it is non-zero then the device
- * is to enter the @a CONFIGURED state.
- *
- * There's no way to reject this request. The host commands a configuration
- * be set, and it shall be done.
- */
-void SET_CONFIGURATION_CALLBACK(uint8_t configuration);
-#endif
-
-#ifdef GET_DEVICE_STATUS_CALLBACK
-/** @brief Callback for GET_STATUS requests
- *
- * GET_DEVICE_STATUS_CALLBACK() is called when a @a GET_STATUS request is
- * received from the host for the device (not the interface or the endpoint).
- * The callback is to return the status of the device as a 16-bit
- * unsigned integer per section 9.4.5 of the USB 2.0 specification.
- *   Bit 0 (LSB) - 0=bus_powered, 1=self_powered
- *   Bit 1       - 0=no_remote_wakeup, 1=remote_wakeup
- *   Bits 2-15   - reserved, set to zero.
- */
-uint16_t GET_DEVICE_STATUS_CALLBACK();
-#endif
-
-#ifdef ENDPOINT_HALT_CALLBACK
-/** @brief Callback for SET_FEATURE or CLEAR_FEATURE with ENDPOINT_HALT
- *
- * ENDPOINT_HALT_CALLBACK() is called when a @a SET_FEATURE or @a
- * CLEAR_FEATURE is received from the host changing the endpoint halt value.
- * This is a notification only.  There is no way to reject this request.
- *
- * @brief endpoint   The endpoint identifier of the affected endpoint
- *                   (direction and number, e.g.: 0x81 means EP 1 IN).
- * @brief halted     1=endpoint_halted (set), 0=endpoint_not_halted (clear)
- */
-void ENDPOINT_HALT_CALLBACK(uint8_t endpoint, bool halted);
-#endif
-
-#ifdef SET_INTERFACE_CALLBACK
-/** @brief Callback for the SET_INTERFACE request
- *
- * SET_INTERFACE_CALLBACK() is called when a @a SET_INTERFACE request is
- * received from the host.  @a SET_INTERFACE is used to set the alternate
- * setting for the specified interface.  The parameters @p interface and @p
- * alt_setting come directly from the device request (from the host).  The
- * callback should return 0 if the new alternate setting can be set or -1 if
- * it cannot.  This callback is completely unnecessary if you only have one
- * alternate setting (alternate setting zero) for each interface.
- *
- * @param interface     The interface on which to set the alternate setting
- * @param alt_setting   The alternate setting
- * @returns
- *   Return 0 for success and -1 for error (will send a STALL to the host)
- */
-int8_t SET_INTERFACE_CALLBACK(uint8_t interface, uint8_t alt_setting);
-#endif
-
-#ifdef GET_INTERFACE_CALLBACK
-/** @brief Callback for the GET_INTERFACE request
- *
- * GET_INTERFACE_CALLBACK() is called when a @a GET_INTERFACE request is
- * received from the host.  @a GET_INTERFACE is a request for the current
- * alternate setting selected for a given interface.  The application should
- * return the interface's current alternate setting from this callback
- * function.  If this callback is not present, zero will be returned as the
- * current alternate setting for all interfaces.
- *
- * @param interface   The interface queried for current altertate setting
- * @returns
- *   Return the current alternate setting for the interface requested or -1
- *   if the interface does not exist.
- */
-int8_t GET_INTERFACE_CALLBACK(uint8_t interface);
-#endif
-
-#ifdef OUT_TRANSACTION_CALLBACK
-/** @brief Callback for an OUT transaction
- *
- * OUT_TRANSACTION_CALLBACK() is called when a transaction has completed
- * on an endpoint numbered 1 through 15, that is when data has been received
- * from the host. The application may then get the data received by calling
- * @p usb_get_out_buffer(), and can then re-arm the endpoint by calling @p
- * usb_arm_out_endpoint(). The application may choose to not re-arm the
- * endpoint if the application intends to do it at a later time.
- *
- * This function is called from interrupt context and should not block.
- *
- * @param endpoint   The endpoint on which the transfer completed
- */
-void OUT_TRANSACTION_CALLBACK(uint8_t endpoint);
-#endif
-
-
-#ifdef IN_TRANSACTION_COMPLETE_CALLBACK
-/** @brief Callback for an IN transaction
- *
- * IN_TRANSACTION_COMPLETE_CALLBACK() is called when an IN transaction has
- * completed on an endpoint numbered 1 through 15, meaning the transaction
- * has successfully been delivered to the host. The application may send
- * another transaction to the host using @p usb_get_in_buffer() and @p
- * usb_send_in_buffer() from this callback if desired.
- *
- * This function is called from interrupt context and should not block.
- *
- * @param endpoint   The endpoint on which the transfer completed
- */
-void IN_TRANSACTION_COMPLETE_CALLBACK(uint8_t endpoint);
-#endif
-
-#ifdef UNKNOWN_SETUP_REQUEST_CALLBACK
-/** @brief Callback for an unrecognized SETUP request
- *
- * UNKNOWN_SETUP_REQUEST_CALLBACK() is called when a SETUP packet is
- * received with a request (bmRequestType,bRequest) which is unknown to the
- * the USB stack.  This could be because it is a vendor-defined request or
- * because it is some other request which is not supported, for example if
- * you were implementing a device class in your application.  There are four
- * ways to handle this:
- *
- * 0. For unknown requests, return -1. This will send a STALL to the host.
- * 1. For requests which have no data stage, the callback should call
- *    @p usb_send_data_stage() with a length of zero to send a zero-length
- *    packet back to the host.
- * 2. For requests which expect an IN data stage, the callback should call
- *    @p usb_send_data_stage() with the data to be sent, and a callback
- *    which will get called when the data stage is complete.  The callback
- *    is required, and the data buffer passed to @p usb_send_data_stage()
- *    must remain valid until the callback is called.
- * 3. For requests which will come with an OUT data stage, the callback
- *    should call @p usb_start_receive_ep0_data_stage() and provide a
- *    buffer and a callback which will get called when the data stage has
- *    completed.  The callback is required, and the data in the buffer
- *    passed to usb_start_receive_ep0_data_stage() is not valid until the
- *    callback is called.
- *
- * It is worth noting that only one control transfer can be active at any
- * given time.  Once UNKNOWN_SETUP_REQUEST_CALLBACK() has been called, it
- * will not be called again until the next transfer, meaning that if the
- * application-provided UNKNOWN_SETUP_REQUEST_CALLBACK() function performs
- * one of options 1-3 above, the callback function passed to @p
- * usb_send_data_stage() or @p usb_start_receive_ep0_data_stage() will be
- * called before UNKNOWN_SETUP_REQUEST_CALLBACK() can be called again.
- * Thus, it is safe to use the same buffer for all control transfers if
- * desired.
- *
- * Make sure to include @p usb_ch9.h in order to use the @p setup_packet
- * structure.
- *
- * @param pkt   The SETUP packet
- * @returns
- *   Return 0 if the SETUP can be handled or -1 if it cannot. Returning -1
- *   will cause STALL to be returned to the host.
- */
-int8_t UNKNOWN_SETUP_REQUEST_CALLBACK(const struct setup_packet *pkt);
-#endif
-
-#ifdef UNKNOWN_GET_DESCRIPTOR_CALLBACK
-/** @brief Callback for a GET_DESCRIPTOR request for an unknown descriptor
- *
- * UNKNOWN_GET_DESCRIPTOR_CALLBACK() is called when a @a GET_DESCRIPTOR
- * request is received from the host for a descriptor which is unrecognized
- * by the USB stack.  This could be because it is a vendor-defined
- * descriptor or because it is some other descriptor which is not supported,
- * for example if you were implementing a device class in your application.
- * The callback function should set the @p descriptor pointer and return the
- * number of bytes in the descriptor.  If the descriptor is not supported,
- * the callback should return -1, which will cause a STALL to be sent to the
- * host.
- *
- * Make sure to include @p usb_ch9.h in order to use the @p setup_packet
- * structure.
- *
- * @param pkt          The SETUP packet with the request in it.
- * @param descriptor   a pointer to a pointer which should be set to the
- *                     descriptor data.
- * @returns
- *   Return the length of the descriptor pointed to by @p *descriptor, or -1
- *   if the descriptor does not exist.
- */
-int16_t UNKNOWN_GET_DESCRIPTOR_CALLBACK(const struct setup_packet *pkt, const void **descriptor);
-#endif
-
-#ifdef START_OF_FRAME_CALLBACK
-/** @brief Callback for USB Start of Frame event
- *
- * START_OF_FRAME_CALLBACK() is called when a USB Start-of-Frame packet is
- * received from the host.  For full-speed devices, this happens every 1
- * millisecond.  For high-speed devices, this happens every 125
- * microseconds.  Low-speed devices do not receive a Start-of-Frame packet.
- */
-void START_OF_FRAME_CALLBACK(void);
-#endif
-
-#ifdef USB_RESET_CALLBACK
-/** @brief USB Reset Callback
- *
- * USB_RESET_CALLBACK() is called when a reset event is detected on the bus.
- * Two bus resets are part of the normal enumeration sequence.  This
- * function is called before the USB stack does any re-initialization.
- */
-void USB_RESET_CALLBACK(void);
-#endif
-
-/* Doxygen end-of-group for static_callbacks */
-/** @}*/
-
-/** @brief Initialize the USB library and hardware
- *
- * Call this function at the beginning of execution. This function initializes
- * the USB peripheral hardware and software library. After calling this
- * funciton, the library will handle enumeration automatically when attached
- * to a host.
- */
-void usb_init(void);
-
-/** @brief Update the USB library and hardware
- *
- * This function services the USB peripheral's interrupts and handles all
- * tasks related to enumeration and transfers. It is non-blocking. Whether an
- * application should call this function depends on the @p USB_USE_INTERRUPTS
- * #define. If @p USB_USE_INTERRUPTS is not defined, this function should be
- * called periodically from the main application. If @p USB_USE_INTERRUPTS is
- * defined, it should be called from interrupt context. On PIC24, this will
- * happen automatically, as the interrupt handler is embedded in usb.c. On
- * 8-bit PIC since the interrupt handlers are shared, this function will need
- * to be called from the application's interrupt handler.
- */
-void usb_service(void);
-
-/** @brief Get the device configuration
- *
- * Get the device configuration as set by the host. If the device is not
- * in the CONFIGURED state, 0 will be returned.
- *
- * @see usb_is_configured()
- * @returns
- *   Return the device configuration or 0 if the device is not configured.
- */
-uint8_t usb_get_configuration(void);
-
-/** @brief Determine whether the device is in the Configured state
- *
- * Return whether the device is in the configured state. During enumeration,
- * the device will start at the DEFAULT state, transition through ADDRESS,
- * and eventually reach CONFIGURED.  The host can also command the device
- * out of the configured state (and back into ADDRESS).  The application
- * shouldn't use any of the endpoints unless in the CONFIGURED state.
- *
- * @see usb_get_configuration()
- */
-#define usb_is_configured() (usb_get_configuration() != 0)
-
-/** @brief Get a pointer to an endpoint's input buffer
- *
- * This function returns a pointer to an endpoint's input buffer. Call this
- * to get a location to copy IN data to in order to send it to the host.
- * Remember that IN data is data which goes from the device to the host.
- * The maximum length of this buffer is defined by the application in
- * usb_config.h (eg: @p EP_1_IN_LEN).  It is wise to call
- * @p usb_in_endpoint_busy() before calling this function.
- *
- * @param endpoint   The endpoint requested
- * @returns
- *   Return a pointer to the endpoint's buffer.
- */
-unsigned char *usb_get_in_buffer(uint8_t endpoint);
-
-/** @brief Send an endpoint's IN buffer to the host
- *
- * Send the data in the IN buffer for the specified endpoint to the host.
- * Since USB is a polled bus, this only queues the data for sending. It will
- * actually be sent when the device receives an IN token for the specified
- * endpoint. To check later whether the data has been sent, call
- * @p usb_in_endpoint_busy(). If the endpoint is busy, a transmission is
- * pending, but has not been actually transmitted yet.
- *
- * @param endpoint   The endpoint on which to send data
- * @param len        The amount of data to send
- */
-void usb_send_in_buffer(uint8_t endpoint, size_t len);
-
-/** @brief Check whether an IN endpoint is busy
- *
- * An IN endpoint is said to be busy if there is data in its buffer and it
- * is waiting for an IN token from the host in order to send it (or if it is
- * in the process of sending the data).
- *
- * @param endpoint   The endpoint requested
- * @returns
- *    Return true if the endpoint is busy, or false if it is not.
- */
-bool usb_in_endpoint_busy(uint8_t endpoint);
-
-/** @brief Halt an IN endpoint
- *
- * Set the ENDPOINT_HALT condition on an IN endpoint. Do not call this on
- * endpoint zero.
- *
- * @param endpoint   The endpoint requested
- * @returns
- *    Return 0 if the endpoint can be halted, or -1 if the endpoint number
- *    is invalid.
-*/
-uint8_t usb_halt_ep_in(uint8_t ep);
-
-/** @brief Check whether an endpoint is halted
- *
- * Check if an endpoint has been halted by the host. If an endpoint is
- * halted, don't call usb_send_in_buffer().
- *
- * @see ENDPOINT_HALT_CALLBACK.
- *
- * @param endpoint   The endpoint requested
- * @returns
- *   Return true if the endpointed is halted, or false if it is not.
- */
-bool usb_in_endpoint_halted(uint8_t endpoint);
-
-/** @brief Check whether an OUT endpoint has received data
- *
- * Check if an OUT endpoint has completed a transaction and has received
- * data from the host.  If it has, the application should call @p
- * usb_get_out_buffer() to get the data and then call @p
- * usb_arm_out_endpoint() to enable reception of the next transaction.
- *
- * @param endpoint   The endpoint requested
- * @returns
- *   Return true if the endpoint has received data, false if it has not.
- */
-bool usb_out_endpoint_has_data(uint8_t endpoint);
-
-/** @brief Re-enable reception on an OUT endpoint
- *
- * Re-enable reception on the specified endpoint. Call this function after
- * @p usb_out_endpoint_has_data() indicated that there was data available,
- * and after the application has dealt with the data.  Calling this function
- * gives the specified OUT endpoint's buffer back to the USB stack to
- * receive the next transaction.
- *
- * @param endpoint   The endpoint requested
- */
-void usb_arm_out_endpoint(uint8_t endpoint);
-
-/** @brief Halt an OUT endpoint
- *
- * Set the ENDPOINT_HALT condition on an OUT endpoint. Do not call this on
- * endpoint zero.
- *
- * @param endpoint   The endpoint requested
- * @returns
- *    Return 0 if the endpoint can be halted, or -1 if the endpoint number
- *    is invalid.
- */
-uint8_t usb_halt_ep_out(uint8_t ep);
-
-/** @brief Check whether an OUT endpoint is halted
- *
- * Check if an endpoint has been halted by the host. If an OUT endpoint is
- * halted, the USB stack will automatically return STALL in response to any
- * OUT tokens.
- *
- * @see ENDPOINT_HALT_CALLBACK.
- *
- * @param endpoint   The endpoint requested
- * @returns
- *   Return true if the endpointed is halted, or false if it is not.
- */
-bool usb_out_endpoint_halted(uint8_t endpoint);
-
-/** @brief Get a pointer to an endpoint's OUT buffer
- *
- * Call this function to get a pointer to an endpoint's OUT buffer after
- * @p usb_out_endpoint_has_data() returns @p true (indicating that
- * an OUT transaction has been received). Do not call this function if
- * @p usb_out_endpoint_has_data() does not return true.
- *
- * @param endpoint   The endpoint requested
- * @param buffer     A pointer to a pointer which will be set to the
- *                   endpoint's OUT buffer.
- * @returns
- *   Return the number of bytes received.
- */
-uint8_t usb_get_out_buffer(uint8_t endpoint, const unsigned char **buffer);
-
-/** @brief Endpoint 0 data stage callback definition
- *
- * This is the callback function type expected to be passed to @p
- * usb_start_receive_ep0_data_stage() and @p usb_send_data_stage().
- * Callback functions will be called by the stack when the event for which
- * they are registered occurs.
- *
- * @param transfer_ok   @a true if transaction completed successfully, or
- *                      @a false if there was an error
- * @param context       A pointer to application-provided context data
- */
-typedef void (*usb_ep0_data_stage_callback)(bool transfer_ok, void *context);
-
-/** @brief Start the data stage of an OUT control transfer
- *
- * Start the data stage of a control transfer for a transfer which has an
- * OUT data stage.  Call this from @p UNKNOWN_SETUP_REQUEST_CALLBACK for OUT
- * control transfers which being handled by the application.  Once the
- * transfer has completed, @p callback will be called with the @p context
- * pointer provided.  The @p buffer should be considered to be owned by the
- * USB stack until the @p callback is called and should not be modified by the
- * application until this time.
- *
- * @see UNKNOWN_SETUP_REQUEST_CALLBACK
- *
- * @param buffer     A buffer in which to place the data
- * @param len        The number of bytes to expect. This must be less than or
- *                   equal to the number of bytes in the buffer, and for
- *                   proper setup packets will be the wLength parameter.
- * @param callback   A callback function to call when the transfer completes.
- *                   This parameter is mandatory. Once the callback is
- *                   called, the transfer is over, and the buffer can be
- *                   considered to be owned by the application again.
- * @param context    A pointer to be passed to the callback.  The USB stack
- *                   does not dereference this pointer
- */
-void usb_start_receive_ep0_data_stage(char *buffer, size_t len,
-	usb_ep0_data_stage_callback callback, void *context);
-
-/** @brief Start the data stage of an IN control transfer
- *
- * Start the data stage of a control transfer for a transfer which has an IN
- * data stage.  Call this from @p UNKNOWN_SETUP_REQUEST_CALLBACK for IN
- * control transfers which are being handled by the application.  Once the
- * transfer has completed, @p callback will be called with the @p context
- * pointer provided.  The @p buffer should be considered to be owned by the
- * USB stack until the callback is called and should not be modified by the
- * application until this time.  Do not pass in a buffer which is on the
- * stack.  The data will automatically be split into as many transactions as
- * necessary to complete the transfer.
- *
- * @see UNKNOWN_SETUP_REQUEST_CALLBACK
- *
- * @param buffer     A buffer containing the data to send. This should be a
- *                   buffer capable of having an arbitrary lifetime.  Do not
- *                   use a stack variable for this buffer, and do not free
- *                   this buffer until the callback has been called.
- * @param len        The number of bytes to send
- * @param callback   A callback function to call when the transfer completes.
- *                   This parameter is mandatory. Once the callback is
- *                   called, the transfer is over, and the buffer can be
- *                   considered to be owned by the application again.
- * @paramcontext     A pointer to be passed to the callback. The USB stack
- *                   does not dereference this pointer.
- */
-void usb_send_data_stage(char *buffer, size_t len,
-	usb_ep0_data_stage_callback callback, void *context);
-
-
-/* Doxygen end-of-group for public_api */
-/** @}*/
-
-#endif /* USB_H_ */
-
--- a/usb/usb_cdc.c	Wed Feb 17 05:54:21 2016 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,306 +0,0 @@
-/*
- *  M-Stack USB Device Stack Implementation
- *  Copyright (C) 2013 Alan Ott <alan@signal11.us>
- *  Copyright (C) 2013 Signal 11 Software
- *
- *  2014-05-12
- *
- *  M-Stack is free software: you can redistribute it and/or modify it under
- *  the terms of the GNU Lesser General Public License as published by the
- *  Free Software Foundation, version 3; or the Apache License, version 2.0
- *  as published by the Apache Software Foundation.  If you have purchased a
- *  commercial license for this software from Signal 11 Software, your
- *  commerical license superceeds the information in this header.
- *
- *  M-Stack is distributed in the hope that it will be useful, but WITHOUT
- *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
- *  License for more details.
- *
- *  You should have received a copy of the GNU Lesser General Public License
- *  along with this software.  If not, see <http://www.gnu.org/licenses/>.
- *
- *  You should have received a copy of the Apache License, verion 2.0 along
- *  with this software.  If not, see <http://www.apache.org/licenses/>.
- */
-
-#include <usb_config.h>
-
-#include <usb_ch9.h>
-#include <usb.h>
-#include <usb_cdc.h>
-
-#define MIN(x,y) (((x)<(y))?(x):(y))
-
-STATIC_SIZE_CHECK_EQUAL(sizeof(struct cdc_functional_descriptor_header), 5);
-STATIC_SIZE_CHECK_EQUAL(sizeof(struct cdc_acm_functional_descriptor), 4);
-STATIC_SIZE_CHECK_EQUAL(sizeof(struct cdc_union_functional_descriptor), 5);
-STATIC_SIZE_CHECK_EQUAL(sizeof(struct cdc_line_coding), 7);
-STATIC_SIZE_CHECK_EQUAL(sizeof(struct cdc_notification_header), 8);
-STATIC_SIZE_CHECK_EQUAL(sizeof(struct cdc_serial_state_notification), 10);
-
-
-#ifdef MULTI_CLASS_DEVICE
-static uint8_t *cdc_interfaces;
-static uint8_t num_cdc_interfaces;
-
-void cdc_set_interface_list(uint8_t *interfaces, uint8_t num_interfaces)
-{
-	cdc_interfaces = interfaces;
-	num_cdc_interfaces = num_interfaces;
-}
-
-static bool interface_is_cdc(uint8_t interface)
-{
-	uint8_t i;
-	for (i = 0; i < num_cdc_interfaces; i++) {
-		if (interface == cdc_interfaces[i])
-			break;
-	}
-
-	/* Return if interface is not in the list of CDC interfaces. */
-	if (i == num_cdc_interfaces)
-		return false;
-
-	return true;
-}
-#endif
-
-static uint8_t transfer_interface;
-static union transfer_data {
-	#if defined(CDC_SET_COMM_FEATURE_CALLBACK) || \
-	    defined(CDC_CLEAR_COMM_FEATURE_CALLBACK) || \
-	    defined(CDC_GET_COMM_FEATURE_CALLBACK)
-	uint16_t comm_feature;
-	#endif
-
-	#if defined(CDC_SET_LINE_CODING_CALLBACK) || defined(CDC_GET_LINE_CODING_CALLBACK)
-	struct cdc_line_coding line_coding;
-	#endif
-} transfer_data;
-
-#if defined(CDC_SET_COMM_FEATURE_CALLBACK) || defined(CDC_CLEAR_COMM_FEATURE_CALLBACK)
-static uint8_t set_or_clear_request;
-static void set_or_clear_comm_feature_callback(bool transfer_ok, void *context)
-{
-	/* Only ABSTRACT_STATE is supported here. */
-
-	if (!transfer_ok)
-		return;
-
-	bool idle_setting = (transfer_data.comm_feature & 1) != 0;
-	bool data_multiplexed_state = (transfer_data.comm_feature & 2) != 0;
-
-	if (set_or_clear_request == CDC_SET_COMM_FEATURE) {
-		CDC_SET_COMM_FEATURE_CALLBACK(transfer_interface,
-		                              idle_setting,
-		                              data_multiplexed_state);
-	}
-	else {
-		/* request == CDC_CLEAR_COMM_FEATURE */
-		CDC_CLEAR_COMM_FEATURE_CALLBACK(transfer_interface,
-		                                idle_setting,
-		                                data_multiplexed_state);
-	}
-}
-#endif
-
-#if defined(CDC_SET_LINE_CODING_CALLBACK)
-static void set_line_coding(bool transfer_ok, void *context) {
-	if (!transfer_ok)
-		return;
-
-	CDC_SET_LINE_CODING_CALLBACK(transfer_interface,
-	                             &transfer_data.line_coding);
-}
-#endif
-
-
-uint8_t process_cdc_setup_request(const struct setup_packet *setup)
-{
-	/* The following comes from the CDC spec 1.1, chapter 6. */
-
-	uint8_t interface = setup->wIndex;
-
-#ifdef MULTI_CLASS_DEVICE
-	/* Check the interface first to make sure the destination is a
-	 * CDC interface. Multi-class devices will need to call
-	 * cdc_set_interface_list() first.
-	 */
-	if (!interface_is_cdc(interface))
-		return -1;
-#endif
-
-#ifdef CDC_SEND_ENCAPSULATED_COMMAND_CALLBACK
-	if (setup->bRequest == CDC_SEND_ENCAPSULATED_COMMAND &&
-	    setup->REQUEST.bmRequestType == 0x21) {
-		int8_t res;
-		res = CDC_SEND_ENCAPSULATED_COMMAND_CALLBACK(interface,
-                                                             setup->wLength);
-		if (res < 0)
-			return -1;
-		return 0;
-	}
-#endif
-
-#ifdef CDC_GET_ENCAPSULATED_RESPONSE_CALLBACK
-	if (setup->bRequest == CDC_GET_ENCAPSULATED_RESPONSE &&
-	    setup->REQUEST.bmRequestType == 0xa1) {
-		const void *response;
-		int16_t len;
-		usb_ep0_data_stage_callback callback;
-		void *context;
-
-		len = CDC_GET_ENCAPSULATED_RESPONSE_CALLBACK(
-		                                interface, setup->wLength,
-		                                &response, &callback,
-		                                &context);
-		if (len < 0)
-			return -1;
-
-		usb_send_data_stage((void*)response,
-		                    MIN(len, setup->wLength),
-		                    callback, context);
-		return 0;
-	}
-#endif
-
-#ifdef CDC_SET_COMM_FEATURE_CALLBACK
-	if (setup->bRequest == CDC_SET_COMM_FEATURE &&
-	    setup->REQUEST.bmRequestType == 0x21) {
-
-		/* Only ABSTRACT_STATE feature is supported. If you need
-		 * something else here, get in contact with Signal 11. */
-		if (setup->wValue != CDC_FEATURE_ABSTRACT_STATE)
-			return -1;
-
-		transfer_interface = interface;
-		set_or_clear_request = setup->bRequest;
-		usb_start_receive_ep0_data_stage((char*) &transfer_data.comm_feature,
-		                                 sizeof(transfer_data.comm_feature),
-		                                 set_or_clear_comm_feature_callback,
-		                                 NULL);
-		return 0;
-	}
-#endif
-
-#ifdef CDC_CLEAR_COMM_FEATURE_CALLBACK
-	if (setup->bRequest == CDC_CLEAR_COMM_FEATURE &&
-	    setup->REQUEST.bmRequestType == 0x21) {
-
-		/* Only ABSTRACT_STATE feature is supported. If you need
-		 * something else here, get in contact with Signal 11. */
-		if (setup->wValue != CDC_FEATURE_ABSTRACT_STATE)
-			return -1;
-
-		transfer_interface = interface;
-		set_or_clear_request = setup->bRequest;
-		usb_start_receive_ep0_data_stage((char*)&transfer_data.comm_feature,
-		                                 sizeof(transfer_data.comm_feature),
-		                                 set_or_clear_comm_feature_callback,
-		                                 NULL);
-		return 0;
-	}
-#endif
-
-#ifdef CDC_GET_COMM_FEATURE_CALLBACK
-	if (setup->bRequest == CDC_GET_COMM_FEATURE &&
-	    setup->REQUEST.bmRequestType == 0xa1) {
-		bool idle_setting;
-		bool data_multiplexed_state;
-		int8_t res;
-
-		/* Only ABSTRACT_STATE feature is supported. If you need
-		 * something else here, get in contact with Signal 11. */
-		if (setup->wValue != CDC_FEATURE_ABSTRACT_STATE)
-			return -1;
-
-		res = CDC_GET_COMM_FEATURE_CALLBACK(
-		                                interface,
-		                                &idle_setting,
-		                                &data_multiplexed_state);
-		if (res < 0)
-			return -1;
-
-		transfer_data.comm_feature =
-			(uint16_t) idle_setting |
-				(uint16_t) data_multiplexed_state << 1;
-
-		usb_send_data_stage((char*)&transfer_data.comm_feature,
-		                    MIN(setup->wLength,
-		                        sizeof(transfer_data.comm_feature)),
-		                    NULL/*callback*/, NULL);
-		return 0;
-	}
-#endif
-
-#ifdef CDC_SET_LINE_CODING_CALLBACK
-	if (setup->bRequest == CDC_SET_LINE_CODING &&
-	    setup->REQUEST.bmRequestType == 0x21) {
-
-		transfer_interface = interface;
-		usb_start_receive_ep0_data_stage(
-		                      (char*)&transfer_data.line_coding,
-		                      MIN(setup->wLength,
-		                          sizeof(transfer_data.line_coding)),
-		                      set_line_coding, NULL);
-		return 0;
-	}
-#endif
-
-#ifdef CDC_GET_LINE_CODING_CALLBACK
-	if (setup->bRequest == CDC_GET_LINE_CODING &&
-	    setup->REQUEST.bmRequestType == 0xa1) {
-		int8_t res;
-
-		res = CDC_GET_LINE_CODING_CALLBACK(
-		                                interface,
-		                                &transfer_data.line_coding);
-		if (res < 0)
-			return -1;
-
-		usb_send_data_stage((char*)&transfer_data.line_coding,
-		                    MIN(setup->wLength,
-		                        sizeof(transfer_data.line_coding)),
-		                    /*callback*/NULL, NULL);
-		return 0;
-	}
-#endif
-
-#ifdef CDC_SET_CONTROL_LINE_STATE_CALLBACK
-	if (setup->bRequest == CDC_SET_CONTROL_LINE_STATE &&
-	    setup->REQUEST.bmRequestType == 0x21) {
-		int8_t res;
-		bool dtr = (setup->wValue & 0x1) != 0;
-		bool rts = (setup->wValue & 0x2) != 0;
-
-		res = CDC_SET_CONTROL_LINE_STATE_CALLBACK(interface, dtr, rts);
-		if (res < 0)
-			return -1;
-
-		/* Return zero-length packet. No data stage. */
-		usb_send_data_stage(NULL, 0, NULL, NULL);
-
-		return 0;
-	}
-#endif
-
-#ifdef CDC_SEND_BREAK_CALLBACK
-	if (setup->bRequest == CDC_SEND_BREAK &&
-	    setup->REQUEST.bmRequestType == 0x21) {
-		int8_t res;
-
-		res = CDC_SEND_BREAK_CALLBACK(interface,
-		                              setup->wValue /*duration*/);
-		if (res < 0)
-			return -1;
-
-		/* Return zero-length packet. No data stage. */
-		usb_send_data_stage(NULL, 0, NULL, NULL);
-
-		return 0;
-	}
-#endif
-
-	return -1;
-}
--- a/usb/usb_cdc.h	Wed Feb 17 05:54:21 2016 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,501 +0,0 @@
-/*
- *  M-Stack USB CDC Device Class Structures
- *  Copyright (C) 2013 Alan Ott <alan@signal11.us>
- *  Copyright (C) 2013 Signal 11 Software
- *
- *  2013-09-27
- *
- *  M-Stack is free software: you can redistribute it and/or modify it under
- *  the terms of the GNU Lesser General Public License as published by the
- *  Free Software Foundation, version 3; or the Apache License, version 2.0
- *  as published by the Apache Software Foundation.  If you have purchased a
- *  commercial license for this software from Signal 11 Software, your
- *  commerical license superceeds the information in this header.
- *
- *  M-Stack is distributed in the hope that it will be useful, but WITHOUT
- *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
- *  License for more details.
- *
- *  You should have received a copy of the GNU Lesser General Public License
- *  along with this software.  If not, see <http://www.gnu.org/licenses/>.
- *
- *  You should have received a copy of the Apache License, verion 2.0 along
- *  with this software.  If not, see <http://www.apache.org/licenses/>.
- */
-
-#ifndef USB_CDC_H__
-#define USB_CDC_H__
-
-/** @file usb_cdc.h
- *  @brief USB CDC Class Enumerations and Structures
- *  @defgroup public_api Public API
- */
-
-/** @addtogroup public_api
- *  @{
- */
-
-#include <stdint.h>
-#include "usb_config.h"
-
-#if defined(__XC16__) || defined(__XC32__)
-#pragma pack(push, 1)
-#elif __XC8
-#else
-#error "Compiler not supported"
-#endif
-
-/** @defgroup cdc_items USB CDC Class Enumerations and Descriptors
- *  @brief Packet structs, constants, and callback functions implementing
- *  the "Universal Serial Bus Class Definitions for Communication Devices"
- *  (commonly the USB CDC Specification), version 1.1.
- *
- *  For more information, see the above referenced document, available from
- *  http://www.usb.org .
- *  @addtogroup cdc_items
- *  @{
- */
-
-/* CDC Specification 1.1 document sections are listed in the comments */
-#define CDC_DEVICE_CLASS 0x02 /* 4.1 */
-#define CDC_COMMUNICATION_INTERFACE_CLASS 0x02 /* 4.2 */
-#define CDC_COMMUNICATION_INTERFACE_CLASS_ACM_SUBCLASS 0x02 /* 4.3 */
-/* Many of the subclass codes (section 4.3) are omitted here. Get in
- * contact with Signal 11 if you need something specific. */
-
-#define CDC_DATA_INTERFACE_CLASS 0x0a /* 4.5 */
-#define CDC_DATA_INTERFACE_CLASS_PROTOCOL_NONE 0x0 /* 4.7 */
-#define CDC_DATA_INTERFACE_CLASS_PROTOCOL_VENDOR 0xff /* 4.7 */
-/* Many of the protocol codes (section 4.7) are omitted here. Get in
- * contact with Signal 11 if you need something specific. */
-
-/** CDC Descriptor types: 5.2.3 */
-enum CDCDescriptorTypes {
-	DESC_CS_INTERFACE = 0x24,
-	DESC_CS_ENDPOINT  = 0x25,
-};
-
-/* Descriptor subtypes: 5.2.3 */
-enum CDCFunctionalDescriptorSubtypes {
-	CDC_FUNCTIONAL_DESCRIPTOR_SUBTYPE_HEADER = 0x0,
-	CDC_FUNCTIONAL_DESCRIPTOR_SUBTYPE_ACM = 0x2,
-	CDC_FUNCTIONAL_DESCRIPTOR_SUBTYPE_UNION = 0x6,
-};
-/* Many of the descriptor subtypes (section 5.2.3, table 25) are omitted
- * here.  Get in contact with Signal 11 if you need something specific. */
-
-/** Abstract Control Management (ACM) capabilities
- *
- * See section 5.2.3.3 of the CDC Specification, version 1.1.
- */
-enum CDCACMCapabilities {
-	CDC_ACM_CAPABILITY_COMM_FEATURES = 0x1,
-	CDC_ACM_CAPABILITY_LINE_CODINGS = 0x2,
-	CDC_ACM_CAPABILITY_SEND_BREAK = 0x4,
-	CDC_ACM_CAPABILITY_NETWORK_CONNECTION = 0x8,
-};
-
-/** CDC ACM Class Requests
- *
- * These are the class requests needed for ACM (see section 6.2, table 45).
- * Others are omitted.  Get in contact with Signal 11 if you need something
- * specific.
- */
-enum CDCRequests {
-	CDC_SEND_ENCAPSULATED_COMMAND = 0x0,
-	CDC_GET_ENCAPSULATED_RESPONSE = 0x1,
-	CDC_SET_COMM_FEATURE = 0x2,
-	CDC_GET_COMM_FEATURE = 0x3,
-	CDC_CLEAR_COMM_FEATURE = 0x4,
-	CDC_SET_LINE_CODING = 0x20,
-	CDC_GET_LINE_CODING = 0x21,
-	CDC_SET_CONTROL_LINE_STATE = 0x22,
-	CDC_SEND_BREAK = 0x23,
-};
-
-/** CDC Communication Feature Selector Codes
- *
- * See section 6.2.4, Table 47 of the CDC Specification, version 1.1.
- */
-enum CDCCommFeatureSelector {
-	CDC_FEATURE_ABSTRACT_STATE = 0x1,
-	CDC_FEATURE_COUNTRY_SETTING = 0x2,
-};
-
-/** CDC Character Format
- *
- * These values are used in the bCharFormat field of the GET_LINE_CODING and
- * SET_LINE_CODING requests.  See section 6.2.13 (table 50) of the CDC
- * Specification, version 1.1.
- */
-enum CDCCharFormat {
-	CDC_CHAR_FORMAT_1_STOP_BIT = 0,
-	CDC_CHAR_FORMAT_1_POINT_5_STOP_BITS = 1,
-	CDC_CHAR_FORMAT_2_STOP_BITS = 2,
-};
-
-/** CDC Parity Type
- *
- * These values are used in the bParityType field of the GET_LINE_CODING and
- * SET_LINE_CODING requests.  See section 6.2.13 (table 50) of the CDC
- * Specification, version 1.1.
- */
-enum CDCParityType {
-	CDC_PARITY_NONE  = 0,
-	CDC_PARITY_ODD   = 1,
-	CDC_PARITY_EVEN  = 2,
-	CDC_PARITY_MARK  = 3,
-	CDC_PARITY_SPACE = 4,
-};
-
-/** CDC Class-Specific Notification Codes
- *
- * See section 6.3 (table 68) of the CDC Specification, version 1.1.
- */
-enum CDCNotifications {
-	CDC_NETWORK_CONNECTION = 0x0,
-	CDC_RESPONSE_AVAILABLE = 0x1,
-	CDC_SERIAL_STATE = 0x20,
-};
-/* Many of the CDC Notifications are omitted here.  Get in contact with
- * Signal 11 if you need something specific.  */
-
-/** CDC Functional Descriptor Header.
- *
- * See section 5.2.3.1 of the CDC Specification, version 1.1.
- */
-struct cdc_functional_descriptor_header {
-	uint8_t bFunctionLength; /**< Size of this functional  descriptor (5) */
-	uint8_t bDescriptorType; /**< Use DESC_CS_INTERFACE */
-	uint8_t bDescriptorSubtype; /**< CDC_DESCRIPTOR_SUBTYPE_HEADER */
-	uint16_t bcdCDC; /**< CDC version in BCD format. Use 0x0101 (1.1). */
-};
-
-/** CDC Abstract Control Management Functional Descriptor
- *
- * See Section 5.2.3.3 of the CDC Specification, version 1.1.
- */
-struct cdc_acm_functional_descriptor {
-	uint8_t bFunctionLength; /**< Size of this functional descriptor (4) */
-	uint8_t bDescriptorType; /**< Use DESC_CS_INTERFACE */
-	uint8_t bDescriptorSubtype; /**< CDC_DESCRIPTOR_SUBTYPE_ACM */
-	uint8_t bmCapabilities; /**< See CDC_ACM_CAPABILITY* definitions */
-};
-
-/** CDC Union Functional Registor
- *
- * See Section 5.2.3.8 of the CDC Specification, version 1.1.
- */
-struct cdc_union_functional_descriptor {
-	uint8_t bFunctionLength; /**< Size of this functional descriptor */
-	uint8_t bDescriptorType; /**< Use DESC_CS_INTERFACE */
-	uint8_t bDescriptorSubtype; /**< CDC_DESCRIPTOR_SUBTYPE_ACM */
-	uint8_t bMasterInterface;
-	uint8_t bSlaveInterface0;
-	/* More bSlaveInterfaces cound go here, but you'll have to pack them
-	 * yourself into the configuration descriptor, and make sure
-	 * bFunctionLength covers them all. */
-};
-
-/* CDC Notification Header
- *
- * CDC Notifications all share this same header. It's very similar to a
- * @p setup_packet .
- */
-struct cdc_notification_header {
-	union {
-		struct {
-			uint8_t destination : 5; /**< @see enum DestinationType */
-			uint8_t type : 2;        /**< @see enum RequestType */
-			uint8_t direction : 1;   /**< 0=out, 1=in */
-		};
-		uint8_t bmRequestType;
-	} REQUEST;
-	uint8_t bNotification;  /**< @see enum CDCNotifications */
-	uint16_t wValue;
-	uint16_t wIndex;
-	uint16_t wLength;
-};
-
-
-/* CDC Serial State Notification
- *
- * See Section 6.3.5 of the CDC Specification, version 1.1.
- */
-struct cdc_serial_state_notification {
-	struct cdc_notification_header header;
-	union {
-		struct {
-			uint16_t bRxCarrier : 1; /**< Indicates DCD */
-			uint16_t bTxCarrier : 1; /**< Indicates DSR */
-			uint16_t bBreak : 1;
-			uint16_t bRingSignal : 1;
-			uint16_t bFraming : 1;
-			uint16_t bParity : 1;
-			uint16_t bOverrun : 1;
-			uint16_t : 1;
-			uint16_t : 8; /* XC8 can't handle a 9-bit bitfield */
-		} bits;
-		uint16_t serial_state;
-	} data;
-};
-
-/* Many functional descriptors are omitted here. Get in contact with
- * Signal 11 if you need something specific. */
-
-/* Message Structures */
-
-/** CDC Line Coding Structure
- *
- * See Section 6.2.13 of the CDC Specification, version 1.1.
- */
-struct cdc_line_coding {
-	uint32_t dwDTERate; /**< Data Terminal Rate (bits per second) */
-	uint8_t bCharFormat; /**< Stop bits: @see CDCCharFormat */
-	uint8_t bParityType; /**< Parity Type: @see CDCParityType */
-	uint8_t bDataBits; /**< Data Bits: 5, 6, 7, 8 or 16 */
-};
-
-
-/** Process CDC Setup Request
- *
- * Process a setup request which has been unhandled as if it is potentially
- * a CDC setup request. This function will then call appropriate callbacks
- * into the appliction if the setup packet is one recognized by the CDC
- * specification.
- *
- * @param setup          A setup packet to handle
- *
- * @returns
- *   Returns 0 if the setup packet could be processed or -1 if it could not.
- */
-uint8_t process_cdc_setup_request(const struct setup_packet *setup);
-
-/** CDC SEND_ENCAPSULATED_COMMAND callback
- *
- * The USB Stack will call this function when a GET_ENCAPSULATED_COMMAND
- * request has been received from the host.  There are two ways to handle
- * this:
- *
- * 1. If the request can't be handled, return -1. This will send a STALL
- *    to the host.
- * 2. If the request can be handled, call @p
- *    usb_start_receive_ep0_data_stage() with a buffer to be filled with the
- *    command data and a callback which will get called when the data stage
- *    is complete.  The callback is required, and the command data buffer
- *    passed to @p usb_start_receive_ep0_data_stage() must remain valid
- *    until the callback is called.
- *
- * It is worth noting that only one control transfer can be active at any
- * given time.  Once HID_SET_REPORT_CALLBACK() has been called, it will not
- * be called again until the next transfer, meaning that if the
- * application-provided HID_SET_REPORT_CALLBACK() function performs option 1
- * above, the callback function passed to @p
- * usb_start_receive_ep0_data_stage() will be called before any other setup
- * transfer can happen again.  Thus, it is safe to use the same buffer for
- * all control transfers if desired.
- *
- *
- * @param interface      The interface for which the command is intended
- * @param length         The length of the command which will be present
- *                       in the data stage.
- * @returns
- *   Return 0 if the request can be handled or -1 if it cannot. Returning -1
- *   will cause STALL to be returned to the host.
- */
-extern int8_t CDC_SEND_ENCAPSULATED_COMMAND_CALLBACK(uint8_t interface,
-                                                     uint16_t length);
-
-#ifdef CDC_GET_ENCAPSULATED_RESPONSE_CALLBACK
-/** CDC GET_ENCAPSULATED_RESPONSE callback
- *
- * The USB Stack will call this function when a GET_ENCAPSULATED_RESPONSE
- * request has been received from the host.  This function should set the @p
- * response pointer to a buffer containing the response data and return the
- * length of the response.  Once the transfer has completed, @p callback will
- * be called with the @p context pointer provided.  The buffer pointed to by
- * @p response should be considered to be owned by the USB stack until the @p
- * callback is called and should not be modified by the application until
- * that time.
- *
- *
- * @param interface      The interface for which the report is requested
- * @param length         The length of the response requested by the host
- * @param response       A pointer to a pointer which should be set to the
- *                       response data.
- * @param callback       A callback function to call when the transfer
- *                       completes.  This parameter is mandatory.  Once the
- *                       callback is called, the transfer is over, and the
- *                       buffer can be considered to be owned by the
- *                       application again.
- * @param context        A pointer to be passed to the callback.  The USB
- *                       stack does not dereference this pointer.
- *
- * @returns
- *   Return 0 if the request can be handled or -1 if it cannot. Returning -1
- *   will cause STALL to be returned to the host.
- */
-extern int16_t CDC_GET_ENCAPSULATED_RESPONSE_CALLBACK(uint8_t interface,
-                               uint16_t length, const void **response,
-                               usb_ep0_data_stage_callback *callback,
-                               void **context);
-#endif
-
-#ifdef CDC_SET_COMM_FEATURE_CALLBACK
-/** CDC SET_COMM_FEATURE callback
- *
- * The USB Stack will call this function when a SET_COMM_FEATURE request has
- * been received from the host.  The device should set the idle setting
- * and/or data multiplexed state if requested.  There is no way to refuse
- * this message.  If this message is not supported by the device, simply do
- * not define CDC_SET_COMM_FEATURE_CALLBACK.
- *
- * @param interface      The interface for which the command is intended
- * @param idle_setting   Whether to set the idle setting. True = clear
- *                       the idle setting.
- * @param data_multiplexed_state  Whether to set the data multiplexed
- *                                state. True = clear the multiplexed state.
- */
-extern void CDC_SET_COMM_FEATURE_CALLBACK(uint8_t interface,
-                                            bool idle_setting,
-                                            bool data_multiplexed_state);
-#endif
-
-#ifdef CDC_CLEAR_COMM_FEATURE_CALLBACK
-/** CDC CLEAR_COMM_FEATURE callback
- *
- * The USB Stack will call this function when a CLEAR_COMM_FEATURE request
- * has been received from the host.  The device should clear the idle
- * setting and/or data multiplexed state if requested.  There is no way to
- * refuse this message.  If this message is not supported by the device,
- * simply do not define CDC_CLEAR_COMM_FEATURE_CALLBACK.
- *
- * @param interface      The interface for which the command is intended
- * @param idle_setting   Whether to clear the idle setting. True = clear
- *                       the idle setting.
- * @param data_multiplexed_state  Whether to clear the data multiplexed
- *                                state. True = clear the multiplexed state.
- */
-extern void CDC_CLEAR_COMM_FEATURE_CALLBACK(uint8_t interface,
-                                            bool idle_setting,
-                                            bool data_multiplexed_state);
-#endif
-
-#ifdef CDC_GET_COMM_FEATURE_CALLBACK
-/** CDC GET_COMM_FEATURE callback
- *
- * The USB Stack will call this function when a GET_COMM_FEATURE request has
- * been received from the host.  This function should set the @p
- * idle_setting and @p multiplexed_state pointers to their current values.
- *
- * @param interface      The interface for which the report is requested
- * @param idle_setting   Set to the current value of the idle setting.
- * @param multiplexed_state   Set to the current value of the multiplexed
- *                            state.
- *
- * @returns
- *   Return 0 if the request can be handled or -1 if it cannot. Returning -1
- *   will cause STALL to be returned to the host.
- */
-extern int8_t CDC_GET_COMM_FEATURE_CALLBACK(
-                               uint8_t interface,
-                               bool *idle_setting,
-                               bool *data_multiplexed_state);
-#endif
-
-#ifdef CDC_SET_LINE_CODING_CALLBACK
-/** CDC SET_LINE_CODING callback
- *
- * The USB Stack will call this function when a SET_LINE_CODING
- * request has been received from the host. The device should then set
- * the line coding to the specified values. There is no way to refuse
- * this message. If this message is not supported by the device, simply
- * do not define CDC_SET_LINE_CODING_CALLBACK.
- *
- * @param interface      The interface for which the command is intended
- * @param coding         The new line coding set by the host
- *
- */
-extern void CDC_SET_LINE_CODING_CALLBACK(uint8_t interface,
-                                         const struct cdc_line_coding *coding);
-#endif
-
-#ifdef CDC_GET_LINE_CODING_CALLBACK
-/** CDC GET_LINE_CODING callback
- *
- * The USB Stack will call this function when a GET_LINE_CODING request has
- * been received from the host.  This function should set the @p values in
- * the structure pointed to by @p coding to the current line coding values.
- *
- * @param interface      The interface for which the report is requested
- * @param coding         Pointer to a structure which must be filled with
- *                       the current line coding values.
- * @param callback       A callback function to call when the transfer
- *                       completes.  This parameter is mandatory.  Once the
- *                       callback is called, the transfer is over, and the
- *                       buffer can be considered to be owned by the
- *                       application again.
- * @param context        A pointer to be passed to the callback.  The USB stack
- *                       does not dereference this pointer.
- *
- * @returns
- *   Return 0 if the request can be handled or -1 if it cannot. Returning -1
- *   will cause STALL to be returned to the host.
- */
-extern int8_t CDC_GET_LINE_CODING_CALLBACK(uint8_t interface,
-                                           struct cdc_line_coding *coding);
-#endif
-
-#ifdef CDC_SET_CONTROL_LINE_STATE_CALLBACK
-/** CDC SET_CONTROL_LINE_STATE callback
- *
- * The USB Stack will call this function when a SET_CONTROL_LINE_STATE
- * request has been received from the host.  The device should then set the
- * control lines as requested.
- *
- * @param interface      The interface for which the command is intended
- * @param dtr            The state of the DTR line. True = activated.
- * @param rts            The state of the RTS line. True = activated.
- *
- * @returns
- *   Return 0 if the request can be handled or -1 if it cannot. Returning -1
- *   will cause STALL to be returned to the host.
- */
-extern int8_t CDC_SET_CONTROL_LINE_STATE_CALLBACK(uint8_t interface,
-                                                  bool dtr, bool dts);
-#endif
-
-#ifdef CDC_SEND_BREAK_CALLBACK
-/** CDC SEND_BREAK callback
- *
- * The USB Stack will call this function when a SEND_BREAK request has been
- * received from the host.  The device should then assert a break condition
- * for the specified number of milliseconds.
- *
- * @param interface      The interface for which the command is intended
- * @param duration       The duration of the break in milliseconds
- *
- * @returns
- *   Return 0 if the request can be handled or -1 if it cannot. Returning -1
- *   will cause STALL to be returned to the host.
- */
-extern int8_t CDC_SEND_BREAK_CALLBACK(uint8_t interface, uint16_t duration);
-#endif
-
-
-/* Doxygen end-of-group for cdc_items */
-/** @}*/
-
-
-#if defined(__XC16__) || defined(__XC32__)
-#pragma pack(pop)
-#elif __XC8
-#else
-#error "Compiler not supported"
-#endif
-
-/* Doxygen end-of-group for public_api */
-/** @}*/
-
-#endif /* USB_CDC_H__ */
--- a/usb/usb_ch9.h	Wed Feb 17 05:54:21 2016 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,286 +0,0 @@
-/*
- *  M-Stack USB Chapter 9 Structures
- *  Copyright (C) 2013 Alan Ott <alan@signal11.us>
- *  Copyright (C) 2013 Signal 11 Software
- *
- *  2013-04-26
- *
- *  M-Stack is free software: you can redistribute it and/or modify it under
- *  the terms of the GNU Lesser General Public License as published by the
- *  Free Software Foundation, version 3; or the Apache License, version 2.0
- *  as published by the Apache Software Foundation.  If you have purchased a
- *  commercial license for this software from Signal 11 Software, your
- *  commerical license superceeds the information in this header.
- *
- *  M-Stack is distributed in the hope that it will be useful, but WITHOUT
- *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
- *  License for more details.
- *
- *  You should have received a copy of the GNU Lesser General Public License
- *  along with this software.  If not, see <http://www.gnu.org/licenses/>.
- *
- *  You should have received a copy of the Apache License, verion 2.0 along
- *  with this software.  If not, see <http://www.apache.org/licenses/>.
- */
-
-#ifndef USB_CH9_H__
-#define USB_CH9_H__
-
-/** @file usb.h
- *  @brief USB Chapter 9 Enumerations and Structures
- *  @defgroup public_api Public API
- */
-
-/** @addtogroup public_api
- *  @{
- */
-
-#include <stdint.h>
-
-#if defined(__XC16__) || defined(__XC32__)
-#pragma pack(push, 1)
-#elif __XC8
-#else
-#error "Compiler not supported"
-#endif
-
-/** @defgroup ch9_items USB Chapter 9 Enumerations and Descriptors
- *  @brief Packet structs from Chapter 9 of the USB spec which deals with
- *  device enumeration.
- *
- *  For more information about these structures, see Chapter 9 of the USB
- *  specification, available from http://www.usb.org .
- *  @addtogroup ch9_items
- *  @{
- */
-
-/** USB PIDs */
-enum PID {
-	PID_OUT = 0x01,
-	PID_IN  = 0x09,
-	PID_SOF = 0x05,
-	PID_SETUP = 0x0D,
-	PID_DATA0 = 0x03,
-	PID_DATA1 = 0x0B,
-	PID_DATA2 = 0x07,
-	PID_MDATA = 0x0F,
-	PID_ACK   = 0x02,
-	PID_NAK   = 0x0A,
-	PID_STALL = 0x0E,
-	PID_NYET  = 0x06,
-	PID_PRE   = 0x0C,
-	PID_ERR   = 0x0C,
-	PID_SPLIT = 0x08,
-	PID_PING  = 0x04,
-	PID_RESERVED = 0x00,
-};
-
-/** Destination type
- *
- * This is present in the SETUP packet's bmRequestType field as Direction.
- */
-enum DestinationType {
-	DEST_DEVICE = 0,
-	DEST_INTERFACE = 1,
-	DEST_ENDPOINT = 2,
-	DEST_OTHER_ELEMENT = 3,
-};
-
-/** Request type
- *
- * These are present in the SETUP packet's bmRequestType field as Type.
- */
-enum RequestType {
-	REQUEST_TYPE_STANDARD = 0,
-	REQUEST_TYPE_CLASS    = 1,
-	REQUEST_TYPE_VENDOR   = 2,
-	REQUEST_TYPE_RESERVED = 3,
-};
-
-/** Control Request
- *
- * These are requests sent in the SETUP packet's bRequest field.
- */
-enum StandardControlRequest {
-	GET_STATUS = 0x0,
-	CLEAR_FEATURE = 0x1,
-	SET_FEATURE = 0x3,
-	SET_ADDRESS = 0x5,
-	GET_DESCRIPTOR = 0x6,
-	SET_DESCRIPTOR = 0x7,
-	GET_CONFIGURATION = 0x8,
-	SET_CONFIGURATION = 0x9,
-	GET_INTERFACE = 0xA,
-	SET_INTERFACE = 0xB,
-	SYNCH_FRAME = 0xC,
-};
-
-/** Standard Descriptor Types */
-enum DescriptorTypes {
-	DESC_DEVICE = 0x1,
-	DESC_CONFIGURATION = 0x2,
-	DESC_STRING = 0x3,
-	DESC_INTERFACE = 0x4,
-	DESC_ENDPOINT = 0x5,
-	DESC_DEVICE_QUALIFIER = 0x6,
-	DESC_OTHER_SPEED_CONFIGURATION = 0x7,
-	DESC_INTERFACE_POWER = 0x8,
-	DESC_OTG = 0x9,
-	DESC_DEBUG = 0xA,
-	DESC_INTERFACE_ASSOCIATION = 0xB,
-};
-
-/** Device Classes
- *
- * Some Device class constants which don't correspond to actual
- * classes.
- *
- * Device class codes which correspond to actual device classes are
- * defined in that device class's header file (for M-Stack supported
- * device classes).
- */
-enum DeviceClassCodes {
-	DEVICE_CLASS_DEFINED_AT_INTERFACE_LEVEL = 0x0,
-	DEVICE_CLASS_MISC = 0xef,
-	DEVICE_CLASS_APPLICATION_SPECIFIC = 0xfe,
-	DEVICE_CLASS_VENDOR_SPECIFIC = 0xff,
-};
-
-/** Endpoint Attributes */
-enum EndpointAttributes {
-	EP_CONTROL = 0x0,
-	EP_ISOCHRONOUS = 0x1,
-	EP_BULK = 0x2,
-	EP_INTERRUPT = 0x3,
-
-	/* More bits here for ISO endpoints only. */
-};
-
-/** The SETUP packet, as defined by the USB specification.
- *
- * The contents of the packet sent from the host during the SETUP stage of
- * every control transfer
- */
-struct setup_packet {
-	union {
-		struct {
-			uint8_t destination : 5; /**< @see enum DestinationType */
-			uint8_t type : 2;        /**< @see enum RequestType */
-			uint8_t direction : 1;   /**< 0=out, 1=in */
-		};
-		uint8_t bmRequestType;
-	} REQUEST;
-	uint8_t bRequest;  /**< Dependent on @p type. @see enum StandardControlRequest */
-	uint16_t wValue;
-	uint16_t wIndex;
-	uint16_t wLength;
-};
-
-/** Device Descriptor */
-struct device_descriptor {
-	uint8_t bLength;
-	uint8_t bDescriptorType; /**< set to DESC_DEVICE */
-	uint16_t bcdUSB; /**< Set to 0x0200 for USB 2.0 */
-	uint8_t bDeviceClass;
-	uint8_t bDeviceSubclass;
-	uint8_t bDeviceProtocol;
-	uint8_t bMaxPacketSize0; /**< Max packet size for ep 0. Must be 8, 16, 32, or 64. */
-	uint16_t idVendor;
-	uint16_t idProduct;
-	uint16_t bcdDevice;
-	uint8_t  iManufacturer; /**< index of manufacturer string descriptor */
-	uint8_t  iProduct;      /**< index of product string descriptor */
-	uint8_t  iSerialNumber; /**< index of serial number string descriptor */
-	uint8_t  bNumConfigurations;
-};
-
-/** Configuration Descriptor */
-struct configuration_descriptor {
-	uint8_t bLength;
-	uint8_t bDescriptorType; /**< Set to DESC_CONFIGURATION */
-	uint16_t wTotalLength;
-	uint8_t bNumInterfaces;
-	uint8_t bConfigurationValue;
-	uint8_t iConfiguration; /**< index of string descriptor */
-	uint8_t bmAttributes;
-	uint8_t bMaxPower; /**< one-half the max power required by this device. */
-};
-
-/** Interface Descriptor */
-struct interface_descriptor {
-	uint8_t bLength;
-	uint8_t bDescriptorType; /**< Set to DESC_INTERFACE */
-	uint8_t bInterfaceNumber;
-	uint8_t bAlternateSetting;
-	uint8_t bNumEndpoints;
-	uint8_t bInterfaceClass;
-	uint8_t bInterfaceSubclass;
-	uint8_t bInterfaceProtocol;
-	uint8_t iInterface;
-};
-
-/** Endpoint Descriptor */
-struct endpoint_descriptor {
-	// ...
-	uint8_t bLength;
-	uint8_t bDescriptorType; /**< Set to DESC_ENDPOINT */
-	uint8_t bEndpointAddress;
-	uint8_t bmAttributes;
-	uint16_t wMaxPacketSize;
-	uint8_t bInterval;
-};
-
-/** String Descriptor */
-struct string_descriptor {
-	uint8_t bLength;
-	uint8_t bDescriptorType; /**< Set to DESC_STRING */
-	uint16_t chars[];
-};
-
-/** Interface Association Descriptor
- *
- * See the Interface Association Descriptors Engineering Change Note (ECN)
- * available from www.usb.org .
- */
-struct interface_association_descriptor {
-	uint8_t bLength;         /**< Set to 8 bytes */
-	uint8_t bDescriptorType; /**< Set to DESC_INTERFACE_ASSOCIATION = 0xB */
-	uint8_t bFirstInterface;
-	uint8_t bInterfaceCount;
-	uint8_t bFunctionClass;
-	uint8_t bFunctionSubClass;
-	uint8_t bFunctionProtocol;
-	uint8_t iFunction; /**< String Descriptor Index */
-};
-
-/* Doxygen end-of-group for ch9_items */
-/** @}*/
-
-
-/** @cond INTERNAL */
-
-/* So far this is the best place for these macros because they are used in
- * usb.c and also in the application's usb_descriptors.c.  Most applications
- * will not need to include this file outside their usb_descriptors.c, so
- * there isn't much namespace pollution.
- */
-#define USB_ARRAYLEN(X) (sizeof(X)/sizeof(*X))
-#define STATIC_SIZE_CHECK_EQUAL(X,Y) typedef char USB_CONCAT(STATIC_SIZE_CHECK_LINE_,__LINE__) [(X==Y)?1:-1]
-#define USB_CONCAT(X,Y)  USB_CONCAT_HIDDEN(X,Y)
-#define USB_CONCAT_HIDDEN(X,Y) X ## Y
-
-/** @endcond */
-
-
-#if defined(__XC16__) || defined(__XC32__)
-#pragma pack(pop)
-#elif __XC8
-#else
-#error "Compiler not supported"
-#endif
-
-/* Doxygen end-of-group for public_api */
-/** @}*/
-
-#endif /* USB_CH9_H__ */
--- a/usb/usb_hal.h	Wed Feb 17 05:54:21 2016 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,580 +0,0 @@
-/*
- *  M-Stack Hardware Abstraction
- *  Copyright (C) 2013 Alan Ott <alan@signal11.us>
- *  Copyright (C) 2013 Signal 11 Software
- *
- *  2013-04-08
- *
- *  M-Stack is free software: you can redistribute it and/or modify it under
- *  the terms of the GNU Lesser General Public License as published by the
- *  Free Software Foundation, version 3; or the Apache License, version 2.0
- *  as published by the Apache Software Foundation.  If you have purchased a
- *  commercial license for this software from Signal 11 Software, your
- *  commerical license superceeds the information in this header.
- *
- *  M-Stack is distributed in the hope that it will be useful, but WITHOUT
- *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
- *  License for more details.
- *
- *  You should have received a copy of the GNU Lesser General Public License
- *  along with this software.  If not, see <http://www.gnu.org/licenses/>.
- *
- *  You should have received a copy of the Apache License, verion 2.0 along
- *  with this software.  If not, see <http://www.apache.org/licenses/>.
- */
-
-#ifndef USB_HAL_H__
-#define UAB_HAL_H__
-
-#ifdef _PIC14E
-#define NEEDS_PULL /* Whether to pull up D+/D- with SFR_PULL_EN. */
-#define HAS_LOW_SPEED
-#define NEEDS_CLEAR_STALL
-
-#define BDNADR_TYPE              uint16_t
-#define PHYS_ADDR(VIRTUAL_ADDR)  pic16_linear_addr(VIRTUAL_ADDR)
-
-#define SFR_FULL_SPEED_EN        UCFGbits.FSEN
-#define SFR_PULL_EN              UCFGbits.UPUEN
-#define SET_PING_PONG_MODE(n)    do { UCFGbits.PPB0 = n & 1; UCFGbits.PPB1 = (n & 2)? 1: 0; } while (0)
-
-#define SFR_USB_INTERRUPT_FLAGS  UIR
-#define SFR_USB_RESET_IF         UIRbits.URSTIF
-#define SFR_USB_STALL_IF         UIRbits.STALLIF
-#define SFR_USB_TOKEN_IF         UIRbits.TRNIF
-#define SFR_USB_SOF_IF           UIRbits.SOFIF
-#define SFR_USB_IF               PIR2bits.USBIF
-
-#define SFR_USB_INTERRUPT_EN     UIE
-#define SFR_TRANSFER_IE          UIEbits.TRNIE
-#define SFR_STALL_IE             UIEbits.STALLIE
-#define SFR_RESET_IE             UIEbits.URSTIE
-#define SFR_SOF_IE               UIEbits.SOFIE
-#define SFR_USB_IE               PIE2bits.USBIE
-
-#define SFR_USB_EXTENDED_INTERRUPT_EN UEIE
-
-#define SFR_EP_MGMT_TYPE         UEP1bits_t /* TODO test */
-#define UEP_REG_STRIDE 1
-#define SFR_EP_MGMT(ep)          ((SFR_EP_MGMT_TYPE*) (&UEP0 + UEP_REG_STRIDE * (ep)))
-#define SFR_EP_MGMT_HANDSHAKE    EPHSHK
-#define SFR_EP_MGMT_STALL        EPSTALL
-#define SFR_EP_MGMT_OUT_EN       EPOUTEN
-#define SFR_EP_MGMT_IN_EN        EPINEN
-#define SFR_EP_MGMT_CON_DIS      EPCONDIS /* disable control transfers */
-
-#define SFR_USB_ADDR             UADDR
-#define SFR_USB_EN               UCONbits.USBEN
-#define SFR_USB_PKT_DIS          UCONbits.PKTDIS
-#define SFR_USB_PING_PONG_RESET  UCONbits.PPBRST
-
-#define SFR_USB_STATUS           USTAT
-#define SFR_USB_STATUS_EP        USTATbits.ENDP
-#define SFR_USB_STATUS_DIR       USTATbits.DIR
-#define SFR_USB_STATUS_PPBI      USTATbits.PPBI
-
-#define CLEAR_ALL_USB_IF()       SFR_USB_INTERRUPT_FLAGS = 0 /*TODO TEST!*/
-#define CLEAR_USB_RESET_IF()     SFR_USB_RESET_IF = 0
-#define CLEAR_USB_STALL_IF()     SFR_USB_STALL_IF = 0
-#define CLEAR_USB_TOKEN_IF()     SFR_USB_TOKEN_IF = 0
-#define CLEAR_USB_SOF_IF()       SFR_USB_SOF_IF = 0
-
-/* Buffer Descriptor BDnSTAT flags. On Some MCUs, apparently, when handing
- * a buffer descriptor to the SIE, there's a race condition that can happen
- * if you don't set the BDnSTAT byte as a single operation. This was observed
- * on the PIC18F46J50 when sending 8-byte IN-transactions while doing control
- * transfers. */
-#define BDNSTAT_UOWN   0x80
-#define BDNSTAT_DTS    0x40
-#define BDNSTAT_DTSEN  0x08
-#define BDNSTAT_BSTALL 0x04
-#define BDNCNT_MASK    0x03ff /* 10 bits of BDnCNT in BDnSTAT_CNT */
-
-/* Buffer Descriptor
- *
- * This represents the Buffer Descriptor as laid out in the PIC18F4550
- * Datasheet.  A buffer descriptor contains data about either an in or out
- * endpoint buffer.  Bufffer descriptors are almost the same on all 8-bit
- * parts, best I've so far been able to tell.  The fields that aren't in the
- * newer datasheets like KEN and INCDIS aren't used, so it doesn't hurt to
- * have them here on those parts.
- *
- * While the layout is very similar on 16-bit parts, a different struct is
- * required on 16-bit for several reasons, including endianness (the 8-bit
- * BC/BDnSTAT bits are effectively big-endian), and the ability to optimize
- * for each platform (eg: writing BDnSTAT/BDnCNT as a 16-bit word on 16-bit
- * platforms).
- */
-struct buffer_descriptor {
-	union {
-		struct {
-			/* When receiving from the SIE. (USB Mode) */
-			uint8_t BC8 : 1;
-			uint8_t BC9 : 1;
-			uint8_t PID : 4; /* See enum PID */
-			uint8_t reserved: 1;
-			uint8_t UOWN : 1;
-		};
-		struct {
-			/* When giving to the SIE (CPU Mode) */
-			uint8_t /*BC8*/ : 1;
-			uint8_t /*BC9*/ : 1;
-			uint8_t BSTALL : 1;
-			uint8_t DTSEN : 1;
-			uint8_t INCDIS : 1;
-			uint8_t KEN : 1;
-			uint8_t DTS : 1;
-			uint8_t /*UOWN*/ : 1;
-		};
-		uint8_t BDnSTAT;
-	} STAT;
-	uint8_t BDnCNT;
-	BDNADR_TYPE BDnADR; /* BDnADRL and BDnADRH; */
-};
-
-#ifdef LARGE_EP
-#define SET_BDN(REG, FLAGS, CNT) do { (REG).BDnCNT = (CNT); \
-           (REG).STAT.BDnSTAT = (FLAGS) | ((CNT) & 0x300) >> 8; } while(0)
-#define BDN_LENGTH(REG) ( ((REG).STAT.BDnSTAT & 0x03) << 8 | (REG).BDnCNT )
-#else
-#define SET_BDN(REG, FLAGS, CNT) do { (REG).BDnCNT = (CNT); \
-                                      (REG).STAT.BDnSTAT = (FLAGS); } while(0)
-#define BDN_LENGTH(REG) (REG.BDnCNT)
-#endif
-
-#if defined(_16F1459) || defined(_16F1454)
-#define BD_ADDR 0x2000
-#define BUFFER_ADDR 0x2080
-#else
-#error "CPU not supported yet"
-#endif
-
-#define PPB_NONE         0
-#define PPB_EPO_OUT_ONLY 1
-#define PPB_ALL          2
-#define PPB_EPN_ONLY     3
-
-#if defined __XC8
-	#define memcpy_from_rom(x,y,z) memcpy(x,y,z)
-	#define FAR
-	#define BD_ATTR_TAG @##BD_ADDR
-	#ifdef BUFFER_ADDR
-		#define XC8_BUFFER_ADDR_TAG @##BUFFER_ADDR
-	#else
-		#define XC8_BUFFER_ADDR_TAG
-	#endif
-#endif
-
-#elif _PIC18
-
-#define NEEDS_PULL /* Whether to pull up D+/D- with SFR_PULL_EN. */
-#define HAS_LOW_SPEED
-#define HAS_ON_CHIP_XCVR_DIS
-#define NEEDS_CLEAR_STALL
-
-#define BDNADR_TYPE              uint16_t
-#define PHYS_ADDR(VIRTUAL_ADDR)  (VIRTUAL_ADDR)
-
-#define SFR_FULL_SPEED_EN        UCFGbits.FSEN
-#define SFR_PULL_EN              UCFGbits.UPUEN
-#define SFR_ON_CHIP_XCVR_DIS     UCFGbits.UTRDIS
-#define SET_PING_PONG_MODE(n)    do { UCFGbits.PPB0 = n & 1; UCFGbits.PPB1 = (n & 2)? 1: 0; } while (0)
-
-#define SFR_USB_INTERRUPT_FLAGS  UIR
-#define SFR_USB_RESET_IF         UIRbits.URSTIF
-#define SFR_USB_STALL_IF         UIRbits.STALLIF
-#define SFR_USB_TOKEN_IF         UIRbits.TRNIF
-#define SFR_USB_SOF_IF           UIRbits.SOFIF
-#define SFR_USB_IF               PIR2bits.USBIF
-
-#define SFR_USB_INTERRUPT_EN     UIE
-#define SFR_TRANSFER_IE          UIEbits.TRNIE
-#define SFR_STALL_IE             UIEbits.STALLIE
-#define SFR_RESET_IE             UIEbits.URSTIE
-#define SFR_SOF_IE               UIEbits.SOFIE
-#define SFR_USB_IE               PIE2bits.USBIE
-
-#define SFR_USB_EXTENDED_INTERRUPT_EN UEIE
-
-#define SFR_EP_MGMT_TYPE         UEP1bits_t /* TODO test */
-#define UEP_REG_STRIDE 1
-#define SFR_EP_MGMT(ep)          ((SFR_EP_MGMT_TYPE*) (&UEP0 + UEP_REG_STRIDE * (ep)))
-#define SFR_EP_MGMT_HANDSHAKE    EPHSHK
-#define SFR_EP_MGMT_STALL        EPSTALL
-#define SFR_EP_MGMT_OUT_EN       EPOUTEN
-#define SFR_EP_MGMT_IN_EN        EPINEN
-#define SFR_EP_MGMT_CON_DIS      EPCONDIS /* disable control transfers */
-
-#define SFR_USB_ADDR             UADDR
-#define SFR_USB_EN               UCONbits.USBEN
-#define SFR_USB_PKT_DIS          UCONbits.PKTDIS
-#define SFR_USB_PING_PONG_RESET  UCONbits.PPBRST
-
-#define SFR_USB_STATUS           USTAT
-#define SFR_USB_STATUS_EP        USTATbits.ENDP
-#define SFR_USB_STATUS_DIR       USTATbits.DIR
-#define SFR_USB_STATUS_PPBI      USTATbits.PPBI
-
-#define CLEAR_ALL_USB_IF()       SFR_USB_INTERRUPT_FLAGS = 0 /*TODO TEST!*/
-#define CLEAR_USB_RESET_IF()     SFR_USB_RESET_IF = 0
-#define CLEAR_USB_STALL_IF()     SFR_USB_STALL_IF = 0
-#define CLEAR_USB_TOKEN_IF()     SFR_USB_TOKEN_IF = 0
-#define CLEAR_USB_SOF_IF()       SFR_USB_SOF_IF = 0
-
-/* Buffer Descriptor BDnSTAT flags. On Some MCUs, apparently, when handing
- * a buffer descriptor to the SIE, there's a race condition that can happen
- * if you don't set the BDnSTAT byte as a single operation. This was observed
- * on the PIC18F46J50 when sending 8-byte IN-transactions while doing control
- * transfers. */
-#define BDNSTAT_UOWN   0x80
-#define BDNSTAT_DTS    0x40
-#define BDNSTAT_DTSEN  0x08
-#define BDNSTAT_BSTALL 0x04
-#define BDNCNT_MASK    0x03ff /* 10 bits of BDnCNT in BDnSTAT_CNT */
-
-/* Buffer Descriptor
- *
- * This represents the Buffer Descriptor as laid out in the PIC18F4550
- * Datasheet.  A buffer descriptor contains data about either an in or out
- * endpoint buffer.  Bufffer descriptors are almost the same on all 8-bit
- * parts, best I've so far been able to tell.  The fields that aren't in the
- * newer datasheets like KEN and INCDIS aren't used, so it doesn't hurt to
- * have them here on those parts.
- *
- * While the layout is very similar on 16-bit parts, a different struct is
- * required on 16-bit for several reasons, including endianness (the 8-bit
- * BC/BDnSTAT bits are effectively big-endian), and the ability to optimize
- * for each platform (eg: writing BDnSTAT/BDnCNT as a 16-bit word on 16-bit
- * platforms).
- */
-struct buffer_descriptor {
-	union {
-		struct {
-			/* When receiving from the SIE. (USB Mode) */
-			uint8_t BC8 : 1;
-			uint8_t BC9 : 1;
-			uint8_t PID : 4; /* See enum PID */
-			uint8_t reserved: 1;
-			uint8_t UOWN : 1;
-		};
-		struct {
-			/* When giving to the SIE (CPU Mode) */
-			uint8_t /*BC8*/ : 1;
-			uint8_t /*BC9*/ : 1;
-			uint8_t BSTALL : 1;
-			uint8_t DTSEN : 1;
-			uint8_t INCDIS : 1;
-			uint8_t KEN : 1;
-			uint8_t DTS : 1;
-			uint8_t /*UOWN*/ : 1;
-		};
-		uint8_t BDnSTAT;
-	} STAT;
-	uint8_t BDnCNT;
-	BDNADR_TYPE BDnADR; /* BDnADRL and BDnADRH; */
-};
-
-#ifdef LARGE_EP
-#define SET_BDN(REG, FLAGS, CNT) do { (REG).BDnCNT = (CNT); \
-           (REG).STAT.BDnSTAT = (FLAGS) | ((CNT) & 0x300) >> 8; } while(0)
-#define BDN_LENGTH(REG) ( ((REG).STAT.BDnSTAT & 0x03) << 8 | (REG).BDnCNT )
-#else
-#define SET_BDN(REG, FLAGS, CNT) do { (REG).BDnCNT = (CNT); \
-                                      (REG).STAT.BDnSTAT = (FLAGS); } while(0)
-#define BDN_LENGTH(REG) (REG.BDnCNT)
-#endif
-
-#ifdef _18F46J50
-#define BD_ADDR 0x400
-//#undef BUFFER_ADDR
-#else
-#error "CPU not supported yet"
-#endif
-
-#define PPB_NONE         0
-#define PPB_EPO_OUT_ONLY 1
-#define PPB_ALL          2
-#define PPB_EPN_ONLY     3
-
-/* Compiler stuff. Probably should be somewhere else. */
-#ifdef __C18
-	#define FAR far
-	#define memcpy_from_rom(x,y,z) memcpypgm2ram(x,(rom void*)y,z)
-	#define BD_ATTR_TAG
-	#define XC8_BUFFER_ADDR_TAG
-#elif defined __XC8
-	#define memcpy_from_rom(x,y,z) memcpy(x,y,z)
-	#define FAR
-	#define BD_ATTR_TAG @##BD_ADDR
-	#ifdef BUFFER_ADDR
-		#define XC8_BUFFER_ADDR_TAG @##BUFFER_ADDR
-	#else
-		#define XC8_BUFFER_ADDR_TAG
-	#endif
-#endif
-
-#elif __XC16__
-
-#define USB_NEEDS_POWER_ON
-#define USB_NEEDS_SET_BD_ADDR_REG
-#define HAS_ON_CHIP_XCVR_DIS
-
-#define BDNADR_TYPE              void *
-#define PHYS_ADDR(VIRTUAL_ADDR)  (VIRTUAL_ADDR)
-
-#define SFR_PULL_EN              /* Not used on PIC24 */
-#define SFR_ON_CHIP_XCVR_DIS     U1CNFG2bits.UTRDIS
-#define SET_PING_PONG_MODE(n)    U1CNFG1bits.PPB = n
-
-#define SFR_USB_INTERRUPT_FLAGS  U1IR
-#define SFR_USB_RESET_IF         U1IRbits.URSTIF
-#define SFR_USB_STALL_IF         U1IRbits.STALLIF
-#define SFR_USB_TOKEN_IF         U1IRbits.TRNIF
-#define SFR_USB_SOF_IF           U1IRbits.SOFIF
-#define SFR_USB_IF               IFS5bits.USB1IF
-
-#define SFR_USB_INTERRUPT_EN     U1IE
-#define SFR_TRANSFER_IE          U1IEbits.TRNIE
-#define SFR_STALL_IE             U1IEbits.STALLIE
-#define SFR_RESET_IE             U1IEbits.URSTIE
-#define SFR_SOF_IE               U1IEbits.SOFIE
-#define SFR_USB_IE               IEC5bits.USB1IE
-
-#define SFR_USB_EXTENDED_INTERRUPT_EN U1EIE
-
-#define SFR_EP_MGMT_TYPE         U1EP1BITS
-#define UEP_REG_STRIDE 1
-#define SFR_EP_MGMT(ep)          ((SFR_EP_MGMT_TYPE*) (&U1EP0 + UEP_REG_STRIDE * (ep)))
-#define SFR_EP_MGMT_HANDSHAKE    EPHSHK
-#define SFR_EP_MGMT_STALL        EPSTALL
-#define SFR_EP_MGMT_IN_EN        EPTXEN   /* In/out from HOST perspective */
-#define SFR_EP_MGMT_OUT_EN       EPRXEN
-#define SFR_EP_MGMT_CON_DIS      EPCONDIS /* disable control transfers */
-                                 /* Ignoring RETRYDIS and LSPD for now */
-#define SFR_USB_ADDR             U1ADDR
-#define SFR_USB_EN               U1CONbits.USBEN
-#define SFR_USB_PKT_DIS          U1CONbits.PKTDIS
-#define SFR_USB_PING_PONG_RESET  U1CONbits.PPBRST
-
-
-#define SFR_USB_STATUS           U1STAT
-#define SFR_USB_STATUS_EP        U1STATbits.ENDPT
-#define SFR_USB_STATUS_DIR       U1STATbits.DIR
-#define SFR_USB_STATUS_PPBI      U1STATbits.PPBI
-
-#define SFR_USB_POWER            U1PWRCbits.USBPWR
-#define SFR_BD_ADDR_REG          U1BDTP1
-
-#define BDnCNT                   STAT.BDnCNT_byte /* buffer descriptor */
-
-#define SFR_OTGEN                U1OTGCONbits.OTGEN
-#define SFR_DPPULUP              U1OTGCONbits.DPPULUP
-
-#define CLEAR_ALL_USB_IF()       do { SFR_USB_INTERRUPT_FLAGS = 0xff; U1EIR = 0xff; } while(0)
-#define CLEAR_USB_RESET_IF()     SFR_USB_INTERRUPT_FLAGS = 0x1
-#define CLEAR_USB_STALL_IF()     SFR_USB_INTERRUPT_FLAGS = 0x80
-#define CLEAR_USB_TOKEN_IF()     SFR_USB_INTERRUPT_FLAGS = 0x08
-#define CLEAR_USB_SOF_IF()       SFR_USB_INTERRUPT_FLAGS = 0x4
-
-#define BDNSTAT_UOWN   0x8000
-#define BDNSTAT_DTS    0x4000
-#define BDNSTAT_DTSEN  0x0800
-#define BDNSTAT_BSTALL 0x0400
-
-/* Buffer Descriptor
- *
- * This struct represents BDnSTAT in the datasheet. See the comment in the
- * 8-bit section above for more information on buffer descriptors.
- */
-struct buffer_descriptor {
-	union {
-		struct {
-			/* When receiving from the SIE. (USB Mode) */
-			uint16_t BC : 10;
-			uint16_t PID : 4; /* See enum PID */
-			uint16_t DTS: 1;
-			uint16_t UOWN : 1;
-		};
-		struct {
-			/* When giving to the SIE (CPU Mode) */
-			uint16_t /*BC*/ : 10;
-			uint16_t BSTALL : 1;
-			uint16_t DTSEN : 1;
-			uint16_t reserved : 2;
-			uint16_t DTS : 1;
-			uint16_t /*UOWN*/ : 1;
-		};
-		struct {
-			uint8_t BDnSTAT_lsb;
-			uint8_t BDnSTAT; /* High byte, where the flags are */
-		};
-		uint16_t BDnSTAT_CNT; /* BDnSTAT and BDnCNT as a 16-bit */
-	}STAT;
-	BDNADR_TYPE BDnADR;
-};
-
-#define SET_BDN(REG, FLAGS, CNT) \
-                     do { (REG).STAT.BDnSTAT_CNT = (FLAGS) | (CNT); } while(0)
-
-#ifdef LARGE_EP
-	#define BDN_LENGTH(REG) (REG.STAT.BC)
-#else
-	#define BDN_LENGTH(REG) (REG.STAT.BDnSTAT_lsb)
-#endif
-
-#define BD_ADDR
-#define BUFFER_ADDR
-#define BD_ATTR_TAG __attribute__((aligned(512)))
-#define XC8_BUFFER_ADDR_TAG
-
-#define PPB_NONE         0
-#define PPB_EPO_OUT_ONLY 1
-#define PPB_ALL          2
-#define PPB_EPN_ONLY     3
-
-/* Compiler stuff. Probably should be somewhere else. */
-#define FAR
-#define memcpy_from_rom(x,y,z) memcpy(x,y,z)
-
-#elif __XC32__
-
-#define USB_NEEDS_POWER_ON
-#define USB_NEEDS_SET_BD_ADDR_REG
-#define USB_FULL_PING_PONG_ONLY
-
-#define BDNADR_TYPE              uint32_t /* physical address */
-#define PHYS_ADDR(VIRTUAL_ADDR)  KVA_TO_PA(VIRTUAL_ADDR)
-
-#define SFR_PULL_EN              /* Not used on PIC32MX */
-#define SFR_ON_CHIP_XCVR_DIS     U1CNFG2bits.UTRDIS
-#define SET_PING_PONG_MODE(n)    U1CNFG1bits.PPB = n
-
-#define SFR_USB_INTERRUPT_FLAGS  U1IR
-#define SFR_USB_RESET_IF         U1IRbits.URSTIF
-#define SFR_USB_STALL_IF         U1IRbits.STALLIF
-#define SFR_USB_TOKEN_IF         U1IRbits.TRNIF
-#define SFR_USB_SOF_IF           U1IRbits.SOFIF
-#define SFR_USB_IF               IFS1bits.USBIF
-
-#define SFR_USB_INTERRUPT_EN     U1IE
-#define SFR_TRANSFER_IE          U1IEbits.TRNIE
-#define SFR_STALL_IE             U1IEbits.STALLIE
-#define SFR_RESET_IE             U1IEbits.URSTIE
-#define SFR_SOF_IE               U1IEbits.SOFIE
-#define SFR_USB_IE               IEC1bits.USBIE
-
-#define SFR_USB_EXTENDED_INTERRUPT_EN U1EIE
-
-#define SFR_EP_MGMT_TYPE         __U1EP1bits_t
-#define UEP_REG_STRIDE           4
-#define SFR_EP_MGMT(ep)          ((SFR_EP_MGMT_TYPE*) (&U1EP0 + UEP_REG_STRIDE * (ep)))
-#define SFR_EP_MGMT_HANDSHAKE    EPHSHK
-#define SFR_EP_MGMT_STALL        EPSTALL
-#define SFR_EP_MGMT_IN_EN        EPTXEN   /* In/out from HOST perspective */
-#define SFR_EP_MGMT_OUT_EN       EPRXEN
-#define SFR_EP_MGMT_CON_DIS      EPCONDIS /* disable control transfers */
-                                 /* Ignoring RETRYDIS and LSPD for now */
-#define SFR_USB_ADDR             U1ADDR
-#define SFR_USB_EN               U1CONbits.USBEN
-#define SFR_USB_PKT_DIS          U1CONbits.PKTDIS
-#define SFR_USB_PING_PONG_RESET  U1CONbits.PPBRST
-
-
-#define SFR_USB_STATUS           U1STAT
-#define SFR_USB_STATUS_EP        U1STATbits.ENDPT
-#define SFR_USB_STATUS_DIR       U1STATbits.DIR
-#define SFR_USB_STATUS_PPBI      U1STATbits.PPBI
-
-#define SFR_USB_POWER            U1PWRCbits.USBPWR
-#define SFR_BD_ADDR_REG1         U1BDTP1
-#define SFR_BD_ADDR_REG2         U1BDTP2
-#define SFR_BD_ADDR_REG3         U1BDTP3
-
-#define SFR_OTGEN                U1OTGCONbits.OTGEN
-#define SFR_DPPULUP              U1OTGCONbits.DPPULUP
-
-#define CLEAR_ALL_USB_IF()       do { SFR_USB_INTERRUPT_FLAGS = 0xff; U1EIR = 0xff; } while(0)
-#define CLEAR_USB_RESET_IF()     SFR_USB_INTERRUPT_FLAGS = 0x1
-#define CLEAR_USB_STALL_IF()     SFR_USB_INTERRUPT_FLAGS = 0x80
-#define CLEAR_USB_TOKEN_IF()     SFR_USB_INTERRUPT_FLAGS = 0x08
-#define CLEAR_USB_SOF_IF()       SFR_USB_INTERRUPT_FLAGS = 0x4
-
-#define BDNSTAT_UOWN   0x0080
-#define BDNSTAT_DTS    0x0040
-#define BDNSTAT_DTSEN  0x0008
-#define BDNSTAT_BSTALL 0x0004
-
-/* Buffer Descriptor
- *
- * This struct represents BDnSTAT in the datasheet. See the comment in the
- * 8-bit section above for more information on buffer descriptors.
- */
-struct buffer_descriptor {
-	union {
-		struct {
-			/* When receiving from the SIE. (USB Mode) */
-			uint32_t : 2;
-			uint32_t PID : 4; /* See enum PID */
-			uint32_t DTS: 1;
-			uint32_t UOWN : 1;
-
-			uint32_t : 8;
-			uint32_t BDnCNT : 10;
-			uint32_t : 6;
-
-		};
-		struct {
-			/* When giving to the SIE (CPU Mode) */
-			uint32_t : 2;
-			uint32_t BSTALL : 1;
-			uint32_t DTSEN : 1;    /* DTS in datasheet */
-			uint32_t reserved : 2; /* NINC, KEEP */
-			uint32_t DTS : 1;      /* DATA0/1 in datasheet */
-			uint32_t /*UOWN*/ : 1;
-
-			uint32_t : 8;
-			uint32_t /*BDnCNT*/ : 10;
-			uint32_t :6;
-		};
-		struct {
-			uint16_t : 16;
-			uint16_t BDnSTAT; /* Low word, where the flags are */
-		};
-		uint32_t BDnSTAT_CNT; /* BDnSTAT and BDnCNT as a 16-bit */
-	}STAT;
-	BDNADR_TYPE BDnADR;
-};
-
-#define SET_BDN(REG, FLAGS, CNT) \
-                     do { (REG).STAT.BDnSTAT_CNT = (FLAGS) | ((CNT)<<16); } while(0)
-
-#ifdef LARGE_EP
-	#define BDN_LENGTH(REG) (REG.STAT.BDnCNT)
-#else
-	#define BDN_LENGTH(REG) (REG.STAT.BDnCNT)
-#endif
-
-
-#define BD_ADDR
-#define BUFFER_ADDR
-#define BD_ATTR_TAG __attribute__((aligned(512), coherent))
-#define XC8_BUFFER_ADDR_TAG __attribute__((coherent))
-
-#define PPB_NONE         0 /* Unused on PIC32 */
-#define PPB_EPO_OUT_ONLY 1 /* Unused on PIC32 */
-#define PPB_ALL          2 /* Unused on PIC32 */
-#define PPB_EPN_ONLY     3
-
-/* Compiler stuff. Probably should be somewhere else. */
-#define FAR
-#define memcpy_from_rom(x,y,z) memcpy(x,y,z)
-
-
-#else
-	#error "Your architecture is not supported"
-#endif
-
-
-
-#endif /* USB_HAL_H__ */
--- a/usb/usb_hid.h	Wed Feb 17 05:54:21 2016 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,346 +0,0 @@
-/*
- *  M-Stack USB Chapter 9 Structures
- *  Copyright (C) 2013 Alan Ott <alan@signal11.us>
- *  Copyright (C) 2013 Signal 11 Software
- *
- *  2013-08-13
- *
- *  M-Stack is free software: you can redistribute it and/or modify it under
- *  the terms of the GNU Lesser General Public License as published by the
- *  Free Software Foundation, version 3; or the Apache License, version 2.0
- *  as published by the Apache Software Foundation.  If you have purchased a
- *  commercial license for this software from Signal 11 Software, your
- *  commerical license superceeds the information in this header.
- *
- *  M-Stack is distributed in the hope that it will be useful, but WITHOUT
- *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
- *  License for more details.
- *
- *  You should have received a copy of the GNU Lesser General Public License
- *  along with this software.  If not, see <http://www.gnu.org/licenses/>.
- *
- *  You should have received a copy of the Apache License, verion 2.0 along
- *  with this software.  If not, see <http://www.apache.org/licenses/>.
- */
-
-#ifndef USB_HID_H__
-#define USB_HID_H__
-
-/** @file usb_hid.h
- *  @brief USB HID Class Enumerations and Structures
- *  @defgroup public_api Public API
- */
-
-/** @addtogroup public_api
- *  @{
- */
-
-#include <stdint.h>
-#include "usb_config.h"
-
-#if defined(__XC16__) || defined(__XC32__)
-#pragma pack(push, 1)
-#elif __XC8
-#else
-#error "Compiler not supported"
-#endif
-
-/** @defgroup hid_items USB HID Class Enumerations and Descriptors
- *  @brief Packet structs from the Device Class Definition for Human
- *  Interface Devices (commonly the USB HID Specification), version 1.11,
- *  chapter 6.
- *
- *  For more information about these structures, see the above referenced
- *  document, available from http://www.usb.org .
- *  @addtogroup hid_items
- *  @{
- */
-
-#define HID_INTERFACE_CLASS 0x03
-
-/** HID Class Descriptor Tyes */
-enum HIDDescriptorTypes {
-	DESC_HID = 0x21,
-	DESC_REPORT = 0x22,
-	DESC_PHYSICAL = 0x23,
-};
-
-/** HID Class Requests */
-enum HIDRequests {
-	HID_GET_REPORT = 0x1,
-	HID_GET_IDLE = 0x2,
-	HID_GET_PROTOCOL = 0x3,
-	HID_SET_REPORT = 0x9,
-	HID_SET_IDLE = 0xa,
-	HID_SET_PROTOCOL = 0xb,
-};
-
-/** HID Report Types */
-enum HIDReportTypes {
-	HID_INPUT = 0x1,
-	HID_OUTPUT = 0x2,
-	HID_FEATURE = 0x3,
-};
-
-/** HID Protocols */
-enum HIDProtocols {
-	HID_PROTO_BOOT = 0,
-	HID_PROTO_REPORT = 1,
-};
-
-struct hid_descriptor {
-	uint8_t bLength; /**< Size of this struct plus any optional descriptors */
-	uint8_t bDescriptorType; /**< Set to DESC_HID */
-	uint16_t bcdHID; /**< HID Version in BCD. (0x0100 is 1.00) */
-	uint8_t bCountryCode;
-	uint8_t bNumDescriptors; /**< Number of class descriptors (always at least 1) */
-	uint8_t bDescriptorType2; /**< Set to DESC_REPORT */
-	uint16_t wDescriptorLength; /**< Set to size of report descriptor */
-};
-
-struct hid_optional_descriptor {
-	uint8_t bDescriptorType;
-	uint16_t wDescriptorLength;
-};
-
-/** HID Descriptor Function
- *
- * The USB Stack will call this function to retrieve the HID descriptor for
- * each HID interface when requested by the host. This function is mandatory
- * for HID devices.
- *
- * @param interface  The interface for which the descriptor is requested
- * @param ptr        A Pointer to a pointer which should be set to the
- *                   requested HID descriptor by this function.
- *
- * @returns
- *   Return the length of the HID descriptor in bytes or -1 if the descriptor
- *   does not exist.
- */
-extern int16_t USB_HID_DESCRIPTOR_FUNC(uint8_t interface, const void **ptr);
-
-/** HID Report Descriptor Function
- *
- * The USB Stack will call this function to retrieve the HID report
- * descriptor for each HID interface when requested by the host.  This
- * function is mandatory for HID devices.
- *
- * @param interface  The interface for which the descriptor is requested
- * @param ptr        A Pointer to a pointer which should be set to the
- *                   requested HID report descriptor by this function.
- *
- * @returns
- *   Return the length of the HID report descriptor in bytes or -1 if the
- *   descriptor does not exist.
- */
-extern int16_t USB_HID_REPORT_DESCRIPTOR_FUNC(uint8_t interface, const void **ptr);
-
-#ifdef USB_HID_PHYSICAL_DESCRIPTOR_FUNC
-/** HID Physical Descriptor Function
- *
- * The USB Stack will call this function to retrieve the physical
- * descriptor for each HID interface when requested by the host.  This
- * function, and physical descriptors, are optional.
- *
- * @param interface  The interface for which the descriptor is requested
- * @param index      The physical descriptor set to return. Index zero
- *                   requests a special descriptor describing the number of
- *                   descriptor sets and their sizes. See the HID
- *                   specification, version 1.11, section 7.1.1.
- * @param ptr        A Pointer to a pointer which should be set to the
- *                   requested physical descriptor by this function
- *
- * @returns
- *   Return the length of the physical descriptor in bytes or -1 if the
- *   descriptor does not exist.
- */
-extern int16_t USB_HID_PHYSICAL_DESCRIPTOR_FUNC(uint8_t interface, uint8_t index, const void **ptr);
-#endif
-
-#ifdef HID_GET_REPORT_CALLBACK
-/** HID Get_Report request callback
- *
- * The USB Stack will call this function when a Get_Report request has been
- * received from the host.  This function should set the @p report pointer
- * to a buffer containing the report data and return the length of the
- * report.  Once the transfer has completed, @p callback will be called with
- * the @p context pointer provided.  The buffer pointed to by @p report
- * should be considered to be owned by the USB stack until the @p callback
- * is called and should not be modified by the application until that time.
- *
- *
- * @param interface      The interface for which the report is requested
- * @param report_type    The type of report, either @p HID_INPUT,
- *                       @p HID_OUTPUT, or @p HID_FEATURE.
- * @param report_id      The report index requested. This will be zero if the
- *                       device does not use numbered reports.
- * @param report         A pointer to a pointer which should be set to the
- *                       report data.
- * @param callback       A callback function to call when the transfer
- *                       completes.  This parameter is mandatory.  Once the
- *                       callback is called, the transfer is over, and the
- *                       buffer can be considered to be owned by the
- *                       application again.
- * @param context        A pointer to be passed to the callback.  The USB stack
- *                       does not dereference this pointer.
- *
- * @returns
- *   Return 0 if the request can be handled or -1 if it cannot. Returning -1
- *   will cause STALL to be returned to the host.
- */
-extern int16_t HID_GET_REPORT_CALLBACK(uint8_t interface, uint8_t report_type,
-                                       uint8_t report_id, const void **report,
-                                       usb_ep0_data_stage_callback *callback,
-                                       void **context);
-#endif
-
-
-#ifdef HID_SET_REPORT_CALLBACK
-/** HID Set_Report request callback
- *
- * The USB Stack will call this function when a Set_Report request has been
- * received from the host. There are two ways to handle this:
- *
- * 0. For unknown requests, return -1. This will send a STALL to the host. 
- * 1. For known requests the callback should call
- *    @p usb_start_receive_ep0_data_stage() with a buffer to be filled with
- *    the report data and a callback which will get called when the data
- *    stage is complete.  The callback is required, and the data buffer
- *    passed to @p usb_start_receive_ep0_data_stage() must remain valid
- *    until the callback is called.
- *
- * It is worth noting that only one control transfer can be active at any
- * given time.  Once HID_SET_REPORT_CALLBACK() has been called, it will not
- * be called again until the next transfer, meaning that if the
- * application-provided HID_SET_REPORT_CALLBACK() function performs option 1
- * above, the callback function passed to @p
- * usb_start_receive_ep0_data_stage() will be called before any other setup
- * transfer can happen again.  Thus, it is safe to use the same buffer
- * for all control transfers if desired.
- *
- *
- * @param interface      The interface for which the report is provided
- * @param report_type    The type of report, either @p HID_INPUT,
- *                       @p HID_OUTPUT, or @p HID_FEATURE.
- * @param report_id      The report index requested. This will be zero if the
- *                       device does not use numbered reports.
- * @returns
- *   Return 0 if the request can be handled or -1 if it cannot. Returning -1
- *   will cause STALL to be returned to the host.
- */
-extern int8_t HID_SET_REPORT_CALLBACK(uint8_t interface, uint8_t report_type,
-                                      uint8_t report_id);
-#endif
-
-#ifdef HID_GET_IDLE_CALLBACK
-/** HID Get_Idle request callback
- *
- * The USB Stack will call this function when a Get_Idle request has been
- * received from the host. The application should return the current idle
- * rate.
- *
- * @param interface      The interface for which the report is provided
- * @param report_id      The report index requested.
- *
- * @returns
- *   Return the current idle rate.
- */
-extern uint8_t HID_GET_IDLE_CALLBACK(uint8_t interface, uint8_t report_id);
-#endif
-
-#ifdef HID_SET_IDLE_CALLBACK
-/** HID Set_Idle request callback
- *
- * The USB Stack will call this function when a Set_Idle request has been
- * received from the host. The application should use the provided value
- * as the idle rate.
- *
- * @param interface      The interface for which the report is provided
- * @param report_id      The report index requested. Zero means all reports.
- * @param idle_rate      The idle rate to set, in multiples of 4 milliseconds.
- *
- * @returns
- *   Return 0 on success and -1 on failure.
- */
-extern int8_t HID_SET_IDLE_CALLBACK(uint8_t interface, uint8_t report_id,
-                                    uint8_t idle_rate);
-#endif
-
-#ifdef HID_GET_PROTOCOL_CALLBACK
-/** HID Get_Protocol request callback
- *
- * The USB Stack will call this function when a Get_Protocol request has
- * been received from the host.  The application should return the current
- * protocol.
- *
- * @param interface      The interface for which the report is provided
- *
- * @returns
- *   Return the current protocol (@p HID_PROTO_BOOT, @p HID_PROTO_REPORT) or
- *   -1 on failure.
- */
-extern int8_t HID_GET_PROTOCOL_CALLBACK(uint8_t interface);
-#endif
-
-#ifdef HID_SET_PROTOCOL_CALLBACK
-/** HID Set_Protocol request callback
- *
- * The USB Stack will call this function when a Set_Protocol request has
- * been received from the host, and will provide the protocol to set as
- * either @p HID_PROTO_BOOT, or @p HID_PROTO_REPORT.
- *
- * @param interface      The interface for which the report is provided
- * @param protocol       The protocol to set. Either @p HID_PROTO_BOOT, or
- *                       @p HID_PROTO_REPORT.
- *
- * @returns
- *   Return 0 on success or -1 on failure.
- */
-extern int8_t HID_SET_PROTOCOL_CALLBACK(uint8_t interface, uint8_t protocol);
-#endif
-
-#ifdef MULTI_CLASS_DEVICE
-/** Set the list of HID interfaces on this device
- *
- * Provide a list to the HID class implementation of the interfaces on this
- * device which should be treated as HID devices.  This is only necessary
- * for multi-class composite devices to make sure that requests are not
- * confused between interfaces.  It should be called before usb_init().
- *
- * @param interfaces      An array of interfaces which are HID class.
- * @param num_interfaces  The size of the @p interfaces array.
- */
-void hid_set_interface_list(uint8_t *interfaces, uint8_t num_interfaces);
-#endif
-
-/** Process HID Setup Request
- *
- * Process a setup request which has been unhandled as if it is potentially
- * a HID setup request. This function will then call appropriate callbacks
- * into the appliction if the setup packet is one recognized by the HID
- * specification.
- *
- * @param setup          A setup packet to handle
- *
- * @returns
- *   Returns 0 if the setup packet could be processed or -1 if it could not.
- */
-uint8_t process_hid_setup_request(const struct setup_packet *setup);
-
-
-/* Doxygen end-of-group for hid_items */
-/** @}*/
-
-
-#if defined(__XC16__) || defined(__XC32__)
-#pragma pack(pop)
-#elif __XC8
-#else
-#error "Compiler not supported"
-#endif
-
-/* Doxygen end-of-group for public_api */
-/** @}*/
-
-#endif /* USB_HID_H__ */
--- a/usb/usb_microsoft.h	Wed Feb 17 05:54:21 2016 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,184 +0,0 @@
-/*
- *  M-Stack Microsoft-Specific OS Descriptors
- *  Copyright (C) 2013 Alan Ott <alan@signal11.us>
- *  Copyright (C) 2013 Signal 11 Software
- *
- *  2013-08-27
- *
- *  M-Stack is free software: you can redistribute it and/or modify it under
- *  the terms of the GNU Lesser General Public License as published by the
- *  Free Software Foundation, version 3; or the Apache License, version 2.0
- *  as published by the Apache Software Foundation.  If you have purchased a
- *  commercial license for this software from Signal 11 Software, your
- *  commerical license superceeds the information in this header.
- *
- *  M-Stack is distributed in the hope that it will be useful, but WITHOUT
- *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
- *  License for more details.
- *
- *  You should have received a copy of the GNU Lesser General Public License
- *  along with this software.  If not, see <http://www.gnu.org/licenses/>.
- *
- *  You should have received a copy of the Apache License, verion 2.0 along
- *  with this software.  If not, see <http://www.apache.org/licenses/>.
- */
-
-#ifndef USB_MICROSOFT_H__
-#define USB_MICROSOFT_H__
-
-/** @file usb.h
- *  @brief Microsoft-Specific OS Descriptors
- *  @defgroup public_api Public API
- */
-
-/** @addtogroup public_api
- *  @{
- */
-
-#include <stdint.h>
-
-#if defined(__XC16__) || defined(__XC32__)
-#pragma pack(push, 1)
-#elif __XC8
-#else
-#error "Compiler not supported"
-#endif
-
-/** @defgroup microsoft_items Microsoft-Specific Descriptors
- *  @brief Packet structs from Microsoft's documentation which deal with
- *  the Microsoft OS String Descriptor and the Extended Compat Descriptors.
- *
- *  For more information about these structures, see the Microsoft
- *  documentation at http://msdn.microsoft.com/library/windows/hardware/gg463182
- *  or search for "Microsoft OS Descriptors" on http://msdn.microsoft.com .
- *  Also see docs/winusb.txt in the M-Stack distribution.
- *
- *  @addtogroup microsoft_items
- *  @{
- */
-
-/** OS String Descriptor
- *
- * This is the first descriptor Windows will request, as string number 0xee.
- */
-struct microsoft_os_descriptor {
-	uint8_t bLength;         /**< set to 0x12 */
-	uint8_t bDescriptorType; /**< set to 0x3 */
-	uint16_t qwSignature[7]; /**< set to "MSFT100" (Unicode) (no NULL) */
-	uint8_t bMS_VendorCode;  /**< Set to the bRequest by which the host
-	                              should ask for the Compat ID and
-	                              Property descriptors. */
-	uint8_t bPad;            /**< Set to 0x0 */
-};
-
-/** Extended Compat ID Header
- *
- * This is the header for the Extended Compat ID Descriptor
- */
-struct microsoft_extended_compat_header {
-	uint32_t dwLength;   /**< Total length of descriptor (header + functions) */
-	uint16_t bcdVersion; /**< Descriptor version number, 0x0100. */
-	uint16_t wIndex;     /**< This OS feature descriptor; set to 0x04. */
-	uint8_t  bCount;     /**< Number of custom property sections */
-	uint8_t  reserved[7];
-};
-
-/** Extended Compat ID Function
- *
- * This is the function struct for the Extended Compat ID Descriptor
- */
-struct microsoft_extended_compat_function {
-	uint8_t bFirstInterfaceNumber; /**< The interface or function number */
-	uint8_t reserved;
-	uint8_t compatibleID[8];       /**< Compatible String */
-	uint8_t subCompatibleID[8];    /**< Subcompatible String */
-	uint8_t reserved2[6];
-};
-
-/** Extended Properties Header
- *
- * This is the header for the Extended Properties Descriptor
- */
-struct microsoft_extended_properties_header {
-	uint32_t dwLength;   /**< Total length of descriptor (header + functions) */
-	uint16_t bcdVersion; /**< Descriptor version number, 0x0100. */
-	uint16_t wIndex;     /**< This OS feature descriptor; set to 0x04. */
-	uint16_t bCount;     /**< Number of custom property sections */
-};
-
-/** Extended Property Section header
- *
- * This is the first part of the Extended Property Section, which is a
- * variable-length descriptor. The Variable-length types must be packed
- * manually after this section header.
- *
- */
-struct microsoft_extended_property_section_header {
-	uint32_t dwSize; /**< Size of this section (this struct + data) */
-	uint32_t dwPropertyDataType; /**< Property Data Format */
-
-/* Variable-length fields and lengths:
-	uint16_t wPropertyNameLength;
-	uint16_t bPropertyName[];
-	uint32_t dwPropertyDataLength;
-	uint8_t  bPropertyData[];
- */
-};
-
-#ifdef MICROSOFT_COMPAT_ID_DESCRIPTOR_FUNC
-/** @brief Callback for the GET_MS_DESCRIPTOR/CompatID request
- *
- * MICROSOFT_COMPAT_ID_DESCRIPTOR_FUNC() is called when a @p
- * GET_MS_DESCRIPTOR request is received from the host with a wIndex of 0x0004.
- * The value of MS_GET_DESCRIPTOR request is defined by
- * MICROSOFT_OS_DESC_VENDOR_CODE which is set in usb_config.h, and reported to
- * the host as part of the @p microsoft_os_descriptor. See the MSDN
- * documentation on "Microsoft OS Descriptors" for more information.
- *
- * @param interface      The interface for which the descriptor is queried
- * @param descriptor     a pointer to a pointer which should be set to the
- *                       descriptor data.
- * @returns
- *   Return the length of the descriptor pointed to by @p *descriptor, or -1
- *   if the descriptor does not exist.
- */
-uint16_t MICROSOFT_COMPAT_ID_DESCRIPTOR_FUNC(uint8_t interface,
-                                              const void **descriptor);
-#endif
-
-#ifdef MICROSOFT_CUSTOM_PROPERTY_DESCRIPTOR_FUNC
-/** @brief Callback for the GET_MS_DESCRIPTOR/Custom_Property request
- *
- * MICROSOFT_CUSTOM_PROPERTY_DESCRIPTOR_FUNC() is called when a @p
- * GET_MS_DESCRIPTOR request with a wIndex of 0x0005 is received from the host.
- * The value of the MS_GET_DESCRIPTOR request is defined by
- * MICROSOFT_OS_DESC_VENDOR_CODE which is set in usb_config.h, and reported to
- * the host as part of the @p microsoft_os_descriptor. See the MSDN
- * documentation on "Microsoft OS Descriptors" for more information.
- *
- * @param interface      The interface for which the descriptor is queried
- * @param descriptor     a pointer to a pointer which should be set to the
- *                       descriptor data.
- * @returns
- *   Return the length of the descriptor pointed to by @p *descriptor, or -1
- *   if the descriptor does not exist.
- */
-uint16_t MICROSOFT_CUSTOM_PROPERTY_DESCRIPTOR_FUNC(uint8_t interface,
-                                                   const void **descriptor);
-#endif
-
-/* Doxygen end-of-group for microsoft_items */
-/** @}*/
-
-#if defined(__XC16__) || defined(__XC32__)
-#pragma pack(pop)
-#elif __XC8
-#else
-#error "Compiler not supported"
-#endif
-
-/* Doxygen end-of-group for public_api */
-/** @}*/
-
-#endif /* USB_MICROSOFT_H__ */
--- a/usb/usb_winusb.c	Wed Feb 17 05:54:21 2016 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,88 +0,0 @@
-/*
- *  M-Stack Automatic WinUSB Support
- *  Copyright (C) 2013 Alan Ott <alan@signal11.us>
- *  Copyright (C) 2013 Signal 11 Software
- *
- *  2013-10-12
- *
- *  M-Stack is free software: you can redistribute it and/or modify it under
- *  the terms of the GNU Lesser General Public License as published by the
- *  Free Software Foundation, version 3; or the Apache License, version 2.0
- *  as published by the Apache Software Foundation.  If you have purchased a
- *  commercial license for this software from Signal 11 Software, your
- *  commerical license superceeds the information in this header.
- *
- *  M-Stack is distributed in the hope that it will be useful, but WITHOUT
- *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
- *  License for more details.
- *
- *  You should have received a copy of the GNU Lesser General Public License
- *  along with this software.  If not, see <http://www.gnu.org/licenses/>.
- *
- *  You should have received a copy of the Apache License, verion 2.0 along
- *  with this software.  If not, see <http://www.apache.org/licenses/>.
- */
-
-#include <stdint.h>
-#include "usb_config.h"
-#include "usb_microsoft.h"
-#include "usb_winusb.h"
-
-#ifdef AUTOMATIC_WINUSB_SUPPORT
-
-/* Microsoft-specific descriptors for automatic binding of the WinUSB driver.
- * See docs/winusb.txt for details. */
-struct extended_compat_descriptor_packet {
-	struct microsoft_extended_compat_header header;
-	struct microsoft_extended_compat_function function;
-};
-
-static struct extended_compat_descriptor_packet
-	this_extended_compat_descriptor =
-{
-	/* Header */
-	{
-	sizeof(struct extended_compat_descriptor_packet), /* dwLength */
-	0x0100, /* dwVersion*/
-	0x0004, /* wIndex: 0x0004 = Extended Compat ID */
-	1,      /* bCount, number of custom property sections */
-	{0},    /* reserved[7] */
-	},
-
-	/* Function */
-	{
-	0x0,      /* bFirstInterfaceNumber */
-	0x1,      /* reserved. Set to 1 in the Microsoft example */
-	"WINUSB", /* compatibleID[8] */
-	"",       /* subCompatibleID[8] */
-	{0},      /* reserved2[6] */
-	},
-};
-
-static struct microsoft_extended_properties_header
-				interface_0_property_descriptor =
-{
-	sizeof(interface_0_property_descriptor), /* dwLength */
-	0x0100, /* bcdVersion */
-	0x0005, /* wIndex, Extended Properties descriptor */
-	0x0,    /* bCount, Number of custom property sections */
-};
-
-uint16_t m_stack_winusb_get_microsoft_compat(uint8_t interface,
-                                              const void **descriptor)
-{
-	/* Check the interface here for composite devices. */
-	*descriptor = &this_extended_compat_descriptor;
-	return sizeof(this_extended_compat_descriptor);
-}
-
-uint16_t m_stack_winusb_get_microsoft_property(uint8_t interface,
-                                                const void **descriptor)
-{
-	/* Check the interface here for composite devices. */
-	*descriptor = &interface_0_property_descriptor;
-	return sizeof(interface_0_property_descriptor);
-}
-
-#endif /* AUTOMATIC_WINUSB_SUPPORT */
--- a/usb/usb_winusb.h	Wed Feb 17 05:54:21 2016 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,40 +0,0 @@
-/*
- *  M-Stack Automatic WinUSB Support
- *  Copyright (C) 2013 Alan Ott <alan@signal11.us>
- *  Copyright (C) 2013 Signal 11 Software
- *
- *  2013-10-12
- *
- *  M-Stack is free software: you can redistribute it and/or modify it under
- *  the terms of the GNU Lesser General Public License as published by the
- *  Free Software Foundation, version 3; or the Apache License, version 2.0
- *  as published by the Apache Software Foundation.  If you have purchased a
- *  commercial license for this software from Signal 11 Software, your
- *  commerical license superceeds the information in this header.
- *
- *  M-Stack is distributed in the hope that it will be useful, but WITHOUT
- *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
- *  License for more details.
- *
- *  You should have received a copy of the GNU Lesser General Public License
- *  along with this software.  If not, see <http://www.gnu.org/licenses/>.
- *
- *  You should have received a copy of the Apache License, verion 2.0 along
- *  with this software.  If not, see <http://www.apache.org/licenses/>.
- */
-
-#ifndef USB_WINUSB_H__
-#define USB_WINUSB_H__
-
-#include <stdint.h>
-
-/* Functions for automatic WinUSB support */
-
-uint16_t m_stack_winusb_get_microsoft_compat(uint8_t interface,
-                                              const void **descriptor);
-
-uint16_t m_stack_winusb_get_microsoft_property(uint8_t interface,
-                                                const void **descriptor);
-
-#endif /* USB_WINUSB_H__ */