use libc::c_int;
use libusb1_sys::constants::*;
#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash)]
pub enum Speed {
Unknown,
Low,
Full,
High,
Super,
}
#[doc(hidden)]
pub(crate) fn speed_from_libusb(n: c_int) -> Speed {
match n {
LIBUSB_SPEED_SUPER => Speed::Super,
LIBUSB_SPEED_HIGH => Speed::High,
LIBUSB_SPEED_FULL => Speed::Full,
LIBUSB_SPEED_LOW => Speed::Low,
LIBUSB_SPEED_UNKNOWN | _ => Speed::Unknown,
}
}
#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash)]
pub enum Direction {
In,
Out,
}
#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash)]
pub enum TransferType {
Control,
Isochronous,
Bulk,
Interrupt,
}
#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash)]
pub enum SyncType {
NoSync,
Asynchronous,
Adaptive,
Synchronous,
}
#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash)]
pub enum UsageType {
Data,
Feedback,
FeedbackData,
Reserved,
}
#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash)]
pub enum RequestType {
Standard,
Class,
Vendor,
Reserved,
}
#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash)]
pub enum Recipient {
Device,
Interface,
Endpoint,
Other,
}
#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash)]
pub struct Version(pub u8, pub u8, pub u8);
impl Version {
pub fn from_bcd(mut raw: u16) -> Self {
let sub_minor: u8 = (raw & 0x000F) as u8;
raw >>= 4;
let minor: u8 = (raw & 0x000F) as u8;
raw >>= 4;
let mut major: u8 = (raw & 0x000F) as u8;
raw >>= 4;
major += (10 * raw) as u8;
Version(major, minor, sub_minor)
}
pub fn major(self) -> u8 {
let Version(major, _, _) = self;
major
}
pub fn minor(self) -> u8 {
let Version(_, minor, _) = self;
minor
}
pub fn sub_minor(self) -> u8 {
let Version(_, _, sub_minor) = self;
sub_minor
}
}
pub fn request_type(direction: Direction, request_type: RequestType, recipient: Recipient) -> u8 {
let mut value: u8 = match direction {
Direction::Out => LIBUSB_ENDPOINT_OUT,
Direction::In => LIBUSB_ENDPOINT_IN,
};
value |= match request_type {
RequestType::Standard => LIBUSB_REQUEST_TYPE_STANDARD,
RequestType::Class => LIBUSB_REQUEST_TYPE_CLASS,
RequestType::Vendor => LIBUSB_REQUEST_TYPE_VENDOR,
RequestType::Reserved => LIBUSB_REQUEST_TYPE_RESERVED,
};
value |= match recipient {
Recipient::Device => LIBUSB_RECIPIENT_DEVICE,
Recipient::Interface => LIBUSB_RECIPIENT_INTERFACE,
Recipient::Endpoint => LIBUSB_RECIPIENT_ENDPOINT,
Recipient::Other => LIBUSB_RECIPIENT_OTHER,
};
value
}
#[cfg(test)]
mod test {
use super::*;
#[test]
fn version_returns_major_version() {
assert_eq!(1, Version(1, 0, 0).major());
assert_eq!(2, Version(2, 0, 0).major());
}
#[test]
fn version_returns_minor_version() {
assert_eq!(1, Version(0, 1, 0).minor());
assert_eq!(2, Version(0, 2, 0).minor());
}
#[test]
fn version_returns_sub_minor_version() {
assert_eq!(1, Version(0, 0, 1).sub_minor());
assert_eq!(2, Version(0, 0, 2).sub_minor());
}
#[test]
fn version_parses_major_version() {
assert_eq!(3, Version::from_bcd(0x0300).major());
}
#[test]
fn version_parses_long_major_version() {
assert_eq!(12, Version::from_bcd(0x1200).major());
}
#[test]
fn version_parses_minor_version() {
assert_eq!(1, Version::from_bcd(0x0010).minor());
assert_eq!(2, Version::from_bcd(0x0020).minor());
}
#[test]
fn version_parses_sub_minor_version() {
assert_eq!(1, Version::from_bcd(0x0001).sub_minor());
assert_eq!(2, Version::from_bcd(0x0002).sub_minor());
}
#[test]
fn version_parses_full_version() {
assert_eq!(Version(12, 3, 4), Version::from_bcd(0x1234));
}
#[test]
fn request_type_builds_value_for_out_direction() {
assert_eq!(
request_type(Direction::Out, RequestType::Standard, Recipient::Device) & 0x80,
0x00
);
}
#[test]
fn request_type_builds_value_for_in_direction() {
assert_eq!(
request_type(Direction::In, RequestType::Standard, Recipient::Device) & 0x80,
0x80
);
}
#[test]
fn request_type_builds_value_for_standard_request() {
assert_eq!(
request_type(Direction::Out, RequestType::Standard, Recipient::Device) & 0x60,
0x00
);
}
#[test]
fn request_type_builds_value_for_class_request() {
assert_eq!(
request_type(Direction::Out, RequestType::Class, Recipient::Device) & 0x60,
0x20
);
}
#[test]
fn request_type_builds_value_for_vendor_request() {
assert_eq!(
request_type(Direction::Out, RequestType::Vendor, Recipient::Device) & 0x60,
0x40
);
}
#[test]
fn request_type_builds_value_for_reserved_request() {
assert_eq!(
request_type(Direction::Out, RequestType::Reserved, Recipient::Device) & 0x60,
0x60
);
}
#[test]
fn request_type_builds_value_for_device_recipient() {
assert_eq!(
request_type(Direction::Out, RequestType::Standard, Recipient::Device) & 0x0F,
0x00
);
}
#[test]
fn request_type_builds_value_for_interface_recipient() {
assert_eq!(
request_type(Direction::Out, RequestType::Standard, Recipient::Interface) & 0x0F,
0x01
);
}
#[test]
fn request_type_builds_value_for_endpoint_recipient() {
assert_eq!(
request_type(Direction::Out, RequestType::Standard, Recipient::Endpoint) & 0x0F,
0x02
);
}
#[test]
fn request_type_builds_value_for_other_recipient() {
assert_eq!(
request_type(Direction::Out, RequestType::Standard, Recipient::Other) & 0x0F,
0x03
);
}
}