Sfoglia il codice sorgente

make keyboard device work with lpc1347

hathach 13 anni fa
parent
commit
851f5bfd06

+ 3 - 0
demos/device/keyboard/.cproject

@@ -35,6 +35,7 @@
 								<option id="gnu.c.compiler.option.misc.other.204394496" name="Other flags" superClass="gnu.c.compiler.option.misc.other" value="-c -fmessage-length=0 -fno-builtin -ffunction-sections -fdata-sections" valueType="string"/>
 								<option id="gnu.c.compiler.option.include.paths.1207481236" name="Include paths (-I)" superClass="gnu.c.compiler.option.include.paths" valueType="includePath">
 									<listOptionValue builtIn="false" value="&quot;${workspace_loc:/CMSISv2p10_LPC13Uxx/inc}&quot;"/>
+									<listOptionValue builtIn="false" value="&quot;${workspace_loc:/LPC13Uxx_DriverLib/inc}&quot;"/>
 									<listOptionValue builtIn="false" value="&quot;${workspace_loc:/tinyusb/tinyusb}&quot;"/>
 								</option>
 								<option id="gnu.c.compiler.option.include.files.318820756" name="Include files (-include)" superClass="gnu.c.compiler.option.include.files"/>
@@ -59,10 +60,12 @@
 								</option>
 								<option id="gnu.c.link.option.paths.1465143173" name="Library search path (-L)" superClass="gnu.c.link.option.paths" valueType="libPaths">
 									<listOptionValue builtIn="false" value="&quot;${workspace_loc:/CMSISv2p10_LPC13Uxx/Debug}&quot;"/>
+									<listOptionValue builtIn="false" value="&quot;${workspace_loc:/LPC13Uxx_DriverLib/Debug}&quot;"/>
 									<listOptionValue builtIn="false" value="&quot;${workspace_loc:/tinyusb/Debug}&quot;"/>
 								</option>
 								<option id="gnu.c.link.option.libs.447978281" name="Libraries (-l)" superClass="gnu.c.link.option.libs" valueType="libs">
 									<listOptionValue builtIn="false" value="CMSISv2p10_LPC13Uxx"/>
+									<listOptionValue builtIn="false" value="LPC13Uxx_DriverLib"/>
 									<listOptionValue builtIn="false" value="tinyusb"/>
 								</option>
 								<option id="com.crt.advproject.link.gcc.hdrlib.1111642583" name="Use C library" superClass="com.crt.advproject.link.gcc.hdrlib" value="com.crt.advproject.gcc.link.hdrlib.codered.nohost" valueType="enumerated"/>

+ 1 - 0
demos/device/keyboard/.project

@@ -4,6 +4,7 @@
 	<comment></comment>
 	<projects>
 		<project>CMSISv2p10_LPC13Uxx</project>
+		<project>LPC13Uxx_DriverLib</project>
 		<project>tinyusb</project>
 	</projects>
 	<buildSpec>

+ 7 - 7
demos/device/keyboard/descriptors.c

@@ -37,8 +37,8 @@
 
 #include "descriptors.h"
 
-#ifdef CFG_USB_HID_KEYBOARD
-ALIGNED(4) const uint8_t HID_KeyboardReportDescriptor[] = {
+#ifdef CFG_CLASS_HID_KEYBOARD
+ATTR_ALIGNED(4) const uint8_t HID_KeyboardReportDescriptor[] = {
   HID_UsagePage  ( HID_USAGE_PAGE_GENERIC     ),
   HID_Usage      ( HID_USAGE_GENERIC_KEYBOARD ),
   HID_Collection ( HID_Application            ),
@@ -81,7 +81,7 @@ ALIGNED(4) const uint8_t HID_KeyboardReportDescriptor[] = {
 #endif
 
 #ifdef CFG_USB_HID_MOUSE
-ALIGNED(4) const uint8_t HID_MouseReportDescriptor[] = {
+ATTR_ALIGNED(4) const uint8_t HID_MouseReportDescriptor[] = {
   HID_UsagePage  ( HID_USAGE_PAGE_GENERIC     ),
   HID_Usage      ( HID_USAGE_GENERIC_MOUSE ),
   HID_Collection ( HID_Application            ),
@@ -119,7 +119,7 @@ ALIGNED(4) const uint8_t HID_MouseReportDescriptor[] = {
 #endif
 
 /* USB Standard Device Descriptor */
-ALIGNED(4) const USB_DEVICE_DESCRIPTOR USB_DeviceDescriptor =
+ATTR_ALIGNED(4) const USB_DEVICE_DESCRIPTOR USB_DeviceDescriptor =
 {
   .bLength            = sizeof(USB_DEVICE_DESCRIPTOR),
   .bDescriptorType    = USB_DEVICE_DESCRIPTOR_TYPE,
@@ -153,7 +153,7 @@ ALIGNED(4) const USB_DEVICE_DESCRIPTOR USB_DeviceDescriptor =
   .bNumConfigurations = 0x01
 };
 
-ALIGNED(4) const USB_FS_CONFIGURATION_DESCRIPTOR USB_FsConfigDescriptor =
+ATTR_ALIGNED(4) const USB_FS_CONFIGURATION_DESCRIPTOR USB_FsConfigDescriptor =
 {
     .Config =
     {
@@ -276,7 +276,7 @@ ALIGNED(4) const USB_FS_CONFIGURATION_DESCRIPTOR USB_FsConfigDescriptor =
     },
     #endif
 
-    #ifdef CFG_USB_HID_KEYBOARD
+    #ifdef CFG_CLASS_HID_KEYBOARD
     ///// USB HID Keyboard interface
     .HID_KeyboardInterface =
     {
@@ -358,7 +358,7 @@ ALIGNED(4) const USB_FS_CONFIGURATION_DESCRIPTOR USB_FsConfigDescriptor =
     .ConfigDescTermination = 0,
 };
 
-ALIGNED(4) const USB_STR_DESCRIPTOR USB_StringDescriptor =
+ATTR_ALIGNED(4) const USB_STR_DESCRIPTOR USB_StringDescriptor =
 {
     .LangID = { .bLength = 0x04, .bDescriptorType = USB_STRING_DESCRIPTOR_TYPE },
     .strLangID= {0x0409}, // US English

+ 3 - 3
demos/device/keyboard/descriptors.h

@@ -88,7 +88,7 @@ typedef PRE_PACK struct POST_PACK _USB_INTERFACE_ASSOCIATION_DESCRIPTOR
 
 ///////////////////////////////////////////////////////////////////////
 // Interface Assosication Descriptor if device is CDC + other class
-#define IAD_DESC_REQUIRED ( defined(CFG_USB_CDC) && (defined(CFG_USB_HID_KEYBOARD) || defined(CFG_USB_HID_MOUSE)) )
+#define IAD_DESC_REQUIRED ( defined(CFG_USB_CDC) && (CLASS_HID) )
 
 #ifdef CFG_USB_CDC
   #define INTERFACES_OF_CDC           2
@@ -96,7 +96,7 @@ typedef PRE_PACK struct POST_PACK _USB_INTERFACE_ASSOCIATION_DESCRIPTOR
   #define INTERFACES_OF_CDC           0
 #endif
 
-#ifdef CFG_USB_HID_KEYBOARD
+#ifdef CFG_CLASS_HID_KEYBOARD
   #define INTERFACES_OF_HID_KEYBOARD  1
 #else
   #define INTERFACES_OF_HID_KEYBOARD  0
@@ -157,7 +157,7 @@ typedef struct
   USB_ENDPOINT_DESCRIPTOR                     CDC_DataInEndpoint;
 #endif
 
-#ifdef CFG_USB_HID_KEYBOARD
+#ifdef CFG_CLASS_HID_KEYBOARD
   //Keyboard HID Interface
   USB_INTERFACE_DESCRIPTOR                    HID_KeyboardInterface;
   HID_DESCRIPTOR                              HID_KeyboardHID;

+ 35 - 0
demos/device/keyboard/main.c

@@ -13,12 +13,47 @@ __CRP const unsigned int CRP_WORD = CRP_NO_CRP ;
 
 int main(void) 
 {
+  uint32_t currentSecond, lastSecond;
+  currentSecond = lastSecond = 0;
+
   SystemInit();
+
+  systickInit(1);
+  GPIOInit();
+
+    #define CFG_LED_PORT                  (0)
+    #define CFG_LED_PIN                   (7)
+    #define CFG_LED_ON                    (1)
+    #define CFG_LED_OFF                   (0)
+
+  GPIOSetDir(CFG_LED_PORT, CFG_LED_PIN, 1);
+  LPC_GPIO->CLR[CFG_LED_PORT] = (1 << CFG_LED_PIN);
+
   tusb_init();
 
   while (1)
   {
+    currentSecond = systickGetSecondsActive();
+    if (currentSecond != lastSecond)
+    {
+      /* Toggle LED once per second */
+      lastSecond = currentSecond;
+      GPIOSetBitValue(CFG_LED_PORT, CFG_LED_PIN, lastSecond % 2);
+
+      #if !defined(CFG_USB_CDC)
+      if (usb_isConfigured())
+      {
+        #ifdef CFG_CLASS_HID_KEYBOARD
+          uint8_t keys[6] = {HID_USAGE_KEYBOARD_aA};
+          usb_hid_keyboard_sendKeys(0x00, keys, 1);
+        #endif
 
+        #ifdef CFG_USB_HID_MOUSE
+          usb_hid_mouse_send(0, 10, 10);
+        #endif
+      }
+      #endif
+    }
   }
 
   return 0;

+ 337 - 0
tinyusb/class/hid.c

@@ -0,0 +1,337 @@
+/*
+ * hid.c
+ *
+ *  Created on: Nov 27, 2012
+ *      Author: hathach (thachha@live.com)
+ */
+
+/*
+ * Software License Agreement (BSD License)
+ * Copyright (c) 2012, hathach (thachha@live.com)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ *    this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ *    this list of conditions and the following disclaimer in the documentation
+ *    and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+ * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ *
+ * This file is part of the tiny usb stack.
+ */
+
+#include "hid.h"
+//#include "../systick/systick.h"
+
+#ifdef CLASS_HID
+
+#ifdef CFG_CLASS_HID_KEYBOARD
+USB_HID_KeyboardReport_t hid_keyboard_report;
+volatile static bool bKeyChanged = false;
+#endif
+
+#ifdef CFG_USB_HID_MOUSE
+USB_HID_MouseReport_t hid_mouse_report;
+volatile static bool bMouseChanged = false;
+#endif
+
+/**************************************************************************/
+/*!
+    @brief Handler for HID_GetReport in the USB ROM driver
+*/
+/**************************************************************************/
+ErrorCode_t HID_GetReport( USBD_HANDLE_T hHid, USB_SETUP_PACKET* pSetup, uint8_t** pBuffer, uint16_t* plength)
+{
+  USB_HID_CTRL_T* pHidCtrl = (USB_HID_CTRL_T*) hHid;
+
+  /* ReportID = SetupPacket.wValue.WB.L; */
+  if (pSetup->wValue.WB.H == HID_REPORT_INPUT)
+    return (ERR_USBD_STALL);          /* Not Supported */
+
+  switch (pHidCtrl->protocol)
+  {
+    #ifdef CFG_CLASS_HID_KEYBOARD
+      case HID_PROTOCOL_KEYBOARD:
+        *pBuffer = (uint8_t*) &hid_keyboard_report;
+        *plength = sizeof(USB_HID_KeyboardReport_t);
+
+        if (!bKeyChanged)
+        {
+          memset(pBuffer, 0, *plength);
+        }
+        bKeyChanged = false;
+      break;
+    #endif
+
+    #ifdef CFG_USB_HID_MOUSE
+      case HID_PROTOCOL_MOUSE:
+        *pBuffer = (uint8_t*) &hid_mouse_report;
+        *plength = sizeof(USB_HID_MouseReport_t);
+
+        if (!bMouseChanged)
+        {
+          memset(pBuffer, 0, *plength);
+        }
+        bMouseChanged = false;
+      break;
+    #endif
+
+    default:
+      break;
+  }
+
+  return (LPC_OK);
+}
+
+/**************************************************************************/
+/*!
+    @brief Handler for HIS_SetReport in the USB ROM driver
+*/
+/**************************************************************************/
+ErrorCode_t HID_SetReport( USBD_HANDLE_T hHid, USB_SETUP_PACKET* pSetup, uint8_t** pBuffer, uint16_t length)
+{
+  /* we will reuse standard EP0Buf */
+  if (length == 0)
+    return LPC_OK;
+
+  /* ReportID = SetupPacket.wValue.WB.L; */
+  if (pSetup->wValue.WB.H != HID_REPORT_OUTPUT)
+    return (ERR_USBD_STALL);          /* Not Supported */
+
+  return (LPC_OK);
+}
+
+/**************************************************************************/
+/*!
+    @brief HID endpoint in handler for the USB ROM driver
+*/
+/**************************************************************************/
+ErrorCode_t HID_EpIn_Hdlr (USBD_HANDLE_T hUsb, void* data, uint32_t event)
+{
+  if (USB_EVT_IN == event)
+  {
+    USB_HID_CTRL_T* pHidCtrl = (USB_HID_CTRL_T*)data;
+    switch(pHidCtrl->protocol)
+    {
+      #ifdef CFG_CLASS_HID_KEYBOARD
+        case HID_PROTOCOL_KEYBOARD:
+          if (!bKeyChanged)
+          {
+            memset(&hid_keyboard_report, 0, sizeof(USB_HID_KeyboardReport_t));
+          }
+          USBD_API->hw->WriteEP(hUsb, pHidCtrl->epin_adr, (uint8_t*) &hid_keyboard_report, sizeof(USB_HID_KeyboardReport_t));
+          bKeyChanged = false;
+        break;
+      #endif
+
+      #ifdef CFG_USB_HID_MOUSE
+        case HID_PROTOCOL_MOUSE:
+          if (!bMouseChanged)
+          {
+            memset(&hid_mouse_report, 0, sizeof(USB_HID_MouseReport_t));
+          }
+          USBD_API->hw->WriteEP(hUsb, pHidCtrl->epin_adr, (uint8_t*) &hid_mouse_report, sizeof(USB_HID_MouseReport_t));
+          bMouseChanged = false;
+        break;
+      #endif
+
+      default:
+        break;
+    }
+  }
+
+  return LPC_OK;
+}
+
+/**************************************************************************/
+/*!
+    @brief HID endpoint out handler for the USB ROM driver
+*/
+/**************************************************************************/
+ErrorCode_t HID_EpOut_Hdlr (USBD_HANDLE_T hUsb, void* data, uint32_t event)
+{
+  if (USB_EVT_OUT == event)
+  {
+    // not used yet
+    // uint8_t outreport[8];
+    // USB_HID_CTRL_T* pHidCtrl = (USB_HID_CTRL_T*)data;
+    // USBD_API->hw->ReadEP(hUsb, pHidCtrl->epout_adr, outreport);
+  }
+  return LPC_OK;
+}
+
+/**************************************************************************/
+/*!
+    @brief Initialises USB HID using the ROM based drivers
+*/
+/**************************************************************************/
+ErrorCode_t usb_hid_init(USBD_HANDLE_T hUsb, USB_INTERFACE_DESCRIPTOR const *const pIntfDesc, uint8_t const * const pHIDReportDesc, uint32_t ReportDescLength, uint32_t* mem_base, uint32_t* mem_size)
+{
+  USB_HID_REPORT_T reports_data =
+  {
+      .desc      = (uint8_t*) pHIDReportDesc,
+      .len       = ReportDescLength,
+      .idle_time = 0,
+  };
+
+  USBD_HID_INIT_PARAM_T hid_param =
+  {
+      .mem_base       = *mem_base,
+      .mem_size       = *mem_size,
+
+      .intf_desc      = (uint8_t*)pIntfDesc,
+      .report_data    = &reports_data,
+      .max_reports    = 1,
+
+      /* user defined functions */
+      .HID_GetReport  = HID_GetReport,
+      .HID_SetReport  = HID_SetReport,
+      .HID_EpIn_Hdlr  = HID_EpIn_Hdlr,
+      .HID_EpOut_Hdlr = HID_EpOut_Hdlr
+  };
+
+  ASSERT( (pIntfDesc != NULL) && (pIntfDesc->bInterfaceClass == USB_DEVICE_CLASS_HUMAN_INTERFACE), ERR_FAILED);
+
+  ASSERT_STATUS( USBD_API->hid->init(hUsb, &hid_param) );
+
+  /* update memory variables */
+  *mem_base = hid_param.mem_base;
+  *mem_size = hid_param.mem_size;
+
+  return LPC_OK;
+}
+
+/**************************************************************************/
+/*!
+
+*/
+/**************************************************************************/
+ErrorCode_t usb_hid_configured(USBD_HANDLE_T hUsb)
+{
+  #ifdef  CFG_CLASS_HID_KEYBOARD
+    USBD_API->hw->WriteEP(hUsb , HID_KEYBOARD_EP_IN , (uint8_t* ) &hid_keyboard_report , sizeof(USB_HID_KeyboardReport_t) ); // initial packet for IN endpoint , will not work if omitted
+  #endif
+
+  #ifdef  CFG_USB_HID_MOUSE
+    USBD_API->hw->WriteEP(hUsb , HID_MOUSE_EP_IN    , (uint8_t* ) &hid_mouse_report    , sizeof(USB_HID_MouseReport_t) ); // initial packet for IN endpoint, will not work if omitted
+  #endif
+
+  return LPC_OK;
+}
+
+#ifdef CFG_CLASS_HID_KEYBOARD
+/**************************************************************************/
+/*!
+    @brief Send the supplied key codes out via HID USB keyboard emulation
+
+    @param[in]  modifier
+                KB modifier code bits (see USB_HID_KB_KEYMODIFIER_CODE)
+    @param[in]  keycodes
+                A buffer containing up to six keycodes
+    @param[in]  numkey
+                The number of keys to send (max 6)
+
+    @note Note that for HID KBs, letter codes are not case sensitive. To
+          create an upper-case letter, you need to include the correct
+          KB modifier code(s), for ex: (1 << HID_KEYMODIFIER_LEFTSHIFT)
+
+    @section EXAMPLE
+
+    @code
+
+    // Send an unmodified 'a' character
+    if (usb_isConfigured())
+    {
+      uint8_t keys[6] = {HID_USAGE_KEYBOARD_aA};
+      usb_hid_keyboard_sendKeys(0x00, keys, 1);
+    }
+
+    // Send Windows + 'e' (shortcut for 'explorer.exe')
+    if (usb_isConfigured())
+    {
+      uint8_t keys[6] = {HID_USAGE_KEYBOARD_aA + 'e' - 'a'};
+      usb_hid_keyboard_sendKeys((1<<HID_KEYMODIFIER_LEFTGUI), keys, 1);
+    }
+
+    @endcode
+*/
+/**************************************************************************/
+ErrorCode_t usb_hid_keyboard_sendKeys(uint8_t modifier, uint8_t keycodes[], uint8_t numkey)
+{
+  uint32_t start_time = systickGetSecondsActive();
+  while (bKeyChanged) // TODO blocking while previous key has yet sent - can use fifo to improve this
+  {
+    ASSERT_MESSAGE(systickGetSecondsActive() - start_time < 5, ERR_FAILED, "HID Keyboard Timeout");
+  }
+  ASSERT(keycodes && numkey && numkey <=6, ERR_FAILED);
+
+  hid_keyboard_report.Modifier = modifier;
+  memset(hid_keyboard_report.KeyCode, 0, 6);
+  memcpy(hid_keyboard_report.KeyCode, keycodes, numkey);
+
+  bKeyChanged = true;
+
+  return LPC_OK;
+}
+#endif
+
+#ifdef CFG_USB_HID_MOUSE
+/**************************************************************************/
+/*!
+    @brief Send the supplied mouse event out via HID USB mouse emulation
+
+    @param[in]  buttons
+                Indicate which button(s) are being pressed (see
+                USB_HID_MOUSE_BUTTON_CODE)
+    @param[in]  x
+                Position adjustment on the X scale
+    @param[in]  y
+                Position adjustment on the Y scale
+
+    @section EXAMPLE
+
+    @code
+
+    if (usb_isConfigured())
+    {
+      // Move the mouse +10 in the X direction and + 10 in the Y direction
+      usb_hid_mouse_send(0x00, 10, 10);
+    }
+
+    @endcode
+*/
+/**************************************************************************/
+ErrorCode_t usb_hid_mouse_send(uint8_t buttons, int8_t x, int8_t y)
+{
+  uint32_t start_time = systickGetSecondsActive();
+  while (bMouseChanged) // TODO Block while previous key hasn't been sent - can use fifo to improve this
+  {
+    ASSERT_MESSAGE(systickGetSecondsActive() - start_time < 5, ERR_FAILED, "HID Mouse Timeout");
+  }
+
+  hid_mouse_report.Button = buttons;
+  hid_mouse_report.X = x;
+  hid_mouse_report.Y = y;
+
+  bMouseChanged = true;
+
+  return LPC_OK;
+}
+#endif
+
+#endif

+ 142 - 0
tinyusb/class/hid.h

@@ -0,0 +1,142 @@
+/*
+ * hid.h
+ *
+ *  Created on: Nov 27, 2012
+ *      Author: hathach (thachha@live.com)
+ */
+
+/*
+ * Software License Agreement (BSD License)
+ * Copyright (c) 2012, hathach (thachha@live.com)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ *    this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ *    this list of conditions and the following disclaimer in the documentation
+ *    and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+ * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ *
+ * This file is part of the tiny usb stack.
+ */
+
+#ifndef _TUSB_HID_H_
+#define _TUSB_HID_H_
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+ // TODO refractor
+#include "common/common.h"
+#include "device/dcd.h"
+
+ErrorCode_t usb_hid_init(USBD_HANDLE_T hUsb, USB_INTERFACE_DESCRIPTOR const *const pIntfDesc, uint8_t const * const pHIDReportDesc, uint32_t ReportDescLength, uint32_t* mem_base, uint32_t* mem_size);
+ErrorCode_t usb_hid_configured(USBD_HANDLE_T hUsb);
+
+ErrorCode_t usb_hid_keyboard_sendKeys(uint8_t modifier, uint8_t keycodes[], uint8_t numkey);
+ErrorCode_t usb_hid_mouse_send(uint8_t buttons, int8_t x, int8_t y);
+
+/** \brief Standard HID Boot Protocol Mouse Report.
+ *
+ *  Type define for a standard Boot Protocol Mouse report
+ */
+typedef PRE_PACK struct
+{
+  uint8_t Button; /**< Button mask for currently pressed buttons in the mouse. */
+  int8_t  X; /**< Current delta X movement of the mouse. */
+  int8_t  Y; /**< Current delta Y movement on the mouse. */
+} POST_PACK USB_HID_MouseReport_t;
+
+/** \brief Standard HID Boot Protocol Keyboard Report.
+ *
+ *  Type define for a standard Boot Protocol Keyboard report
+ */
+typedef PRE_PACK struct
+{
+  uint8_t Modifier; /**< Keyboard modifier byte, indicating pressed modifier keys (a combination of HID_KEYBOARD_MODIFER_* masks). */
+  uint8_t Reserved; /**< Reserved for OEM use, always set to 0. */
+  uint8_t KeyCode[6]; /**< Key codes of the currently pressed keys. */
+} POST_PACK USB_HID_KeyboardReport_t;
+
+/* Button codes for HID mouse */
+enum USB_HID_MOUSE_BUTTON_CODE
+{
+	HID_MOUSEBUTTON_RIGHT = 0,
+	HID_MOUSEBUTTON_LEFT = 1,
+	HID_MOUSEBUTTON_MIDDLE = 2
+};
+
+/* KB modifier codes for HID KB */
+enum USB_HID_KB_KEYMODIFIER_CODE
+{
+	HID_KEYMODIFIER_LEFTCTRL = 0,
+	HID_KEYMODIFIER_LEFTSHIFT,
+	HID_KEYMODIFIER_LEFTALT,
+	HID_KEYMODIFIER_LEFTGUI,
+	HID_KEYMODIFIER_RIGHTCTRL,
+	HID_KEYMODIFIER_RIGHTSHIFT,
+	HID_KEYMODIFIER_RIGHTALT,
+	HID_KEYMODIFIER_RIGHTGUI
+};
+
+enum USB_HID_LOCAL_CODE
+{
+  HID_Local_NotSupported = 0,
+  HID_Local_Arabic,
+  HID_Local_Belgian,
+  HID_Local_Canadian_Bilingual,
+  HID_Local_Canadian_French,
+  HID_Local_Czech_Republic,
+  HID_Local_Danish,
+  HID_Local_Finnish,
+  HID_Local_French,
+  HID_Local_German,
+  HID_Local_Greek,
+  HID_Local_Hebrew,
+  HID_Local_Hungary,
+  HID_Local_International,
+  HID_Local_Italian,
+  HID_Local_Japan_Katakana,
+  HID_Local_Korean,
+  HID_Local_Latin_American,
+  HID_Local_Netherlands_Dutch,
+  HID_Local_Norwegian,
+  HID_Local_Persian_Farsi,
+  HID_Local_Poland,
+  HID_Local_Portuguese,
+  HID_Local_Russia,
+  HID_Local_Slovakia,
+  HID_Local_Spanish,
+  HID_Local_Swedish,
+  HID_Local_Swiss_French,
+  HID_Local_Swiss_German,
+  HID_Local_Switzerland,
+  HID_Local_Taiwan,
+  HID_Local_Turkish_Q,
+  HID_Local_UK,
+  HID_Local_US,
+  HID_Local_Yugoslavia,
+  HID_Local_Turkish_F
+};
+
+#ifdef __cplusplus
+ }
+#endif
+
+#endif /* _TUSB_HID_H__ */

+ 1 - 1
tinyusb/common/common.h

@@ -51,7 +51,7 @@
 #include "errors.h"
 
 //#if ( defined CFG_PRINTF_UART || defined CFG_PRINTF_USBCDC || defined CFG_PRINTF_DEBUG )
-#if 1
+#if 1 // TODO refractor ASSERT
   #define PRINTF_LOCATION(mess)	printf("Assert: %s at line %d: %s\n", __func__, __LINE__, mess)
 #else
   #define PRINTF_LOCATION(mess)

+ 212 - 0
tinyusb/common/fifo.c

@@ -0,0 +1,212 @@
+/*
+ * fifo.c
+ *
+ *  Created on: Nov 27, 2012
+ *      Author: hathach (thachha@live.com)
+ */
+
+/*
+ * Software License Agreement (BSD License)
+ * Copyright (c) 2012, hathach (thachha@live.com)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ *    this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ *    this list of conditions and the following disclaimer in the documentation
+ *    and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+ * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ *
+ * This file is part of the tiny usb stack.
+ */
+
+#include "fifo.h"
+
+/**************************************************************************/
+/*!
+    @brief Disables the IRQ specified in the FIFO's 'irq' field
+           to prevent reads/write issues with interrupts
+
+    @param[in]  f
+                Pointer to the FIFO that should be protected
+*/
+/**************************************************************************/
+static inline void mutex_lock (fifo_t* f)
+{
+  if (f->irq > 0)
+    NVIC_DisableIRQ(f->irq);
+}
+
+/**************************************************************************/
+/*!
+    @brief Re-enables the IRQ specified in the FIFO's 'irq' field
+
+    @param[in]  f
+                Pointer to the FIFO that should be protected
+*/
+/**************************************************************************/
+static inline void mutex_unlock (fifo_t* f)
+{
+  if (f->irq > 0)
+    NVIC_EnableIRQ(f->irq);
+}
+
+/**************************************************************************/
+/*!
+    @brief Initialises the FIFO buffer
+
+    @param[in]  f
+                Pointer to the fifo_t object to intiialize
+    @param[in]  buffer
+                Pointer to the buffer's location in memory
+    @param[in]  size
+                The buffer size in bytes
+    @param[in]  overwritable
+                Set to TRUE is the FIFO is overwritable when the FIFO
+                is full (the first element will be overwritten)
+    @param[in]  irq
+                The IRQ number to disable for MUTEX protection.
+                Set the -1 if not required.
+*/
+/**************************************************************************/
+void fifo_init(fifo_t* f, uint8_t* buffer, uint16_t size, bool overwritable, IRQn_Type irq)
+{
+  f->buf = buffer;
+  f->size = size;
+  f->rd_ptr = f->wr_ptr = f->len = 0;
+  f->overwritable = overwritable;
+  f->irq = irq;
+}
+
+/**************************************************************************/
+/*!
+    @brief Read one byte out of the RX buffer.
+
+    This function will return the byte located at the array index of the
+    read pointer, and then increment the read pointer index.  If the read
+    pointer exceeds the maximum buffer size, it will roll over to zero.
+
+    @param[in]  f
+                Pointer to the FIFO buffer to manipulate
+    @param[in]  data
+                Pointer to the place holder for data read from the buffer
+
+    @returns TRUE if the queue is not empty
+*/
+/**************************************************************************/
+bool fifo_read(fifo_t* f, uint8_t *data)
+{
+  if (fifo_isEmpty(f))
+    return false;
+
+  mutex_lock(f);
+
+  *data = f->buf[f->rd_ptr];
+  f->rd_ptr = (f->rd_ptr + 1) % f->size;
+  f->len--;
+
+  mutex_unlock(f);
+
+  return true;
+}
+
+/**************************************************************************/
+/*!
+    @brief Read a byte array from FIFO
+
+    @param[in]  f
+                Pointer to the FIFO buffer to manipulate
+    @param[in]  rx
+                Pointer to the place holder for data read from the buffer
+    @param[in]  maxlen
+                The maximum number of bytes to read from the FIFO
+
+    @returns The actual number of bytes read from the FIFO
+ */
+/**************************************************************************/
+uint16_t fifo_readArray(fifo_t* f, uint8_t* rx, uint16_t maxlen)
+{
+  uint16_t len = 0;
+  
+  while ( len < maxlen && fifo_read(f, rx) )
+  {
+    len++;
+    rx++;
+  }
+  
+  return len;
+}
+
+/**************************************************************************/
+/*!
+    @brief Write one byte into the RX buffer.
+
+    This function will write one byte into the array index specified by
+    the write pointer and increment the write index. If the write index
+    exceeds the max buffer size, then it will roll over to zero.
+
+    @param[in]  f
+                Pointer to the FIFO buffer to manipulate
+    @param[in]  data
+                The byte to add to the FIFO
+
+    @returns TRUE if the data was written to the FIFO (overwrittable
+             FIFO will always return TRUE)
+*/
+/**************************************************************************/
+bool fifo_write(fifo_t* f, uint8_t data)
+{
+  if ( fifo_isFull(f) && f->overwritable == false)
+      return false;
+
+  mutex_lock(f);
+
+  f->buf[f->wr_ptr] = data;
+  f->wr_ptr = (f->wr_ptr + 1) % f->size;
+
+  if (fifo_isFull(f))
+  {
+    f->rd_ptr = f->wr_ptr; // keep the full state (rd == wr && len = size)
+  }else
+  {
+    f->len++;
+  }
+
+  mutex_unlock(f);
+
+  return true;
+}
+
+/**************************************************************************/
+/*!
+    @brief Clear the fifo read and write pointers and set length to zero
+
+    @param[in]  f
+                Pointer to the FIFO buffer to manipulate
+*/
+/**************************************************************************/
+void fifo_clear(fifo_t *f)
+{
+  mutex_lock(f);
+
+  f->rd_ptr = 0;
+  f->wr_ptr = 0;
+  f->len = 0;
+
+  mutex_unlock(f);
+}

+ 76 - 0
tinyusb/common/fifo.h

@@ -0,0 +1,76 @@
+/*
+ * fifo.h
+ *
+ *  Created on: Nov 27, 2012
+ *      Author: hathach (thachha@live.com)
+ */
+
+/*
+ * Software License Agreement (BSD License)
+ * Copyright (c) 2012, hathach (thachha@live.com)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ *    this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ *    this list of conditions and the following disclaimer in the documentation
+ *    and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+ * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ *
+ * This file is part of the tiny usb stack.
+ */
+
+#ifndef _TUSB_FIFO_H_
+#define _TUSB_FIFO_H_
+
+#include "common/common.h"
+
+/* ToDo: Describe each field in fifo_t */
+typedef struct _fifo_t
+{
+  uint8_t* buf;
+  uint16_t size;
+  volatile uint16_t len;
+  volatile uint16_t wr_ptr;
+  volatile uint16_t rd_ptr;
+  bool overwritable;
+  IRQn_Type irq;
+} fifo_t;
+
+void fifo_init(fifo_t* f, uint8_t* buffer, uint16_t size, bool overwritable, IRQn_Type irq);
+bool fifo_write(fifo_t* f, uint8_t data);
+bool fifo_read(fifo_t* f, uint8_t *data);
+uint16_t fifo_readArray(fifo_t* f, uint8_t * rx, uint16_t maxlen);
+void fifo_clear(fifo_t*);
+
+static inline bool fifo_isEmpty(fifo_t* f)
+{
+  return (f->len == 0);
+}
+
+static inline bool fifo_isFull(fifo_t* f)
+{
+  return (f->len == f->size);
+}
+
+static inline uint16_t fifo_getLength(fifo_t* f)
+{
+  return f->len;
+}
+
+#endif /* _TUSB_FIFO_H_ */

+ 90 - 9
tinyusb/device/dcd.c

@@ -40,20 +40,58 @@
 // TODO refractor later
 #include "descriptors.h"
 
+#define USB_ROM_SIZE (1024*2)
+uint8_t usb_RomDriver_buffer[USB_ROM_SIZE]ALIGNED(2048) /*__BSS(RAM2)*/;
+USBD_HANDLE_T g_hUsb;
+volatile static bool isConfigured = false;
 
+/**************************************************************************/
+/*!
+    @brief Handler for the USB Configure Event
+*/
+/**************************************************************************/
+ErrorCode_t USB_Configure_Event (USBD_HANDLE_T hUsb)
+{
+  USB_CORE_CTRL_T* pCtrl = (USB_CORE_CTRL_T*)hUsb;
+  if (pCtrl->config_value)
+  {
+    #if defined(CLASS_HID)
+    ASSERT_STATUS( usb_hid_configured(hUsb) );
+    #endif
+
+    #ifdef CFG_USB_CDC
+    ASSERT_STATUS( usb_cdc_configured(hUsb) );
+    #endif
+  }
+
+  isConfigured = true;
+
+  return LPC_OK;
+}
+
+/**************************************************************************/
+/*!
+    @brief Handler for the USB Reset Event
+*/
+/**************************************************************************/
+ErrorCode_t USB_Reset_Event (USBD_HANDLE_T hUsb)
+{
+  isConfigured = false;
+  return LPC_OK;
+}
 
 void dcd_init()
 {
-    /* ROM DRIVER INIT */
+  /* ROM DRIVER INIT */
   USBD_API_INIT_PARAM_T usb_param =
   {
-//    .usb_reg_base        = LPC_USB_BASE,
-//    .max_num_ep          = USB_MAX_EP_NUM,
-//    .mem_base            = (uint32_t) usb_RomDriver_buffer,
-//    .mem_size            = USB_ROM_SIZE, //USBD_API->hw->GetMemSize()
-//
-//    .USB_Configure_Event = USB_Configure_Event,
-//    .USB_Reset_Event     = USB_Reset_Event
+    .usb_reg_base        = LPC_USB_BASE,
+    .max_num_ep          = USB_MAX_EP_NUM,
+    .mem_base            = (uint32_t) usb_RomDriver_buffer,
+    .mem_size            = USB_ROM_SIZE, //USBD_API->hw->GetMemSize()
+
+    .USB_Configure_Event = USB_Configure_Event,
+    .USB_Reset_Event     = USB_Reset_Event
   };
 
   USB_CORE_DESCS_T DeviceDes =
@@ -65,7 +103,50 @@ void dcd_init()
     .device_qualifier = NULL
   };
 
-  USBD_HANDLE_T g_hUsb;
   /* Start USB hardware initialisation */
   ASSERT_STATUS(USBD_API->hw->Init(&g_hUsb, &DeviceDes, &usb_param));
+
+    /* Initialise the class driver(s) */
+  #ifdef CFG_USB_CDC
+    ASSERT_STATUS( usb_cdc_init(g_hUsb, &USB_FsConfigDescriptor.CDC_CCI_Interface,
+            &USB_FsConfigDescriptor.CDC_DCI_Interface, &usb_param.mem_base, &usb_param.mem_size) );
+  #endif
+
+  #ifdef CFG_CLASS_HID_KEYBOARD
+    ASSERT_STATUS( usb_hid_init(g_hUsb , &USB_FsConfigDescriptor.HID_KeyboardInterface ,
+            HID_KeyboardReportDescriptor, USB_FsConfigDescriptor.HID_KeyboardHID.DescriptorList[0].wDescriptorLength,
+            &usb_param.mem_base , &usb_param.mem_size) );
+  #endif
+
+  #ifdef CFG_USB_HID_MOUSE
+    ASSERT_STATUS( usb_hid_init(g_hUsb , &USB_FsConfigDescriptor.HID_MouseInterface    ,
+            HID_MouseReportDescriptor, USB_FsConfigDescriptor.HID_MouseHID.DescriptorList[0].wDescriptorLength,
+            &usb_param.mem_base , &usb_param.mem_size) );
+  #endif
+
+  /* Enable the USB interrupt */
+  NVIC_EnableIRQ(USB_IRQ_IRQn);
+
+  /* Perform USB soft connect */
+  USBD_API->hw->Connect(g_hUsb, 1);
+}
+
+/**************************************************************************/
+/*!
+    @brief Indicates whether USB is configured or not
+*/
+/**************************************************************************/
+bool usb_isConfigured(void)
+{
+  return isConfigured;
+}
+
+/**************************************************************************/
+/*!
+    @brief Redirect the USB IRQ handler to the ROM handler
+*/
+/**************************************************************************/
+void USB_IRQHandler(void)
+{
+  USBD_API->hw->ISR(g_hUsb);
 }

+ 2 - 2
tinyusb/tusb_cfg.h

@@ -47,9 +47,9 @@
 #define CFG_TUSB_HOST
 #define CFG_TUSB_DEVICE
 
-#define CFG_USB_HID_KEYBOARD
+#define CFG_CLASS_HID_KEYBOARD
 
-#define CLASS_HID (defined CFG_USB_HID_KEYBOARD)
+#define CLASS_HID (defined CFG_CLASS_HID_KEYBOARD)
 
 
 // TODO APP