Explorar o código

add tuh_hid_receive_report() for applicaiton to explicitly request report

hathach %!s(int64=4) %!d(string=hai) anos
pai
achega
800f85329e

+ 13 - 0
examples/host/cdc_msc_hid/src/hid_app.c

@@ -80,6 +80,13 @@ void tuh_hid_mount_cb(uint8_t dev_addr, uint8_t instance, uint8_t const* desc_re
     hid_info[instance].report_count = tuh_hid_parse_report_descriptor(hid_info[instance].report_info, MAX_REPORT, desc_report, desc_len);
     printf("HID has %u reports \r\n", hid_info[instance].report_count);
   }
+
+  // request to receive report
+  // tuh_hid_report_received_cb() will be invoked when report is available
+  if ( !tuh_hid_receive_report(dev_addr, instance) )
+  {
+    printf("Error: cannot request to receive report\r\n");
+  }
 }
 
 // Invoked when device with hid interface is un-mounted
@@ -110,6 +117,12 @@ void tuh_hid_report_received_cb(uint8_t dev_addr, uint8_t instance, uint8_t cons
       process_generic_report(dev_addr, instance, report, len);
     break;
   }
+
+  // continue to request to receive report
+  if ( !tuh_hid_receive_report(dev_addr, instance) )
+  {
+    printf("Error: cannot request to receive report\r\n");
+  }
 }
 
 //--------------------------------------------------------------------+

+ 2 - 27
examples/host/cdc_msc_hid/src/main.c

@@ -33,7 +33,6 @@
 //--------------------------------------------------------------------+
 // MACRO CONSTANT TYPEDEF PROTYPES
 //--------------------------------------------------------------------+
-void print_greeting(void);
 void led_blinking_task(void);
 
 extern void cdc_task(void);
@@ -43,7 +42,8 @@ extern void hid_app_task(void);
 int main(void)
 {
   board_init();
-  print_greeting();
+
+  printf("TinyUSB Host CDC MSC HID Example\r\n");
 
   tusb_init();
 
@@ -126,28 +126,3 @@ void led_blinking_task(void)
   board_led_write(led_state);
   led_state = 1 - led_state; // toggle
 }
-
-//--------------------------------------------------------------------+
-// HELPER FUNCTION
-//--------------------------------------------------------------------+
-void print_greeting(void)
-{
-  char const * const rtos_name[] =
-  {
-      [OPT_OS_NONE]      = "None",
-      [OPT_OS_FREERTOS]  = "FreeRTOS",
-      [OPT_OS_MYNEWT]    = "Mynewt OS",
-      [OPT_OS_CUSTOM]    = "Custom OS implemnted by application",
-      [OPT_OS_PICO]      = "Raspberry Pi Pico SDK",
-      [OPT_OS_RTTHREAD]  = "RT-Thread"
-  };
-
-  printf("----------------------------------------------------\r\n");
-  printf("TinyUSB Host Example\r\n");
-  printf("If you find any bugs or problems, feel free to open\r\n");
-  printf("an issue at https://github.com/hathach/tinyusb\r\n");
-  printf("----------------------------------------------------\r\n\r\n");
-
-  printf("This Host demo is configured to support:\r\n");
-  printf("  - RTOS = %s\r\n", rtos_name[CFG_TUSB_OS]);
-}

+ 3 - 3
examples/host/cdc_msc_hid/src/tusb_config.h

@@ -76,15 +76,15 @@
 
 #define CFG_TUH_HUB                 1
 #define CFG_TUH_CDC                 1
-#define CFG_TUH_HID                 4
+#define CFG_TUH_HID                 4 // typical keyboard + mouse device can have 3-4 HID interfaces
 #define CFG_TUH_MSC                 1
 #define CFG_TUH_VENDOR              0
 
 #define CFG_TUSB_HOST_DEVICE_MAX    (CFG_TUH_HUB ? 5 : 1) // normal hub has 4 ports
 
 //------------- HID -------------//
-
-#define CFG_TUH_HID_EP_BUFSIZE      64
+#define CFG_TUH_HID_EPIN_BUFSIZE    64
+#define CFG_TUH_HID_EPOUT_BUFSIZE   64
 
 #ifdef __cplusplus
  }

+ 24 - 15
src/class/hid/hid_host.c

@@ -52,8 +52,8 @@ typedef struct
   uint16_t epin_size;
   uint16_t epout_size;
 
-  uint8_t epin_buf[CFG_TUH_HID_EP_BUFSIZE];
-  uint8_t epout_buf[CFG_TUH_HID_EP_BUFSIZE];
+  uint8_t epin_buf[CFG_TUH_HID_EPIN_BUFSIZE];
+  uint8_t epout_buf[CFG_TUH_HID_EPOUT_BUFSIZE];
 } hidh_interface_t;
 
 typedef struct
@@ -72,13 +72,8 @@ TU_ATTR_ALWAYS_INLINE static inline hidh_interface_t* get_instance(uint8_t dev_a
 static uint8_t get_instance_id_by_itfnum(uint8_t dev_addr, uint8_t itf);
 static uint8_t get_instance_id_by_epaddr(uint8_t dev_addr, uint8_t ep_addr);
 
-TU_ATTR_ALWAYS_INLINE static inline bool hidh_get_report(uint8_t dev_addr, hidh_interface_t* hid_itf)
-{
-  return usbh_edpt_xfer(dev_addr, hid_itf->ep_in, hid_itf->epin_buf, hid_itf->epin_size);
-}
-
 //--------------------------------------------------------------------+
-// Application API
+// Interface API
 //--------------------------------------------------------------------+
 
 uint8_t tuh_hid_instance_count(uint8_t dev_addr)
@@ -98,6 +93,10 @@ uint8_t tuh_hid_interface_protocol(uint8_t dev_addr, uint8_t instance)
   return hid_itf->itf_protocol;
 }
 
+//--------------------------------------------------------------------+
+// Control Endpoint API
+//--------------------------------------------------------------------+
+
 uint8_t tuh_hid_get_protocol(uint8_t dev_addr, uint8_t instance)
 {
   hidh_interface_t* hid_itf = get_instance(dev_addr, instance);
@@ -186,6 +185,20 @@ bool tuh_hid_set_report(uint8_t dev_addr, uint8_t instance, uint8_t report_id, u
   return true;
 }
 
+//--------------------------------------------------------------------+
+// Interrupt Endpoint API
+//--------------------------------------------------------------------+
+
+bool tuh_hid_receive_report(uint8_t dev_addr, uint8_t instance)
+{
+  hidh_interface_t* hid_itf = get_instance(dev_addr, instance);
+
+  // claim endpoint
+  TU_VERIFY( usbh_edpt_claim(dev_addr, hid_itf->ep_in) );
+
+  return usbh_edpt_xfer(dev_addr, hid_itf->ep_in, hid_itf->epin_buf, hid_itf->epin_size);
+}
+
 //bool tuh_n_hid_n_ready(uint8_t dev_addr, uint8_t instance)
 //{
 //  TU_VERIFY(tuh_n_hid_n_mounted(dev_addr, instance));
@@ -217,9 +230,6 @@ bool hidh_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t result, uint3
     TU_LOG2("  Get Report callback (%u, %u)\r\n", dev_addr, instance);
     TU_LOG1_MEM(hid_itf->epin_buf, 8, 2);
     tuh_hid_report_received_cb(dev_addr, instance, hid_itf->epin_buf, xferred_bytes);
-
-    // queue next report
-    hidh_get_report(dev_addr, hid_itf);
   }else
   {
     if (tuh_hid_report_sent_cb) tuh_hid_report_sent_cb(dev_addr, instance, hid_itf->epout_buf, xferred_bytes);
@@ -255,6 +265,8 @@ bool hidh_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *de
 
   TU_VERIFY(TUSB_CLASS_HID == desc_itf->bInterfaceClass);
 
+  TU_LOG2("HID opening Interface %u (addr = %u)\r\n", desc_itf->bInterfaceNumber, dev_addr);
+
   // len = interface + hid + n*endpoints
   uint16_t const drv_len = sizeof(tusb_desc_interface_t) + sizeof(tusb_hid_descriptor_hid_t) + desc_itf->bNumEndpoints*sizeof(tusb_desc_endpoint_t);
   TU_ASSERT(max_len >= drv_len);
@@ -336,7 +348,7 @@ static bool config_set_protocol(uint8_t dev_addr, tusb_control_request_t const *
   uint8_t const instance    = get_instance_id_by_itfnum(dev_addr, itf_num);
   hidh_interface_t* hid_itf = get_instance(dev_addr, instance);
 
-  TU_LOG2("HID Set Protocol\r\n");
+  TU_LOG2("HID Set Protocol to Boot Mode\r\n");
   hid_itf->protocol_mode = HID_PROTOCOL_BOOT;
   tusb_control_request_t const new_request =
   {
@@ -422,9 +434,6 @@ static void config_driver_mount_complete(uint8_t dev_addr, uint8_t instance, uin
   // enumeration is complete
   tuh_hid_mount_cb(dev_addr, instance, desc_report, desc_len);
 
-  // queue transfer for IN endpoint
-  hidh_get_report(dev_addr, hid_itf);
-
   // notify usbh that driver enumeration is complete
   usbh_driver_set_config_complete(dev_addr, hid_itf->itf_num);
 }

+ 24 - 6
src/class/hid/hid_host.h

@@ -38,10 +38,15 @@
 //--------------------------------------------------------------------+
 
 // TODO Highspeed interrupt can be up to 512 bytes
-#ifndef CFG_TUH_HID_EP_BUFSIZE
-#define CFG_TUH_HID_EP_BUFSIZE 64
+#ifndef CFG_TUH_HID_EPIN_BUFSIZE
+#define CFG_TUH_HID_EPIN_BUFSIZE 64
 #endif
 
+#ifndef CFG_TUH_HID_EPOUT_BUFSIZE
+#define CFG_TUH_HID_EPOUT_BUFSIZE 64
+#endif
+
+
 typedef struct
 {
   uint8_t  report_id;
@@ -54,7 +59,7 @@ typedef struct
 } tuh_hid_report_info_t;
 
 //--------------------------------------------------------------------+
-// Application API
+// Interface API
 //--------------------------------------------------------------------+
 
 // Get the number of HID instances
@@ -66,6 +71,14 @@ bool tuh_hid_mounted(uint8_t dev_addr, uint8_t instance);
 // Get interface supported protocol (bInterfaceProtocol) check out hid_interface_protocol_enum_t for possible values
 uint8_t tuh_hid_interface_protocol(uint8_t dev_addr, uint8_t instance);
 
+// Parse report descriptor into array of report_info struct and return number of reports.
+// For complicated report, application should write its own parser.
+uint8_t tuh_hid_parse_report_descriptor(tuh_hid_report_info_t* reports_info_arr, uint8_t arr_count, uint8_t const* desc_report, uint16_t desc_len) TU_ATTR_UNUSED;
+
+//--------------------------------------------------------------------+
+// Control Endpoint API
+//--------------------------------------------------------------------+
+
 // Get current protocol: HID_PROTOCOL_BOOT (0) or HID_PROTOCOL_REPORT (1)
 // Note: Device will be initialized in Boot protocol for simplicity.
 //       Application can use set_protocol() to switch back to Report protocol.
@@ -79,13 +92,18 @@ bool tuh_hid_set_protocol(uint8_t dev_addr, uint8_t instance, uint8_t protocol);
 // report_type is either Intput, Output or Feature, (value from hid_report_type_t)
 bool tuh_hid_set_report(uint8_t dev_addr, uint8_t instance, uint8_t report_id, uint8_t report_type, void* report, uint16_t len);
 
-// Parse report descriptor into array of report_info struct and return number of reports.
-// For complicated report, application should write its own parser.
-uint8_t tuh_hid_parse_report_descriptor(tuh_hid_report_info_t* reports_info_arr, uint8_t arr_count, uint8_t const* desc_report, uint16_t desc_len) TU_ATTR_UNUSED;
+//--------------------------------------------------------------------+
+// Interrupt Endpoint API
+//--------------------------------------------------------------------+
 
 // Check if the interface is ready to use
 //bool tuh_n_hid_n_ready(uint8_t dev_addr, uint8_t instance);
 
+// Try to receive next report on Interrupt Endpoint. Immediately return
+// - true If succeeded, tuh_hid_report_received_cb() callback will be invoked when report is available
+// - false if failed to queue the transfer e.g endpoint is busy
+bool tuh_hid_receive_report(uint8_t dev_addr, uint8_t instance);
+
 // Send report using interrupt endpoint
 // If report_id > 0 (composite), it will be sent as 1st byte, then report contents. Otherwise only report content is sent.
 //void tuh_hid_send_report(uint8_t dev_addr, uint8_t instance, uint8_t report_id, uint8_t const* report, uint16_t len);

+ 5 - 3
src/host/usbh.c

@@ -186,7 +186,7 @@ bool tuh_init(uint8_t rhport)
 
   TU_LOG2("USBH init\r\n");
 
-  tu_memclr(_usbh_devices, sizeof(usbh_device_t)*(CFG_TUSB_HOST_DEVICE_MAX+1));
+  tu_memclr(_usbh_devices, sizeof(_usbh_devices));
 
   //------------- Enumeration & Reporter Task init -------------//
   _usbh_q = osal_queue_create( &_usbh_qdef );
@@ -436,6 +436,7 @@ void usbh_driver_set_config_complete(uint8_t dev_addr, uint8_t itf_num)
   for(itf_num++; itf_num < sizeof(dev->itf2drv); itf_num++)
   {
     // continue with next valid interface
+    // TODO skip IAD binding interface such as CDCs
     uint8_t const drv_id = dev->itf2drv[itf_num];
     if (drv_id != DRVID_INVALID)
     {
@@ -474,6 +475,7 @@ static bool enum_get_config_desc_complete       (uint8_t dev_addr, tusb_control_
 static bool enum_set_config_complete            (uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result);
 static bool parse_configuration_descriptor      (uint8_t dev_addr, tusb_desc_configuration_t const* desc_cfg);
 
+#if CFG_TUH_HUB
 static bool enum_hub_clear_reset0_complete(uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result)
 {
   (void) dev_addr; (void) request;
@@ -540,7 +542,7 @@ static bool enum_hub_get_status0_complete(uint8_t dev_addr, tusb_control_request
 
   return true;
 }
-
+#endif
 
 static bool enum_request_set_addr(void)
 {
@@ -889,7 +891,7 @@ static bool parse_configuration_descriptor(uint8_t dev_addr, tusb_desc_configura
         if ( driver->open(dev->rhport, dev_addr, desc_itf, drv_len) )
         {
           // open successfully
-          TU_LOG2("%s opened\r\n", driver->name);
+          TU_LOG2("  Opened successfully\r\n");
 
           // bind interface to found driver
           dev->itf2drv[desc_itf->bInterfaceNumber] = drv_id;

+ 2 - 1
src/tusb.c

@@ -117,10 +117,11 @@ void tu_edpt_bind_driver(uint8_t ep2drv[][2], tusb_desc_interface_t const* desc_
     {
       uint8_t const ep_addr = ((tusb_desc_endpoint_t const*) p_desc)->bEndpointAddress;
 
+      TU_LOG(2, "  Bind EP %02x to driver id %u\r\n", ep_addr, driver_id);
       ep2drv[tu_edpt_number(ep_addr)][tu_edpt_dir(ep_addr)] = driver_id;
     }
 
-    len   = (uint16_t)(len + tu_desc_len(p_desc));
+    len    = (uint16_t)(len + tu_desc_len(p_desc));
     p_desc = tu_desc_next(p_desc);
   }
 }