Просмотр исходного кода

add keyboard led mask
make usbd control request to subtask
add get/set report via control pipe to hidd
enforce soft DMA to control pipe for lpc11u (lpc17xx not yet)
temp add led_blinking_set_interval to change led blinking interval
refractor dcd_pipe_control_xfer to have interrupt on complete option
add get/set report support of moused_app and keyboardd_app, keyboard LED will make LED blink faster

hathach 12 лет назад
Родитель
Сommit
e320659f8a

+ 35 - 0
demos/device/device_os_none/keyboardd_app.c

@@ -80,6 +80,41 @@ void tusbd_hid_keyboard_cb(uint8_t coreid, tusb_event_t event, uint32_t xferred_
   }
 }
 
+uint16_t tusbd_hid_keyboard_get_report_cb(uint8_t coreid, hid_request_report_type_t report_type, void** pp_report, uint16_t requested_length)
+{
+  // get other than input report is not supported by this keyboard demo
+  if ( report_type != HID_REQUEST_REPORT_INPUT ) return 0;
+
+  (*pp_report) = &keyboard_report;
+  return requested_length;
+}
+
+void tusbd_hid_keyboard_set_report_cb(uint8_t coreid, hid_request_report_type_t report_type, uint8_t p_report_data[], uint16_t length)
+{
+  // set other than output report is not supported by this keyboard demo
+  if ( report_type != HID_REQUEST_REPORT_OUTPUT ) return;
+
+  uint8_t kbd_led = p_report_data[0];
+  uint32_t interval_divider = 1; // each LED will reduce blinking interval by a half
+
+  if (kbd_led & KEYBOARD_LED_NUMLOCK)
+  {
+    interval_divider *= 2;
+  }
+
+  if (kbd_led & KEYBOARD_LED_CAPSLOCK)
+  {
+    interval_divider *= 2;
+  }
+
+  if (kbd_led & KEYBOARD_LED_SCROLLLOCK)
+  {
+    interval_divider *= 2;
+  }
+
+  led_blinking_set_interval( 1000 / interval_divider);
+}
+
 //--------------------------------------------------------------------+
 // APPLICATION CODE
 //--------------------------------------------------------------------+

+ 8 - 2
demos/device/device_os_none/main.c

@@ -108,7 +108,7 @@ int main(void)
   #error need to start RTOS schduler
 #endif
 
-  while(1) { } // should not be reached here
+  while(1) { } // should not reach here
 
   return 0;
 }
@@ -116,13 +116,19 @@ int main(void)
 //--------------------------------------------------------------------+
 // BLINKING TASK
 //--------------------------------------------------------------------+
+static uint32_t led_blink_interval_ms = 1000; // default is 1 seconda
+void led_blinking_set_interval(uint32_t ms)
+{
+  led_blink_interval_ms = ms;
+}
+
 OSAL_TASK_FUNCTION( led_blinking_task ) (void* p_task_para)
 {
   OSAL_TASK_LOOP_BEGIN
 
   static uint32_t led_on_mask = 0;
 
-  osal_task_delay(1000);
+  osal_task_delay(led_blink_interval_ms);
 
   board_leds(led_on_mask, 1 - led_on_mask);
   led_on_mask = 1 - led_on_mask; // toggle

+ 13 - 0
demos/device/device_os_none/moused_app.c

@@ -80,6 +80,19 @@ void tusbd_hid_mouse_cb(uint8_t coreid, tusb_event_t event, uint32_t xferred_byt
   }
 }
 
+uint16_t tusbd_hid_mouse_get_report_cb(uint8_t coreid, hid_request_report_type_t report_type, void** pp_report, uint16_t requested_length)
+{
+  if ( report_type != HID_REQUEST_REPORT_INPUT ) return 0; // not support other report type for this mouse demo
+
+  (*pp_report) =  &mouse_report;
+  return requested_length;
+}
+
+void tusbd_hid_mouse_set_report_cb(uint8_t coreid, hid_request_report_type_t report_type, uint8_t report_data[], uint16_t length)
+{
+  // mouse demo does not support set report --> return 0 will result in rejecting (STALL) this request
+  return 0;
+}
 //--------------------------------------------------------------------+
 // APPLICATION CODE
 //--------------------------------------------------------------------+

+ 1 - 1
demos/device/device_os_none/tusb_config.h

@@ -87,7 +87,7 @@
 #define TUSB_CFG_DEVICE_HID_MOUSE     1
 #define TUSB_CFG_DEVICE_HID_GENERIC   0
 #define TUSB_CFG_DEVICE_MSC           0
-#define TUSB_CFG_DEVICE_CDC           0
+#define TUSB_CFG_DEVICE_CDC           1
 
 
 

+ 4 - 4
tinyusb/class/cdc_device.c

@@ -182,7 +182,7 @@ void cdcd_close(uint8_t coreid)
   memclr_(&cdcd_data[coreid], sizeof(cdcd_data_t));
 }
 
-tusb_error_t cdcd_control_request(uint8_t coreid, tusb_control_request_t const * p_request)
+tusb_error_t cdcd_control_request_subtask(uint8_t coreid, tusb_control_request_t const * p_request)
 {
   //------------- Class Specific Request -------------//
   if (p_request->bmRequestType_bit.type != TUSB_REQUEST_TYPE_CLASS) return TUSB_ERROR_DCD_CONTROL_REQUEST_NOT_SUPPORT;
@@ -191,17 +191,17 @@ tusb_error_t cdcd_control_request(uint8_t coreid, tusb_control_request_t const *
   {
     case CDC_REQUEST_GET_LINE_CODING:
       dcd_pipe_control_xfer(coreid, p_request->bmRequestType_bit.direction,
-                            &cdcd_line_coding[coreid], min16_of(sizeof(cdc_line_coding_t), p_request->wLength) );
+                            &cdcd_line_coding[coreid], min16_of(sizeof(cdc_line_coding_t), p_request->wLength), false );
     break;
 
     case CDC_REQUEST_SET_LINE_CODING:
       dcd_pipe_control_xfer(coreid, p_request->bmRequestType_bit.direction,
-                            &cdcd_line_coding[coreid], min16_of(sizeof(cdc_line_coding_t), p_request->wLength) );
+                            &cdcd_line_coding[coreid], min16_of(sizeof(cdc_line_coding_t), p_request->wLength), false );
       // TODO notify application on xfer complete
     break;
 
     case CDC_REQUEST_SET_CONTROL_LINE_STATE: // TODO extract DTE present
-      dcd_pipe_control_xfer(coreid, p_request->bmRequestType_bit.direction, NULL, 0);
+//      dcd_pipe_control_xfer(coreid, p_request->bmRequestType_bit.direction, NULL, 0);
     break;
 
 

+ 1 - 1
tinyusb/class/cdc_device.h

@@ -76,7 +76,7 @@ void tusbd_cdc_xfer_cb(uint8_t coreid, tusb_event_t event, cdc_pipeid_t pipe_id,
 
 void cdcd_init(void);
 tusb_error_t cdcd_open(uint8_t coreid, tusb_descriptor_interface_t const * p_interface_desc, uint16_t *p_length);
-tusb_error_t cdcd_control_request(uint8_t coreid, tusb_control_request_t const * p_request);
+tusb_error_t cdcd_control_request_subtask(uint8_t coreid, tusb_control_request_t const * p_request);
 tusb_error_t cdcd_xfer_cb(endpoint_handle_t edpt_hdl, tusb_event_t event, uint32_t xferred_bytes);
 void cdcd_close(uint8_t coreid);
 

+ 8 - 0
tinyusb/class/hid.h

@@ -199,6 +199,14 @@ typedef enum {
 	KEYBOARD_MODIFIER_RIGHTGUI   = BIT_(7)  ///< Right Window
 }hid_keyboard_modifier_bm_t;
 
+typedef enum {
+  KEYBOARD_LED_NUMLOCK    = BIT_(0), ///< Num Lock LED
+  KEYBOARD_LED_CAPSLOCK   = BIT_(1), ///< Caps Lock LED
+  KEYBOARD_LED_SCROLLLOCK = BIT_(2), ///< Scroll Lock LED
+  KEYBOARD_LED_COMPOSE    = BIT_(3), ///< Composition Mode
+  KEYBOARD_LED_KANA       = BIT_(4) ///< Kana mode
+}hid_keyboard_led_bm_t;
+
 /// @}
 
 #define HID_KEYCODE_TABLE(ENTRY) \

+ 48 - 28
tinyusb/class/hid_device.c

@@ -51,7 +51,6 @@
 //--------------------------------------------------------------------+
 // MACRO CONSTANT TYPEDEF
 //--------------------------------------------------------------------+
-ATTR_USB_MIN_ALIGNMENT uint8_t set_report[ MAX_OF(sizeof(hid_keyboard_report_t), sizeof(hid_mouse_report_t)) ] TUSB_CFG_ATTR_USBRAM;
 
 enum {
   HIDD_NUMBER_OF_SUBCLASS = 3
@@ -70,6 +69,8 @@ typedef struct {
   void (* const mounted_cb) (uint8_t coreid);
   void (* const unmounted_cb) (uint8_t coreid);
   void (* const xfer_cb) (uint8_t, tusb_event_t, uint32_t);
+  uint16_t (* const get_report_cb) (uint8_t, hid_request_report_type_t, void**, uint16_t );
+  void (* const set_report_cb) (uint8_t, hid_request_report_type_t, uint8_t[], uint16_t);
 }hidd_class_driver_t;
 
 extern ATTR_WEAK hidd_interface_t keyboardd_data;
@@ -86,7 +87,9 @@ static hidd_class_driver_t const hidd_class_driver[HIDD_NUMBER_OF_SUBCLASS] =
         .p_interface   = &keyboardd_data,
         .mounted_cb    = tusbd_hid_keyboard_mounted_cb,
         .unmounted_cb  = tusbd_hid_keyboard_unmounted_cb,
-        .xfer_cb       = tusbd_hid_keyboard_cb
+        .xfer_cb       = tusbd_hid_keyboard_cb,
+        .get_report_cb = tusbd_hid_keyboard_get_report_cb,
+        .set_report_cb = tusbd_hid_keyboard_set_report_cb
     },
 #endif
 
@@ -97,11 +100,17 @@ static hidd_class_driver_t const hidd_class_driver[HIDD_NUMBER_OF_SUBCLASS] =
         .p_interface   = &moused_data,
         .mounted_cb    = tusbd_hid_mouse_mounted_cb,
         .unmounted_cb  = tusbd_hid_mouse_unmounted_cb,
-        .xfer_cb       = tusbd_hid_mouse_cb
+        .xfer_cb       = tusbd_hid_mouse_cb,
+        .get_report_cb = tusbd_hid_mouse_get_report_cb,
+        .set_report_cb = tusbd_hid_mouse_set_report_cb
     }
 #endif
 };
 
+#if TUSB_CFG_DEVICE_HID_KEYBOARD || TUSB_CFG_DEVICE_HID_MOUSE
+ATTR_USB_MIN_ALIGNMENT uint8_t m_control_data[ MAX_OF(sizeof(hid_keyboard_report_t), sizeof(hid_mouse_report_t)) ] TUSB_CFG_ATTR_USBRAM;
+#endif
+
 //--------------------------------------------------------------------+
 // KEYBOARD APPLICATION API
 //--------------------------------------------------------------------+
@@ -180,7 +189,7 @@ void hidd_close(uint8_t coreid)
   }
 }
 
-tusb_error_t hidd_control_request(uint8_t coreid, tusb_control_request_t const * p_request)
+tusb_error_t hidd_control_request_subtask(uint8_t coreid, tusb_control_request_t const * p_request)
 {
   uint8_t subclass_idx;
   for(subclass_idx=0; subclass_idx<HIDD_NUMBER_OF_SUBCLASS; subclass_idx++)
@@ -194,7 +203,7 @@ tusb_error_t hidd_control_request(uint8_t coreid, tusb_control_request_t const *
 
   ASSERT(subclass_idx < HIDD_NUMBER_OF_SUBCLASS, TUSB_ERROR_FAILED);
 
-  hidd_class_driver_t* const p_driver = &hidd_class_driver[subclass_idx];
+  hidd_class_driver_t const * const p_driver = &hidd_class_driver[subclass_idx];
   hidd_interface_t* const p_hid = p_driver->p_interface;
 
   //------------- STD Request -------------//
@@ -208,39 +217,50 @@ tusb_error_t hidd_control_request(uint8_t coreid, tusb_control_request_t const *
     ASSERT ( p_request->bRequest == TUSB_REQUEST_GET_DESCRIPTOR && desc_type == HID_DESC_TYPE_REPORT,
              TUSB_ERROR_DCD_CONTROL_REQUEST_NOT_SUPPORT);
 
-    dcd_pipe_control_xfer(coreid, TUSB_DIR_DEV_TO_HOST, p_driver->p_report_desc, p_hid->report_length);
+    dcd_pipe_control_xfer(coreid, TUSB_DIR_DEV_TO_HOST, p_driver->p_report_desc, p_hid->report_length, false);
   }
   //------------- Class Specific Request -------------//
   else if (p_request->bmRequestType_bit.type == TUSB_REQUEST_TYPE_CLASS)
   {
-    switch(p_request->bRequest)
+    OSAL_SUBTASK_BEGIN
+
+    if( (HID_REQUEST_CONTROL_GET_REPORT == p_request->bRequest) && (p_driver->get_report_cb != NULL) )
     {
-      case HID_REQUEST_CONTROL_SET_IDLE:
-        // idle_rate = u16_high_u8(p_request->wValue);
-      break;
+      // wValue = Report Type | Report ID
+      void* p_buffer = NULL;
 
-      case HID_REQUEST_CONTROL_SET_REPORT:
-      {
-//        return TUSB_ERROR_DCD_CONTROL_REQUEST_NOT_SUPPORT; // TODO test STALL control out endpoint (with mouse+keyboard)aaaaa
+      uint16_t actual_length = p_driver->get_report_cb(coreid, (hid_request_report_type_t) u16_high_u8(p_request->wValue),
+                                                       &p_buffer, p_request->wLength);
+      SUBTASK_ASSERT( p_buffer != NULL && actual_length > 0 );
 
-        // TODO HIDD set report support
-        hid_request_report_type_t report_type = u16_high_u8(p_request->wValue);
-        uint8_t report_id = u16_low_u8(p_request->wValue);
+      dcd_pipe_control_xfer(coreid, p_request->bmRequestType_bit.direction, p_buffer, actual_length, false);
+    }
+    else if ( (HID_REQUEST_CONTROL_SET_REPORT == p_request->bRequest) && (p_driver->set_report_cb != NULL) )
+    {
+      //        return TUSB_ERROR_DCD_CONTROL_REQUEST_NOT_SUPPORT; // TODO test STALL control out endpoint (with mouse+keyboard)
+      // wValue = Report Type | Report ID
+      tusb_error_t error;
 
-        (void) report_id;
-        (void) report_type;
+      dcd_pipe_control_xfer(coreid, p_request->bmRequestType_bit.direction, &m_control_data, p_request->wLength, true);
 
-        dcd_pipe_control_xfer(coreid, TUSB_DIR_HOST_TO_DEV, &set_report, p_request->wLength);
-      }
-      break;
+      osal_semaphore_wait(usbd_control_xfer_sem_hdl, OSAL_TIMEOUT_NORMAL, &error); // wait for control xfer complete
+      SUBTASK_ASSERT_STATUS(error);
 
-      case HID_REQUEST_CONTROL_GET_IDLE:
-      case HID_REQUEST_CONTROL_GET_REPORT:
-      case HID_REQUEST_CONTROL_GET_PROTOCOL:
-      case HID_REQUEST_CONTROL_SET_PROTOCOL:
-      default:
-        return TUSB_ERROR_DCD_CONTROL_REQUEST_NOT_SUPPORT;
+      p_driver->set_report_cb(coreid, (hid_request_report_type_t) u16_high_u8(p_request->wValue),
+                              &m_control_data, p_request->wLength);
     }
+    else if (HID_REQUEST_CONTROL_SET_IDLE == p_request->bRequest)
+    {
+      // uint8_t idle_rate = u16_high_u8(p_request->wValue);
+    }else
+    {
+//      HID_REQUEST_CONTROL_GET_IDLE:
+//      HID_REQUEST_CONTROL_GET_PROTOCOL:
+//      HID_REQUEST_CONTROL_SET_PROTOCOL:
+      return TUSB_ERROR_DCD_CONTROL_REQUEST_NOT_SUPPORT;
+    }
+
+    OSAL_SUBTASK_END
   }else
   {
     return TUSB_ERROR_DCD_CONTROL_REQUEST_NOT_SUPPORT;
@@ -270,7 +290,7 @@ tusb_error_t hidd_open(uint8_t coreid, tusb_descriptor_interface_t const * p_int
       case HID_PROTOCOL_KEYBOARD:
       case HID_PROTOCOL_MOUSE:
       {
-        hidd_class_driver_t * const p_driver = &hidd_class_driver[p_interface_desc->bInterfaceProtocol];
+        hidd_class_driver_t const * const p_driver = &hidd_class_driver[p_interface_desc->bInterfaceProtocol];
         hidd_interface_t * const p_hid = p_driver->p_interface;
 
         ASSERT_PTR(p_hid, TUSB_ERROR_FAILED);

+ 5 - 5
tinyusb/class/hid_device.h

@@ -94,8 +94,8 @@ void tusbd_hid_keyboard_unmounted_cb(uint8_t coreid);
  */
 void tusbd_hid_keyboard_cb(uint8_t coreid, tusb_event_t event, uint32_t xferred_bytes);
 
-void tusbd_hid_keyboard_set_report_cb(uint8_t coreid, hid_request_report_type_t report_type, uint8_t report_data[]);
-void tusbd_hid_keyboard_get_report_cb(uint8_t coreid, hid_request_report_type_t report_type, void** pp_report);
+void tusbd_hid_keyboard_set_report_cb(uint8_t coreid, hid_request_report_type_t report_type, uint8_t p_report_data[], uint16_t length);
+uint16_t tusbd_hid_keyboard_get_report_cb(uint8_t coreid, hid_request_report_type_t report_type, void** pp_report, uint16_t requested_length);
 
 /** @} */
 /** @} */
@@ -108,8 +108,6 @@ void tusbd_hid_keyboard_get_report_cb(uint8_t coreid, hid_request_report_type_t
 /** \defgroup Mouse_Device Device
  *  @{ */
 
-//bool tusbd_hid_mouse_is_configured(uint8_t coreid);
-
 /** \brief      Check if the interface is currently busy or not
  * \param[in]   coreid USB Controller ID
  * \retval      true if the interface is busy meaning the stack is still transferring/waiting data from/to host
@@ -149,6 +147,8 @@ void tusbd_hid_mouse_unmounted_cb(uint8_t coreid);
  */
 void tusbd_hid_mouse_cb(uint8_t coreid, tusb_event_t event, uint32_t xferred_bytes);
 
+uint16_t tusbd_hid_mouse_get_report_cb(uint8_t coreid, hid_request_report_type_t report_type, void** pp_report, uint16_t requested_length);
+void tusbd_hid_mouse_set_report_cb(uint8_t coreid, hid_request_report_type_t report_type, uint8_t p_report_data[], uint16_t length);
 /** @} */
 /** @} */
 
@@ -161,7 +161,7 @@ void tusbd_hid_mouse_cb(uint8_t coreid, tusb_event_t event, uint32_t xferred_byt
 
 void hidd_init(void);
 tusb_error_t hidd_open(uint8_t coreid, tusb_descriptor_interface_t const * p_interface_desc, uint16_t *p_length);
-tusb_error_t hidd_control_request(uint8_t coreid, tusb_control_request_t const * p_request);
+tusb_error_t hidd_control_request_subtask(uint8_t coreid, tusb_control_request_t const * p_request);
 tusb_error_t hidd_xfer_cb(endpoint_handle_t edpt_hdl, tusb_event_t event, uint32_t xferred_bytes);
 void hidd_close(uint8_t coreid);
 

+ 1 - 1
tinyusb/class/msc_device.c

@@ -113,7 +113,7 @@ tusb_error_t mscd_open(uint8_t coreid, tusb_descriptor_interface_t const * p_int
   return TUSB_ERROR_NONE;
 }
 
-tusb_error_t mscd_control_request(uint8_t coreid, tusb_control_request_t const * p_request)
+tusb_error_t mscd_control_request_subtask(uint8_t coreid, tusb_control_request_t const * p_request)
 {
   ASSERT(p_request->bmRequestType_bit.type == TUSB_REQUEST_TYPE_CLASS, TUSB_ERROR_DCD_CONTROL_REQUEST_NOT_SUPPORT);
 

+ 1 - 1
tinyusb/class/msc_device.h

@@ -126,7 +126,7 @@ msc_csw_status_t tusbd_msc_scsi_received_isr (uint8_t coreid, uint8_t lun, uint8
 
 void mscd_init(void);
 tusb_error_t mscd_open(uint8_t coreid, tusb_descriptor_interface_t const * p_interface_desc, uint16_t *p_length);
-tusb_error_t mscd_control_request(uint8_t coreid, tusb_control_request_t const * p_request);
+tusb_error_t mscd_control_request_subtask(uint8_t coreid, tusb_control_request_t const * p_request);
 tusb_error_t mscd_xfer_cb(endpoint_handle_t edpt_hdl, tusb_event_t event, uint32_t xferred_bytes);
 void mscd_close(uint8_t coreid);
 

+ 3 - 0
tinyusb/common/common.h

@@ -83,6 +83,8 @@
 #include "std_descriptors.h"
 #include "std_request.h"
 
+#include "osal/osal.h"
+
 
 //--------------------------------------------------------------------+
 // MACROS
@@ -93,6 +95,7 @@
 #define XSTRING_CONCAT_(a, b) STRING_CONCAT_(a, b) // expand then concat
 
 #define MAX_OF(a, b)  ( (a) > (b) ? (a) : (b) )
+#define MIN_OF(a, b)  ( (a) < (b) ? (a) : (b) )
 
 #define U16_HIGH_U8(u16) ((uint8_t) (((u16) >> 8) & 0x00ff))
 #define U16_LOW_U8(u16)  ((uint8_t) ((u16)       & 0x00ff))

+ 1 - 1
tinyusb/device/dcd.h

@@ -81,7 +81,7 @@ void dcd_controller_set_address(uint8_t coreid, uint8_t dev_addr);
 void dcd_controller_set_configuration(uint8_t coreid);
 
 //------------- PIPE API -------------//
-tusb_error_t dcd_pipe_control_xfer(uint8_t coreid, tusb_direction_t dir, void * p_buffer, uint16_t length);
+tusb_error_t dcd_pipe_control_xfer(uint8_t coreid, tusb_direction_t dir, void * p_buffer, uint16_t length, bool int_on_complete);
 void dcd_pipe_control_stall(uint8_t coreid);
 
 endpoint_handle_t dcd_pipe_open(uint8_t coreid, tusb_descriptor_endpoint_t const * p_endpoint_desc, uint8_t class_code) ATTR_WARN_UNUSED_RESULT;

+ 99 - 59
tinyusb/device/dcd_lpc_11uxx_13uxx.c

@@ -114,7 +114,7 @@ typedef struct {
   }next_td[DCD_11U_13U_QHD_COUNT];
 
   uint32_t current_ioc; ///< interrupt on complete mask for current TD
-  uint32_t next_ioc;    ///< interrupt on complete mask for next TD
+  uint32_t next_ioc;             ///< interrupt on complete mask for next TD
 
   // should start from 128
   ATTR_ALIGNED(64) tusb_control_request_t setup_request;
@@ -200,6 +200,61 @@ static void bus_reset(void)
   LPC_USB->INTEN        = INT_MASK_DEVICE_STATUS | BIT_(0) | BIT_(1); // enable device status & control endpoints
 }
 
+static void endpoint_non_control_isr(uint32_t int_status)
+{
+  for(uint8_t ep_id = 2; ep_id < DCD_11U_13U_QHD_COUNT; ep_id++ )
+  {
+    if ( BIT_TEST_(int_status, ep_id) )
+    {
+      dcd_11u_13u_qhd_t * const arr_qhd = dcd_data.qhd[ep_id];
+
+      // when double buffering, the complete buffer is opposed to the current active buffer in EPINUSE
+      uint8_t const buff_idx = LPC_USB->EPINUSE & BIT_(ep_id) ? 0 : 1;
+      uint16_t const xferred_bytes = dcd_data.current_td[ep_id].queued_bytes_in_buff[buff_idx] - arr_qhd[buff_idx].total_bytes;
+
+      dcd_data.current_td[ep_id].xferred_total += xferred_bytes;
+
+      // there are still data to transfer.
+      if ( (arr_qhd[buff_idx].total_bytes == 0) && (dcd_data.current_td[ep_id].remaining_bytes > 0) )
+      { // NOTE although buff_addr_offset has been increased when xfer is completed
+        // but we still need to increase it one more as we are using double buffering.
+        queue_xfer_to_buffer(ep_id, buff_idx, arr_qhd[buff_idx].buff_addr_offset+1, dcd_data.current_td[ep_id].remaining_bytes);
+      }
+      // short packet or (no more byte and both buffers are finished)
+      else if ( (arr_qhd[buff_idx].total_bytes > 0) || !arr_qhd[1-buff_idx].active  )
+      { // current TD (request) is completed
+        LPC_USB->EPSKIP   = BIT_SET_(LPC_USB->EPSKIP, ep_id); // skip other endpoint in case of short-package
+
+        dcd_data.current_td[ep_id].remaining_bytes = 0;
+
+        if ( BIT_TEST_(dcd_data.current_ioc, ep_id) )
+        {
+          endpoint_handle_t edpt_hdl =
+          {
+              .coreid     = 0,
+              .index      = ep_id,
+              .class_code = dcd_data.class_code[ep_id]
+          };
+
+          dcd_data.current_ioc = BIT_CLR_(dcd_data.current_ioc, edpt_hdl.index);
+
+          // TODO no way determine if the transfer is failed or not
+          usbd_xfer_isr(edpt_hdl, TUSB_EVENT_XFER_COMPLETE, dcd_data.current_td[ep_id].xferred_total);
+        }
+
+        //------------- Next TD is available -------------//
+        if ( dcd_data.next_td[ep_id].total_bytes != 0 )
+        {
+          queue_xfer_in_next_td(ep_id);
+        }
+      }else
+      {
+        // transfer complete, there is no more remaining bytes, but this buffer is not the last transaction (the other is)
+      }
+    }
+  }
+}
+
 void dcd_isr(uint8_t coreid)
 {
   (void) coreid;
@@ -248,7 +303,7 @@ void dcd_isr(uint8_t coreid)
 //    }
   }
 
-  //------------- Control Endpoint -------------//
+  //------------- Setup Received -------------//
   if ( BIT_TEST_(int_status, 0) && (dev_cmd_stat & CMDSTAT_SETUP_RECEIVED_MASK) )
   { // received control request from host
     // copy setup request & acknowledge so that the next setup can be received by hw
@@ -260,88 +315,73 @@ void dcd_isr(uint8_t coreid)
     LPC_USB->DEVCMDSTAT |= CMDSTAT_SETUP_RECEIVED_MASK;
     dcd_data.qhd[0][1].buff_addr_offset = addr_offset(&dcd_data.setup_request);
   }
+  //------------- Control Endpoint -------------//
   else if ( int_status & 0x03 )
   { // either control endpoints
-    endpoint_handle_t edpt_hdl =
-    {
-        .coreid     = coreid,
-        .index      = BIT_TEST_(int_status, 1) ? 1 : 0
-    };
+    uint8_t const ep_id = ( int_status & BIT_(0) ) ? 0 : 1;
 
-    // FIXME xferred_byte for control xfer is not needed now !!!
-    usbd_xfer_isr(edpt_hdl, TUSB_EVENT_XFER_COMPLETE, 0);
-  }
-
-  //------------- Non-Control Endpoints -------------//
-  for(uint8_t ep_id = 2; ep_id < DCD_11U_13U_QHD_COUNT; ep_id++ )
-  {
-    if ( BIT_TEST_(int_status, ep_id) )
+    // there are still data to transfer.
+    if ( (dcd_data.qhd[ep_id][0].total_bytes == 0) && (dcd_data.current_td[ep_id].remaining_bytes > 0) )
     {
-      dcd_11u_13u_qhd_t * const arr_qhd = dcd_data.qhd[ep_id];
-
-      // when double buffering, the complete buffer is opposed to the current active buffer in EPINUSE
-      uint8_t const buff_idx = LPC_USB->EPINUSE & BIT_(ep_id) ? 0 : 1;
-      uint16_t const xferred_bytes = dcd_data.current_td[ep_id].queued_bytes_in_buff[buff_idx] - arr_qhd[buff_idx].total_bytes;
-
-      dcd_data.current_td[ep_id].xferred_total += xferred_bytes;
-
-      // there are still data to transfer.
-      if ( (arr_qhd[buff_idx].total_bytes == 0) && (dcd_data.current_td[ep_id].remaining_bytes > 0) )
-      { // NOTE although buff_addr_offset has been increased when xfer is completed
-        // but we still need to increase it one more as we are using double buffering.
-        queue_xfer_to_buffer(ep_id, buff_idx, arr_qhd[buff_idx].buff_addr_offset+1, dcd_data.current_td[ep_id].remaining_bytes);
-      }
-      // short packet or (no more byte and both buffers are finished)
-      else if ( (arr_qhd[buff_idx].total_bytes > 0) || !arr_qhd[1-buff_idx].active  )
-      { // current TD (request) is completed
-        LPC_USB->EPSKIP   = BIT_SET_(LPC_USB->EPSKIP, ep_id); // skip other endpoint in case of short-package
-
-        dcd_data.current_td[ep_id].remaining_bytes = 0;
+      queue_xfer_to_buffer(ep_id, 0, dcd_data.qhd[ep_id][0].buff_addr_offset, dcd_data.current_td[ep_id].remaining_bytes);
+    }else
+    {
+      dcd_data.current_td[ep_id].remaining_bytes = 0;
 
-        if ( BIT_TEST_(dcd_data.current_ioc, ep_id) )
+      if ( BIT_TEST_(dcd_data.current_ioc, ep_id) )
+      {
+        endpoint_handle_t edpt_hdl =
         {
-          endpoint_handle_t edpt_hdl =
-          {
-              .coreid     = coreid,
-              .index      = ep_id,
-              .class_code = dcd_data.class_code[ep_id]
-          };
+            .coreid     = coreid,
+            .index      = 0
+        };
 
-          dcd_data.current_ioc = BIT_CLR_(dcd_data.current_ioc, edpt_hdl.index);
+        dcd_data.current_ioc = BIT_CLR_(dcd_data.current_ioc, edpt_hdl.index);
 
-          // TODO no way determine if the transfer is failed or not
-          usbd_xfer_isr(edpt_hdl, TUSB_EVENT_XFER_COMPLETE, dcd_data.current_td[ep_id].xferred_total);
-        }
-
-        //------------- Next TD is available -------------//
-        if ( dcd_data.next_td[ep_id].total_bytes != 0 )
-        {
-          queue_xfer_in_next_td(ep_id);
-        }
+        // FIXME xferred_byte for control xfer is not needed now !!!
+        usbd_xfer_isr(edpt_hdl, TUSB_EVENT_XFER_COMPLETE, 0);
       }
     }
   }
+
+  //------------- Non-Control Endpoints -------------//
+  endpoint_non_control_isr(int_status);
 }
 
 //--------------------------------------------------------------------+
 // CONTROL PIPE API
 //--------------------------------------------------------------------+
 void dcd_pipe_control_stall(uint8_t coreid)
-{ // TODO cannot able to STALL Control OUT endpoint !!!!!
+{
   (void) coreid;
-
+  // TODO cannot able to STALL Control OUT endpoint !!!!! FIXME try some walk-around
   dcd_data.qhd[0][0].stall = dcd_data.qhd[1][0].stall = 1;
 }
 
-tusb_error_t dcd_pipe_control_xfer(uint8_t coreid, tusb_direction_t dir, void * p_buffer, uint16_t length)
+tusb_error_t dcd_pipe_control_xfer(uint8_t coreid, tusb_direction_t dir, void * p_buffer, uint16_t length, bool int_on_complete)
 {
   (void) coreid;
 
-  uint8_t const ep_id = dir; // IN : 1, OUT = 0
+  // determine Endpoint where Data & Status phase occurred (IN or OUT)
+  uint8_t const ep_data   = (dir == TUSB_DIR_DEV_TO_HOST) ? 1 : 0;
+  uint8_t const ep_status = 1 - ep_data;
+
+  dcd_data.current_ioc = int_on_complete ? BIT_SET_(dcd_data.current_ioc, ep_status) : BIT_CLR_(dcd_data.current_ioc, ep_status);
+
+  //------------- Data Phase -------------//
+  if (length)
+  {
+    dcd_data.current_td[ep_data].remaining_bytes = length;
+    dcd_data.current_td[ep_data].xferred_total   = 0;
+
+    queue_xfer_to_buffer(ep_data, 0, addr_offset(p_buffer), length);
+  }
+
+  //------------- Status Phase -------------//
+  dcd_data.current_td[ep_status].remaining_bytes = 0;
+  dcd_data.current_td[ep_status].xferred_total   = 0;
 
-  dcd_data.qhd[ep_id][0].buff_addr_offset = (length ? addr_offset(p_buffer) : 0 );
-  dcd_data.qhd[ep_id][0].total_bytes      = length;
-  dcd_data.qhd[ep_id][0].active           = 1 ;
+  queue_xfer_to_buffer(ep_status, 0, NULL, 0);
 
   return TUSB_ERROR_NONE;
 }

+ 28 - 51
tinyusb/device/usbd.c

@@ -49,13 +49,6 @@
 #include "tusb_descriptors.h" // TODO callback include
 #include "usbd_dcd.h"
 
-// Some MCUs cannot transfer more than 64 bytes each queue, thus require special task-alike treatment
-#if TUSB_CFG_MCU == MCU_LPC11UXX || TUSB_CFG_MCU == MCU_LPC175X_6X
-  #define USBD_CONTROL_ONE_PACKET_EACH_XFER // for each Transfer, cannot queue more than packet size
-  enum {
-    USBD_COTNROL_MAX_LENGTH_EACH_XFER = 64
-  };
-#endif
 //--------------------------------------------------------------------+
 // MACRO CONSTANT TYPEDEF
 //--------------------------------------------------------------------+
@@ -67,33 +60,33 @@ static usbd_class_driver_t const usbd_class_drivers[TUSB_CLASS_MAPPED_INDEX_STAR
 #if DEVICE_CLASS_HID
     [TUSB_CLASS_HID] =
     {
-        .init            = hidd_init,
-        .open            = hidd_open,
-        .control_request = hidd_control_request,
-        .xfer_cb         = hidd_xfer_cb,
-        .close           = hidd_close
+        .init                    = hidd_init,
+        .open                    = hidd_open,
+        .control_request_subtask = hidd_control_request_subtask,
+        .xfer_cb                 = hidd_xfer_cb,
+        .close                   = hidd_close
     },
 #endif
 
 #if TUSB_CFG_DEVICE_MSC
     [TUSB_CLASS_MSC] =
     {
-        .init            = mscd_init,
-        .open            = mscd_open,
-        .control_request = mscd_control_request,
-        .xfer_cb         = mscd_xfer_cb,
-        .close           = mscd_close
+        .init                    = mscd_init,
+        .open                    = mscd_open,
+        .control_request_subtask = mscd_control_request_subtask,
+        .xfer_cb                 = mscd_xfer_cb,
+        .close                   = mscd_close
     },
 #endif
 
 #if TUSB_CFG_DEVICE_CDC
     [TUSB_CLASS_CDC] =
     {
-        .init            = cdcd_init,
-        .open            = cdcd_open,
-        .control_request = cdcd_control_request,
-        .xfer_cb         = cdcd_xfer_cb,
-        .close           = cdcd_close
+        .init                    = cdcd_init,
+        .open                    = cdcd_open,
+        .control_request_subtask = cdcd_control_request_subtask,
+        .xfer_cb                 = cdcd_xfer_cb,
+        .close                   = cdcd_close
     },
 #endif
 
@@ -151,7 +144,7 @@ OSAL_QUEUE_DEF(usbd_queue_def, USBD_TASK_QUEUE_DEPTH, usbd_task_event_t);
 OSAL_SEM_DEF(usbd_control_xfer_semaphore_def);
 
 static osal_queue_handle_t usbd_queue_hdl;
-static osal_semaphore_handle_t usbd_control_xfer_sem_hdl;
+/*static*/ osal_semaphore_handle_t usbd_control_xfer_sem_hdl; // TODO may need to change to static with wrapper function
 
 tusb_error_t usbd_control_request_subtask(uint8_t coreid, tusb_control_request_t const * const p_request)
 {
@@ -165,29 +158,14 @@ tusb_error_t usbd_control_request_subtask(uint8_t coreid, tusb_control_request_t
   {
     if ( TUSB_REQUEST_GET_DESCRIPTOR == p_request->bRequest )
     {
-      OSAL_VAR uint8_t* p_buffer = NULL;
-      OSAL_VAR uint16_t length = 0;
+      uint8_t* p_buffer = NULL;
+      uint16_t length = 0;
 
       error = get_descriptor_subtask(coreid, p_request, &p_buffer, &length);
 
-#ifdef USBD_CONTROL_ONE_PACKET_EACH_XFER
-      while ( length > USBD_COTNROL_MAX_LENGTH_EACH_XFER && error == TUSB_ERROR_NONE )
-      {
-        usbd_devices[coreid].is_waiting_control_xfer = true;
-
-        dcd_pipe_control_xfer(coreid, p_request->bmRequestType_bit.direction, p_buffer, USBD_COTNROL_MAX_LENGTH_EACH_XFER); // zero length
-        osal_semaphore_wait(usbd_control_xfer_sem_hdl, OSAL_TIMEOUT_NORMAL, &error);
-
-        length   -= USBD_COTNROL_MAX_LENGTH_EACH_XFER;
-        p_buffer += USBD_COTNROL_MAX_LENGTH_EACH_XFER;
-
-        usbd_devices[coreid].is_waiting_control_xfer = false;
-      }
-#endif
-
       if ( TUSB_ERROR_NONE == error )
       {
-        dcd_pipe_control_xfer(coreid, p_request->bmRequestType_bit.direction, p_buffer, length);
+        dcd_pipe_control_xfer(coreid, p_request->bmRequestType_bit.direction, p_buffer, length, false);
       }
     }
     else if ( TUSB_REQUEST_SET_ADDRESS == p_request->bRequest )
@@ -207,12 +185,14 @@ tusb_error_t usbd_control_request_subtask(uint8_t coreid, tusb_control_request_t
   //------------- Class/Interface Specific Request -------------//
   else if ( TUSB_REQUEST_RECIPIENT_INTERFACE == p_request->bmRequestType_bit.recipient)
   {
-    tusb_std_class_code_t class_code = usbd_devices[coreid].interface2class[ u16_low_u8(p_request->wIndex) ];
+    OSAL_VAR tusb_std_class_code_t class_code;
+
+    class_code = usbd_devices[coreid].interface2class[ u16_low_u8(p_request->wIndex) ];
 
     if ( (TUSB_CLASS_AUDIO <= class_code) && (class_code <= TUSB_CLASS_AUDIO_VIDEO) &&
-         usbd_class_drivers[class_code].control_request )
+         usbd_class_drivers[class_code].control_request_subtask )
     {
-      error = usbd_class_drivers[class_code].control_request(coreid, p_request);
+      OSAL_SUBTASK_INVOKED_AND_WAIT( usbd_class_drivers[class_code].control_request_subtask(coreid, p_request), error );
     }else
     {
       error = TUSB_ERROR_DCD_CONTROL_REQUEST_NOT_SUPPORT;
@@ -234,9 +214,9 @@ tusb_error_t usbd_control_request_subtask(uint8_t coreid, tusb_control_request_t
   { // Response with Protocol Stall if request is not supported
     dcd_pipe_control_stall(coreid);
     //    ASSERT(error == TUSB_ERROR_NONE, VOID_RETURN);
-  }else
-  { // status phase
-    dcd_pipe_control_xfer(coreid, 1-p_request->bmRequestType_bit.direction, NULL, 0); // zero length
+  }else if (p_request->wLength == 0)
+  {
+    dcd_pipe_control_xfer(coreid, p_request->bmRequestType_bit.direction, NULL, 0, false); // zero length for non-data
   }
 
   OSAL_SUBTASK_END
@@ -418,10 +398,7 @@ void usbd_xfer_isr(endpoint_handle_t edpt_hdl, tusb_event_t event, uint32_t xfer
 {
   if (edpt_hdl.class_code == 0 ) // Control Transfer
   {
-    if (usbd_devices[edpt_hdl.coreid].is_waiting_control_xfer)
-    {
-      osal_semaphore_post( usbd_control_xfer_sem_hdl );
-    }
+    osal_semaphore_post( usbd_control_xfer_sem_hdl );
   }else
   {
     usbd_task_event_t task_event =

+ 4 - 1
tinyusb/device/usbd.h

@@ -70,7 +70,7 @@
 typedef struct {
   void (* const init) (void);
   tusb_error_t (* const open)(uint8_t, tusb_descriptor_interface_t const *, uint16_t*);
-  tusb_error_t (* const control_request) (uint8_t, tusb_control_request_t const *);
+  tusb_error_t (* const control_request_subtask) (uint8_t, tusb_control_request_t const *);
   tusb_error_t (* const xfer_cb) (endpoint_handle_t, tusb_event_t, uint32_t);
   void (* const close) (uint8_t);
 } usbd_class_driver_t;
@@ -90,8 +90,11 @@ bool tusbd_is_configured(uint8_t coreid) ATTR_WARN_UNUSED_RESULT;
 //--------------------------------------------------------------------+
 #ifdef _TINY_USB_SOURCE_FILE_
 
+extern osal_semaphore_handle_t usbd_control_xfer_sem_hdl;
+
 tusb_error_t usbd_init(void);
 OSAL_TASK_FUNCTION (usbd_task) (void* p_task_para);
+
 #endif
 
 #ifdef __cplusplus

+ 0 - 1
tinyusb/device/usbd_dcd.h

@@ -68,7 +68,6 @@ typedef enum {
 
 typedef struct {
   volatile uint8_t state;
-  uint8_t is_waiting_control_xfer;             // set if task is waiting for control xfer to complete to proceed
   uint8_t interface2class[USBD_INTERFACE_NUM_MAX]; // determine interface number belongs to which class
 }usbd_device_info_t;