hardware 0.0.9

A no_std bare-metal hardware abstraction layer — all port I/O, memory and swap allocations are guarded at runtime. Do not consider this dependency stable before x.1.x
Documentation
pub const DESC_DEVICE: u8 = 0x01;
pub const DESC_CONFIGURATION: u8 = 0x02;
pub const DESC_STRING: u8 = 0x03;
pub const DESC_INTERFACE: u8 = 0x04;
pub const DESC_ENDPOINT: u8 = 0x05;
pub const DESC_HID: u8 = 0x21;
pub const DESC_HUB: u8 = 0x29;
pub const DESC_SS_HUB: u8 = 0x2A;
pub const DESC_BOS: u8 = 0x0F;

#[derive(Clone, Copy)]
pub struct DeviceDescriptor {
    pub usb_version: u16,
    pub device_class: u8,
    pub device_subclass: u8,
    pub device_protocol: u8,
    pub max_packet_size0: u8,
    pub vendor_id: u16,
    pub product_id: u16,
    pub device_version: u16,
    pub num_configurations: u8,
}

#[derive(Clone, Copy)]
pub struct ConfigDescriptor {
    pub total_length: u16,
    pub num_interfaces: u8,
    pub config_value: u8,
    pub attributes: u8,
    pub max_power: u8,
}

#[derive(Clone, Copy)]
pub struct InterfaceDescriptor {
    pub interface_number: u8,
    pub alternate_setting: u8,
    pub num_endpoints: u8,
    pub interface_class: u8,
    pub interface_subclass: u8,
    pub interface_protocol: u8,
}

impl DeviceDescriptor {
    pub fn from_bytes(data: &[u8]) -> Option<Self> {
        if data.len() < 18 || data[1] != DESC_DEVICE {
            return None;
        }
        Some(DeviceDescriptor {
            usb_version: u16::from_le_bytes([data[2], data[3]]),
            device_class: data[4],
            device_subclass: data[5],
            device_protocol: data[6],
            max_packet_size0: data[7],
            vendor_id: u16::from_le_bytes([data[8], data[9]]),
            product_id: u16::from_le_bytes([data[10], data[11]]),
            device_version: u16::from_le_bytes([data[12], data[13]]),
            num_configurations: data[17],
        })
    }

    pub fn is_hub(&self) -> bool {
        self.device_class == 0x09
    }

    pub fn is_hid(&self) -> bool {
        self.device_class == 0x03
    }

    pub fn is_mass_storage(&self) -> bool {
        self.device_class == 0x08
    }

    pub fn is_vendor_specific(&self) -> bool {
        self.device_class == 0xFF
    }
}

impl ConfigDescriptor {
    pub fn from_bytes(data: &[u8]) -> Option<Self> {
        if data.len() < 9 || data[1] != DESC_CONFIGURATION {
            return None;
        }
        Some(ConfigDescriptor {
            total_length: u16::from_le_bytes([data[2], data[3]]),
            num_interfaces: data[4],
            config_value: data[5],
            attributes: data[7],
            max_power: data[8],
        })
    }

    pub fn self_powered(&self) -> bool {
        self.attributes & (1 << 6) != 0
    }

    pub fn remote_wakeup(&self) -> bool {
        self.attributes & (1 << 5) != 0
    }

    pub fn max_power_ma(&self) -> u16 {
        self.max_power as u16 * 2
    }
}

impl InterfaceDescriptor {
    pub fn from_bytes(data: &[u8]) -> Option<Self> {
        if data.len() < 9 || data[1] != DESC_INTERFACE {
            return None;
        }
        Some(InterfaceDescriptor {
            interface_number: data[2],
            alternate_setting: data[3],
            num_endpoints: data[4],
            interface_class: data[5],
            interface_subclass: data[6],
            interface_protocol: data[7],
        })
    }
}