Selaa lähdekoodia

better support for hid device set/get protocol

add caplock detection for hid_composite
hathach 4 vuotta sitten
vanhempi
sitoutus
ca98996e1f

+ 26 - 5
examples/device/hid_composite/src/main.c

@@ -255,12 +255,30 @@ uint16_t tud_hid_get_report_cb(uint8_t itf, uint8_t report_id, hid_report_type_t
 // received data on OUT endpoint ( Report ID = 0, Type = 0 )
 void tud_hid_set_report_cb(uint8_t itf, uint8_t report_id, hid_report_type_t report_type, uint8_t const* buffer, uint16_t bufsize)
 {
-  // TODO set LED based on CAPLOCK, NUMLOCK etc...
   (void) itf;
-  (void) report_id;
-  (void) report_type;
-  (void) buffer;
-  (void) bufsize;
+
+  if (report_type == HID_REPORT_TYPE_OUTPUT)
+  {
+    // Set keyboard LED e.g Capslock, Numlock etc...
+    if (report_id == REPORT_ID_KEYBOARD)
+    {
+      // bufsize should be (at least) 1
+      if ( bufsize < 1 ) return;
+
+      uint8_t const kbd_leds = buffer[0];
+
+      if (kbd_leds & KEYBOARD_LED_CAPSLOCK)
+      {
+        // Capslock On: disable blink, turn led on
+        blink_interval_ms = 0;
+        board_led_write(true);
+      }else
+      {
+        // Caplocks Off: back to normal link
+        blink_interval_ms = BLINK_MOUNTED;
+      }
+    }
+  }
 }
 
 //--------------------------------------------------------------------+
@@ -271,6 +289,9 @@ void led_blinking_task(void)
   static uint32_t start_ms = 0;
   static bool led_state = false;
 
+  // blink is disabled
+  if (!blink_interval_ms) return;
+
   // Blink every interval ms
   if ( board_millis() - start_ms < blink_interval_ms) return; // not enough time
   start_ms += blink_interval_ms;

+ 54 - 4
hw/bsp/board.c

@@ -25,6 +25,60 @@
 
 #include "board.h"
 
+#if 0
+#define LED_PHASE_MAX   8
+
+static struct
+{
+  uint32_t phase[LED_PHASE_MAX];
+  uint8_t phase_count;
+
+  bool led_state;
+  uint8_t current_phase;
+  uint32_t current_ms;
+}led_pattern;
+
+void board_led_pattern(uint32_t const phase_ms[], uint8_t count)
+{
+  memcpy(led_pattern.phase, phase_ms, 4*count);
+  led_pattern.phase_count = count;
+
+  // reset with 1st phase is on
+  led_pattern.current_ms = board_millis();
+  led_pattern.current_phase = 0;
+  led_pattern.led_state = true;
+  board_led_on();
+}
+
+void board_led_task(void)
+{
+  if ( led_pattern.phase_count == 0 ) return;
+
+  uint32_t const duration = led_pattern.phase[led_pattern.current_phase];
+
+  // return if not enough time
+  if (board_millis() - led_pattern.current_ms < duration) return;
+
+  led_pattern.led_state = !led_pattern.led_state;
+  board_led_write(led_pattern.led_state);
+
+  led_pattern.current_ms += duration;
+  led_pattern.current_phase++;
+
+  if (led_pattern.current_phase == led_pattern.phase_count)
+  {
+    led_pattern.current_phase = 0;
+    led_pattern.led_state = true;
+    board_led_on();
+  }
+}
+
+#endif
+
+//--------------------------------------------------------------------+
+// newlib read()/write() retarget
+//--------------------------------------------------------------------+
+
 #if defined(__MSP430__)
   #define sys_write   write
   #define sys_read    read
@@ -33,10 +87,6 @@
   #define sys_read    _read
 #endif
 
-//--------------------------------------------------------------------+
-// newlib read()/write() retarget
-//--------------------------------------------------------------------+
-
 #if defined(LOGGER_RTT)
 // Logging with RTT
 

+ 7 - 2
hw/bsp/board.h

@@ -54,6 +54,10 @@ void board_init(void);
 // Turn LED on or off
 void board_led_write(bool state);
 
+// Control led pattern using phase duration in ms.
+// For each phase, LED is toggle then repeated, board_led_task() is required to be called
+//void board_led_pattern(uint32_t const phase_ms[], uint8_t count);
+
 // Get the current state of button
 // a '1' means active (pressed), a '0' means inactive.
 uint32_t board_button_read(void);
@@ -81,11 +85,12 @@ int board_uart_write(void const * buf, int len);
   }
 
 #elif CFG_TUSB_OS == OPT_OS_PICO
-#include "pico/time.h"
-static inline uint32_t board_millis(void)
+  #include "pico/time.h"
+  static inline uint32_t board_millis(void)
   {
     return to_ms_since_boot(get_absolute_time());
   }
+
 #elif CFG_TUSB_OS == OPT_OS_RTTHREAD
   static inline uint32_t board_millis(void)
   {

+ 26 - 2
src/class/hid/hid_device.c

@@ -280,7 +280,21 @@ bool hidd_control_xfer_cb (uint8_t rhport, uint8_t stage, tusb_control_request_t
           uint8_t const report_type = tu_u16_high(request->wValue);
           uint8_t const report_id   = tu_u16_low(request->wValue);
 
-          uint16_t xferlen = tud_hid_get_report_cb(hid_itf, report_id, (hid_report_type_t) report_type, p_hid->epin_buf, request->wLength);
+          uint8_t* report_buf = p_hid->epin_buf;
+          uint16_t req_len = request->wLength;
+
+          uint16_t xferlen = 0;
+
+          // If host request a specific Report ID, add ID to as 1 byte of response
+          if ( (report_id != HID_REPORT_TYPE_INVALID) && (req_len > 1) )
+          {
+            *report_buf++ = report_id;
+            req_len--;
+
+            xferlen++;
+          }
+
+          xferlen += tud_hid_get_report_cb(hid_itf, report_id, (hid_report_type_t) report_type, report_buf, req_len);
           TU_ASSERT( xferlen > 0 );
 
           tud_control_xfer(rhport, request, p_hid->epin_buf, xferlen);
@@ -298,7 +312,17 @@ bool hidd_control_xfer_cb (uint8_t rhport, uint8_t stage, tusb_control_request_t
           uint8_t const report_type = tu_u16_high(request->wValue);
           uint8_t const report_id   = tu_u16_low(request->wValue);
 
-          tud_hid_set_report_cb(hid_itf, report_id, (hid_report_type_t) report_type, p_hid->epout_buf, request->wLength);
+          uint8_t const* report_buf = p_hid->epout_buf;
+          uint16_t report_len = request->wLength;
+
+          // If host request a specific Report ID, extract report ID in buffer before invoking callback
+          if ( (report_id != HID_REPORT_TYPE_INVALID) && (report_len > 1) && (report_id == p_hid->epout_buf[0]) )
+          {
+            report_buf++;
+            report_len--;
+          }
+
+          tud_hid_set_report_cb(hid_itf, report_id, (hid_report_type_t) report_type, report_buf, report_len);
         }
       break;
 

+ 1 - 1
src/device/usbd.c

@@ -1243,7 +1243,7 @@ bool usbd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t
   uint8_t const epnum = tu_edpt_number(ep_addr);
   uint8_t const dir   = tu_edpt_dir(ep_addr);
 
-  TU_LOG2("  Queue EP %02X with %u bytes ... ", ep_addr, total_bytes);
+  TU_LOG2("  Queue EP %02X with %u bytes ...\r\n", ep_addr, total_bytes);
 
   // Attempt to transfer on a busy endpoint, sound like an race condition !
   TU_ASSERT(_usbd_dev.ep_status[epnum][dir].busy == 0);

+ 1 - 0
src/device/usbd_control.c

@@ -186,6 +186,7 @@ bool usbd_control_xfer_cb (uint8_t rhport, uint8_t ep_addr, xfer_result_t result
   {
     TU_VERIFY(_ctrl_xfer.buffer);
     memcpy(_ctrl_xfer.buffer, _usbd_ctrl_buf, xferred_bytes);
+    TU_LOG_MEM(2, _usbd_ctrl_buf, xferred_bytes, 2);
   }
 
   _ctrl_xfer.total_xferred += xferred_bytes;