@@ -5,16 +5,24 @@ use crate::touchscreen_win;
55
66pub const ILI_VID : u16 = 0x222A ;
77pub const ILI_PID : u16 = 0x5539 ;
8+ const VENDOR_USAGE_PAGE : u16 = 0xFF00 ;
89pub const USI_BITMAP : u8 = 1 << 1 ;
910pub const MPP_BITMAP : u8 = 1 << 2 ;
1011
12+ const REPORT_ID_FIRMWARE : u8 = 0x27 ;
13+ const REPORT_ID_USI_VER : u8 = 0x28 ;
14+
1115struct HidapiTouchScreen {
1216 device : HidDevice ,
1317}
1418
1519impl 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;
1826 match HidApi :: new ( ) {
1927 Ok ( api) => {
2028 for dev_info in api. device_list ( ) {
@@ -29,7 +37,7 @@ impl TouchScreen for HidapiTouchScreen {
2937 " Found {:04X}:{:04X} (Usage Page {:04X})" ,
3038 vid, pid, usage_page
3139 ) ;
32- if usage_page != 0xFF00 {
40+ if usage_page != target_up {
3341 debug ! ( " Skipping usage page. Expected {:04X}" , 0xFF00 ) ;
3442 continue ;
3543 }
@@ -40,6 +48,10 @@ impl TouchScreen for HidapiTouchScreen {
4048 debug ! ( " Found matching touchscreen HID device" ) ;
4149 debug ! ( " Path: {:?}" , dev_info. path( ) ) ;
4250 debug ! ( " IC Type: {:04X}" , pid) ;
51+ if skip > 0 {
52+ skip -= 1 ;
53+ continue ;
54+ }
4355
4456 // Unwrapping because if we can enumerate it, we should be able to open it
4557 let device = dev_info. open_device ( & api) . unwrap ( ) ;
@@ -97,16 +109,86 @@ impl TouchScreen for HidapiTouchScreen {
97109 debug ! ( " Read buf: {:X?}" , buf) ;
98110 Some ( buf[ msg_len..msg_len + read_len] . to_vec ( ) )
99111 }
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+ }
100181}
101182
102183pub trait TouchScreen {
103- fn open_device ( ) -> Option < Self >
184+ fn open_device ( usage_page : u16 , skip : u8 ) -> Option < Self >
104185 where
105186 Self : std:: marker:: Sized ;
106187 fn send_message ( & self , message_id : u8 , read_len : usize , data : Vec < u8 > ) -> Option < Vec < u8 > > ;
107188
108189 fn check_fw_version ( & self ) -> Option < ( ) > {
109190 println ! ( "Touchscreen" ) ;
191+
110192 let res = self . send_message ( 0x42 , 3 , vec ! [ 0 ] ) ?;
111193 let ver = res
112194 . iter ( )
@@ -135,22 +217,44 @@ pub trait TouchScreen {
135217 self . send_message ( 0x38 , 0 , vec ! [ !enable as u8 , 0x00 ] ) ?;
136218 Some ( ( ) )
137219 }
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
138234}
139235
140236pub 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+
141245 #[ cfg( target_os = "windows" ) ]
142- let device = touchscreen_win:: NativeWinTouchScreen :: open_device ( ) ?;
246+ let device = touchscreen_win:: NativeWinTouchScreen :: open_device ( VENDOR_USAGE_PAGE , 0 ) ?;
143247 #[ cfg( not( target_os = "windows" ) ) ]
144- let device = HidapiTouchScreen :: open_device ( ) ?;
248+ let device = HidapiTouchScreen :: open_device ( VENDOR_USAGE_PAGE , 0 ) ?;
145249
146250 device. check_fw_version ( )
147251}
148252
149253pub fn enable_touch ( enable : bool ) -> Option < ( ) > {
150254 #[ cfg( target_os = "windows" ) ]
151- let device = touchscreen_win:: NativeWinTouchScreen :: open_device ( ) ?;
255+ let device = touchscreen_win:: NativeWinTouchScreen :: open_device ( VENDOR_USAGE_PAGE , 0 ) ?;
152256 #[ cfg( not( target_os = "windows" ) ) ]
153- let device = HidapiTouchScreen :: open_device ( ) ?;
257+ let device = HidapiTouchScreen :: open_device ( VENDOR_USAGE_PAGE , 0 ) ?;
154258
155259 device. enable_touch ( enable)
156260}
0 commit comments