私は、Windowsコンピュータに接続し、コンピュータ上のタッチスクリーンをシミュレートするArduinoデバイスを作成しています。画面はArduinoに属していませんが、ArduinoはHIDタッチメッセージをUSB経由でWindows 10コンピュータに中継します。USB HIDマルチタッチシリアルレポート
私が最初にしたことは、Digitizerイベントの代わりにAbsoluteMouseイベントをリレーすることでした。これは私のためにうまくいった。しかし、私のデバイスが複数のタッチをサポートしているので、私はAbsoluteMouseの代わりにマルチタッチHIDメッセージを使用したいと思います。概念の証明として、私は1本の指のデータだけを中継することから始めています。 (私はこれを動作させた後に指を追加する予定です)。実装するのが最も簡単であるように思わように私は、SerialReportのアプローチを取っています:
- https://docs.microsoft.com/en-us/windows-hardware/design/component-guidelines/sample-report-descriptor--serial-reporting-mode-
- https://docs.microsoft.com/en-us/windows-hardware/design/component-guidelines/selecting-packet-reporting-modes-in-multitouch-drivers
を私は基本的に、私は持っていなかった、AbsoluteMouseの多くの使用例を発見しましたHIDレポートをコピーして貼り付けるよりもはるかに機能します。しかし、タッチスクリーンの場合、コードサンプルは非常に難しいです。 (私は、タッチスクリーンではないパッドサンプルだけを見つけました)。私はタッチメッセージを報告する独自のコードを実装しようとしました。しかしこれは失敗する。私はHID記述子をどのように解釈するのかを理解していると思いますが、これは初めてのことですので、わかりません。メッセージ構造に何か問題はありますか?
#define REPORTID_MTOUCH 1
static const uint8_t _hidSerialMultiTouchDescriptor[] PROGMEM = {
//https://docs.microsoft.com/en-us/windows-hardware/design/component-guidelines/sample-report-descriptor--serial-reporting-mode-
//linked from: https://docs.microsoft.com/en-us/windows-hardware/design/component-guidelines/selecting-packet-reporting-modes-in-multitouch-drivers
0x05, 0x0d, // USAGE_PAGE (Digitizers)
0x09, 0x04, // USAGE (Touch Screen)
0xa1, 0x01, // COLLECTION (Application)
0x85, REPORTID_MTOUCH, // REPORT_ID (Touch)
0x09, 0x22, // USAGE (Finger)
0xa1, 0x00, // COLLECTION (Physical)
0x09, 0x42, // USAGE (Tip Switch)
0x15, 0x00, // LOGICAL_MINIMUM (0)
0x25, 0x01, // LOGICAL_MAXIMUM (1)
0x75, 0x01, // REPORT_SIZE (1)
0x95, 0x01, // REPORT_COUNT (1)
0x81, 0x02, // INPUT (Data,Var,Abs)
0x95, 0x03, // REPORT_COUNT (3)
0x81, 0x03, // INPUT (Cnst,Ary,Abs)
0x09, 0x32, // USAGE (In Range)
0x09, 0x47, // USAGE (Confidence)
0x95, 0x02, // REPORT_COUNT (2)
0x81, 0x02, // INPUT (Data,Var,Abs)
0x95, 0x0a, // REPORT_COUNT (10)
0x81, 0x03, // INPUT (Cnst,Ary,Abs)
0x05, 0x01, // USAGE_PAGE (Generic Desk..
0x26, 0xff, 0x7f, // LOGICAL_MAXIMUM (32767)
0x75, 0x10, // REPORT_SIZE (16)
0x95, 0x01, // REPORT_COUNT (1)
0x65, 0x00, // UNIT (None)
0x09, 0x30, // USAGE (X)
0x81, 0x02, // INPUT (Data,Var,Abs)
0x09, 0x31, // USAGE (Y)
0x46, 0x00, 0x00, // PHYSICAL_MAXIMUM (0)
0x81, 0x02, // INPUT (Data,Var,Abs)
0x05, 0x0d, // USAGE PAGE (Digitizers)
0x09, 0x48, // USAGE (Width)
0x09, 0x49, // USAGE (Height)
0x95, 0x01, // REPORT_COUNT (2)
0x81, 0x02, // INPUT (Data,Var,Abs)
0x81, 0x03, // INPUT (Cnst,Ary,Abs)
0x09, 0x51, // USAGE (Contact Identifier)
0x75, 0x10, // REPORT_SIZE (16)
0x95, 0x02, // REPORT_COUNT (1)
0x81, 0x02, // INPUT (Data,Var,Abs)
0x09, 0x55, // USAGE(Maximum Count)
0x15, 0x00, // LOGICAL_MINIMUM (0)
0x25, 0x08, // LOGICAL_MAXIMUM (255)
0x75, 0x08, // REPORT_SIZE (8)
0x95, 0x01, // REPORT_COUNT (1)
0xb1, 0x02, // FEATURE (Data,Var,Abs)
0xc0, // END_COLLECTION
0xc0 // END_COLLECTION
};
これはメッセージとの私の実装です:
typedef union {
struct{
uint8_t TipSwitchLsb4Bits_InRange_Confidence_Empty2Bits;
uint8_t Padding8_10Minus2;
int16_t xAxis;
int16_t yAxis;
int16_t width;
int16_t height;
int16_t ContactId;
uint8_t MaximumCount;
};
} HID_SerialTouchReport;
void reportTouch(unsigned int x, unsigned int y) {
HID_SerialTouchReport report;
report.TipSwitchLsb4Bits_InRange_Confidence_Empty2Bits=0xff;
report.xAxis=x;
report.yAxis=y;
report.width=4;
report.height=4;
report.ContactId=0;
report.MaximumCount=1;
HID().SendReport(REPORTID_MTOUCH,&report,sizeof(report));
}
...
static HIDSubDescriptor node(_hidSerialMultiTouchDescriptor, sizeof(_hidSerialMultiTouchDescriptor));
HID().AppendDescriptor(&node);
...
//Move the pointer diagonally across the screen:
for(unsigned int x=0;x<32767;x+=1000) {
reportTouch(x,x);
delay(50);
}
テストコードがMSPaint上の左上から右下に斜めの線を引くことになっています。
これをAbsoluteMouse記述子/ Messageでテストすると、すべてが機能します。だから私は問題が私の定義のHID_SerialTouchReportにあると推測します。
私の注意をつかんできたいくつかのもの:
- まだ "USAGE(Y)" を定義しながら、なぜ "PHYSICAL_MAXIMUM(0)" 来るん。それはXとは関係なく、Yと関係がありますか?それはなぜ "0"ですか?
- 高さと幅の "INPUT(Cnst、Ary、Abs)"の "Ary"の意義は何ですか?
- 私は、「report.TipSwitchLsb4Bits_InRange_Confidence_Empty2Bits = 0xff;」を使って「見開き」のようなことをしています。しかし、これは私には問題ないと思われます。なぜなら、パディングされていないビットはすべて「1」に設定する必要があるからです。
- report.MaximumCountを何に設定すべきかわかりません。私は異なった数の& Id値を実験しようとしましたが、すべて効果がありませんでした。
- 私のArduinoはデバイスマネージャで「複合デバイス」として表示されるので、すべてが間違っているとは限りません。
- 私がリンクしている記事では、「シリアルパケット」モードはレガシーWindows 7用であり、Windows 10を使用しています。しかし、これは問題ではないはずです。
- マイクロソフトのサイトから直接HIDディスクリプタをコピーしていましたが、メッセージ構造を正しく構築したかどうかはわかりません。 (私はいくつかのビットを忘れましたか?)
また、私のコードが失敗する原因になっていますか?
0x09の、0x48、// USAGE(幅) 0x09の、0x49、// USAGE(高さ) 0x95、0x01の、// REPORT_COUNT(2) ...する必要があります: 0x09の、0x48、// USAGE(幅) 0x09、0x49、// USAGE(高さ) 0x95,0x02、// REPORT_COUNT(2) (インデントについては申し訳ありません) – aja