Bamboo Touchで複数の指の絶対座標を取る

next : http://d.hatena.ne.jp/mjt/20091005/p2
USBから直接取る方法は直ぐ分かったものの、まだWinTAB経由で取る方法が分からない。。

USB HIDレポート

  • Set_Reportで送出を有効にする必要が有る。
  • エンドポイント 0x82が指、0x81が従来のタブレットと互換性のあるペンイベントとなる。
    • 起動時はマウスとして動作しペンではなく指で操作する。この場合、タップは無効。
    • 起動時のイベントは0x81で受け取る。
  • 長さは0x14 bytes。ちょうど読み取ること。
      <- GROUP 1              -> <- GROUP 2              ->
      PP xxxxx yyyyy XXXXX YYYYY PP xxxxx yyyyy XXXXX YYYYY
02 00 00 00 00 00 00 81 42 00 aa 34 81 47 00 aa 80 11 00 00

レポートは2つのグループに分かれている。

  • グループ1
    • P : 圧力?
    • x : X座標(先頭1ビットは有効フラグ、big endian)
    • y : Y座標
    • X : X座標?
    • Y : Y座標?
  • グループ2
    • P : 圧力?
    • x : X座標(先頭1ビットは有効フラグ、big endian)
    • y : Y座標

複数の指を検出した場合の挙動はちょっと難しくて、

  • 1つの指しか検出しない場合はGroup 1を使う
  • Group 1を使っているときにさらに指を検出したときはGroup 2を使う
    • このとき、トラッキングしている指が入れ替わることがある
  • Group 2を使っているときにGroup 1上の指を離してもGroup 2を使い続ける
  • 3本以上の指を置くと、何か間違ったことが起こる

code

moshで書かれているが、svnmoshでも実行できない。
重要なのは2箇所で、

(usb_claim_interface dh 1)

タッチを読み取るためにはインターフェース1をclaimする必要が有る。

; Class Write Request / HID Set_Report / value #x302 / index 0
(define init-data #vu8(2 2))
(usb_control_msg dh 33 9 #x0302 0 init-data 2)

タッチのリポートを有効にするためには、Set_Reportする必要が有る。これはHIDのclassリクエストで、libusbならcontrol_msgによって行える。書き込むデータは"0x02 0x02"(2 bytes)。

(import (rnrs)
        (ext win32 usb)
        (srfi :42))

(usb_init)
(define dh (usb_open0 #x56a #xd1))
(display dh)(newline)
(usb_set_configuration dh 1)
(usb_claim_interface dh 0)
(usb_claim_interface dh 1)

(define buflen #x14)
(define buf (make-bytevector buflen))

(define init-data #vu8(2 2))

; Class Write Request / HID Set_Report / value #x302 / index 0
(usb_control_msg dh 33 9 #x0302 0 init-data 2)

(define (loop)
  (define (tab-display bv)
    (define (display-x bv)
      (define (dispbyte b)
        (let ((str (number->string b 16)))
          (when (< (string-length str) 2) (display "0"))
          (display str) (display " ")))
      (do-ec (: x 0 (bytevector-length bv)) (dispbyte (bytevector-u8-ref bv x))))

    (display "      PP xxxxx yyyyy XXXXX YYYYY PP xxxxx yyyyy XXXXX YYYYY")(newline)
    (display-x bv)(newline))
  (let ((r (usb_interrupt_read dh #x82 buf buflen)))
    (if (< r 0)
      (loop)
      (begin
        (tab-display buf)(newline)
        (loop)))))

(loop)