Skip to content

Commit 6cfb29b

Browse files
committed
improv: Refactoring to help with implementing hotplug support
1 parent d208098 commit 6cfb29b

File tree

1 file changed

+67
-34
lines changed

1 file changed

+67
-34
lines changed

backend/src/daemon/server.rs

Lines changed: 67 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
#[cfg(target_os = "linux")]
22
use ectool::AccessLpcLinux;
33
use ectool::{Access, AccessHid, Ec};
4-
use hidapi::HidApi;
4+
use hidapi::{DeviceInfo, HidApi};
55
use std::{
66
cell::{Cell, RefCell, RefMut},
77
collections::HashMap,
@@ -15,11 +15,12 @@ use super::{err_str, BoardId, Daemon, DaemonCommand};
1515
use crate::Matrix;
1616

1717
pub struct DaemonServer<R: Read, W: Write> {
18+
hidapi: RefCell<Option<HidApi>>,
1819
running: Cell<bool>,
1920
read: BufReader<R>,
2021
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>>,
2324
}
2425

2526
impl DaemonServer<io::Stdin, io::Stdout> {
@@ -39,7 +40,7 @@ impl<R: Read, W: Write> DaemonServer<R, W> {
3940
Ok(ec) => {
4041
info!("Adding LPC EC");
4142
let id = BoardId(Uuid::new_v4().as_u128());
42-
boards.insert(id, ec.into_dyn());
43+
boards.insert(id, (ec.into_dyn(), None));
4344
board_ids.push(id);
4445
}
4546
Err(err) => {
@@ -60,52 +61,84 @@ impl<R: Read, W: Write> DaemonServer<R, W> {
6061
}
6162
};
6263

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+
}
6496
for info in api.device_list() {
6597
match (info.vendor_id(), info.product_id(), info.interface_number()) {
6698
// System76 launch_1
6799
//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+
},
77125
Err(err) => {
78126
error!(
79-
"Failed to probe USB HID EC at {:?}: {:?}",
127+
"Failed to access USB HID EC at {:?}: {:?}",
80128
info.path(),
81129
err
82130
);
83131
}
84132
},
85133
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);
91135
}
92-
},
93-
Err(err) => {
94-
error!("Failed to open USB HID EC at {:?}: {:?}", info.path(), err);
95136
}
96-
},
137+
}
97138
_ => (),
98139
}
99140
}
100141
}
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-
})
109142
}
110143

111144
pub fn run(mut self) -> io::Result<()> {
@@ -132,7 +165,7 @@ impl<R: Read, W: Write> DaemonServer<R, W> {
132165
fn board(&self, board: BoardId) -> Result<RefMut<Ec<Box<dyn Access>>>, String> {
133166
let mut boards = self.boards.borrow_mut();
134167
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))
136169
} else {
137170
Err("failed to find board".to_string())
138171
}
@@ -141,7 +174,7 @@ impl<R: Read, W: Write> DaemonServer<R, W> {
141174

142175
impl<R: Read, W: Write> Daemon for DaemonServer<R, W> {
143176
fn boards(&self) -> Result<Vec<BoardId>, String> {
144-
Ok(self.board_ids.clone())
177+
Ok(self.board_ids.borrow().clone())
145178
}
146179

147180
fn model(&self, board: BoardId) -> Result<String, String> {

0 commit comments

Comments
 (0)