Skip to content

Commit 886ace3

Browse files
author
Dilawar Singh
authored
feat: Adds friendly name and manufactorer (#5)
* chore: Adds friendly names * chore: Adds manufactoror on linux * feat: show 'class' on Windows * chore: osx doesn't have a consistent class name * chore: use windows-sys
1 parent 219e28d commit 886ace3

File tree

5 files changed

+90
-11
lines changed

5 files changed

+90
-11
lines changed

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ strict = []
2020
crossbeam = "0.8"
2121
num_enum = "0.7.2"
2222
[target.'cfg(target_os = "windows")'.dependencies]
23-
windows-sys = { version = "0.52.0", features = ["Win32_Devices_DeviceAndDriverInstallation", "Win32_Foundation"] }
23+
windows-sys = { version = "0.52", features = ["Win32_Devices_DeviceAndDriverInstallation", "Win32_Foundation"] }
2424
[target.'cfg(target_os = "linux")'.dependencies]
2525
udev = "0.8"
2626
[target.'cfg(target_os = "macos")'.dependencies]

src/common.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,17 +10,24 @@ pub struct UsbDevice {
1010
pub vendor_id: u16,
1111
/// Product ID
1212
pub product_id: u16,
13+
/// Friendly name.
14+
pub friendly_name: Option<String>,
1315
/// Optional device description
1416
pub description: Option<String>,
1517
/// Optional serial number
1618
pub serial_number: Option<String>,
1719
/// Class (bDeviceBaseClass) of device.
1820
pub base_class: Option<DeviceBaseClass>,
21+
/// Class as string
22+
pub class: Option<String>,
23+
/// Manufacturer
24+
pub manufacturer: Option<String>,
1925
}
2026

2127
/// See <https://www.usb.org/defined-class-codes>
2228
#[repr(u8)]
2329
#[derive(Hash, Eq, Debug, Clone, PartialEq, TryFromPrimitive)]
30+
#[allow(dead_code)]
2431
pub enum DeviceBaseClass {
2532
UseClassCodeFromInterfaceDescriptors = 0x00,
2633
Audio = 0x01,

src/linux.rs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,13 +67,29 @@ pub fn enumerate_platform(vid: Option<u16>, pid: Option<u16>) -> Vec<UsbDevice>
6767
.attribute_value("bDeviceClass")
6868
.and_then(|x| x.to_str()?.parse::<u8>().ok());
6969

70+
let friendly_name = device
71+
.property_value("ID_MODEL_FROM_DATABASE")
72+
.and_then(|s| s.to_str())
73+
.map(|x| x.to_string());
74+
let manufacturer = device
75+
.property_value("ID_VENDOR_FROM_DATABASE")
76+
.and_then(|s| s.to_str())
77+
.map(|x| x.to_string());
78+
let class = device
79+
.property_value("ID_PCI_CLASS_FROM_DATABASE")
80+
.and_then(|s| s.to_str())
81+
.map(|x| x.to_string());
82+
7083
output.push(UsbDevice {
7184
id,
7285
vendor_id,
7386
product_id,
7487
description,
7588
serial_number,
7689
base_class: bclass.and_then(|bc| DeviceBaseClass::try_from(bc).ok()),
90+
class,
91+
friendly_name,
92+
manufacturer,
7793
});
7894

7995
Ok(())

src/macos.rs

Lines changed: 25 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,7 @@ use crate::common::*;
22
use core_foundation::{base::*, dictionary::*, number::*, string::*};
33
use io_kit_sys::{types::*, usb::lib::*, *};
44
use mach::kern_return::*;
5-
use std::{error::Error, mem::MaybeUninit};
6-
use std::convert::TryFrom;
5+
use std::{convert::TryFrom, error::Error, mem::MaybeUninit};
76

87
pub fn enumerate_platform(vid: Option<u16>, pid: Option<u16>) -> Vec<UsbDevice> {
98
let mut output = Vec::new();
@@ -91,20 +90,38 @@ pub fn enumerate_platform(vid: Option<u16>, pid: Option<u16>) -> Vec<UsbDevice>
9190
.map(|s| s.to_string());
9291

9392
let key = CFString::from_static_string("bDeviceClass");
94-
let base_class = properties
93+
let base_class = DeviceBaseClass::try_from(
94+
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+
)
101+
.ok();
102+
103+
let key = CFString::from_static_string("USB Product Name");
104+
let friendly_name = properties
95105
.find(&key)
96-
.and_then(|value_ref| value_ref.downcast::<CFNumber>())
97-
.ok_or(ParseError)?
98-
.to_i32()
99-
.ok_or(ParseError)? as u8;
106+
.and_then(|value_ref| value_ref.downcast::<CFString>())
107+
.map(|s| s.to_string());
108+
109+
let key = CFString::from_static_string("USB Vendor Name");
110+
let manufacturer = properties
111+
.find(&key)
112+
.and_then(|value_ref| value_ref.downcast::<CFString>())
113+
.map(|s| s.to_string());
100114

101115
output.push(UsbDevice {
102116
id: id.to_string(),
103117
vendor_id,
104118
product_id,
105119
description,
106120
serial_number,
107-
base_class: DeviceBaseClass::try_from(base_class).ok(),
121+
base_class,
122+
class: None,
123+
friendly_name,
124+
manufacturer,
108125
});
109126

110127
Ok(())

src/windows.rs

Lines changed: 41 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,13 @@ use windows_sys::{
99
Win32::Devices::DeviceAndDriverInstallation::{
1010
SetupDiDestroyDeviceInfoList, SetupDiEnumDeviceInfo, SetupDiGetClassDevsW,
1111
SetupDiGetDeviceInstanceIdW, SetupDiGetDeviceRegistryPropertyW, DIGCF_ALLCLASSES,
12-
DIGCF_PRESENT, SPDRP_CLASS, SPDRP_DEVICEDESC, SPDRP_HARDWAREID, SP_DEVINFO_DATA,
12+
DIGCF_PRESENT, SPDRP_CLASS, SPDRP_DEVICEDESC, SPDRP_FRIENDLYNAME, SPDRP_HARDWAREID,
13+
SPDRP_MFG, SP_DEVINFO_DATA,
1314
},
1415
};
1516

1617
pub fn enumerate_platform(vid: Option<u16>, pid: Option<u16>) -> Vec<UsbDevice> {
1718
let mut output: Vec<UsbDevice> = Vec::new();
18-
// let usb: Vec<u16> = OsStr::new("USB\0").encode_wide().collect();
1919
let usb = w!("USB\0");
2020
let dev_info =
2121
unsafe { SetupDiGetClassDevsW(null(), usb, -1, DIGCF_ALLCLASSES | DIGCF_PRESENT) };
@@ -77,6 +77,42 @@ pub fn enumerate_platform(vid: Option<u16>, pid: Option<u16>) -> Vec<UsbDevice>
7777
class = Some(string_from_buf_u8(buf));
7878
}
7979

80+
// manufactor
81+
buf = vec![0; 1000];
82+
let mut manufacturer = None;
83+
if unsafe {
84+
SetupDiGetDeviceRegistryPropertyW(
85+
dev_info,
86+
&mut dev_info_data,
87+
SPDRP_MFG,
88+
null_mut(),
89+
buf.as_mut_ptr(),
90+
buf.len() as u32,
91+
null_mut(),
92+
)
93+
} > 0
94+
{
95+
manufacturer = Some(string_from_buf_u8(buf));
96+
}
97+
98+
// friendly name
99+
buf = vec![0; 1000];
100+
let mut friendly_name = None;
101+
if unsafe {
102+
SetupDiGetDeviceRegistryPropertyW(
103+
dev_info,
104+
&mut dev_info_data,
105+
SPDRP_FRIENDLYNAME,
106+
null_mut(),
107+
buf.as_mut_ptr(),
108+
buf.len() as u32,
109+
null_mut(),
110+
)
111+
} > 0
112+
{
113+
friendly_name = Some(string_from_buf_u8(buf));
114+
}
115+
80116
buf = vec![0; 1000];
81117

82118
if unsafe {
@@ -111,8 +147,11 @@ pub fn enumerate_platform(vid: Option<u16>, pid: Option<u16>) -> Vec<UsbDevice>
111147
id,
112148
vendor_id,
113149
product_id,
150+
friendly_name,
151+
manufacturer,
114152
description: Some(description),
115153
serial_number,
154+
class: class.clone(),
116155
base_class: class.map(|cls| cls.into()),
117156
});
118157
}

0 commit comments

Comments
 (0)