tud_hid_report_complete_cb() API
update hid composite to make use of tud_hid_report_complete_cb() for sending reports when possible.
This commit is contained in:
		| @@ -1,5 +1,11 @@ | ||||
| # TinyUSB Changelog | ||||
|  | ||||
| ## WIP | ||||
|  | ||||
| - Fix dropping MIDI sysex message when fifo is full | ||||
| - Add DPad/Hat support for HID Gamepad | ||||
| - Add tud_hid_report_complete_cb() API | ||||
|  | ||||
| ## 0.8.0 - 2021.02.05 | ||||
|  | ||||
| ### Device Controller Driver | ||||
|   | ||||
| @@ -104,6 +104,98 @@ void tud_resume_cb(void) | ||||
| // USB HID | ||||
| //--------------------------------------------------------------------+ | ||||
|  | ||||
| static void send_hid_report(uint8_t report_id, uint32_t btn) | ||||
| { | ||||
|   // skip if hid is not ready yet | ||||
|   if ( !tud_hid_ready() ) return; | ||||
|  | ||||
|   switch(report_id) | ||||
|   { | ||||
|     case REPORT_ID_KEYBOARD: | ||||
|     { | ||||
|       // use to avoid send multiple consecutive zero report for keyboard | ||||
|       static bool has_keyboard_key = false; | ||||
|  | ||||
|       if ( btn ) | ||||
|       { | ||||
|         uint8_t keycode[6] = { 0 }; | ||||
|         keycode[0] = HID_KEY_A; | ||||
|  | ||||
|         tud_hid_keyboard_report(REPORT_ID_KEYBOARD, 0, keycode); | ||||
|         has_keyboard_key = true; | ||||
|       }else | ||||
|       { | ||||
|         // send empty key report if previously has key pressed | ||||
|         if (has_keyboard_key) tud_hid_keyboard_report(REPORT_ID_KEYBOARD, 0, NULL); | ||||
|         has_keyboard_key = false; | ||||
|       } | ||||
|     } | ||||
|     break; | ||||
|  | ||||
|     case REPORT_ID_MOUSE: | ||||
|     { | ||||
|       int8_t const delta = 5; | ||||
|  | ||||
|       // no button, right + down, no scroll, no pan | ||||
|       tud_hid_mouse_report(REPORT_ID_MOUSE, 0x00, delta, delta, 0, 0); | ||||
|     } | ||||
|     break; | ||||
|  | ||||
|     case REPORT_ID_CONSUMER_CONTROL: | ||||
|     { | ||||
|       // use to avoid send multiple consecutive zero report | ||||
|       static bool has_consumer_key = false; | ||||
|  | ||||
|       if ( btn ) | ||||
|       { | ||||
|         // volume down | ||||
|         uint16_t volume_down = HID_USAGE_CONSUMER_VOLUME_DECREMENT; | ||||
|         tud_hid_report(REPORT_ID_CONSUMER_CONTROL, &volume_down, 2); | ||||
|         has_consumer_key = true; | ||||
|       }else | ||||
|       { | ||||
|         // send empty key report (release key) if previously has key pressed | ||||
|         uint16_t empty_key = 0; | ||||
|         if (has_consumer_key) tud_hid_report(REPORT_ID_CONSUMER_CONTROL, &empty_key, 2); | ||||
|         has_consumer_key = false; | ||||
|       } | ||||
|     } | ||||
|     break; | ||||
|  | ||||
|     case REPORT_ID_GAMEPAD: | ||||
|     { | ||||
|       // use to avoid send multiple consecutive zero report for keyboard | ||||
|       static bool has_gamepad_key = false; | ||||
|  | ||||
|       hid_gamepad_report_t report = | ||||
|       { | ||||
|         .x   = 0, .y = 0, .z = 0, .rz = 0, .rx = 0, .ry = 0, | ||||
|         .hat = 0, .buttons = 0 | ||||
|       }; | ||||
|  | ||||
|       if ( btn ) | ||||
|       { | ||||
|         report.hat = GAMEPAD_HAT_UP; | ||||
|         report.buttons = GAMEPAD_BUTTON_A; | ||||
|         tud_hid_report(REPORT_ID_GAMEPAD, &report, sizeof(report)); | ||||
|  | ||||
|         has_gamepad_key = true; | ||||
|       }else | ||||
|       { | ||||
|         report.hat = GAMEPAD_HAT_CENTERED; | ||||
|         report.buttons = 0; | ||||
|         if (has_gamepad_key) tud_hid_report(REPORT_ID_GAMEPAD, &report, sizeof(report)); | ||||
|         has_gamepad_key = false; | ||||
|       } | ||||
|     } | ||||
|     break; | ||||
|  | ||||
|     default: break; | ||||
|   } | ||||
| } | ||||
|  | ||||
| // Every 10ms, we will sent 1 report for each HID profile (keyboard, mouse etc ..) | ||||
| // tud_hid_report_complete_cb() is used to send the next report after previous one is complete | ||||
| void hid_task(void) | ||||
| { | ||||
|   // Poll every 10ms | ||||
| @@ -121,97 +213,26 @@ void hid_task(void) | ||||
|     // Wake up host if we are in suspend mode | ||||
|     // and REMOTE_WAKEUP feature is enabled by host | ||||
|     tud_remote_wakeup(); | ||||
|   } | ||||
|  | ||||
|   /*------------- Mouse -------------*/ | ||||
|   if ( tud_hid_ready() ) | ||||
|   { | ||||
|     if ( btn ) | ||||
|     { | ||||
|       int8_t const delta = 5; | ||||
|  | ||||
|       // no button, right + down, no scroll pan | ||||
|       tud_hid_mouse_report(REPORT_ID_MOUSE, 0x00, delta, delta, 0, 0); | ||||
|  | ||||
|       // delay a bit before sending keyboard report | ||||
|       board_delay(10); | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   /*------------- Keyboard -------------*/ | ||||
|   if ( tud_hid_ready() ) | ||||
|   { | ||||
|     // use to avoid send multiple consecutive zero report for keyboard | ||||
|     static bool has_key = false; | ||||
|  | ||||
|     if ( btn ) | ||||
|     { | ||||
|       uint8_t keycode[6] = { 0 }; | ||||
|       keycode[0] = HID_KEY_A; | ||||
|  | ||||
|       tud_hid_keyboard_report(REPORT_ID_KEYBOARD, 0, keycode); | ||||
|  | ||||
|       has_key = true; | ||||
|   }else | ||||
|   { | ||||
|       // send empty key report if previously has key pressed | ||||
|       if (has_key) tud_hid_keyboard_report(REPORT_ID_KEYBOARD, 0, NULL); | ||||
|       has_key = false; | ||||
|     // Send the 1st of report chain, the rest will be sent by tud_hid_report_complete_cb() | ||||
|     send_hid_report(REPORT_ID_KEYBOARD, btn); | ||||
|   } | ||||
| } | ||||
|  | ||||
|     // delay a bit before sending consumer report | ||||
|     board_delay(10); | ||||
|   } | ||||
|  | ||||
|   /*------------- Consume Control -------------*/ | ||||
|   if ( tud_hid_ready() ) | ||||
| // Invoked when sent REPORT successfully to host | ||||
| // Application can use this to send the next report | ||||
| // Note: For composite reports, report[0] is report ID | ||||
| void tud_hid_report_complete_cb(uint8_t itf, uint8_t const* report, uint8_t len) | ||||
| { | ||||
|     // use to avoid send multiple consecutive zero report | ||||
|     static bool has_consumer_key = false; | ||||
|   (void) itf; | ||||
|   (void) len; | ||||
|  | ||||
|     if ( btn ) | ||||
|   uint8_t next_report_id = report[0] + 1; | ||||
|  | ||||
|   if (next_report_id < REPORT_ID_COUNT) | ||||
|   { | ||||
|       // volume down | ||||
|       uint16_t volume_down = HID_USAGE_CONSUMER_VOLUME_DECREMENT; | ||||
|       tud_hid_report(REPORT_ID_CONSUMER_CONTROL, &volume_down, 2); | ||||
|  | ||||
|       has_consumer_key = true; | ||||
|     }else | ||||
|     { | ||||
|       // send empty key report (release key) if previously has key pressed | ||||
|       uint16_t empty_key = 0; | ||||
|       if (has_consumer_key) tud_hid_report(REPORT_ID_CONSUMER_CONTROL, &empty_key, 2); | ||||
|       has_consumer_key = false; | ||||
|     } | ||||
|  | ||||
|     // delay a bit before sending next report | ||||
|     board_delay(10); | ||||
|   } | ||||
|  | ||||
|   /*------------- Gamepad -------------*/ | ||||
|   if ( tud_hid_ready() ) | ||||
|   { | ||||
|     // use to avoid send multiple consecutive zero report for keyboard | ||||
|     static bool has_gamepad_key = false; | ||||
|  | ||||
|     hid_gamepad_report_t report = | ||||
|     { | ||||
|       .x   = 0, .y = 0, .z = 0, .rz = 0, .rx = 0, .ry = 0, | ||||
|       .hat = 0, .buttons = 0 | ||||
|     }; | ||||
|  | ||||
|     if ( btn ) | ||||
|     { | ||||
|       report.hat = GAMEPAD_HAT_UP; | ||||
|       tud_hid_report(REPORT_ID_GAMEPAD, &report, sizeof(report)); | ||||
|  | ||||
|       has_gamepad_key = true; | ||||
|     }else | ||||
|     { | ||||
|       report.hat = GAMEPAD_HAT_CENTERED; | ||||
|       if (has_gamepad_key) tud_hid_report(REPORT_ID_GAMEPAD, &report, sizeof(report)); | ||||
|       has_gamepad_key = false; | ||||
|     } | ||||
|     send_hid_report(next_report_id, board_button_read()); | ||||
|   } | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -107,7 +107,7 @@ uint8_t const desc_configuration[] = | ||||
|   TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100), | ||||
|  | ||||
|   // Interface number, string index, protocol, report descriptor len, EP In address, size & polling interval | ||||
|   TUD_HID_DESCRIPTOR(ITF_NUM_HID, 0, HID_PROTOCOL_NONE, sizeof(desc_hid_report), EPNUM_HID, CFG_TUD_HID_EP_BUFSIZE, 10) | ||||
|   TUD_HID_DESCRIPTOR(ITF_NUM_HID, 0, HID_PROTOCOL_NONE, sizeof(desc_hid_report), EPNUM_HID, CFG_TUD_HID_EP_BUFSIZE, 2) | ||||
| }; | ||||
|  | ||||
| // Invoked when received GET CONFIGURATION DESCRIPTOR | ||||
|   | ||||
| @@ -30,7 +30,8 @@ enum | ||||
|   REPORT_ID_KEYBOARD = 1, | ||||
|   REPORT_ID_MOUSE, | ||||
|   REPORT_ID_CONSUMER_CONTROL, | ||||
|   REPORT_ID_GAMEPAD | ||||
|   REPORT_ID_GAMEPAD, | ||||
|   REPORT_ID_COUNT | ||||
| }; | ||||
|  | ||||
| #endif /* USB_DESCRIPTORS_H_ */ | ||||
|   | ||||
| @@ -381,14 +381,24 @@ bool hidd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_ | ||||
|   uint8_t itf = 0; | ||||
|   hidd_interface_t * p_hid = _hidd_itf; | ||||
|  | ||||
|   for ( ; ; itf++, p_hid++) | ||||
|   // Identify which interface to use | ||||
|   for (itf = 0; itf < CFG_TUD_HID; itf++) | ||||
|   { | ||||
|     if (itf >= TU_ARRAY_SIZE(_hidd_itf)) return false; | ||||
|  | ||||
|     if ( ep_addr == p_hid->ep_out ) break; | ||||
|     p_hid = &_hidd_itf[itf]; | ||||
|     if ( (ep_addr == p_hid->ep_out) || (ep_addr == p_hid->ep_in) ) break; | ||||
|   } | ||||
|   TU_ASSERT(itf < CFG_TUD_HID); | ||||
|  | ||||
|   if (ep_addr == p_hid->ep_out) | ||||
|   // Sent report successfully | ||||
|   if (ep_addr == p_hid->ep_in) | ||||
|   { | ||||
|     if (tud_hid_report_complete_cb) | ||||
|     { | ||||
|       tud_hid_report_complete_cb(itf, p_hid->epin_buf, (uint8_t) xferred_bytes); | ||||
|     } | ||||
|   } | ||||
|   // Received report | ||||
|   else if (ep_addr == p_hid->ep_out) | ||||
|   { | ||||
|     tud_hid_set_report_cb( | ||||
|         #if CFG_TUD_HID > 1 | ||||
|   | ||||
| @@ -123,7 +123,10 @@ TU_ATTR_WEAK bool tud_hid_set_idle_cb(uint8_t idle_rate); | ||||
|  | ||||
| #endif | ||||
|  | ||||
| // TU_ATTR_WEAK void tud_hid_report_complete_cb(uint8_t itf, ); | ||||
| // Invoked when sent REPORT successfully to host | ||||
| // Application can use this to send the next report | ||||
| // Note: For composite reports, report[0] is report ID | ||||
| TU_ATTR_WEAK void tud_hid_report_complete_cb(uint8_t itf, uint8_t const* report, uint8_t len); | ||||
|  | ||||
|  | ||||
| //--------------------------------------------------------------------+ | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 hathach
					hathach