Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

別の種類のタッチパッドでは送られてくる形式が異なるようです #1

Open
kamektx opened this issue Nov 2, 2021 · 2 comments

Comments

@kamektx
Copy link

kamektx commented Nov 2, 2021

TouchpadGestures_Advanced の作者のkamektxです。

件名の通り、別の種類のタッチパッドでは送られてくるデータの形式が異なるようです。先日新しいPCを購入してTGAが動かないことで判明しました。

どうやらある種類のタッチパッドでは、

  • マルチタッチ時の2点目以降のデータを 2回目の 後に続く複数回の WM_INPUTメッセージへと分けて送信している
  • 2点目以降のデータは従来の通りLinkCollectionによってインデックス化されているのではなく、RAWINPUT->data.hid.bRawData のバイト列に連なるようにして保存されている

ようです。詳しい仕様としては、

1回目のWM_INPUT

  • RAWINPUT->data.hid.dwCount: 必ず(?) 1
  • Values from RAWINPUT->data.hid.bRawData
    • LinkCollection: 0
      • ScanTime: 2回目のメッセージと同
      • ContactCount: 合計タッチ数
    • LinkCollection: 1
      • ContactID
      • X
      • Y
  • Usages (Button input) from RAWINPUT->data.hid.bRawData
    • LinkCollection: 1
      • Tip (あればOn, なければOff)
      • IsFinger (あれば指判定, なければ手の平判定)

2回目の 後に続く複数回のWM_INPUT

  • 1本指タッチでは送られてこない
  • RAWINPUT->data.hid.dwCount: 合計タッチ数(ContactCount) - 1 とは限らず、計3回に分けて送ってきたりもする
  • Values from (RAWINPUT->data.hid.bRawData + RAWINPUT->data.hid.dwSizeHid * {0, 1, ... , dwCount - 1}) (ポインタ演算です)
    • LinkCollection: 0
      • ScanTime: 1回目のメッセージと同
      • ContactCount: 必ず0
    • LinkCollection: 1
      • ContactID
      • X
      • Y
  • Usages (Button input) from (RAWINPUT->data.hid.bRawData + RAWINPUT->data.hid.dwSizeHid * {0, 1, ... , dwCount - 1})
    • LinkCollection: 1
      • Tip (あればOn, なければOff)
      • IsFinger (あれば指判定, なければ手の平判定)

といった感じになってます。

実装としては、

  • 1回目のメッセージではContactCountとLinkCollectionの最大値が一致しないことで従来型のメッセージと判別できる
  • 2回目のメッセージでは RAWINPUT->data.hid.dwCountが2以上となること、または ContactCountが0であることで従来型のメッセージと判別できる
 HidP_GetUsageValue(
      HIDP_REPORT_TYPE.HidP_Input,
      valueCap.UsagePage,
      valueCap.LinkCollection,
      valueCap.Usage,
      out uint value,
      preparsedDataPointer,
-     rawHidRawDataPointer,
+    // rawHidRawDataPointerからRAWINPUT->data.hid.dwSizeHidバイト * {0, 1, 2 ...}だけポインタをズラしてください。
+    // 現在rawHidRawDataPointerがIntPtr型なのでそのまま+で足すと多分バグります。気をつけて…。
      (uint)rawHidRawData.Length)

みたいな感じで行けると思います。プルリク送れなくてすみません。

一応自前のC++での実装を載せておきます。参考になれば幸いです。

Microsoftのページ の"Packet reporting modes"の節を見る限り、なんだかもっとデータにバリエーションがありそうな気もしていて、非常に恐ろしく思っています……。

@emoacht
Copy link
Owner

emoacht commented Nov 2, 2021

わざわざお知らせいただきありがとうございます。
こちらでも見直してみます。

@kamektx
Copy link
Author

kamektx commented Nov 2, 2021

嫌な予感がしたとおり、必ず2回に分けてデータが送られてくるわけではなく、3回だったりすることがわかりました。
最初のポストをそれに合わせて訂正しておきます。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants