sysfs_serde/
usb_attributes.rs

1use crate::uevent::UEvent;
2#[cfg(feature = "serde")]
3use serde::Serialize;
4use std::collections::HashMap;
5use std::str::FromStr;
6
7/// De-serialized /sys/class/bus/usb to a Rust structure.
8/// Note unknown fields are stored in raw format in the attributes: HashMap<String, String>
9#[cfg_attr(feature = "serde", derive(Serialize))]
10#[derive(Default)]
11pub struct UsbAttributes {
12    pub num_endpoints: u8,
13    pub num_configurations: u8,
14    pub num_interfaces: u8,
15    pub interface_class: u8,
16    pub interface_number: u8,
17    pub interface_protocol: u8,
18    pub alternate_setting: u8,
19    pub interface_subclass: u8,
20    pub max_packet_size0: u16,
21    pub supports_autosuspend: u8,
22    pub authorized: u8,
23    #[cfg_attr(feature = "serde", serde(skip_serializing_if = "String::is_empty"))]
24    pub modalias: String,
25    #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
26    pub id_product: Option<String>,
27    #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
28    pub id_vendor: Option<String>,
29    pub bus_num: u8,
30    pub dev_num: u8,
31    #[cfg_attr(feature = "serde", serde(skip_serializing_if = "String::is_empty"))]
32    pub product: String,
33    #[cfg_attr(feature = "serde", serde(skip_serializing_if = "String::is_empty"))]
34    pub manufacturer: String,
35    #[cfg_attr(feature = "serde", serde(skip_serializing_if = "String::is_empty"))]
36    pub serial: String,
37    #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
38    pub uevent: Option<UEvent>,
39    #[cfg_attr(feature = "serde", serde(skip))]
40    pub descriptors: Vec<u8>,
41    #[cfg_attr(
42        feature = "serde",
43        serde(flatten, skip_serializing_if = "HashMap::is_empty")
44    )]
45    pub attributes: HashMap<String, String>,
46}
47
48impl UsbAttributes {
49    pub(crate) fn add(&mut self, key: &str, value: Vec<u8>) -> Result<(), std::num::ParseIntError> {
50        if key == "descriptors" {
51            // Raw descriptors from the device is stored in a Vec.
52            self.descriptors = value;
53            return Ok(());
54        }
55
56        let value = if let Ok(value) = String::from_utf8(value) {
57            value.trim().to_string()
58        } else {
59            log::warn!("Could not decode {} as UTF8 string.", key);
60            return Ok(());
61        };
62        match &key[0..] {
63            "busnum" => self.bus_num = value.parse()?,
64            "devnum" => self.dev_num = value.parse()?,
65            "supports_autosuspend" => self.supports_autosuspend = value.parse()?,
66            "authorized" => self.authorized = value.parse()?,
67            "uevent" => self.uevent = UEvent::from_str(&value).ok(),
68            "bNumEndpoints" => self.num_endpoints = value.parse()?,
69            "bNumInterfaces" => self.num_interfaces = value.parse()?,
70            "bNumConfigurations" => self.num_configurations = value.parse()?,
71            "bInterfaceNumber" => self.interface_number = u8::from_str_radix(&value, 16)?,
72            "bInterfaceProtocol" => self.interface_protocol = u8::from_str_radix(&value, 16)?,
73            "bInterfaceClass" => self.interface_class = u8::from_str_radix(&value, 16)?,
74            "bInterfaceSubClass" => self.interface_subclass = u8::from_str_radix(&value, 16)?,
75            "bAlternateSetting" => self.alternate_setting = u8::from_str_radix(&value, 16)?,
76            "bMaxPacketSize0" => self.max_packet_size0 = value.parse()?,
77            "manufacturer" => self.manufacturer = value,
78            "product" => self.product = value,
79            "serial" => self.serial = value,
80            _ => {
81                self.attributes.insert(key.into(), value);
82            }
83        }
84
85        Ok(())
86    }
87}