aboutsummaryrefslogtreecommitdiffstats
path: root/libmaple/usb
diff options
context:
space:
mode:
Diffstat (limited to 'libmaple/usb')
-rw-r--r--libmaple/usb/README63
-rw-r--r--libmaple/usb/rules.mk45
-rw-r--r--libmaple/usb/stm32f1/usb.c387
-rw-r--r--libmaple/usb/stm32f1/usb_cdcacm.c709
-rw-r--r--libmaple/usb/stm32f1/usb_lib_globals.h55
-rw-r--r--libmaple/usb/stm32f1/usb_reg_map.c88
-rw-r--r--libmaple/usb/stm32f1/usb_reg_map.h617
-rw-r--r--libmaple/usb/usb_lib/usb_core.c1013
-rw-r--r--libmaple/usb/usb_lib/usb_core.h251
-rw-r--r--libmaple/usb/usb_lib/usb_def.h88
-rw-r--r--libmaple/usb/usb_lib/usb_init.c64
-rw-r--r--libmaple/usb/usb_lib/usb_init.h57
-rw-r--r--libmaple/usb/usb_lib/usb_lib.h36
-rw-r--r--libmaple/usb/usb_lib/usb_mem.c73
-rw-r--r--libmaple/usb/usb_lib/usb_mem.h40
-rw-r--r--libmaple/usb/usb_lib/usb_regs.c748
-rw-r--r--libmaple/usb/usb_lib/usb_regs.h627
-rw-r--r--libmaple/usb/usb_lib/usb_type.h77
18 files changed, 5038 insertions, 0 deletions
diff --git a/libmaple/usb/README b/libmaple/usb/README
new file mode 100644
index 0000000..d0fca8d
--- /dev/null
+++ b/libmaple/usb/README
@@ -0,0 +1,63 @@
+The USB submodule of libmaple is a separate piece of the codebase for
+reasons that are largely historical.
+
+Current Status:
+
+ There's only support for the USB device peripheral found on
+ STM32F103s.
+
+ We rely on the low level core library provided by ST to implement
+ the USB transfer protocol for control endpoint transfers.
+
+ The virtual com port (which is exposed via
+ <libmaple/usb_cdcacm.h>) serves two important purposes.
+
+ 1) It allows serial data transfers between user sketches an a
+ host computer.
+
+ 2) It allows the host PC to issue a system reset into the DFU
+ bootloader with the DTR + RTS + "1EAF" sequence (see
+ leaflabs.com/docs/bootloader.html for more information on
+ this).
+
+ After reset, Maple will run the DFU bootloader for a few seconds,
+ during which the user can begin a DFU upload operation (uploads
+ application binary into RAM/FLASH). Thus, without this virtual com
+ port, it would be necessary to find an alternative means to reset
+ the chip in order to enable the bootloader.
+
+ If you would like to develop your own USB application for whatever
+ reason (e.g. to use faster isochronous enpoints for streaming
+ audio, or implement the USB HID or Mass Storage specs), then
+ ensure that you leave some hook for resetting Maple remotely in
+ order to spin up the DFU bootloader. Please make sure to get
+ yourself a unique vendor/product ID pair for your application, as
+ some operating systems will assign a host-side driver based on
+ these tags.
+
+ It would be possible to build a compound USB device, that
+ implements endpoints for both the virtual COM port as well as some
+ other components (mass storage etc.). However, this turns out to
+ be a burden from the host driver side, as Windows and *nix handle
+ compound USB devices quite differently.
+
+ Be mindful that enabling the USB peripheral isn't "free." The
+ device must respond to periodic bus activity (every few
+ milliseconds) by servicing an ISR. Therefore, the USB application
+ should be disabled inside of timing critical applications.
+
+ In order to disconnect the device from the host, a USB_DISC pin is
+ asserted (e.g. on Maple, this is PC12). Alternatively, the NVIC
+ can be directly configured to disable the USB LP/HP IRQ's.
+
+ The files inside of usb_lib were provided by ST and are subject to
+ their own license, all other files were written by the LeafLabs
+ team and fall under the MIT license.
+
+TODO:
+
+ - Generic USB driver core with series-provided backends, like
+ libopencm3 has.
+ - Strip out ST code.
+ - Integration with a high level USB library (like LUFA/MyUSB) to
+ allow users to write custom USB applications.
diff --git a/libmaple/usb/rules.mk b/libmaple/usb/rules.mk
new file mode 100644
index 0000000..e8ccc15
--- /dev/null
+++ b/libmaple/usb/rules.mk
@@ -0,0 +1,45 @@
+# Standard things
+sp := $(sp).x
+dirstack_$(sp) := $(d)
+d := $(dir)
+BUILDDIRS += $(BUILD_PATH)/$(d)
+
+# Local flags
+CFLAGS_$(d) = -I$(d) -I$(d)/$(MCU_SERIES) -I$(d)/usb_lib $(LIBMAPLE_INCLUDES) $(LIBMAPLE_PRIVATE_INCLUDES) -Wall
+
+# Add usblib and series subdirectory to BUILDDIRS.
+BUILDDIRS += $(BUILD_PATH)/$(d)/$(MCU_SERIES)
+BUILDDIRS += $(BUILD_PATH)/$(d)/usb_lib
+
+# Local rules and targets
+sSRCS_$(d) :=
+cSRCS_$(d) :=
+# We currently only have F1 performance line support. Sigh.
+ifeq ($(MCU_SERIES), stm32f1)
+ifeq ($(MCU_F1_LINE), performance)
+cSRCS_$(d) += $(MCU_SERIES)/usb.c
+cSRCS_$(d) += $(MCU_SERIES)/usb_reg_map.c
+cSRCS_$(d) += $(MCU_SERIES)/usb_cdcacm.c
+cSRCS_$(d) += usb_lib/usb_core.c
+cSRCS_$(d) += usb_lib/usb_init.c
+cSRCS_$(d) += usb_lib/usb_mem.c
+cSRCS_$(d) += usb_lib/usb_regs.c
+endif
+endif
+
+sFILES_$(d) := $(sSRCS_$(d):%=$(d)/%)
+cFILES_$(d) := $(cSRCS_$(d):%=$(d)/%)
+
+OBJS_$(d) := $(sFILES_$(d):%.S=$(BUILD_PATH)/%.o) \
+ $(cFILES_$(d):%.c=$(BUILD_PATH)/%.o)
+DEPS_$(d) := $(OBJS_$(d):%.o=%.d)
+
+$(OBJS_$(d)): TGT_CFLAGS := $(CFLAGS_$(d))
+$(OBJS_$(d)): TGT_ASFLAGS :=
+
+TGT_BIN += $(OBJS_$(d))
+
+# Standard things
+-include $(DEPS_$(d))
+d := $(dirstack_$(sp))
+sp := $(basename $(sp))
diff --git a/libmaple/usb/stm32f1/usb.c b/libmaple/usb/stm32f1/usb.c
new file mode 100644
index 0000000..f694f04
--- /dev/null
+++ b/libmaple/usb/stm32f1/usb.c
@@ -0,0 +1,387 @@
+/******************************************************************************
+ * The MIT License
+ *
+ * Copyright (c) 2010 LeafLabs LLC.
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *****************************************************************************/
+
+/**
+ * @file libmaple/usb/stm32f1/usb.c
+ * @brief USB support.
+ *
+ * This is a mess.
+ */
+
+#include <libmaple/usb.h>
+
+#include <libmaple/libmaple.h>
+#include <libmaple/rcc.h>
+
+/* Private headers */
+#include "usb_reg_map.h"
+#include "usb_lib_globals.h"
+
+/* usb_lib headers */
+#include "usb_type.h"
+#include "usb_core.h"
+
+static void dispatch_ctr_lp(void);
+
+/*
+ * usb_lib/ globals
+ */
+
+uint16 SaveTState; /* caches TX status for later use */
+uint16 SaveRState; /* caches RX status for later use */
+
+/*
+ * Other state
+ */
+
+typedef enum {
+ RESUME_EXTERNAL,
+ RESUME_INTERNAL,
+ RESUME_LATER,
+ RESUME_WAIT,
+ RESUME_START,
+ RESUME_ON,
+ RESUME_OFF,
+ RESUME_ESOF
+} RESUME_STATE;
+
+struct {
+ volatile RESUME_STATE eState;
+ volatile uint8 bESOFcnt;
+} ResumeS;
+
+static usblib_dev usblib = {
+ .irq_mask = USB_ISR_MSK,
+ .state = USB_UNCONNECTED,
+ .prevState = USB_UNCONNECTED,
+ .clk_id = RCC_USB,
+};
+usblib_dev *USBLIB = &usblib;
+
+/*
+ * Routines
+ */
+
+void usb_init_usblib(usblib_dev *dev,
+ void (**ep_int_in)(void),
+ void (**ep_int_out)(void)) {
+ rcc_clk_enable(dev->clk_id);
+
+ dev->ep_int_in = ep_int_in;
+ dev->ep_int_out = ep_int_out;
+
+ /* usb_lib/ declares both and then assumes that pFoo points to Foo
+ * (even though the names don't always match), which is stupid for
+ * all of the obvious reasons, but whatever. Here we are. */
+ pInformation = &Device_Info;
+ pProperty = &Device_Property;
+ pUser_Standard_Requests = &User_Standard_Requests;
+
+ pInformation->ControlState = 2; /* FIXME [0.0.12] use
+ CONTROL_STATE enumerator */
+ pProperty->Init();
+}
+
+static void usb_suspend(void) {
+ uint16 cntr;
+
+ /* TODO decide if read/modify/write is really what we want
+ * (e.g. usb_resume_init() reconfigures CNTR). */
+ cntr = USB_BASE->CNTR;
+ cntr |= USB_CNTR_FSUSP;
+ USB_BASE->CNTR = cntr;
+ cntr |= USB_CNTR_LP_MODE;
+ USB_BASE->CNTR = cntr;
+
+ USBLIB->prevState = USBLIB->state;
+ USBLIB->state = USB_SUSPENDED;
+}
+
+static void usb_resume_init(void) {
+ uint16 cntr;
+
+ cntr = USB_BASE->CNTR;
+ cntr &= ~USB_CNTR_LP_MODE;
+ USB_BASE->CNTR = cntr;
+
+ /* Enable interrupt lines */
+ USB_BASE->CNTR = USB_ISR_MSK;
+}
+
+static void usb_resume(RESUME_STATE eResumeSetVal) {
+ uint16 cntr;
+
+ if (eResumeSetVal != RESUME_ESOF) {
+ ResumeS.eState = eResumeSetVal;
+ }
+
+ switch (ResumeS.eState) {
+ case RESUME_EXTERNAL:
+ usb_resume_init();
+ ResumeS.eState = RESUME_OFF;
+ USBLIB->state = USBLIB->prevState;
+ break;
+ case RESUME_INTERNAL:
+ usb_resume_init();
+ ResumeS.eState = RESUME_START;
+ break;
+ case RESUME_LATER:
+ ResumeS.bESOFcnt = 2;
+ ResumeS.eState = RESUME_WAIT;
+ break;
+ case RESUME_WAIT:
+ ResumeS.bESOFcnt--;
+ if (ResumeS.bESOFcnt == 0) {
+ ResumeS.eState = RESUME_START;
+ }
+ break;
+ case RESUME_START:
+ cntr = USB_BASE->CNTR;
+ cntr |= USB_CNTR_RESUME;
+ USB_BASE->CNTR = cntr;
+ ResumeS.eState = RESUME_ON;
+ ResumeS.bESOFcnt = 10;
+ break;
+ case RESUME_ON:
+ ResumeS.bESOFcnt--;
+ if (ResumeS.bESOFcnt == 0) {
+ cntr = USB_BASE->CNTR;
+ cntr &= ~USB_CNTR_RESUME;
+ USB_BASE->CNTR = cntr;
+ USBLIB->state = USBLIB->prevState;
+ ResumeS.eState = RESUME_OFF;
+ }
+ break;
+ case RESUME_OFF:
+ case RESUME_ESOF:
+ default:
+ ResumeS.eState = RESUME_OFF;
+ break;
+ }
+}
+
+#define SUSPEND_ENABLED 1
+void __irq_usb_lp_can_rx0(void) {
+ uint16 istr = USB_BASE->ISTR;
+
+ /* Use USB_ISR_MSK to only include code for bits we care about. */
+
+#if (USB_ISR_MSK & USB_ISTR_RESET)
+ if (istr & USB_ISTR_RESET & USBLIB->irq_mask) {
+ USB_BASE->ISTR = ~USB_ISTR_RESET;
+ pProperty->Reset();
+ }
+#endif
+
+#if (USB_ISR_MSK & USB_ISTR_PMAOVR)
+ if (istr & ISTR_PMAOVR & USBLIB->irq_mask) {
+ USB_BASE->ISTR = ~USB_ISTR_PMAOVR;
+ }
+#endif
+
+#if (USB_ISR_MSK & USB_ISTR_ERR)
+ if (istr & USB_ISTR_ERR & USBLIB->irq_mask) {
+ USB_BASE->ISTR = ~USB_ISTR_ERR;
+ }
+#endif
+
+#if (USB_ISR_MSK & USB_ISTR_WKUP)
+ if (istr & USB_ISTR_WKUP & USBLIB->irq_mask) {
+ USB_BASE->ISTR = ~USB_ISTR_WKUP;
+ usb_resume(RESUME_EXTERNAL);
+ }
+#endif
+
+#if (USB_ISR_MSK & USB_ISTR_SUSP)
+ if (istr & USB_ISTR_SUSP & USBLIB->irq_mask) {
+ /* check if SUSPEND is possible */
+ if (SUSPEND_ENABLED) {
+ usb_suspend();
+ } else {
+ /* if not possible then resume after xx ms */
+ usb_resume(RESUME_LATER);
+ }
+ /* clear of the ISTR bit must be done after setting of CNTR_FSUSP */
+ USB_BASE->ISTR = ~USB_ISTR_SUSP;
+ }
+#endif
+
+#if (USB_ISR_MSK & USB_ISTR_SOF)
+ if (istr & USB_ISTR_SOF & USBLIB->irq_mask) {
+ USB_BASE->ISTR = ~USB_ISTR_SOF;
+ }
+#endif
+
+#if (USB_ISR_MSK & USB_ISTR_ESOF)
+ if (istr & USB_ISTR_ESOF & USBLIB->irq_mask) {
+ USB_BASE->ISTR = ~USB_ISTR_ESOF;
+ /* resume handling timing is made with ESOFs */
+ usb_resume(RESUME_ESOF); /* request without change of the machine state */
+ }
+#endif
+
+ /*
+ * Service the correct transfer interrupt.
+ */
+
+#if (USB_ISR_MSK & USB_ISTR_CTR)
+ if (istr & USB_ISTR_CTR & USBLIB->irq_mask) {
+ dispatch_ctr_lp();
+ }
+#endif
+}
+
+/*
+ * Auxiliary routines
+ */
+
+static inline uint8 dispatch_endpt_zero(uint16 istr_dir);
+static inline void dispatch_endpt(uint8 ep);
+static inline void set_rx_tx_status0(uint16 rx, uint16 tx);
+
+static void handle_setup0(void);
+static void handle_in0(void);
+static void handle_out0(void);
+
+static void dispatch_ctr_lp() {
+ uint16 istr;
+ while (((istr = USB_BASE->ISTR) & USB_ISTR_CTR) != 0) {
+ /* TODO WTF, figure this out: RM0008 says CTR is read-only,
+ * but ST's firmware claims it's clear-only, and emphasizes
+ * the importance of clearing it in more than one place. */
+ USB_BASE->ISTR = ~USB_ISTR_CTR;
+ uint8 ep_id = istr & USB_ISTR_EP_ID;
+ if (ep_id == 0) {
+ /* TODO figure out why it's OK to break out of the loop
+ * once we're done serving endpoint zero, but not okay if
+ * there are multiple nonzero endpoint transfers to
+ * handle. */
+ if (dispatch_endpt_zero(istr & USB_ISTR_DIR)) {
+ return;
+ }
+ } else {
+ dispatch_endpt(ep_id);
+ }
+ }
+}
+
+/* FIXME Dataflow on endpoint 0 RX/TX status is based off of ST's
+ * code, and is ugly/confusing in its use of SaveRState/SaveTState.
+ * Fixing this requires filling in handle_in0(), handle_setup0(),
+ * handle_out0(). */
+static inline uint8 dispatch_endpt_zero(uint16 istr_dir) {
+ uint32 epr = (uint16)USB_BASE->EP[0];
+
+ if (!(epr & (USB_EP_CTR_TX | USB_EP_SETUP | USB_EP_CTR_RX))) {
+ return 0;
+ }
+
+ /* Cache RX/TX statuses in SaveRState/SaveTState, respectively.
+ * The various handle_foo0() may clobber these values
+ * before we reset them at the end of this routine. */
+ SaveRState = epr & USB_EP_STAT_RX;
+ SaveTState = epr & USB_EP_STAT_TX;
+
+ /* Set actual RX/TX statuses to NAK while we're thinking */
+ set_rx_tx_status0(USB_EP_STAT_RX_NAK, USB_EP_STAT_TX_NAK);
+
+ if (istr_dir == 0) {
+ /* ST RM0008: "If DIR bit=0, CTR_TX bit is set in the USB_EPnR
+ * register related to the interrupting endpoint. The
+ * interrupting transaction is of IN type (data transmitted by
+ * the USB peripheral to the host PC)." */
+ ASSERT_FAULT(epr & USB_EP_CTR_TX);
+ usb_clear_ctr_tx(USB_EP0);
+ handle_in0();
+ } else {
+ /* RM0008: "If DIR bit=1, CTR_RX bit or both CTR_TX/CTR_RX
+ * are set in the USB_EPnR register related to the
+ * interrupting endpoint. The interrupting transaction is of
+ * OUT type (data received by the USB peripheral from the host
+ * PC) or two pending transactions are waiting to be
+ * processed."
+ *
+ * [mbolivar] Note how the following control flow (which
+ * replicates ST's) doesn't seem to actually handle both
+ * interrupts that are ostensibly pending when both CTR_RX and
+ * CTR_TX are set.
+ *
+ * TODO sort this mess out.
+ */
+ if (epr & USB_EP_CTR_TX) {
+ usb_clear_ctr_tx(USB_EP0);
+ handle_in0();
+ } else { /* SETUP or CTR_RX */
+ /* SETUP is held constant while CTR_RX is set, so clear it
+ * either way */
+ usb_clear_ctr_rx(USB_EP0);
+ if (epr & USB_EP_SETUP) {
+ handle_setup0();
+ } else { /* CTR_RX */
+ handle_out0();
+ }
+ }
+ }
+
+ set_rx_tx_status0(SaveRState, SaveTState);
+ return 1;
+}
+
+static inline void dispatch_endpt(uint8 ep) {
+ uint32 epr = USB_BASE->EP[ep];
+ /* If ISTR_CTR is set and the ISTR gave us this EP_ID to handle,
+ * then presumably at least one of CTR_RX and CTR_TX is set, but
+ * again, ST's control flow allows for the possibility of neither.
+ *
+ * TODO try to find out if neither being set is possible. */
+ if (epr & USB_EP_CTR_RX) {
+ usb_clear_ctr_rx(ep);
+ (USBLIB->ep_int_out[ep - 1])();
+ }
+ if (epr & USB_EP_CTR_TX) {
+ usb_clear_ctr_tx(ep);
+ (USBLIB->ep_int_in[ep - 1])();
+ }
+}
+
+static inline void set_rx_tx_status0(uint16 rx, uint16 tx) {
+ usb_set_ep_rx_stat(USB_EP0, rx);
+ usb_set_ep_tx_stat(USB_EP0, tx);
+}
+
+/* TODO Rip out usb_lib/ dependency from the following functions: */
+
+static void handle_setup0(void) {
+ Setup0_Process();
+}
+
+static void handle_in0(void) {
+ In0_Process();
+}
+
+static void handle_out0(void) {
+ Out0_Process();
+}
diff --git a/libmaple/usb/stm32f1/usb_cdcacm.c b/libmaple/usb/stm32f1/usb_cdcacm.c
new file mode 100644
index 0000000..d4d4262
--- /dev/null
+++ b/libmaple/usb/stm32f1/usb_cdcacm.c
@@ -0,0 +1,709 @@
+/******************************************************************************
+ * The MIT License
+ *
+ * Copyright (c) 2011 LeafLabs LLC.
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *****************************************************************************/
+
+/**
+ * @file libmaple/usb/stm32f1/usb_cdcacm.c
+ * @brief USB CDC ACM (a.k.a. virtual serial terminal, VCOM).
+ *
+ * FIXME: this works on the STM32F1 USB peripherals, and probably no
+ * place else. Nonportable bits really need to be factored out, and
+ * the result made cleaner.
+ */
+
+#include <libmaple/usb_cdcacm.h>
+
+#include <libmaple/usb.h>
+#include <libmaple/nvic.h>
+#include <libmaple/delay.h>
+
+/* Private headers */
+#include "usb_lib_globals.h"
+#include "usb_reg_map.h"
+
+/* usb_lib headers */
+#include "usb_type.h"
+#include "usb_core.h"
+#include "usb_def.h"
+
+/******************************************************************************
+ ******************************************************************************
+ ***
+ *** HACK ALERT! FIXME FIXME FIXME FIXME!
+ ***
+ *** A bunch of LeafLabs-specific configuration lives in here for
+ *** now. This mess REALLY needs to get teased apart, with
+ *** appropriate pieces moved into Wirish.
+ ***
+ ******************************************************************************
+ *****************************************************************************/
+
+#if !(defined(BOARD_maple) || defined(BOARD_maple_RET6) || \
+ defined(BOARD_maple_mini) || defined(BOARD_maple_native))
+#warning USB CDC ACM relies on LeafLabs board-specific configuration.\
+ You may have problems on non-LeafLabs boards.
+#endif
+
+static void vcomDataTxCb(void);
+static void vcomDataRxCb(void);
+static uint8* vcomGetSetLineCoding(uint16);
+
+static void usbInit(void);
+static void usbReset(void);
+static RESULT usbDataSetup(uint8 request);
+static RESULT usbNoDataSetup(uint8 request);
+static RESULT usbGetInterfaceSetting(uint8 interface, uint8 alt_setting);
+static uint8* usbGetDeviceDescriptor(uint16 length);
+static uint8* usbGetConfigDescriptor(uint16 length);
+static uint8* usbGetStringDescriptor(uint16 length);
+static void usbSetConfiguration(void);
+static void usbSetDeviceAddress(void);
+
+/*
+ * Descriptors
+ */
+
+/* FIXME move to Wirish */
+#define LEAFLABS_ID_VENDOR 0x1EAF
+#define MAPLE_ID_PRODUCT 0x0004
+static const usb_descriptor_device usbVcomDescriptor_Device =
+ USB_CDCACM_DECLARE_DEV_DESC(LEAFLABS_ID_VENDOR, MAPLE_ID_PRODUCT);
+
+typedef struct {
+ usb_descriptor_config_header Config_Header;
+ usb_descriptor_interface CCI_Interface;
+ CDC_FUNCTIONAL_DESCRIPTOR(2) CDC_Functional_IntHeader;
+ CDC_FUNCTIONAL_DESCRIPTOR(2) CDC_Functional_CallManagement;
+ CDC_FUNCTIONAL_DESCRIPTOR(1) CDC_Functional_ACM;
+ CDC_FUNCTIONAL_DESCRIPTOR(2) CDC_Functional_Union;
+ usb_descriptor_endpoint ManagementEndpoint;
+ usb_descriptor_interface DCI_Interface;
+ usb_descriptor_endpoint DataOutEndpoint;
+ usb_descriptor_endpoint DataInEndpoint;
+} __packed usb_descriptor_config;
+
+#define MAX_POWER (100 >> 1)
+static const usb_descriptor_config usbVcomDescriptor_Config = {
+ .Config_Header = {
+ .bLength = sizeof(usb_descriptor_config_header),
+ .bDescriptorType = USB_DESCRIPTOR_TYPE_CONFIGURATION,
+ .wTotalLength = sizeof(usb_descriptor_config),
+ .bNumInterfaces = 0x02,
+ .bConfigurationValue = 0x01,
+ .iConfiguration = 0x00,
+ .bmAttributes = (USB_CONFIG_ATTR_BUSPOWERED |
+ USB_CONFIG_ATTR_SELF_POWERED),
+ .bMaxPower = MAX_POWER,
+ },
+
+ .CCI_Interface = {
+ .bLength = sizeof(usb_descriptor_interface),
+ .bDescriptorType = USB_DESCRIPTOR_TYPE_INTERFACE,
+ .bInterfaceNumber = 0x00,
+ .bAlternateSetting = 0x00,
+ .bNumEndpoints = 0x01,
+ .bInterfaceClass = USB_INTERFACE_CLASS_CDC,
+ .bInterfaceSubClass = USB_INTERFACE_SUBCLASS_CDC_ACM,
+ .bInterfaceProtocol = 0x01, /* Common AT Commands */
+ .iInterface = 0x00,
+ },
+
+ .CDC_Functional_IntHeader = {
+ .bLength = CDC_FUNCTIONAL_DESCRIPTOR_SIZE(2),
+ .bDescriptorType = 0x24,
+ .SubType = 0x00,
+ .Data = {0x01, 0x10},
+ },
+
+ .CDC_Functional_CallManagement = {
+ .bLength = CDC_FUNCTIONAL_DESCRIPTOR_SIZE(2),
+ .bDescriptorType = 0x24,
+ .SubType = 0x01,
+ .Data = {0x03, 0x01},
+ },
+
+ .CDC_Functional_ACM = {
+ .bLength = CDC_FUNCTIONAL_DESCRIPTOR_SIZE(1),
+ .bDescriptorType = 0x24,
+ .SubType = 0x02,
+ .Data = {0x06},
+ },
+
+ .CDC_Functional_Union = {
+ .bLength = CDC_FUNCTIONAL_DESCRIPTOR_SIZE(2),
+ .bDescriptorType = 0x24,
+ .SubType = 0x06,
+ .Data = {0x00, 0x01},
+ },
+
+ .ManagementEndpoint = {
+ .bLength = sizeof(usb_descriptor_endpoint),
+ .bDescriptorType = USB_DESCRIPTOR_TYPE_ENDPOINT,
+ .bEndpointAddress = (USB_DESCRIPTOR_ENDPOINT_IN |
+ USB_CDCACM_MANAGEMENT_ENDP),
+ .bmAttributes = USB_EP_TYPE_INTERRUPT,
+ .wMaxPacketSize = USB_CDCACM_MANAGEMENT_EPSIZE,
+ .bInterval = 0xFF,
+ },
+
+ .DCI_Interface = {
+ .bLength = sizeof(usb_descriptor_interface),
+ .bDescriptorType = USB_DESCRIPTOR_TYPE_INTERFACE,
+ .bInterfaceNumber = 0x01,
+ .bAlternateSetting = 0x00,
+ .bNumEndpoints = 0x02,
+ .bInterfaceClass = USB_INTERFACE_CLASS_DIC,
+ .bInterfaceSubClass = 0x00, /* None */
+ .bInterfaceProtocol = 0x00, /* None */
+ .iInterface = 0x00,
+ },
+
+ .DataOutEndpoint = {
+ .bLength = sizeof(usb_descriptor_endpoint),
+ .bDescriptorType = USB_DESCRIPTOR_TYPE_ENDPOINT,
+ .bEndpointAddress = (USB_DESCRIPTOR_ENDPOINT_OUT |
+ USB_CDCACM_RX_ENDP),
+ .bmAttributes = USB_EP_TYPE_BULK,
+ .wMaxPacketSize = USB_CDCACM_RX_EPSIZE,
+ .bInterval = 0x00,
+ },
+
+ .DataInEndpoint = {
+ .bLength = sizeof(usb_descriptor_endpoint),
+ .bDescriptorType = USB_DESCRIPTOR_TYPE_ENDPOINT,
+ .bEndpointAddress = (USB_DESCRIPTOR_ENDPOINT_IN | USB_CDCACM_TX_ENDP),
+ .bmAttributes = USB_EP_TYPE_BULK,
+ .wMaxPacketSize = USB_CDCACM_TX_EPSIZE,
+ .bInterval = 0x00,
+ },
+};
+
+/*
+ String Descriptors:
+
+ we may choose to specify any or none of the following string
+ identifiers:
+
+ iManufacturer: LeafLabs
+ iProduct: Maple
+ iSerialNumber: NONE
+ iConfiguration: NONE
+ iInterface(CCI): NONE
+ iInterface(DCI): NONE
+
+*/
+
+/* Unicode language identifier: 0x0409 is US English */
+/* FIXME move to Wirish */
+static const usb_descriptor_string usbVcomDescriptor_LangID = {
+ .bLength = USB_DESCRIPTOR_STRING_LEN(1),
+ .bDescriptorType = USB_DESCRIPTOR_TYPE_STRING,
+ .bString = {0x09, 0x04},
+};
+
+/* FIXME move to Wirish */
+static const usb_descriptor_string usbVcomDescriptor_iManufacturer = {
+ .bLength = USB_DESCRIPTOR_STRING_LEN(8),
+ .bDescriptorType = USB_DESCRIPTOR_TYPE_STRING,
+ .bString = {'L', 0, 'e', 0, 'a', 0, 'f', 0,
+ 'L', 0, 'a', 0, 'b', 0, 's', 0},
+};
+
+/* FIXME move to Wirish */
+static const usb_descriptor_string usbVcomDescriptor_iProduct = {
+ .bLength = USB_DESCRIPTOR_STRING_LEN(5),
+ .bDescriptorType = USB_DESCRIPTOR_TYPE_STRING,
+ .bString = {'M', 0, 'a', 0, 'p', 0, 'l', 0, 'e', 0},
+};
+
+static ONE_DESCRIPTOR Device_Descriptor = {
+ (uint8*)&usbVcomDescriptor_Device,
+ sizeof(usb_descriptor_device)
+};
+
+static ONE_DESCRIPTOR Config_Descriptor = {
+ (uint8*)&usbVcomDescriptor_Config,
+ sizeof(usb_descriptor_config)
+};
+
+#define N_STRING_DESCRIPTORS 3
+static ONE_DESCRIPTOR String_Descriptor[N_STRING_DESCRIPTORS] = {
+ {(uint8*)&usbVcomDescriptor_LangID, USB_DESCRIPTOR_STRING_LEN(1)},
+ {(uint8*)&usbVcomDescriptor_iManufacturer,USB_DESCRIPTOR_STRING_LEN(8)},
+ {(uint8*)&usbVcomDescriptor_iProduct, USB_DESCRIPTOR_STRING_LEN(5)}
+};
+
+/*
+ * Etc.
+ */
+
+/* I/O state */
+
+/* Received data */
+static volatile uint8 vcomBufferRx[USB_CDCACM_RX_EPSIZE];
+/* Read index into vcomBufferRx */
+static volatile uint32 rx_offset = 0;
+/* Number of bytes left to transmit */
+static volatile uint32 n_unsent_bytes = 0;
+/* Are we currently sending an IN packet? */
+static volatile uint8 transmitting = 0;
+/* Number of unread bytes */
+static volatile uint32 n_unread_bytes = 0;
+
+/* Other state (line coding, DTR/RTS) */
+
+static volatile usb_cdcacm_line_coding line_coding = {
+ /* This default is 115200 baud, 8N1. */
+ .dwDTERate = 115200,
+ .bCharFormat = USB_CDCACM_STOP_BITS_1,
+ .bParityType = USB_CDCACM_PARITY_NONE,
+ .bDataBits = 8,
+};
+
+/* DTR in bit 0, RTS in bit 1. */
+static volatile uint8 line_dtr_rts = 0;
+
+/*
+ * Endpoint callbacks
+ */
+
+static void (*ep_int_in[7])(void) =
+ {vcomDataTxCb,
+ NOP_Process,
+ NOP_Process,
+ NOP_Process,
+ NOP_Process,
+ NOP_Process,
+ NOP_Process};
+
+static void (*ep_int_out[7])(void) =
+ {NOP_Process,
+ NOP_Process,
+ vcomDataRxCb,
+ NOP_Process,
+ NOP_Process,
+ NOP_Process,
+ NOP_Process};
+
+/*
+ * Globals required by usb_lib/
+ *
+ * Mark these weak so they can be overriden to implement other USB
+ * functionality.
+ */
+
+#define NUM_ENDPTS 0x04
+__weak DEVICE Device_Table = {
+ .Total_Endpoint = NUM_ENDPTS,
+ .Total_Configuration = 1
+};
+
+#define MAX_PACKET_SIZE 0x40 /* 64B, maximum for USB FS Devices */
+__weak DEVICE_PROP Device_Property = {
+ .Init = usbInit,
+ .Reset = usbReset,
+ .Process_Status_IN = NOP_Process,
+ .Process_Status_OUT = NOP_Process,
+ .Class_Data_Setup = usbDataSetup,
+ .Class_NoData_Setup = usbNoDataSetup,
+ .Class_Get_Interface_Setting = usbGetInterfaceSetting,
+ .GetDeviceDescriptor = usbGetDeviceDescriptor,
+ .GetConfigDescriptor = usbGetConfigDescriptor,
+ .GetStringDescriptor = usbGetStringDescriptor,
+ .RxEP_buffer = NULL,
+ .MaxPacketSize = MAX_PACKET_SIZE
+};
+
+__weak USER_STANDARD_REQUESTS User_Standard_Requests = {
+ .User_GetConfiguration = NOP_Process,
+ .User_SetConfiguration = usbSetConfiguration,
+ .User_GetInterface = NOP_Process,
+ .User_SetInterface = NOP_Process,
+ .User_GetStatus = NOP_Process,
+ .User_ClearFeature = NOP_Process,
+ .User_SetEndPointFeature = NOP_Process,
+ .User_SetDeviceFeature = NOP_Process,
+ .User_SetDeviceAddress = usbSetDeviceAddress
+};
+
+/*
+ * User hooks
+ */
+
+static void (*rx_hook)(unsigned, void*) = 0;
+static void (*iface_setup_hook)(unsigned, void*) = 0;
+
+void usb_cdcacm_set_hooks(unsigned hook_flags, void (*hook)(unsigned, void*)) {
+ if (hook_flags & USB_CDCACM_HOOK_RX) {
+ rx_hook = hook;
+ }
+ if (hook_flags & USB_CDCACM_HOOK_IFACE_SETUP) {
+ iface_setup_hook = hook;
+ }
+}
+
+/*
+ * CDC ACM interface
+ */
+
+void usb_cdcacm_enable(gpio_dev *disc_dev, uint8 disc_bit) {
+ /* Present ourselves to the host. Writing 0 to "disc" pin must
+ * pull USB_DP pin up while leaving USB_DM pulled down by the
+ * transceiver. See USB 2.0 spec, section 7.1.7.3. */
+ gpio_set_mode(disc_dev, disc_bit, GPIO_OUTPUT_PP);
+ gpio_write_bit(disc_dev, disc_bit, 0);
+
+ /* Initialize the USB peripheral. */
+ usb_init_usblib(USBLIB, ep_int_in, ep_int_out);
+}
+
+void usb_cdcacm_disable(gpio_dev *disc_dev, uint8 disc_bit) {
+ /* Turn off the interrupt and signal disconnect (see e.g. USB 2.0
+ * spec, section 7.1.7.3). */
+ nvic_irq_disable(NVIC_USB_LP_CAN_RX0);
+ gpio_write_bit(disc_dev, disc_bit, 1);
+}
+
+void usb_cdcacm_putc(char ch) {
+ while (!usb_cdcacm_tx((uint8*)&ch, 1))
+ ;
+}
+
+/* This function is non-blocking.
+ *
+ * It copies data from a usercode buffer into the USB peripheral TX
+ * buffer, and returns the number of bytes copied. */
+uint32 usb_cdcacm_tx(const uint8* buf, uint32 len) {
+ /* Last transmission hasn't finished, so abort. */
+ if (usb_cdcacm_is_transmitting()) {
+ return 0;
+ }
+
+ /* We can only put USB_CDCACM_TX_EPSIZE bytes in the buffer. */
+ if (len > USB_CDCACM_TX_EPSIZE) {
+ len = USB_CDCACM_TX_EPSIZE;
+ }
+
+ /* Queue bytes for sending. */
+ if (len) {
+ usb_copy_to_pma(buf, len, USB_CDCACM_TX_ADDR);
+ }
+ // We still need to wait for the interrupt, even if we're sending
+ // zero bytes. (Sending zero-size packets is useful for flushing
+ // host-side buffers.)
+ usb_set_ep_tx_count(USB_CDCACM_TX_ENDP, len);
+ n_unsent_bytes = len;
+ transmitting = 1;
+ usb_set_ep_tx_stat(USB_CDCACM_TX_ENDP, USB_EP_STAT_TX_VALID);
+
+ return len;
+}
+
+uint32 usb_cdcacm_data_available(void) {
+ return n_unread_bytes;
+}
+
+uint8 usb_cdcacm_is_transmitting(void) {
+ return transmitting;
+}
+
+uint16 usb_cdcacm_get_pending(void) {
+ return n_unsent_bytes;
+}
+
+/* Nonblocking byte receive.
+ *
+ * Copies up to len bytes from our private data buffer (*NOT* the PMA)
+ * into buf and deq's the FIFO. */
+uint32 usb_cdcacm_rx(uint8* buf, uint32 len) {
+ /* Copy bytes to buffer. */
+ uint32 n_copied = usb_cdcacm_peek(buf, len);
+
+ /* Mark bytes as read. */
+ n_unread_bytes -= n_copied;
+ rx_offset += n_copied;
+
+ /* If all bytes have been read, re-enable the RX endpoint, which
+ * was set to NAK when the current batch of bytes was received. */
+ if (n_unread_bytes == 0) {
+ usb_set_ep_rx_count(USB_CDCACM_RX_ENDP, USB_CDCACM_RX_EPSIZE);
+ usb_set_ep_rx_stat(USB_CDCACM_RX_ENDP, USB_EP_STAT_RX_VALID);
+ rx_offset = 0;
+ }
+
+ return n_copied;
+}
+
+/* Nonblocking byte lookahead.
+ *
+ * Looks at unread bytes without marking them as read. */
+uint32 usb_cdcacm_peek(uint8* buf, uint32 len) {
+ int i;
+
+ if (len > n_unread_bytes) {
+ len = n_unread_bytes;
+ }
+
+ for (i = 0; i < len; i++) {
+ buf[i] = vcomBufferRx[i + rx_offset];
+ }
+
+ return len;
+}
+
+uint8 usb_cdcacm_get_dtr() {
+ return ((line_dtr_rts & USB_CDCACM_CONTROL_LINE_DTR) != 0);
+}
+
+uint8 usb_cdcacm_get_rts() {
+ return ((line_dtr_rts & USB_CDCACM_CONTROL_LINE_RTS) != 0);
+}
+
+void usb_cdcacm_get_line_coding(usb_cdcacm_line_coding *ret) {
+ ret->dwDTERate = line_coding.dwDTERate;
+ ret->bCharFormat = line_coding.bCharFormat;
+ ret->bParityType = line_coding.bParityType;
+ ret->bDataBits = line_coding.bDataBits;
+}
+
+int usb_cdcacm_get_baud(void) {
+ return line_coding.dwDTERate;
+}
+
+int usb_cdcacm_get_stop_bits(void) {
+ return line_coding.bCharFormat;
+}
+
+int usb_cdcacm_get_parity(void) {
+ return line_coding.bParityType;
+}
+
+int usb_cdcacm_get_n_data_bits(void) {
+ return line_coding.bDataBits;
+}
+
+
+/*
+ * Callbacks
+ */
+
+static void vcomDataTxCb(void) {
+ n_unsent_bytes = 0;
+ transmitting = 0;
+}
+
+static void vcomDataRxCb(void) {
+ usb_set_ep_rx_stat(USB_CDCACM_RX_ENDP, USB_EP_STAT_RX_NAK);
+ n_unread_bytes = usb_get_ep_rx_count(USB_CDCACM_RX_ENDP);
+ /* This copy won't overwrite unread bytes, since we've set the RX
+ * endpoint to NAK, and will only set it to VALID when all bytes
+ * have been read. */
+ usb_copy_from_pma((uint8*)vcomBufferRx, n_unread_bytes,
+ USB_CDCACM_RX_ADDR);
+
+
+ if (n_unread_bytes == 0) {
+ usb_set_ep_rx_count(USB_CDCACM_RX_ENDP, USB_CDCACM_RX_EPSIZE);
+ usb_set_ep_rx_stat(USB_CDCACM_RX_ENDP, USB_EP_STAT_RX_VALID);
+ rx_offset = 0;
+ }
+
+ if (rx_hook) {
+ rx_hook(USB_CDCACM_HOOK_RX, 0);
+ }
+}
+
+static uint8* vcomGetSetLineCoding(uint16 length) {
+ if (length == 0) {
+ pInformation->Ctrl_Info.Usb_wLength = sizeof(struct usb_cdcacm_line_coding);
+ }
+ return (uint8*)&line_coding;
+}
+
+static void usbInit(void) {
+ pInformation->Current_Configuration = 0;
+
+ USB_BASE->CNTR = USB_CNTR_FRES;
+
+ USBLIB->irq_mask = 0;
+ USB_BASE->CNTR = USBLIB->irq_mask;
+ USB_BASE->ISTR = 0;
+ USBLIB->irq_mask = USB_CNTR_RESETM | USB_CNTR_SUSPM | USB_CNTR_WKUPM;
+ USB_BASE->CNTR = USBLIB->irq_mask;
+
+ USB_BASE->ISTR = 0;
+ USBLIB->irq_mask = USB_ISR_MSK;
+ USB_BASE->CNTR = USBLIB->irq_mask;
+
+ nvic_irq_enable(NVIC_USB_LP_CAN_RX0);
+ USBLIB->state = USB_UNCONNECTED;
+}
+
+#define BTABLE_ADDRESS 0x00
+static void usbReset(void) {
+ pInformation->Current_Configuration = 0;
+
+ /* current feature is current bmAttributes */
+ pInformation->Current_Feature = (USB_CONFIG_ATTR_BUSPOWERED |
+ USB_CONFIG_ATTR_SELF_POWERED);
+
+ USB_BASE->BTABLE = BTABLE_ADDRESS;
+
+ /* setup control endpoint 0 */
+ usb_set_ep_type(USB_EP0, USB_EP_EP_TYPE_CONTROL);
+ usb_set_ep_tx_stat(USB_EP0, USB_EP_STAT_TX_STALL);
+ usb_set_ep_rx_addr(USB_EP0, USB_CDCACM_CTRL_RX_ADDR);
+ usb_set_ep_tx_addr(USB_EP0, USB_CDCACM_CTRL_TX_ADDR);
+ usb_clear_status_out(USB_EP0);
+
+ usb_set_ep_rx_count(USB_EP0, pProperty->MaxPacketSize);
+ usb_set_ep_rx_stat(USB_EP0, USB_EP_STAT_RX_VALID);
+
+ /* setup management endpoint 1 */
+ usb_set_ep_type(USB_CDCACM_MANAGEMENT_ENDP, USB_EP_EP_TYPE_INTERRUPT);
+ usb_set_ep_tx_addr(USB_CDCACM_MANAGEMENT_ENDP,
+ USB_CDCACM_MANAGEMENT_ADDR);
+ usb_set_ep_tx_stat(USB_CDCACM_MANAGEMENT_ENDP, USB_EP_STAT_TX_NAK);
+ usb_set_ep_rx_stat(USB_CDCACM_MANAGEMENT_ENDP, USB_EP_STAT_RX_DISABLED);
+
+ /* TODO figure out differences in style between RX/TX EP setup */
+
+ /* set up data endpoint OUT (RX) */
+ usb_set_ep_type(USB_CDCACM_RX_ENDP, USB_EP_EP_TYPE_BULK);
+ usb_set_ep_rx_addr(USB_CDCACM_RX_ENDP, USB_CDCACM_RX_ADDR);
+ usb_set_ep_rx_count(USB_CDCACM_RX_ENDP, USB_CDCACM_RX_EPSIZE);
+ usb_set_ep_rx_stat(USB_CDCACM_RX_ENDP, USB_EP_STAT_RX_VALID);
+
+ /* set up data endpoint IN (TX) */
+ usb_set_ep_type(USB_CDCACM_TX_ENDP, USB_EP_EP_TYPE_BULK);
+ usb_set_ep_tx_addr(USB_CDCACM_TX_ENDP, USB_CDCACM_TX_ADDR);
+ usb_set_ep_tx_stat(USB_CDCACM_TX_ENDP, USB_EP_STAT_TX_NAK);
+ usb_set_ep_rx_stat(USB_CDCACM_TX_ENDP, USB_EP_STAT_RX_DISABLED);
+
+ USBLIB->state = USB_ATTACHED;
+ SetDeviceAddress(0);
+
+ /* Reset the RX/TX state */
+ n_unread_bytes = 0;
+ n_unsent_bytes = 0;
+ rx_offset = 0;
+ transmitting = 0;
+}
+
+static RESULT usbDataSetup(uint8 request) {
+ uint8* (*CopyRoutine)(uint16) = 0;
+
+ if (Type_Recipient == (CLASS_REQUEST | INTERFACE_RECIPIENT)) {
+ switch (request) {
+ case USB_CDCACM_GET_LINE_CODING:
+ CopyRoutine = vcomGetSetLineCoding;
+ break;
+ case USB_CDCACM_SET_LINE_CODING:
+ CopyRoutine = vcomGetSetLineCoding;
+ break;
+ default:
+ break;
+ }
+
+ /* Call the user hook. */
+ if (iface_setup_hook) {
+ uint8 req_copy = request;
+ iface_setup_hook(USB_CDCACM_HOOK_IFACE_SETUP, &req_copy);
+ }
+ }
+
+ if (CopyRoutine == NULL) {
+ return USB_UNSUPPORT;
+ }
+
+ pInformation->Ctrl_Info.CopyData = CopyRoutine;
+ pInformation->Ctrl_Info.Usb_wOffset = 0;
+ (*CopyRoutine)(0);
+ return USB_SUCCESS;
+}
+
+static RESULT usbNoDataSetup(uint8 request) {
+ RESULT ret = USB_UNSUPPORT;
+
+ if (Type_Recipient == (CLASS_REQUEST | INTERFACE_RECIPIENT)) {
+ switch (request) {
+ case USB_CDCACM_SET_COMM_FEATURE:
+ /* We support set comm. feature, but don't handle it. */
+ ret = USB_SUCCESS;
+ break;
+ case USB_CDCACM_SET_CONTROL_LINE_STATE:
+ /* Track changes to DTR and RTS. */
+ line_dtr_rts = (pInformation->USBwValues.bw.bb0 &
+ (USB_CDCACM_CONTROL_LINE_DTR |
+ USB_CDCACM_CONTROL_LINE_RTS));
+ ret = USB_SUCCESS;
+ break;
+ }
+
+ /* Call the user hook. */
+ if (iface_setup_hook) {
+ uint8 req_copy = request;
+ iface_setup_hook(USB_CDCACM_HOOK_IFACE_SETUP, &req_copy);
+ }
+ }
+ return ret;
+}
+
+static RESULT usbGetInterfaceSetting(uint8 interface, uint8 alt_setting) {
+ if (alt_setting > 0) {
+ return USB_UNSUPPORT;
+ } else if (interface > 1) {
+ return USB_UNSUPPORT;
+ }
+
+ return USB_SUCCESS;
+}
+
+static uint8* usbGetDeviceDescriptor(uint16 length) {
+ return Standard_GetDescriptorData(length, &Device_Descriptor);
+}
+
+static uint8* usbGetConfigDescriptor(uint16 length) {
+ return Standard_GetDescriptorData(length, &Config_Descriptor);
+}
+
+static uint8* usbGetStringDescriptor(uint16 length) {
+ uint8 wValue0 = pInformation->USBwValue0;
+
+ if (wValue0 > N_STRING_DESCRIPTORS) {
+ return NULL;
+ }
+ return Standard_GetDescriptorData(length, &String_Descriptor[wValue0]);
+}
+
+static void usbSetConfiguration(void) {
+ if (pInformation->Current_Configuration != 0) {
+ USBLIB->state = USB_CONFIGURED;
+ }
+}
+
+static void usbSetDeviceAddress(void) {
+ USBLIB->state = USB_ADDRESSED;
+}
diff --git a/libmaple/usb/stm32f1/usb_lib_globals.h b/libmaple/usb/stm32f1/usb_lib_globals.h
new file mode 100644
index 0000000..1cd2754
--- /dev/null
+++ b/libmaple/usb/stm32f1/usb_lib_globals.h
@@ -0,0 +1,55 @@
+/******************************************************************************
+ * The MIT License
+ *
+ * Copyright (c) 2011 LeafLabs LLC.
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *****************************************************************************/
+
+#ifndef _USB_LIB_GLOBALS_H_
+#define _USB_LIB_GLOBALS_H_
+
+/* usb_lib headers */
+#include "usb_type.h"
+#include "usb_core.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern USER_STANDARD_REQUESTS User_Standard_Requests;
+extern USER_STANDARD_REQUESTS *pUser_Standard_Requests;
+
+extern DEVICE_PROP Device_Property;
+extern DEVICE_PROP *pProperty;
+
+extern DEVICE_INFO Device_Info;
+extern DEVICE_INFO *pInformation;
+
+extern DEVICE Device_Table;
+extern u16 SaveRState;
+extern u16 SaveTState;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/libmaple/usb/stm32f1/usb_reg_map.c b/libmaple/usb/stm32f1/usb_reg_map.c
new file mode 100644
index 0000000..ea60cb3
--- /dev/null
+++ b/libmaple/usb/stm32f1/usb_reg_map.c
@@ -0,0 +1,88 @@
+/******************************************************************************
+ * The MIT License
+ *
+ * Copyright (c) 2011 LeafLabs, LLC.
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *****************************************************************************/
+
+#include "usb_reg_map.h"
+
+/* TODO these could use some improvement; they're fairly
+ * straightforward ports of the analogous ST code. The PMA blit
+ * routines in particular are obvious targets for performance
+ * measurement and tuning. */
+
+void usb_copy_to_pma(const uint8 *buf, uint16 len, uint16 pma_offset) {
+ uint16 *dst = (uint16*)usb_pma_ptr(pma_offset);
+ uint16 n = len >> 1;
+ uint16 i;
+ for (i = 0; i < n; i++) {
+ *dst = (uint16)(*buf) | *(buf + 1) << 8;
+ buf += 2;
+ dst += 2;
+ }
+ if (len & 1) {
+ *dst = *buf;
+ }
+}
+
+void usb_copy_from_pma(uint8 *buf, uint16 len, uint16 pma_offset) {
+ uint32 *src = (uint32*)usb_pma_ptr(pma_offset);
+ uint16 *dst = (uint16*)buf;
+ uint16 n = len >> 1;
+ uint16 i;
+ for (i = 0; i < n; i++) {
+ *dst++ = *src++;
+ }
+ if (len & 1) {
+ *dst = *src & 0xFF;
+ }
+}
+
+static void usb_set_ep_rx_count_common(uint32 *rxc, uint16 count) {
+ uint16 nblocks;
+ if (count > 62) {
+ /* use 32-byte memory block size */
+ nblocks = count >> 5;
+ if ((count & 0x1F) == 0) {
+ nblocks--;
+ }
+ *rxc = (nblocks << 10) | 0x8000;
+ } else {
+ /* use 2-byte memory block size */
+ nblocks = count >> 1;
+ if ((count & 0x1) != 0) {
+ nblocks++;
+ }
+ *rxc = nblocks << 10;
+ }
+}
+
+void usb_set_ep_rx_buf0_count(uint8 ep, uint16 count) {
+ uint32 *rxc = usb_ep_rx_buf0_count_ptr(ep);
+ usb_set_ep_rx_count_common(rxc, count);
+}
+
+void usb_set_ep_rx_count(uint8 ep, uint16 count) {
+ uint32 *rxc = usb_ep_rx_count_ptr(ep);
+ usb_set_ep_rx_count_common(rxc, count);
+}
diff --git a/libmaple/usb/stm32f1/usb_reg_map.h b/libmaple/usb/stm32f1/usb_reg_map.h
new file mode 100644
index 0000000..2e3f6bc
--- /dev/null
+++ b/libmaple/usb/stm32f1/usb_reg_map.h
@@ -0,0 +1,617 @@
+/******************************************************************************
+ * The MIT License
+ *
+ * Copyright (c) 2011 LeafLabs, LLC.
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *****************************************************************************/
+
+#include <libmaple/libmaple_types.h>
+#include <libmaple/util.h>
+
+#ifndef _USB_REG_MAP_H_
+#define _USB_REG_MAP_H_
+
+/* TODO:
+ * - Pick one of "endp", "ep" "endpt"
+ */
+
+/*
+ * Register map and base pointer
+ */
+
+#define USB_NR_EP_REGS 8
+
+/** USB register map type */
+typedef struct usb_reg_map {
+ __io uint32 EP[USB_NR_EP_REGS]; /**< Endpoint registers */
+ const uint32 RESERVED[8]; /**< Reserved */
+ __io uint32 CNTR; /**< Control register */
+ __io uint32 ISTR; /**< Interrupt status register */
+ __io uint32 FNR; /**< Frame number register */
+ __io uint32 DADDR; /**< Device address */
+ __io uint32 BTABLE; /**< @brief Buffer table address
+ *
+ * Address offset within the USB
+ * packet memory area which points
+ * to the base of the buffer
+ * descriptor table. Must be
+ * aligned to an 8 byte boundary.
+ */
+} usb_reg_map;
+
+/** USB register map base pointer */
+#define USB_BASE ((struct usb_reg_map*)0x40005C00)
+
+/*
+ * Register bit definitions
+ */
+
+/* Endpoint registers (USB_EPnR) */
+
+#define USB_EP_CTR_RX_BIT 15
+#define USB_EP_DTOG_RX_BIT 14
+#define USB_EP_SETUP_BIT 11
+#define USB_EP_EP_KIND_BIT 8
+#define USB_EP_CTR_TX_BIT 7
+#define USB_EP_DTOG_TX_BIT 6
+
+#define USB_EP_CTR_RX BIT(USB_EP_CTR_RX_BIT)
+#define USB_EP_DTOG_RX BIT(USB_EP_DTOG_RX_BIT)
+#define USB_EP_STAT_RX (0x3 << 12)
+#define USB_EP_STAT_RX_DISABLED (0x0 << 12)
+#define USB_EP_STAT_RX_STALL (0x1 << 12)
+#define USB_EP_STAT_RX_NAK (0x2 << 12)
+#define USB_EP_STAT_RX_VALID (0x3 << 12)
+#define USB_EP_SETUP BIT(USB_EP_SETUP_BIT)
+#define USB_EP_EP_TYPE (0x3 << 9)
+#define USB_EP_EP_TYPE_BULK (0x0 << 9)
+#define USB_EP_EP_TYPE_CONTROL (0x1 << 9)
+#define USB_EP_EP_TYPE_ISO (0x2 << 9)
+#define USB_EP_EP_TYPE_INTERRUPT (0x3 << 9)
+#define USB_EP_EP_KIND BIT(USB_EP_EP_KIND_BIT)
+#define USB_EP_EP_KIND_DBL_BUF (0x1 << USB_EP_EP_KIND_BIT)
+#define USB_EP_CTR_TX BIT(USB_EP_CTR_TX_BIT)
+#define USB_EP_DTOG_TX BIT(USB_EP_DTOG_TX_BIT)
+#define USB_EP_STAT_TX (0x3 << 4)
+#define USB_EP_STAT_TX_DISABLED (0x0 << 4)
+#define USB_EP_STAT_TX_STALL (0x1 << 4)
+#define USB_EP_STAT_TX_NAK (0x2 << 4)
+#define USB_EP_STAT_TX_VALID (0x3 << 4)
+#define USB_EP_EA 0xF
+
+/* Control register (USB_CNTR) */
+
+#define USB_CNTR_CTRM_BIT 15
+#define USB_CNTR_PMAOVERM_BIT 14
+#define USB_CNTR_ERRM_BIT 13
+#define USB_CNTR_WKUPM_BIT 12
+#define USB_CNTR_SUSPM_BIT 11
+#define USB_CNTR_RESETM_BIT 10
+#define USB_CNTR_SOFM_BIT 9
+#define USB_CNTR_ESOFM_BIT 8
+#define USB_CNTR_RESUME_BIT 4
+#define USB_CNTR_FSUSP_BIT 3
+#define USB_CNTR_LP_MODE_BIT 2
+#define USB_CNTR_PDWN_BIT 1
+#define USB_CNTR_FRES_BIT 0
+
+#define USB_CNTR_CTRM BIT(USB_CNTR_CTRM_BIT)
+#define USB_CNTR_PMAOVERM BIT(USB_CNTR_PMAOVERM_BIT)
+#define USB_CNTR_ERRM BIT(USB_CNTR_ERRM_BIT)
+#define USB_CNTR_WKUPM BIT(USB_CNTR_WKUPM_BIT)
+#define USB_CNTR_SUSPM BIT(USB_CNTR_SUSPM_BIT)
+#define USB_CNTR_RESETM BIT(USB_CNTR_RESETM_BIT)
+#define USB_CNTR_SOFM BIT(USB_CNTR_SOFM_BIT)
+#define USB_CNTR_ESOFM BIT(USB_CNTR_ESOFM_BIT)
+#define USB_CNTR_RESUME BIT(USB_CNTR_RESUME_BIT)
+#define USB_CNTR_FSUSP BIT(USB_CNTR_FSUSP_BIT)
+#define USB_CNTR_LP_MODE BIT(USB_CNTR_LP_MODE_BIT)
+#define USB_CNTR_PDWN BIT(USB_CNTR_PDWN_BIT)
+#define USB_CNTR_FRES BIT(USB_CNTR_FRES_BIT)
+
+/* Interrupt status register (USB_ISTR) */
+
+#define USB_ISTR_CTR_BIT 15
+#define USB_ISTR_PMAOVR_BIT 14
+#define USB_ISTR_ERR_BIT 13
+#define USB_ISTR_WKUP_BIT 12
+#define USB_ISTR_SUSP_BIT 11
+#define USB_ISTR_RESET_BIT 10
+#define USB_ISTR_SOF_BIT 9
+#define USB_ISTR_ESOF_BIT 8
+#define USB_ISTR_DIR_BIT 4
+
+#define USB_ISTR_CTR BIT(USB_ISTR_CTR_BIT)
+#define USB_ISTR_PMAOVR BIT(USB_ISTR_PMAOVR_BIT)
+#define USB_ISTR_ERR BIT(USB_ISTR_ERR_BIT)
+#define USB_ISTR_WKUP BIT(USB_ISTR_WKUP_BIT)
+#define USB_ISTR_SUSP BIT(USB_ISTR_SUSP_BIT)
+#define USB_ISTR_RESET BIT(USB_ISTR_RESET_BIT)
+#define USB_ISTR_SOF BIT(USB_ISTR_SOF_BIT)
+#define USB_ISTR_ESOF BIT(USB_ISTR_ESOF_BIT)
+#define USB_ISTR_DIR BIT(USB_ISTR_DIR_BIT)
+#define USB_ISTR_EP_ID 0xF
+
+/* Frame number register (USB_FNR) */
+
+#define USB_FNR_RXDP_BIT 15
+#define USB_FNR_RXDM_BIT 14
+#define USB_FNR_LCK_BIT 13
+
+#define USB_FNR_RXDP BIT(USB_FNR_RXDP_BIT)
+#define USB_FNR_RXDM BIT(USB_FNR_RXDM_BIT)
+#define USB_FNR_LCK BIT(USB_FNR_LCK_BIT)
+#define USB_FNR_LSOF (0x3 << 11)
+#define USB_FNR_FN 0x7FF
+
+/* Device address (USB_DADDR) */
+
+#define USB_DADDR_EF_BIT 7
+#define USB_DADDR_ADD6_BIT 6
+#define USB_DADDR_ADD5_BIT 5
+#define USB_DADDR_ADD4_BIT 4
+#define USB_DADDR_ADD3_BIT 3
+#define USB_DADDR_ADD2_BIT 2
+#define USB_DADDR_ADD1_BIT 1
+#define USB_DADDR_ADD0_BIT 0
+
+#define USB_DADDR_EF BIT(USB_DADDR_EF_BIT)
+#define USB_DADDR_ADD6 BIT(USB_DADDR_ADD6_BIT)
+#define USB_DADDR_ADD5 BIT(USB_DADDR_ADD5_BIT)
+#define USB_DADDR_ADD4 BIT(USB_DADDR_ADD4_BIT)
+#define USB_DADDR_ADD3 BIT(USB_DADDR_ADD3_BIT)
+#define USB_DADDR_ADD2 BIT(USB_DADDR_ADD2_BIT)
+#define USB_DADDR_ADD1 BIT(USB_DADDR_ADD1_BIT)
+#define USB_DADDR_ADD0 BIT(USB_DADDR_ADD0_BIT)
+
+/* Buffer table address (USB_BTABLE) */
+
+#define USB_BTABLE_BTABLE (0x1FFF << 3)
+
+/*
+ * Register convenience routines
+ */
+
+#define __EP_CTR_NOP (USB_EP_CTR_RX | USB_EP_CTR_TX)
+#define __EP_NONTOGGLE (USB_EP_CTR_RX | USB_EP_SETUP | \
+ USB_EP_EP_TYPE | USB_EP_EP_KIND | \
+ USB_EP_CTR_TX | USB_EP_EA)
+
+static inline void usb_clear_ctr_rx(uint8 ep) {
+ uint32 epr = USB_BASE->EP[ep];
+ USB_BASE->EP[ep] = epr & ~USB_EP_CTR_RX & __EP_NONTOGGLE;
+}
+
+static inline void usb_clear_ctr_tx(uint8 ep) {
+ uint32 epr = USB_BASE->EP[ep];
+ USB_BASE->EP[ep] = epr & ~USB_EP_CTR_TX & __EP_NONTOGGLE;
+}
+
+static inline uint32 usb_get_ep_dtog_tx(uint8 ep) {
+ uint32 epr = USB_BASE->EP[ep];
+ return epr & USB_EP_DTOG_TX;
+}
+
+static inline uint32 usb_get_ep_dtog_rx(uint8 ep) {
+ uint32 epr = USB_BASE->EP[ep];
+ return epr & USB_EP_DTOG_RX;
+}
+
+static inline uint32 usb_get_ep_tx_sw_buf(uint8 ep) {
+ return usb_get_ep_dtog_rx(ep);
+}
+
+static inline uint32 usb_get_ep_rx_sw_buf(uint8 ep) {
+ return usb_get_ep_dtog_tx(ep);
+}
+
+static inline void usb_toggle_ep_dtog_tx(uint8 ep) {
+ uint32 epr = USB_BASE->EP[ep];
+ epr &= __EP_NONTOGGLE;
+ epr |= USB_EP_DTOG_TX;
+ USB_BASE->EP[ep] = epr;
+}
+
+static inline void usb_toggle_ep_dtog_rx(uint8 ep) {
+ uint32 epr = USB_BASE->EP[ep];
+ epr &= __EP_NONTOGGLE;
+ epr |= USB_EP_DTOG_RX;
+ USB_BASE->EP[ep] = epr;
+}
+
+static inline void usb_clear_ep_dtog_tx(uint8 ep) {
+ if (usb_get_ep_dtog_tx(ep) != 0) {
+ usb_toggle_ep_dtog_tx(ep);
+ }
+}
+
+static inline void usb_clear_ep_dtog_rx(uint8 ep) {
+ if (usb_get_ep_dtog_rx(ep) != 0) {
+ usb_toggle_ep_dtog_rx(ep);
+ }
+}
+
+static inline void usb_set_ep_dtog_tx(uint8 ep) {
+ if (usb_get_ep_dtog_tx(ep) == 0) {
+ usb_toggle_ep_dtog_tx(ep);
+ }
+}
+
+static inline void usb_set_ep_dtog_rx(uint8 ep) {
+ if (usb_get_ep_dtog_rx(ep) == 0) {
+ usb_toggle_ep_dtog_rx(ep);
+ }
+}
+
+static inline void usb_toggle_ep_rx_sw_buf(uint8 ep) {
+ usb_toggle_ep_dtog_tx(ep);
+}
+
+static inline void usb_toggle_ep_tx_sw_buf(uint8 ep) {
+ usb_toggle_ep_dtog_rx(ep);
+}
+
+static inline void usb_clear_ep_rx_sw_buf(uint8 ep) {
+ usb_clear_ep_dtog_tx(ep);
+}
+
+static inline void usb_clear_ep_tx_sw_buf(uint8 ep) {
+ usb_clear_ep_dtog_rx(ep);
+}
+
+static inline void usb_set_ep_rx_sw_buf(uint8 ep) {
+ usb_set_ep_dtog_tx(ep);
+}
+
+static inline void usb_set_ep_tx_sw_buf(uint8 ep) {
+ usb_set_ep_dtog_rx(ep);
+}
+
+static inline void usb_set_ep_rx_stat(uint8 ep, uint32 status) {
+ uint32 epr = USB_BASE->EP[ep];
+ epr &= ~(USB_EP_STAT_TX | USB_EP_DTOG_RX | USB_EP_DTOG_TX);
+ epr |= __EP_CTR_NOP;
+ epr ^= status;
+ USB_BASE->EP[ep] = epr;
+}
+
+static inline void usb_set_ep_tx_stat(uint8 ep, uint32 status) {
+ uint32 epr = USB_BASE->EP[ep];
+ epr &= ~(USB_EP_STAT_RX | USB_EP_DTOG_RX | USB_EP_DTOG_TX);
+ epr |= __EP_CTR_NOP;
+ epr ^= status;
+ USB_BASE->EP[ep] = epr;
+}
+
+static inline void usb_set_ep_type(uint8 ep, uint32 type) {
+ uint32 epr = USB_BASE->EP[ep];
+ epr &= ~USB_EP_EP_TYPE & __EP_NONTOGGLE;
+ epr |= type;
+ USB_BASE->EP[ep] = epr;
+}
+
+static inline void usb_set_ep_kind(uint8 ep, uint32 kind) {
+ uint32 epr = USB_BASE->EP[ep];
+ epr &= ~USB_EP_EP_KIND & __EP_NONTOGGLE;
+ epr |= kind;
+ USB_BASE->EP[ep] = epr;
+}
+
+static inline uint32 usb_get_ep_type(uint8 ep) {
+ uint32 epr = USB_BASE->EP[ep];
+ return epr & USB_EP_EP_TYPE;
+}
+
+static inline uint32 usb_get_ep_kind(uint8 ep) {
+ uint32 epr = USB_BASE->EP[ep];
+ return epr & USB_EP_EP_TYPE;
+}
+
+
+static inline void usb_clear_status_out(uint8 ep) {
+ usb_set_ep_kind(ep, 0);
+}
+
+/*
+ * Packet memory area (PMA) base pointer
+ */
+
+/**
+ * @brief USB packet memory area (PMA) base pointer.
+ *
+ * The USB PMA is SRAM shared between USB and CAN. The USB peripheral
+ * accesses this memory directly via the packet buffer interface. */
+#define USB_PMA_BASE ((__io void*)0x40006000)
+
+/*
+ * PMA conveniences
+ */
+
+void usb_copy_to_pma(const uint8 *buf, uint16 len, uint16 pma_offset);
+void usb_copy_from_pma(uint8 *buf, uint16 len, uint16 pma_offset);
+
+static inline void* usb_pma_ptr(uint32 offset) {
+ return (void*)(USB_PMA_BASE + 2 * offset);
+}
+
+/*
+ * BTABLE
+ */
+
+/* (Forward-declared) BTABLE entry.
+ *
+ * The BTABLE can be viewed as an array of usb_btable_ent values;
+ * these vary in structure according to the configuration of the
+ * endpoint.
+ */
+union usb_btable_ent;
+
+/* Bidirectional endpoint BTABLE entry */
+typedef struct usb_btable_bidi {
+ __io uint16 addr_tx; const uint16 PAD1;
+ __io uint16 count_tx; const uint16 PAD2;
+ __io uint16 addr_rx; const uint16 PAD3;
+ __io uint16 count_rx; const uint16 PAD4;
+} usb_btable_bidi;
+
+/* Unidirectional receive-only endpoint BTABLE entry */
+typedef struct usb_btable_uni_rx {
+ __io uint16 empty1; const uint16 PAD1;
+ __io uint16 empty2; const uint16 PAD2;
+ __io uint16 addr_rx; const uint16 PAD3;
+ __io uint16 count_rx; const uint16 PAD4;
+} usb_btable_uni_rx;
+
+/* Unidirectional transmit-only endpoint BTABLE entry */
+typedef struct usb_btable_uni_tx {
+ __io uint16 addr_tx; const uint16 PAD1;
+ __io uint16 count_tx; const uint16 PAD2;
+ __io uint16 empty1; const uint16 PAD3;
+ __io uint16 empty2; const uint16 PAD4;
+} usb_btable_uni_tx;
+
+/* Double-buffered transmission endpoint BTABLE entry */
+typedef struct usb_btable_dbl_tx {
+ __io uint16 addr_tx0; const uint16 PAD1;
+ __io uint16 count_tx0; const uint16 PAD2;
+ __io uint16 addr_tx1; const uint16 PAD3;
+ __io uint16 count_tx1; const uint16 PAD4;
+} usb_btable_dbl_tx;
+
+/* Double-buffered reception endpoint BTABLE entry */
+typedef struct usb_btable_dbl_rx {
+ __io uint16 addr_rx0; const uint16 PAD1;
+ __io uint16 count_rx0; const uint16 PAD2;
+ __io uint16 addr_rx1; const uint16 PAD3;
+ __io uint16 count_rx1; const uint16 PAD4;
+} usb_btable_dbl_rx;
+
+/* TODO isochronous endpoint entries */
+
+/* Definition for above forward-declared BTABLE entry. */
+typedef union usb_btable_ent {
+ usb_btable_bidi bidi;
+ usb_btable_uni_rx u_rx;
+ usb_btable_uni_tx u_tx;
+ usb_btable_dbl_tx d_tx;
+ usb_btable_dbl_rx d_rx;
+} usb_btable_ent;
+
+/*
+ * BTABLE conveniences
+ */
+
+/* TODO (?) Convert usages of the many (and lengthily-named)
+ * accessors/mutators below to just manipulating usb_btable_entry
+ * values. */
+
+static inline uint32* usb_btable_ptr(uint32 offset) {
+ return (uint32*)usb_pma_ptr(USB_BASE->BTABLE + offset);
+}
+
+/* TX address */
+
+static inline uint32* usb_ep_tx_addr_ptr(uint8 ep) {
+ return usb_btable_ptr(ep * 8);
+}
+
+static inline uint16 usb_get_ep_tx_addr(uint8 ep) {
+ return (uint16)*usb_ep_tx_addr_ptr(ep);
+}
+
+static inline void usb_set_ep_tx_addr(uint8 ep, uint16 addr) {
+ uint32 *tx_addr = usb_ep_tx_addr_ptr(ep);
+ *tx_addr = addr & ~0x1;
+}
+
+/* RX address */
+
+static inline uint32* usb_ep_rx_addr_ptr(uint8 ep) {
+ return usb_btable_ptr(ep * 8 + 4);
+}
+
+static inline uint16 usb_get_ep_rx_addr(uint8 ep) {
+ return (uint16)*usb_ep_rx_addr_ptr(ep);
+}
+
+static inline void usb_set_ep_rx_addr(uint8 ep, uint16 addr) {
+ uint32 *rx_addr = usb_ep_rx_addr_ptr(ep);
+ *rx_addr = addr & ~0x1;
+}
+
+/* TX count (doesn't cover double-buffered and isochronous in) */
+
+static inline uint32* usb_ep_tx_count_ptr(uint8 ep) {
+ return usb_btable_ptr(ep * 8 + 2);
+}
+
+static inline uint16 usb_get_ep_tx_count(uint8 ep) {
+ /* FIXME: this is broken somehow; calling it seems to
+ * confuse/crash the chip. */
+ return (uint16)(*usb_ep_tx_count_ptr(ep) & 0x3FF);
+}
+
+static inline void usb_set_ep_tx_count(uint8 ep, uint16 count) {
+ uint32 *txc = usb_ep_tx_count_ptr(ep);
+ *txc = count;
+}
+
+/* RX count */
+
+static inline uint32* usb_ep_rx_count_ptr(uint8 ep) {
+ return usb_btable_ptr(ep * 8 + 6);
+}
+
+static inline uint16 usb_get_ep_rx_count(uint8 ep) {
+ return (uint16)*usb_ep_rx_count_ptr(ep) & 0x3FF;
+}
+
+void usb_set_ep_rx_count(uint8 ep, uint16 count);
+
+/* double buffer definitions */
+static inline uint32* usb_get_ep_tx_buf0_addr_ptr(uint8 ep) {
+ return usb_ep_tx_addr_ptr(ep);
+}
+
+static inline uint16 usb_get_ep_tx_buf0_addr(uint8 ep) {
+ return usb_get_ep_tx_addr(ep);
+}
+
+static inline void usb_set_ep_tx_buf0_addr(uint8 ep, uint16 addr) {
+ usb_set_ep_tx_addr(ep, addr);
+}
+
+static inline uint32* usb_get_ep_tx_buf1_addr_ptr(uint8 ep) {
+ return usb_ep_rx_addr_ptr(ep);
+}
+
+static inline uint16 usb_get_ep_tx_buf1_addr(uint8 ep) {
+ return usb_get_ep_rx_addr(ep);
+}
+
+static inline void usb_set_ep_tx_buf1_addr(uint8 ep, uint16 addr) {
+ usb_set_ep_rx_addr(ep, addr);
+}
+
+static inline uint32* usb_ep_tx_buf0_count_ptr(uint8 ep) {
+ return usb_ep_tx_count_ptr(ep);
+}
+
+static inline uint16 usb_get_ep_tx_buf0_count(uint8 ep) {
+ return usb_get_ep_tx_count(ep);
+}
+
+static inline void usb_set_ep_tx_buf0_count(uint8 ep, uint16 count) {
+ usb_set_ep_tx_count(ep, count);
+}
+
+static inline uint32* usb_ep_tx_buf1_count_ptr(uint8 ep) {
+ return usb_ep_rx_count_ptr(ep);
+}
+
+static inline uint16 usb_get_ep_tx_buf1_count(uint8 ep) {
+ return usb_get_ep_rx_count(ep);
+}
+
+static inline void usb_set_ep_tx_buf1_count(uint8 ep, uint16 count) {
+ usb_set_ep_rx_count(ep, count);
+}
+static inline uint32* usb_get_ep_rx_buf0_addr_ptr(uint8 ep) {
+ return usb_ep_tx_addr_ptr(ep);
+}
+
+static inline uint16 usb_get_ep_rx_buf0_addr(uint8 ep) {
+ return usb_get_ep_tx_addr(ep);
+}
+
+static inline void usb_set_ep_rx_buf0_addr(uint8 ep, uint16 addr) {
+ usb_set_ep_tx_addr(ep, addr);
+}
+
+static inline uint32* usb_get_ep_rx_buf1_addr_ptr(uint8 ep) {
+ return usb_ep_rx_addr_ptr(ep);
+}
+
+static inline uint16 usb_get_ep_rx_buf1_addr(uint8 ep) {
+ return usb_get_ep_rx_addr(ep);
+}
+
+static inline void usb_set_ep_rx_buf1_addr(uint8 ep, uint16 addr) {
+ usb_set_ep_rx_addr(ep, addr);
+}
+
+static inline uint32* usb_ep_rx_buf0_count_ptr(uint8 ep) {
+ return usb_ep_tx_count_ptr(ep);
+}
+
+static inline uint16 usb_get_ep_rx_buf0_count(uint8 ep) {
+ return usb_get_ep_tx_count(ep);
+}
+
+void usb_set_ep_rx_buf0_count(uint8 ep, uint16 count);
+
+static inline uint32* usb_ep_rx_buf1_count_ptr(uint8 ep) {
+ return usb_ep_rx_count_ptr(ep);
+}
+
+static inline uint16 usb_get_ep_rx_buf1_count(uint8 ep) {
+ return usb_get_ep_rx_count(ep);
+}
+
+static inline void usb_set_ep_rx_buf1_count(uint8 ep, uint16 count) {
+ usb_set_ep_rx_count(ep, count);
+}
+
+/*
+ * Misc. types
+ */
+
+typedef enum usb_ep {
+ USB_EP0,
+ USB_EP1,
+ USB_EP2,
+ USB_EP3,
+ USB_EP4,
+ USB_EP5,
+ USB_EP6,
+ USB_EP7,
+} usb_ep;
+
+typedef enum usb_ep_type {
+ USB_EP_T_CTL = USB_EP_EP_TYPE_CONTROL,
+ USB_EP_T_BULK = USB_EP_EP_TYPE_BULK,
+ USB_EP_T_INT = USB_EP_EP_TYPE_INTERRUPT,
+ USB_EP_T_ISO = USB_EP_EP_TYPE_ISO
+} usb_ep_type;
+
+typedef enum usb_ep_stat {
+ USB_EP_ST_RX_DIS = USB_EP_STAT_RX_DISABLED,
+ USB_EP_ST_RX_STL = USB_EP_STAT_RX_STALL,
+ USB_EP_ST_RX_NAK = USB_EP_STAT_RX_NAK,
+ USB_EP_ST_RX_VAL = USB_EP_STAT_RX_VALID,
+ USB_EP_ST_TX_DIS = USB_EP_STAT_TX_DISABLED,
+ USB_EP_ST_TX_STL = USB_EP_STAT_TX_STALL,
+ USB_EP_ST_TX_NAK = USB_EP_STAT_TX_NAK,
+ USB_EP_ST_TX_VAL = USB_EP_STAT_TX_VALID
+} usb_ep_stat;
+
+#endif
diff --git a/libmaple/usb/usb_lib/usb_core.c b/libmaple/usb/usb_lib/usb_core.c
new file mode 100644
index 0000000..5cf9e87
--- /dev/null
+++ b/libmaple/usb/usb_lib/usb_core.c
@@ -0,0 +1,1013 @@
+/******************** (C) COPYRIGHT 2008 STMicroelectronics ********************
+* File Name : usb_core.c
+* Author : MCD Application Team
+* Version : V2.2.1
+* Date : 09/22/2008
+* Description : Standard protocol processing (USB v2.0)
+********************************************************************************
+* THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
+* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE TIME.
+* AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY DIRECT,
+* INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING FROM THE
+* CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE CODING
+* INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
+*******************************************************************************/
+
+/* Includes ------------------------------------------------------------------*/
+#include "usb_lib.h"
+/* Private typedef -----------------------------------------------------------*/
+/* Private define ------------------------------------------------------------*/
+#define ValBit(VAR,Place) (VAR & (1 << Place))
+#define SetBit(VAR,Place) (VAR |= (1 << Place))
+#define ClrBit(VAR,Place) (VAR &= ((1 << Place) ^ 255))
+
+#define Send0LengthData() { _SetEPTxCount(ENDP0, 0); \
+ vSetEPTxStatus(EP_TX_VALID); \
+ }
+
+#define vSetEPRxStatus(st) (SaveRState = st)
+#define vSetEPTxStatus(st) (SaveTState = st)
+
+#define USB_StatusIn() Send0LengthData()
+#define USB_StatusOut() vSetEPRxStatus(EP_RX_VALID)
+
+#define StatusInfo0 StatusInfo.bw.bb1 /* Reverse bb0 & bb1 */
+#define StatusInfo1 StatusInfo.bw.bb0
+
+/* Private macro -------------------------------------------------------------*/
+/* Private variables ---------------------------------------------------------*/
+u16_u8 StatusInfo;
+USB_Bool Data_Mul_MaxPacketSize = FALSE;
+/* Private function prototypes -----------------------------------------------*/
+static void DataStageOut(void);
+static void DataStageIn(void);
+static void NoData_Setup0(void);
+static void Data_Setup0(void);
+/* Private functions ---------------------------------------------------------*/
+
+/*******************************************************************************
+* Function Name : Standard_GetConfiguration.
+* Description : Return the current configuration variable address.
+* Input : Length - How many bytes are needed.
+* Output : None.
+* Return : Return 1 , if the request is invalid when "Length" is 0.
+* Return "Buffer" if the "Length" is not 0.
+*******************************************************************************/
+u8 *Standard_GetConfiguration(u16 Length)
+{
+ if (Length == 0)
+ {
+ pInformation->Ctrl_Info.Usb_wLength =
+ sizeof(pInformation->Current_Configuration);
+ return 0;
+ }
+ pUser_Standard_Requests->User_GetConfiguration();
+ return (u8 *)&pInformation->Current_Configuration;
+}
+
+/*******************************************************************************
+* Function Name : Standard_SetConfiguration.
+* Description : This routine is called to set the configuration value
+* Then each class should configure device themself.
+* Input : None.
+* Output : None.
+* Return : Return USB_SUCCESS, if the request is performed.
+* Return USB_UNSUPPORT, if the request is invalid.
+*******************************************************************************/
+RESULT Standard_SetConfiguration(void)
+{
+
+ if ((pInformation->USBwValue0 <=
+ Device_Table.Total_Configuration) && (pInformation->USBwValue1 == 0)
+ && (pInformation->USBwIndex == 0)) /*call Back usb spec 2.0*/
+ {
+ pInformation->Current_Configuration = pInformation->USBwValue0;
+ pUser_Standard_Requests->User_SetConfiguration();
+ return USB_SUCCESS;
+ }
+ else
+ {
+ return USB_UNSUPPORT;
+ }
+}
+
+/*******************************************************************************
+* Function Name : Standard_GetInterface.
+* Description : Return the Alternate Setting of the current interface.
+* Input : Length - How many bytes are needed.
+* Output : None.
+* Return : Return 0, if the request is invalid when "Length" is 0.
+* Return "Buffer" if the "Length" is not 0.
+*******************************************************************************/
+u8 *Standard_GetInterface(u16 Length)
+{
+ if (Length == 0)
+ {
+ pInformation->Ctrl_Info.Usb_wLength =
+ sizeof(pInformation->Current_AlternateSetting);
+ return 0;
+ }
+ pUser_Standard_Requests->User_GetInterface();
+ return (u8 *)&pInformation->Current_AlternateSetting;
+}
+
+/*******************************************************************************
+* Function Name : Standard_SetInterface.
+* Description : This routine is called to set the interface.
+* Then each class should configure the interface them self.
+* Input : None.
+* Output : None.
+* Return : - Return USB_SUCCESS, if the request is performed.
+* - Return USB_UNSUPPORT, if the request is invalid.
+*******************************************************************************/
+RESULT Standard_SetInterface(void)
+{
+ RESULT Re;
+ /*Test if the specified Interface and Alternate Setting are supported by
+ the application Firmware*/
+ Re = (*pProperty->Class_Get_Interface_Setting)(pInformation->USBwIndex0, pInformation->USBwValue0);
+
+ if (pInformation->Current_Configuration != 0)
+ {
+ if ((Re != USB_SUCCESS) || (pInformation->USBwIndex1 != 0)
+ || (pInformation->USBwValue1 != 0))
+ {
+ return USB_UNSUPPORT;
+ }
+ else if (Re == USB_SUCCESS)
+ {
+ pUser_Standard_Requests->User_SetInterface();
+ pInformation->Current_Interface = pInformation->USBwIndex0;
+ pInformation->Current_AlternateSetting = pInformation->USBwValue0;
+ return USB_SUCCESS;
+ }
+
+ }
+
+ return USB_UNSUPPORT;
+}
+
+/*******************************************************************************
+* Function Name : Standard_GetStatus.
+* Description : Copy the device request data to "StatusInfo buffer".
+* Input : - Length - How many bytes are needed.
+* Output : None.
+* Return : Return 0, if the request is at end of data block,
+* or is invalid when "Length" is 0.
+*******************************************************************************/
+u8 *Standard_GetStatus(u16 Length)
+{
+ if (Length == 0)
+ {
+ pInformation->Ctrl_Info.Usb_wLength = 2;
+ return 0;
+ }
+
+ StatusInfo.w = 0;
+ /* Reset Status Information */
+
+ if (Type_Recipient == (STANDARD_REQUEST | DEVICE_RECIPIENT))
+ {
+ /*Get Device Status */
+ u8 Feature = pInformation->Current_Feature;
+
+ /* Remote Wakeup enabled */
+ if (ValBit(Feature, 5))
+ {
+ SetBit(StatusInfo0, 1);
+ }
+
+ /* Bus-powered */
+ if (ValBit(Feature, 6))
+ {
+ ClrBit(StatusInfo0, 0);
+ }
+ else /* Self-powered */
+ {
+ SetBit(StatusInfo0, 0);
+ }
+ }
+ /*Interface Status*/
+ else if (Type_Recipient == (STANDARD_REQUEST | INTERFACE_RECIPIENT))
+ {
+ return (u8 *)&StatusInfo;
+ }
+ /*Get EndPoint Status*/
+ else if (Type_Recipient == (STANDARD_REQUEST | ENDPOINT_RECIPIENT))
+ {
+ u8 Related_Endpoint;
+ u8 wIndex0 = pInformation->USBwIndex0;
+
+ Related_Endpoint = (wIndex0 & 0x0f);
+ if (ValBit(wIndex0, 7))
+ {
+ /* IN endpoint */
+ if (_GetTxStallStatus(Related_Endpoint))
+ {
+ SetBit(StatusInfo0, 0); /* IN Endpoint stalled */
+ }
+ }
+ else
+ {
+ /* OUT endpoint */
+ if (_GetRxStallStatus(Related_Endpoint))
+ {
+ SetBit(StatusInfo0, 0); /* OUT Endpoint stalled */
+ }
+ }
+
+ }
+ else
+ {
+ return NULL;
+ }
+ pUser_Standard_Requests->User_GetStatus();
+ return (u8 *)&StatusInfo;
+}
+
+/*******************************************************************************
+* Function Name : Standard_ClearFeature.
+* Description : Clear or disable a specific feature.
+* Input : None.
+* Output : None.
+* Return : - Return USB_SUCCESS, if the request is performed.
+* - Return USB_UNSUPPORT, if the request is invalid.
+*******************************************************************************/
+RESULT Standard_ClearFeature(void)
+{
+ u32 Type_Rec = Type_Recipient;
+ u32 Status;
+
+
+ if (Type_Rec == (STANDARD_REQUEST | DEVICE_RECIPIENT))
+ {/*Device Clear Feature*/
+ ClrBit(pInformation->Current_Feature, 5);
+ return USB_SUCCESS;
+ }
+ else if (Type_Rec == (STANDARD_REQUEST | ENDPOINT_RECIPIENT))
+ {/*EndPoint Clear Feature*/
+ DEVICE* pDev;
+ u32 Related_Endpoint;
+ u32 wIndex0;
+ u32 rEP;
+
+ if ((pInformation->USBwValue != ENDPOINT_STALL)
+ || (pInformation->USBwIndex1 != 0))
+ {
+ return USB_UNSUPPORT;
+ }
+
+ pDev = &Device_Table;
+ wIndex0 = pInformation->USBwIndex0;
+ rEP = wIndex0 & ~0x80;
+ Related_Endpoint = ENDP0 + rEP;
+
+ if (ValBit(pInformation->USBwIndex0, 7))
+ {
+ /*Get Status of endpoint & stall the request if the related_ENdpoint
+ is Disabled*/
+ Status = _GetEPTxStatus(Related_Endpoint);
+ }
+ else
+ {
+ Status = _GetEPRxStatus(Related_Endpoint);
+ }
+
+ if ((rEP >= pDev->Total_Endpoint) || (Status == 0)
+ || (pInformation->Current_Configuration == 0))
+ {
+ return USB_UNSUPPORT;
+ }
+
+
+ if (wIndex0 & 0x80)
+ {
+ /* IN endpoint */
+ if (_GetTxStallStatus(Related_Endpoint ))
+ {
+ ClearDTOG_TX(Related_Endpoint);
+ SetEPTxStatus(Related_Endpoint, EP_TX_VALID);
+ }
+ }
+ else
+ {
+ /* OUT endpoint */
+ if (_GetRxStallStatus(Related_Endpoint))
+ {
+ if (Related_Endpoint == ENDP0)
+ {
+ /* After clear the STALL, enable the default endpoint receiver */
+ SetEPRxCount(Related_Endpoint, Device_Property.MaxPacketSize);
+ _SetEPRxStatus(Related_Endpoint, EP_RX_VALID);
+ }
+ else
+ {
+ ClearDTOG_RX(Related_Endpoint);
+ _SetEPRxStatus(Related_Endpoint, EP_RX_VALID);
+ }
+ }
+ }
+ pUser_Standard_Requests->User_ClearFeature();
+ return USB_SUCCESS;
+ }
+
+ return USB_UNSUPPORT;
+}
+
+/*******************************************************************************
+* Function Name : Standard_SetEndPointFeature
+* Description : Set or enable a specific feature of EndPoint
+* Input : None.
+* Output : None.
+* Return : - Return USB_SUCCESS, if the request is performed.
+* - Return USB_UNSUPPORT, if the request is invalid.
+*******************************************************************************/
+RESULT Standard_SetEndPointFeature(void)
+{
+ u32 wIndex0;
+ u32 Related_Endpoint;
+ u32 rEP;
+ u32 Status;
+
+ wIndex0 = pInformation->USBwIndex0;
+ rEP = wIndex0 & ~0x80;
+ Related_Endpoint = ENDP0 + rEP;
+
+ if (ValBit(pInformation->USBwIndex0, 7))
+ {
+ /* get Status of endpoint & stall the request if the related_ENdpoint
+ is Disabled*/
+ Status = _GetEPTxStatus(Related_Endpoint);
+ }
+ else
+ {
+ Status = _GetEPRxStatus(Related_Endpoint);
+ }
+
+ if (Related_Endpoint >= Device_Table.Total_Endpoint
+ || pInformation->USBwValue != 0 || Status == 0
+ || pInformation->Current_Configuration == 0)
+ {
+ return USB_UNSUPPORT;
+ }
+ else
+ {
+ if (wIndex0 & 0x80)
+ {
+ /* IN endpoint */
+ _SetEPTxStatus(Related_Endpoint, EP_TX_STALL);
+ }
+
+ else
+ {
+ /* OUT endpoint */
+ _SetEPRxStatus(Related_Endpoint, EP_RX_STALL);
+ }
+ }
+ pUser_Standard_Requests->User_SetEndPointFeature();
+ return USB_SUCCESS;
+}
+
+/*******************************************************************************
+* Function Name : Standard_SetDeviceFeature.
+* Description : Set or enable a specific feature of Device.
+* Input : None.
+* Output : None.
+* Return : - Return USB_SUCCESS, if the request is performed.
+* - Return USB_UNSUPPORT, if the request is invalid.
+*******************************************************************************/
+RESULT Standard_SetDeviceFeature(void)
+{
+ SetBit(pInformation->Current_Feature, 5);
+ pUser_Standard_Requests->User_SetDeviceFeature();
+ return USB_SUCCESS;
+}
+
+/*******************************************************************************
+* Function Name : Standard_GetDescriptorData.
+* Description : Standard_GetDescriptorData is used for descriptors transfer.
+* : This routine is used for the descriptors resident in Flash
+* or RAM
+* pDesc can be in either Flash or RAM
+* The purpose of this routine is to have a versatile way to
+* response descriptors request. It allows user to generate
+* certain descriptors with software or read descriptors from
+* external storage part by part.
+* Input : - Length - Length of the data in this transfer.
+* - pDesc - A pointer points to descriptor struct.
+* The structure gives the initial address of the descriptor and
+* its original size.
+* Output : None.
+* Return : Address of a part of the descriptor pointed by the Usb_
+* wOffset The buffer pointed by this address contains at least
+* Length bytes.
+*******************************************************************************/
+u8 *Standard_GetDescriptorData(u16 Length, ONE_DESCRIPTOR *pDesc)
+{
+ u32 wOffset;
+
+ wOffset = pInformation->Ctrl_Info.Usb_wOffset;
+ if (Length == 0)
+ {
+ pInformation->Ctrl_Info.Usb_wLength = pDesc->Descriptor_Size - wOffset;
+ return 0;
+ }
+
+ return pDesc->Descriptor + wOffset;
+}
+
+/*******************************************************************************
+* Function Name : DataStageOut.
+* Description : Data stage of a Control Write Transfer.
+* Input : None.
+* Output : None.
+* Return : None.
+*******************************************************************************/
+void DataStageOut(void)
+{
+ ENDPOINT_INFO *pEPinfo = &pInformation->Ctrl_Info;
+ u32 save_rLength;
+
+ save_rLength = pEPinfo->Usb_rLength;
+
+ if (pEPinfo->CopyData && save_rLength)
+ {
+ u8 *Buffer;
+ u32 Length;
+
+ Length = pEPinfo->PacketSize;
+ if (Length > save_rLength)
+ {
+ Length = save_rLength;
+ }
+
+ Buffer = (*pEPinfo->CopyData)(Length);
+ pEPinfo->Usb_rLength -= Length;
+ pEPinfo->Usb_rOffset += Length;
+
+ PMAToUserBufferCopy(Buffer, GetEPRxAddr(ENDP0), Length);
+ }
+
+ if (pEPinfo->Usb_rLength != 0)
+ {
+ vSetEPRxStatus(EP_RX_VALID);/* re-enable for next data reception */
+ SetEPTxCount(ENDP0, 0);
+ vSetEPTxStatus(EP_TX_VALID);/* Expect the host to abort the data OUT stage */
+ }
+ /* Set the next State*/
+ if (pEPinfo->Usb_rLength >= pEPinfo->PacketSize)
+ {
+ pInformation->ControlState = OUT_DATA;
+ }
+ else
+ {
+ if (pEPinfo->Usb_rLength > 0)
+ {
+ pInformation->ControlState = LAST_OUT_DATA;
+ }
+ else if (pEPinfo->Usb_rLength == 0)
+ {
+ pInformation->ControlState = WAIT_STATUS_IN;
+ USB_StatusIn();
+ }
+ }
+}
+
+/*******************************************************************************
+* Function Name : DataStageIn.
+* Description : Data stage of a Control Read Transfer.
+* Input : None.
+* Output : None.
+* Return : None.
+*******************************************************************************/
+void DataStageIn(void)
+{
+ ENDPOINT_INFO *pEPinfo = &pInformation->Ctrl_Info;
+ u32 save_wLength = pEPinfo->Usb_wLength;
+ u32 ControlState = pInformation->ControlState;
+
+ u8 *DataBuffer;
+ u32 Length;
+
+ if ((save_wLength == 0) && (ControlState == LAST_IN_DATA))
+ {
+ if(Data_Mul_MaxPacketSize == TRUE)
+ {
+ /* No more data to send and empty packet */
+ Send0LengthData();
+ ControlState = LAST_IN_DATA;
+ Data_Mul_MaxPacketSize = FALSE;
+ }
+ else
+ {
+ /* No more data to send so STALL the TX Status*/
+ ControlState = WAIT_STATUS_OUT;
+ vSetEPTxStatus(EP_TX_STALL);
+ }
+
+ goto Expect_Status_Out;
+ }
+
+ Length = pEPinfo->PacketSize;
+ ControlState = (save_wLength <= Length) ? LAST_IN_DATA : IN_DATA;
+
+ if (Length > save_wLength)
+ {
+ Length = save_wLength;
+ }
+
+ DataBuffer = (*pEPinfo->CopyData)(Length);
+
+ UserToPMABufferCopy(DataBuffer, GetEPTxAddr(ENDP0), Length);
+
+ SetEPTxCount(ENDP0, Length);
+
+ pEPinfo->Usb_wLength -= Length;
+ pEPinfo->Usb_wOffset += Length;
+ vSetEPTxStatus(EP_TX_VALID);
+
+ USB_StatusOut();/* Expect the host to abort the data IN stage */
+
+Expect_Status_Out:
+ pInformation->ControlState = ControlState;
+}
+
+/*******************************************************************************
+* Function Name : NoData_Setup0.
+* Description : Proceed the processing of setup request without data stage.
+* Input : None.
+* Output : None.
+* Return : None.
+*******************************************************************************/
+void NoData_Setup0(void)
+{
+ RESULT Result = USB_UNSUPPORT;
+ u32 RequestNo = pInformation->USBbRequest;
+ u32 ControlState;
+
+ if (Type_Recipient == (STANDARD_REQUEST | DEVICE_RECIPIENT))
+ {
+ /* Device Request*/
+ /* SET_CONFIGURATION*/
+ if (RequestNo == SET_CONFIGURATION)
+ {
+ Result = Standard_SetConfiguration();
+ }
+
+ /*SET ADDRESS*/
+ else if (RequestNo == SET_ADDRESS)
+ {
+ if ((pInformation->USBwValue0 > 127) || (pInformation->USBwValue1 != 0)
+ || (pInformation->USBwIndex != 0)
+ || (pInformation->Current_Configuration != 0))
+ /* Device Address should be 127 or less*/
+ {
+ ControlState = STALLED;
+ goto exit_NoData_Setup0;
+ }
+ else
+ {
+ Result = USB_SUCCESS;
+ }
+ }
+ /*SET FEATURE for Device*/
+ else if (RequestNo == SET_FEATURE)
+ {
+ if ((pInformation->USBwValue0 == DEVICE_REMOTE_WAKEUP)
+ && (pInformation->USBwIndex == 0)
+ && (ValBit(pInformation->Current_Feature, 5)))
+ {
+ Result = Standard_SetDeviceFeature();
+ }
+ else
+ {
+ Result = USB_UNSUPPORT;
+ }
+ }
+ /*Clear FEATURE for Device */
+ else if (RequestNo == CLEAR_FEATURE)
+ {
+ if (pInformation->USBwValue0 == DEVICE_REMOTE_WAKEUP
+ && pInformation->USBwIndex == 0
+ && ValBit(pInformation->Current_Feature, 5))
+ {
+ Result = Standard_ClearFeature();
+ }
+ else
+ {
+ Result = USB_UNSUPPORT;
+ }
+ }
+
+ }
+
+ /* Interface Request*/
+ else if (Type_Recipient == (STANDARD_REQUEST | INTERFACE_RECIPIENT))
+ {
+ /*SET INTERFACE*/
+ if (RequestNo == SET_INTERFACE)
+ {
+ Result = Standard_SetInterface();
+ }
+ }
+
+ /* EndPoint Request*/
+ else if (Type_Recipient == (STANDARD_REQUEST | ENDPOINT_RECIPIENT))
+ {
+ /*CLEAR FEATURE for EndPoint*/
+ if (RequestNo == CLEAR_FEATURE)
+ {
+ Result = Standard_ClearFeature();
+ }
+ /* SET FEATURE for EndPoint*/
+ else if (RequestNo == SET_FEATURE)
+ {
+ Result = Standard_SetEndPointFeature();
+ }
+ }
+ else
+ {
+ Result = USB_UNSUPPORT;
+ }
+
+
+ if (Result != USB_SUCCESS)
+ {
+ Result = (*pProperty->Class_NoData_Setup)(RequestNo);
+ if (Result == USB_NOT_READY)
+ {
+ ControlState = PAUSE;
+ goto exit_NoData_Setup0;
+ }
+ }
+
+ if (Result != USB_SUCCESS)
+ {
+ ControlState = STALLED;
+ goto exit_NoData_Setup0;
+ }
+
+ ControlState = WAIT_STATUS_IN;/* After no data stage SETUP */
+
+ USB_StatusIn();
+
+exit_NoData_Setup0:
+ pInformation->ControlState = ControlState;
+ return;
+}
+
+/*******************************************************************************
+* Function Name : Data_Setup0.
+* Description : Proceed the processing of setup request with data stage.
+* Input : None.
+* Output : None.
+* Return : None.
+*******************************************************************************/
+void Data_Setup0(void)
+{
+ u8 *(*CopyRoutine)(u16);
+ RESULT Result;
+ u32 Request_No = pInformation->USBbRequest;
+
+ u32 Related_Endpoint, Reserved;
+ u32 wOffset, Status;
+
+
+
+ CopyRoutine = NULL;
+ wOffset = 0;
+
+ if (Request_No == GET_DESCRIPTOR)
+ {
+ if (Type_Recipient == (STANDARD_REQUEST | DEVICE_RECIPIENT))
+ {
+ u8 wValue1 = pInformation->USBwValue1;
+ if (wValue1 == DEVICE_DESCRIPTOR)
+ {
+ CopyRoutine = pProperty->GetDeviceDescriptor;
+ }
+ else if (wValue1 == CONFIG_DESCRIPTOR)
+ {
+ CopyRoutine = pProperty->GetConfigDescriptor;
+ }
+ else if (wValue1 == STRING_DESCRIPTOR)
+ {
+ CopyRoutine = pProperty->GetStringDescriptor;
+ } /* End of GET_DESCRIPTOR */
+ }
+ }
+
+ /*GET STATUS*/
+ else if ((Request_No == GET_STATUS) && (pInformation->USBwValue == 0)
+ && (pInformation->USBwLength == 0x0002)
+ && (pInformation->USBwIndex1 == 0))
+ {
+ /* GET STATUS for Device*/
+ if ((Type_Recipient == (STANDARD_REQUEST | DEVICE_RECIPIENT))
+ && (pInformation->USBwIndex == 0))
+ {
+ CopyRoutine = Standard_GetStatus;
+ }
+
+ /* GET STATUS for Interface*/
+ else if (Type_Recipient == (STANDARD_REQUEST | INTERFACE_RECIPIENT))
+ {
+ if (((*pProperty->Class_Get_Interface_Setting)(pInformation->USBwIndex0, 0) == USB_SUCCESS)
+ && (pInformation->Current_Configuration != 0))
+ {
+ CopyRoutine = Standard_GetStatus;
+ }
+ }
+
+ /* GET STATUS for EndPoint*/
+ else if (Type_Recipient == (STANDARD_REQUEST | ENDPOINT_RECIPIENT))
+ {
+ Related_Endpoint = (pInformation->USBwIndex0 & 0x0f);
+ Reserved = pInformation->USBwIndex0 & 0x70;
+
+ if (ValBit(pInformation->USBwIndex0, 7))
+ {
+ /*Get Status of endpoint & stall the request if the related_ENdpoint
+ is Disabled*/
+ Status = _GetEPTxStatus(Related_Endpoint);
+ }
+ else
+ {
+ Status = _GetEPRxStatus(Related_Endpoint);
+ }
+
+ if ((Related_Endpoint < Device_Table.Total_Endpoint) && (Reserved == 0)
+ && (Status != 0))
+ {
+ CopyRoutine = Standard_GetStatus;
+ }
+ }
+
+ }
+
+ /*GET CONFIGURATION*/
+ else if (Request_No == GET_CONFIGURATION)
+ {
+ if (Type_Recipient == (STANDARD_REQUEST | DEVICE_RECIPIENT))
+ {
+ CopyRoutine = Standard_GetConfiguration;
+ }
+ }
+ /*GET INTERFACE*/
+ else if (Request_No == GET_INTERFACE)
+ {
+ if ((Type_Recipient == (STANDARD_REQUEST | INTERFACE_RECIPIENT))
+ && (pInformation->Current_Configuration != 0) && (pInformation->USBwValue == 0)
+ && (pInformation->USBwIndex1 == 0) && (pInformation->USBwLength == 0x0001)
+ && ((*pProperty->Class_Get_Interface_Setting)(pInformation->USBwIndex0, 0) == USB_SUCCESS))
+ {
+ CopyRoutine = Standard_GetInterface;
+ }
+
+ }
+
+ if (CopyRoutine)
+ {
+ pInformation->Ctrl_Info.Usb_wOffset = wOffset;
+ pInformation->Ctrl_Info.CopyData = CopyRoutine;
+ /* sb in the original the cast to word was directly */
+ /* now the cast is made step by step */
+ (*CopyRoutine)(0);
+ Result = USB_SUCCESS;
+ }
+ else
+ {
+ Result = (*pProperty->Class_Data_Setup)(pInformation->USBbRequest);
+ if (Result == USB_NOT_READY)
+ {
+ pInformation->ControlState = PAUSE;
+ return;
+ }
+ }
+
+ if (pInformation->Ctrl_Info.Usb_wLength == 0xFFFF)
+ {
+ /* Data is not ready, wait it */
+ pInformation->ControlState = PAUSE;
+ return;
+ }
+ if ((Result == USB_UNSUPPORT) || (pInformation->Ctrl_Info.Usb_wLength == 0))
+ {
+ /* Unsupported request */
+ pInformation->ControlState = STALLED;
+ return;
+ }
+
+
+ if (ValBit(pInformation->USBbmRequestType, 7))
+ {
+ /* Device ==> Host */
+ vu32 wLength = pInformation->USBwLength;
+
+ /* Restrict the data length to be the one host asks */
+ if (pInformation->Ctrl_Info.Usb_wLength > wLength)
+ {
+ pInformation->Ctrl_Info.Usb_wLength = wLength;
+ }
+
+ else if (pInformation->Ctrl_Info.Usb_wLength < pInformation->USBwLength)
+ {
+ if (pInformation->Ctrl_Info.Usb_wLength < pProperty->MaxPacketSize)
+ {
+ Data_Mul_MaxPacketSize = FALSE;
+ }
+ else if ((pInformation->Ctrl_Info.Usb_wLength % pProperty->MaxPacketSize) == 0)
+ {
+ Data_Mul_MaxPacketSize = TRUE;
+ }
+ }
+
+ pInformation->Ctrl_Info.PacketSize = pProperty->MaxPacketSize;
+ DataStageIn();
+ }
+ else
+ {
+ pInformation->ControlState = OUT_DATA;
+ vSetEPRxStatus(EP_RX_VALID); /* enable for next data reception */
+ }
+
+ return;
+}
+
+/*******************************************************************************
+* Function Name : Setup0_Process
+* Description : Get the device request data and dispatch to individual process.
+* Input : None.
+* Output : None.
+* Return : Post0_Process.
+*******************************************************************************/
+u8 Setup0_Process(void)
+{
+
+ union
+ {
+ u8* b;
+ u16* w;
+ } pBuf;
+
+ pBuf.b = PMAAddr + (u8 *)(_GetEPRxAddr(ENDP0) * 2); /* *2 for 32 bits addr */
+
+ if (pInformation->ControlState != PAUSE)
+ {
+ pInformation->USBbmRequestType = *pBuf.b++; /* bmRequestType */
+ pInformation->USBbRequest = *pBuf.b++; /* bRequest */
+ pBuf.w++; /* word not accessed because of 32 bits addressing */
+ pInformation->USBwValue = ByteSwap(*pBuf.w++); /* wValue */
+ pBuf.w++; /* word not accessed because of 32 bits addressing */
+ pInformation->USBwIndex = ByteSwap(*pBuf.w++); /* wIndex */
+ pBuf.w++; /* word not accessed because of 32 bits addressing */
+ pInformation->USBwLength = *pBuf.w; /* wLength */
+ }
+
+ pInformation->ControlState = SETTING_UP;
+ if (pInformation->USBwLength == 0)
+ {
+ /* Setup with no data stage */
+ NoData_Setup0();
+ }
+ else
+ {
+ /* Setup with data stage */
+ Data_Setup0();
+ }
+ return Post0_Process();
+}
+
+/*******************************************************************************
+* Function Name : In0_Process
+* Description : Process the IN token on all default endpoint.
+* Input : None.
+* Output : None.
+* Return : Post0_Process.
+*******************************************************************************/
+u8 In0_Process(void)
+{
+ u32 ControlState = pInformation->ControlState;
+
+ if ((ControlState == IN_DATA) || (ControlState == LAST_IN_DATA))
+ {
+ DataStageIn();
+ /* ControlState may be changed outside the function */
+ ControlState = pInformation->ControlState;
+ }
+
+ else if (ControlState == WAIT_STATUS_IN)
+ {
+ if ((pInformation->USBbRequest == SET_ADDRESS) &&
+ (Type_Recipient == (STANDARD_REQUEST | DEVICE_RECIPIENT)))
+ {
+ SetDeviceAddress(pInformation->USBwValue0);
+ pUser_Standard_Requests->User_SetDeviceAddress();
+ }
+ (*pProperty->Process_Status_IN)();
+ ControlState = STALLED;
+ }
+
+ else
+ {
+ ControlState = STALLED;
+ }
+
+ pInformation->ControlState = ControlState;
+
+ return Post0_Process();
+}
+
+/*******************************************************************************
+* Function Name : Out0_Process
+* Description : Process the OUT token on all default endpoint.
+* Input : None.
+* Output : None.
+* Return : Post0_Process.
+*******************************************************************************/
+u8 Out0_Process(void)
+{
+ u32 ControlState = pInformation->ControlState;
+
+ if ((ControlState == OUT_DATA) || (ControlState == LAST_OUT_DATA))
+ {
+ DataStageOut();
+ ControlState = pInformation->ControlState; /* may be changed outside the function */
+ }
+
+ else if (ControlState == WAIT_STATUS_OUT)
+ {
+ (*pProperty->Process_Status_OUT)();
+ ControlState = STALLED;
+ }
+
+ else if ((ControlState == IN_DATA) || (ControlState == LAST_IN_DATA))
+ {
+ /* host aborts the transfer before finish */
+ ControlState = STALLED;
+ }
+
+ /* Unexpect state, STALL the endpoint */
+ else
+ {
+ ControlState = STALLED;
+ }
+
+ pInformation->ControlState = ControlState;
+
+ return Post0_Process();
+}
+
+/*******************************************************************************
+* Function Name : Post0_Process
+* Description : Stall the Endpoint 0 in case of error.
+* Input : None.
+* Output : None.
+* Return : - 0 if the control State is in PAUSE
+* - 1 if not.
+*******************************************************************************/
+u8 Post0_Process(void)
+{
+ SetEPRxCount(ENDP0, Device_Property.MaxPacketSize);
+
+ if (pInformation->ControlState == STALLED)
+ {
+ vSetEPRxStatus(EP_RX_STALL);
+ vSetEPTxStatus(EP_TX_STALL);
+ }
+
+ return (pInformation->ControlState == PAUSE);
+}
+
+/*******************************************************************************
+* Function Name : SetDeviceAddress.
+* Description : Set the device and all the used Endpoints addresses.
+* Input : - Val: device adress.
+* Output : None.
+* Return : None.
+*******************************************************************************/
+void SetDeviceAddress(u8 Val)
+{
+ u32 i;
+ u32 nEP = Device_Table.Total_Endpoint;
+
+ /* set address in every used endpoint */
+ for (i = 0; i < nEP; i++)
+ {
+ _SetEPAddress((u8)i, (u8)i);
+ } /* for */
+ _SetDADDR(Val | DADDR_EF); /* set device address and enable function */
+}
+
+/*******************************************************************************
+* Function Name : NOP_Process
+* Description : No operation function.
+* Input : None.
+* Output : None.
+* Return : None.
+*******************************************************************************/
+void NOP_Process(void)
+{
+}
+
+/******************* (C) COPYRIGHT 2008 STMicroelectronics *****END OF FILE****/
diff --git a/libmaple/usb/usb_lib/usb_core.h b/libmaple/usb/usb_lib/usb_core.h
new file mode 100644
index 0000000..fa29a18
--- /dev/null
+++ b/libmaple/usb/usb_lib/usb_core.h
@@ -0,0 +1,251 @@
+/******************** (C) COPYRIGHT 2008 STMicroelectronics ********************
+* File Name : usb_core.h
+* Author : MCD Application Team
+* Version : V2.2.1
+* Date : 09/22/2008
+* Description : Standard protocol processing functions prototypes
+********************************************************************************
+* THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
+* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE TIME.
+* AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY DIRECT,
+* INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING FROM THE
+* CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE CODING
+* INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
+*******************************************************************************/
+
+/* Define to prevent recursive inclusion -------------------------------------*/
+#ifndef __USB_CORE_H
+#define __USB_CORE_H
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+/* Includes ------------------------------------------------------------------*/
+/* Exported types ------------------------------------------------------------*/
+typedef enum _CONTROL_STATE
+{
+ WAIT_SETUP, /* 0 */
+ SETTING_UP, /* 1 */
+ IN_DATA, /* 2 */
+ OUT_DATA, /* 3 */
+ LAST_IN_DATA, /* 4 */
+ LAST_OUT_DATA, /* 5 */
+ WAIT_STATUS_IN, /* 7 */
+ WAIT_STATUS_OUT, /* 8 */
+ STALLED, /* 9 */
+ PAUSE /* 10 */
+} CONTROL_STATE; /* The state machine states of a control pipe */
+
+typedef struct OneDescriptor
+{
+ u8 *Descriptor;
+ u16 Descriptor_Size;
+}
+ONE_DESCRIPTOR, *PONE_DESCRIPTOR;
+/* All the request process routines return a value of this type
+ If the return value is not SUCCESS or NOT_READY,
+ the software will STALL the correspond endpoint */
+typedef enum _RESULT
+{
+ USB_SUCCESS = 0, /* Process sucessfully */
+ USB_ERROR,
+ USB_UNSUPPORT,
+ USB_NOT_READY /* The process has not been finished, endpoint will be
+ NAK to further rquest */
+} RESULT;
+
+
+/*-*-*-*-*-*-*-*-*-*-* Definitions for endpoint level -*-*-*-*-*-*-*-*-*-*-*-*/
+typedef struct _ENDPOINT_INFO
+{
+ /* When send data out of the device,
+ CopyData() is used to get data buffer 'Length' bytes data
+ if Length is 0,
+ CopyData() returns the total length of the data
+ if the request is not supported, returns 0
+ (NEW Feature )
+ if CopyData() returns -1, the calling routine should not proceed
+ further and will resume the SETUP process by the class device
+ if Length is not 0,
+ CopyData() returns a pointer to indicate the data location
+ Usb_wLength is the data remain to be sent,
+ Usb_wOffset is the Offset of original data
+ When receive data from the host,
+ CopyData() is used to get user data buffer which is capable
+ of Length bytes data to copy data from the endpoint buffer.
+ if Length is 0,
+ CopyData() returns the available data length,
+ if Length is not 0,
+ CopyData() returns user buffer address
+ Usb_rLength is the data remain to be received,
+ Usb_rPointer is the Offset of data buffer
+ */
+ u16 Usb_wLength;
+ u16 Usb_wOffset;
+ u16 PacketSize;
+ u8 *(*CopyData)(u16 Length);
+}ENDPOINT_INFO;
+
+/*-*-*-*-*-*-*-*-*-*-*-* Definitions for device level -*-*-*-*-*-*-*-*-*-*-*-*/
+
+typedef struct _DEVICE
+{
+ u8 Total_Endpoint; /* Number of endpoints that are used */
+ u8 Total_Configuration;/* Number of configuration available */
+}
+DEVICE;
+
+typedef union
+{
+ u16 w;
+ struct BW
+ {
+ u8 bb1;
+ u8 bb0;
+ }
+ bw;
+} u16_u8;
+
+typedef struct _DEVICE_INFO
+{
+ u8 USBbmRequestType; /* bmRequestType */
+ u8 USBbRequest; /* bRequest */
+ u16_u8 USBwValues; /* wValue */
+ u16_u8 USBwIndexs; /* wIndex */
+ u16_u8 USBwLengths; /* wLength */
+
+ u8 ControlState; /* of type CONTROL_STATE */
+ u8 Current_Feature;
+ u8 Current_Configuration; /* Selected configuration */
+ u8 Current_Interface; /* Selected interface of current configuration */
+ u8 Current_AlternateSetting;/* Selected Alternate Setting of current
+ interface*/
+
+ ENDPOINT_INFO Ctrl_Info;
+}DEVICE_INFO;
+
+typedef struct _DEVICE_PROP
+{
+ void (*Init)(void); /* Initialize the device */
+ void (*Reset)(void); /* Reset routine of this device */
+
+ /* Device dependent process after the status stage */
+ void (*Process_Status_IN)(void);
+ void (*Process_Status_OUT)(void);
+
+ /* Procedure of process on setup stage of a class specified request with data stage */
+ /* All class specified requests with data stage are processed in Class_Data_Setup
+ Class_Data_Setup()
+ responses to check all special requests and fills ENDPOINT_INFO
+ according to the request
+ If IN tokens are expected, then wLength & wOffset will be filled
+ with the total transferring bytes and the starting position
+ If OUT tokens are expected, then rLength & rOffset will be filled
+ with the total expected bytes and the starting position in the buffer
+
+ If the request is valid, Class_Data_Setup returns SUCCESS, else UNSUPPORT
+
+ CAUTION:
+ Since GET_CONFIGURATION & GET_INTERFACE are highly related to
+ the individual classes, they will be checked and processed here.
+ */
+ RESULT (*Class_Data_Setup)(u8 RequestNo);
+
+ /* Procedure of process on setup stage of a class specified request without data stage */
+ /* All class specified requests without data stage are processed in Class_NoData_Setup
+ Class_NoData_Setup
+ responses to check all special requests and perform the request
+
+ CAUTION:
+ Since SET_CONFIGURATION & SET_INTERFACE are highly related to
+ the individual classes, they will be checked and processed here.
+ */
+ RESULT (*Class_NoData_Setup)(u8 RequestNo);
+
+ /*Class_Get_Interface_Setting
+ This function is used by the file usb_core.c to test if the selected Interface
+ and Alternate Setting (u8 Interface, u8 AlternateSetting) are supported by
+ the application.
+ This function is writing by user. It should return "SUCCESS" if the Interface
+ and Alternate Setting are supported by the application or "UNSUPPORT" if they
+ are not supported. */
+
+ RESULT (*Class_Get_Interface_Setting)(u8 Interface, u8 AlternateSetting);
+
+ u8* (*GetDeviceDescriptor)(u16 Length);
+ u8* (*GetConfigDescriptor)(u16 Length);
+ u8* (*GetStringDescriptor)(u16 Length);
+
+ u8* RxEP_buffer;
+ u8 MaxPacketSize;
+
+}DEVICE_PROP;
+
+typedef struct _USER_STANDARD_REQUESTS
+{
+ void (*User_GetConfiguration)(void); /* Get Configuration */
+ void (*User_SetConfiguration)(void); /* Set Configuration */
+ void (*User_GetInterface)(void); /* Get Interface */
+ void (*User_SetInterface)(void); /* Set Interface */
+ void (*User_GetStatus)(void); /* Get Status */
+ void (*User_ClearFeature)(void); /* Clear Feature */
+ void (*User_SetEndPointFeature)(void); /* Set Endpoint Feature */
+ void (*User_SetDeviceFeature)(void); /* Set Device Feature */
+ void (*User_SetDeviceAddress)(void); /* Set Device Address */
+}
+USER_STANDARD_REQUESTS;
+
+/* Exported constants --------------------------------------------------------*/
+#define Type_Recipient (pInformation->USBbmRequestType & (REQUEST_TYPE | RECIPIENT))
+
+#define Usb_rLength Usb_wLength
+#define Usb_rOffset Usb_wOffset
+
+#define USBwValue USBwValues.w
+#define USBwValue0 USBwValues.bw.bb0
+#define USBwValue1 USBwValues.bw.bb1
+#define USBwIndex USBwIndexs.w
+#define USBwIndex0 USBwIndexs.bw.bb0
+#define USBwIndex1 USBwIndexs.bw.bb1
+#define USBwLength USBwLengths.w
+#define USBwLength0 USBwLengths.bw.bb0
+#define USBwLength1 USBwLengths.bw.bb1
+
+/* Exported macro ------------------------------------------------------------*/
+/* Exported functions ------------------------------------------------------- */
+u8 Setup0_Process(void);
+u8 Post0_Process(void);
+u8 Out0_Process(void);
+u8 In0_Process(void);
+
+RESULT Standard_SetEndPointFeature(void);
+RESULT Standard_SetDeviceFeature(void);
+
+u8 *Standard_GetConfiguration(u16 Length);
+RESULT Standard_SetConfiguration(void);
+u8 *Standard_GetInterface(u16 Length);
+RESULT Standard_SetInterface(void);
+u8 *Standard_GetDescriptorData(u16 Length, PONE_DESCRIPTOR pDesc);
+
+u8 *Standard_GetStatus(u16 Length);
+RESULT Standard_ClearFeature(void);
+void SetDeviceAddress(u8);
+void NOP_Process(void);
+
+extern DEVICE_PROP Device_Property;
+extern USER_STANDARD_REQUESTS User_Standard_Requests;
+extern DEVICE Device_Table;
+extern DEVICE_INFO Device_Info;
+
+/* cells saving status during interrupt servicing */
+extern u16 SaveRState;
+extern u16 SaveTState;
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif /* __USB_CORE_H */
+
+/******************* (C) COPYRIGHT 2008 STMicroelectronics *****END OF FILE****/
diff --git a/libmaple/usb/usb_lib/usb_def.h b/libmaple/usb/usb_lib/usb_def.h
new file mode 100644
index 0000000..80aa303
--- /dev/null
+++ b/libmaple/usb/usb_lib/usb_def.h
@@ -0,0 +1,88 @@
+/******************** (C) COPYRIGHT 2008 STMicroelectronics ********************
+* File Name : usb_def.h
+* Author : MCD Application Team
+* Version : V2.2.1
+* Date : 09/22/2008
+* Description : Definitions related to USB Core
+********************************************************************************
+* THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
+* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE TIME.
+* AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY DIRECT,
+* INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING FROM THE
+* CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE CODING
+* INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
+*******************************************************************************/
+
+/* Define to prevent recursive inclusion -------------------------------------*/
+#ifndef __USB_DEF_H
+#define __USB_DEF_H
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+/* Includes ------------------------------------------------------------------*/
+/* Exported types ------------------------------------------------------------*/
+typedef enum _RECIPIENT_TYPE
+{
+ DEVICE_RECIPIENT, /* Recipient device */
+ INTERFACE_RECIPIENT, /* Recipient interface */
+ ENDPOINT_RECIPIENT, /* Recipient endpoint */
+ OTHER_RECIPIENT
+} RECIPIENT_TYPE;
+
+
+typedef enum _STANDARD_REQUESTS
+{
+ GET_STATUS = 0,
+ CLEAR_FEATURE,
+ RESERVED1,
+ SET_FEATURE,
+ RESERVED2,
+ SET_ADDRESS,
+ GET_DESCRIPTOR,
+ SET_DESCRIPTOR,
+ GET_CONFIGURATION,
+ SET_CONFIGURATION,
+ GET_INTERFACE,
+ SET_INTERFACE,
+ TOTAL_sREQUEST, /* Total number of Standard request */
+ SYNCH_FRAME = 12
+} STANDARD_REQUESTS;
+
+/* Definition of "USBwValue" */
+typedef enum _DESCRIPTOR_TYPE
+{
+ DEVICE_DESCRIPTOR = 1,
+ CONFIG_DESCRIPTOR,
+ STRING_DESCRIPTOR,
+ INTERFACE_DESCRIPTOR,
+ ENDPOINT_DESCRIPTOR
+} DESCRIPTOR_TYPE;
+
+/* Feature selector of a SET_FEATURE or CLEAR_FEATURE */
+typedef enum _FEATURE_SELECTOR
+{
+ ENDPOINT_STALL,
+ DEVICE_REMOTE_WAKEUP
+} FEATURE_SELECTOR;
+
+/* Exported constants --------------------------------------------------------*/
+/* Definition of "USBbmRequestType" */
+#define REQUEST_TYPE 0x60 /* Mask to get request type */
+#define STANDARD_REQUEST 0x00 /* Standard request */
+#define CLASS_REQUEST 0x20 /* Class request */
+#define VENDOR_REQUEST 0x40 /* Vendor request */
+
+#define RECIPIENT 0x1F /* Mask to get recipient */
+
+/* Exported macro ------------------------------------------------------------*/
+/* Exported functions ------------------------------------------------------- */
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif /* __USB_DEF_H */
+
+/******************* (C) COPYRIGHT 2008 STMicroelectronics *****END OF FILE****/
diff --git a/libmaple/usb/usb_lib/usb_init.c b/libmaple/usb/usb_lib/usb_init.c
new file mode 100644
index 0000000..94f3a83
--- /dev/null
+++ b/libmaple/usb/usb_lib/usb_init.c
@@ -0,0 +1,64 @@
+/******************** (C) COPYRIGHT 2008 STMicroelectronics ********************
+* File Name : usb_init.c
+* Author : MCD Application Team
+* Version : V2.2.1
+* Date : 09/22/2008
+* Description : Initialization routines & global variables
+********************************************************************************
+* THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
+* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE TIME.
+* AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY DIRECT,
+* INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING FROM THE
+* CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE CODING
+* INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
+*******************************************************************************/
+
+/* Includes ------------------------------------------------------------------*/
+#include "usb_lib.h"
+
+/* Private typedef -----------------------------------------------------------*/
+/* Private define ------------------------------------------------------------*/
+/* Private macro -------------------------------------------------------------*/
+/* Private variables ---------------------------------------------------------*/
+/* The number of current endpoint, it will be used to specify an endpoint */
+ u8 EPindex;
+/* The number of current device, it is an index to the Device_Table */
+/* u8 Device_no; */
+/* Points to the DEVICE_INFO structure of current device */
+/* The purpose of this register is to speed up the execution */
+DEVICE_INFO *pInformation;
+/* Points to the DEVICE_PROP structure of current device */
+/* The purpose of this register is to speed up the execution */
+DEVICE_PROP *pProperty;
+/* Temporary save the state of Rx & Tx status. */
+/* Whenever the Rx or Tx state is changed, its value is saved */
+/* in this variable first and will be set to the EPRB or EPRA */
+/* at the end of interrupt process */
+u16 SaveState ;
+u16 wInterrupt_Mask;
+DEVICE_INFO Device_Info;
+USER_STANDARD_REQUESTS *pUser_Standard_Requests;
+
+/* Extern variables ----------------------------------------------------------*/
+/* Private function prototypes -----------------------------------------------*/
+/* Private functions ---------------------------------------------------------*/
+
+/*******************************************************************************
+* Function Name : USB_Init
+* Description : USB system initialization
+* Input : None.
+* Output : None.
+* Return : None.
+*******************************************************************************/
+void USB_Init(void)
+{
+ pInformation = &Device_Info;
+ pInformation->ControlState = 2;
+ pProperty = &Device_Property;
+ pUser_Standard_Requests = &User_Standard_Requests;
+ /* Initialize devices one by one */
+
+ pProperty->Init();
+}
+
+/******************* (C) COPYRIGHT 2008 STMicroelectronics *****END OF FILE****/
diff --git a/libmaple/usb/usb_lib/usb_init.h b/libmaple/usb/usb_lib/usb_init.h
new file mode 100644
index 0000000..80ee2fb
--- /dev/null
+++ b/libmaple/usb/usb_lib/usb_init.h
@@ -0,0 +1,57 @@
+/******************** (C) COPYRIGHT 2008 STMicroelectronics ********************
+* File Name : usb_init.h
+* Author : MCD Application Team
+* Version : V2.2.1
+* Date : 09/22/2008
+* Description : Initialization routines & global variables
+********************************************************************************
+* THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
+* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE TIME.
+* AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY DIRECT,
+* INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING FROM THE
+* CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE CODING
+* INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
+*******************************************************************************/
+
+/* Define to prevent recursive inclusion -------------------------------------*/
+#ifndef __USB_INIT_H
+#define __USB_INIT_H
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+/* Includes ------------------------------------------------------------------*/
+/* Exported types ------------------------------------------------------------*/
+/* Exported constants --------------------------------------------------------*/
+/* Exported macro ------------------------------------------------------------*/
+/* Exported functions ------------------------------------------------------- */
+void USB_Init(void);
+
+/* External variables --------------------------------------------------------*/
+/* The number of current endpoint, it will be used to specify an endpoint */
+extern u8 EPindex;
+/* The number of current device, it is an index to the Device_Table */
+/*extern u8 Device_no; */
+/* Points to the DEVICE_INFO structure of current device */
+/* The purpose of this register is to speed up the execution */
+extern DEVICE_INFO* pInformation;
+/* Points to the DEVICE_PROP structure of current device */
+/* The purpose of this register is to speed up the execution */
+extern DEVICE_PROP* pProperty;
+/* Temporary save the state of Rx & Tx status. */
+/* Whenever the Rx or Tx state is changed, its value is saved */
+/* in this variable first and will be set to the EPRB or EPRA */
+/* at the end of interrupt process */
+extern USER_STANDARD_REQUESTS *pUser_Standard_Requests;
+
+extern u16 SaveState ;
+extern u16 wInterrupt_Mask;
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif /* __USB_INIT_H */
+
+/******************* (C) COPYRIGHT 2008 STMicroelectronics *****END OF FILE****/
diff --git a/libmaple/usb/usb_lib/usb_lib.h b/libmaple/usb/usb_lib/usb_lib.h
new file mode 100644
index 0000000..85f94ab
--- /dev/null
+++ b/libmaple/usb/usb_lib/usb_lib.h
@@ -0,0 +1,36 @@
+/******************** (C) COPYRIGHT 2008 STMicroelectronics ********************
+* File Name : usb_lib.h
+* Author : MCD Application Team
+* Version : V2.2.1
+* Date : 09/22/2008
+* Description : USB library include files
+********************************************************************************
+* THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
+* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE TIME.
+* AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY DIRECT,
+* INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING FROM THE
+* CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE CODING
+* INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
+*******************************************************************************/
+
+/* Define to prevent recursive inclusion -------------------------------------*/
+#ifndef __USB_LIB_H
+#define __USB_LIB_H
+
+/* Includes ------------------------------------------------------------------*/
+#include "usb_type.h"
+#include "usb_regs.h"
+#include "usb_def.h"
+#include "usb_core.h"
+#include "usb_init.h"
+#include "usb_mem.h"
+
+/* Exported types ------------------------------------------------------------*/
+/* Exported constants --------------------------------------------------------*/
+/* Exported macro ------------------------------------------------------------*/
+/* Exported functions ------------------------------------------------------- */
+/* External variables --------------------------------------------------------*/
+
+#endif /* __USB_LIB_H */
+
+/******************* (C) COPYRIGHT 2008 STMicroelectronics *****END OF FILE****/
diff --git a/libmaple/usb/usb_lib/usb_mem.c b/libmaple/usb/usb_lib/usb_mem.c
new file mode 100644
index 0000000..ad9740a
--- /dev/null
+++ b/libmaple/usb/usb_lib/usb_mem.c
@@ -0,0 +1,73 @@
+/******************** (C) COPYRIGHT 2008 STMicroelectronics ********************
+* File Name : usb_mem.c
+* Author : MCD Application Team
+* Version : V2.2.1
+* Date : 09/22/2008
+* Description : Utility functions for memory transfers to/from PMA
+********************************************************************************
+* THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
+* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE TIME.
+* AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY DIRECT,
+* INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING FROM THE
+* CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE CODING
+* INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
+*******************************************************************************/
+
+/* Includes ------------------------------------------------------------------*/
+#include "usb_lib.h"
+
+/* Private typedef -----------------------------------------------------------*/
+/* Private define ------------------------------------------------------------*/
+/* Private macro -------------------------------------------------------------*/
+/* Private variables ---------------------------------------------------------*/
+/* Extern variables ----------------------------------------------------------*/
+/* Private function prototypes -----------------------------------------------*/
+/* Private functions ---------------------------------------------------------*/
+/*******************************************************************************
+* Function Name : UserToPMABufferCopy
+* Description : Copy a buffer from user memory area to packet memory area (PMA)
+* Input : - pbUsrBuf: pointer to user memory area.
+* - wPMABufAddr: address into PMA.
+* - wNBytes: no. of bytes to be copied.
+* Output : None.
+* Return : None .
+*******************************************************************************/
+void UserToPMABufferCopy(const u8 *pbUsrBuf, u16 wPMABufAddr, u16 wNBytes)
+{
+ u32 n = (wNBytes + 1) >> 1; /* n = (wNBytes + 1) / 2 */
+ u32 i, temp1, temp2;
+ u16 *pdwVal;
+ pdwVal = (u16 *)(wPMABufAddr * 2 + PMAAddr);
+ for (i = n; i != 0; i--)
+ {
+ temp1 = (u16) * pbUsrBuf;
+ pbUsrBuf++;
+ temp2 = temp1 | (u16) * pbUsrBuf << 8;
+ *pdwVal++ = temp2;
+ pdwVal++;
+ pbUsrBuf++;
+ }
+}
+/*******************************************************************************
+* Function Name : PMAToUserBufferCopy
+* Description : Copy a buffer from user memory area to packet memory area (PMA)
+* Input : - pbUsrBuf = pointer to user memory area.
+* - wPMABufAddr = address into PMA.
+* - wNBytes = no. of bytes to be copied.
+* Output : None.
+* Return : None.
+*******************************************************************************/
+void PMAToUserBufferCopy(u8 *pbUsrBuf, u16 wPMABufAddr, u16 wNBytes)
+{
+ u32 n = (wNBytes + 1) >> 1;/* /2*/
+ u32 i;
+ u32 *pdwVal;
+ pdwVal = (u32 *)(wPMABufAddr * 2 + PMAAddr);
+ for (i = n; i != 0; i--)
+ {
+ *(u16*)pbUsrBuf++ = *pdwVal++;
+ pbUsrBuf++;
+ }
+}
+
+/******************* (C) COPYRIGHT 2008 STMicroelectronics *****END OF FILE****/
diff --git a/libmaple/usb/usb_lib/usb_mem.h b/libmaple/usb/usb_lib/usb_mem.h
new file mode 100644
index 0000000..b0e0474
--- /dev/null
+++ b/libmaple/usb/usb_lib/usb_mem.h
@@ -0,0 +1,40 @@
+/******************** (C) COPYRIGHT 2008 STMicroelectronics ********************
+* File Name : usb_mem.h
+* Author : MCD Application Team
+* Version : V2.2.1
+* Date : 09/22/2008
+* Description : Utility prototypes functions for memory/PMA transfers
+********************************************************************************
+* THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
+* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE TIME.
+* AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY DIRECT,
+* INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING FROM THE
+* CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE CODING
+* INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
+*******************************************************************************/
+
+/* Define to prevent recursive inclusion -------------------------------------*/
+#ifndef __USB_MEM_H
+#define __USB_MEM_H
+
+/* Includes ------------------------------------------------------------------*/
+/* Exported types ------------------------------------------------------------*/
+/* Exported constants --------------------------------------------------------*/
+/* Exported macro ------------------------------------------------------------*/
+/* Exported functions ------------------------------------------------------- */
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+void UserToPMABufferCopy(const u8 *pbUsrBuf, u16 wPMABufAddr, u16 wNBytes);
+void PMAToUserBufferCopy(u8 *pbUsrBuf, u16 wPMABufAddr, u16 wNBytes);
+
+#if defined(__cplusplus)
+}
+#endif
+
+/* External variables --------------------------------------------------------*/
+
+#endif /*__USB_MEM_H*/
+
+/******************* (C) COPYRIGHT 2008 STMicroelectronics *****END OF FILE****/
diff --git a/libmaple/usb/usb_lib/usb_regs.c b/libmaple/usb/usb_lib/usb_regs.c
new file mode 100644
index 0000000..c7e0276
--- /dev/null
+++ b/libmaple/usb/usb_lib/usb_regs.c
@@ -0,0 +1,748 @@
+/******************** (C) COPYRIGHT 2008 STMicroelectronics ********************
+* File Name : usb_regs.c
+* Author : MCD Application Team
+* Version : V2.2.1
+* Date : 09/22/2008
+* Description : Interface functions to USB cell registers
+********************************************************************************
+* THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
+* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE TIME.
+* AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY DIRECT,
+* INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING FROM THE
+* CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE CODING
+* INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
+*******************************************************************************/
+
+/* Includes ------------------------------------------------------------------*/
+#include "usb_lib.h"
+
+/* Private typedef -----------------------------------------------------------*/
+/* Private define ------------------------------------------------------------*/
+/* Private macro -------------------------------------------------------------*/
+/* Private variables ---------------------------------------------------------*/
+/* Extern variables ----------------------------------------------------------*/
+/* Private function prototypes -----------------------------------------------*/
+/* Private functions ---------------------------------------------------------*/
+
+/*******************************************************************************
+* Function Name : SetCNTR.
+* Description : Set the CNTR register value.
+* Input : wRegValue: new register value.
+* Output : None.
+* Return : None.
+*******************************************************************************/
+void SetCNTR(u16 wRegValue)
+{
+ _SetCNTR(wRegValue);
+}
+
+/*******************************************************************************
+* Function Name : GetCNTR.
+* Description : returns the CNTR register value.
+* Input : None.
+* Output : None.
+* Return : CNTR register Value.
+*******************************************************************************/
+u16 GetCNTR(void)
+{
+ return(_GetCNTR());
+}
+
+/*******************************************************************************
+* Function Name : SetISTR.
+* Description : Set the ISTR register value.
+* Input : wRegValue: new register value.
+* Output : None.
+* Return : None.
+*******************************************************************************/
+void SetISTR(u16 wRegValue)
+{
+ _SetISTR(wRegValue);
+}
+
+/*******************************************************************************
+* Function Name : GetISTR
+* Description : Returns the ISTR register value.
+* Input : None.
+* Output : None.
+* Return : ISTR register Value
+*******************************************************************************/
+u16 GetISTR(void)
+{
+ return(_GetISTR());
+}
+
+/*******************************************************************************
+* Function Name : GetFNR
+* Description : Returns the FNR register value.
+* Input : None.
+* Output : None.
+* Return : FNR register Value
+*******************************************************************************/
+u16 GetFNR(void)
+{
+ return(_GetFNR());
+}
+
+/*******************************************************************************
+* Function Name : SetDADDR
+* Description : Set the DADDR register value.
+* Input : wRegValue: new register value.
+* Output : None.
+* Return : None.
+*******************************************************************************/
+void SetDADDR(u16 wRegValue)
+{
+ _SetDADDR(wRegValue);
+}
+
+/*******************************************************************************
+* Function Name : GetDADDR
+* Description : Returns the DADDR register value.
+* Input : None.
+* Output : None.
+* Return : DADDR register Value
+*******************************************************************************/
+u16 GetDADDR(void)
+{
+ return(_GetDADDR());
+}
+
+/*******************************************************************************
+* Function Name : SetBTABLE
+* Description : Set the BTABLE.
+* Input : wRegValue: New register value.
+* Output : None.
+* Return : None.
+*******************************************************************************/
+void SetBTABLE(u16 wRegValue)
+{
+ _SetBTABLE(wRegValue);
+}
+
+/*******************************************************************************
+* Function Name : GetBTABLE.
+* Description : Returns the BTABLE register value.
+* Input : None.
+* Output : None.
+* Return : BTABLE address.
+*******************************************************************************/
+u16 GetBTABLE(void)
+{
+ return(_GetBTABLE());
+}
+
+/*******************************************************************************
+* Function Name : SetENDPOINT
+* Description : Setthe Endpoint register value.
+* Input : bEpNum: Endpoint Number.
+* wRegValue.
+* Output : None.
+* Return : None.
+*******************************************************************************/
+void SetENDPOINT(u8 bEpNum, u16 wRegValue)
+{
+ _SetENDPOINT(bEpNum, wRegValue);
+}
+
+/*******************************************************************************
+* Function Name : GetENDPOINT
+* Description : Return the Endpoint register value.
+* Input : bEpNum: Endpoint Number.
+* Output : None.
+* Return : Endpoint register value.
+*******************************************************************************/
+u16 GetENDPOINT(u8 bEpNum)
+{
+ return(_GetENDPOINT(bEpNum));
+}
+
+/*******************************************************************************
+* Function Name : SetEPType
+* Description : sets the type in the endpoint register.
+* Input : bEpNum: Endpoint Number.
+* wType: type definition.
+* Output : None.
+* Return : None.
+*******************************************************************************/
+void SetEPType(u8 bEpNum, u16 wType)
+{
+ _SetEPType(bEpNum, wType);
+}
+
+/*******************************************************************************
+* Function Name : GetEPType
+* Description : Returns the endpoint type.
+* Input : bEpNum: Endpoint Number.
+* Output : None.
+* Return : Endpoint Type
+*******************************************************************************/
+u16 GetEPType(u8 bEpNum)
+{
+ return(_GetEPType(bEpNum));
+}
+
+/*******************************************************************************
+* Function Name : SetEPTxStatus
+* Description : Set the status of Tx endpoint.
+* Input : bEpNum: Endpoint Number.
+* wState: new state.
+* Output : None.
+* Return : None.
+*******************************************************************************/
+void SetEPTxStatus(u8 bEpNum, u16 wState)
+{
+ _SetEPTxStatus(bEpNum, wState);
+}
+
+/*******************************************************************************
+* Function Name : SetEPRxStatus
+* Description : Set the status of Rx endpoint.
+* Input : bEpNum: Endpoint Number.
+* wState: new state.
+* Output : None.
+* Return : None.
+*******************************************************************************/
+void SetEPRxStatus(u8 bEpNum, u16 wState)
+{
+ _SetEPRxStatus(bEpNum, wState);
+}
+
+/*******************************************************************************
+* Function Name : SetDouBleBuffEPStall
+* Description : sets the status for Double Buffer Endpoint to STALL
+* Input : bEpNum: Endpoint Number.
+* bDir: Endpoint direction.
+* Output : None.
+* Return : None.
+*******************************************************************************/
+void SetDouBleBuffEPStall(u8 bEpNum, u8 bDir)
+{
+ u16 Endpoint_DTOG_Status;
+ Endpoint_DTOG_Status = GetENDPOINT(bEpNum);
+ if (bDir == EP_DBUF_OUT)
+ { /* OUT double buffered endpoint */
+ _SetENDPOINT(bEpNum, Endpoint_DTOG_Status & ~EPRX_DTOG1);
+ }
+ else if (bDir == EP_DBUF_IN)
+ { /* IN double buffered endpoint */
+ _SetENDPOINT(bEpNum, Endpoint_DTOG_Status & ~EPTX_DTOG1);
+ }
+}
+
+/*******************************************************************************
+* Function Name : GetEPTxStatus
+* Description : Returns the endpoint Tx status.
+* Input : bEpNum: Endpoint Number.
+* Output : None.
+* Return : Endpoint TX Status
+*******************************************************************************/
+u16 GetEPTxStatus(u8 bEpNum)
+{
+ return(_GetEPTxStatus(bEpNum));
+}
+
+/*******************************************************************************
+* Function Name : GetEPRxStatus
+* Description : Returns the endpoint Rx status.
+* Input : bEpNum: Endpoint Number.
+* Output : None.
+* Return : Endpoint RX Status
+*******************************************************************************/
+u16 GetEPRxStatus(u8 bEpNum)
+{
+ return(_GetEPRxStatus(bEpNum));
+}
+
+/*******************************************************************************
+* Function Name : SetEPTxValid
+* Description : Valid the endpoint Tx Status.
+* Input : bEpNum: Endpoint Number.
+* Output : None.
+* Return : None.
+*******************************************************************************/
+void SetEPTxValid(u8 bEpNum)
+{
+ _SetEPTxStatus(bEpNum, EP_TX_VALID);
+}
+
+/*******************************************************************************
+* Function Name : SetEPRxValid
+* Description : Valid the endpoint Rx Status.
+* Input : bEpNum: Endpoint Number.
+* Output : None.
+* Return : None.
+*******************************************************************************/
+void SetEPRxValid(u8 bEpNum)
+{
+ _SetEPRxStatus(bEpNum, EP_RX_VALID);
+}
+
+/*******************************************************************************
+* Function Name : SetEP_KIND
+* Description : Clear the EP_KIND bit.
+* Input : bEpNum: Endpoint Number.
+* Output : None.
+* Return : None.
+*******************************************************************************/
+void SetEP_KIND(u8 bEpNum)
+{
+ _SetEP_KIND(bEpNum);
+}
+
+/*******************************************************************************
+* Function Name : ClearEP_KIND
+* Description : set the EP_KIND bit.
+* Input : bEpNum: Endpoint Number.
+* Output : None.
+* Return : None.
+*******************************************************************************/
+void ClearEP_KIND(u8 bEpNum)
+{
+ _ClearEP_KIND(bEpNum);
+}
+/*******************************************************************************
+* Function Name : Clear_Status_Out
+* Description : Clear the Status Out of the related Endpoint
+* Input : bEpNum: Endpoint Number.
+* Output : None.
+* Return : None.
+*******************************************************************************/
+void Clear_Status_Out(u8 bEpNum)
+{
+ _ClearEP_KIND(bEpNum);
+}
+/*******************************************************************************
+* Function Name : Set_Status_Out
+* Description : Set the Status Out of the related Endpoint
+* Input : bEpNum: Endpoint Number.
+* Output : None.
+* Return : None.
+*******************************************************************************/
+void Set_Status_Out(u8 bEpNum)
+{
+ _SetEP_KIND(bEpNum);
+}
+/*******************************************************************************
+* Function Name : SetEPDoubleBuff
+* Description : Enable the double buffer feature for the endpoint.
+* Input : bEpNum: Endpoint Number.
+* Output : None.
+* Return : None.
+*******************************************************************************/
+void SetEPDoubleBuff(u8 bEpNum)
+{
+ _SetEP_KIND(bEpNum);
+}
+/*******************************************************************************
+* Function Name : ClearEPDoubleBuff
+* Description : Disable the double buffer feature for the endpoint.
+* Input : bEpNum: Endpoint Number.
+* Output : None.
+* Return : None.
+*******************************************************************************/
+void ClearEPDoubleBuff(u8 bEpNum)
+{
+ _ClearEP_KIND(bEpNum);
+}
+/*******************************************************************************
+* Function Name : GetTxStallStatus
+* Description : Returns the Stall status of the Tx endpoint.
+* Input : bEpNum: Endpoint Number.
+* Output : None.
+* Return : Tx Stall status.
+*******************************************************************************/
+u16 GetTxStallStatus(u8 bEpNum)
+{
+ return(_GetTxStallStatus(bEpNum));
+}
+/*******************************************************************************
+* Function Name : GetRxStallStatus
+* Description : Returns the Stall status of the Rx endpoint.
+* Input : bEpNum: Endpoint Number.
+* Output : None.
+* Return : Rx Stall status.
+*******************************************************************************/
+u16 GetRxStallStatus(u8 bEpNum)
+{
+ return(_GetRxStallStatus(bEpNum));
+}
+/*******************************************************************************
+* Function Name : ClearEP_CTR_RX
+* Description : Clear the CTR_RX bit.
+* Input : bEpNum: Endpoint Number.
+* Output : None.
+* Return : None.
+*******************************************************************************/
+void ClearEP_CTR_RX(u8 bEpNum)
+{
+ _ClearEP_CTR_RX(bEpNum);
+}
+/*******************************************************************************
+* Function Name : ClearEP_CTR_TX
+* Description : Clear the CTR_TX bit.
+* Input : bEpNum: Endpoint Number.
+* Output : None.
+* Return : None.
+*******************************************************************************/
+void ClearEP_CTR_TX(u8 bEpNum)
+{
+ _ClearEP_CTR_TX(bEpNum);
+}
+/*******************************************************************************
+* Function Name : ToggleDTOG_RX
+* Description : Toggle the DTOG_RX bit.
+* Input : bEpNum: Endpoint Number.
+* Output : None.
+* Return : None.
+*******************************************************************************/
+void ToggleDTOG_RX(u8 bEpNum)
+{
+ _ToggleDTOG_RX(bEpNum);
+}
+/*******************************************************************************
+* Function Name : ToggleDTOG_TX
+* Description : Toggle the DTOG_TX bit.
+* Input : bEpNum: Endpoint Number.
+* Output : None.
+* Return : None.
+*******************************************************************************/
+void ToggleDTOG_TX(u8 bEpNum)
+{
+ _ToggleDTOG_TX(bEpNum);
+}
+/*******************************************************************************
+* Function Name : ClearDTOG_RX.
+* Description : Clear the DTOG_RX bit.
+* Input : bEpNum: Endpoint Number.
+* Output : None.
+* Return : None.
+*******************************************************************************/
+void ClearDTOG_RX(u8 bEpNum)
+{
+ _ClearDTOG_RX(bEpNum);
+}
+/*******************************************************************************
+* Function Name : ClearDTOG_TX.
+* Description : Clear the DTOG_TX bit.
+* Input : bEpNum: Endpoint Number.
+* Output : None.
+* Return : None.
+*******************************************************************************/
+void ClearDTOG_TX(u8 bEpNum)
+{
+ _ClearDTOG_TX(bEpNum);
+}
+/*******************************************************************************
+* Function Name : SetEPAddress
+* Description : Set the endpoint address.
+* Input : bEpNum: Endpoint Number.
+* bAddr: New endpoint address.
+* Output : None.
+* Return : None.
+*******************************************************************************/
+void SetEPAddress(u8 bEpNum, u8 bAddr)
+{
+ _SetEPAddress(bEpNum, bAddr);
+}
+/*******************************************************************************
+* Function Name : GetEPAddress
+* Description : Get the endpoint address.
+* Input : bEpNum: Endpoint Number.
+* Output : None.
+* Return : Endpoint address.
+*******************************************************************************/
+u8 GetEPAddress(u8 bEpNum)
+{
+ return(_GetEPAddress(bEpNum));
+}
+/*******************************************************************************
+* Function Name : SetEPTxAddr
+* Description : Set the endpoint Tx buffer address.
+* Input : bEpNum: Endpoint Number.
+* wAddr: new address.
+* Output : None.
+* Return : None.
+*******************************************************************************/
+void SetEPTxAddr(u8 bEpNum, u16 wAddr)
+{
+ _SetEPTxAddr(bEpNum, wAddr);
+}
+/*******************************************************************************
+* Function Name : SetEPRxAddr
+* Description : Set the endpoint Rx buffer address.
+* Input : bEpNum: Endpoint Number.
+* wAddr: new address.
+* Output : None.
+* Return : None.
+*******************************************************************************/
+void SetEPRxAddr(u8 bEpNum, u16 wAddr)
+{
+ _SetEPRxAddr(bEpNum, wAddr);
+}
+/*******************************************************************************
+* Function Name : GetEPTxAddr
+* Description : Returns the endpoint Tx buffer address.
+* Input : bEpNum: Endpoint Number.
+* Output : None.
+* Return : Rx buffer address.
+*******************************************************************************/
+u16 GetEPTxAddr(u8 bEpNum)
+{
+ return(_GetEPTxAddr(bEpNum));
+}
+/*******************************************************************************
+* Function Name : GetEPRxAddr.
+* Description : Returns the endpoint Rx buffer address.
+* Input : bEpNum: Endpoint Number.
+* Output : None.
+* Return : Rx buffer address.
+*******************************************************************************/
+u16 GetEPRxAddr(u8 bEpNum)
+{
+ return(_GetEPRxAddr(bEpNum));
+}
+/*******************************************************************************
+* Function Name : SetEPTxCount.
+* Description : Set the Tx count.
+* Input : bEpNum: Endpoint Number.
+* wCount: new count value.
+* Output : None.
+* Return : None.
+*******************************************************************************/
+void SetEPTxCount(u8 bEpNum, u16 wCount)
+{
+ _SetEPTxCount(bEpNum, wCount);
+}
+/*******************************************************************************
+* Function Name : SetEPCountRxReg.
+* Description : Set the Count Rx Register value.
+* Input : *pdwReg: point to the register.
+* wCount: the new register value.
+* Output : None.
+* Return : None.
+*******************************************************************************/
+void SetEPCountRxReg(u32 *pdwReg, u16 wCount)
+{
+ _SetEPCountRxReg(dwReg, wCount);
+}
+/*******************************************************************************
+* Function Name : SetEPRxCount
+* Description : Set the Rx count.
+* Input : bEpNum: Endpoint Number.
+* wCount: the new count value.
+* Output : None.
+* Return : None.
+*******************************************************************************/
+void SetEPRxCount(u8 bEpNum, u16 wCount)
+{
+ _SetEPRxCount(bEpNum, wCount);
+}
+/*******************************************************************************
+* Function Name : GetEPTxCount
+* Description : Get the Tx count.
+* Input : bEpNum: Endpoint Number.
+* Output : None
+* Return : Tx count value.
+*******************************************************************************/
+u16 GetEPTxCount(u8 bEpNum)
+{
+ return(_GetEPTxCount(bEpNum));
+}
+/*******************************************************************************
+* Function Name : GetEPRxCount
+* Description : Get the Rx count.
+* Input : bEpNum: Endpoint Number.
+* Output : None.
+* Return : Rx count value.
+*******************************************************************************/
+u16 GetEPRxCount(u8 bEpNum)
+{
+ return(_GetEPRxCount(bEpNum));
+}
+/*******************************************************************************
+* Function Name : SetEPDblBuffAddr
+* Description : Set the addresses of the buffer 0 and 1.
+* Input : bEpNum: Endpoint Number.
+* wBuf0Addr: new address of buffer 0.
+* wBuf1Addr: new address of buffer 1.
+* Output : None.
+* Return : None.
+*******************************************************************************/
+void SetEPDblBuffAddr(u8 bEpNum, u16 wBuf0Addr, u16 wBuf1Addr)
+{
+ _SetEPDblBuffAddr(bEpNum, wBuf0Addr, wBuf1Addr);
+}
+/*******************************************************************************
+* Function Name : SetEPDblBuf0Addr
+* Description : Set the Buffer 1 address.
+* Input : bEpNum: Endpoint Number
+* wBuf0Addr: new address.
+* Output : None.
+* Return : None.
+*******************************************************************************/
+void SetEPDblBuf0Addr(u8 bEpNum, u16 wBuf0Addr)
+{
+ _SetEPDblBuf0Addr(bEpNum, wBuf0Addr);
+}
+/*******************************************************************************
+* Function Name : SetEPDblBuf1Addr
+* Description : Set the Buffer 1 address.
+* Input : bEpNum: Endpoint Number
+* wBuf1Addr: new address.
+* Output : None.
+* Return : None.
+*******************************************************************************/
+void SetEPDblBuf1Addr(u8 bEpNum, u16 wBuf1Addr)
+{
+ _SetEPDblBuf1Addr(bEpNum, wBuf1Addr);
+}
+/*******************************************************************************
+* Function Name : GetEPDblBuf0Addr
+* Description : Returns the address of the Buffer 0.
+* Input : bEpNum: Endpoint Number.
+* Output : None.
+* Return : None.
+*******************************************************************************/
+u16 GetEPDblBuf0Addr(u8 bEpNum)
+{
+ return(_GetEPDblBuf0Addr(bEpNum));
+}
+/*******************************************************************************
+* Function Name : GetEPDblBuf1Addr
+* Description : Returns the address of the Buffer 1.
+* Input : bEpNum: Endpoint Number.
+* Output : None.
+* Return : Address of the Buffer 1.
+*******************************************************************************/
+u16 GetEPDblBuf1Addr(u8 bEpNum)
+{
+ return(_GetEPDblBuf1Addr(bEpNum));
+}
+/*******************************************************************************
+* Function Name : SetEPDblBuffCount
+* Description : Set the number of bytes for a double Buffer
+* endpoint.
+* Input : bEpNum,bDir, wCount
+* Output : None.
+* Return : None.
+*******************************************************************************/
+void SetEPDblBuffCount(u8 bEpNum, u8 bDir, u16 wCount)
+{
+ _SetEPDblBuffCount(bEpNum, bDir, wCount);
+}
+/*******************************************************************************
+* Function Name : SetEPDblBuf0Count
+* Description : Set the number of bytes in the buffer 0 of a double Buffer
+* endpoint.
+* Input : bEpNum, bDir, wCount
+* Output : None.
+* Return : None.
+*******************************************************************************/
+void SetEPDblBuf0Count(u8 bEpNum, u8 bDir, u16 wCount)
+{
+ _SetEPDblBuf0Count(bEpNum, bDir, wCount);
+}
+/*******************************************************************************
+* Function Name : SetEPDblBuf1Count
+* Description : Set the number of bytes in the buffer 0 of a double Buffer
+* endpoint.
+* Input : bEpNum, bDir, wCount
+* Output : None.
+* Return : None.
+*******************************************************************************/
+void SetEPDblBuf1Count(u8 bEpNum, u8 bDir, u16 wCount)
+{
+ _SetEPDblBuf1Count(bEpNum, bDir, wCount);
+}
+/*******************************************************************************
+* Function Name : GetEPDblBuf0Count
+* Description : Returns the number of byte received in the buffer 0 of a double
+* Buffer endpoint.
+* Input : bEpNum: Endpoint Number.
+* Output : None.
+* Return : Endpoint Buffer 0 count
+*******************************************************************************/
+u16 GetEPDblBuf0Count(u8 bEpNum)
+{
+ return(_GetEPDblBuf0Count(bEpNum));
+}
+/*******************************************************************************
+* Function Name : GetEPDblBuf1Count
+* Description : Returns the number of data received in the buffer 1 of a double
+* Buffer endpoint.
+* Input : bEpNum: Endpoint Number.
+* Output : None.
+* Return : Endpoint Buffer 1 count.
+*******************************************************************************/
+u16 GetEPDblBuf1Count(u8 bEpNum)
+{
+ return(_GetEPDblBuf1Count(bEpNum));
+}
+/*******************************************************************************
+* Function Name : GetEPDblBufDir
+* Description : gets direction of the double buffered endpoint
+* Input : bEpNum: Endpoint Number.
+* Output : None.
+* Return : EP_DBUF_OUT, EP_DBUF_IN,
+* EP_DBUF_ERR if the endpoint counter not yet programmed.
+*******************************************************************************/
+EP_DBUF_DIR GetEPDblBufDir(u8 bEpNum)
+{
+ if ((u16)(*_pEPRxCount(bEpNum) & 0xFC00) != 0)
+ return(EP_DBUF_OUT);
+ else if (((u16)(*_pEPTxCount(bEpNum)) & 0x03FF) != 0)
+ return(EP_DBUF_IN);
+ else
+ return(EP_DBUF_ERR);
+}
+/*******************************************************************************
+* Function Name : FreeUserBuffer
+* Description : free buffer used from the application realizing it to the line
+ toggles bit SW_BUF in the double buffered endpoint register
+* Input : bEpNum, bDir
+* Output : None.
+* Return : None.
+*******************************************************************************/
+void FreeUserBuffer(u8 bEpNum, u8 bDir)
+{
+ if (bDir == EP_DBUF_OUT)
+ { /* OUT double buffered endpoint */
+ _ToggleDTOG_TX(bEpNum);
+ }
+ else if (bDir == EP_DBUF_IN)
+ { /* IN double buffered endpoint */
+ _ToggleDTOG_RX(bEpNum);
+ }
+}
+
+/*******************************************************************************
+* Function Name : ToWord
+* Description : merge two byte in a word.
+* Input : bh: byte high, bl: bytes low.
+* Output : None.
+* Return : resulted word.
+*******************************************************************************/
+u16 ToWord(u8 bh, u8 bl)
+{
+ u16 wRet;
+ wRet = (u16)bl | ((u16)bh << 8);
+ return(wRet);
+}
+/*******************************************************************************
+* Function Name : ByteSwap
+* Description : Swap two byte in a word.
+* Input : wSwW: word to Swap.
+* Output : None.
+* Return : resulted word.
+*******************************************************************************/
+u16 ByteSwap(u16 wSwW)
+{
+ u8 bTemp;
+ u16 wRet;
+ bTemp = (u8)(wSwW & 0xff);
+ wRet = (wSwW >> 8) | ((u16)bTemp << 8);
+ return(wRet);
+}
+
+/******************* (C) COPYRIGHT 2008 STMicroelectronics *****END OF FILE****/
diff --git a/libmaple/usb/usb_lib/usb_regs.h b/libmaple/usb/usb_lib/usb_regs.h
new file mode 100644
index 0000000..b63cc5f
--- /dev/null
+++ b/libmaple/usb/usb_lib/usb_regs.h
@@ -0,0 +1,627 @@
+/******************** (C) COPYRIGHT 2008 STMicroelectronics ********************
+* File Name : usb_regs.h
+* Author : MCD Application Team
+* Version : V2.2.1
+* Date : 09/22/2008
+* Description : Interface prototype functions to USB cell registers
+********************************************************************************
+* THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
+* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE TIME.
+* AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY DIRECT,
+* INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING FROM THE
+* CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE CODING
+* INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
+*******************************************************************************/
+
+/* Define to prevent recursive inclusion -------------------------------------*/
+#ifndef __USB_REGS_H
+#define __USB_REGS_H
+
+/* Includes ------------------------------------------------------------------*/
+/* Exported types ------------------------------------------------------------*/
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+typedef enum _EP_DBUF_DIR
+{
+ /* double buffered endpoint direction */
+ EP_DBUF_ERR,
+ EP_DBUF_OUT,
+ EP_DBUF_IN
+}EP_DBUF_DIR;
+
+/* endpoint buffer number */
+enum EP_BUF_NUM
+{
+ EP_NOBUF,
+ EP_BUF0,
+ EP_BUF1
+};
+
+/* Exported constants --------------------------------------------------------*/
+#define RegBase (0x40005C00L) /* USB_IP Peripheral Registers base address */
+#define PMAAddr (0x40006000L) /* USB_IP Packet Memory Area base address */
+
+/******************************************************************************/
+/* General registers */
+/******************************************************************************/
+
+/* Control register */
+#define CNTR ((volatile unsigned *)(RegBase + 0x40))
+/* Interrupt status register */
+#define ISTR ((volatile unsigned *)(RegBase + 0x44))
+/* Frame number register */
+#define FNR ((volatile unsigned *)(RegBase + 0x48))
+/* Device address register */
+#define DADDR ((volatile unsigned *)(RegBase + 0x4C))
+/* Buffer Table address register */
+#define BTABLE ((volatile unsigned *)(RegBase + 0x50))
+/******************************************************************************/
+/* Endpoint registers */
+/******************************************************************************/
+#define EP0REG ((volatile unsigned *)(RegBase)) /* endpoint 0 register address */
+
+/* endpoints enumeration */
+#define ENDP0 ((u8)0)
+#define ENDP1 ((u8)1)
+#define ENDP2 ((u8)2)
+#define ENDP3 ((u8)3)
+#define ENDP4 ((u8)4)
+#define ENDP5 ((u8)5)
+#define ENDP6 ((u8)6)
+#define ENDP7 ((u8)7)
+/******************************************************************************/
+/* ISTR interrupt events */
+/******************************************************************************/
+#define ISTR_CTR (0x8000) /* Correct TRansfer (clear-only bit) */
+#define ISTR_DOVR (0x4000) /* DMA OVeR/underrun (clear-only bit) */
+#define ISTR_ERR (0x2000) /* ERRor (clear-only bit) */
+#define ISTR_WKUP (0x1000) /* WaKe UP (clear-only bit) */
+#define ISTR_SUSP (0x0800) /* SUSPend (clear-only bit) */
+#define ISTR_RESET (0x0400) /* RESET (clear-only bit) */
+#define ISTR_SOF (0x0200) /* Start Of Frame (clear-only bit) */
+#define ISTR_ESOF (0x0100) /* Expected Start Of Frame (clear-only bit) */
+
+
+#define ISTR_DIR (0x0010) /* DIRection of transaction (read-only bit) */
+#define ISTR_EP_ID (0x000F) /* EndPoint IDentifier (read-only bit) */
+
+#define CLR_CTR (~ISTR_CTR) /* clear Correct TRansfer bit */
+#define CLR_DOVR (~ISTR_DOVR) /* clear DMA OVeR/underrun bit*/
+#define CLR_ERR (~ISTR_ERR) /* clear ERRor bit */
+#define CLR_WKUP (~ISTR_WKUP) /* clear WaKe UP bit */
+#define CLR_SUSP (~ISTR_SUSP) /* clear SUSPend bit */
+#define CLR_RESET (~ISTR_RESET) /* clear RESET bit */
+#define CLR_SOF (~ISTR_SOF) /* clear Start Of Frame bit */
+#define CLR_ESOF (~ISTR_ESOF) /* clear Expected Start Of Frame bit */
+
+/******************************************************************************/
+/* CNTR control register bits definitions */
+/******************************************************************************/
+#define CNTR_CTRM (0x8000) /* Correct TRansfer Mask */
+#define CNTR_DOVRM (0x4000) /* DMA OVeR/underrun Mask */
+#define CNTR_ERRM (0x2000) /* ERRor Mask */
+#define CNTR_WKUPM (0x1000) /* WaKe UP Mask */
+#define CNTR_SUSPM (0x0800) /* SUSPend Mask */
+#define CNTR_RESETM (0x0400) /* RESET Mask */
+#define CNTR_SOFM (0x0200) /* Start Of Frame Mask */
+#define CNTR_ESOFM (0x0100) /* Expected Start Of Frame Mask */
+
+
+#define CNTR_RESUME (0x0010) /* RESUME request */
+#define CNTR_FSUSP (0x0008) /* Force SUSPend */
+#define CNTR_LPMODE (0x0004) /* Low-power MODE */
+#define CNTR_PDWN (0x0002) /* Power DoWN */
+#define CNTR_FRES (0x0001) /* Force USB RESet */
+
+/******************************************************************************/
+/* FNR Frame Number Register bit definitions */
+/******************************************************************************/
+#define FNR_RXDP (0x8000) /* status of D+ data line */
+#define FNR_RXDM (0x4000) /* status of D- data line */
+#define FNR_LCK (0x2000) /* LoCKed */
+#define FNR_LSOF (0x1800) /* Lost SOF */
+#define FNR_FN (0x07FF) /* Frame Number */
+/******************************************************************************/
+/* DADDR Device ADDRess bit definitions */
+/******************************************************************************/
+#define DADDR_EF (0x80)
+#define DADDR_ADD (0x7F)
+/******************************************************************************/
+/* Endpoint register */
+/******************************************************************************/
+/* bit positions */
+#define EP_CTR_RX (0x8000) /* EndPoint Correct TRansfer RX */
+#define EP_DTOG_RX (0x4000) /* EndPoint Data TOGGLE RX */
+#define EPRX_STAT (0x3000) /* EndPoint RX STATus bit field */
+#define EP_SETUP (0x0800) /* EndPoint SETUP */
+#define EP_T_FIELD (0x0600) /* EndPoint TYPE */
+#define EP_KIND (0x0100) /* EndPoint KIND */
+#define EP_CTR_TX (0x0080) /* EndPoint Correct TRansfer TX */
+#define EP_DTOG_TX (0x0040) /* EndPoint Data TOGGLE TX */
+#define EPTX_STAT (0x0030) /* EndPoint TX STATus bit field */
+#define EPADDR_FIELD (0x000F) /* EndPoint ADDRess FIELD */
+
+/* EndPoint REGister MASK (no toggle fields) */
+#define EPREG_MASK (EP_CTR_RX|EP_SETUP|EP_T_FIELD|EP_KIND|EP_CTR_TX|EPADDR_FIELD)
+
+/* EP_TYPE[1:0] EndPoint TYPE */
+#define EP_TYPE_MASK (0x0600) /* EndPoint TYPE Mask */
+#define EP_BULK (0x0000) /* EndPoint BULK */
+#define EP_CONTROL (0x0200) /* EndPoint CONTROL */
+#define EP_ISOCHRONOUS (0x0400) /* EndPoint ISOCHRONOUS */
+#define EP_INTERRUPT (0x0600) /* EndPoint INTERRUPT */
+#define EP_T_MASK (~EP_T_FIELD & EPREG_MASK)
+
+
+/* EP_KIND EndPoint KIND */
+#define EPKIND_MASK (~EP_KIND & EPREG_MASK)
+
+/* STAT_TX[1:0] STATus for TX transfer */
+#define EP_TX_DIS (0x0000) /* EndPoint TX DISabled */
+#define EP_TX_STALL (0x0010) /* EndPoint TX STALLed */
+#define EP_TX_NAK (0x0020) /* EndPoint TX NAKed */
+#define EP_TX_VALID (0x0030) /* EndPoint TX VALID */
+#define EPTX_DTOG1 (0x0010) /* EndPoint TX Data TOGgle bit1 */
+#define EPTX_DTOG2 (0x0020) /* EndPoint TX Data TOGgle bit2 */
+#define EPTX_DTOGMASK (EPTX_STAT|EPREG_MASK)
+
+/* STAT_RX[1:0] STATus for RX transfer */
+#define EP_RX_DIS (0x0000) /* EndPoint RX DISabled */
+#define EP_RX_STALL (0x1000) /* EndPoint RX STALLed */
+#define EP_RX_NAK (0x2000) /* EndPoint RX NAKed */
+#define EP_RX_VALID (0x3000) /* EndPoint RX VALID */
+#define EPRX_DTOG1 (0x1000) /* EndPoint RX Data TOGgle bit1 */
+#define EPRX_DTOG2 (0x2000) /* EndPoint RX Data TOGgle bit1 */
+#define EPRX_DTOGMASK (EPRX_STAT|EPREG_MASK)
+/* Exported macro ------------------------------------------------------------*/
+/* SetCNTR */
+#define _SetCNTR(wRegValue) (*CNTR = (u16)wRegValue)
+
+/* SetISTR */
+#define _SetISTR(wRegValue) (*ISTR = (u16)wRegValue)
+
+/* SetDADDR */
+#define _SetDADDR(wRegValue) (*DADDR = (u16)wRegValue)
+
+/* SetBTABLE */
+#define _SetBTABLE(wRegValue)(*BTABLE = (u16)(wRegValue & 0xFFF8))
+
+/* GetCNTR */
+#define _GetCNTR() ((u16) *CNTR)
+
+/* GetISTR */
+#define _GetISTR() ((u16) *ISTR)
+
+/* GetFNR */
+#define _GetFNR() ((u16) *FNR)
+
+/* GetDADDR */
+#define _GetDADDR() ((u16) *DADDR)
+
+/* GetBTABLE */
+#define _GetBTABLE() ((u16) *BTABLE)
+
+/* SetENDPOINT */
+#define _SetENDPOINT(bEpNum,wRegValue) (*(EP0REG + bEpNum)= \
+ (u16)wRegValue)
+
+/* GetENDPOINT */
+#define _GetENDPOINT(bEpNum) ((u16)(*(EP0REG + bEpNum)))
+
+/*******************************************************************************
+* Macro Name : SetEPType
+* Description : sets the type in the endpoint register(bits EP_TYPE[1:0])
+* Input : bEpNum: Endpoint Number.
+* wType
+* Output : None.
+* Return : None.
+*******************************************************************************/
+#define _SetEPType(bEpNum,wType) (_SetENDPOINT(bEpNum,\
+ ((_GetENDPOINT(bEpNum) & EP_T_MASK) | wType)))
+
+/*******************************************************************************
+* Macro Name : GetEPType
+* Description : gets the type in the endpoint register(bits EP_TYPE[1:0])
+* Input : bEpNum: Endpoint Number.
+* Output : None.
+* Return : Endpoint Type
+*******************************************************************************/
+#define _GetEPType(bEpNum) (_GetENDPOINT(bEpNum) & EP_T_FIELD)
+
+/*******************************************************************************
+* Macro Name : SetEPTxStatus
+* Description : sets the status for tx transfer (bits STAT_TX[1:0]).
+* Input : bEpNum: Endpoint Number.
+* wState: new state
+* Output : None.
+* Return : None.
+*******************************************************************************/
+#define _SetEPTxStatus(bEpNum,wState) {\
+ register u16 _wRegVal; \
+ _wRegVal = _GetENDPOINT(bEpNum) & EPTX_DTOGMASK;\
+ /* toggle first bit ? */ \
+ if((EPTX_DTOG1 & wState)!= 0) \
+ _wRegVal ^= EPTX_DTOG1; \
+ /* toggle second bit ? */ \
+ if((EPTX_DTOG2 & wState)!= 0) \
+ _wRegVal ^= EPTX_DTOG2; \
+ _SetENDPOINT(bEpNum, _wRegVal); \
+ } /* _SetEPTxStatus */
+
+/*******************************************************************************
+* Macro Name : SetEPRxStatus
+* Description : sets the status for rx transfer (bits STAT_TX[1:0])
+* Input : bEpNum: Endpoint Number.
+* wState: new state.
+* Output : None.
+* Return : None.
+*******************************************************************************/
+#define _SetEPRxStatus(bEpNum,wState) {\
+ register u16 _wRegVal; \
+ \
+ _wRegVal = _GetENDPOINT(bEpNum) & EPRX_DTOGMASK;\
+ /* toggle first bit ? */ \
+ if((EPRX_DTOG1 & wState)!= 0) \
+ _wRegVal ^= EPRX_DTOG1; \
+ /* toggle second bit ? */ \
+ if((EPRX_DTOG2 & wState)!= 0) \
+ _wRegVal ^= EPRX_DTOG2; \
+ _SetENDPOINT(bEpNum, _wRegVal); \
+ } /* _SetEPRxStatus */
+/*******************************************************************************
+* Macro Name : GetEPTxStatus / GetEPRxStatus
+* Description : gets the status for tx/rx transfer (bits STAT_TX[1:0]
+* /STAT_RX[1:0])
+* Input : bEpNum: Endpoint Number.
+* Output : None.
+* Return : status .
+*******************************************************************************/
+#define _GetEPTxStatus(bEpNum) ((u16)_GetENDPOINT(bEpNum) & EPTX_STAT)
+
+#define _GetEPRxStatus(bEpNum) ((u16)_GetENDPOINT(bEpNum) & EPRX_STAT)
+
+/*******************************************************************************
+* Macro Name : SetEPTxValid / SetEPRxValid
+* Description : sets directly the VALID tx/rx-status into the enpoint register
+* Input : bEpNum: Endpoint Number.
+* Output : None.
+* Return : None.
+*******************************************************************************/
+#define _SetEPTxValid(bEpNum) (_SetEPTxStatus(bEpNum, EP_TX_VALID))
+
+#define _SetEPRxValid(bEpNum) (_SetEPRxStatus(bEpNum, EP_RX_VALID))
+
+/*******************************************************************************
+* Macro Name : GetTxStallStatus / GetRxStallStatus.
+* Description : checks stall condition in an endpoint.
+* Input : bEpNum: Endpoint Number.
+* Output : None.
+* Return : TRUE = endpoint in stall condition.
+*******************************************************************************/
+#define _GetTxStallStatus(bEpNum) (_GetEPTxStatus(bEpNum) \
+ == EP_TX_STALL)
+#define _GetRxStallStatus(bEpNum) (_GetEPRxStatus(bEpNum) \
+ == EP_RX_STALL)
+
+/*******************************************************************************
+* Macro Name : SetEP_KIND / ClearEP_KIND.
+* Description : set & clear EP_KIND bit.
+* Input : bEpNum: Endpoint Number.
+* Output : None.
+* Return : None.
+*******************************************************************************/
+#define _SetEP_KIND(bEpNum) (_SetENDPOINT(bEpNum, \
+ (_GetENDPOINT(bEpNum) | EP_KIND) & EPREG_MASK))
+#define _ClearEP_KIND(bEpNum) (_SetENDPOINT(bEpNum, \
+ (_GetENDPOINT(bEpNum) & EPKIND_MASK)))
+
+/*******************************************************************************
+* Macro Name : Set_Status_Out / Clear_Status_Out.
+* Description : Sets/clears directly STATUS_OUT bit in the endpoint register.
+* Input : bEpNum: Endpoint Number.
+* Output : None.
+* Return : None.
+*******************************************************************************/
+#define _Set_Status_Out(bEpNum) _SetEP_KIND(bEpNum)
+#define _Clear_Status_Out(bEpNum) _ClearEP_KIND(bEpNum)
+
+/*******************************************************************************
+* Macro Name : SetEPDoubleBuff / ClearEPDoubleBuff.
+* Description : Sets/clears directly EP_KIND bit in the endpoint register.
+* Input : bEpNum: Endpoint Number.
+* Output : None.
+* Return : None.
+*******************************************************************************/
+#define _SetEPDoubleBuff(bEpNum) _SetEP_KIND(bEpNum)
+#define _ClearEPDoubleBuff(bEpNum) _ClearEP_KIND(bEpNum)
+
+/*******************************************************************************
+* Macro Name : ClearEP_CTR_RX / ClearEP_CTR_TX.
+* Description : Clears bit CTR_RX / CTR_TX in the endpoint register.
+* Input : bEpNum: Endpoint Number.
+* Output : None.
+* Return : None.
+*******************************************************************************/
+#define _ClearEP_CTR_RX(bEpNum) (_SetENDPOINT(bEpNum,\
+ _GetENDPOINT(bEpNum) & 0x7FFF & EPREG_MASK))
+#define _ClearEP_CTR_TX(bEpNum) (_SetENDPOINT(bEpNum,\
+ _GetENDPOINT(bEpNum) & 0xFF7F & EPREG_MASK))
+
+/*******************************************************************************
+* Macro Name : ToggleDTOG_RX / ToggleDTOG_TX .
+* Description : Toggles DTOG_RX / DTOG_TX bit in the endpoint register.
+* Input : bEpNum: Endpoint Number.
+* Output : None.
+* Return : None.
+*******************************************************************************/
+#define _ToggleDTOG_RX(bEpNum) (_SetENDPOINT(bEpNum, \
+ EP_DTOG_RX | (_GetENDPOINT(bEpNum) & EPREG_MASK)))
+#define _ToggleDTOG_TX(bEpNum) (_SetENDPOINT(bEpNum, \
+ EP_DTOG_TX | (_GetENDPOINT(bEpNum) & EPREG_MASK)))
+
+/*******************************************************************************
+* Macro Name : ClearDTOG_RX / ClearDTOG_TX.
+* Description : Clears DTOG_RX / DTOG_TX bit in the endpoint register.
+* Input : bEpNum: Endpoint Number.
+* Output : None.
+* Return : None.
+*******************************************************************************/
+#define _ClearDTOG_RX(bEpNum) if((_GetENDPOINT(bEpNum) & EP_DTOG_RX) != 0)\
+ _ToggleDTOG_RX(bEpNum)
+#define _ClearDTOG_TX(bEpNum) if((_GetENDPOINT(bEpNum) & EP_DTOG_TX) != 0)\
+ _ToggleDTOG_TX(bEpNum)
+/*******************************************************************************
+* Macro Name : SetEPAddress.
+* Description : Sets address in an endpoint register.
+* Input : bEpNum: Endpoint Number.
+* bAddr: Address.
+* Output : None.
+* Return : None.
+*******************************************************************************/
+#define _SetEPAddress(bEpNum,bAddr) _SetENDPOINT(bEpNum,\
+ (_GetENDPOINT(bEpNum) & EPREG_MASK) | bAddr)
+
+/*******************************************************************************
+* Macro Name : GetEPAddress.
+* Description : Gets address in an endpoint register.
+* Input : bEpNum: Endpoint Number.
+* Output : None.
+* Return : None.
+*******************************************************************************/
+#define _GetEPAddress(bEpNum) ((u8)(_GetENDPOINT(bEpNum) & EPADDR_FIELD))
+
+#define _pEPTxAddr(bEpNum) ((u32 *)((_GetBTABLE()+bEpNum*8 )*2 + PMAAddr))
+#define _pEPTxCount(bEpNum) ((u32 *)((_GetBTABLE()+bEpNum*8+2)*2 + PMAAddr))
+#define _pEPRxAddr(bEpNum) ((u32 *)((_GetBTABLE()+bEpNum*8+4)*2 + PMAAddr))
+#define _pEPRxCount(bEpNum) ((u32 *)((_GetBTABLE()+bEpNum*8+6)*2 + PMAAddr))
+
+/*******************************************************************************
+* Macro Name : SetEPTxAddr / SetEPRxAddr.
+* Description : sets address of the tx/rx buffer.
+* Input : bEpNum: Endpoint Number.
+* wAddr: address to be set (must be word aligned).
+* Output : None.
+* Return : None.
+*******************************************************************************/
+#define _SetEPTxAddr(bEpNum,wAddr) (*_pEPTxAddr(bEpNum) = ((wAddr >> 1) << 1))
+#define _SetEPRxAddr(bEpNum,wAddr) (*_pEPRxAddr(bEpNum) = ((wAddr >> 1) << 1))
+
+/*******************************************************************************
+* Macro Name : GetEPTxAddr / GetEPRxAddr.
+* Description : Gets address of the tx/rx buffer.
+* Input : bEpNum: Endpoint Number.
+* Output : None.
+* Return : address of the buffer.
+*******************************************************************************/
+#define _GetEPTxAddr(bEpNum) ((u16)*_pEPTxAddr(bEpNum))
+#define _GetEPRxAddr(bEpNum) ((u16)*_pEPRxAddr(bEpNum))
+
+/*******************************************************************************
+* Macro Name : SetEPCountRxReg.
+* Description : Sets counter of rx buffer with no. of blocks.
+* Input : pdwReg: pointer to counter.
+* wCount: Counter.
+* Output : None.
+* Return : None.
+*******************************************************************************/
+#define _BlocksOf32(dwReg,wCount,wNBlocks) {\
+ wNBlocks = wCount >> 5;\
+ if((wCount & 0x1f) == 0)\
+ wNBlocks--;\
+ *pdwReg = (u32)((wNBlocks << 10) | 0x8000);\
+ }/* _BlocksOf32 */
+
+#define _BlocksOf2(dwReg,wCount,wNBlocks) {\
+ wNBlocks = wCount >> 1;\
+ if((wCount & 0x1) != 0)\
+ wNBlocks++;\
+ *pdwReg = (u32)(wNBlocks << 10);\
+ }/* _BlocksOf2 */
+
+#define _SetEPCountRxReg(dwReg,wCount) {\
+ u16 wNBlocks;\
+ if(wCount > 62){_BlocksOf32(dwReg,wCount,wNBlocks);}\
+ else {_BlocksOf2(dwReg,wCount,wNBlocks);}\
+ }/* _SetEPCountRxReg */
+
+
+
+#define _SetEPRxDblBuf0Count(bEpNum,wCount) {\
+ u32 *pdwReg = _pEPTxCount(bEpNum); \
+ _SetEPCountRxReg(pdwReg, wCount);\
+ }
+/*******************************************************************************
+* Macro Name : SetEPTxCount / SetEPRxCount.
+* Description : sets counter for the tx/rx buffer.
+* Input : bEpNum: endpoint number.
+* wCount: Counter value.
+* Output : None.
+* Return : None.
+*******************************************************************************/
+#define _SetEPTxCount(bEpNum,wCount) (*_pEPTxCount(bEpNum) = wCount)
+#define _SetEPRxCount(bEpNum,wCount) {\
+ u32 *pdwReg = _pEPRxCount(bEpNum); \
+ _SetEPCountRxReg(pdwReg, wCount);\
+ }
+/*******************************************************************************
+* Macro Name : GetEPTxCount / GetEPRxCount.
+* Description : gets counter of the tx buffer.
+* Input : bEpNum: endpoint number.
+* Output : None.
+* Return : Counter value.
+*******************************************************************************/
+#define _GetEPTxCount(bEpNum)((u16)(*_pEPTxCount(bEpNum)) & 0x3ff)
+#define _GetEPRxCount(bEpNum)((u16)(*_pEPRxCount(bEpNum)) & 0x3ff)
+
+/*******************************************************************************
+* Macro Name : SetEPDblBuf0Addr / SetEPDblBuf1Addr.
+* Description : Sets buffer 0/1 address in a double buffer endpoint.
+* Input : bEpNum: endpoint number.
+* : wBuf0Addr: buffer 0 address.
+* Output : None.
+* Return : None.
+*******************************************************************************/
+#define _SetEPDblBuf0Addr(bEpNum,wBuf0Addr) {_SetEPTxAddr(bEpNum, wBuf0Addr);}
+#define _SetEPDblBuf1Addr(bEpNum,wBuf1Addr) {_SetEPRxAddr(bEpNum, wBuf1Addr);}
+
+/*******************************************************************************
+* Macro Name : SetEPDblBuffAddr.
+* Description : Sets addresses in a double buffer endpoint.
+* Input : bEpNum: endpoint number.
+* : wBuf0Addr: buffer 0 address.
+* : wBuf1Addr = buffer 1 address.
+* Output : None.
+* Return : None.
+*******************************************************************************/
+#define _SetEPDblBuffAddr(bEpNum,wBuf0Addr,wBuf1Addr) { \
+ _SetEPDblBuf0Addr(bEpNum, wBuf0Addr);\
+ _SetEPDblBuf1Addr(bEpNum, wBuf1Addr);\
+ } /* _SetEPDblBuffAddr */
+
+/*******************************************************************************
+* Macro Name : GetEPDblBuf0Addr / GetEPDblBuf1Addr.
+* Description : Gets buffer 0/1 address of a double buffer endpoint.
+* Input : bEpNum: endpoint number.
+* Output : None.
+* Return : None.
+*******************************************************************************/
+#define _GetEPDblBuf0Addr(bEpNum) (_GetEPTxAddr(bEpNum))
+#define _GetEPDblBuf1Addr(bEpNum) (_GetEPRxAddr(bEpNum))
+
+/*******************************************************************************
+* Macro Name : SetEPDblBuffCount / SetEPDblBuf0Count / SetEPDblBuf1Count.
+* Description : Gets buffer 0/1 address of a double buffer endpoint.
+* Input : bEpNum: endpoint number.
+* : bDir: endpoint dir EP_DBUF_OUT = OUT
+* EP_DBUF_IN = IN
+* : wCount: Counter value
+* Output : None.
+* Return : None.
+*******************************************************************************/
+#define _SetEPDblBuf0Count(bEpNum, bDir, wCount) { \
+ if(bDir == EP_DBUF_OUT)\
+ /* OUT endpoint */ \
+ {_SetEPRxDblBuf0Count(bEpNum,wCount);} \
+ else if(bDir == EP_DBUF_IN)\
+ /* IN endpoint */ \
+ *_pEPTxCount(bEpNum) = (u32)wCount; \
+ } /* SetEPDblBuf0Count*/
+
+#define _SetEPDblBuf1Count(bEpNum, bDir, wCount) { \
+ if(bDir == EP_DBUF_OUT)\
+ /* OUT endpoint */ \
+ {_SetEPRxCount(bEpNum,wCount);}\
+ else if(bDir == EP_DBUF_IN)\
+ /* IN endpoint */\
+ *_pEPRxCount(bEpNum) = (u32)wCount; \
+ } /* SetEPDblBuf1Count */
+
+#define _SetEPDblBuffCount(bEpNum, bDir, wCount) {\
+ _SetEPDblBuf0Count(bEpNum, bDir, wCount); \
+ _SetEPDblBuf1Count(bEpNum, bDir, wCount); \
+ } /* _SetEPDblBuffCount */
+
+/*******************************************************************************
+* Macro Name : GetEPDblBuf0Count / GetEPDblBuf1Count.
+* Description : Gets buffer 0/1 rx/tx counter for double buffering.
+* Input : bEpNum: endpoint number.
+* Output : None.
+* Return : None.
+*******************************************************************************/
+#define _GetEPDblBuf0Count(bEpNum) (_GetEPTxCount(bEpNum))
+#define _GetEPDblBuf1Count(bEpNum) (_GetEPRxCount(bEpNum))
+
+
+/* External variables --------------------------------------------------------*/
+extern volatile u16 wIstr; /* ISTR register last read value */
+
+/* Exported functions ------------------------------------------------------- */
+void SetCNTR(u16 /*wRegValue*/);
+void SetISTR(u16 /*wRegValue*/);
+void SetDADDR(u16 /*wRegValue*/);
+void SetBTABLE(u16 /*wRegValue*/);
+u16 GetCNTR(void);
+u16 GetISTR(void);
+u16 GetFNR(void);
+u16 GetDADDR(void);
+u16 GetBTABLE(void);
+void SetENDPOINT(u8 /*bEpNum*/, u16 /*wRegValue*/);
+u16 GetENDPOINT(u8 /*bEpNum*/);
+void SetEPType(u8 /*bEpNum*/, u16 /*wType*/);
+u16 GetEPType(u8 /*bEpNum*/);
+void SetEPTxStatus(u8 /*bEpNum*/, u16 /*wState*/);
+void SetEPRxStatus(u8 /*bEpNum*/, u16 /*wState*/);
+void SetDouBleBuffEPStall(u8 /*bEpNum*/, u8 bDir);
+u16 GetEPTxStatus(u8 /*bEpNum*/);
+u16 GetEPRxStatus(u8 /*bEpNum*/);
+void SetEPTxValid(u8 /*bEpNum*/);
+void SetEPRxValid(u8 /*bEpNum*/);
+u16 GetTxStallStatus(u8 /*bEpNum*/);
+u16 GetRxStallStatus(u8 /*bEpNum*/);
+void SetEP_KIND(u8 /*bEpNum*/);
+void ClearEP_KIND(u8 /*bEpNum*/);
+void Set_Status_Out(u8 /*bEpNum*/);
+void Clear_Status_Out(u8 /*bEpNum*/);
+void SetEPDoubleBuff(u8 /*bEpNum*/);
+void ClearEPDoubleBuff(u8 /*bEpNum*/);
+void ClearEP_CTR_RX(u8 /*bEpNum*/);
+void ClearEP_CTR_TX(u8 /*bEpNum*/);
+void ToggleDTOG_RX(u8 /*bEpNum*/);
+void ToggleDTOG_TX(u8 /*bEpNum*/);
+void ClearDTOG_RX(u8 /*bEpNum*/);
+void ClearDTOG_TX(u8 /*bEpNum*/);
+void SetEPAddress(u8 /*bEpNum*/, u8 /*bAddr*/);
+u8 GetEPAddress(u8 /*bEpNum*/);
+void SetEPTxAddr(u8 /*bEpNum*/, u16 /*wAddr*/);
+void SetEPRxAddr(u8 /*bEpNum*/, u16 /*wAddr*/);
+u16 GetEPTxAddr(u8 /*bEpNum*/);
+u16 GetEPRxAddr(u8 /*bEpNum*/);
+void SetEPCountRxReg(u32 * /*pdwReg*/, u16 /*wCount*/);
+void SetEPTxCount(u8 /*bEpNum*/, u16 /*wCount*/);
+void SetEPRxCount(u8 /*bEpNum*/, u16 /*wCount*/);
+u16 GetEPTxCount(u8 /*bEpNum*/);
+u16 GetEPRxCount(u8 /*bEpNum*/);
+void SetEPDblBuf0Addr(u8 /*bEpNum*/, u16 /*wBuf0Addr*/);
+void SetEPDblBuf1Addr(u8 /*bEpNum*/, u16 /*wBuf1Addr*/);
+void SetEPDblBuffAddr(u8 /*bEpNum*/, u16 /*wBuf0Addr*/, u16 /*wBuf1Addr*/);
+u16 GetEPDblBuf0Addr(u8 /*bEpNum*/);
+u16 GetEPDblBuf1Addr(u8 /*bEpNum*/);
+void SetEPDblBuffCount(u8 /*bEpNum*/, u8 /*bDir*/, u16 /*wCount*/);
+void SetEPDblBuf0Count(u8 /*bEpNum*/, u8 /*bDir*/, u16 /*wCount*/);
+void SetEPDblBuf1Count(u8 /*bEpNum*/, u8 /*bDir*/, u16 /*wCount*/);
+u16 GetEPDblBuf0Count(u8 /*bEpNum*/);
+u16 GetEPDblBuf1Count(u8 /*bEpNum*/);
+EP_DBUF_DIR GetEPDblBufDir(u8 /*bEpNum*/);
+void FreeUserBuffer(u8 bEpNum/*bEpNum*/, u8 bDir);
+u16 ToWord(u8, u8);
+u16 ByteSwap(u16);
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif /* __USB_REGS_H */
+
+/******************* (C) COPYRIGHT 2008 STMicroelectronics *****END OF FILE****/
diff --git a/libmaple/usb/usb_lib/usb_type.h b/libmaple/usb/usb_lib/usb_type.h
new file mode 100644
index 0000000..34b3bf5
--- /dev/null
+++ b/libmaple/usb/usb_lib/usb_type.h
@@ -0,0 +1,77 @@
+/******************** (C) COPYRIGHT 2008 STMicroelectronics ********************
+* File Name : usb_type.h
+* Author : MCD Application Team
+* Version : V2.2.1
+* Date : 09/22/2008
+* Description : Type definitions used by the USB Library
+********************************************************************************
+* THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
+* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE TIME.
+* AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY DIRECT,
+* INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING FROM THE
+* CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE CODING
+* INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
+*******************************************************************************/
+
+/* Define to prevent recursive inclusion -------------------------------------*/
+#ifndef __USB_TYPE_H
+#define __USB_TYPE_H
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+/* Exported types ------------------------------------------------------------*/
+/* Exported constants --------------------------------------------------------*/
+#ifndef NULL
+#define NULL ((void *)0)
+#endif
+
+typedef signed long s32;
+typedef signed short s16;
+typedef signed char s8;
+
+typedef volatile signed long vs32;
+typedef volatile signed short vs16;
+typedef volatile signed char vs8;
+
+typedef unsigned long u32;
+typedef unsigned short u16;
+typedef unsigned char u8;
+
+typedef unsigned long const uc32; /* Read Only */
+typedef unsigned short const uc16; /* Read Only */
+typedef unsigned char const uc8; /* Read Only */
+
+typedef volatile unsigned long vu32;
+typedef volatile unsigned short vu16;
+typedef volatile unsigned char vu8;
+
+typedef volatile unsigned long const vuc32; /* Read Only */
+typedef volatile unsigned short const vuc16; /* Read Only */
+typedef volatile unsigned char const vuc8; /* Read Only */
+
+
+typedef enum
+{
+ FALSE = 0, TRUE = !FALSE
+}
+USB_Bool;
+
+typedef enum { RESET = 0, SET = !RESET } FlagStatus, ITStatus;
+
+typedef enum { DISABLE = 0, ENABLE = !DISABLE} FunctionalState;
+
+typedef enum { ERROR = 0, SUCCESS = !ERROR} ErrorStatus;
+
+/* Exported macro ------------------------------------------------------------*/
+/* Exported functions ------------------------------------------------------- */
+/* External variables --------------------------------------------------------*/
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif /* __USB_TYPE_H */
+
+/******************* (C) COPYRIGHT 2008 STMicroelectronics *****END OF FILE****/