#[cfg(test)] mod test{ use libusb_src as ffi; #[test] fn test_version() { use std::{ffi::CStr, str}; let version = unsafe { &*ffi::libusb_get_version() }; let rc = str::from_utf8(unsafe { CStr::from_ptr(version.rc) }.to_bytes()).unwrap_or(""); let describe = str::from_utf8(unsafe { CStr::from_ptr(version.describe) }.to_bytes()).unwrap_or(""); assert_eq!(version.major, 1); assert_eq!(version.minor, 0); println!( "libusb v{}.{}.{}.{}{} {}", version.major, version.minor, version.micro, version.nano, rc, describe ); } #[test] fn test_init_and_exit() { let mut context: *mut ffi::libusb_context = std::ptr::null_mut(); for i in 0..=100 { match unsafe { ffi::libusb_init(&mut context) } { 0 => (), err => panic!("Failed to init libusb on iteration {}: {}", i, err), } unsafe { ffi::libusb_exit(context); } #[cfg(target_os = "macos")] std::thread::sleep(std::time::Duration::from_millis(1)); context = std::ptr::null_mut(); } } #[test] fn test_get_device_list() { let mut context = std::mem::MaybeUninit::<*mut ffi::libusb_context>::uninit(); match unsafe { ffi::libusb_init(context.as_mut_ptr()) } { 0 => (), err => panic!("Failed to init libusb {}", err), } let mut list = std::mem::MaybeUninit::<*const *mut ffi::libusb_device>::uninit(); let list_size = unsafe { ffi::libusb_get_device_list(context.assume_init(), list.as_mut_ptr()) }; if list_size < 0 || unsafe { list.assume_init().is_null() } { panic!("Failed to get device list {} {:p}", -list_size, unsafe { list.assume_init() }); } unsafe { ffi::libusb_free_device_list(list.assume_init(), 1); } unsafe { ffi::libusb_exit(context.assume_init()); } } #[test] fn test_fill_control_setup() { let mut buf = [0u8; ffi::LIBUSB_CONTROL_SETUP_SIZE + 1]; unsafe { ffi::libusb_fill_control_setup( buf.as_mut_ptr(), ffi::LIBUSB_REQUEST_TYPE_VENDOR | ffi::LIBUSB_ENDPOINT_OUT, 0x04, 0x4e, 0, (buf.len() - ffi::LIBUSB_CONTROL_SETUP_SIZE) as u16, ); } buf[ffi::LIBUSB_CONTROL_SETUP_SIZE] = 0x01; let setup: *mut ffi::libusb_control_setup = buf.as_mut_ptr() as *mut _; assert_eq!( unsafe { (*setup).bmRequestType }, ffi::LIBUSB_REQUEST_TYPE_VENDOR | ffi::LIBUSB_ENDPOINT_OUT ); assert_eq!(unsafe { (*setup).bRequest }, 0x04); assert_eq!(unsafe { u16::from_le((*setup).wValue) }, 0x4e); assert_eq!(unsafe { u16::from_le((*setup).wIndex) }, 0); assert_eq!(unsafe { u16::from_le((*setup).wLength) }, 1); } #[test] fn test_fill_control_transfer() { extern "system" fn callback(_transfer: *mut ffi::libusb_transfer) {} let mut buf = [0u8; ffi::LIBUSB_CONTROL_SETUP_SIZE + 1]; unsafe { ffi::libusb_fill_control_setup( buf.as_mut_ptr(), ffi::LIBUSB_REQUEST_TYPE_VENDOR | ffi::LIBUSB_ENDPOINT_OUT, 0x04, 0x4e, 0, (buf.len() - ffi::LIBUSB_CONTROL_SETUP_SIZE) as u16, ); } buf[ffi::LIBUSB_CONTROL_SETUP_SIZE] = 0x05; let mut transfer = std::mem::MaybeUninit::::uninit(); unsafe { ffi::libusb_fill_control_transfer( transfer.as_mut_ptr(), std::ptr::null_mut(), buf.as_mut_ptr(), callback, std::ptr::null_mut(), 1000, ); } let transfer = unsafe { &mut transfer.assume_init() }; assert_eq!(transfer.endpoint, 0); assert_eq!( transfer.length as usize, ffi::LIBUSB_CONTROL_SETUP_SIZE + 1 ); assert_eq!(transfer.timeout, 1000); assert_eq!( transfer.transfer_type, ffi::LIBUSB_TRANSFER_TYPE_CONTROL ); assert_eq!(transfer.buffer, buf.as_mut_ptr()); let data = unsafe { std::slice::from_raw_parts(ffi::libusb_control_transfer_get_data(transfer as *mut _), 1) }; assert_eq!(data[0], 0x05); } #[test] fn test_fill_bulk_transfer() { extern "system" fn callback(_transfer: *mut ffi::libusb_transfer) {} let mut transfer = std::mem::MaybeUninit::::uninit(); let mut buf = [5u8; 64]; unsafe { ffi::libusb_fill_bulk_transfer( transfer.as_mut_ptr(), std::ptr::null_mut(), 0x80, buf.as_mut_ptr(), buf.len() as libc::c_int, callback, std::ptr::null_mut(), 1000, ); } let transfer = unsafe { &transfer.assume_init() }; assert_eq!(transfer.endpoint, 0x80); assert_eq!(transfer.timeout, 1000); assert_eq!( transfer.transfer_type, ffi::LIBUSB_TRANSFER_TYPE_BULK ); assert_eq!(transfer.buffer, buf.as_mut_ptr()); assert_eq!(transfer.length, buf.len() as libc::c_int); } }