@@ -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,86 @@ 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_battery_status ( & self ) -> Option < u8 > {
114
+ let mut msg = [ 0u8 ; 0x40 ] ;
115
+ msg[ 0 ] = 0x0D ;
116
+ self . device . read ( & mut msg) . ok ( ) ?;
117
+ // println!(" Tip Switch {}%", msg[12]);
118
+ // println!(" Barrell Switch: {}%", msg[12]);
119
+ // println!(" Eraser: {}%", msg[12]);
120
+ // println!(" Invert: {}%", msg[12]);
121
+ // println!(" In Range: {}%", msg[12]);
122
+ // println!(" 2nd Barrel Switch:{}%", msg[12]);
123
+ // println!(" X {}%", msg[12]);
124
+ // println!(" Y {}%", msg[12]);
125
+ // println!(" Tip Pressure: {}%", msg[12]);
126
+ // println!(" X Tilt: {}%", msg[12]);
127
+ // println!(" Y Tilt: {}%", msg[12]);
128
+ debug ! ( " Battery Strength: {}%" , msg[ 12 ] ) ;
129
+ debug ! (
130
+ " Barrel Pressure: {}" ,
131
+ u16 :: from_le_bytes( [ msg[ 13 ] , msg[ 14 ] ] )
132
+ ) ;
133
+ debug ! ( " Transducer Index: {}" , msg[ 15 ] ) ;
134
+
135
+ if msg[ 12 ] == 0 {
136
+ None
137
+ } else {
138
+ Some ( msg[ 12 ] )
139
+ }
140
+ }
141
+
142
+ fn get_stylus_fw ( & self ) -> Option < ( ) > {
143
+ let mut msg = [ 0u8 ; 0x40 ] ;
144
+ msg[ 0 ] = REPORT_ID_USI_VER ;
145
+ self . device . get_feature_report ( & mut msg) . ok ( ) ?;
146
+ let usi_major = msg[ 2 ] ;
147
+ let usi_minor = msg[ 3 ] ;
148
+ debug ! ( "USI version (Major.Minor): {}.{}" , usi_major, usi_minor) ;
149
+
150
+ if usi_major != 2 || usi_minor != 0 {
151
+ // Probably not USI mode
152
+ return None ;
153
+ }
154
+
155
+ let mut msg = [ 0u8 ; 0x40 ] ;
156
+ msg[ 0 ] = REPORT_ID_FIRMWARE ;
157
+ self . device . get_feature_report ( & mut msg) . ok ( ) ?;
158
+ let sn_low = u32:: from_le_bytes ( [ msg[ 2 ] , msg[ 3 ] , msg[ 4 ] , msg[ 5 ] ] ) ;
159
+ let sn_high = u32:: from_le_bytes ( [ msg[ 6 ] , msg[ 7 ] , msg[ 8 ] , msg[ 9 ] ] ) ;
160
+ let vid = u16:: from_le_bytes ( [ msg[ 14 ] , msg[ 15 ] ] ) ;
161
+ let vendor = if vid == 0x32AC {
162
+ " (Framework Computer)"
163
+ } else {
164
+ ""
165
+ } ;
166
+ let pid = u16:: from_le_bytes ( [ msg[ 16 ] , msg[ 17 ] ] ) ;
167
+ let product = if pid == 0x002B {
168
+ " (Framework Stylus)"
169
+ } else {
170
+ ""
171
+ } ;
172
+ println ! ( "Stylus" ) ;
173
+ println ! ( " Serial Number: {:X}-{:X}" , sn_high, sn_low) ;
174
+ debug ! ( " Redundant SN {:X?}" , & msg[ 10 ..14 ] ) ;
175
+ println ! ( " Vendor ID: {:04X}{}" , vid, vendor) ;
176
+ println ! ( " Product ID: {:04X}{}" , pid, product) ;
177
+ println ! ( " Firmware Version: {:02X}.{:02X}" , & msg[ 18 ] , msg[ 19 ] ) ;
178
+
179
+ Some ( ( ) )
180
+ }
100
181
}
101
182
102
183
pub trait TouchScreen {
103
- fn open_device ( ) -> Option < Self >
184
+ fn open_device ( usage_page : u16 , skip : u8 ) -> Option < Self >
104
185
where
105
186
Self : std:: marker:: Sized ;
106
187
fn send_message ( & self , message_id : u8 , read_len : usize , data : Vec < u8 > ) -> Option < Vec < u8 > > ;
107
188
108
189
fn check_fw_version ( & self ) -> Option < ( ) > {
109
190
println ! ( "Touchscreen" ) ;
191
+
110
192
let res = self . send_message ( 0x42 , 3 , vec ! [ 0 ] ) ?;
111
193
let ver = res
112
194
. iter ( )
@@ -135,22 +217,44 @@ pub trait TouchScreen {
135
217
self . send_message ( 0x38 , 0 , vec ! [ !enable as u8 , 0x00 ] ) ?;
136
218
Some ( ( ) )
137
219
}
220
+
221
+ fn get_stylus_fw ( & self ) -> Option < ( ) > ;
222
+ fn get_battery_status ( & self ) -> Option < u8 > ;
223
+ }
224
+
225
+ pub fn get_battery_level ( ) -> Option < u8 > {
226
+ for skip in 0 ..5 {
227
+ if let Some ( device) = HidapiTouchScreen :: open_device ( 0x000D , skip) {
228
+ if let Some ( level) = device. get_battery_status ( ) {
229
+ return Some ( level) ;
230
+ }
231
+ }
232
+ }
233
+ None
138
234
}
139
235
140
236
pub fn print_fw_ver ( ) -> Option < ( ) > {
237
+ for skip in 0 ..5 {
238
+ if let Some ( device) = HidapiTouchScreen :: open_device ( 0x000D , skip) {
239
+ if device. get_stylus_fw ( ) . is_some ( ) {
240
+ break ;
241
+ }
242
+ }
243
+ }
244
+
141
245
#[ cfg( target_os = "windows" ) ]
142
- let device = touchscreen_win:: NativeWinTouchScreen :: open_device ( ) ?;
246
+ let device = touchscreen_win:: NativeWinTouchScreen :: open_device ( VENDOR_USAGE_PAGE , 0 ) ?;
143
247
#[ cfg( not( target_os = "windows" ) ) ]
144
- let device = HidapiTouchScreen :: open_device ( ) ?;
248
+ let device = HidapiTouchScreen :: open_device ( VENDOR_USAGE_PAGE , 0 ) ?;
145
249
146
250
device. check_fw_version ( )
147
251
}
148
252
149
253
pub fn enable_touch ( enable : bool ) -> Option < ( ) > {
150
254
#[ cfg( target_os = "windows" ) ]
151
- let device = touchscreen_win:: NativeWinTouchScreen :: open_device ( ) ?;
255
+ let device = touchscreen_win:: NativeWinTouchScreen :: open_device ( VENDOR_USAGE_PAGE , 0 ) ?;
152
256
#[ cfg( not( target_os = "windows" ) ) ]
153
- let device = HidapiTouchScreen :: open_device ( ) ?;
257
+ let device = HidapiTouchScreen :: open_device ( VENDOR_USAGE_PAGE , 0 ) ?;
154
258
155
259
device. enable_touch ( enable)
156
260
}
0 commit comments