1 use libusb1_sys as ffi;
2 
3 #[test]
test_version()4 fn test_version() {
5     use std::{ffi::CStr, str};
6     let version = unsafe { &*ffi::libusb_get_version() };
7     let rc = str::from_utf8(unsafe { CStr::from_ptr(version.rc) }.to_bytes()).unwrap_or("");
8     let describe =
9         str::from_utf8(unsafe { CStr::from_ptr(version.describe) }.to_bytes()).unwrap_or("");
10 
11     assert_eq!(version.major, 1);
12     assert_eq!(version.minor, 0);
13     println!(
14         "libusb v{}.{}.{}.{}{} {}",
15         version.major, version.minor, version.micro, version.nano, rc, describe
16     );
17 }
18 
19 #[test]
test_init_and_exit()20 fn test_init_and_exit() {
21     let mut context: *mut ffi::libusb_context = std::ptr::null_mut();
22     for i in 0..=100 {
23         match unsafe { ffi::libusb_init(&mut context) } {
24             0 => (),
25             err => panic!("Failed to init libusb on iteration {}: {}", i, err),
26         }
27         unsafe {
28             ffi::libusb_exit(context);
29         }
30         #[cfg(target_os = "macos")]
31         std::thread::sleep(std::time::Duration::from_millis(1));
32         context = std::ptr::null_mut();
33     }
34 }
35 
36 #[test]
test_get_device_list()37 fn test_get_device_list() {
38     let mut context = std::mem::MaybeUninit::<*mut ffi::libusb_context>::uninit();
39     match unsafe { ffi::libusb_init(context.as_mut_ptr()) } {
40         0 => (),
41         err => panic!("Failed to init libusb {}", err),
42     }
43     let mut list = std::mem::MaybeUninit::<*const *mut ffi::libusb_device>::uninit();
44     let list_size =
45         unsafe { ffi::libusb_get_device_list(context.assume_init(), list.as_mut_ptr()) };
46     if list_size < 0 || unsafe { list.assume_init().is_null() } {
47         panic!("Failed to get device list {} {:p}", -list_size, unsafe {
48             list.assume_init()
49         });
50     }
51     unsafe {
52         ffi::libusb_free_device_list(list.assume_init(), 1);
53     }
54     unsafe {
55         ffi::libusb_exit(context.assume_init());
56     }
57 }
58 
59 #[test]
test_fill_control_setup()60 fn test_fill_control_setup() {
61     let mut buf = [0u8; ffi::constants::LIBUSB_CONTROL_SETUP_SIZE + 1];
62     unsafe {
63         ffi::libusb_fill_control_setup(
64             buf.as_mut_ptr(),
65             ffi::constants::LIBUSB_REQUEST_TYPE_VENDOR | ffi::constants::LIBUSB_ENDPOINT_OUT,
66             0x04,
67             0x4e,
68             0,
69             (buf.len() - ffi::constants::LIBUSB_CONTROL_SETUP_SIZE) as u16,
70         );
71     }
72     buf[ffi::constants::LIBUSB_CONTROL_SETUP_SIZE] = 0x01;
73     let setup: *mut ffi::libusb_control_setup = buf.as_mut_ptr() as *mut _;
74 
75     assert_eq!(
76         unsafe { (*setup).bmRequestType },
77         ffi::constants::LIBUSB_REQUEST_TYPE_VENDOR | ffi::constants::LIBUSB_ENDPOINT_OUT
78     );
79     assert_eq!(unsafe { (*setup).bRequest }, 0x04);
80     assert_eq!(unsafe { u16::from_le((*setup).wValue) }, 0x4e);
81     assert_eq!(unsafe { u16::from_le((*setup).wIndex) }, 0);
82     assert_eq!(unsafe { u16::from_le((*setup).wLength) }, 1);
83 }
84 
85 #[test]
test_fill_control_transfer()86 fn test_fill_control_transfer() {
87     extern "system" fn callback(_transfer: *mut ffi::libusb_transfer) {}
88 
89     let mut buf = [0u8; ffi::constants::LIBUSB_CONTROL_SETUP_SIZE + 1];
90     unsafe {
91         ffi::libusb_fill_control_setup(
92             buf.as_mut_ptr(),
93             ffi::constants::LIBUSB_REQUEST_TYPE_VENDOR | ffi::constants::LIBUSB_ENDPOINT_OUT,
94             0x04,
95             0x4e,
96             0,
97             (buf.len() - ffi::constants::LIBUSB_CONTROL_SETUP_SIZE) as u16,
98         );
99     }
100     buf[ffi::constants::LIBUSB_CONTROL_SETUP_SIZE] = 0x05;
101 
102     let mut transfer = std::mem::MaybeUninit::<ffi::libusb_transfer>::uninit();
103 
104     unsafe {
105         ffi::libusb_fill_control_transfer(
106             transfer.as_mut_ptr(),
107             std::ptr::null_mut(),
108             buf.as_mut_ptr(),
109             callback,
110             std::ptr::null_mut(),
111             1000,
112         );
113     }
114     let transfer = unsafe { &mut transfer.assume_init() };
115     assert_eq!(transfer.endpoint, 0);
116     assert_eq!(
117         transfer.length as usize,
118         ffi::constants::LIBUSB_CONTROL_SETUP_SIZE + 1
119     );
120     assert_eq!(transfer.timeout, 1000);
121     assert_eq!(
122         transfer.transfer_type,
123         ffi::constants::LIBUSB_TRANSFER_TYPE_CONTROL
124     );
125     assert_eq!(transfer.buffer, buf.as_mut_ptr());
126 
127     let data = unsafe {
128         std::slice::from_raw_parts(ffi::libusb_control_transfer_get_data(transfer as *mut _), 1)
129     };
130     assert_eq!(data[0], 0x05);
131 }
132 
133 #[test]
test_fill_bulk_transfer()134 fn test_fill_bulk_transfer() {
135     extern "system" fn callback(_transfer: *mut ffi::libusb_transfer) {}
136 
137     let mut transfer = std::mem::MaybeUninit::<ffi::libusb_transfer>::uninit();
138     let mut buf = [5u8; 64];
139     unsafe {
140         ffi::libusb_fill_bulk_transfer(
141             transfer.as_mut_ptr(),
142             std::ptr::null_mut(),
143             0x80,
144             buf.as_mut_ptr(),
145             buf.len() as libc::c_int,
146             callback,
147             std::ptr::null_mut(),
148             1000,
149         );
150     }
151     let transfer = unsafe { &transfer.assume_init() };
152     assert_eq!(transfer.endpoint, 0x80);
153     assert_eq!(transfer.timeout, 1000);
154     assert_eq!(
155         transfer.transfer_type,
156         ffi::constants::LIBUSB_TRANSFER_TYPE_BULK
157     );
158     assert_eq!(transfer.buffer, buf.as_mut_ptr());
159     assert_eq!(transfer.length, buf.len() as libc::c_int);
160 }
161