Skip to content

Commit 6fdc1ca

Browse files
author
Dilawar Singh
authored
feat: Add device class (#4)
* feat: Adds defined codes * chore: baseClass on Linux as well * chore: class -> baseClass
1 parent 54db0d8 commit 6fdc1ca

File tree

5 files changed

+66
-3
lines changed

5 files changed

+66
-3
lines changed

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ strict = []
1818

1919
[dependencies]
2020
crossbeam = "0.8"
21+
num_enum = "0.7.2"
2122
[target.'cfg(target_os = "windows")'.dependencies]
2223
windows-sys = { version = "0.52.0", features = ["Win32_Devices_DeviceAndDriverInstallation", "Win32_Foundation"] }
2324
[target.'cfg(target_os = "linux")'.dependencies]

src/common.rs

Lines changed: 48 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
use num_enum::TryFromPrimitive;
12
use std::error::Error;
23

34
/// Discovered USB device
@@ -13,8 +14,53 @@ pub struct UsbDevice {
1314
pub description: Option<String>,
1415
/// Optional serial number
1516
pub serial_number: Option<String>,
16-
/// Class of device.
17-
pub class: Option<String>,
17+
/// Class (bDeviceBaseClass) of device.
18+
pub base_class: Option<DeviceBaseClass>,
19+
}
20+
21+
/// See <https://www.usb.org/defined-class-codes>
22+
#[repr(u8)]
23+
#[derive(Hash, Eq, Debug, Clone, PartialEq, TryFromPrimitive)]
24+
pub enum DeviceBaseClass {
25+
UseClassCodeFromInterfaceDescriptors = 0x00,
26+
Audio = 0x01,
27+
Communication = 0x02,
28+
HumanInterfaceDevice = 0x03,
29+
Physical = 0x05,
30+
Image = 0x06,
31+
Printer = 0x07,
32+
MassStorage = 0x08,
33+
Hub = 0x09,
34+
CDCData = 0x0A,
35+
SmartCard = 0x0B,
36+
ContentSecurity = 0x0D,
37+
Video = 0x0E,
38+
PersonalHealthCare = 0x0F,
39+
AudioVideo = 0x10,
40+
Billboard = 0x11,
41+
UsbTypeCBridge = 0x12,
42+
UsbBulkDisplay = 0x13,
43+
MctpOverUsb = 0x14,
44+
I3C = 0x3C,
45+
Diagnostic = 0xDC,
46+
WirelessController = 0xE0,
47+
Miscellaneous = 0xEF,
48+
ApplicationSpecific = 0xFE,
49+
VendorSpecific = 0xFF,
50+
}
51+
52+
impl From<String> for DeviceBaseClass {
53+
fn from(v: String) -> Self {
54+
match v.to_lowercase().as_ref() {
55+
"usb" => Self::MassStorage,
56+
"bluetooth" => Self::Communication,
57+
"hidclass" => Self::HumanInterfaceDevice,
58+
"camera" => Self::Video,
59+
"biometric" => Self::ContentSecurity,
60+
"net" => Self::WirelessController,
61+
_ => Self::UseClassCodeFromInterfaceDescriptors,
62+
}
63+
}
1864
}
1965

2066
#[derive(Copy, Clone, Debug)]

src/linux.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
use crate::common::*;
2+
use std::convert::TryFrom;
23

34
use std::error::Error;
45
use udev::Enumerator;
@@ -62,12 +63,17 @@ pub fn enumerate_platform(vid: Option<u16>, pid: Option<u16>) -> Vec<UsbDevice>
6263
.and_then(|s| s.to_str())
6364
.map(|s| s.to_string());
6465

66+
let bclass = device
67+
.attribute_value("bDeviceClass")
68+
.and_then(|x| x.to_str()?.parse::<u8>().ok());
69+
6570
output.push(UsbDevice {
6671
id,
6772
vendor_id,
6873
product_id,
6974
description,
7075
serial_number,
76+
base_class: bclass.and_then(|bc| DeviceBaseClass::try_from(bc).ok()),
7177
});
7278

7379
Ok(())

src/macos.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ use core_foundation::{base::*, dictionary::*, number::*, string::*};
33
use io_kit_sys::{types::*, usb::lib::*, *};
44
use mach::kern_return::*;
55
use std::{error::Error, mem::MaybeUninit};
6+
use std::convert::TryFrom;
67

78
pub fn enumerate_platform(vid: Option<u16>, pid: Option<u16>) -> Vec<UsbDevice> {
89
let mut output = Vec::new();
@@ -89,12 +90,21 @@ pub fn enumerate_platform(vid: Option<u16>, pid: Option<u16>) -> Vec<UsbDevice>
8990
.and_then(|value_ref| value_ref.downcast::<CFString>())
9091
.map(|s| s.to_string());
9192

93+
let key = CFString::from_static_string("bDeviceClass");
94+
let base_class = properties
95+
.find(&key)
96+
.and_then(|value_ref| value_ref.downcast::<CFNumber>())
97+
.ok_or(ParseError)?
98+
.to_i32()
99+
.ok_or(ParseError)? as u8;
100+
92101
output.push(UsbDevice {
93102
id: id.to_string(),
94103
vendor_id,
95104
product_id,
96105
description,
97106
serial_number,
107+
base_class: DeviceBaseClass::try_from(base_class).ok(),
98108
});
99109

100110
Ok(())

src/windows.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,7 @@ pub fn enumerate_platform(vid: Option<u16>, pid: Option<u16>) -> Vec<UsbDevice>
113113
product_id,
114114
description: Some(description),
115115
serial_number,
116-
class,
116+
base_class: class.map(|cls| cls.into()),
117117
});
118118
}
119119
}

0 commit comments

Comments
 (0)