tegra_rcm/hotplug/
unix.rs1use std::sync::mpsc::Sender;
2
3use log::{error, info};
4use rusb::{has_hotplug, Context, Device, Hotplug, HotplugBuilder, UsbContext};
5
6use super::{HotplugError, HotplugHandler};
7use crate::device::{SwitchDevice, RCM_PID, RCM_VID};
8use crate::switch::Switch;
9use crate::SwitchError;
10
11impl Hotplug<Context> for HotplugHandler {
12 fn device_arrived(&mut self, device: Device<Context>) {
14 let device = SwitchDevice::new(device);
15 let switch = Switch::new(device);
16
17 if let Err(e) = self.sender.send(Ok(switch)) {
18 error!("device arrive event {e}");
19 }
20
21 info!("rcm device arrived");
22
23 if let Some(callback) = &self.callback {
24 callback();
25 }
26 }
27
28 fn device_left(&mut self, _device: Device<Context>) {
30 if let Err(e) = self.sender.send(Err(crate::SwitchError::SwitchNotFound)) {
31 error!("device left event {e}");
32 }
33
34 info!("rcm device left");
35
36 if let Some(callback) = &self.callback {
37 callback();
38 }
39 }
40}
41
42pub fn create_hotplug(
44 tx: Sender<Result<Switch, SwitchError>>,
45 callback: Option<impl Fn() + Send + Sync + 'static>,
46) -> Result<(), HotplugError> {
47 cfg_if::cfg_if! {
48 if #[cfg(all(feature = "notify", target_os = "linux"))] {
49 super::notify::watcher_hotplug(tx, callback)
50 .map_err(|_| HotplugError::Watcher)
51 } else {
52 libusb_hotplug(tx, callback)
53 }
54 }
55}
56
57pub fn libusb_hotplug(
58 tx: Sender<Result<Switch, SwitchError>>,
59 callback: Option<impl Fn() + Send + Sync + 'static>,
60) -> Result<(), HotplugError> {
61 if !has_hotplug() {
62 return Err(HotplugError::NotSupported);
63 }
64
65 let mut callback = callback;
66 let context = Context::new().unwrap();
67
68 let hotplug_handler = match callback.take() {
69 Some(callback) => HotplugHandler {
70 sender: tx,
71 callback: Some(Box::new(callback)),
72 },
73 None => HotplugHandler {
74 sender: tx,
75 callback: None,
76 },
77 };
78
79 let _hotplug = HotplugBuilder::new()
80 .vendor_id(RCM_VID)
81 .product_id(RCM_PID)
82 .enumerate(true)
83 .register(context.clone(), Box::new(hotplug_handler))
84 .expect("We where able to successfully wrap the context");
85
86 loop {
87 context
89 .handle_events(None)
90 .expect("We are able to handle USB hotplug events");
91 }
92}