re-arrange m-stack as per distribution. this makes the build
more complicated but it's easier to upgrade m-stack this way.
--- 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__ */