1 use libc::c_int;
2 use libusb1_sys::constants::*;
3 
4 #[cfg(feature = "serde")]
5 use serde::{Deserialize, Serialize};
6 
7 /// Device speeds. Indicates the speed at which a device is operating.
8 /// - [libusb_supported_speed](http://libusb.sourceforge.net/api-1.0/group__libusb__dev.html#ga1454797ecc0de4d084c1619c420014f6)
9 /// - [USB release versions](https://en.wikipedia.org/wiki/USB#Release_versions)
10 #[derive(Debug, PartialEq, Eq, Clone, Copy, Hash)]
11 #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
12 #[non_exhaustive]
13 pub enum Speed {
14     /// The operating system doesn't know the device speed.
15     Unknown,
16 
17     /// The device is operating at low speed (1.5 Mbps).
18     Low,
19 
20     /// The device is operating at full speed (12 Mbps).
21     Full,
22 
23     /// The device is operating at high speed (480 Mbps).
24     High,
25 
26     /// The device is operating at super speed (5 Gbps).
27     Super,
28 
29     /// The device is operating at super speed (10 Gbps).
30     SuperPlus,
31 }
32 
33 #[doc(hidden)]
speed_from_libusb(n: c_int) -> Speed34 pub(crate) fn speed_from_libusb(n: c_int) -> Speed {
35     match n {
36         LIBUSB_SPEED_SUPER_PLUS => Speed::SuperPlus,
37         LIBUSB_SPEED_SUPER => Speed::Super,
38         LIBUSB_SPEED_HIGH => Speed::High,
39         LIBUSB_SPEED_FULL => Speed::Full,
40         LIBUSB_SPEED_LOW => Speed::Low,
41 
42         LIBUSB_SPEED_UNKNOWN | _ => Speed::Unknown,
43     }
44 }
45 
46 /// Transfer and endpoint directions.
47 #[derive(Debug, PartialEq, Eq, Clone, Copy, Hash)]
48 #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
49 pub enum Direction {
50     /// Direction for read (device to host) transfers.
51     In,
52 
53     /// Direction for write (host to device) transfers.
54     Out,
55 }
56 
57 /// An endpoint's transfer type.
58 #[derive(Debug, PartialEq, Eq, Clone, Copy, Hash)]
59 #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
60 pub enum TransferType {
61     /// Control endpoint.
62     Control,
63 
64     /// Isochronous endpoint.
65     Isochronous,
66 
67     /// Bulk endpoint.
68     Bulk,
69 
70     /// Interrupt endpoint.
71     Interrupt,
72 }
73 
74 /// Isochronous synchronization mode.
75 #[derive(Debug, PartialEq, Eq, Clone, Copy, Hash)]
76 #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
77 pub enum SyncType {
78     /// No synchronisation.
79     NoSync,
80 
81     /// Asynchronous.
82     Asynchronous,
83 
84     /// Adaptive.
85     Adaptive,
86 
87     /// Synchronous.
88     Synchronous,
89 }
90 
91 /// Isochronous usage type.
92 #[derive(Debug, PartialEq, Eq, Clone, Copy, Hash)]
93 #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
94 pub enum UsageType {
95     /// Data endpoint.
96     Data,
97 
98     /// Feedback endpoint.
99     Feedback,
100 
101     /// Explicit feedback data endpoint.
102     FeedbackData,
103 
104     /// Reserved.
105     Reserved,
106 }
107 
108 /// Types of control transfers.
109 #[derive(Debug, PartialEq, Eq, Clone, Copy, Hash)]
110 #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
111 pub enum RequestType {
112     /// Requests that are defined by the USB standard.
113     Standard,
114 
115     /// Requests that are defined by a device class, e.g., HID.
116     Class,
117 
118     /// Vendor-specific requests.
119     Vendor,
120 
121     /// Reserved for future use.
122     Reserved,
123 }
124 
125 /// Recipients of control transfers.
126 #[derive(Debug, PartialEq, Eq, Clone, Copy, Hash)]
127 #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
128 pub enum Recipient {
129     /// The recipient is a device.
130     Device,
131 
132     /// The recipient is an interface.
133     Interface,
134 
135     /// The recipient is an endpoint.
136     Endpoint,
137 
138     /// Other.
139     Other,
140 }
141 
142 /// A three-part version consisting of major, minor, and sub minor components.
143 ///
144 /// This can be used to represent versions of the format `J.M.N`, where `J` is the major version,
145 /// `M` is the minor version, and `N` is the sub minor version. A version is constructed by
146 /// providing the fields in the same order to the tuple. For example:
147 ///
148 /// ```
149 /// rusb::Version(0, 2, 1);
150 /// ```
151 ///
152 /// represents the version 0.2.1.
153 ///
154 /// The intended use case of `Version` is to extract meaning from the version fields in USB
155 /// descriptors, such as `bcdUSB` and `bcdDevice` in device descriptors.
156 #[derive(Debug, PartialEq, Eq, Clone, Copy, Hash, PartialOrd, Ord)]
157 #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
158 pub struct Version(pub u8, pub u8, pub u8);
159 
160 impl Version {
161     /// Extracts a version from a binary coded decimal (BCD) field. BCD fields exist in USB
162     /// descriptors as 16-bit integers encoding a version as `0xJJMN`, where `JJ` is the major
163     /// version, `M` is the minor version, and `N` is the sub minor version. For example, 2.0 is
164     /// encoded as `0x0200` and 1.1 is encoded as `0x0110`.
from_bcd(mut raw: u16) -> Self165     pub fn from_bcd(mut raw: u16) -> Self {
166         let sub_minor: u8 = (raw & 0x000F) as u8;
167         raw >>= 4;
168 
169         let minor: u8 = (raw & 0x000F) as u8;
170         raw >>= 4;
171 
172         let mut major: u8 = (raw & 0x000F) as u8;
173         raw >>= 4;
174 
175         major += (10 * raw) as u8;
176 
177         Version(major, minor, sub_minor)
178     }
179 
180     /// Returns the major version.
major(self) -> u8181     pub fn major(self) -> u8 {
182         let Version(major, _, _) = self;
183         major
184     }
185 
186     /// Returns the minor version.
minor(self) -> u8187     pub fn minor(self) -> u8 {
188         let Version(_, minor, _) = self;
189         minor
190     }
191 
192     /// Returns the sub minor version.
sub_minor(self) -> u8193     pub fn sub_minor(self) -> u8 {
194         let Version(_, _, sub_minor) = self;
195         sub_minor
196     }
197 }
198 
199 impl std::fmt::Display for Version {
fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result200     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
201         write!(f, "{}.{}.{}", self.major(), self.minor(), self.sub_minor())
202     }
203 }
204 
205 /// Builds a value for the `bmRequestType` field of a control transfer setup packet.
206 ///
207 /// The `bmRequestType` field of a USB control transfer setup packet is a bit field specifying
208 /// three parameters, which are given to this function by corresponding enum values.
209 ///
210 /// ## Examples
211 ///
212 /// The following example returns a `bmRequestType` value for a standard inbound transfer from the
213 /// device, which could be used for reading a device's descriptors:
214 ///
215 /// ```no_run
216 /// use rusb::{Direction,RequestType,Recipient};
217 ///
218 /// rusb::request_type(Direction::In, RequestType::Standard, Recipient::Device);
219 /// ```
request_type( direction: Direction, request_type: RequestType, recipient: Recipient, ) -> u8220 pub const fn request_type(
221     direction: Direction,
222     request_type: RequestType,
223     recipient: Recipient,
224 ) -> u8 {
225     let mut value: u8 = match direction {
226         Direction::Out => LIBUSB_ENDPOINT_OUT,
227         Direction::In => LIBUSB_ENDPOINT_IN,
228     };
229 
230     value |= match request_type {
231         RequestType::Standard => LIBUSB_REQUEST_TYPE_STANDARD,
232         RequestType::Class => LIBUSB_REQUEST_TYPE_CLASS,
233         RequestType::Vendor => LIBUSB_REQUEST_TYPE_VENDOR,
234         RequestType::Reserved => LIBUSB_REQUEST_TYPE_RESERVED,
235     };
236 
237     value |= match recipient {
238         Recipient::Device => LIBUSB_RECIPIENT_DEVICE,
239         Recipient::Interface => LIBUSB_RECIPIENT_INTERFACE,
240         Recipient::Endpoint => LIBUSB_RECIPIENT_ENDPOINT,
241         Recipient::Other => LIBUSB_RECIPIENT_OTHER,
242     };
243 
244     value
245 }
246 
247 #[cfg(test)]
248 mod test {
249     use super::*;
250 
251     // Version
252 
253     #[test]
version_returns_major_version()254     fn version_returns_major_version() {
255         assert_eq!(1, Version(1, 0, 0).major());
256         assert_eq!(2, Version(2, 0, 0).major());
257     }
258 
259     #[test]
version_returns_minor_version()260     fn version_returns_minor_version() {
261         assert_eq!(1, Version(0, 1, 0).minor());
262         assert_eq!(2, Version(0, 2, 0).minor());
263     }
264 
265     #[test]
version_returns_sub_minor_version()266     fn version_returns_sub_minor_version() {
267         assert_eq!(1, Version(0, 0, 1).sub_minor());
268         assert_eq!(2, Version(0, 0, 2).sub_minor());
269     }
270 
271     #[test]
version_parses_major_version()272     fn version_parses_major_version() {
273         assert_eq!(3, Version::from_bcd(0x0300).major());
274     }
275 
276     #[test]
version_parses_long_major_version()277     fn version_parses_long_major_version() {
278         assert_eq!(12, Version::from_bcd(0x1200).major());
279     }
280 
281     #[test]
version_parses_minor_version()282     fn version_parses_minor_version() {
283         assert_eq!(1, Version::from_bcd(0x0010).minor());
284         assert_eq!(2, Version::from_bcd(0x0020).minor());
285     }
286 
287     #[test]
version_parses_sub_minor_version()288     fn version_parses_sub_minor_version() {
289         assert_eq!(1, Version::from_bcd(0x0001).sub_minor());
290         assert_eq!(2, Version::from_bcd(0x0002).sub_minor());
291     }
292 
293     #[test]
version_parses_full_version()294     fn version_parses_full_version() {
295         assert_eq!(Version(12, 3, 4), Version::from_bcd(0x1234));
296     }
297 
298     #[test]
version_display()299     fn version_display() {
300         assert_eq!(Version(2, 45, 13).to_string(), "2.45.13");
301     }
302 
303     #[test]
version_ord()304     fn version_ord() {
305         assert!(Version(0, 0, 0) < Version(1, 2, 3));
306         assert!(Version(1, 0, 0) < Version(1, 2, 3));
307         assert!(Version(1, 2, 0) < Version(1, 2, 3));
308         assert!(Version(1, 2, 0) < Version(1, 3, 0));
309         assert!(Version(255, 255, 255) > Version(254, 0, 0));
310         assert!(Version(0, 255, 0) > Version(0, 254, 255));
311     }
312 
313     // request_type for direction
314 
315     #[test]
request_type_builds_value_for_out_direction()316     fn request_type_builds_value_for_out_direction() {
317         assert_eq!(
318             request_type(Direction::Out, RequestType::Standard, Recipient::Device) & 0x80,
319             0x00
320         );
321     }
322 
323     #[test]
request_type_builds_value_for_in_direction()324     fn request_type_builds_value_for_in_direction() {
325         assert_eq!(
326             request_type(Direction::In, RequestType::Standard, Recipient::Device) & 0x80,
327             0x80
328         );
329     }
330 
331     // request_type for request type
332 
333     #[test]
request_type_builds_value_for_standard_request()334     fn request_type_builds_value_for_standard_request() {
335         assert_eq!(
336             request_type(Direction::Out, RequestType::Standard, Recipient::Device) & 0x60,
337             0x00
338         );
339     }
340 
341     #[test]
request_type_builds_value_for_class_request()342     fn request_type_builds_value_for_class_request() {
343         assert_eq!(
344             request_type(Direction::Out, RequestType::Class, Recipient::Device) & 0x60,
345             0x20
346         );
347     }
348 
349     #[test]
request_type_builds_value_for_vendor_request()350     fn request_type_builds_value_for_vendor_request() {
351         assert_eq!(
352             request_type(Direction::Out, RequestType::Vendor, Recipient::Device) & 0x60,
353             0x40
354         );
355     }
356 
357     #[test]
request_type_builds_value_for_reserved_request()358     fn request_type_builds_value_for_reserved_request() {
359         assert_eq!(
360             request_type(Direction::Out, RequestType::Reserved, Recipient::Device) & 0x60,
361             0x60
362         );
363     }
364 
365     // request_type for recipient
366 
367     #[test]
request_type_builds_value_for_device_recipient()368     fn request_type_builds_value_for_device_recipient() {
369         assert_eq!(
370             request_type(Direction::Out, RequestType::Standard, Recipient::Device) & 0x0F,
371             0x00
372         );
373     }
374 
375     #[test]
request_type_builds_value_for_interface_recipient()376     fn request_type_builds_value_for_interface_recipient() {
377         assert_eq!(
378             request_type(Direction::Out, RequestType::Standard, Recipient::Interface) & 0x0F,
379             0x01
380         );
381     }
382 
383     #[test]
request_type_builds_value_for_endpoint_recipient()384     fn request_type_builds_value_for_endpoint_recipient() {
385         assert_eq!(
386             request_type(Direction::Out, RequestType::Standard, Recipient::Endpoint) & 0x0F,
387             0x02
388         );
389     }
390 
391     #[test]
request_type_builds_value_for_other_recipient()392     fn request_type_builds_value_for_other_recipient() {
393         assert_eq!(
394             request_type(Direction::Out, RequestType::Standard, Recipient::Other) & 0x0F,
395             0x03
396         );
397     }
398 }
399