| use libc::c_int; | 
 | use libusb1_sys::constants::*; | 
 |  | 
 | #[cfg(feature = "serde")] | 
 | use serde::{Deserialize, Serialize}; | 
 |  | 
 | /// Device speeds. Indicates the speed at which a device is operating. | 
 | /// - [libusb_supported_speed](http://libusb.sourceforge.net/api-1.0/group__libusb__dev.html#ga1454797ecc0de4d084c1619c420014f6) | 
 | /// - [USB release versions](https://en.wikipedia.org/wiki/USB#Release_versions) | 
 | #[derive(Debug, PartialEq, Eq, Clone, Copy, Hash)] | 
 | #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] | 
 | #[non_exhaustive] | 
 | pub enum Speed { | 
 |     /// The operating system doesn't know the device speed. | 
 |     Unknown, | 
 |  | 
 |     /// The device is operating at low speed (1.5 Mbps). | 
 |     Low, | 
 |  | 
 |     /// The device is operating at full speed (12 Mbps). | 
 |     Full, | 
 |  | 
 |     /// The device is operating at high speed (480 Mbps). | 
 |     High, | 
 |  | 
 |     /// The device is operating at super speed (5 Gbps). | 
 |     Super, | 
 |  | 
 |     /// The device is operating at super speed (10 Gbps). | 
 |     SuperPlus, | 
 | } | 
 |  | 
 | #[doc(hidden)] | 
 | pub(crate) fn speed_from_libusb(n: c_int) -> Speed { | 
 |     match n { | 
 |         LIBUSB_SPEED_SUPER_PLUS => Speed::SuperPlus, | 
 |         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, | 
 |     } | 
 | } | 
 |  | 
 | /// Transfer and endpoint directions. | 
 | #[derive(Debug, PartialEq, Eq, Clone, Copy, Hash)] | 
 | #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] | 
 | pub enum Direction { | 
 |     /// Direction for read (device to host) transfers. | 
 |     In, | 
 |  | 
 |     /// Direction for write (host to device) transfers. | 
 |     Out, | 
 | } | 
 |  | 
 | /// An endpoint's transfer type. | 
 | #[derive(Debug, PartialEq, Eq, Clone, Copy, Hash)] | 
 | #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] | 
 | pub enum TransferType { | 
 |     /// Control endpoint. | 
 |     Control, | 
 |  | 
 |     /// Isochronous endpoint. | 
 |     Isochronous, | 
 |  | 
 |     /// Bulk endpoint. | 
 |     Bulk, | 
 |  | 
 |     /// Interrupt endpoint. | 
 |     Interrupt, | 
 | } | 
 |  | 
 | /// Isochronous synchronization mode. | 
 | #[derive(Debug, PartialEq, Eq, Clone, Copy, Hash)] | 
 | #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] | 
 | pub enum SyncType { | 
 |     /// No synchronisation. | 
 |     NoSync, | 
 |  | 
 |     /// Asynchronous. | 
 |     Asynchronous, | 
 |  | 
 |     /// Adaptive. | 
 |     Adaptive, | 
 |  | 
 |     /// Synchronous. | 
 |     Synchronous, | 
 | } | 
 |  | 
 | /// Isochronous usage type. | 
 | #[derive(Debug, PartialEq, Eq, Clone, Copy, Hash)] | 
 | #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] | 
 | pub enum UsageType { | 
 |     /// Data endpoint. | 
 |     Data, | 
 |  | 
 |     /// Feedback endpoint. | 
 |     Feedback, | 
 |  | 
 |     /// Explicit feedback data endpoint. | 
 |     FeedbackData, | 
 |  | 
 |     /// Reserved. | 
 |     Reserved, | 
 | } | 
 |  | 
 | /// Types of control transfers. | 
 | #[derive(Debug, PartialEq, Eq, Clone, Copy, Hash)] | 
 | #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] | 
 | pub enum RequestType { | 
 |     /// Requests that are defined by the USB standard. | 
 |     Standard, | 
 |  | 
 |     /// Requests that are defined by a device class, e.g., HID. | 
 |     Class, | 
 |  | 
 |     /// Vendor-specific requests. | 
 |     Vendor, | 
 |  | 
 |     /// Reserved for future use. | 
 |     Reserved, | 
 | } | 
 |  | 
 | /// Recipients of control transfers. | 
 | #[derive(Debug, PartialEq, Eq, Clone, Copy, Hash)] | 
 | #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] | 
 | pub enum Recipient { | 
 |     /// The recipient is a device. | 
 |     Device, | 
 |  | 
 |     /// The recipient is an interface. | 
 |     Interface, | 
 |  | 
 |     /// The recipient is an endpoint. | 
 |     Endpoint, | 
 |  | 
 |     /// Other. | 
 |     Other, | 
 | } | 
 |  | 
 | /// A three-part version consisting of major, minor, and sub minor components. | 
 | /// | 
 | /// This can be used to represent versions of the format `J.M.N`, where `J` is the major version, | 
 | /// `M` is the minor version, and `N` is the sub minor version. A version is constructed by | 
 | /// providing the fields in the same order to the tuple. For example: | 
 | /// | 
 | /// ``` | 
 | /// rusb::Version(0, 2, 1); | 
 | /// ``` | 
 | /// | 
 | /// represents the version 0.2.1. | 
 | /// | 
 | /// The intended use case of `Version` is to extract meaning from the version fields in USB | 
 | /// descriptors, such as `bcdUSB` and `bcdDevice` in device descriptors. | 
 | #[derive(Debug, PartialEq, Eq, Clone, Copy, Hash, PartialOrd, Ord)] | 
 | #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] | 
 | pub struct Version(pub u8, pub u8, pub u8); | 
 |  | 
 | impl Version { | 
 |     /// Extracts a version from a binary coded decimal (BCD) field. BCD fields exist in USB | 
 |     /// descriptors as 16-bit integers encoding a version as `0xJJMN`, where `JJ` is the major | 
 |     /// version, `M` is the minor version, and `N` is the sub minor version. For example, 2.0 is | 
 |     /// encoded as `0x0200` and 1.1 is encoded as `0x0110`. | 
 |     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) | 
 |     } | 
 |  | 
 |     /// Returns the major version. | 
 |     pub fn major(self) -> u8 { | 
 |         let Version(major, _, _) = self; | 
 |         major | 
 |     } | 
 |  | 
 |     /// Returns the minor version. | 
 |     pub fn minor(self) -> u8 { | 
 |         let Version(_, minor, _) = self; | 
 |         minor | 
 |     } | 
 |  | 
 |     /// Returns the sub minor version. | 
 |     pub fn sub_minor(self) -> u8 { | 
 |         let Version(_, _, sub_minor) = self; | 
 |         sub_minor | 
 |     } | 
 | } | 
 |  | 
 | impl std::fmt::Display for Version { | 
 |     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { | 
 |         write!(f, "{}.{}.{}", self.major(), self.minor(), self.sub_minor()) | 
 |     } | 
 | } | 
 |  | 
 | /// Builds a value for the `bmRequestType` field of a control transfer setup packet. | 
 | /// | 
 | /// The `bmRequestType` field of a USB control transfer setup packet is a bit field specifying | 
 | /// three parameters, which are given to this function by corresponding enum values. | 
 | /// | 
 | /// ## Examples | 
 | /// | 
 | /// The following example returns a `bmRequestType` value for a standard inbound transfer from the | 
 | /// device, which could be used for reading a device's descriptors: | 
 | /// | 
 | /// ```no_run | 
 | /// use rusb::{Direction,RequestType,Recipient}; | 
 | /// | 
 | /// rusb::request_type(Direction::In, RequestType::Standard, Recipient::Device); | 
 | /// ``` | 
 | pub const 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::*; | 
 |  | 
 |     // Version | 
 |  | 
 |     #[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 version_display() { | 
 |         assert_eq!(Version(2, 45, 13).to_string(), "2.45.13"); | 
 |     } | 
 |  | 
 |     #[test] | 
 |     fn version_ord() { | 
 |         assert!(Version(0, 0, 0) < Version(1, 2, 3)); | 
 |         assert!(Version(1, 0, 0) < Version(1, 2, 3)); | 
 |         assert!(Version(1, 2, 0) < Version(1, 2, 3)); | 
 |         assert!(Version(1, 2, 0) < Version(1, 3, 0)); | 
 |         assert!(Version(255, 255, 255) > Version(254, 0, 0)); | 
 |         assert!(Version(0, 255, 0) > Version(0, 254, 255)); | 
 |     } | 
 |  | 
 |     // request_type for direction | 
 |  | 
 |     #[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 | 
 |         ); | 
 |     } | 
 |  | 
 |     // request_type for request type | 
 |  | 
 |     #[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 | 
 |         ); | 
 |     } | 
 |  | 
 |     // request_type for recipient | 
 |  | 
 |     #[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 | 
 |         ); | 
 |     } | 
 | } |