@@ -5,16 +5,24 @@ use crate::touchscreen_win;
5
5
6
6
pub const ILI_VID : u16 = 0x222A ;
7
7
pub const ILI_PID : u16 = 0x5539 ;
8
+ const VENDOR_USAGE_PAGE : u16 = 0xFF00 ;
8
9
pub const USI_BITMAP : u8 = 1 << 1 ;
9
10
pub const MPP_BITMAP : u8 = 1 << 2 ;
10
11
12
+ const REPORT_ID_FIRMWARE : u8 = 0x27 ;
13
+ const REPORT_ID_USI_VER : u8 = 0x28 ;
14
+
11
15
struct HidapiTouchScreen {
12
16
device : HidDevice ,
13
17
}
14
18
15
19
impl TouchScreen for HidapiTouchScreen {
16
- fn open_device ( ) -> Option < HidapiTouchScreen > {
17
- debug ! ( "Looking for touchscreen HID device" ) ;
20
+ fn open_device ( target_up : u16 , skip : u8 ) -> Option < HidapiTouchScreen > {
21
+ debug ! (
22
+ "Looking for touchscreen HID device {:X} {}" ,
23
+ target_up, skip
24
+ ) ;
25
+ let mut skip = skip;
18
26
match HidApi :: new ( ) {
19
27
Ok ( api) => {
20
28
for dev_info in api. device_list ( ) {
@@ -29,7 +37,7 @@ impl TouchScreen for HidapiTouchScreen {
29
37
" Found {:04X}:{:04X} (Usage Page {:04X})" ,
30
38
vid, pid, usage_page
31
39
) ;
32
- if usage_page != 0xFF00 {
40
+ if usage_page != target_up {
33
41
debug ! ( " Skipping usage page. Expected {:04X}" , 0xFF00 ) ;
34
42
continue ;
35
43
}
@@ -40,6 +48,10 @@ impl TouchScreen for HidapiTouchScreen {
40
48
debug ! ( " Found matching touchscreen HID device" ) ;
41
49
debug ! ( " Path: {:?}" , dev_info. path( ) ) ;
42
50
debug ! ( " IC Type: {:04X}" , pid) ;
51
+ if skip > 0 {
52
+ skip -= 1 ;
53
+ continue ;
54
+ }
43
55
44
56
// Unwrapping because if we can enumerate it, we should be able to open it
45
57
let device = dev_info. open_device ( & api) . unwrap ( ) ;
@@ -97,16 +109,57 @@ impl TouchScreen for HidapiTouchScreen {
97
109
debug ! ( " Read buf: {:X?}" , buf) ;
98
110
Some ( buf[ msg_len..msg_len + read_len] . to_vec ( ) )
99
111
}
112
+
113
+ fn get_stylus_fw ( & self ) -> Option < ( ) > {
114
+ let mut msg = [ 0u8 ; 0x40 ] ;
115
+ msg[ 0 ] = REPORT_ID_USI_VER ;
116
+ self . device . get_feature_report ( & mut msg) . ok ( ) ?;
117
+ let usi_major = msg[ 2 ] ;
118
+ let usi_minor = msg[ 3 ] ;
119
+ debug ! ( "USI version (Major.Minor): {}.{}" , usi_major, usi_minor) ;
120
+
121
+ if usi_major != 2 || usi_minor != 0 {
122
+ // Probably not USI mode
123
+ return None ;
124
+ }
125
+
126
+ let mut msg = [ 0u8 ; 0x40 ] ;
127
+ msg[ 0 ] = REPORT_ID_FIRMWARE ;
128
+ self . device . get_feature_report ( & mut msg) . ok ( ) ?;
129
+ let sn_low = u32:: from_le_bytes ( [ msg[ 2 ] , msg[ 3 ] , msg[ 4 ] , msg[ 5 ] ] ) ;
130
+ let sn_high = u32:: from_le_bytes ( [ msg[ 6 ] , msg[ 7 ] , msg[ 8 ] , msg[ 9 ] ] ) ;
131
+ let vid = u16:: from_le_bytes ( [ msg[ 14 ] , msg[ 15 ] ] ) ;
132
+ let vendor = if vid == 0x32AC {
133
+ " (Framework Computer)"
134
+ } else {
135
+ ""
136
+ } ;
137
+ let pid = u16:: from_le_bytes ( [ msg[ 16 ] , msg[ 17 ] ] ) ;
138
+ let product = if pid == 0x002B {
139
+ " (Framework Stylus)"
140
+ } else {
141
+ ""
142
+ } ;
143
+ println ! ( "Stylus" ) ;
144
+ println ! ( " Serial Number: {:X}-{:X}" , sn_high, sn_low) ;
145
+ debug ! ( " Redundant SN {:X?}" , & msg[ 10 ..14 ] ) ;
146
+ println ! ( " Vendor ID: {:04X}{}" , vid, vendor) ;
147
+ println ! ( " Product ID: {:04X}{}" , pid, product) ;
148
+ println ! ( " Firmware Version: {:02X}.{:02X}" , & msg[ 18 ] , msg[ 19 ] ) ;
149
+
150
+ Some ( ( ) )
151
+ }
100
152
}
101
153
102
154
pub trait TouchScreen {
103
- fn open_device ( ) -> Option < Self >
155
+ fn open_device ( usage_page : u16 , skip : u8 ) -> Option < Self >
104
156
where
105
157
Self : std:: marker:: Sized ;
106
158
fn send_message ( & self , message_id : u8 , read_len : usize , data : Vec < u8 > ) -> Option < Vec < u8 > > ;
107
159
108
160
fn check_fw_version ( & self ) -> Option < ( ) > {
109
161
println ! ( "Touchscreen" ) ;
162
+
110
163
let res = self . send_message ( 0x42 , 3 , vec ! [ 0 ] ) ?;
111
164
let ver = res
112
165
. iter ( )
@@ -135,22 +188,32 @@ pub trait TouchScreen {
135
188
self . send_message ( 0x38 , 0 , vec ! [ !enable as u8 , 0x00 ] ) ?;
136
189
Some ( ( ) )
137
190
}
191
+
192
+ fn get_stylus_fw ( & self ) -> Option < ( ) > ;
138
193
}
139
194
140
195
pub fn print_fw_ver ( ) -> Option < ( ) > {
196
+ for skip in 0 ..5 {
197
+ if let Some ( device) = HidapiTouchScreen :: open_device ( 0x000D , skip) {
198
+ if device. get_stylus_fw ( ) . is_some ( ) {
199
+ break ;
200
+ }
201
+ }
202
+ }
203
+
141
204
#[ cfg( target_os = "windows" ) ]
142
- let device = touchscreen_win:: NativeWinTouchScreen :: open_device ( ) ?;
205
+ let device = touchscreen_win:: NativeWinTouchScreen :: open_device ( VENDOR_USAGE_PAGE , 0 ) ?;
143
206
#[ cfg( not( target_os = "windows" ) ) ]
144
- let device = HidapiTouchScreen :: open_device ( ) ?;
207
+ let device = HidapiTouchScreen :: open_device ( VENDOR_USAGE_PAGE , 0 ) ?;
145
208
146
209
device. check_fw_version ( )
147
210
}
148
211
149
212
pub fn enable_touch ( enable : bool ) -> Option < ( ) > {
150
213
#[ cfg( target_os = "windows" ) ]
151
- let device = touchscreen_win:: NativeWinTouchScreen :: open_device ( ) ?;
214
+ let device = touchscreen_win:: NativeWinTouchScreen :: open_device ( VENDOR_USAGE_PAGE , 0 ) ?;
152
215
#[ cfg( not( target_os = "windows" ) ) ]
153
- let device = HidapiTouchScreen :: open_device ( ) ?;
216
+ let device = HidapiTouchScreen :: open_device ( VENDOR_USAGE_PAGE , 0 ) ?;
154
217
155
218
device. enable_touch ( enable)
156
219
}
0 commit comments