2008/12/16

Windows 7 Touch Digitizer 心得

本文要說明的主要來自微軟的文件

For Windows 7, touch digitizers appear through HID as a touch digitizer (page 0x0D, usage 0x04).
The following usages are required:
• X (page 0x01, usage 0x30) and Y (page 0x01, usage 0x31).
• Contact ID (page 0x0D, usage 0x51).
• Tip switch (page 0x0D, usage 0x42) - 指示出手指是否碰觸到螢幕(Digitizer Surface)
• In-range (page 0x0D, usage 0x32).

關於 z 軸我一直覺得很有用,微軟有一段說明如下:
If the device supports z-axis detection, it reports in-range correctly. If the device does not support z-axis detection, the driver reports packets with in-range and tip switch set when a finger comes in contact with the digitizer.

我試著解釋一下(不保證我的理解正確):
如果有 z 軸值,就放在 In-Range 中,此時 Tip Switch 不必設定。
如果沒有 z 軸值,那麼碰觸時請設定 Tip Switch 及傳回適當的 In-Range 值。
(註: 這一版本與之前的 OS 規範不一樣,如與 XP Tablet PC,請見Windows XP Tablet PC OEM Preinstallation Kit (OPK))

底下的資訊是選擇性的,意思是硬體有支援再提供即可:
• Confidence (page 0x0D, usage 0x47) - 這一點很奇怪,意思是前面的觸控點資訊有可能是意外產生時,可以由裝置設定這個值。
• Width and height (page 0x0D, usages 0x48 and 0x49).

來看看一個 USB HID device report 的 sample:

Here is a sample report descriptor for a touch digitizer device:
0x05, 0x0d, // USAGE_PAGE (Digitizers) 0
0x09, 0x04, // USAGE (Touch Screen) 2
0xa1, 0x01, // COLLECTION (Application) 4
0x85, REPORTID_TOUCH, // REPORT_ID (Touch) 6
0x09, 0x20, // USAGE (Stylus) 8
0xa1, 0x00, // COLLECTION (Physical) 10
0x09, 0x42, // USAGE (Tip Switch) 12
0x15, 0x00, // LOGICAL_MINIMUM (0) 14
0x25, 0x01, // LOGICAL_MAXIMUM (1) 16
0x75, 0x01, // REPORT_SIZE (1) 18
0x95, 0x01, // REPORT_COUNT (1) 20
0x81, 0x02, // INPUT (Data,Var,Abs) 22
0x95, 0x03, // REPORT_COUNT (3) 24
0x81, 0x03, // INPUT (Cnst,Ary,Abs) 26
0x09, 0x32, // USAGE (In Range) 28
0x09, 0x37, // USAGE (Data Valid-Finger) 30
0x95, 0x02, // REPORT_COUNT (2) 32
0x81, 0x02, // INPUT (Data,Var,Abs) 34
0x95, 0x0a, // REPORT_COUNT (10) 36
0x81, 0x03, // INPUT (Cnst,Ary,Abs) 38
0x05, 0x01, // USAGE_PAGE (Generic Desktop) 40
0x26, 0xff, 0x7f, // LOGICAL_MAXIMUM (32767) 42
0x75, 0x10, // REPORT_SIZE (16) 45
0x95, 0x01, // REPORT_COUNT (1) 47
0xa4, // PUSH 49
0x55, 0x0d, // UNIT_EXPONENT (-3) 50
0x65, 0x00, // UNIT (None) 52
0x09, 0x30, // USAGE (X) 54
0x35, 0x00, // PHYSICAL_MINIMUM (0) 56
0x46, 0x00, 0x00, // PHYSICAL_MAXIMUM (0) 58
0x81, 0x02, // INPUT (Data,Var,Abs) 61
0x09, 0x31, // USAGE (Y) 63
0x46, 0x00, 0x00, // PHYSICAL_MAXIMUM (0) 65
0x81, 0x02, // INPUT (Data,Var,Abs) 68
0xb4, // POP 70
0x05, 0x0d, // USAGE PAGE (Digitizers) 71
0x09, 0x60, // USAGE (Width) 73
0x09, 0x61, // USAGE (Height) 75
0x95, 0x02, // REPORT_COUNT (2) 77
0x81, 0x02, // INPUT (Data,Var,Abs) 79
0x95, 0x01, // REPORT_COUNT (1) 81
0x81, 0x03, // INPUT (Cnst,Ary,Abs) 83/85
#ifdef _ CUSTOMVENDORUSAGE _
0x06, 0x00, 0xff, // USAGE_PAGE (Vendor Defined) 0
0x09, 0x80, // USAGE (Vendor Usage 0x80) 3
0x09, 0x81, // USAGE (Vendor Usage 0x81) 5
0x15, 0x00, // LOGICAL_MINIMUM (0) 7
0x27, 0xff, 0xff, 0xff, 0xff, // LOGICAL_MAXIMUM (0xffffffff) 9
0x75, 0x20, // REPORT_SIZE (32) 14
0x95, 0x02, // REPORT_COUNT (2) 16
0x81, 0x02, // INPUT (Data,Var,Abs) 18/20
#endif
0xc0, // END_COLLECTION 0/1
0xc0, // END_COLLECTION 0/1


底下的資訊由微軟提出,隨時有可能修正:









Proposed Additions to the HID Specification to Support Multitouch
Description Page Type Name ID
Contact identifier Digitizer DV (Dynamic Value) Contact identifier 0x51
Configuration Digitizer CA (Collection Application) Configuration 0x0E
Input mode Digitizer DV (Dynamic Value) Input mode 0x52
Device index Digitizer DV (Dynamic Value) Device index 0x53
Actual contact count Digitizer DV (Dynamic Value) Contact count 0x54
Maximum number of contacts supported Digitizer DV (Dynamic Value) Maximum count 0x55


Reporting 模式有三種, 建議採用 Parallel Mode:
• Serial mode: 一次只有一個單一接觸點. 這種模式有可能會改變裝置報告的速度。
• Parallel mode: 每個封包夠寬,足以容納所有接觸
• Hybrid mode: 混合模式可以將前面兩個模式視為它的特例,它擁有固定寬度的封包,卻同時可以擁有多個封包內容。

Parallel Mode 會使用到 Actual contact count 及 Null Value, 底下有個範例,根據 maximum count 及 actual count 的不同可以視為 Parallel Mode 或 Hybrid Mode:

0x05, 0x0d, // USAGE_PAGE (Digitizers)
0x09, 0x04, // USAGE (Touch Screen)
0xa1, 0x01, // COLLECTION (Application)
0x85, REPORTID_PEN, // REPORT_ID (Touch)
0x09, 0x22, // USAGE (Finger)
0xa1, 0x02, // COLLECTION (Logical)
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)
0x09, 0x32, // USAGE (In Range)
0x81, 0x02, // INPUT (Data,Var,Abs)
0x09, 0x47, // USAGE (Touch Valid)
0x81, 0x02, // INPUT (Data,Var,Abs)
0x95, 0x05, // REPORT_COUNT (5)
0x81, 0x03, // INPUT (Cnst,Ary,Abs)
0x75, 0x08, // REPORT_SIZE (8)
0x09, 0x51, // USAGE (Contact Identifier)
0x95, 0x01, // REPORT_COUNT (1)
0x81, 0x02, // INPUT (Data,Var,Abs)
0x05, 0x01, // USAGE_PAGE (Generic Desk..
0x26, 0xff, 0x7f, // LOGICAL_MAXIMUM (32767)
0x75, 0x10, // REPORT_SIZE (16)
0x55, 0x00, // UNIT_EXPONENT (0)
0x65, 0x00, // UNIT (None)
0x09, 0x30, // USAGE (X)
0x35, 0x00, // PHYSICAL_MINIMUM (0)
0x46, 0x00, 0x00, // PHYSICAL_MAXIMUM (0)
0x81, 0x02, // INPUT (Data,Var,Abs)
0x09, 0x31, // USAGE (Y)
0x46, 0x00, 0x00, // PHYSICAL_MAXIMUM (0)
0x81, 0x02, // INPUT (Data,Var,Abs)
0xc0, // END_COLLECTION
0xa1, 0x02, // COLLECTION (Logical)
0x05, 0x0d, // USAGE_PAGE (Digitizers)
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)
0x09, 0x32, // USAGE (In Range)
0x81, 0x02, // INPUT (Data,Var,Abs)
0x09, 0x47, // USAGE (Touch Valid)
0x81, 0x02, // INPUT (Data,Var,Abs)
0x95, 0x05, // REPORT_COUNT (5)
0x81, 0x03, // INPUT (Cnst,Ary,Abs)
0x75, 0x08, // REPORT_SIZE (8)
0x09, 0x51, // USAGE ( Temp Identifier)
0x95, 0x01, // REPORT_COUNT (1)
0x81, 0x02, // INPUT (Data,Var,Abs)
0x05, 0x01, // USAGE_PAGE (Generic Desk..
0x26, 0xff, 0x7f, // LOGICAL_MAXIMUM (32767)
0x75, 0x10, // REPORT_SIZE (16)
0x55, 0x00, // UNIT_EXPONENT (0)
0x65, 0x00, // UNIT (None)
0x09, 0x30, // USAGE (X)
0x35, 0x00, // PHYSICAL_MINIMUM (0)
0x46, 0x00, 0x00, // PHYSICAL_MAXIMUM (0)
0x81, 0x02, // INPUT (Data,Var,Abs)
0x09, 0x31, // USAGE (Y)
0x46, 0x00, 0x00, // PHYSICAL_MAXIMUM (0)
0x81, 0x02, // INPUT (Data,Var,Abs)
0xc0, // END_COLLECTION
0x05, 0x0d, // USAGE_PAGE (Digitizers)
0x09, 0x54, // USAGE (Actual count)
0x95, 0x01, // REPORT_COUNT (1)
0x75, 0x08, // REPORT_SIZE (8)
0x15, 0x00, // LOGICAL_MINIMUM (0)
0x27, 0x08, // LOGICAL_MAXIMUM (255)
0x81, 0x02, // INPUT (Data,Var,Abs)
0x09, 0x56, // USAGE(Maximum Count)
0xb1, 0x02, // FEATURE (Data,Var,Abs)
0xc0, // END_COLLECTION


Top-Level Collection 每個裝置一定要有此描述內容,至少要指出來裝置是單點輸入、多點輸入或是滑鼠。

Collection Applications (CAs) 值對應的裝置若為底下的值,均可以用來做多點輸入:
Digitizer - 1
Pen - 2
Touch Screen - 4
Touch Pad - 5


多點觸控裝置應該在 top-level collections中採用 Finger (0x22) CL (Collection Logical) 來裝 data 及控制訊息。

多觸控裝置的尋找與組態能力:
尋找是透過 report descriptor 裡的 input mode 完成,也應該允許作業系統重新規劃成 multi-input, single-input, or mouse top-level collection。為了系統安全考量,此項 report descriptor 只允許作業系統存取,不開放第三方應用程式存取。這一點跟舊的 Vista 或 XP, 2000 都不一樣,舊的作業系統允許第三方應用程式透過 feature report 重設裝置為 single touch or the mouse。

Feature Report Requirements
所有裝置都需要一個 feature report 在其 report descriptor 中,以便報告裝置的組態。底下來看個實例:

0x06, 0x0d // USAGE_PAGE (Digitizer)
Ox09, 0x0E // USAGE (Configuration)
0x85, REPORTID_FEATURE, // REPORT_ID (Feature)
0xa1, 0x01, // COLLECTION (Application)
0x09, 0x52, // USAGE (Input Mode)
0x09, 0x53, // USAGE (Device Index)
0x15, 0x00, // LOGICAL_MINIMUM (0)
0x27, 0x08, // LOGICAL_MAXIMUM (255)
0x75, 0x08, // REPORT_SIZE (8)
0x95, 0x02, // REPORT_COUNT (2)
0xb1, 0x02, // FEATURE (Data,Var,Abs)
0xc0, // END_COLLECTION


Input Mode的值有:



Mode Value
Mouse (recommended default) 0x00
Single-input (single touch or stylus) 0x00
Multi-input 0x02

所以,多觸控點裝置是可以被重新設定成單一輸入裝置的,此時要表現的如作業系統所期望才行,而且微軟建議所有的多觸控裝置都預設採用 Mouse Mode。

Device Index
The device index usage selects the top-level collection to configure. A value of 0 tells the device to change the mode for every multi-input top-level collection in its report descriptor. A value of 1 and higher indicates the position of the top-level collection in the report descriptor. Applications that use values other than 0 must correctly handle the positions of the multi-input top-level collections in the report descriptor.

參考文獻:
  1. Device Class Definitions for Human Interface Devices (HID)
  2. HID Usage Tables

16 意見:

Unknown 提到...

您好:
請問驅動程式是否需要自己寫?或是OS以內建?

菠蘿麵包 提到...

Hi,
事實上 Win7 目前所知有各種不同的版本,以最陽春版來說連 Touch 都沒有,這一版非常接近 WinXP, 而高階版才會有 Multi-Touch, 若裝置符合本文說的 Digitizer 的規範的話,Win7 本身不必特別的趨動程式即可使用,包含手勢操作。當然,應用程式要特別去寫才能享有此項便利。

FelixLin 提到...

Hi,您好
我的HID Report有用到Tip Switch及In-Range,當touch down 時Tip Switch及In-Range設為"1",而當touch up時Tip Switch及In-Range設為"0",於windows 7操作時,發現click反應沒有像mouse那麼即時,例如我在桌面某一個ICON點一下,約過1秒event才發生,不知道您知不知道原因?

菠蘿麵包 提到...

我若說我不知道,或許你會罵我,確實是。我猜測一下答案:

在規範中,可以見到幾個欄位,不知道你是否都有 reset:

tip_switch = 0;
in_range = 0;
touch_valid = 0;
reserved = 0;

#if DUAL_TOUCH
contact_id = id;
x = 0;
y = 0;
#endif

還要想想一個問題,可能不是 reset 的問題,而是你在做 HID 的 protocol talking 時沒弄對,這部份若有問題可以再提出討論。

Coke 提到...

Hi,
請問你所提到的規範是在那裡可以得到?可以email給我嗎? 另外protocol talking的部分有什麼地方要注意的嗎? 謝謝!

andrewcoke0918@gmail.com

oneball 提到...

您好,小弟最近在研讀微軟此篇文章,也出現一些困惑,所以來跟您請教,
(1)Null Values,
Device必須填"0"給剩下無用的欄位,來告訴Host.
(2)Hybird Mode,
若一各Device最多能支援48各觸摸點,且一各封包最多送12點,假設今天有47點被觸發,則Device會送出4各封包,其中最後一各封包資料為11點+0.

不知小弟這想法正確嗎?若是對的,那微軟文中還有此段話,
若Device採用Hybird Mode,Device必須一開始就告訴Host,一共有幾點會被傳送=>我的疑問是既然可以用Null Values,為何還需要先告訴Host呢?

謝謝您

菠蘿麵包 提到...

Coke 的問題,請參考文中最前面的 URL, 還有Input Device

oneball 的問題我的想法是這樣:
Null Values 指的是一個 Package 是否有效的 Touch

也就是 NULL values 與字串的 #xxx 及 xxx\0 兩種意義上並不相同。

PS: 敝公司從未實作過 Hybrid Mode, 無從查證。

Coke 提到...

Hi!

謝謝你的回覆. 我有試著照規範加parallel 的descriptor. 可是我沒有看到有:
tip_switch = 0;
in_range = 0;
touch_valid = 0;
reserved = 0;

#if DUAL_TOUCH
contact_id = id;
x = 0;
y = 0;
#endif

我以為是有類似的sample code, 所以才跟你請教. 因為我的裝置試著傳上面的幾項資料到一台有multi-touch panel的notebook上, 都沒有反應. 才想是不是有那裡遺漏的.

謝謝!

K.C 提到...

版主您好,
最近接觸Touch的工作,有些問題希望版主能提供意見,謝謝...
關於"Device Identifier",假設我有兩個
top-level collection 在我的 report descriptor(one is Digitizer, the other is mouse)

而其中 Feature report如下:
0x09, 0x0E,
0xA1, 0x01,
0x85, 0x03,
0x09, 0x23, //(Device Setting)
0xA1, 0x02,
0x09, 0x52, //(Device Mode)
0x09, 0x53, //(Device Identifier)
0x15, 0x00,
0x25, 0x0a,
0x75, 0x08, //REPORT_SIZE (8)
0x95, 0x02, //REPORT_COUNT (2)
0xB1, 0x02, //FEATURE
0xC0,
0xC0,

假設我的裝置初始設定為"MOUSE",當我將裝置接上Win 7後, 系統將會發出一個 SET_FEATURE命令,依照上面的 FEATURE,命令裡將包含一個Device Mode(設為 0x02, Multi-input), 另一為 Device identifier, 其值不為固定,這個 Device identifier是做什麼用的呢? 文章上說:
"If the device can function as a mouse, the mouse collection should have the same device identifier as the corresponding digitizer collection".

我需要將
"0x09, 0x53,//Device identifier" 這個欄位增加在Digitize 和 Mouse collection中嗎?
這個 "Device identifier" 是做何用處呢?? 是否有範例可參考說明? 謝謝了

Fish 提到...

有關 K.C. 的問題 , 我知道的大約是這樣 , 這個 Device identifier , 如果是在 Multi-input Mode , 那這個 Device identifier 指的就是 您的硬體最多可以支援到幾點 ? 一般都是填 0x02 !!

不過這裡只會影響 第四層 應用層的命令 , 並不會影響第二層的宣告 , 也就是說 這裡只會影響您在 system 那邊所顯示的訊息正確與否 , 並不會影響硬體層的溝通

K.C 提到...

Fish版主您好,
感謝您的回覆,關於您的回覆,我有些疑問,
"如果是在 Multi-input Mode , 那這個 Device identifier 指的就是 您的硬體最多可以支援到幾點 ? 一般都是填 0x02", 硬體最多可以支援幾點不是在 Digitizer collection 中的Feature 中宣告
"0x09, 0x55,//Contact count maximum)" 嗎? 系統會送出 GET_FEATURE命令, 由韌體回覆而得到最大支援的點數.

而您說的回覆 "0x02", 應該是指 Device setting的 collection 中指定的 "Device Mode" (0x02 為 Multi-input), 而我的問題是, 在我的 Device setting的 collection宣告中, 除了宣告有 "Device Mode" 還有一個 "Device Identifier", 而這個 "Device Identifier" 的功能為何? 感覺這個值好像由系統給定,但是不管是Mouse或是Digitizer在回報的input report中,都沒有使用到? 而文章上說:
"If the device can function as a mouse, the mouse collection should have the same device identifier as the corresponding digitizer collection".
這個值的意義何在呢? 謝謝了

菠蘿麵包 提到...

先聲明一下,我本身其實並沒有在開發相關的軟、硬體,只是看到文件貼心得,不過試著回答一下:

在 Input Mode的值有:

Mode Value
Mouse (recommended default) 0x00
Single-input (single touch or stylus) 0x00
Multi-input 0x02

裡面有提到,Multi-input 的值是 0x02,指的不是「點數」,點數是在 USB HID device report 中填進去

K.C 提到...

是...關於支援點數的問題我明白,我想知道的是 "Device Identifier" 是做何用處呢?? Document說的不是很明白,也沒有範例可參考, 系統發出命令設定DI之後就沒有再利用這個值,那這個值到底是在做什麼用的呢? 謝謝囉

菠蘿麵包 提到...

Device Identifier, 翻成中文叫....裝置識別號碼,當然是給 OS 看的,所以通常照填就對了。真像您這樣要搞清楚來龍去脈的話,應該去 windows 的網站問。

不過,我還是把我的認知說一下,再聲明,我並沒真的去實作過,所說可能是錯的。

Device Identifier 在作業系統上會去識別它有什麼能力,對微軟來說,不同的作業系統,包括 win7 本身的不同版本,就有可能支援或不支援。

總之,就是識別它有什麼能力,而這,是作業系統的事,跟動作能力本身無關。

Unknown 提到...

請問以下 描述 Tip switch ,IN range, Confidence 以及 Contact Identifier 各是給個 bits?

typedef struct
{
U8 Controls; // Tip Switch, In Range, Confidence
U8 Contact_Identifier;
UU16 X;
UU16 Y;
UU16 Width;
UU16 Height;
UU16 Pressure;
} Touch_Structure;



0x09, 0x22, // USAGE (Finger)
0xA1, 0x02, // COLLECTION (Logical)
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)
0x09, 0x32, // USAGE (In Range)
0x81, 0x02, // INPUT (Data,Var,Abs)
0x09, 0x47, // USAGE (Confidence)
0x81, 0x02, // INPUT (Data,Var,Abs)
0x95, 0x05, // REPORT_COUNT (5)
0x81, 0x03, // INPUT (Cnst,Ary,Abs)
0x75, 0x08, // REPORT_SIZE (8)
0x09, 0x51, // USAGE (Contact Identifier)
0x95, 0x01, // REPORT_COUNT (1)
0x81, 0x02, // INPUT (Data,Var,Abs)

菠蘿麵包 提到...

建議自己用軟體來 trace usb communication, 例如:
http://www.sysnucleus.com/
http://www.usblyzer.com/