Arduinoでキー変換器を作る(BLE編)：スクロール対応

https://qiita.com/sushisushiBoo/items/3b0be1c026cad10306f4

こちらでBLE対応したキー変換器を作ったが、
USB接続するキーボードは`Thinkpad Tracpoint Keyboard`なので、Tracpointでスクロールができる。

これに対応するために`USB Host Shield Library`とキー変換器のソースに変更を加えた

### USB Host Shieldの変更
USBのKeyboardやMouseはHIDとして認識され、デフォルトでは`BOOT PROTOCOL`が有効になっている。このままではスクロールの情報は取得できないので`REPORTER PROTOCOL`を使う。

`REPORER PROTOCOL`を有効にするにはHIDBootクラスのコンストラクタの第二引数をtrueにする
``` C++
USB Usb;
USBHub Hub(&Usb);
HIDBoot<USB_HID_PROTOCOL_KEYBOARD | USB_HID_PROTOCOL_MOUSE> HidComposite(&Usb, true);
```
また、これだけではreportデータの処理がうまくいかないのでhidboot.h/cppに手を加える
``` diff: hidboot.h diff
diff --git a/libraries/USB_Host_Shield_Library_2.0/hidboot.h b/libraries/USB_Host_Shield_Library_2.0/hidboot.h
index 4076400..722bea6 100644
--- a/libraries/USB_Host_Shield_Library_2.0/hidboot.h
+++ b/libraries/USB_Host_Shield_Library_2.0/hidboot.h
@@ -46,6 +46,7 @@ struct MOUSEINFO {
         };
         int8_t dX;
         int8_t dY;
+        int8_t dH;
 };
 
 class MouseReportParser : public HIDReportParser {
@@ -63,6 +64,9 @@ protected:
         virtual void OnMouseMove(MOUSEINFO *mi __attribute__((unused))) {
         };
 
+        virtual void OnScroll(MOUSEINFO *mi __attribute__((unused))) {
+        };
+
         virtual void OnLeftButtonUp(MOUSEINFO *mi __attribute__((unused))) {
         };
 
@@ -593,9 +597,20 @@ uint8_t HIDBoot<BOOT_PROTOCOL>::Poll() {
                         rcode = pUsb->inTransfer(bAddress, epInfo[epInterruptInIndex + i].epAddr, &read, buf);
                         // SOME buggy dongles report extra keys (like sleep) using a 2 byte packet on the wrong endpoint.
                         // Since keyboard and mice must report at least 3 bytes, we ignore the extra data.
-                        if(!rcode && read > 2) {
+                        // if protocol is Report, data must be at least 6 bytes.
+                        if(!rcode && read > ((!bRptProtoEnable) ? 2 : 5)) {
+# if 0
+                                Serial.print(read);
+                                Serial.print(":");
+                                for(uint16_t j = 0; j < read; j++)
+                                {
+                                        Serial.print(buf[j], HEX);
+                                        Serial.print(",");
+                                }
+                                Serial.println();
+#endif
                                 if(pRptParser[i])
-                                        pRptParser[i]->Parse((USBHID*)this, 0, (uint8_t)read, buf);
+                                        pRptParser[i]->Parse((USBHID*)this, bRptProtoEnable, (uint8_t)read, buf);
 #ifdef DEBUG_USB_HOST
                                 // We really don't care about errors and anomalies unless we are debugging.
                         } else {
```

``` diff: hidboo.cpp diff
diff --git a/libraries/USB_Host_Shield_Library_2.0/hidboot.cpp b/libraries/USB_Host_Shield_Library_2.0/hidboot.cpp
index e372e62..5bd23d1 100644
--- a/libraries/USB_Host_Shield_Library_2.0/hidboot.cpp
+++ b/libraries/USB_Host_Shield_Library_2.0/hidboot.cpp
@@ -17,7 +17,12 @@ e-mail   :  support@circuitsathome.com
 #include "hidboot.h"
 
 void MouseReportParser::Parse(USBHID *hid __attribute__((unused)), bool is_rpt_id __attribute__((unused)), uint8_t len __attribute__((unused)), uint8_t *buf) {
-        MOUSEINFO *pmi = (MOUSEINFO*)buf;
+        MOUSEINFO *pmi;
+        if(is_rpt_id && (len > 3)) {
+                pmi = (MOUSEINFO*)(buf + 1);
+        } else {
+                pmi = (MOUSEINFO*)buf;
+        }
         // Future:
         // bool event;
 
@@ -111,6 +116,12 @@ void MouseReportParser::Parse(USBHID *hid __attribute__((unused)), bool is_rpt_i
                 // event = true;
         }
 
+        if(len > 3) {
+                if(pmi->dH) {
+                        OnScroll(pmi);
+                }
+        }
+
         //
         // Future:
         // Provide a callback that operates on the gathered events from above.
@@ -119,7 +130,7 @@ void MouseReportParser::Parse(USBHID *hid __attribute__((unused)), bool is_rpt_i
         //
 
         // Only the first byte matters (buttons). We do NOT need to save position info.
-        prevState.bInfo[0] = buf[0];
+        prevState.bInfo[0] = *(uint8_t*)pmi;
 #endif
 
 };
```
### inoの修正
修正したソースは以下においてある

https://github.com/sushisushiboo/BLEHIDKeyboardAndMouse