use std::sync::Arc;
use hidpp::{
channel::HidppChannel,
receiver::{self, Receiver},
};
pub use openlogi_core::hid::route::{
BOLT_PIDS, DIRECT_DEVICE_INDEX, DeviceRoute, LIGHTSPEED_PIDS, UNIFYING_PIDS, is_receiver_pid,
receiver_display_name, speaks_unifying_protocol,
};
use crate::transport::{enumerate_hidpp_devices, open_hidpp_channel};
pub(crate) async fn open_route_channel(
route: &DeviceRoute,
) -> Result<Option<Arc<HidppChannel>>, async_hid::HidError> {
if matches!(route, DeviceRoute::RawHid { .. }) {
return Ok(None);
}
let candidates = enumerate_hidpp_devices().await?;
for dev in candidates {
if let DeviceRoute::Direct {
vendor_id,
product_id,
} = route
&& (dev.vendor_id != *vendor_id || dev.product_id != *product_id)
{
continue;
}
let Some((_, channel)) = open_hidpp_channel(dev).await? else {
continue;
};
match route {
DeviceRoute::Bolt { receiver_uid, .. } => {
let Some(Receiver::Bolt(bolt)) = receiver::detect(Arc::clone(&channel)) else {
continue;
};
if let Ok(uid) = bolt.get_unique_id().await
&& uid.eq_ignore_ascii_case(receiver_uid)
{
return Ok(Some(channel));
}
}
DeviceRoute::Unifying { receiver_uid, .. } => {
let Some(Receiver::Unifying(unifying)) = receiver::detect(Arc::clone(&channel))
else {
continue;
};
if let Ok(uid) = unifying.get_unique_id().await
&& uid.eq_ignore_ascii_case(receiver_uid)
{
return Ok(Some(channel));
}
}
DeviceRoute::Direct { .. } => return Ok(Some(channel)),
DeviceRoute::RawHid { .. } => unreachable!("raw HID route entered HID++ channel path"),
}
}
Ok(None)
}