usb_hid_sample.c 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130
  1. #include <stdio.h>
  2. #include "pico/stdlib.h"
  3. #include "bsp/board_api.h"
  4. #include "tusb.h"
  5. #include "usb_descriptors.h"
  6. #define INDICATOR_LED PICO_DEFAULT_LED_PIN
  7. #define A_SWITCH 16
  8. #define B_SWITCH 17
  9. #define KEYREPORT_SIZE 6
  10. uint8_t keyreport[KEYREPORT_SIZE] = {0,0,0,0,0,0};
  11. void add_key(uint8_t keycode)
  12. {
  13. for(int i=0; i<KEYREPORT_SIZE; i++) {
  14. if(keyreport[i] == HID_KEY_NONE) {
  15. keyreport[i] = keycode;
  16. break;
  17. }
  18. }
  19. }
  20. void remove_key(uint8_t keycode)
  21. {
  22. for(int i=0; i<KEYREPORT_SIZE; i++) {
  23. if(keyreport[i] == keycode) {
  24. keyreport[i] = HID_KEY_NONE;
  25. }
  26. }
  27. }
  28. void clear_key(void)
  29. {
  30. for(int i=0; i<KEYREPORT_SIZE; i++) {
  31. keyreport[i] = HID_KEY_NONE;
  32. }
  33. }
  34. // キーボード状態に変化があったことを知らせるフラグ
  35. volatile bool key_event_flag = false;
  36. void keysw_event_handler(uint gpio, uint32_t events)
  37. {
  38. uint8_t key = HID_KEY_NONE;
  39. if(gpio == A_SWITCH) key = HID_KEY_A;
  40. else if(gpio == B_SWITCH) key = HID_KEY_B;
  41. else return;
  42. if(events & GPIO_IRQ_EDGE_FALL){
  43. add_key(key);
  44. }
  45. if(events & GPIO_IRQ_EDGE_RISE) {
  46. remove_key(key);
  47. }
  48. key_event_flag = true;
  49. }
  50. // USBデバイスがマウントされた
  51. void tud_mount_cb(void)
  52. {
  53. clear_key();
  54. }
  55. // インジケーターLEDを制御する
  56. void tud_hid_set_report_cb(uint8_t instance, uint8_t report_id, hid_report_type_t report_type, uint8_t const* buffer, uint16_t bufsize)
  57. {
  58. if( bufsize < 1 ) return; // バッファゼロなら何もしない
  59. // キーボードレポートか?
  60. if(report_type == HID_REPORT_TYPE_OUTPUT && report_id == REPORT_ID_KEYBOARD) {
  61. // CAPS LOCKでインジケーターを変更
  62. gpio_put(INDICATOR_LED, buffer[0] & KEYBOARD_LED_CAPSLOCK);
  63. }
  64. }
  65. // キーボードレポートを返す
  66. uint16_t tud_hid_get_report_cb(uint8_t instance, uint8_t report_id, hid_report_type_t report_type, uint8_t* buffer, uint16_t reqlen)
  67. {
  68. // キーボードレポートのサイズがなければ0を返す
  69. if(reqlen < sizeof(hid_keyboard_report_t) ) {
  70. buffer[0] = 0;
  71. return 1; // とにかく何か返さないと駄目
  72. }
  73. // キーボードレポートを作成
  74. hid_keyboard_report_t report;
  75. report.modifier = 0; // 修飾キー情報
  76. report.reserved = 0;
  77. memcpy(report.keycode, keyreport, KEYREPORT_SIZE );
  78. memcpy(buffer, &report, sizeof(hid_keyboard_report_t));
  79. return sizeof(hid_keyboard_report_t);
  80. }
  81. int main()
  82. {
  83. stdio_init_all();
  84. // LED
  85. gpio_init(INDICATOR_LED);
  86. gpio_set_dir(INDICATOR_LED, GPIO_OUT);
  87. gpio_put(INDICATOR_LED, 0);
  88. // A Switch = Pull Up
  89. gpio_init(A_SWITCH);
  90. gpio_set_dir(A_SWITCH, GPIO_IN);
  91. gpio_disable_pulls(A_SWITCH);
  92. gpio_pull_up(A_SWITCH);
  93. // B Switch = Pull Up
  94. gpio_init(B_SWITCH);
  95. gpio_set_dir(B_SWITCH, GPIO_IN);
  96. gpio_disable_pulls(B_SWITCH);
  97. gpio_pull_up(B_SWITCH);
  98. // GPIO割り込み
  99. gpio_set_irq_enabled_with_callback(A_SWITCH, GPIO_IRQ_EDGE_FALL|GPIO_IRQ_EDGE_RISE,true, keysw_event_handler);
  100. gpio_set_irq_enabled_with_callback(B_SWITCH, GPIO_IRQ_EDGE_FALL|GPIO_IRQ_EDGE_RISE,true, keysw_event_handler);
  101. // TinyUSB
  102. board_init();
  103. tud_init(BOARD_TUD_RHPORT); // TinyUSB本体の初期化
  104. if (board_init_after_tusb) { // マイコン依存の初期化後の処理
  105. board_init_after_tusb();
  106. }
  107. while (true) {
  108. tud_task(); // TinyUSBのジョブを定期的に呼び出す
  109. if(key_event_flag) {
  110. if(tud_hid_ready())
  111. tud_hid_keyboard_report(REPORT_ID_KEYBOARD, 0, keyreport);
  112. key_event_flag == false;
  113. }
  114. }
  115. }