1
1
#[ cfg( target_os = "linux" ) ]
2
2
use ectool:: AccessLpcLinux ;
3
3
use ectool:: { Access , AccessHid , Ec } ;
4
- use hidapi:: HidApi ;
4
+ use hidapi:: { DeviceInfo , HidApi } ;
5
5
use std:: {
6
6
cell:: { Cell , RefCell , RefMut } ,
7
7
collections:: HashMap ,
@@ -15,11 +15,12 @@ use super::{err_str, BoardId, Daemon, DaemonCommand};
15
15
use crate :: Matrix ;
16
16
17
17
pub struct DaemonServer < R : Read , W : Write > {
18
+ hidapi : RefCell < Option < HidApi > > ,
18
19
running : Cell < bool > ,
19
20
read : BufReader < R > ,
20
21
write : W ,
21
- boards : RefCell < HashMap < BoardId , Ec < Box < dyn Access > > > > ,
22
- board_ids : Vec < BoardId > ,
22
+ boards : RefCell < HashMap < BoardId , ( Ec < Box < dyn Access > > , Option < DeviceInfo > ) > > ,
23
+ board_ids : RefCell < Vec < BoardId > > ,
23
24
}
24
25
25
26
impl DaemonServer < io:: Stdin , io:: Stdout > {
@@ -39,7 +40,7 @@ impl<R: Read, W: Write> DaemonServer<R, W> {
39
40
Ok ( ec) => {
40
41
info ! ( "Adding LPC EC" ) ;
41
42
let id = BoardId ( Uuid :: new_v4 ( ) . as_u128 ( ) ) ;
42
- boards. insert ( id, ec. into_dyn ( ) ) ;
43
+ boards. insert ( id, ( ec. into_dyn ( ) , None ) ) ;
43
44
board_ids. push ( id) ;
44
45
}
45
46
Err ( err) => {
@@ -60,52 +61,84 @@ impl<R: Read, W: Write> DaemonServer<R, W> {
60
61
}
61
62
} ;
62
63
63
- if let Some ( api) = & hidapi {
64
+ let self_ = Self {
65
+ hidapi : RefCell :: new ( hidapi) ,
66
+ running : Cell :: new ( true ) ,
67
+ read : BufReader :: new ( read) ,
68
+ write,
69
+ boards : RefCell :: new ( boards) ,
70
+ board_ids : RefCell :: new ( board_ids) ,
71
+ } ;
72
+
73
+ self_. refresh ( ) ;
74
+
75
+ Ok ( self_)
76
+ }
77
+
78
+ fn have_device ( & self , info : & DeviceInfo ) -> bool {
79
+ for ( _, i) in self . boards . borrow ( ) . values ( ) {
80
+ if let Some ( i) = i {
81
+ if ( i. vendor_id ( ) , i. product_id ( ) , i. path ( ) )
82
+ == ( info. vendor_id ( ) , info. product_id ( ) , info. path ( ) )
83
+ {
84
+ return true ;
85
+ }
86
+ }
87
+ }
88
+ false
89
+ }
90
+
91
+ fn refresh ( & self ) {
92
+ if let Some ( api) = & mut * self . hidapi . borrow_mut ( ) {
93
+ if let Err ( err) = api. refresh_devices ( ) {
94
+ error ! ( "Failed to refresh hidapi devices: {}" , err) ;
95
+ }
64
96
for info in api. device_list ( ) {
65
97
match ( info. vendor_id ( ) , info. product_id ( ) , info. interface_number ( ) ) {
66
98
// System76 launch_1
67
99
//TODO: better way to determine this
68
- ( 0x3384 , 0x0001 , 1 ) => match info. open_device ( & api) {
69
- Ok ( device) => match AccessHid :: new ( device, 10 , 100 ) {
70
- Ok ( access) => match unsafe { Ec :: new ( access) } {
71
- Ok ( ec) => {
72
- info ! ( "Adding USB HID EC at {:?}" , info. path( ) ) ;
73
- let id = BoardId ( Uuid :: new_v4 ( ) . as_u128 ( ) ) ;
74
- boards. insert ( id, ec. into_dyn ( ) ) ;
75
- board_ids. push ( id) ;
76
- }
100
+ ( 0x3384 , 0x0001 , 1 ) => {
101
+ // Skip if device already open
102
+ if self . have_device ( & info) {
103
+ continue ;
104
+ }
105
+
106
+ match info. open_device ( & api) {
107
+ Ok ( device) => match AccessHid :: new ( device, 10 , 100 ) {
108
+ Ok ( access) => match unsafe { Ec :: new ( access) } {
109
+ Ok ( ec) => {
110
+ info ! ( "Adding USB HID EC at {:?}" , info. path( ) ) ;
111
+ let id = BoardId ( Uuid :: new_v4 ( ) . as_u128 ( ) ) ;
112
+ self . boards
113
+ . borrow_mut ( )
114
+ . insert ( id, ( ec. into_dyn ( ) , Some ( info. clone ( ) ) ) ) ;
115
+ self . board_ids . borrow_mut ( ) . push ( id) ;
116
+ }
117
+ Err ( err) => {
118
+ error ! (
119
+ "Failed to probe USB HID EC at {:?}: {:?}" ,
120
+ info. path( ) ,
121
+ err
122
+ ) ;
123
+ }
124
+ } ,
77
125
Err ( err) => {
78
126
error ! (
79
- "Failed to probe USB HID EC at {:?}: {:?}" ,
127
+ "Failed to access USB HID EC at {:?}: {:?}" ,
80
128
info. path( ) ,
81
129
err
82
130
) ;
83
131
}
84
132
} ,
85
133
Err ( err) => {
86
- error ! (
87
- "Failed to access USB HID EC at {:?}: {:?}" ,
88
- info. path( ) ,
89
- err
90
- ) ;
134
+ error ! ( "Failed to open USB HID EC at {:?}: {:?}" , info. path( ) , err) ;
91
135
}
92
- } ,
93
- Err ( err) => {
94
- error ! ( "Failed to open USB HID EC at {:?}: {:?}" , info. path( ) , err) ;
95
136
}
96
- } ,
137
+ }
97
138
_ => ( ) ,
98
139
}
99
140
}
100
141
}
101
-
102
- Ok ( Self {
103
- running : Cell :: new ( true ) ,
104
- read : BufReader :: new ( read) ,
105
- write,
106
- boards : RefCell :: new ( boards) ,
107
- board_ids,
108
- } )
109
142
}
110
143
111
144
pub fn run ( mut self ) -> io:: Result < ( ) > {
@@ -132,7 +165,7 @@ impl<R: Read, W: Write> DaemonServer<R, W> {
132
165
fn board ( & self , board : BoardId ) -> Result < RefMut < Ec < Box < dyn Access > > > , String > {
133
166
let mut boards = self . boards . borrow_mut ( ) ;
134
167
if boards. get_mut ( & board) . is_some ( ) {
135
- Ok ( RefMut :: map ( boards, |x| x. get_mut ( & board) . unwrap ( ) ) )
168
+ Ok ( RefMut :: map ( boards, |x| & mut x. get_mut ( & board) . unwrap ( ) . 0 ) )
136
169
} else {
137
170
Err ( "failed to find board" . to_string ( ) )
138
171
}
@@ -141,7 +174,7 @@ impl<R: Read, W: Write> DaemonServer<R, W> {
141
174
142
175
impl < R : Read , W : Write > Daemon for DaemonServer < R , W > {
143
176
fn boards ( & self ) -> Result < Vec < BoardId > , String > {
144
- Ok ( self . board_ids . clone ( ) )
177
+ Ok ( self . board_ids . borrow ( ) . clone ( ) )
145
178
}
146
179
147
180
fn model ( & self , board : BoardId ) -> Result < String , String > {
0 commit comments