aboutsummaryrefslogtreecommitdiff
path: root/src/hid.rs
diff options
context:
space:
mode:
authorjamie <git@skilet.ro>2026-08-29 22:15:55 +0100
committerjamie <git@skilet.ro>2026-08-29 22:15:55 +0100
commit3dd652c1d70da608c77d1ded9e6d44774fc10ebc (patch)
treecdd5d0ed985494f3ac66f19d4fedd8fd039b9357 /src/hid.rs
parentc1110ac81f87ba374696e419f3807f48a3a06d6d (diff)
refactor: dedupe helpers, name protocol constants, testable daemon args
Diffstat (limited to 'src/hid.rs')
-rw-r--r--src/hid.rs56
1 files changed, 15 insertions, 41 deletions
diff --git a/src/hid.rs b/src/hid.rs
index 6b09e98..72f67fa 100644
--- a/src/hid.rs
+++ b/src/hid.rs
@@ -63,40 +63,7 @@ pub struct HidDevice {
/// Enumerate hidraw devices matching `vid`/`pid` by reading the sysfs `uevent`
/// of each `/sys/class/hidraw/hidrawN`.
pub fn find_devices(vid: u16, pid: u16) -> io::Result<Vec<HidDevice>> {
- let mut out = Vec::new();
- for entry in fs::read_dir(HIDRAW_SYSFS)? {
- let entry = entry?;
- let name = entry.file_name();
- let Some(name) = name.to_str() else {
- continue;
- };
- if !name.starts_with("hidraw") {
- continue;
- }
- let Some(uevent) = read_sysfs(&entry.path().join("device/uevent")) else {
- continue;
- };
- let Some((bus, v, p)) = parse_hid_id(&uevent) else {
- continue;
- };
- if bus != 3 {
- continue; // USB only
- }
- if v == vid && p == pid {
- let dev_name = uevent
- .lines()
- .find(|l| l.starts_with("HID_NAME="))
- .map(|l| l.trim_start_matches("HID_NAME=").to_string())
- .unwrap_or_default();
- out.push(HidDevice {
- vid: v,
- pid: p,
- name: dev_name,
- devnode: PathBuf::from("/dev").join(name),
- });
- }
- }
- Ok(out)
+ find_with(|v, p| v == vid && p == pid)
}
/// Find the first (only) MMX 150 dongle HID device.
@@ -108,6 +75,12 @@ pub fn find_mmx150() -> io::Result<Option<HidDevice>> {
/// Enumerate all hidraw devices belonging to a vendor.
pub fn find_devices_by_vendor(vid: u16) -> io::Result<Vec<HidDevice>> {
+ find_with(|v, _| v == vid)
+}
+
+/// Collect USB hidraw devices whose `HID_ID` vendor/product pair matches
+/// `keep`. Returns one [`HidDevice`] per match.
+fn find_with(mut keep: impl FnMut(u16, u16) -> bool) -> io::Result<Vec<HidDevice>> {
let mut out = Vec::new();
for entry in fs::read_dir(HIDRAW_SYSFS)? {
let entry = entry?;
@@ -124,8 +97,8 @@ pub fn find_devices_by_vendor(vid: u16) -> io::Result<Vec<HidDevice>> {
let Some((bus, v, p)) = parse_hid_id(&uevent) else {
continue;
};
- if bus != 3 || v != vid {
- continue;
+ if bus != 3 || !keep(v, p) {
+ continue; // USB only, filtered by caller
}
let dev_name = uevent
.lines()
@@ -160,11 +133,6 @@ impl Hidraw {
})
}
- /// Returns the underlying raw file descriptor.
- pub fn as_raw_fd(&self) -> std::os::fd::RawFd {
- self.file.as_raw_fd()
- }
-
/// `HIDIOCGFEATURE`: fetch `report_id` into `data` (report length + 1
/// bytes including the report-id byte). Returns bytes received.
pub fn get_feature(&self, report_id: u8, len: usize) -> io::Result<Vec<u8>> {
@@ -266,6 +234,12 @@ impl Hidraw {
}
}
+impl std::os::fd::AsRawFd for Hidraw {
+ fn as_raw_fd(&self) -> std::os::fd::RawFd {
+ self.file.as_raw_fd()
+ }
+}
+
fn read_sysfs(path: &Path) -> Option<String> {
fs::read_to_string(path).ok()
}