diff options
Diffstat (limited to 'usb_util')
-rw-r--r-- | usb_util/Cargo.toml | 12 | ||||
-rw-r--r-- | usb_util/build.rs | 10 | ||||
-rw-r--r-- | usb_util/src/bindings.rs | 4638 | ||||
-rw-r--r-- | usb_util/src/config_descriptor.rs | 66 | ||||
-rw-r--r-- | usb_util/src/descriptor.rs | 499 | ||||
-rw-r--r-- | usb_util/src/device.rs | 458 | ||||
-rw-r--r-- | usb_util/src/device_handle.rs | 161 | ||||
-rw-r--r-- | usb_util/src/endpoint_descriptor.rs | 57 | ||||
-rw-r--r-- | usb_util/src/error.rs | 103 | ||||
-rw-r--r-- | usb_util/src/hotplug.rs | 77 | ||||
-rw-r--r-- | usb_util/src/interface_descriptor.rs | 40 | ||||
-rw-r--r-- | usb_util/src/lib.rs | 33 | ||||
-rw-r--r-- | usb_util/src/libusb_context.rs | 268 | ||||
-rw-r--r-- | usb_util/src/libusb_device.rs | 108 | ||||
-rw-r--r-- | usb_util/src/types.rs | 259 | ||||
-rw-r--r-- | usb_util/src/usb_transfer.rs | 382 |
16 files changed, 1242 insertions, 5929 deletions
diff --git a/usb_util/Cargo.toml b/usb_util/Cargo.toml index fab07d6..ed505ff 100644 --- a/usb_util/Cargo.toml +++ b/usb_util/Cargo.toml @@ -3,15 +3,11 @@ name = "usb_util" version = "0.1.0" authors = ["The Chromium OS Authors"] edition = "2018" -build = "build.rs" - -[features] -sandboxed-libusb = [] [dependencies] assertions = { path = "../assertions" } data_model = { path = "../data_model" } -sync = { path = "../sync" } - -[build-dependencies] -pkg-config = "=0.3.11" +libc = "*" +remain = "*" +sys_util = { path = "../sys_util" } +usb_sys = { path = "../usb_sys" } diff --git a/usb_util/build.rs b/usb_util/build.rs deleted file mode 100644 index 34e14da..0000000 --- a/usb_util/build.rs +++ /dev/null @@ -1,10 +0,0 @@ -// Copyright 2018 The Chromium OS Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -use std::env; - -fn main() { - env::set_var("PKG_CONFIG_ALLOW_CROSS", "1"); - pkg_config::probe_library("libusb-1.0").unwrap(); -} diff --git a/usb_util/src/bindings.rs b/usb_util/src/bindings.rs deleted file mode 100644 index 8f62a01..0000000 --- a/usb_util/src/bindings.rs +++ /dev/null @@ -1,4638 +0,0 @@ -// Copyright 2019 The Chromium OS Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -/* automatically generated by rust-bindgen */ - -#[repr(C)] -#[derive(Default)] -pub struct __IncompleteArrayField<T>(::std::marker::PhantomData<T>); -impl<T> __IncompleteArrayField<T> { - #[inline] - pub fn new() -> Self { - __IncompleteArrayField(::std::marker::PhantomData) - } - #[inline] - pub unsafe fn as_ptr(&self) -> *const T { - ::std::mem::transmute(self) - } - #[inline] - pub unsafe fn as_mut_ptr(&mut self) -> *mut T { - ::std::mem::transmute(self) - } - #[inline] - pub unsafe fn as_slice(&self, len: usize) -> &[T] { - ::std::slice::from_raw_parts(self.as_ptr(), len) - } - #[inline] - pub unsafe fn as_mut_slice(&mut self, len: usize) -> &mut [T] { - ::std::slice::from_raw_parts_mut(self.as_mut_ptr(), len) - } -} -impl<T> ::std::fmt::Debug for __IncompleteArrayField<T> { - fn fmt(&self, fmt: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { - fmt.write_str("__IncompleteArrayField") - } -} -impl<T> ::std::clone::Clone for __IncompleteArrayField<T> { - #[inline] - fn clone(&self) -> Self { - Self::new() - } -} -impl<T> ::std::marker::Copy for __IncompleteArrayField<T> {} -pub const _STDINT_H: u32 = 1; -pub const _FEATURES_H: u32 = 1; -pub const _DEFAULT_SOURCE: u32 = 1; -pub const __USE_ISOC11: u32 = 1; -pub const __USE_ISOC99: u32 = 1; -pub const __USE_ISOC95: u32 = 1; -pub const __USE_POSIX_IMPLICITLY: u32 = 1; -pub const _POSIX_SOURCE: u32 = 1; -pub const _POSIX_C_SOURCE: u32 = 200809; -pub const __USE_POSIX: u32 = 1; -pub const __USE_POSIX2: u32 = 1; -pub const __USE_POSIX199309: u32 = 1; -pub const __USE_POSIX199506: u32 = 1; -pub const __USE_XOPEN2K: u32 = 1; -pub const __USE_XOPEN2K8: u32 = 1; -pub const _ATFILE_SOURCE: u32 = 1; -pub const __USE_MISC: u32 = 1; -pub const __USE_ATFILE: u32 = 1; -pub const __USE_FORTIFY_LEVEL: u32 = 0; -pub const _STDC_PREDEF_H: u32 = 1; -pub const __STDC_IEC_559__: u32 = 1; -pub const __STDC_IEC_559_COMPLEX__: u32 = 1; -pub const __STDC_ISO_10646__: u32 = 201605; -pub const __STDC_NO_THREADS__: u32 = 1; -pub const __GNU_LIBRARY__: u32 = 6; -pub const __GLIBC__: u32 = 2; -pub const __GLIBC_MINOR__: u32 = 24; -pub const _SYS_CDEFS_H: u32 = 1; -pub const __WORDSIZE: u32 = 64; -pub const __WORDSIZE_TIME64_COMPAT32: u32 = 1; -pub const __SYSCALL_WORDSIZE: u32 = 64; -pub const _BITS_WCHAR_H: u32 = 1; -pub const INT8_MIN: i32 = -128; -pub const INT16_MIN: i32 = -32768; -pub const INT32_MIN: i32 = -2147483648; -pub const INT8_MAX: u32 = 127; -pub const INT16_MAX: u32 = 32767; -pub const INT32_MAX: u32 = 2147483647; -pub const UINT8_MAX: u32 = 255; -pub const UINT16_MAX: u32 = 65535; -pub const UINT32_MAX: u32 = 4294967295; -pub const INT_LEAST8_MIN: i32 = -128; -pub const INT_LEAST16_MIN: i32 = -32768; -pub const INT_LEAST32_MIN: i32 = -2147483648; -pub const INT_LEAST8_MAX: u32 = 127; -pub const INT_LEAST16_MAX: u32 = 32767; -pub const INT_LEAST32_MAX: u32 = 2147483647; -pub const UINT_LEAST8_MAX: u32 = 255; -pub const UINT_LEAST16_MAX: u32 = 65535; -pub const UINT_LEAST32_MAX: u32 = 4294967295; -pub const INT_FAST8_MIN: i32 = -128; -pub const INT_FAST16_MIN: i64 = -9223372036854775808; -pub const INT_FAST32_MIN: i64 = -9223372036854775808; -pub const INT_FAST8_MAX: u32 = 127; -pub const INT_FAST16_MAX: u64 = 9223372036854775807; -pub const INT_FAST32_MAX: u64 = 9223372036854775807; -pub const UINT_FAST8_MAX: u32 = 255; -pub const UINT_FAST16_MAX: i32 = -1; -pub const UINT_FAST32_MAX: i32 = -1; -pub const INTPTR_MIN: i64 = -9223372036854775808; -pub const INTPTR_MAX: u64 = 9223372036854775807; -pub const UINTPTR_MAX: i32 = -1; -pub const PTRDIFF_MIN: i64 = -9223372036854775808; -pub const PTRDIFF_MAX: u64 = 9223372036854775807; -pub const SIG_ATOMIC_MIN: i32 = -2147483648; -pub const SIG_ATOMIC_MAX: u32 = 2147483647; -pub const SIZE_MAX: i32 = -1; -pub const WINT_MIN: u32 = 0; -pub const WINT_MAX: u32 = 4294967295; -pub const _SYS_TYPES_H: u32 = 1; -pub const _BITS_TYPES_H: u32 = 1; -pub const _BITS_TYPESIZES_H: u32 = 1; -pub const __OFF_T_MATCHES_OFF64_T: u32 = 1; -pub const __INO_T_MATCHES_INO64_T: u32 = 1; -pub const __FD_SETSIZE: u32 = 1024; -pub const __clock_t_defined: u32 = 1; -pub const __time_t_defined: u32 = 1; -pub const __clockid_t_defined: u32 = 1; -pub const __timer_t_defined: u32 = 1; -pub const __BIT_TYPES_DEFINED__: u32 = 1; -pub const _ENDIAN_H: u32 = 1; -pub const __LITTLE_ENDIAN: u32 = 1234; -pub const __BIG_ENDIAN: u32 = 4321; -pub const __PDP_ENDIAN: u32 = 3412; -pub const __BYTE_ORDER: u32 = 1234; -pub const __FLOAT_WORD_ORDER: u32 = 1234; -pub const LITTLE_ENDIAN: u32 = 1234; -pub const BIG_ENDIAN: u32 = 4321; -pub const PDP_ENDIAN: u32 = 3412; -pub const BYTE_ORDER: u32 = 1234; -pub const _BITS_BYTESWAP_H: u32 = 1; -pub const _SYS_SELECT_H: u32 = 1; -pub const __FD_ZERO_STOS: &'static [u8; 6usize] = b"stosq\0"; -pub const _SIGSET_H_types: u32 = 1; -pub const __timespec_defined: u32 = 1; -pub const _STRUCT_TIMEVAL: u32 = 1; -pub const FD_SETSIZE: u32 = 1024; -pub const _SYS_SYSMACROS_H: u32 = 1; -pub const _BITS_PTHREADTYPES_H: u32 = 1; -pub const __SIZEOF_PTHREAD_ATTR_T: u32 = 56; -pub const __SIZEOF_PTHREAD_MUTEX_T: u32 = 40; -pub const __SIZEOF_PTHREAD_MUTEXATTR_T: u32 = 4; -pub const __SIZEOF_PTHREAD_COND_T: u32 = 48; -pub const __SIZEOF_PTHREAD_CONDATTR_T: u32 = 4; -pub const __SIZEOF_PTHREAD_RWLOCK_T: u32 = 56; -pub const __SIZEOF_PTHREAD_RWLOCKATTR_T: u32 = 8; -pub const __SIZEOF_PTHREAD_BARRIER_T: u32 = 32; -pub const __SIZEOF_PTHREAD_BARRIERATTR_T: u32 = 4; -pub const __have_pthread_attr_t: u32 = 1; -pub const __PTHREAD_MUTEX_HAVE_PREV: u32 = 1; -pub const __PTHREAD_RWLOCK_INT_FLAGS_SHARED: u32 = 1; -pub const _SYS_TIME_H: u32 = 1; -pub const _TIME_H: u32 = 1; -pub const _BITS_TIME_H: u32 = 1; -pub const CLOCK_REALTIME: u32 = 0; -pub const CLOCK_MONOTONIC: u32 = 1; -pub const CLOCK_PROCESS_CPUTIME_ID: u32 = 2; -pub const CLOCK_THREAD_CPUTIME_ID: u32 = 3; -pub const CLOCK_MONOTONIC_RAW: u32 = 4; -pub const CLOCK_REALTIME_COARSE: u32 = 5; -pub const CLOCK_MONOTONIC_COARSE: u32 = 6; -pub const CLOCK_BOOTTIME: u32 = 7; -pub const CLOCK_REALTIME_ALARM: u32 = 8; -pub const CLOCK_BOOTTIME_ALARM: u32 = 9; -pub const CLOCK_TAI: u32 = 11; -pub const TIMER_ABSTIME: u32 = 1; -pub const TIME_UTC: u32 = 1; -pub const _XLOCALE_H: u32 = 1; -pub const _LIBC_LIMITS_H_: u32 = 1; -pub const MB_LEN_MAX: u32 = 16; -pub const _BITS_POSIX1_LIM_H: u32 = 1; -pub const _POSIX_AIO_LISTIO_MAX: u32 = 2; -pub const _POSIX_AIO_MAX: u32 = 1; -pub const _POSIX_ARG_MAX: u32 = 4096; -pub const _POSIX_CHILD_MAX: u32 = 25; -pub const _POSIX_DELAYTIMER_MAX: u32 = 32; -pub const _POSIX_HOST_NAME_MAX: u32 = 255; -pub const _POSIX_LINK_MAX: u32 = 8; -pub const _POSIX_LOGIN_NAME_MAX: u32 = 9; -pub const _POSIX_MAX_CANON: u32 = 255; -pub const _POSIX_MAX_INPUT: u32 = 255; -pub const _POSIX_MQ_OPEN_MAX: u32 = 8; -pub const _POSIX_MQ_PRIO_MAX: u32 = 32; -pub const _POSIX_NAME_MAX: u32 = 14; -pub const _POSIX_NGROUPS_MAX: u32 = 8; -pub const _POSIX_OPEN_MAX: u32 = 20; -pub const _POSIX_PATH_MAX: u32 = 256; -pub const _POSIX_PIPE_BUF: u32 = 512; -pub const _POSIX_RE_DUP_MAX: u32 = 255; -pub const _POSIX_RTSIG_MAX: u32 = 8; -pub const _POSIX_SEM_NSEMS_MAX: u32 = 256; -pub const _POSIX_SEM_VALUE_MAX: u32 = 32767; -pub const _POSIX_SIGQUEUE_MAX: u32 = 32; -pub const _POSIX_SSIZE_MAX: u32 = 32767; -pub const _POSIX_STREAM_MAX: u32 = 8; -pub const _POSIX_SYMLINK_MAX: u32 = 255; -pub const _POSIX_SYMLOOP_MAX: u32 = 8; -pub const _POSIX_TIMER_MAX: u32 = 32; -pub const _POSIX_TTY_NAME_MAX: u32 = 9; -pub const _POSIX_TZNAME_MAX: u32 = 6; -pub const _POSIX_CLOCKRES_MIN: u32 = 20000000; -pub const NR_OPEN: u32 = 1024; -pub const NGROUPS_MAX: u32 = 65536; -pub const ARG_MAX: u32 = 131072; -pub const LINK_MAX: u32 = 127; -pub const MAX_CANON: u32 = 255; -pub const MAX_INPUT: u32 = 255; -pub const NAME_MAX: u32 = 255; -pub const PATH_MAX: u32 = 4096; -pub const PIPE_BUF: u32 = 4096; -pub const XATTR_NAME_MAX: u32 = 255; -pub const XATTR_SIZE_MAX: u32 = 65536; -pub const XATTR_LIST_MAX: u32 = 65536; -pub const RTSIG_MAX: u32 = 32; -pub const _POSIX_THREAD_KEYS_MAX: u32 = 128; -pub const PTHREAD_KEYS_MAX: u32 = 1024; -pub const _POSIX_THREAD_DESTRUCTOR_ITERATIONS: u32 = 4; -pub const PTHREAD_DESTRUCTOR_ITERATIONS: u32 = 4; -pub const _POSIX_THREAD_THREADS_MAX: u32 = 64; -pub const AIO_PRIO_DELTA_MAX: u32 = 20; -pub const PTHREAD_STACK_MIN: u32 = 16384; -pub const DELAYTIMER_MAX: u32 = 2147483647; -pub const TTY_NAME_MAX: u32 = 32; -pub const LOGIN_NAME_MAX: u32 = 256; -pub const HOST_NAME_MAX: u32 = 64; -pub const MQ_PRIO_MAX: u32 = 32768; -pub const SEM_VALUE_MAX: u32 = 2147483647; -pub const _BITS_POSIX2_LIM_H: u32 = 1; -pub const _POSIX2_BC_BASE_MAX: u32 = 99; -pub const _POSIX2_BC_DIM_MAX: u32 = 2048; -pub const _POSIX2_BC_SCALE_MAX: u32 = 99; -pub const _POSIX2_BC_STRING_MAX: u32 = 1000; -pub const _POSIX2_COLL_WEIGHTS_MAX: u32 = 2; -pub const _POSIX2_EXPR_NEST_MAX: u32 = 32; -pub const _POSIX2_LINE_MAX: u32 = 2048; -pub const _POSIX2_RE_DUP_MAX: u32 = 255; -pub const _POSIX2_CHARCLASS_NAME_MAX: u32 = 14; -pub const BC_BASE_MAX: u32 = 99; -pub const BC_DIM_MAX: u32 = 2048; -pub const BC_SCALE_MAX: u32 = 99; -pub const BC_STRING_MAX: u32 = 1000; -pub const COLL_WEIGHTS_MAX: u32 = 255; -pub const EXPR_NEST_MAX: u32 = 32; -pub const LINE_MAX: u32 = 2048; -pub const CHARCLASS_NAME_MAX: u32 = 2048; -pub const RE_DUP_MAX: u32 = 32767; -pub const LIBUSB_API_VERSION: u32 = 16777477; -pub const LIBUSBX_API_VERSION: u32 = 16777477; -pub const LIBUSB_DT_DEVICE_SIZE: u32 = 18; -pub const LIBUSB_DT_CONFIG_SIZE: u32 = 9; -pub const LIBUSB_DT_INTERFACE_SIZE: u32 = 9; -pub const LIBUSB_DT_ENDPOINT_SIZE: u32 = 7; -pub const LIBUSB_DT_ENDPOINT_AUDIO_SIZE: u32 = 9; -pub const LIBUSB_DT_HUB_NONVAR_SIZE: u32 = 7; -pub const LIBUSB_DT_SS_ENDPOINT_COMPANION_SIZE: u32 = 6; -pub const LIBUSB_DT_BOS_SIZE: u32 = 5; -pub const LIBUSB_DT_DEVICE_CAPABILITY_SIZE: u32 = 3; -pub const LIBUSB_BT_USB_2_0_EXTENSION_SIZE: u32 = 7; -pub const LIBUSB_BT_SS_USB_DEVICE_CAPABILITY_SIZE: u32 = 10; -pub const LIBUSB_BT_CONTAINER_ID_SIZE: u32 = 20; -pub const LIBUSB_DT_BOS_MAX_SIZE: u32 = 42; -pub const LIBUSB_ENDPOINT_ADDRESS_MASK: u32 = 15; -pub const LIBUSB_ENDPOINT_DIR_MASK: u32 = 128; -pub const LIBUSB_TRANSFER_TYPE_MASK: u32 = 3; -pub const LIBUSB_ISO_SYNC_TYPE_MASK: u32 = 12; -pub const LIBUSB_ISO_USAGE_TYPE_MASK: u32 = 48; -pub const LIBUSB_ERROR_COUNT: u32 = 14; -pub const LIBUSB_HOTPLUG_MATCH_ANY: i32 = -1; -pub type int_least8_t = ::std::os::raw::c_schar; -pub type int_least16_t = ::std::os::raw::c_short; -pub type int_least32_t = ::std::os::raw::c_int; -pub type int_least64_t = ::std::os::raw::c_long; -pub type uint_least8_t = ::std::os::raw::c_uchar; -pub type uint_least16_t = ::std::os::raw::c_ushort; -pub type uint_least32_t = ::std::os::raw::c_uint; -pub type uint_least64_t = ::std::os::raw::c_ulong; -pub type int_fast8_t = ::std::os::raw::c_schar; -pub type int_fast16_t = ::std::os::raw::c_long; -pub type int_fast32_t = ::std::os::raw::c_long; -pub type int_fast64_t = ::std::os::raw::c_long; -pub type uint_fast8_t = ::std::os::raw::c_uchar; -pub type uint_fast16_t = ::std::os::raw::c_ulong; -pub type uint_fast32_t = ::std::os::raw::c_ulong; -pub type uint_fast64_t = ::std::os::raw::c_ulong; -pub type intmax_t = ::std::os::raw::c_long; -pub type uintmax_t = ::std::os::raw::c_ulong; -pub type __u_char = ::std::os::raw::c_uchar; -pub type __u_short = ::std::os::raw::c_ushort; -pub type __u_int = ::std::os::raw::c_uint; -pub type __u_long = ::std::os::raw::c_ulong; -pub type __int8_t = ::std::os::raw::c_schar; -pub type __uint8_t = ::std::os::raw::c_uchar; -pub type __int16_t = ::std::os::raw::c_short; -pub type __uint16_t = ::std::os::raw::c_ushort; -pub type __int32_t = ::std::os::raw::c_int; -pub type __uint32_t = ::std::os::raw::c_uint; -pub type __int64_t = ::std::os::raw::c_long; -pub type __uint64_t = ::std::os::raw::c_ulong; -pub type __quad_t = ::std::os::raw::c_long; -pub type __u_quad_t = ::std::os::raw::c_ulong; -pub type __dev_t = ::std::os::raw::c_ulong; -pub type __uid_t = ::std::os::raw::c_uint; -pub type __gid_t = ::std::os::raw::c_uint; -pub type __ino_t = ::std::os::raw::c_ulong; -pub type __ino64_t = ::std::os::raw::c_ulong; -pub type __mode_t = ::std::os::raw::c_uint; -pub type __nlink_t = ::std::os::raw::c_ulong; -pub type __off_t = ::std::os::raw::c_long; -pub type __off64_t = ::std::os::raw::c_long; -pub type __pid_t = ::std::os::raw::c_int; -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct __fsid_t { - pub __val: [::std::os::raw::c_int; 2usize], -} -#[test] -fn bindgen_test_layout___fsid_t() { - assert_eq!( - ::std::mem::size_of::<__fsid_t>(), - 8usize, - concat!("Size of: ", stringify!(__fsid_t)) - ); - assert_eq!( - ::std::mem::align_of::<__fsid_t>(), - 4usize, - concat!("Alignment of ", stringify!(__fsid_t)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::<__fsid_t>())).__val as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(__fsid_t), - "::", - stringify!(__val) - ) - ); -} -pub type __clock_t = ::std::os::raw::c_long; -pub type __rlim_t = ::std::os::raw::c_ulong; -pub type __rlim64_t = ::std::os::raw::c_ulong; -pub type __id_t = ::std::os::raw::c_uint; -pub type __time_t = ::std::os::raw::c_long; -pub type __useconds_t = ::std::os::raw::c_uint; -pub type __suseconds_t = ::std::os::raw::c_long; -pub type __daddr_t = ::std::os::raw::c_int; -pub type __key_t = ::std::os::raw::c_int; -pub type __clockid_t = ::std::os::raw::c_int; -pub type __timer_t = *mut ::std::os::raw::c_void; -pub type __blksize_t = ::std::os::raw::c_long; -pub type __blkcnt_t = ::std::os::raw::c_long; -pub type __blkcnt64_t = ::std::os::raw::c_long; -pub type __fsblkcnt_t = ::std::os::raw::c_ulong; -pub type __fsblkcnt64_t = ::std::os::raw::c_ulong; -pub type __fsfilcnt_t = ::std::os::raw::c_ulong; -pub type __fsfilcnt64_t = ::std::os::raw::c_ulong; -pub type __fsword_t = ::std::os::raw::c_long; -pub type __ssize_t = ::std::os::raw::c_long; -pub type __syscall_slong_t = ::std::os::raw::c_long; -pub type __syscall_ulong_t = ::std::os::raw::c_ulong; -pub type __loff_t = __off64_t; -pub type __qaddr_t = *mut __quad_t; -pub type __caddr_t = *mut ::std::os::raw::c_char; -pub type __intptr_t = ::std::os::raw::c_long; -pub type __socklen_t = ::std::os::raw::c_uint; -pub type u_char = __u_char; -pub type u_short = __u_short; -pub type u_int = __u_int; -pub type u_long = __u_long; -pub type quad_t = __quad_t; -pub type u_quad_t = __u_quad_t; -pub type fsid_t = __fsid_t; -pub type loff_t = __loff_t; -pub type ino_t = __ino_t; -pub type dev_t = __dev_t; -pub type gid_t = __gid_t; -pub type mode_t = __mode_t; -pub type nlink_t = __nlink_t; -pub type uid_t = __uid_t; -pub type off_t = __off_t; -pub type pid_t = __pid_t; -pub type id_t = __id_t; -pub type daddr_t = __daddr_t; -pub type caddr_t = __caddr_t; -pub type key_t = __key_t; -pub type clock_t = __clock_t; -pub type time_t = __time_t; -pub type clockid_t = __clockid_t; -pub type timer_t = __timer_t; -pub type ulong = ::std::os::raw::c_ulong; -pub type ushort = ::std::os::raw::c_ushort; -pub type uint = ::std::os::raw::c_uint; -pub type u_int8_t = ::std::os::raw::c_uchar; -pub type u_int16_t = ::std::os::raw::c_ushort; -pub type u_int32_t = ::std::os::raw::c_uint; -pub type u_int64_t = ::std::os::raw::c_ulong; -pub type register_t = ::std::os::raw::c_long; -pub type __sig_atomic_t = ::std::os::raw::c_int; -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct __sigset_t { - pub __val: [::std::os::raw::c_ulong; 16usize], -} -#[test] -fn bindgen_test_layout___sigset_t() { - assert_eq!( - ::std::mem::size_of::<__sigset_t>(), - 128usize, - concat!("Size of: ", stringify!(__sigset_t)) - ); - assert_eq!( - ::std::mem::align_of::<__sigset_t>(), - 8usize, - concat!("Alignment of ", stringify!(__sigset_t)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::<__sigset_t>())).__val as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(__sigset_t), - "::", - stringify!(__val) - ) - ); -} -pub type sigset_t = __sigset_t; -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct timespec { - pub tv_sec: __time_t, - pub tv_nsec: __syscall_slong_t, -} -#[test] -fn bindgen_test_layout_timespec() { - assert_eq!( - ::std::mem::size_of::<timespec>(), - 16usize, - concat!("Size of: ", stringify!(timespec)) - ); - assert_eq!( - ::std::mem::align_of::<timespec>(), - 8usize, - concat!("Alignment of ", stringify!(timespec)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::<timespec>())).tv_sec as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(timespec), - "::", - stringify!(tv_sec) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::<timespec>())).tv_nsec as *const _ as usize }, - 8usize, - concat!( - "Offset of field: ", - stringify!(timespec), - "::", - stringify!(tv_nsec) - ) - ); -} -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct timeval { - pub tv_sec: __time_t, - pub tv_usec: __suseconds_t, -} -#[test] -fn bindgen_test_layout_timeval() { - assert_eq!( - ::std::mem::size_of::<timeval>(), - 16usize, - concat!("Size of: ", stringify!(timeval)) - ); - assert_eq!( - ::std::mem::align_of::<timeval>(), - 8usize, - concat!("Alignment of ", stringify!(timeval)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::<timeval>())).tv_sec as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(timeval), - "::", - stringify!(tv_sec) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::<timeval>())).tv_usec as *const _ as usize }, - 8usize, - concat!( - "Offset of field: ", - stringify!(timeval), - "::", - stringify!(tv_usec) - ) - ); -} -pub type suseconds_t = __suseconds_t; -pub type __fd_mask = ::std::os::raw::c_long; -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct fd_set { - pub __fds_bits: [__fd_mask; 16usize], -} -#[test] -fn bindgen_test_layout_fd_set() { - assert_eq!( - ::std::mem::size_of::<fd_set>(), - 128usize, - concat!("Size of: ", stringify!(fd_set)) - ); - assert_eq!( - ::std::mem::align_of::<fd_set>(), - 8usize, - concat!("Alignment of ", stringify!(fd_set)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::<fd_set>())).__fds_bits as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(fd_set), - "::", - stringify!(__fds_bits) - ) - ); -} -pub type fd_mask = __fd_mask; -extern "C" { - pub fn select( - __nfds: ::std::os::raw::c_int, - __readfds: *mut fd_set, - __writefds: *mut fd_set, - __exceptfds: *mut fd_set, - __timeout: *mut timeval, - ) -> ::std::os::raw::c_int; -} -extern "C" { - pub fn pselect( - __nfds: ::std::os::raw::c_int, - __readfds: *mut fd_set, - __writefds: *mut fd_set, - __exceptfds: *mut fd_set, - __timeout: *const timespec, - __sigmask: *const __sigset_t, - ) -> ::std::os::raw::c_int; -} -extern "C" { - pub fn gnu_dev_major(__dev: ::std::os::raw::c_ulonglong) -> ::std::os::raw::c_uint; -} -extern "C" { - pub fn gnu_dev_minor(__dev: ::std::os::raw::c_ulonglong) -> ::std::os::raw::c_uint; -} -extern "C" { - pub fn gnu_dev_makedev( - __major: ::std::os::raw::c_uint, - __minor: ::std::os::raw::c_uint, - ) -> ::std::os::raw::c_ulonglong; -} -pub type blksize_t = __blksize_t; -pub type blkcnt_t = __blkcnt_t; -pub type fsblkcnt_t = __fsblkcnt_t; -pub type fsfilcnt_t = __fsfilcnt_t; -pub type pthread_t = ::std::os::raw::c_ulong; -#[repr(C)] -#[derive(Copy, Clone)] -pub union pthread_attr_t { - pub __size: [::std::os::raw::c_char; 56usize], - pub __align: ::std::os::raw::c_long, - _bindgen_union_align: [u64; 7usize], -} -#[test] -fn bindgen_test_layout_pthread_attr_t() { - assert_eq!( - ::std::mem::size_of::<pthread_attr_t>(), - 56usize, - concat!("Size of: ", stringify!(pthread_attr_t)) - ); - assert_eq!( - ::std::mem::align_of::<pthread_attr_t>(), - 8usize, - concat!("Alignment of ", stringify!(pthread_attr_t)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::<pthread_attr_t>())).__size as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(pthread_attr_t), - "::", - stringify!(__size) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::<pthread_attr_t>())).__align as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(pthread_attr_t), - "::", - stringify!(__align) - ) - ); -} -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct __pthread_internal_list { - pub __prev: *mut __pthread_internal_list, - pub __next: *mut __pthread_internal_list, -} -#[test] -fn bindgen_test_layout___pthread_internal_list() { - assert_eq!( - ::std::mem::size_of::<__pthread_internal_list>(), - 16usize, - concat!("Size of: ", stringify!(__pthread_internal_list)) - ); - assert_eq!( - ::std::mem::align_of::<__pthread_internal_list>(), - 8usize, - concat!("Alignment of ", stringify!(__pthread_internal_list)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::<__pthread_internal_list>())).__prev as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(__pthread_internal_list), - "::", - stringify!(__prev) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::<__pthread_internal_list>())).__next as *const _ as usize }, - 8usize, - concat!( - "Offset of field: ", - stringify!(__pthread_internal_list), - "::", - stringify!(__next) - ) - ); -} -pub type __pthread_list_t = __pthread_internal_list; -#[repr(C)] -#[derive(Copy, Clone)] -pub union pthread_mutex_t { - pub __data: pthread_mutex_t___pthread_mutex_s, - pub __size: [::std::os::raw::c_char; 40usize], - pub __align: ::std::os::raw::c_long, - _bindgen_union_align: [u64; 5usize], -} -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct pthread_mutex_t___pthread_mutex_s { - pub __lock: ::std::os::raw::c_int, - pub __count: ::std::os::raw::c_uint, - pub __owner: ::std::os::raw::c_int, - pub __nusers: ::std::os::raw::c_uint, - pub __kind: ::std::os::raw::c_int, - pub __spins: ::std::os::raw::c_short, - pub __elision: ::std::os::raw::c_short, - pub __list: __pthread_list_t, -} -#[test] -fn bindgen_test_layout_pthread_mutex_t___pthread_mutex_s() { - assert_eq!( - ::std::mem::size_of::<pthread_mutex_t___pthread_mutex_s>(), - 40usize, - concat!("Size of: ", stringify!(pthread_mutex_t___pthread_mutex_s)) - ); - assert_eq!( - ::std::mem::align_of::<pthread_mutex_t___pthread_mutex_s>(), - 8usize, - concat!( - "Alignment of ", - stringify!(pthread_mutex_t___pthread_mutex_s) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::<pthread_mutex_t___pthread_mutex_s>())).__lock as *const _ - as usize - }, - 0usize, - concat!( - "Offset of field: ", - stringify!(pthread_mutex_t___pthread_mutex_s), - "::", - stringify!(__lock) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::<pthread_mutex_t___pthread_mutex_s>())).__count as *const _ - as usize - }, - 4usize, - concat!( - "Offset of field: ", - stringify!(pthread_mutex_t___pthread_mutex_s), - "::", - stringify!(__count) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::<pthread_mutex_t___pthread_mutex_s>())).__owner as *const _ - as usize - }, - 8usize, - concat!( - "Offset of field: ", - stringify!(pthread_mutex_t___pthread_mutex_s), - "::", - stringify!(__owner) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::<pthread_mutex_t___pthread_mutex_s>())).__nusers as *const _ - as usize - }, - 12usize, - concat!( - "Offset of field: ", - stringify!(pthread_mutex_t___pthread_mutex_s), - "::", - stringify!(__nusers) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::<pthread_mutex_t___pthread_mutex_s>())).__kind as *const _ - as usize - }, - 16usize, - concat!( - "Offset of field: ", - stringify!(pthread_mutex_t___pthread_mutex_s), - "::", - stringify!(__kind) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::<pthread_mutex_t___pthread_mutex_s>())).__spins as *const _ - as usize - }, - 20usize, - concat!( - "Offset of field: ", - stringify!(pthread_mutex_t___pthread_mutex_s), - "::", - stringify!(__spins) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::<pthread_mutex_t___pthread_mutex_s>())).__elision as *const _ - as usize - }, - 22usize, - concat!( - "Offset of field: ", - stringify!(pthread_mutex_t___pthread_mutex_s), - "::", - stringify!(__elision) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::<pthread_mutex_t___pthread_mutex_s>())).__list as *const _ - as usize - }, - 24usize, - concat!( - "Offset of field: ", - stringify!(pthread_mutex_t___pthread_mutex_s), - "::", - stringify!(__list) - ) - ); -} -#[test] -fn bindgen_test_layout_pthread_mutex_t() { - assert_eq!( - ::std::mem::size_of::<pthread_mutex_t>(), - 40usize, - concat!("Size of: ", stringify!(pthread_mutex_t)) - ); - assert_eq!( - ::std::mem::align_of::<pthread_mutex_t>(), - 8usize, - concat!("Alignment of ", stringify!(pthread_mutex_t)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::<pthread_mutex_t>())).__data as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(pthread_mutex_t), - "::", - stringify!(__data) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::<pthread_mutex_t>())).__size as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(pthread_mutex_t), - "::", - stringify!(__size) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::<pthread_mutex_t>())).__align as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(pthread_mutex_t), - "::", - stringify!(__align) - ) - ); -} -#[repr(C)] -#[derive(Copy, Clone)] -pub union pthread_mutexattr_t { - pub __size: [::std::os::raw::c_char; 4usize], - pub __align: ::std::os::raw::c_int, - _bindgen_union_align: u32, -} -#[test] -fn bindgen_test_layout_pthread_mutexattr_t() { - assert_eq!( - ::std::mem::size_of::<pthread_mutexattr_t>(), - 4usize, - concat!("Size of: ", stringify!(pthread_mutexattr_t)) - ); - assert_eq!( - ::std::mem::align_of::<pthread_mutexattr_t>(), - 4usize, - concat!("Alignment of ", stringify!(pthread_mutexattr_t)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::<pthread_mutexattr_t>())).__size as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(pthread_mutexattr_t), - "::", - stringify!(__size) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::<pthread_mutexattr_t>())).__align as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(pthread_mutexattr_t), - "::", - stringify!(__align) - ) - ); -} -#[repr(C)] -#[derive(Copy, Clone)] -pub union pthread_cond_t { - pub __data: pthread_cond_t__bindgen_ty_1, - pub __size: [::std::os::raw::c_char; 48usize], - pub __align: ::std::os::raw::c_longlong, - _bindgen_union_align: [u64; 6usize], -} -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct pthread_cond_t__bindgen_ty_1 { - pub __lock: ::std::os::raw::c_int, - pub __futex: ::std::os::raw::c_uint, - pub __total_seq: ::std::os::raw::c_ulonglong, - pub __wakeup_seq: ::std::os::raw::c_ulonglong, - pub __woken_seq: ::std::os::raw::c_ulonglong, - pub __mutex: *mut ::std::os::raw::c_void, - pub __nwaiters: ::std::os::raw::c_uint, - pub __broadcast_seq: ::std::os::raw::c_uint, -} -#[test] -fn bindgen_test_layout_pthread_cond_t__bindgen_ty_1() { - assert_eq!( - ::std::mem::size_of::<pthread_cond_t__bindgen_ty_1>(), - 48usize, - concat!("Size of: ", stringify!(pthread_cond_t__bindgen_ty_1)) - ); - assert_eq!( - ::std::mem::align_of::<pthread_cond_t__bindgen_ty_1>(), - 8usize, - concat!("Alignment of ", stringify!(pthread_cond_t__bindgen_ty_1)) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::<pthread_cond_t__bindgen_ty_1>())).__lock as *const _ as usize - }, - 0usize, - concat!( - "Offset of field: ", - stringify!(pthread_cond_t__bindgen_ty_1), - "::", - stringify!(__lock) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::<pthread_cond_t__bindgen_ty_1>())).__futex as *const _ as usize - }, - 4usize, - concat!( - "Offset of field: ", - stringify!(pthread_cond_t__bindgen_ty_1), - "::", - stringify!(__futex) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::<pthread_cond_t__bindgen_ty_1>())).__total_seq as *const _ - as usize - }, - 8usize, - concat!( - "Offset of field: ", - stringify!(pthread_cond_t__bindgen_ty_1), - "::", - stringify!(__total_seq) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::<pthread_cond_t__bindgen_ty_1>())).__wakeup_seq as *const _ - as usize - }, - 16usize, - concat!( - "Offset of field: ", - stringify!(pthread_cond_t__bindgen_ty_1), - "::", - stringify!(__wakeup_seq) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::<pthread_cond_t__bindgen_ty_1>())).__woken_seq as *const _ - as usize - }, - 24usize, - concat!( - "Offset of field: ", - stringify!(pthread_cond_t__bindgen_ty_1), - "::", - stringify!(__woken_seq) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::<pthread_cond_t__bindgen_ty_1>())).__mutex as *const _ as usize - }, - 32usize, - concat!( - "Offset of field: ", - stringify!(pthread_cond_t__bindgen_ty_1), - "::", - stringify!(__mutex) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::<pthread_cond_t__bindgen_ty_1>())).__nwaiters as *const _ as usize - }, - 40usize, - concat!( - "Offset of field: ", - stringify!(pthread_cond_t__bindgen_ty_1), - "::", - stringify!(__nwaiters) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::<pthread_cond_t__bindgen_ty_1>())).__broadcast_seq as *const _ - as usize - }, - 44usize, - concat!( - "Offset of field: ", - stringify!(pthread_cond_t__bindgen_ty_1), - "::", - stringify!(__broadcast_seq) - ) - ); -} -#[test] -fn bindgen_test_layout_pthread_cond_t() { - assert_eq!( - ::std::mem::size_of::<pthread_cond_t>(), - 48usize, - concat!("Size of: ", stringify!(pthread_cond_t)) - ); - assert_eq!( - ::std::mem::align_of::<pthread_cond_t>(), - 8usize, - concat!("Alignment of ", stringify!(pthread_cond_t)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::<pthread_cond_t>())).__data as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(pthread_cond_t), - "::", - stringify!(__data) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::<pthread_cond_t>())).__size as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(pthread_cond_t), - "::", - stringify!(__size) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::<pthread_cond_t>())).__align as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(pthread_cond_t), - "::", - stringify!(__align) - ) - ); -} -#[repr(C)] -#[derive(Copy, Clone)] -pub union pthread_condattr_t { - pub __size: [::std::os::raw::c_char; 4usize], - pub __align: ::std::os::raw::c_int, - _bindgen_union_align: u32, -} -#[test] -fn bindgen_test_layout_pthread_condattr_t() { - assert_eq!( - ::std::mem::size_of::<pthread_condattr_t>(), - 4usize, - concat!("Size of: ", stringify!(pthread_condattr_t)) - ); - assert_eq!( - ::std::mem::align_of::<pthread_condattr_t>(), - 4usize, - concat!("Alignment of ", stringify!(pthread_condattr_t)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::<pthread_condattr_t>())).__size as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(pthread_condattr_t), - "::", - stringify!(__size) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::<pthread_condattr_t>())).__align as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(pthread_condattr_t), - "::", - stringify!(__align) - ) - ); -} -pub type pthread_key_t = ::std::os::raw::c_uint; -pub type pthread_once_t = ::std::os::raw::c_int; -#[repr(C)] -#[derive(Copy, Clone)] -pub union pthread_rwlock_t { - pub __data: pthread_rwlock_t__bindgen_ty_1, - pub __size: [::std::os::raw::c_char; 56usize], - pub __align: ::std::os::raw::c_long, - _bindgen_union_align: [u64; 7usize], -} -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct pthread_rwlock_t__bindgen_ty_1 { - pub __lock: ::std::os::raw::c_int, - pub __nr_readers: ::std::os::raw::c_uint, - pub __readers_wakeup: ::std::os::raw::c_uint, - pub __writer_wakeup: ::std::os::raw::c_uint, - pub __nr_readers_queued: ::std::os::raw::c_uint, - pub __nr_writers_queued: ::std::os::raw::c_uint, - pub __writer: ::std::os::raw::c_int, - pub __shared: ::std::os::raw::c_int, - pub __rwelision: ::std::os::raw::c_schar, - pub __pad1: [::std::os::raw::c_uchar; 7usize], - pub __pad2: ::std::os::raw::c_ulong, - pub __flags: ::std::os::raw::c_uint, -} -#[test] -fn bindgen_test_layout_pthread_rwlock_t__bindgen_ty_1() { - assert_eq!( - ::std::mem::size_of::<pthread_rwlock_t__bindgen_ty_1>(), - 56usize, - concat!("Size of: ", stringify!(pthread_rwlock_t__bindgen_ty_1)) - ); - assert_eq!( - ::std::mem::align_of::<pthread_rwlock_t__bindgen_ty_1>(), - 8usize, - concat!("Alignment of ", stringify!(pthread_rwlock_t__bindgen_ty_1)) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::<pthread_rwlock_t__bindgen_ty_1>())).__lock as *const _ as usize - }, - 0usize, - concat!( - "Offset of field: ", - stringify!(pthread_rwlock_t__bindgen_ty_1), - "::", - stringify!(__lock) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::<pthread_rwlock_t__bindgen_ty_1>())).__nr_readers as *const _ - as usize - }, - 4usize, - concat!( - "Offset of field: ", - stringify!(pthread_rwlock_t__bindgen_ty_1), - "::", - stringify!(__nr_readers) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::<pthread_rwlock_t__bindgen_ty_1>())).__readers_wakeup as *const _ - as usize - }, - 8usize, - concat!( - "Offset of field: ", - stringify!(pthread_rwlock_t__bindgen_ty_1), - "::", - stringify!(__readers_wakeup) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::<pthread_rwlock_t__bindgen_ty_1>())).__writer_wakeup as *const _ - as usize - }, - 12usize, - concat!( - "Offset of field: ", - stringify!(pthread_rwlock_t__bindgen_ty_1), - "::", - stringify!(__writer_wakeup) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::<pthread_rwlock_t__bindgen_ty_1>())).__nr_readers_queued - as *const _ as usize - }, - 16usize, - concat!( - "Offset of field: ", - stringify!(pthread_rwlock_t__bindgen_ty_1), - "::", - stringify!(__nr_readers_queued) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::<pthread_rwlock_t__bindgen_ty_1>())).__nr_writers_queued - as *const _ as usize - }, - 20usize, - concat!( - "Offset of field: ", - stringify!(pthread_rwlock_t__bindgen_ty_1), - "::", - stringify!(__nr_writers_queued) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::<pthread_rwlock_t__bindgen_ty_1>())).__writer as *const _ as usize - }, - 24usize, - concat!( - "Offset of field: ", - stringify!(pthread_rwlock_t__bindgen_ty_1), - "::", - stringify!(__writer) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::<pthread_rwlock_t__bindgen_ty_1>())).__shared as *const _ as usize - }, - 28usize, - concat!( - "Offset of field: ", - stringify!(pthread_rwlock_t__bindgen_ty_1), - "::", - stringify!(__shared) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::<pthread_rwlock_t__bindgen_ty_1>())).__rwelision as *const _ - as usize - }, - 32usize, - concat!( - "Offset of field: ", - stringify!(pthread_rwlock_t__bindgen_ty_1), - "::", - stringify!(__rwelision) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::<pthread_rwlock_t__bindgen_ty_1>())).__pad1 as *const _ as usize - }, - 33usize, - concat!( - "Offset of field: ", - stringify!(pthread_rwlock_t__bindgen_ty_1), - "::", - stringify!(__pad1) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::<pthread_rwlock_t__bindgen_ty_1>())).__pad2 as *const _ as usize - }, - 40usize, - concat!( - "Offset of field: ", - stringify!(pthread_rwlock_t__bindgen_ty_1), - "::", - stringify!(__pad2) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::<pthread_rwlock_t__bindgen_ty_1>())).__flags as *const _ as usize - }, - 48usize, - concat!( - "Offset of field: ", - stringify!(pthread_rwlock_t__bindgen_ty_1), - "::", - stringify!(__flags) - ) - ); -} -#[test] -fn bindgen_test_layout_pthread_rwlock_t() { - assert_eq!( - ::std::mem::size_of::<pthread_rwlock_t>(), - 56usize, - concat!("Size of: ", stringify!(pthread_rwlock_t)) - ); - assert_eq!( - ::std::mem::align_of::<pthread_rwlock_t>(), - 8usize, - concat!("Alignment of ", stringify!(pthread_rwlock_t)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::<pthread_rwlock_t>())).__data as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(pthread_rwlock_t), - "::", - stringify!(__data) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::<pthread_rwlock_t>())).__size as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(pthread_rwlock_t), - "::", - stringify!(__size) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::<pthread_rwlock_t>())).__align as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(pthread_rwlock_t), - "::", - stringify!(__align) - ) - ); -} -#[repr(C)] -#[derive(Copy, Clone)] -pub union pthread_rwlockattr_t { - pub __size: [::std::os::raw::c_char; 8usize], - pub __align: ::std::os::raw::c_long, - _bindgen_union_align: u64, -} -#[test] -fn bindgen_test_layout_pthread_rwlockattr_t() { - assert_eq!( - ::std::mem::size_of::<pthread_rwlockattr_t>(), - 8usize, - concat!("Size of: ", stringify!(pthread_rwlockattr_t)) - ); - assert_eq!( - ::std::mem::align_of::<pthread_rwlockattr_t>(), - 8usize, - concat!("Alignment of ", stringify!(pthread_rwlockattr_t)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::<pthread_rwlockattr_t>())).__size as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(pthread_rwlockattr_t), - "::", - stringify!(__size) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::<pthread_rwlockattr_t>())).__align as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(pthread_rwlockattr_t), - "::", - stringify!(__align) - ) - ); -} -pub type pthread_spinlock_t = ::std::os::raw::c_int; -#[repr(C)] -#[derive(Copy, Clone)] -pub union pthread_barrier_t { - pub __size: [::std::os::raw::c_char; 32usize], - pub __align: ::std::os::raw::c_long, - _bindgen_union_align: [u64; 4usize], -} -#[test] -fn bindgen_test_layout_pthread_barrier_t() { - assert_eq!( - ::std::mem::size_of::<pthread_barrier_t>(), - 32usize, - concat!("Size of: ", stringify!(pthread_barrier_t)) - ); - assert_eq!( - ::std::mem::align_of::<pthread_barrier_t>(), - 8usize, - concat!("Alignment of ", stringify!(pthread_barrier_t)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::<pthread_barrier_t>())).__size as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(pthread_barrier_t), - "::", - stringify!(__size) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::<pthread_barrier_t>())).__align as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(pthread_barrier_t), - "::", - stringify!(__align) - ) - ); -} -#[repr(C)] -#[derive(Copy, Clone)] -pub union pthread_barrierattr_t { - pub __size: [::std::os::raw::c_char; 4usize], - pub __align: ::std::os::raw::c_int, - _bindgen_union_align: u32, -} -#[test] -fn bindgen_test_layout_pthread_barrierattr_t() { - assert_eq!( - ::std::mem::size_of::<pthread_barrierattr_t>(), - 4usize, - concat!("Size of: ", stringify!(pthread_barrierattr_t)) - ); - assert_eq!( - ::std::mem::align_of::<pthread_barrierattr_t>(), - 4usize, - concat!("Alignment of ", stringify!(pthread_barrierattr_t)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::<pthread_barrierattr_t>())).__size as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(pthread_barrierattr_t), - "::", - stringify!(__size) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::<pthread_barrierattr_t>())).__align as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(pthread_barrierattr_t), - "::", - stringify!(__align) - ) - ); -} -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct timezone { - pub tz_minuteswest: ::std::os::raw::c_int, - pub tz_dsttime: ::std::os::raw::c_int, -} -#[test] -fn bindgen_test_layout_timezone() { - assert_eq!( - ::std::mem::size_of::<timezone>(), - 8usize, - concat!("Size of: ", stringify!(timezone)) - ); - assert_eq!( - ::std::mem::align_of::<timezone>(), - 4usize, - concat!("Alignment of ", stringify!(timezone)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::<timezone>())).tz_minuteswest as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(timezone), - "::", - stringify!(tz_minuteswest) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::<timezone>())).tz_dsttime as *const _ as usize }, - 4usize, - concat!( - "Offset of field: ", - stringify!(timezone), - "::", - stringify!(tz_dsttime) - ) - ); -} -pub type __timezone_ptr_t = *mut timezone; -extern "C" { - pub fn gettimeofday(__tv: *mut timeval, __tz: __timezone_ptr_t) -> ::std::os::raw::c_int; -} -extern "C" { - pub fn settimeofday(__tv: *const timeval, __tz: *const timezone) -> ::std::os::raw::c_int; -} -extern "C" { - pub fn adjtime(__delta: *const timeval, __olddelta: *mut timeval) -> ::std::os::raw::c_int; -} -pub const ITIMER_REAL: __itimer_which = 0; -pub const ITIMER_VIRTUAL: __itimer_which = 1; -pub const ITIMER_PROF: __itimer_which = 2; -pub type __itimer_which = u32; -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct itimerval { - pub it_interval: timeval, - pub it_value: timeval, -} -#[test] -fn bindgen_test_layout_itimerval() { - assert_eq!( - ::std::mem::size_of::<itimerval>(), - 32usize, - concat!("Size of: ", stringify!(itimerval)) - ); - assert_eq!( - ::std::mem::align_of::<itimerval>(), - 8usize, - concat!("Alignment of ", stringify!(itimerval)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::<itimerval>())).it_interval as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(itimerval), - "::", - stringify!(it_interval) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::<itimerval>())).it_value as *const _ as usize }, - 16usize, - concat!( - "Offset of field: ", - stringify!(itimerval), - "::", - stringify!(it_value) - ) - ); -} -pub type __itimer_which_t = ::std::os::raw::c_int; -extern "C" { - pub fn getitimer(__which: __itimer_which_t, __value: *mut itimerval) -> ::std::os::raw::c_int; -} -extern "C" { - pub fn setitimer( - __which: __itimer_which_t, - __new: *const itimerval, - __old: *mut itimerval, - ) -> ::std::os::raw::c_int; -} -extern "C" { - pub fn utimes( - __file: *const ::std::os::raw::c_char, - __tvp: *const timeval, - ) -> ::std::os::raw::c_int; -} -extern "C" { - pub fn lutimes( - __file: *const ::std::os::raw::c_char, - __tvp: *const timeval, - ) -> ::std::os::raw::c_int; -} -extern "C" { - pub fn futimes(__fd: ::std::os::raw::c_int, __tvp: *const timeval) -> ::std::os::raw::c_int; -} -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct tm { - pub tm_sec: ::std::os::raw::c_int, - pub tm_min: ::std::os::raw::c_int, - pub tm_hour: ::std::os::raw::c_int, - pub tm_mday: ::std::os::raw::c_int, - pub tm_mon: ::std::os::raw::c_int, - pub tm_year: ::std::os::raw::c_int, - pub tm_wday: ::std::os::raw::c_int, - pub tm_yday: ::std::os::raw::c_int, - pub tm_isdst: ::std::os::raw::c_int, - pub tm_gmtoff: ::std::os::raw::c_long, - pub tm_zone: *const ::std::os::raw::c_char, -} -#[test] -fn bindgen_test_layout_tm() { - assert_eq!( - ::std::mem::size_of::<tm>(), - 56usize, - concat!("Size of: ", stringify!(tm)) - ); - assert_eq!( - ::std::mem::align_of::<tm>(), - 8usize, - concat!("Alignment of ", stringify!(tm)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::<tm>())).tm_sec as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(tm), - "::", - stringify!(tm_sec) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::<tm>())).tm_min as *const _ as usize }, - 4usize, - concat!( - "Offset of field: ", - stringify!(tm), - "::", - stringify!(tm_min) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::<tm>())).tm_hour as *const _ as usize }, - 8usize, - concat!( - "Offset of field: ", - stringify!(tm), - "::", - stringify!(tm_hour) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::<tm>())).tm_mday as *const _ as usize }, - 12usize, - concat!( - "Offset of field: ", - stringify!(tm), - "::", - stringify!(tm_mday) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::<tm>())).tm_mon as *const _ as usize }, - 16usize, - concat!( - "Offset of field: ", - stringify!(tm), - "::", - stringify!(tm_mon) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::<tm>())).tm_year as *const _ as usize }, - 20usize, - concat!( - "Offset of field: ", - stringify!(tm), - "::", - stringify!(tm_year) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::<tm>())).tm_wday as *const _ as usize }, - 24usize, - concat!( - "Offset of field: ", - stringify!(tm), - "::", - stringify!(tm_wday) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::<tm>())).tm_yday as *const _ as usize }, - 28usize, - concat!( - "Offset of field: ", - stringify!(tm), - "::", - stringify!(tm_yday) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::<tm>())).tm_isdst as *const _ as usize }, - 32usize, - concat!( - "Offset of field: ", - stringify!(tm), - "::", - stringify!(tm_isdst) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::<tm>())).tm_gmtoff as *const _ as usize }, - 40usize, - concat!( - "Offset of field: ", - stringify!(tm), - "::", - stringify!(tm_gmtoff) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::<tm>())).tm_zone as *const _ as usize }, - 48usize, - concat!( - "Offset of field: ", - stringify!(tm), - "::", - stringify!(tm_zone) - ) - ); -} -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct itimerspec { - pub it_interval: timespec, - pub it_value: timespec, -} -#[test] -fn bindgen_test_layout_itimerspec() { - assert_eq!( - ::std::mem::size_of::<itimerspec>(), - 32usize, - concat!("Size of: ", stringify!(itimerspec)) - ); - assert_eq!( - ::std::mem::align_of::<itimerspec>(), - 8usize, - concat!("Alignment of ", stringify!(itimerspec)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::<itimerspec>())).it_interval as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(itimerspec), - "::", - stringify!(it_interval) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::<itimerspec>())).it_value as *const _ as usize }, - 16usize, - concat!( - "Offset of field: ", - stringify!(itimerspec), - "::", - stringify!(it_value) - ) - ); -} -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct sigevent { - _unused: [u8; 0], -} -extern "C" { - pub fn clock() -> clock_t; -} -extern "C" { - pub fn time(__timer: *mut time_t) -> time_t; -} -extern "C" { - pub fn difftime(__time1: time_t, __time0: time_t) -> f64; -} -extern "C" { - pub fn mktime(__tp: *mut tm) -> time_t; -} -extern "C" { - pub fn strftime( - __s: *mut ::std::os::raw::c_char, - __maxsize: usize, - __format: *const ::std::os::raw::c_char, - __tp: *const tm, - ) -> usize; -} -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct __locale_struct { - pub __locales: [*mut __locale_data; 13usize], - pub __ctype_b: *const ::std::os::raw::c_ushort, - pub __ctype_tolower: *const ::std::os::raw::c_int, - pub __ctype_toupper: *const ::std::os::raw::c_int, - pub __names: [*const ::std::os::raw::c_char; 13usize], -} -#[test] -fn bindgen_test_layout___locale_struct() { - assert_eq!( - ::std::mem::size_of::<__locale_struct>(), - 232usize, - concat!("Size of: ", stringify!(__locale_struct)) - ); - assert_eq!( - ::std::mem::align_of::<__locale_struct>(), - 8usize, - concat!("Alignment of ", stringify!(__locale_struct)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::<__locale_struct>())).__locales as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(__locale_struct), - "::", - stringify!(__locales) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::<__locale_struct>())).__ctype_b as *const _ as usize }, - 104usize, - concat!( - "Offset of field: ", - stringify!(__locale_struct), - "::", - stringify!(__ctype_b) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::<__locale_struct>())).__ctype_tolower as *const _ as usize }, - 112usize, - concat!( - "Offset of field: ", - stringify!(__locale_struct), - "::", - stringify!(__ctype_tolower) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::<__locale_struct>())).__ctype_toupper as *const _ as usize }, - 120usize, - concat!( - "Offset of field: ", - stringify!(__locale_struct), - "::", - stringify!(__ctype_toupper) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::<__locale_struct>())).__names as *const _ as usize }, - 128usize, - concat!( - "Offset of field: ", - stringify!(__locale_struct), - "::", - stringify!(__names) - ) - ); -} -pub type __locale_t = *mut __locale_struct; -pub type locale_t = __locale_t; -extern "C" { - pub fn strftime_l( - __s: *mut ::std::os::raw::c_char, - __maxsize: usize, - __format: *const ::std::os::raw::c_char, - __tp: *const tm, - __loc: __locale_t, - ) -> usize; -} -extern "C" { - pub fn gmtime(__timer: *const time_t) -> *mut tm; -} -extern "C" { - pub fn localtime(__timer: *const time_t) -> *mut tm; -} -extern "C" { - pub fn gmtime_r(__timer: *const time_t, __tp: *mut tm) -> *mut tm; -} -extern "C" { - pub fn localtime_r(__timer: *const time_t, __tp: *mut tm) -> *mut tm; -} -extern "C" { - pub fn asctime(__tp: *const tm) -> *mut ::std::os::raw::c_char; -} -extern "C" { - pub fn ctime(__timer: *const time_t) -> *mut ::std::os::raw::c_char; -} -extern "C" { - pub fn asctime_r( - __tp: *const tm, - __buf: *mut ::std::os::raw::c_char, - ) -> *mut ::std::os::raw::c_char; -} -extern "C" { - pub fn ctime_r( - __timer: *const time_t, - __buf: *mut ::std::os::raw::c_char, - ) -> *mut ::std::os::raw::c_char; -} -extern "C" { - #[link_name = "\u{1}__tzname"] - pub static mut __tzname: [*mut ::std::os::raw::c_char; 2usize]; -} -extern "C" { - #[link_name = "\u{1}__daylight"] - pub static mut __daylight: ::std::os::raw::c_int; -} -extern "C" { - #[link_name = "\u{1}__timezone"] - pub static mut __timezone: ::std::os::raw::c_long; -} -extern "C" { - #[link_name = "\u{1}tzname"] - pub static mut tzname: [*mut ::std::os::raw::c_char; 2usize]; -} -extern "C" { - pub fn tzset(); -} -extern "C" { - #[link_name = "\u{1}daylight"] - pub static mut daylight: ::std::os::raw::c_int; -} -extern "C" { - #[link_name = "\u{1}timezone"] - pub static mut timezone: ::std::os::raw::c_long; -} -extern "C" { - pub fn stime(__when: *const time_t) -> ::std::os::raw::c_int; -} -extern "C" { - pub fn timegm(__tp: *mut tm) -> time_t; -} -extern "C" { - pub fn timelocal(__tp: *mut tm) -> time_t; -} -extern "C" { - pub fn dysize(__year: ::std::os::raw::c_int) -> ::std::os::raw::c_int; -} -extern "C" { - pub fn nanosleep( - __requested_time: *const timespec, - __remaining: *mut timespec, - ) -> ::std::os::raw::c_int; -} -extern "C" { - pub fn clock_getres(__clock_id: clockid_t, __res: *mut timespec) -> ::std::os::raw::c_int; -} -extern "C" { - pub fn clock_gettime(__clock_id: clockid_t, __tp: *mut timespec) -> ::std::os::raw::c_int; -} -extern "C" { - pub fn clock_settime(__clock_id: clockid_t, __tp: *const timespec) -> ::std::os::raw::c_int; -} -extern "C" { - pub fn clock_nanosleep( - __clock_id: clockid_t, - __flags: ::std::os::raw::c_int, - __req: *const timespec, - __rem: *mut timespec, - ) -> ::std::os::raw::c_int; -} -extern "C" { - pub fn clock_getcpuclockid(__pid: pid_t, __clock_id: *mut clockid_t) -> ::std::os::raw::c_int; -} -extern "C" { - pub fn timer_create( - __clock_id: clockid_t, - __evp: *mut sigevent, - __timerid: *mut timer_t, - ) -> ::std::os::raw::c_int; -} -extern "C" { - pub fn timer_delete(__timerid: timer_t) -> ::std::os::raw::c_int; -} -extern "C" { - pub fn timer_settime( - __timerid: timer_t, - __flags: ::std::os::raw::c_int, - __value: *const itimerspec, - __ovalue: *mut itimerspec, - ) -> ::std::os::raw::c_int; -} -extern "C" { - pub fn timer_gettime(__timerid: timer_t, __value: *mut itimerspec) -> ::std::os::raw::c_int; -} -extern "C" { - pub fn timer_getoverrun(__timerid: timer_t) -> ::std::os::raw::c_int; -} -extern "C" { - pub fn timespec_get( - __ts: *mut timespec, - __base: ::std::os::raw::c_int, - ) -> ::std::os::raw::c_int; -} -/// In the context of a \ref libusb_device_descriptor "device descriptor", -/// this bDeviceClass value indicates that each interface specifies its -/// own class information and all interfaces operate independently. -pub const LIBUSB_CLASS_PER_INTERFACE: libusb_class_code = 0; -/// Audio class -pub const LIBUSB_CLASS_AUDIO: libusb_class_code = 1; -/// Communications class -pub const LIBUSB_CLASS_COMM: libusb_class_code = 2; -/// Human Interface Device class -pub const LIBUSB_CLASS_HID: libusb_class_code = 3; -/// Physical -pub const LIBUSB_CLASS_PHYSICAL: libusb_class_code = 5; -/// Printer class -pub const LIBUSB_CLASS_PRINTER: libusb_class_code = 7; -/// Image class -pub const LIBUSB_CLASS_PTP: libusb_class_code = 6; -/// Image class -pub const LIBUSB_CLASS_IMAGE: libusb_class_code = 6; -/// Mass storage class -pub const LIBUSB_CLASS_MASS_STORAGE: libusb_class_code = 8; -/// Hub class -pub const LIBUSB_CLASS_HUB: libusb_class_code = 9; -/// Data class -pub const LIBUSB_CLASS_DATA: libusb_class_code = 10; -/// Smart Card -pub const LIBUSB_CLASS_SMART_CARD: libusb_class_code = 11; -/// Content Security -pub const LIBUSB_CLASS_CONTENT_SECURITY: libusb_class_code = 13; -/// Video -pub const LIBUSB_CLASS_VIDEO: libusb_class_code = 14; -/// Personal Healthcare -pub const LIBUSB_CLASS_PERSONAL_HEALTHCARE: libusb_class_code = 15; -/// Diagnostic Device -pub const LIBUSB_CLASS_DIAGNOSTIC_DEVICE: libusb_class_code = 220; -/// Wireless class -pub const LIBUSB_CLASS_WIRELESS: libusb_class_code = 224; -/// Application class -pub const LIBUSB_CLASS_APPLICATION: libusb_class_code = 254; -/// Class is vendor-specific -pub const LIBUSB_CLASS_VENDOR_SPEC: libusb_class_code = 255; -/// \ingroup libusb_desc -/// Device and/or Interface Class codes -pub type libusb_class_code = u32; -/// Device descriptor. See libusb_device_descriptor. -pub const LIBUSB_DT_DEVICE: libusb_descriptor_type = 1; -/// Configuration descriptor. See libusb_config_descriptor. -pub const LIBUSB_DT_CONFIG: libusb_descriptor_type = 2; -/// String descriptor -pub const LIBUSB_DT_STRING: libusb_descriptor_type = 3; -/// Interface descriptor. See libusb_interface_descriptor. -pub const LIBUSB_DT_INTERFACE: libusb_descriptor_type = 4; -/// Endpoint descriptor. See libusb_endpoint_descriptor. -pub const LIBUSB_DT_ENDPOINT: libusb_descriptor_type = 5; -/// BOS descriptor -pub const LIBUSB_DT_BOS: libusb_descriptor_type = 15; -/// Device Capability descriptor -pub const LIBUSB_DT_DEVICE_CAPABILITY: libusb_descriptor_type = 16; -/// HID descriptor -pub const LIBUSB_DT_HID: libusb_descriptor_type = 33; -/// HID report descriptor -pub const LIBUSB_DT_REPORT: libusb_descriptor_type = 34; -/// Physical descriptor -pub const LIBUSB_DT_PHYSICAL: libusb_descriptor_type = 35; -/// Hub descriptor -pub const LIBUSB_DT_HUB: libusb_descriptor_type = 41; -/// SuperSpeed Hub descriptor -pub const LIBUSB_DT_SUPERSPEED_HUB: libusb_descriptor_type = 42; -/// SuperSpeed Endpoint Companion descriptor -pub const LIBUSB_DT_SS_ENDPOINT_COMPANION: libusb_descriptor_type = 48; -/// \ingroup libusb_desc -/// Descriptor types as defined by the USB specification. -pub type libusb_descriptor_type = u32; -/// In: device-to-host -pub const LIBUSB_ENDPOINT_IN: libusb_endpoint_direction = 128; -/// Out: host-to-device -pub const LIBUSB_ENDPOINT_OUT: libusb_endpoint_direction = 0; -/// \ingroup libusb_desc -/// Endpoint direction. Values for bit 7 of the -/// \ref libusb_endpoint_descriptor::bEndpointAddress "endpoint address" scheme. -pub type libusb_endpoint_direction = u32; -/// Control endpoint -pub const LIBUSB_TRANSFER_TYPE_CONTROL: libusb_transfer_type = 0; -/// Isochronous endpoint -pub const LIBUSB_TRANSFER_TYPE_ISOCHRONOUS: libusb_transfer_type = 1; -/// Bulk endpoint -pub const LIBUSB_TRANSFER_TYPE_BULK: libusb_transfer_type = 2; -/// Interrupt endpoint -pub const LIBUSB_TRANSFER_TYPE_INTERRUPT: libusb_transfer_type = 3; -/// Stream endpoint -pub const LIBUSB_TRANSFER_TYPE_BULK_STREAM: libusb_transfer_type = 4; -/// \ingroup libusb_desc -/// Endpoint transfer type. Values for bits 0:1 of the -/// \ref libusb_endpoint_descriptor::bmAttributes "endpoint attributes" field. -pub type libusb_transfer_type = u32; -/// Request status of the specific recipient -pub const LIBUSB_REQUEST_GET_STATUS: libusb_standard_request = 0; -/// Clear or disable a specific feature -pub const LIBUSB_REQUEST_CLEAR_FEATURE: libusb_standard_request = 1; -/// Set or enable a specific feature -pub const LIBUSB_REQUEST_SET_FEATURE: libusb_standard_request = 3; -/// Set device address for all future accesses -pub const LIBUSB_REQUEST_SET_ADDRESS: libusb_standard_request = 5; -/// Get the specified descriptor -pub const LIBUSB_REQUEST_GET_DESCRIPTOR: libusb_standard_request = 6; -/// Used to update existing descriptors or add new descriptors -pub const LIBUSB_REQUEST_SET_DESCRIPTOR: libusb_standard_request = 7; -/// Get the current device configuration value -pub const LIBUSB_REQUEST_GET_CONFIGURATION: libusb_standard_request = 8; -/// Set device configuration -pub const LIBUSB_REQUEST_SET_CONFIGURATION: libusb_standard_request = 9; -/// Return the selected alternate setting for the specified interface -pub const LIBUSB_REQUEST_GET_INTERFACE: libusb_standard_request = 10; -/// Select an alternate interface for the specified interface -pub const LIBUSB_REQUEST_SET_INTERFACE: libusb_standard_request = 11; -/// Set then report an endpoint's synchronization frame -pub const LIBUSB_REQUEST_SYNCH_FRAME: libusb_standard_request = 12; -/// Sets both the U1 and U2 Exit Latency -pub const LIBUSB_REQUEST_SET_SEL: libusb_standard_request = 48; -/// Delay from the time a host transmits a packet to the time it is -/// received by the device. -pub const LIBUSB_SET_ISOCH_DELAY: libusb_standard_request = 49; -/// \ingroup libusb_misc -/// Standard requests, as defined in table 9-5 of the USB 3.0 specifications -pub type libusb_standard_request = u32; -/// Standard -pub const LIBUSB_REQUEST_TYPE_STANDARD: libusb_request_type = 0; -/// Class -pub const LIBUSB_REQUEST_TYPE_CLASS: libusb_request_type = 32; -/// Vendor -pub const LIBUSB_REQUEST_TYPE_VENDOR: libusb_request_type = 64; -/// Reserved -pub const LIBUSB_REQUEST_TYPE_RESERVED: libusb_request_type = 96; -/// \ingroup libusb_misc -/// Request type bits of the -/// \ref libusb_control_setup::bmRequestType "bmRequestType" field in control -/// transfers. -pub type libusb_request_type = u32; -/// Device -pub const LIBUSB_RECIPIENT_DEVICE: libusb_request_recipient = 0; -/// Interface -pub const LIBUSB_RECIPIENT_INTERFACE: libusb_request_recipient = 1; -/// Endpoint -pub const LIBUSB_RECIPIENT_ENDPOINT: libusb_request_recipient = 2; -/// Other -pub const LIBUSB_RECIPIENT_OTHER: libusb_request_recipient = 3; -/// \ingroup libusb_misc -/// Recipient bits of the -/// \ref libusb_control_setup::bmRequestType "bmRequestType" field in control -/// transfers. Values 4 through 31 are reserved. -pub type libusb_request_recipient = u32; -/// No synchronization -pub const LIBUSB_ISO_SYNC_TYPE_NONE: libusb_iso_sync_type = 0; -/// Asynchronous -pub const LIBUSB_ISO_SYNC_TYPE_ASYNC: libusb_iso_sync_type = 1; -/// Adaptive -pub const LIBUSB_ISO_SYNC_TYPE_ADAPTIVE: libusb_iso_sync_type = 2; -/// Synchronous -pub const LIBUSB_ISO_SYNC_TYPE_SYNC: libusb_iso_sync_type = 3; -/// \ingroup libusb_desc -/// Synchronization type for isochronous endpoints. Values for bits 2:3 of the -/// \ref libusb_endpoint_descriptor::bmAttributes "bmAttributes" field in -/// libusb_endpoint_descriptor. -pub type libusb_iso_sync_type = u32; -/// Data endpoint -pub const LIBUSB_ISO_USAGE_TYPE_DATA: libusb_iso_usage_type = 0; -/// Feedback endpoint -pub const LIBUSB_ISO_USAGE_TYPE_FEEDBACK: libusb_iso_usage_type = 1; -/// Implicit feedback Data endpoint -pub const LIBUSB_ISO_USAGE_TYPE_IMPLICIT: libusb_iso_usage_type = 2; -/// \ingroup libusb_desc -/// Usage type for isochronous endpoints. Values for bits 4:5 of the -/// \ref libusb_endpoint_descriptor::bmAttributes "bmAttributes" field in -/// libusb_endpoint_descriptor. -pub type libusb_iso_usage_type = u32; -/// \ingroup libusb_desc -/// A structure representing the standard USB device descriptor. This -/// descriptor is documented in section 9.6.1 of the USB 3.0 specification. -/// All multiple-byte fields are represented in host-endian format. -#[repr(C)] -#[derive(Default, Debug, Copy, Clone)] -pub struct libusb_device_descriptor { - /// Size of this descriptor (in bytes) - pub bLength: u8, - /// Descriptor type. Will have value - /// \ref libusb_descriptor_type::LIBUSB_DT_DEVICE LIBUSB_DT_DEVICE in this - /// context. - pub bDescriptorType: u8, - /// USB specification release number in binary-coded decimal. A value of - /// 0x0200 indicates USB 2.0, 0x0110 indicates USB 1.1, etc. - pub bcdUSB: u16, - /// USB-IF class code for the device. See \ref libusb_class_code. - pub bDeviceClass: u8, - /// USB-IF subclass code for the device, qualified by the bDeviceClass - /// value - pub bDeviceSubClass: u8, - /// USB-IF protocol code for the device, qualified by the bDeviceClass and - /// bDeviceSubClass values - pub bDeviceProtocol: u8, - /// Maximum packet size for endpoint 0 - pub bMaxPacketSize0: u8, - /// USB-IF vendor ID - pub idVendor: u16, - /// USB-IF product ID - pub idProduct: u16, - /// Device release number in binary-coded decimal - pub bcdDevice: u16, - /// Index of string descriptor describing manufacturer - pub iManufacturer: u8, - /// Index of string descriptor describing product - pub iProduct: u8, - /// Index of string descriptor containing device serial number - pub iSerialNumber: u8, - /// Number of possible configurations - pub bNumConfigurations: u8, -} -#[test] -fn bindgen_test_layout_libusb_device_descriptor() { - assert_eq!( - ::std::mem::size_of::<libusb_device_descriptor>(), - 18usize, - concat!("Size of: ", stringify!(libusb_device_descriptor)) - ); - assert_eq!( - ::std::mem::align_of::<libusb_device_descriptor>(), - 2usize, - concat!("Alignment of ", stringify!(libusb_device_descriptor)) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::<libusb_device_descriptor>())).bLength as *const _ as usize - }, - 0usize, - concat!( - "Offset of field: ", - stringify!(libusb_device_descriptor), - "::", - stringify!(bLength) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::<libusb_device_descriptor>())).bDescriptorType as *const _ - as usize - }, - 1usize, - concat!( - "Offset of field: ", - stringify!(libusb_device_descriptor), - "::", - stringify!(bDescriptorType) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::<libusb_device_descriptor>())).bcdUSB as *const _ as usize }, - 2usize, - concat!( - "Offset of field: ", - stringify!(libusb_device_descriptor), - "::", - stringify!(bcdUSB) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::<libusb_device_descriptor>())).bDeviceClass as *const _ as usize - }, - 4usize, - concat!( - "Offset of field: ", - stringify!(libusb_device_descriptor), - "::", - stringify!(bDeviceClass) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::<libusb_device_descriptor>())).bDeviceSubClass as *const _ - as usize - }, - 5usize, - concat!( - "Offset of field: ", - stringify!(libusb_device_descriptor), - "::", - stringify!(bDeviceSubClass) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::<libusb_device_descriptor>())).bDeviceProtocol as *const _ - as usize - }, - 6usize, - concat!( - "Offset of field: ", - stringify!(libusb_device_descriptor), - "::", - stringify!(bDeviceProtocol) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::<libusb_device_descriptor>())).bMaxPacketSize0 as *const _ - as usize - }, - 7usize, - concat!( - "Offset of field: ", - stringify!(libusb_device_descriptor), - "::", - stringify!(bMaxPacketSize0) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::<libusb_device_descriptor>())).idVendor as *const _ as usize - }, - 8usize, - concat!( - "Offset of field: ", - stringify!(libusb_device_descriptor), - "::", - stringify!(idVendor) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::<libusb_device_descriptor>())).idProduct as *const _ as usize - }, - 10usize, - concat!( - "Offset of field: ", - stringify!(libusb_device_descriptor), - "::", - stringify!(idProduct) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::<libusb_device_descriptor>())).bcdDevice as *const _ as usize - }, - 12usize, - concat!( - "Offset of field: ", - stringify!(libusb_device_descriptor), - "::", - stringify!(bcdDevice) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::<libusb_device_descriptor>())).iManufacturer as *const _ as usize - }, - 14usize, - concat!( - "Offset of field: ", - stringify!(libusb_device_descriptor), - "::", - stringify!(iManufacturer) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::<libusb_device_descriptor>())).iProduct as *const _ as usize - }, - 15usize, - concat!( - "Offset of field: ", - stringify!(libusb_device_descriptor), - "::", - stringify!(iProduct) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::<libusb_device_descriptor>())).iSerialNumber as *const _ as usize - }, - 16usize, - concat!( - "Offset of field: ", - stringify!(libusb_device_descriptor), - "::", - stringify!(iSerialNumber) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::<libusb_device_descriptor>())).bNumConfigurations as *const _ - as usize - }, - 17usize, - concat!( - "Offset of field: ", - stringify!(libusb_device_descriptor), - "::", - stringify!(bNumConfigurations) - ) - ); -} -/// \ingroup libusb_desc -/// A structure representing the standard USB endpoint descriptor. This -/// descriptor is documented in section 9.6.6 of the USB 3.0 specification. -/// All multiple-byte fields are represented in host-endian format. -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct libusb_endpoint_descriptor { - /// Size of this descriptor (in bytes) - pub bLength: u8, - /// Descriptor type. Will have value - /// \ref libusb_descriptor_type::LIBUSB_DT_ENDPOINT LIBUSB_DT_ENDPOINT in - /// this context. - pub bDescriptorType: u8, - /// The address of the endpoint described by this descriptor. Bits 0:3 are - /// the endpoint number. Bits 4:6 are reserved. Bit 7 indicates direction, - /// see \ref libusb_endpoint_direction. - pub bEndpointAddress: u8, - /// Attributes which apply to the endpoint when it is configured using - /// the bConfigurationValue. Bits 0:1 determine the transfer type and - /// correspond to \ref libusb_transfer_type. Bits 2:3 are only used for - /// isochronous endpoints and correspond to \ref libusb_iso_sync_type. - /// Bits 4:5 are also only used for isochronous endpoints and correspond to - /// \ref libusb_iso_usage_type. Bits 6:7 are reserved. - pub bmAttributes: u8, - /// Maximum packet size this endpoint is capable of sending/receiving. - pub wMaxPacketSize: u16, - /// Interval for polling endpoint for data transfers. - pub bInterval: u8, - /// For audio devices only: the rate at which synchronization feedback - /// is provided. - pub bRefresh: u8, - /// For audio devices only: the address if the synch endpoint - pub bSynchAddress: u8, - /// Extra descriptors. If libusb encounters unknown endpoint descriptors, - /// it will store them here, should you wish to parse them. - pub extra: *const ::std::os::raw::c_uchar, - /// Length of the extra descriptors, in bytes. - pub extra_length: ::std::os::raw::c_int, -} -#[test] -fn bindgen_test_layout_libusb_endpoint_descriptor() { - assert_eq!( - ::std::mem::size_of::<libusb_endpoint_descriptor>(), - 32usize, - concat!("Size of: ", stringify!(libusb_endpoint_descriptor)) - ); - assert_eq!( - ::std::mem::align_of::<libusb_endpoint_descriptor>(), - 8usize, - concat!("Alignment of ", stringify!(libusb_endpoint_descriptor)) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::<libusb_endpoint_descriptor>())).bLength as *const _ as usize - }, - 0usize, - concat!( - "Offset of field: ", - stringify!(libusb_endpoint_descriptor), - "::", - stringify!(bLength) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::<libusb_endpoint_descriptor>())).bDescriptorType as *const _ - as usize - }, - 1usize, - concat!( - "Offset of field: ", - stringify!(libusb_endpoint_descriptor), - "::", - stringify!(bDescriptorType) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::<libusb_endpoint_descriptor>())).bEndpointAddress as *const _ - as usize - }, - 2usize, - concat!( - "Offset of field: ", - stringify!(libusb_endpoint_descriptor), - "::", - stringify!(bEndpointAddress) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::<libusb_endpoint_descriptor>())).bmAttributes as *const _ as usize - }, - 3usize, - concat!( - "Offset of field: ", - stringify!(libusb_endpoint_descriptor), - "::", - stringify!(bmAttributes) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::<libusb_endpoint_descriptor>())).wMaxPacketSize as *const _ - as usize - }, - 4usize, - concat!( - "Offset of field: ", - stringify!(libusb_endpoint_descriptor), - "::", - stringify!(wMaxPacketSize) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::<libusb_endpoint_descriptor>())).bInterval as *const _ as usize - }, - 6usize, - concat!( - "Offset of field: ", - stringify!(libusb_endpoint_descriptor), - "::", - stringify!(bInterval) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::<libusb_endpoint_descriptor>())).bRefresh as *const _ as usize - }, - 7usize, - concat!( - "Offset of field: ", - stringify!(libusb_endpoint_descriptor), - "::", - stringify!(bRefresh) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::<libusb_endpoint_descriptor>())).bSynchAddress as *const _ - as usize - }, - 8usize, - concat!( - "Offset of field: ", - stringify!(libusb_endpoint_descriptor), - "::", - stringify!(bSynchAddress) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::<libusb_endpoint_descriptor>())).extra as *const _ as usize - }, - 16usize, - concat!( - "Offset of field: ", - stringify!(libusb_endpoint_descriptor), - "::", - stringify!(extra) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::<libusb_endpoint_descriptor>())).extra_length as *const _ as usize - }, - 24usize, - concat!( - "Offset of field: ", - stringify!(libusb_endpoint_descriptor), - "::", - stringify!(extra_length) - ) - ); -} -/// \ingroup libusb_desc -/// A structure representing the standard USB interface descriptor. This -/// descriptor is documented in section 9.6.5 of the USB 3.0 specification. -/// All multiple-byte fields are represented in host-endian format. -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct libusb_interface_descriptor { - /// Size of this descriptor (in bytes) - pub bLength: u8, - /// Descriptor type. Will have value - /// \ref libusb_descriptor_type::LIBUSB_DT_INTERFACE LIBUSB_DT_INTERFACE - /// in this context. - pub bDescriptorType: u8, - /// Number of this interface - pub bInterfaceNumber: u8, - /// Value used to select this alternate setting for this interface - pub bAlternateSetting: u8, - /// Number of endpoints used by this interface (excluding the control - /// endpoint). - pub bNumEndpoints: u8, - /// USB-IF class code for this interface. See \ref libusb_class_code. - pub bInterfaceClass: u8, - /// USB-IF subclass code for this interface, qualified by the - /// bInterfaceClass value - pub bInterfaceSubClass: u8, - /// USB-IF protocol code for this interface, qualified by the - /// bInterfaceClass and bInterfaceSubClass values - pub bInterfaceProtocol: u8, - /// Index of string descriptor describing this interface - pub iInterface: u8, - /// Array of endpoint descriptors. This length of this array is determined - /// by the bNumEndpoints field. - pub endpoint: *const libusb_endpoint_descriptor, - /// Extra descriptors. If libusb encounters unknown interface descriptors, - /// it will store them here, should you wish to parse them. - pub extra: *const ::std::os::raw::c_uchar, - /// Length of the extra descriptors, in bytes. - pub extra_length: ::std::os::raw::c_int, -} -#[test] -fn bindgen_test_layout_libusb_interface_descriptor() { - assert_eq!( - ::std::mem::size_of::<libusb_interface_descriptor>(), - 40usize, - concat!("Size of: ", stringify!(libusb_interface_descriptor)) - ); - assert_eq!( - ::std::mem::align_of::<libusb_interface_descriptor>(), - 8usize, - concat!("Alignment of ", stringify!(libusb_interface_descriptor)) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::<libusb_interface_descriptor>())).bLength as *const _ as usize - }, - 0usize, - concat!( - "Offset of field: ", - stringify!(libusb_interface_descriptor), - "::", - stringify!(bLength) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::<libusb_interface_descriptor>())).bDescriptorType as *const _ - as usize - }, - 1usize, - concat!( - "Offset of field: ", - stringify!(libusb_interface_descriptor), - "::", - stringify!(bDescriptorType) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::<libusb_interface_descriptor>())).bInterfaceNumber as *const _ - as usize - }, - 2usize, - concat!( - "Offset of field: ", - stringify!(libusb_interface_descriptor), - "::", - stringify!(bInterfaceNumber) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::<libusb_interface_descriptor>())).bAlternateSetting as *const _ - as usize - }, - 3usize, - concat!( - "Offset of field: ", - stringify!(libusb_interface_descriptor), - "::", - stringify!(bAlternateSetting) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::<libusb_interface_descriptor>())).bNumEndpoints as *const _ - as usize - }, - 4usize, - concat!( - "Offset of field: ", - stringify!(libusb_interface_descriptor), - "::", - stringify!(bNumEndpoints) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::<libusb_interface_descriptor>())).bInterfaceClass as *const _ - as usize - }, - 5usize, - concat!( - "Offset of field: ", - stringify!(libusb_interface_descriptor), - "::", - stringify!(bInterfaceClass) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::<libusb_interface_descriptor>())).bInterfaceSubClass as *const _ - as usize - }, - 6usize, - concat!( - "Offset of field: ", - stringify!(libusb_interface_descriptor), - "::", - stringify!(bInterfaceSubClass) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::<libusb_interface_descriptor>())).bInterfaceProtocol as *const _ - as usize - }, - 7usize, - concat!( - "Offset of field: ", - stringify!(libusb_interface_descriptor), - "::", - stringify!(bInterfaceProtocol) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::<libusb_interface_descriptor>())).iInterface as *const _ as usize - }, - 8usize, - concat!( - "Offset of field: ", - stringify!(libusb_interface_descriptor), - "::", - stringify!(iInterface) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::<libusb_interface_descriptor>())).endpoint as *const _ as usize - }, - 16usize, - concat!( - "Offset of field: ", - stringify!(libusb_interface_descriptor), - "::", - stringify!(endpoint) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::<libusb_interface_descriptor>())).extra as *const _ as usize - }, - 24usize, - concat!( - "Offset of field: ", - stringify!(libusb_interface_descriptor), - "::", - stringify!(extra) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::<libusb_interface_descriptor>())).extra_length as *const _ - as usize - }, - 32usize, - concat!( - "Offset of field: ", - stringify!(libusb_interface_descriptor), - "::", - stringify!(extra_length) - ) - ); -} -/// \ingroup libusb_desc -/// A collection of alternate settings for a particular USB interface. -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct libusb_interface { - /// Array of interface descriptors. The length of this array is determined - /// by the num_altsetting field. - pub altsetting: *const libusb_interface_descriptor, - /// The number of alternate settings that belong to this interface - pub num_altsetting: ::std::os::raw::c_int, -} -#[test] -fn bindgen_test_layout_libusb_interface() { - assert_eq!( - ::std::mem::size_of::<libusb_interface>(), - 16usize, - concat!("Size of: ", stringify!(libusb_interface)) - ); - assert_eq!( - ::std::mem::align_of::<libusb_interface>(), - 8usize, - concat!("Alignment of ", stringify!(libusb_interface)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::<libusb_interface>())).altsetting as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(libusb_interface), - "::", - stringify!(altsetting) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::<libusb_interface>())).num_altsetting as *const _ as usize }, - 8usize, - concat!( - "Offset of field: ", - stringify!(libusb_interface), - "::", - stringify!(num_altsetting) - ) - ); -} -/// \ingroup libusb_desc -/// A structure representing the standard USB configuration descriptor. This -/// descriptor is documented in section 9.6.3 of the USB 3.0 specification. -/// All multiple-byte fields are represented in host-endian format. -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct libusb_config_descriptor { - /// Size of this descriptor (in bytes) - pub bLength: u8, - /// Descriptor type. Will have value - /// \ref libusb_descriptor_type::LIBUSB_DT_CONFIG LIBUSB_DT_CONFIG - /// in this context. - pub bDescriptorType: u8, - /// Total length of data returned for this configuration - pub wTotalLength: u16, - /// Number of interfaces supported by this configuration - pub bNumInterfaces: u8, - /// Identifier value for this configuration - pub bConfigurationValue: u8, - /// Index of string descriptor describing this configuration - pub iConfiguration: u8, - /// Configuration characteristics - pub bmAttributes: u8, - /// Maximum power consumption of the USB device from this bus in this - /// configuration when the device is fully operation. Expressed in units - /// of 2 mA when the device is operating in high-speed mode and in units - /// of 8 mA when the device is operating in super-speed mode. - pub MaxPower: u8, - /// Array of interfaces supported by this configuration. The length of - /// this array is determined by the bNumInterfaces field. - pub interface: *const libusb_interface, - /// Extra descriptors. If libusb encounters unknown configuration - /// descriptors, it will store them here, should you wish to parse them. - pub extra: *const ::std::os::raw::c_uchar, - /// Length of the extra descriptors, in bytes. - pub extra_length: ::std::os::raw::c_int, -} -#[test] -fn bindgen_test_layout_libusb_config_descriptor() { - assert_eq!( - ::std::mem::size_of::<libusb_config_descriptor>(), - 40usize, - concat!("Size of: ", stringify!(libusb_config_descriptor)) - ); - assert_eq!( - ::std::mem::align_of::<libusb_config_descriptor>(), - 8usize, - concat!("Alignment of ", stringify!(libusb_config_descriptor)) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::<libusb_config_descriptor>())).bLength as *const _ as usize - }, - 0usize, - concat!( - "Offset of field: ", - stringify!(libusb_config_descriptor), - "::", - stringify!(bLength) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::<libusb_config_descriptor>())).bDescriptorType as *const _ - as usize - }, - 1usize, - concat!( - "Offset of field: ", - stringify!(libusb_config_descriptor), - "::", - stringify!(bDescriptorType) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::<libusb_config_descriptor>())).wTotalLength as *const _ as usize - }, - 2usize, - concat!( - "Offset of field: ", - stringify!(libusb_config_descriptor), - "::", - stringify!(wTotalLength) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::<libusb_config_descriptor>())).bNumInterfaces as *const _ as usize - }, - 4usize, - concat!( - "Offset of field: ", - stringify!(libusb_config_descriptor), - "::", - stringify!(bNumInterfaces) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::<libusb_config_descriptor>())).bConfigurationValue as *const _ - as usize - }, - 5usize, - concat!( - "Offset of field: ", - stringify!(libusb_config_descriptor), - "::", - stringify!(bConfigurationValue) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::<libusb_config_descriptor>())).iConfiguration as *const _ as usize - }, - 6usize, - concat!( - "Offset of field: ", - stringify!(libusb_config_descriptor), - "::", - stringify!(iConfiguration) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::<libusb_config_descriptor>())).bmAttributes as *const _ as usize - }, - 7usize, - concat!( - "Offset of field: ", - stringify!(libusb_config_descriptor), - "::", - stringify!(bmAttributes) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::<libusb_config_descriptor>())).MaxPower as *const _ as usize - }, - 8usize, - concat!( - "Offset of field: ", - stringify!(libusb_config_descriptor), - "::", - stringify!(MaxPower) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::<libusb_config_descriptor>())).interface as *const _ as usize - }, - 16usize, - concat!( - "Offset of field: ", - stringify!(libusb_config_descriptor), - "::", - stringify!(interface) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::<libusb_config_descriptor>())).extra as *const _ as usize }, - 24usize, - concat!( - "Offset of field: ", - stringify!(libusb_config_descriptor), - "::", - stringify!(extra) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::<libusb_config_descriptor>())).extra_length as *const _ as usize - }, - 32usize, - concat!( - "Offset of field: ", - stringify!(libusb_config_descriptor), - "::", - stringify!(extra_length) - ) - ); -} -/// \ingroup libusb_desc -/// A structure representing the superspeed endpoint companion -/// descriptor. This descriptor is documented in section 9.6.7 of -/// the USB 3.0 specification. All multiple-byte fields are represented in -/// host-endian format. -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct libusb_ss_endpoint_companion_descriptor { - /// Size of this descriptor (in bytes) - pub bLength: u8, - /// Descriptor type. Will have value - /// \ref libusb_descriptor_type::LIBUSB_DT_SS_ENDPOINT_COMPANION in - /// this context. - pub bDescriptorType: u8, - /// The maximum number of packets the endpoint can send or - /// receive as part of a burst. - pub bMaxBurst: u8, - /// In bulk EP: bits 4:0 represents the maximum number of - /// streams the EP supports. In isochronous EP: bits 1:0 - /// represents the Mult - a zero based value that determines - /// the maximum number of packets within a service interval - pub bmAttributes: u8, - /// The total number of bytes this EP will transfer every - /// service interval. valid only for periodic EPs. - pub wBytesPerInterval: u16, -} -#[test] -fn bindgen_test_layout_libusb_ss_endpoint_companion_descriptor() { - assert_eq!( - ::std::mem::size_of::<libusb_ss_endpoint_companion_descriptor>(), - 6usize, - concat!( - "Size of: ", - stringify!(libusb_ss_endpoint_companion_descriptor) - ) - ); - assert_eq!( - ::std::mem::align_of::<libusb_ss_endpoint_companion_descriptor>(), - 2usize, - concat!( - "Alignment of ", - stringify!(libusb_ss_endpoint_companion_descriptor) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::<libusb_ss_endpoint_companion_descriptor>())).bLength as *const _ - as usize - }, - 0usize, - concat!( - "Offset of field: ", - stringify!(libusb_ss_endpoint_companion_descriptor), - "::", - stringify!(bLength) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::<libusb_ss_endpoint_companion_descriptor>())).bDescriptorType - as *const _ as usize - }, - 1usize, - concat!( - "Offset of field: ", - stringify!(libusb_ss_endpoint_companion_descriptor), - "::", - stringify!(bDescriptorType) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::<libusb_ss_endpoint_companion_descriptor>())).bMaxBurst - as *const _ as usize - }, - 2usize, - concat!( - "Offset of field: ", - stringify!(libusb_ss_endpoint_companion_descriptor), - "::", - stringify!(bMaxBurst) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::<libusb_ss_endpoint_companion_descriptor>())).bmAttributes - as *const _ as usize - }, - 3usize, - concat!( - "Offset of field: ", - stringify!(libusb_ss_endpoint_companion_descriptor), - "::", - stringify!(bmAttributes) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::<libusb_ss_endpoint_companion_descriptor>())).wBytesPerInterval - as *const _ as usize - }, - 4usize, - concat!( - "Offset of field: ", - stringify!(libusb_ss_endpoint_companion_descriptor), - "::", - stringify!(wBytesPerInterval) - ) - ); -} -/// \ingroup libusb_desc -/// A generic representation of a BOS Device Capability descriptor. It is -/// advised to check bDevCapabilityType and call the matching -/// libusb_get_*_descriptor function to get a structure fully matching the type. -#[repr(C)] -#[derive(Debug)] -pub struct libusb_bos_dev_capability_descriptor { - /// Size of this descriptor (in bytes) - pub bLength: u8, - /// Descriptor type. Will have value - /// \ref libusb_descriptor_type::LIBUSB_DT_DEVICE_CAPABILITY - /// LIBUSB_DT_DEVICE_CAPABILITY in this context. - pub bDescriptorType: u8, - /// Device Capability type - pub bDevCapabilityType: u8, - /// Device Capability data (bLength - 3 bytes) - pub dev_capability_data: __IncompleteArrayField<u8>, -} -#[test] -fn bindgen_test_layout_libusb_bos_dev_capability_descriptor() { - assert_eq!( - ::std::mem::size_of::<libusb_bos_dev_capability_descriptor>(), - 3usize, - concat!( - "Size of: ", - stringify!(libusb_bos_dev_capability_descriptor) - ) - ); - assert_eq!( - ::std::mem::align_of::<libusb_bos_dev_capability_descriptor>(), - 1usize, - concat!( - "Alignment of ", - stringify!(libusb_bos_dev_capability_descriptor) - ) - ); -} -/// \ingroup libusb_desc -/// A structure representing the Binary Device Object Store (BOS) descriptor. -/// This descriptor is documented in section 9.6.2 of the USB 3.0 specification. -/// All multiple-byte fields are represented in host-endian format. -#[repr(C)] -#[derive(Debug)] -pub struct libusb_bos_descriptor { - /// Size of this descriptor (in bytes) - pub bLength: u8, - /// Descriptor type. Will have value - /// \ref libusb_descriptor_type::LIBUSB_DT_BOS LIBUSB_DT_BOS - /// in this context. - pub bDescriptorType: u8, - /// Length of this descriptor and all of its sub descriptors - pub wTotalLength: u16, - /// The number of separate device capability descriptors in - /// the BOS - pub bNumDeviceCaps: u8, - /// bNumDeviceCap Device Capability Descriptors - pub dev_capability: __IncompleteArrayField<*mut libusb_bos_dev_capability_descriptor>, - pub __bindgen_align: [u64; 0usize], -} -#[test] -fn bindgen_test_layout_libusb_bos_descriptor() { - assert_eq!( - ::std::mem::size_of::<libusb_bos_descriptor>(), - 8usize, - concat!("Size of: ", stringify!(libusb_bos_descriptor)) - ); - assert_eq!( - ::std::mem::align_of::<libusb_bos_descriptor>(), - 8usize, - concat!("Alignment of ", stringify!(libusb_bos_descriptor)) - ); -} -/// \ingroup libusb_desc -/// A structure representing the USB 2.0 Extension descriptor -/// This descriptor is documented in section 9.6.2.1 of the USB 3.0 specification. -/// All multiple-byte fields are represented in host-endian format. -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct libusb_usb_2_0_extension_descriptor { - /// Size of this descriptor (in bytes) - pub bLength: u8, - /// Descriptor type. Will have value - /// \ref libusb_descriptor_type::LIBUSB_DT_DEVICE_CAPABILITY - /// LIBUSB_DT_DEVICE_CAPABILITY in this context. - pub bDescriptorType: u8, - /// Capability type. Will have value - /// \ref libusb_capability_type::LIBUSB_BT_USB_2_0_EXTENSION - /// LIBUSB_BT_USB_2_0_EXTENSION in this context. - pub bDevCapabilityType: u8, - /// Bitmap encoding of supported device level features. - /// A value of one in a bit location indicates a feature is - /// supported; a value of zero indicates it is not supported. - /// See \ref libusb_usb_2_0_extension_attributes. - pub bmAttributes: u32, -} -#[test] -fn bindgen_test_layout_libusb_usb_2_0_extension_descriptor() { - assert_eq!( - ::std::mem::size_of::<libusb_usb_2_0_extension_descriptor>(), - 8usize, - concat!("Size of: ", stringify!(libusb_usb_2_0_extension_descriptor)) - ); - assert_eq!( - ::std::mem::align_of::<libusb_usb_2_0_extension_descriptor>(), - 4usize, - concat!( - "Alignment of ", - stringify!(libusb_usb_2_0_extension_descriptor) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::<libusb_usb_2_0_extension_descriptor>())).bLength as *const _ - as usize - }, - 0usize, - concat!( - "Offset of field: ", - stringify!(libusb_usb_2_0_extension_descriptor), - "::", - stringify!(bLength) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::<libusb_usb_2_0_extension_descriptor>())).bDescriptorType - as *const _ as usize - }, - 1usize, - concat!( - "Offset of field: ", - stringify!(libusb_usb_2_0_extension_descriptor), - "::", - stringify!(bDescriptorType) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::<libusb_usb_2_0_extension_descriptor>())).bDevCapabilityType - as *const _ as usize - }, - 2usize, - concat!( - "Offset of field: ", - stringify!(libusb_usb_2_0_extension_descriptor), - "::", - stringify!(bDevCapabilityType) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::<libusb_usb_2_0_extension_descriptor>())).bmAttributes as *const _ - as usize - }, - 4usize, - concat!( - "Offset of field: ", - stringify!(libusb_usb_2_0_extension_descriptor), - "::", - stringify!(bmAttributes) - ) - ); -} -/// \ingroup libusb_desc -/// A structure representing the SuperSpeed USB Device Capability descriptor -/// This descriptor is documented in section 9.6.2.2 of the USB 3.0 specification. -/// All multiple-byte fields are represented in host-endian format. -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct libusb_ss_usb_device_capability_descriptor { - /// Size of this descriptor (in bytes) - pub bLength: u8, - /// Descriptor type. Will have value - /// \ref libusb_descriptor_type::LIBUSB_DT_DEVICE_CAPABILITY - /// LIBUSB_DT_DEVICE_CAPABILITY in this context. - pub bDescriptorType: u8, - /// Capability type. Will have value - /// \ref libusb_capability_type::LIBUSB_BT_SS_USB_DEVICE_CAPABILITY - /// LIBUSB_BT_SS_USB_DEVICE_CAPABILITY in this context. - pub bDevCapabilityType: u8, - /// Bitmap encoding of supported device level features. - /// A value of one in a bit location indicates a feature is - /// supported; a value of zero indicates it is not supported. - /// See \ref libusb_ss_usb_device_capability_attributes. - pub bmAttributes: u8, - /// Bitmap encoding of the speed supported by this device when - /// operating in SuperSpeed mode. See \ref libusb_supported_speed. - pub wSpeedSupported: u16, - /// The lowest speed at which all the functionality supported - /// by the device is available to the user. For example if the - /// device supports all its functionality when connected at - /// full speed and above then it sets this value to 1. - pub bFunctionalitySupport: u8, - /// U1 Device Exit Latency. - pub bU1DevExitLat: u8, - /// U2 Device Exit Latency. - pub bU2DevExitLat: u16, -} -#[test] -fn bindgen_test_layout_libusb_ss_usb_device_capability_descriptor() { - assert_eq!( - ::std::mem::size_of::<libusb_ss_usb_device_capability_descriptor>(), - 10usize, - concat!( - "Size of: ", - stringify!(libusb_ss_usb_device_capability_descriptor) - ) - ); - assert_eq!( - ::std::mem::align_of::<libusb_ss_usb_device_capability_descriptor>(), - 2usize, - concat!( - "Alignment of ", - stringify!(libusb_ss_usb_device_capability_descriptor) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::<libusb_ss_usb_device_capability_descriptor>())).bLength - as *const _ as usize - }, - 0usize, - concat!( - "Offset of field: ", - stringify!(libusb_ss_usb_device_capability_descriptor), - "::", - stringify!(bLength) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::<libusb_ss_usb_device_capability_descriptor>())).bDescriptorType - as *const _ as usize - }, - 1usize, - concat!( - "Offset of field: ", - stringify!(libusb_ss_usb_device_capability_descriptor), - "::", - stringify!(bDescriptorType) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::<libusb_ss_usb_device_capability_descriptor>())) - .bDevCapabilityType as *const _ as usize - }, - 2usize, - concat!( - "Offset of field: ", - stringify!(libusb_ss_usb_device_capability_descriptor), - "::", - stringify!(bDevCapabilityType) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::<libusb_ss_usb_device_capability_descriptor>())).bmAttributes - as *const _ as usize - }, - 3usize, - concat!( - "Offset of field: ", - stringify!(libusb_ss_usb_device_capability_descriptor), - "::", - stringify!(bmAttributes) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::<libusb_ss_usb_device_capability_descriptor>())).wSpeedSupported - as *const _ as usize - }, - 4usize, - concat!( - "Offset of field: ", - stringify!(libusb_ss_usb_device_capability_descriptor), - "::", - stringify!(wSpeedSupported) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::<libusb_ss_usb_device_capability_descriptor>())) - .bFunctionalitySupport as *const _ as usize - }, - 6usize, - concat!( - "Offset of field: ", - stringify!(libusb_ss_usb_device_capability_descriptor), - "::", - stringify!(bFunctionalitySupport) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::<libusb_ss_usb_device_capability_descriptor>())).bU1DevExitLat - as *const _ as usize - }, - 7usize, - concat!( - "Offset of field: ", - stringify!(libusb_ss_usb_device_capability_descriptor), - "::", - stringify!(bU1DevExitLat) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::<libusb_ss_usb_device_capability_descriptor>())).bU2DevExitLat - as *const _ as usize - }, - 8usize, - concat!( - "Offset of field: ", - stringify!(libusb_ss_usb_device_capability_descriptor), - "::", - stringify!(bU2DevExitLat) - ) - ); -} -/// \ingroup libusb_desc -/// A structure representing the Container ID descriptor. -/// This descriptor is documented in section 9.6.2.3 of the USB 3.0 specification. -/// All multiple-byte fields, except UUIDs, are represented in host-endian format. -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct libusb_container_id_descriptor { - /// Size of this descriptor (in bytes) - pub bLength: u8, - /// Descriptor type. Will have value - /// \ref libusb_descriptor_type::LIBUSB_DT_DEVICE_CAPABILITY - /// LIBUSB_DT_DEVICE_CAPABILITY in this context. - pub bDescriptorType: u8, - /// Capability type. Will have value - /// \ref libusb_capability_type::LIBUSB_BT_CONTAINER_ID - /// LIBUSB_BT_CONTAINER_ID in this context. - pub bDevCapabilityType: u8, - /// Reserved field - pub bReserved: u8, - /// 128 bit UUID - pub ContainerID: [u8; 16usize], -} -#[test] -fn bindgen_test_layout_libusb_container_id_descriptor() { - assert_eq!( - ::std::mem::size_of::<libusb_container_id_descriptor>(), - 20usize, - concat!("Size of: ", stringify!(libusb_container_id_descriptor)) - ); - assert_eq!( - ::std::mem::align_of::<libusb_container_id_descriptor>(), - 1usize, - concat!("Alignment of ", stringify!(libusb_container_id_descriptor)) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::<libusb_container_id_descriptor>())).bLength as *const _ as usize - }, - 0usize, - concat!( - "Offset of field: ", - stringify!(libusb_container_id_descriptor), - "::", - stringify!(bLength) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::<libusb_container_id_descriptor>())).bDescriptorType as *const _ - as usize - }, - 1usize, - concat!( - "Offset of field: ", - stringify!(libusb_container_id_descriptor), - "::", - stringify!(bDescriptorType) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::<libusb_container_id_descriptor>())).bDevCapabilityType - as *const _ as usize - }, - 2usize, - concat!( - "Offset of field: ", - stringify!(libusb_container_id_descriptor), - "::", - stringify!(bDevCapabilityType) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::<libusb_container_id_descriptor>())).bReserved as *const _ - as usize - }, - 3usize, - concat!( - "Offset of field: ", - stringify!(libusb_container_id_descriptor), - "::", - stringify!(bReserved) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::<libusb_container_id_descriptor>())).ContainerID as *const _ - as usize - }, - 4usize, - concat!( - "Offset of field: ", - stringify!(libusb_container_id_descriptor), - "::", - stringify!(ContainerID) - ) - ); -} -/// \ingroup libusb_asyncio -/// Setup packet for control transfers. -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct libusb_control_setup { - /// Request type. Bits 0:4 determine recipient, see - /// \ref libusb_request_recipient. Bits 5:6 determine type, see - /// \ref libusb_request_type. Bit 7 determines data transfer direction, see - /// \ref libusb_endpoint_direction. - pub bmRequestType: u8, - /// Request. If the type bits of bmRequestType are equal to - /// \ref libusb_request_type::LIBUSB_REQUEST_TYPE_STANDARD - /// "LIBUSB_REQUEST_TYPE_STANDARD" then this field refers to - /// \ref libusb_standard_request. For other cases, use of this field is - /// application-specific. - pub bRequest: u8, - /// Value. Varies according to request - pub wValue: u16, - /// Index. Varies according to request, typically used to pass an index - /// or offset - pub wIndex: u16, - /// Number of bytes to transfer - pub wLength: u16, -} -#[test] -fn bindgen_test_layout_libusb_control_setup() { - assert_eq!( - ::std::mem::size_of::<libusb_control_setup>(), - 8usize, - concat!("Size of: ", stringify!(libusb_control_setup)) - ); - assert_eq!( - ::std::mem::align_of::<libusb_control_setup>(), - 2usize, - concat!("Alignment of ", stringify!(libusb_control_setup)) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::<libusb_control_setup>())).bmRequestType as *const _ as usize - }, - 0usize, - concat!( - "Offset of field: ", - stringify!(libusb_control_setup), - "::", - stringify!(bmRequestType) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::<libusb_control_setup>())).bRequest as *const _ as usize }, - 1usize, - concat!( - "Offset of field: ", - stringify!(libusb_control_setup), - "::", - stringify!(bRequest) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::<libusb_control_setup>())).wValue as *const _ as usize }, - 2usize, - concat!( - "Offset of field: ", - stringify!(libusb_control_setup), - "::", - stringify!(wValue) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::<libusb_control_setup>())).wIndex as *const _ as usize }, - 4usize, - concat!( - "Offset of field: ", - stringify!(libusb_control_setup), - "::", - stringify!(wIndex) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::<libusb_control_setup>())).wLength as *const _ as usize }, - 6usize, - concat!( - "Offset of field: ", - stringify!(libusb_control_setup), - "::", - stringify!(wLength) - ) - ); -} -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct libusb_context { - _unused: [u8; 0], -} -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct libusb_device { - _unused: [u8; 0], -} -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct libusb_device_handle { - _unused: [u8; 0], -} -/// \ingroup libusb_lib -/// Structure providing the version of the libusb runtime -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct libusb_version { - /// Library major version. - pub major: u16, - /// Library minor version. - pub minor: u16, - /// Library micro version. - pub micro: u16, - /// Library nano version. - pub nano: u16, - /// Library release candidate suffix string, e.g. "-rc4". - pub rc: *const ::std::os::raw::c_char, - /// For ABI compatibility only. - pub describe: *const ::std::os::raw::c_char, -} -#[test] -fn bindgen_test_layout_libusb_version() { - assert_eq!( - ::std::mem::size_of::<libusb_version>(), - 24usize, - concat!("Size of: ", stringify!(libusb_version)) - ); - assert_eq!( - ::std::mem::align_of::<libusb_version>(), - 8usize, - concat!("Alignment of ", stringify!(libusb_version)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::<libusb_version>())).major as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(libusb_version), - "::", - stringify!(major) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::<libusb_version>())).minor as *const _ as usize }, - 2usize, - concat!( - "Offset of field: ", - stringify!(libusb_version), - "::", - stringify!(minor) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::<libusb_version>())).micro as *const _ as usize }, - 4usize, - concat!( - "Offset of field: ", - stringify!(libusb_version), - "::", - stringify!(micro) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::<libusb_version>())).nano as *const _ as usize }, - 6usize, - concat!( - "Offset of field: ", - stringify!(libusb_version), - "::", - stringify!(nano) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::<libusb_version>())).rc as *const _ as usize }, - 8usize, - concat!( - "Offset of field: ", - stringify!(libusb_version), - "::", - stringify!(rc) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::<libusb_version>())).describe as *const _ as usize }, - 16usize, - concat!( - "Offset of field: ", - stringify!(libusb_version), - "::", - stringify!(describe) - ) - ); -} -/// The OS doesn't report or know the device speed. -pub const LIBUSB_SPEED_UNKNOWN: libusb_speed = 0; -/// The device is operating at low speed (1.5MBit/s). -pub const LIBUSB_SPEED_LOW: libusb_speed = 1; -/// The device is operating at full speed (12MBit/s). -pub const LIBUSB_SPEED_FULL: libusb_speed = 2; -/// The device is operating at high speed (480MBit/s). -pub const LIBUSB_SPEED_HIGH: libusb_speed = 3; -/// The device is operating at super speed (5000MBit/s). -pub const LIBUSB_SPEED_SUPER: libusb_speed = 4; -/// \ingroup libusb_dev -/// Speed codes. Indicates the speed at which the device is operating. -pub type libusb_speed = u32; -/// Low speed operation supported (1.5MBit/s). -pub const LIBUSB_LOW_SPEED_OPERATION: libusb_supported_speed = 1; -/// Full speed operation supported (12MBit/s). -pub const LIBUSB_FULL_SPEED_OPERATION: libusb_supported_speed = 2; -/// High speed operation supported (480MBit/s). -pub const LIBUSB_HIGH_SPEED_OPERATION: libusb_supported_speed = 4; -/// Superspeed operation supported (5000MBit/s). -pub const LIBUSB_SUPER_SPEED_OPERATION: libusb_supported_speed = 8; -/// \ingroup libusb_dev -/// Supported speeds (wSpeedSupported) bitfield. Indicates what -/// speeds the device supports. -pub type libusb_supported_speed = u32; -/// Supports Link Power Management (LPM) -pub const LIBUSB_BM_LPM_SUPPORT: libusb_usb_2_0_extension_attributes = 2; -/// \ingroup libusb_dev -/// Masks for the bits of the -/// \ref libusb_usb_2_0_extension_descriptor::bmAttributes "bmAttributes" field -/// of the USB 2.0 Extension descriptor. -pub type libusb_usb_2_0_extension_attributes = u32; -/// Supports Latency Tolerance Messages (LTM) -pub const LIBUSB_BM_LTM_SUPPORT: libusb_ss_usb_device_capability_attributes = 2; -/// \ingroup libusb_dev -/// Masks for the bits of the -/// \ref libusb_ss_usb_device_capability_descriptor::bmAttributes "bmAttributes" field -/// field of the SuperSpeed USB Device Capability descriptor. -pub type libusb_ss_usb_device_capability_attributes = u32; -/// Wireless USB device capability -pub const LIBUSB_BT_WIRELESS_USB_DEVICE_CAPABILITY: libusb_bos_type = 1; -/// USB 2.0 extensions -pub const LIBUSB_BT_USB_2_0_EXTENSION: libusb_bos_type = 2; -/// SuperSpeed USB device capability -pub const LIBUSB_BT_SS_USB_DEVICE_CAPABILITY: libusb_bos_type = 3; -/// Container ID type -pub const LIBUSB_BT_CONTAINER_ID: libusb_bos_type = 4; -/// \ingroup libusb_dev -/// USB capability types -pub type libusb_bos_type = u32; -/// Success (no error) -pub const LIBUSB_SUCCESS: libusb_error = 0; -/// Input/output error -pub const LIBUSB_ERROR_IO: libusb_error = -1; -/// Invalid parameter -pub const LIBUSB_ERROR_INVALID_PARAM: libusb_error = -2; -/// Access denied (insufficient permissions) -pub const LIBUSB_ERROR_ACCESS: libusb_error = -3; -/// No such device (it may have been disconnected) -pub const LIBUSB_ERROR_NO_DEVICE: libusb_error = -4; -/// Entity not found -pub const LIBUSB_ERROR_NOT_FOUND: libusb_error = -5; -/// Resource busy -pub const LIBUSB_ERROR_BUSY: libusb_error = -6; -/// Operation timed out -pub const LIBUSB_ERROR_TIMEOUT: libusb_error = -7; -/// Overflow -pub const LIBUSB_ERROR_OVERFLOW: libusb_error = -8; -/// Pipe error -pub const LIBUSB_ERROR_PIPE: libusb_error = -9; -/// System call interrupted (perhaps due to signal) -pub const LIBUSB_ERROR_INTERRUPTED: libusb_error = -10; -/// Insufficient memory -pub const LIBUSB_ERROR_NO_MEM: libusb_error = -11; -/// Operation not supported or unimplemented on this platform -pub const LIBUSB_ERROR_NOT_SUPPORTED: libusb_error = -12; -/// Other error -pub const LIBUSB_ERROR_OTHER: libusb_error = -99; -/// \ingroup libusb_misc -/// Error codes. Most libusb functions return 0 on success or one of these -/// codes on failure. -/// You can call libusb_error_name() to retrieve a string representation of an -/// error code or libusb_strerror() to get an end-user suitable description of -/// an error code. -pub type libusb_error = i32; -/// Transfer completed without error. Note that this does not indicate -/// that the entire amount of requested data was transferred. -pub const LIBUSB_TRANSFER_COMPLETED: libusb_transfer_status = 0; -/// Transfer failed -pub const LIBUSB_TRANSFER_ERROR: libusb_transfer_status = 1; -/// Transfer timed out -pub const LIBUSB_TRANSFER_TIMED_OUT: libusb_transfer_status = 2; -/// Transfer was cancelled -pub const LIBUSB_TRANSFER_CANCELLED: libusb_transfer_status = 3; -/// For bulk/interrupt endpoints: halt condition detected (endpoint -/// stalled). For control endpoints: control request not supported. -pub const LIBUSB_TRANSFER_STALL: libusb_transfer_status = 4; -/// Device was disconnected -pub const LIBUSB_TRANSFER_NO_DEVICE: libusb_transfer_status = 5; -/// Device sent more data than requested -pub const LIBUSB_TRANSFER_OVERFLOW: libusb_transfer_status = 6; -/// \ingroup libusb_asyncio -/// Transfer status codes -pub type libusb_transfer_status = u32; -/// Report short frames as errors -pub const LIBUSB_TRANSFER_SHORT_NOT_OK: libusb_transfer_flags = 1; -/// Automatically free() transfer buffer during libusb_free_transfer(). -/// Note that buffers allocated with libusb_dev_mem_alloc() should not -/// be attempted freed in this way, since free() is not an appropriate -/// way to release such memory. -pub const LIBUSB_TRANSFER_FREE_BUFFER: libusb_transfer_flags = 2; -/// Automatically call libusb_free_transfer() after callback returns. -/// If this flag is set, it is illegal to call libusb_free_transfer() -/// from your transfer callback, as this will result in a double-free -/// when this flag is acted upon. -pub const LIBUSB_TRANSFER_FREE_TRANSFER: libusb_transfer_flags = 4; -/// Terminate transfers that are a multiple of the endpoint's -/// wMaxPacketSize with an extra zero length packet. This is useful -/// when a device protocol mandates that each logical request is -/// terminated by an incomplete packet (i.e. the logical requests are -/// not separated by other means). -/// -/// This flag only affects host-to-device transfers to bulk and interrupt -/// endpoints. In other situations, it is ignored. -/// -/// This flag only affects transfers with a length that is a multiple of -/// the endpoint's wMaxPacketSize. On transfers of other lengths, this -/// flag has no effect. Therefore, if you are working with a device that -/// needs a ZLP whenever the end of the logical request falls on a packet -/// boundary, then it is sensible to set this flag on <em>every</em> -/// transfer (you do not have to worry about only setting it on transfers -/// that end on the boundary). -/// -/// This flag is currently only supported on Linux. -/// On other systems, libusb_submit_transfer() will return -/// LIBUSB_ERROR_NOT_SUPPORTED for every transfer where this flag is set. -/// -/// Available since libusb-1.0.9. -pub const LIBUSB_TRANSFER_ADD_ZERO_PACKET: libusb_transfer_flags = 8; -/// \ingroup libusb_asyncio -/// libusb_transfer.flags values -pub type libusb_transfer_flags = u32; -/// \ingroup libusb_asyncio -/// Isochronous packet descriptor. -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct libusb_iso_packet_descriptor { - /// Length of data to request in this packet - pub length: ::std::os::raw::c_uint, - /// Amount of data that was actually transferred - pub actual_length: ::std::os::raw::c_uint, - /// Status code for this packet - pub status: libusb_transfer_status, -} -#[test] -fn bindgen_test_layout_libusb_iso_packet_descriptor() { - assert_eq!( - ::std::mem::size_of::<libusb_iso_packet_descriptor>(), - 12usize, - concat!("Size of: ", stringify!(libusb_iso_packet_descriptor)) - ); - assert_eq!( - ::std::mem::align_of::<libusb_iso_packet_descriptor>(), - 4usize, - concat!("Alignment of ", stringify!(libusb_iso_packet_descriptor)) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::<libusb_iso_packet_descriptor>())).length as *const _ as usize - }, - 0usize, - concat!( - "Offset of field: ", - stringify!(libusb_iso_packet_descriptor), - "::", - stringify!(length) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::<libusb_iso_packet_descriptor>())).actual_length as *const _ - as usize - }, - 4usize, - concat!( - "Offset of field: ", - stringify!(libusb_iso_packet_descriptor), - "::", - stringify!(actual_length) - ) - ); - assert_eq!( - unsafe { - &(*(::std::ptr::null::<libusb_iso_packet_descriptor>())).status as *const _ as usize - }, - 8usize, - concat!( - "Offset of field: ", - stringify!(libusb_iso_packet_descriptor), - "::", - stringify!(status) - ) - ); -} -/// \ingroup libusb_asyncio -/// Asynchronous transfer callback function type. When submitting asynchronous -/// transfers, you pass a pointer to a callback function of this type via the -/// \ref libusb_transfer::callback "callback" member of the libusb_transfer -/// structure. libusb will call this function later, when the transfer has -/// completed or failed. See \ref libusb_asyncio for more information. -/// \param transfer The libusb_transfer struct the callback function is being -/// notified about. -pub type libusb_transfer_cb_fn = - ::std::option::Option<unsafe extern "C" fn(transfer: *mut libusb_transfer)>; -/// \ingroup libusb_asyncio -/// The generic USB transfer structure. The user populates this structure and -/// then submits it in order to request a transfer. After the transfer has -/// completed, the library populates the transfer with the results and passes -/// it back to the user. -#[repr(C)] -#[derive(Debug)] -pub struct libusb_transfer { - /// Handle of the device that this transfer will be submitted to - pub dev_handle: *mut libusb_device_handle, - /// A bitwise OR combination of \ref libusb_transfer_flags. - pub flags: u8, - /// Address of the endpoint where this transfer will be sent. - pub endpoint: ::std::os::raw::c_uchar, - /// Type of the endpoint from \ref libusb_transfer_type - pub type_: ::std::os::raw::c_uchar, - /// Timeout for this transfer in millseconds. A value of 0 indicates no - /// timeout. - pub timeout: ::std::os::raw::c_uint, - /// The status of the transfer. Read-only, and only for use within - /// transfer callback function. - /// - /// If this is an isochronous transfer, this field may read COMPLETED even - /// if there were errors in the frames. Use the - /// \ref libusb_iso_packet_descriptor::status "status" field in each packet - /// to determine if errors occurred. - pub status: libusb_transfer_status, - /// Length of the data buffer - pub length: ::std::os::raw::c_int, - /// Actual length of data that was transferred. Read-only, and only for - /// use within transfer callback function. Not valid for isochronous - /// endpoint transfers. - pub actual_length: ::std::os::raw::c_int, - /// Callback function. This will be invoked when the transfer completes, - /// fails, or is cancelled. - pub callback: libusb_transfer_cb_fn, - /// User context data to pass to the callback function. - pub user_data: *mut ::std::os::raw::c_void, - /// Data buffer - pub buffer: *mut ::std::os::raw::c_uchar, - /// Number of isochronous packets. Only used for I/O with isochronous - /// endpoints. - pub num_iso_packets: ::std::os::raw::c_int, - /// Isochronous packet descriptors, for isochronous transfers only. - pub iso_packet_desc: __IncompleteArrayField<libusb_iso_packet_descriptor>, -} -#[test] -fn bindgen_test_layout_libusb_transfer() { - assert_eq!( - ::std::mem::size_of::<libusb_transfer>(), - 64usize, - concat!("Size of: ", stringify!(libusb_transfer)) - ); - assert_eq!( - ::std::mem::align_of::<libusb_transfer>(), - 8usize, - concat!("Alignment of ", stringify!(libusb_transfer)) - ); -} -/// The libusb_has_capability() API is available. -pub const LIBUSB_CAP_HAS_CAPABILITY: libusb_capability = 0; -/// Hotplug support is available on this platform. -pub const LIBUSB_CAP_HAS_HOTPLUG: libusb_capability = 1; -/// The library can access HID devices without requiring user intervention. -/// Note that before being able to actually access an HID device, you may -/// still have to call additional libusb functions such as -/// \ref libusb_detach_kernel_driver(). -pub const LIBUSB_CAP_HAS_HID_ACCESS: libusb_capability = 256; -/// The library supports detaching of the default USB driver, using -/// \ref libusb_detach_kernel_driver(), if one is set by the OS kernel -pub const LIBUSB_CAP_SUPPORTS_DETACH_KERNEL_DRIVER: libusb_capability = 257; -/// \ingroup libusb_misc -/// Capabilities supported by an instance of libusb on the current running -/// platform. Test if the loaded library supports a given capability by calling -/// \ref libusb_has_capability(). -pub type libusb_capability = u32; -pub const LIBUSB_LOG_LEVEL_NONE: libusb_log_level = 0; -pub const LIBUSB_LOG_LEVEL_ERROR: libusb_log_level = 1; -pub const LIBUSB_LOG_LEVEL_WARNING: libusb_log_level = 2; -pub const LIBUSB_LOG_LEVEL_INFO: libusb_log_level = 3; -pub const LIBUSB_LOG_LEVEL_DEBUG: libusb_log_level = 4; -/// \ingroup libusb_lib -/// Log message levels. -/// - LIBUSB_LOG_LEVEL_NONE (0) : no messages ever printed by the library (default) -/// - LIBUSB_LOG_LEVEL_ERROR (1) : error messages are printed to stderr -/// - LIBUSB_LOG_LEVEL_WARNING (2) : warning and error messages are printed to stderr -/// - LIBUSB_LOG_LEVEL_INFO (3) : informational messages are printed to stdout, warning -/// and error messages are printed to stderr -/// - LIBUSB_LOG_LEVEL_DEBUG (4) : debug and informational messages are printed to stdout, -/// warnings and errors to stderr -pub type libusb_log_level = u32; -extern "C" { - pub fn libusb_init(ctx: *mut *mut libusb_context) -> ::std::os::raw::c_int; -} -extern "C" { - pub fn libusb_exit(ctx: *mut libusb_context); -} -extern "C" { - pub fn libusb_wrap_sys_device( - ctx: *mut libusb_context, - fd: __intptr_t, - handle: *mut *mut libusb_device_handle, - ) -> ::std::os::raw::c_int; -} -extern "C" { - pub fn libusb_set_debug(ctx: *mut libusb_context, level: ::std::os::raw::c_int); -} -extern "C" { - pub fn libusb_get_version() -> *const libusb_version; -} -extern "C" { - pub fn libusb_has_capability(capability: u32) -> ::std::os::raw::c_int; -} -extern "C" { - pub fn libusb_error_name(errcode: ::std::os::raw::c_int) -> *const ::std::os::raw::c_char; -} -extern "C" { - pub fn libusb_setlocale(locale: *const ::std::os::raw::c_char) -> ::std::os::raw::c_int; -} -extern "C" { - pub fn libusb_strerror(errcode: libusb_error) -> *const ::std::os::raw::c_char; -} -extern "C" { - pub fn libusb_get_device_list( - ctx: *mut libusb_context, - list: *mut *mut *mut libusb_device, - ) -> isize; -} -extern "C" { - pub fn libusb_free_device_list( - list: *mut *mut libusb_device, - unref_devices: ::std::os::raw::c_int, - ); -} -extern "C" { - pub fn libusb_ref_device(dev: *mut libusb_device) -> *mut libusb_device; -} -extern "C" { - pub fn libusb_unref_device(dev: *mut libusb_device); -} -extern "C" { - pub fn libusb_get_configuration( - dev: *mut libusb_device_handle, - config: *mut ::std::os::raw::c_int, - ) -> ::std::os::raw::c_int; -} -extern "C" { - pub fn libusb_get_device_descriptor( - dev: *mut libusb_device, - desc: *mut libusb_device_descriptor, - ) -> ::std::os::raw::c_int; -} -extern "C" { - pub fn libusb_get_active_config_descriptor( - dev: *mut libusb_device, - config: *mut *mut libusb_config_descriptor, - ) -> ::std::os::raw::c_int; -} -extern "C" { - pub fn libusb_get_config_descriptor( - dev: *mut libusb_device, - config_index: u8, - config: *mut *mut libusb_config_descriptor, - ) -> ::std::os::raw::c_int; -} -extern "C" { - pub fn libusb_get_config_descriptor_by_value( - dev: *mut libusb_device, - bConfigurationValue: u8, - config: *mut *mut libusb_config_descriptor, - ) -> ::std::os::raw::c_int; -} -extern "C" { - pub fn libusb_free_config_descriptor(config: *mut libusb_config_descriptor); -} -extern "C" { - pub fn libusb_get_ss_endpoint_companion_descriptor( - ctx: *mut libusb_context, - endpoint: *const libusb_endpoint_descriptor, - ep_comp: *mut *mut libusb_ss_endpoint_companion_descriptor, - ) -> ::std::os::raw::c_int; -} -extern "C" { - pub fn libusb_free_ss_endpoint_companion_descriptor( - ep_comp: *mut libusb_ss_endpoint_companion_descriptor, - ); -} -extern "C" { - pub fn libusb_get_bos_descriptor( - dev_handle: *mut libusb_device_handle, - bos: *mut *mut libusb_bos_descriptor, - ) -> ::std::os::raw::c_int; -} -extern "C" { - pub fn libusb_free_bos_descriptor(bos: *mut libusb_bos_descriptor); -} -extern "C" { - pub fn libusb_get_usb_2_0_extension_descriptor( - ctx: *mut libusb_context, - dev_cap: *mut libusb_bos_dev_capability_descriptor, - usb_2_0_extension: *mut *mut libusb_usb_2_0_extension_descriptor, - ) -> ::std::os::raw::c_int; -} -extern "C" { - pub fn libusb_free_usb_2_0_extension_descriptor( - usb_2_0_extension: *mut libusb_usb_2_0_extension_descriptor, - ); -} -extern "C" { - pub fn libusb_get_ss_usb_device_capability_descriptor( - ctx: *mut libusb_context, - dev_cap: *mut libusb_bos_dev_capability_descriptor, - ss_usb_device_cap: *mut *mut libusb_ss_usb_device_capability_descriptor, - ) -> ::std::os::raw::c_int; -} -extern "C" { - pub fn libusb_free_ss_usb_device_capability_descriptor( - ss_usb_device_cap: *mut libusb_ss_usb_device_capability_descriptor, - ); -} -extern "C" { - pub fn libusb_get_container_id_descriptor( - ctx: *mut libusb_context, - dev_cap: *mut libusb_bos_dev_capability_descriptor, - container_id: *mut *mut libusb_container_id_descriptor, - ) -> ::std::os::raw::c_int; -} -extern "C" { - pub fn libusb_free_container_id_descriptor(container_id: *mut libusb_container_id_descriptor); -} -extern "C" { - pub fn libusb_get_bus_number(dev: *mut libusb_device) -> u8; -} -extern "C" { - pub fn libusb_get_port_number(dev: *mut libusb_device) -> u8; -} -extern "C" { - pub fn libusb_get_port_numbers( - dev: *mut libusb_device, - port_numbers: *mut u8, - port_numbers_len: ::std::os::raw::c_int, - ) -> ::std::os::raw::c_int; -} -extern "C" { - pub fn libusb_get_port_path( - ctx: *mut libusb_context, - dev: *mut libusb_device, - path: *mut u8, - path_length: u8, - ) -> ::std::os::raw::c_int; -} -extern "C" { - pub fn libusb_get_parent(dev: *mut libusb_device) -> *mut libusb_device; -} -extern "C" { - pub fn libusb_get_device_address(dev: *mut libusb_device) -> u8; -} -extern "C" { - pub fn libusb_get_device_speed(dev: *mut libusb_device) -> ::std::os::raw::c_int; -} -extern "C" { - pub fn libusb_get_max_packet_size( - dev: *mut libusb_device, - endpoint: ::std::os::raw::c_uchar, - ) -> ::std::os::raw::c_int; -} -extern "C" { - pub fn libusb_get_max_iso_packet_size( - dev: *mut libusb_device, - endpoint: ::std::os::raw::c_uchar, - ) -> ::std::os::raw::c_int; -} -extern "C" { - pub fn libusb_open( - dev: *mut libusb_device, - dev_handle: *mut *mut libusb_device_handle, - ) -> ::std::os::raw::c_int; -} -extern "C" { - pub fn libusb_close(dev_handle: *mut libusb_device_handle); -} -extern "C" { - pub fn libusb_get_device(dev_handle: *mut libusb_device_handle) -> *mut libusb_device; -} -extern "C" { - pub fn libusb_set_configuration( - dev_handle: *mut libusb_device_handle, - configuration: ::std::os::raw::c_int, - ) -> ::std::os::raw::c_int; -} -extern "C" { - pub fn libusb_claim_interface( - dev_handle: *mut libusb_device_handle, - interface_number: ::std::os::raw::c_int, - ) -> ::std::os::raw::c_int; -} -extern "C" { - pub fn libusb_release_interface( - dev_handle: *mut libusb_device_handle, - interface_number: ::std::os::raw::c_int, - ) -> ::std::os::raw::c_int; -} -extern "C" { - pub fn libusb_open_device_with_vid_pid( - ctx: *mut libusb_context, - vendor_id: u16, - product_id: u16, - ) -> *mut libusb_device_handle; -} -extern "C" { - pub fn libusb_set_interface_alt_setting( - dev_handle: *mut libusb_device_handle, - interface_number: ::std::os::raw::c_int, - alternate_setting: ::std::os::raw::c_int, - ) -> ::std::os::raw::c_int; -} -extern "C" { - pub fn libusb_clear_halt( - dev_handle: *mut libusb_device_handle, - endpoint: ::std::os::raw::c_uchar, - ) -> ::std::os::raw::c_int; -} -extern "C" { - pub fn libusb_reset_device(dev_handle: *mut libusb_device_handle) -> ::std::os::raw::c_int; -} -extern "C" { - pub fn libusb_alloc_streams( - dev_handle: *mut libusb_device_handle, - num_streams: u32, - endpoints: *mut ::std::os::raw::c_uchar, - num_endpoints: ::std::os::raw::c_int, - ) -> ::std::os::raw::c_int; -} -extern "C" { - pub fn libusb_free_streams( - dev_handle: *mut libusb_device_handle, - endpoints: *mut ::std::os::raw::c_uchar, - num_endpoints: ::std::os::raw::c_int, - ) -> ::std::os::raw::c_int; -} -extern "C" { - pub fn libusb_dev_mem_alloc( - dev_handle: *mut libusb_device_handle, - length: usize, - ) -> *mut ::std::os::raw::c_uchar; -} -extern "C" { - pub fn libusb_dev_mem_free( - dev_handle: *mut libusb_device_handle, - buffer: *mut ::std::os::raw::c_uchar, - length: usize, - ) -> ::std::os::raw::c_int; -} -extern "C" { - pub fn libusb_kernel_driver_active( - dev_handle: *mut libusb_device_handle, - interface_number: ::std::os::raw::c_int, - ) -> ::std::os::raw::c_int; -} -extern "C" { - pub fn libusb_detach_kernel_driver( - dev_handle: *mut libusb_device_handle, - interface_number: ::std::os::raw::c_int, - ) -> ::std::os::raw::c_int; -} -extern "C" { - pub fn libusb_attach_kernel_driver( - dev_handle: *mut libusb_device_handle, - interface_number: ::std::os::raw::c_int, - ) -> ::std::os::raw::c_int; -} -extern "C" { - pub fn libusb_set_auto_detach_kernel_driver( - dev_handle: *mut libusb_device_handle, - enable: ::std::os::raw::c_int, - ) -> ::std::os::raw::c_int; -} -extern "C" { - pub fn libusb_alloc_transfer(iso_packets: ::std::os::raw::c_int) -> *mut libusb_transfer; -} -extern "C" { - pub fn libusb_submit_transfer(transfer: *mut libusb_transfer) -> ::std::os::raw::c_int; -} -extern "C" { - pub fn libusb_cancel_transfer(transfer: *mut libusb_transfer) -> ::std::os::raw::c_int; -} -extern "C" { - pub fn libusb_free_transfer(transfer: *mut libusb_transfer); -} -extern "C" { - pub fn libusb_transfer_set_stream_id(transfer: *mut libusb_transfer, stream_id: u32); -} -extern "C" { - pub fn libusb_transfer_get_stream_id(transfer: *mut libusb_transfer) -> u32; -} -extern "C" { - pub fn libusb_control_transfer( - dev_handle: *mut libusb_device_handle, - request_type: u8, - bRequest: u8, - wValue: u16, - wIndex: u16, - data: *mut ::std::os::raw::c_uchar, - wLength: u16, - timeout: ::std::os::raw::c_uint, - ) -> ::std::os::raw::c_int; -} -extern "C" { - pub fn libusb_bulk_transfer( - dev_handle: *mut libusb_device_handle, - endpoint: ::std::os::raw::c_uchar, - data: *mut ::std::os::raw::c_uchar, - length: ::std::os::raw::c_int, - actual_length: *mut ::std::os::raw::c_int, - timeout: ::std::os::raw::c_uint, - ) -> ::std::os::raw::c_int; -} -extern "C" { - pub fn libusb_interrupt_transfer( - dev_handle: *mut libusb_device_handle, - endpoint: ::std::os::raw::c_uchar, - data: *mut ::std::os::raw::c_uchar, - length: ::std::os::raw::c_int, - actual_length: *mut ::std::os::raw::c_int, - timeout: ::std::os::raw::c_uint, - ) -> ::std::os::raw::c_int; -} -extern "C" { - pub fn libusb_get_string_descriptor_ascii( - dev_handle: *mut libusb_device_handle, - desc_index: u8, - data: *mut ::std::os::raw::c_uchar, - length: ::std::os::raw::c_int, - ) -> ::std::os::raw::c_int; -} -extern "C" { - pub fn libusb_try_lock_events(ctx: *mut libusb_context) -> ::std::os::raw::c_int; -} -extern "C" { - pub fn libusb_lock_events(ctx: *mut libusb_context); -} -extern "C" { - pub fn libusb_unlock_events(ctx: *mut libusb_context); -} -extern "C" { - pub fn libusb_event_handling_ok(ctx: *mut libusb_context) -> ::std::os::raw::c_int; -} -extern "C" { - pub fn libusb_event_handler_active(ctx: *mut libusb_context) -> ::std::os::raw::c_int; -} -extern "C" { - pub fn libusb_interrupt_event_handler(ctx: *mut libusb_context); -} -extern "C" { - pub fn libusb_lock_event_waiters(ctx: *mut libusb_context); -} -extern "C" { - pub fn libusb_unlock_event_waiters(ctx: *mut libusb_context); -} -extern "C" { - pub fn libusb_wait_for_event( - ctx: *mut libusb_context, - tv: *mut timeval, - ) -> ::std::os::raw::c_int; -} -extern "C" { - pub fn libusb_handle_events_timeout( - ctx: *mut libusb_context, - tv: *mut timeval, - ) -> ::std::os::raw::c_int; -} -extern "C" { - pub fn libusb_handle_events_timeout_completed( - ctx: *mut libusb_context, - tv: *mut timeval, - completed: *mut ::std::os::raw::c_int, - ) -> ::std::os::raw::c_int; -} -extern "C" { - pub fn libusb_handle_events(ctx: *mut libusb_context) -> ::std::os::raw::c_int; -} -extern "C" { - pub fn libusb_handle_events_completed( - ctx: *mut libusb_context, - completed: *mut ::std::os::raw::c_int, - ) -> ::std::os::raw::c_int; -} -extern "C" { - pub fn libusb_handle_events_locked( - ctx: *mut libusb_context, - tv: *mut timeval, - ) -> ::std::os::raw::c_int; -} -extern "C" { - pub fn libusb_pollfds_handle_timeouts(ctx: *mut libusb_context) -> ::std::os::raw::c_int; -} -extern "C" { - pub fn libusb_get_next_timeout( - ctx: *mut libusb_context, - tv: *mut timeval, - ) -> ::std::os::raw::c_int; -} -/// \ingroup libusb_poll -/// File descriptor for polling -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct libusb_pollfd { - /// Numeric file descriptor - pub fd: ::std::os::raw::c_int, - /// Event flags to poll for from <poll.h>. POLLIN indicates that you - /// should monitor this file descriptor for becoming ready to read from, - /// and POLLOUT indicates that you should monitor this file descriptor for - /// nonblocking write readiness. - pub events: ::std::os::raw::c_short, -} -#[test] -fn bindgen_test_layout_libusb_pollfd() { - assert_eq!( - ::std::mem::size_of::<libusb_pollfd>(), - 8usize, - concat!("Size of: ", stringify!(libusb_pollfd)) - ); - assert_eq!( - ::std::mem::align_of::<libusb_pollfd>(), - 4usize, - concat!("Alignment of ", stringify!(libusb_pollfd)) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::<libusb_pollfd>())).fd as *const _ as usize }, - 0usize, - concat!( - "Offset of field: ", - stringify!(libusb_pollfd), - "::", - stringify!(fd) - ) - ); - assert_eq!( - unsafe { &(*(::std::ptr::null::<libusb_pollfd>())).events as *const _ as usize }, - 4usize, - concat!( - "Offset of field: ", - stringify!(libusb_pollfd), - "::", - stringify!(events) - ) - ); -} -/// \ingroup libusb_poll -/// Callback function, invoked when a new file descriptor should be added -/// to the set of file descriptors monitored for events. -/// \param fd the new file descriptor -/// \param events events to monitor for, see \ref libusb_pollfd for a -/// description -/// \param user_data User data pointer specified in -/// libusb_set_pollfd_notifiers() call -/// \see libusb_set_pollfd_notifiers() -pub type libusb_pollfd_added_cb = ::std::option::Option< - unsafe extern "C" fn( - fd: ::std::os::raw::c_int, - events: ::std::os::raw::c_short, - user_data: *mut ::std::os::raw::c_void, - ), ->; -/// \ingroup libusb_poll -/// Callback function, invoked when a file descriptor should be removed from -/// the set of file descriptors being monitored for events. After returning -/// from this callback, do not use that file descriptor again. -/// \param fd the file descriptor to stop monitoring -/// \param user_data User data pointer specified in -/// libusb_set_pollfd_notifiers() call -/// \see libusb_set_pollfd_notifiers() -pub type libusb_pollfd_removed_cb = ::std::option::Option< - unsafe extern "C" fn(fd: ::std::os::raw::c_int, user_data: *mut ::std::os::raw::c_void), ->; -extern "C" { - pub fn libusb_get_pollfds(ctx: *mut libusb_context) -> *mut *const libusb_pollfd; -} -extern "C" { - pub fn libusb_free_pollfds(pollfds: *mut *const libusb_pollfd); -} -extern "C" { - pub fn libusb_set_pollfd_notifiers( - ctx: *mut libusb_context, - added_cb: libusb_pollfd_added_cb, - removed_cb: libusb_pollfd_removed_cb, - user_data: *mut ::std::os::raw::c_void, - ); -} -/// \ingroup libusb_hotplug -/// Callback handle. -/// -/// Callbacks handles are generated by libusb_hotplug_register_callback() -/// and can be used to deregister callbacks. Callback handles are unique -/// per libusb_context and it is safe to call libusb_hotplug_deregister_callback() -/// on an already deregisted callback. -/// -/// Since version 1.0.16, \ref LIBUSB_API_VERSION >= 0x01000102 -/// -/// For more information, see \ref libusb_hotplug. -pub type libusb_hotplug_callback_handle = ::std::os::raw::c_int; -/// Default value when not using any flags. -pub const LIBUSB_HOTPLUG_NO_FLAGS: libusb_hotplug_flag = 0; -/// Arm the callback and fire it for all matching currently attached devices. -pub const LIBUSB_HOTPLUG_ENUMERATE: libusb_hotplug_flag = 1; -/// \ingroup libusb_hotplug -/// -/// Since version 1.0.16, \ref LIBUSB_API_VERSION >= 0x01000102 -/// -/// Flags for hotplug events -pub type libusb_hotplug_flag = u32; -/// A device has been plugged in and is ready to use -pub const LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED: libusb_hotplug_event = 1; -/// A device has left and is no longer available. -/// It is the user's responsibility to call libusb_close on any handle associated with a disconnected device. -/// It is safe to call libusb_get_device_descriptor on a device that has left -pub const LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT: libusb_hotplug_event = 2; -/// \ingroup libusb_hotplug -/// -/// Since version 1.0.16, \ref LIBUSB_API_VERSION >= 0x01000102 -/// -/// Hotplug events -pub type libusb_hotplug_event = u32; -/// \ingroup libusb_hotplug -/// Hotplug callback function type. When requesting hotplug event notifications, -/// you pass a pointer to a callback function of this type. -/// -/// This callback may be called by an internal event thread and as such it is -/// recommended the callback do minimal processing before returning. -/// -/// libusb will call this function later, when a matching event had happened on -/// a matching device. See \ref libusb_hotplug for more information. -/// -/// It is safe to call either libusb_hotplug_register_callback() or -/// libusb_hotplug_deregister_callback() from within a callback function. -/// -/// Since version 1.0.16, \ref LIBUSB_API_VERSION >= 0x01000102 -/// -/// \param ctx context of this notification -/// \param device libusb_device this event occurred on -/// \param event event that occurred -/// \param user_data user data provided when this callback was registered -/// \returns bool whether this callback is finished processing events. -/// returning 1 will cause this callback to be deregistered -pub type libusb_hotplug_callback_fn = ::std::option::Option< - unsafe extern "C" fn( - ctx: *mut libusb_context, - device: *mut libusb_device, - event: libusb_hotplug_event, - user_data: *mut ::std::os::raw::c_void, - ) -> ::std::os::raw::c_int, ->; -extern "C" { - /// \ingroup libusb_hotplug - /// Register a hotplug callback function - /// - /// Register a callback with the libusb_context. The callback will fire - /// when a matching event occurs on a matching device. The callback is - /// armed until either it is deregistered with libusb_hotplug_deregister_callback() - /// or the supplied callback returns 1 to indicate it is finished processing events. - /// - /// If the \ref LIBUSB_HOTPLUG_ENUMERATE is passed the callback will be - /// called with a \ref LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED for all devices - /// already plugged into the machine. Note that libusb modifies its internal - /// device list from a separate thread, while calling hotplug callbacks from - /// libusb_handle_events(), so it is possible for a device to already be present - /// on, or removed from, its internal device list, while the hotplug callbacks - /// still need to be dispatched. This means that when using \ref - /// LIBUSB_HOTPLUG_ENUMERATE, your callback may be called twice for the arrival - /// of the same device, once from libusb_hotplug_register_callback() and once - /// from libusb_handle_events(); and/or your callback may be called for the - /// removal of a device for which an arrived call was never made. - /// - /// Since version 1.0.16, \ref LIBUSB_API_VERSION >= 0x01000102 - /// - /// \param[in] ctx context to register this callback with - /// \param[in] events bitwise or of events that will trigger this callback. See \ref - /// libusb_hotplug_event - /// \param[in] flags hotplug callback flags. See \ref libusb_hotplug_flag - /// \param[in] vendor_id the vendor id to match or \ref LIBUSB_HOTPLUG_MATCH_ANY - /// \param[in] product_id the product id to match or \ref LIBUSB_HOTPLUG_MATCH_ANY - /// \param[in] dev_class the device class to match or \ref LIBUSB_HOTPLUG_MATCH_ANY - /// \param[in] cb_fn the function to be invoked on a matching event/device - /// \param[in] user_data user data to pass to the callback function - /// \param[out] callback_handle pointer to store the handle of the allocated callback (can be NULL) - /// \returns LIBUSB_SUCCESS on success LIBUSB_ERROR code on failure - pub fn libusb_hotplug_register_callback( - ctx: *mut libusb_context, - events: libusb_hotplug_event, - flags: libusb_hotplug_flag, - vendor_id: ::std::os::raw::c_int, - product_id: ::std::os::raw::c_int, - dev_class: ::std::os::raw::c_int, - cb_fn: libusb_hotplug_callback_fn, - user_data: *mut ::std::os::raw::c_void, - callback_handle: *mut libusb_hotplug_callback_handle, - ) -> ::std::os::raw::c_int; -} -extern "C" { - /// \ingroup libusb_hotplug - /// Deregisters a hotplug callback. - /// - /// Deregister a callback from a libusb_context. This function is safe to call from within - /// a hotplug callback. - /// - /// Since version 1.0.16, \ref LIBUSB_API_VERSION >= 0x01000102 - /// - /// \param[in] ctx context this callback is registered with - /// \param[in] callback_handle the handle of the callback to deregister - pub fn libusb_hotplug_deregister_callback( - ctx: *mut libusb_context, - callback_handle: libusb_hotplug_callback_handle, - ); -} -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct __locale_data { - pub _address: u8, -} diff --git a/usb_util/src/config_descriptor.rs b/usb_util/src/config_descriptor.rs deleted file mode 100644 index 8aebbac..0000000 --- a/usb_util/src/config_descriptor.rs +++ /dev/null @@ -1,66 +0,0 @@ -// Copyright 2018 The Chromium OS Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -use std::ops::Deref; - -use crate::bindings::{self, libusb_config_descriptor}; -use crate::interface_descriptor::InterfaceDescriptor; - -/// ConfigDescriptor wraps libusb_config_descriptor. -pub struct ConfigDescriptor { - descriptor: *mut libusb_config_descriptor, -} - -impl Drop for ConfigDescriptor { - // Free configuration descriptor. - // Safe because 'self' is intialized with a valid libusb_config_descriptor from libusb - // functions. - fn drop(&mut self) { - unsafe { - bindings::libusb_free_config_descriptor(self.descriptor); - } - } -} - -impl ConfigDescriptor { - /// Build ConfigDescriptor. 'descriptor' should be a valid pointer from - /// libusb_config_descriptor. This function will panic if it's null. - pub unsafe fn new(descriptor: *mut libusb_config_descriptor) -> ConfigDescriptor { - assert!(!descriptor.is_null()); - ConfigDescriptor { descriptor } - } - - /// Get interface by number and alt setting. - pub fn get_interface_descriptor( - &self, - interface_num: u8, - alt_setting: i32, - ) -> Option<InterfaceDescriptor> { - let config_descriptor = self.deref(); - if interface_num >= config_descriptor.bNumInterfaces { - return None; - } - // Safe because interface num is checked. - let interface = unsafe { &*(config_descriptor.interface.offset(interface_num as isize)) }; - - if alt_setting >= interface.num_altsetting { - return None; - } - // Safe because setting num is checked. - unsafe { - Some(InterfaceDescriptor::new( - &*(interface.altsetting.offset(alt_setting as isize)), - )) - } - } -} - -impl Deref for ConfigDescriptor { - type Target = libusb_config_descriptor; - - fn deref(&self) -> &libusb_config_descriptor { - // Safe because 'self.descriptor' is valid. - unsafe { &*(self.descriptor) } - } -} diff --git a/usb_util/src/descriptor.rs b/usb_util/src/descriptor.rs new file mode 100644 index 0000000..cf711d1 --- /dev/null +++ b/usb_util/src/descriptor.rs @@ -0,0 +1,499 @@ +// Copyright 2019 The Chromium OS Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +use crate::types::{self, Descriptor, DescriptorHeader, EndpointDescriptor}; +use crate::{Error, Result}; +use data_model::DataInit; +use std::collections::BTreeMap; +use std::io::{self, Read}; +use std::mem::size_of; +use std::ops::Deref; +use sys_util::warn; + +#[derive(Clone)] +pub struct DeviceDescriptorTree { + inner: types::DeviceDescriptor, + // Map of bConfigurationValue to ConfigDescriptor + config_descriptors: BTreeMap<u8, ConfigDescriptorTree>, +} + +#[derive(Clone)] +pub struct ConfigDescriptorTree { + inner: types::ConfigDescriptor, + // Map of (bInterfaceNumber, bAlternateSetting) to InterfaceDescriptor + interface_descriptors: BTreeMap<(u8, u8), InterfaceDescriptorTree>, +} + +#[derive(Clone)] +pub struct InterfaceDescriptorTree { + inner: types::InterfaceDescriptor, + // Map of bEndpointAddress to EndpointDescriptor + endpoint_descriptors: BTreeMap<u8, EndpointDescriptor>, +} + +impl DeviceDescriptorTree { + pub fn get_config_descriptor(&self, config_value: u8) -> Option<&ConfigDescriptorTree> { + self.config_descriptors.get(&config_value) + } +} + +impl Deref for DeviceDescriptorTree { + type Target = types::DeviceDescriptor; + + fn deref(&self) -> &types::DeviceDescriptor { + &self.inner + } +} + +impl ConfigDescriptorTree { + /// Get interface by number and alt setting. + pub fn get_interface_descriptor( + &self, + interface_num: u8, + alt_setting: u8, + ) -> Option<&InterfaceDescriptorTree> { + self.interface_descriptors + .get(&(interface_num, alt_setting)) + } +} + +impl Deref for ConfigDescriptorTree { + type Target = types::ConfigDescriptor; + + fn deref(&self) -> &types::ConfigDescriptor { + &self.inner + } +} + +impl InterfaceDescriptorTree { + pub fn get_endpoint_descriptor(&self, ep_idx: u8) -> Option<&EndpointDescriptor> { + self.endpoint_descriptors.get(&ep_idx) + } +} + +impl Deref for InterfaceDescriptorTree { + type Target = types::InterfaceDescriptor; + + fn deref(&self) -> &types::InterfaceDescriptor { + &self.inner + } +} + +/// Given a `reader` for a full set of descriptors as provided by the Linux kernel +/// usbdevfs `descriptors` file, parse the descriptors into a tree data structure. +pub fn parse_usbfs_descriptors<R: Read>(mut reader: R) -> Result<DeviceDescriptorTree> { + // Given a structure of length `struct_length`, of which `bytes_consumed` have + // already been read, skip the remainder of the struct. If `bytes_consumed` is + // more than `struct_length`, no additional bytes are skipped. + fn skip<R: Read>(reader: R, bytes_consumed: usize, struct_length: u8) -> io::Result<u64> { + let bytes_to_skip = u64::from(struct_length).saturating_sub(bytes_consumed as u64); + io::copy(&mut reader.take(bytes_to_skip), &mut io::sink()) + } + + // Find the next descriptor of type T and return it. + // Any other descriptors encountered while searching for the expected type are skipped. + fn next_descriptor<R: Read, T: Descriptor + DataInit>(mut reader: R) -> Result<T> { + let desc_type = T::descriptor_type() as u8; + loop { + let hdr = DescriptorHeader::from_reader(&mut reader).map_err(Error::DescriptorRead)?; + if hdr.bDescriptorType == desc_type { + if usize::from(hdr.bLength) < size_of::<DescriptorHeader>() + size_of::<T>() { + return Err(Error::DescriptorParse); + } + + let desc = T::from_reader(&mut reader).map_err(Error::DescriptorRead)?; + + // Skip any extra data beyond the standard descriptor length. + skip( + &mut reader, + size_of::<DescriptorHeader>() + size_of::<T>(), + hdr.bLength, + ) + .map_err(Error::DescriptorRead)?; + return Ok(desc); + } + + // Skip this entire descriptor, since it's not the right type. + skip(&mut reader, size_of::<DescriptorHeader>(), hdr.bLength) + .map_err(Error::DescriptorRead)?; + } + } + + let raw_device_descriptor: types::DeviceDescriptor = next_descriptor(&mut reader)?; + let mut device_descriptor = DeviceDescriptorTree { + inner: raw_device_descriptor, + config_descriptors: BTreeMap::new(), + }; + + for cfg_idx in 0..device_descriptor.bNumConfigurations { + if let Ok(raw_config_descriptor) = + next_descriptor::<_, types::ConfigDescriptor>(&mut reader) + { + let mut config_descriptor = ConfigDescriptorTree { + inner: raw_config_descriptor, + interface_descriptors: BTreeMap::new(), + }; + + for intf_idx in 0..config_descriptor.bNumInterfaces { + if let Ok(raw_interface_descriptor) = + next_descriptor::<_, types::InterfaceDescriptor>(&mut reader) + { + let mut interface_descriptor = InterfaceDescriptorTree { + inner: raw_interface_descriptor, + endpoint_descriptors: BTreeMap::new(), + }; + + for ep_idx in 0..interface_descriptor.bNumEndpoints { + if let Ok(endpoint_descriptor) = + next_descriptor::<_, EndpointDescriptor>(&mut reader) + { + interface_descriptor + .endpoint_descriptors + .insert(ep_idx, endpoint_descriptor); + } else { + warn!("Could not read endpoint descriptor {}", ep_idx); + break; + } + } + + config_descriptor.interface_descriptors.insert( + ( + interface_descriptor.bInterfaceNumber, + interface_descriptor.bAlternateSetting, + ), + interface_descriptor, + ); + } else { + warn!("Could not read interface descriptor {}", intf_idx); + break; + } + } + + device_descriptor + .config_descriptors + .insert(config_descriptor.bConfigurationValue, config_descriptor); + } else { + warn!("Could not read config descriptor {}", cfg_idx); + break; + } + } + + Ok(device_descriptor) +} + +#[cfg(test)] +mod tests { + use super::*; + #[test] + fn parse_descriptors_mass_storage() { + let data: &[u8] = &[ + 0x12, 0x01, 0x00, 0x03, 0x00, 0x00, 0x00, 0x09, 0x81, 0x07, 0x80, 0x55, 0x10, 0x00, + 0x01, 0x02, 0x03, 0x01, 0x09, 0x02, 0x2C, 0x00, 0x01, 0x01, 0x00, 0x80, 0x32, 0x09, + 0x04, 0x00, 0x00, 0x02, 0x08, 0x06, 0x50, 0x00, 0x07, 0x05, 0x81, 0x02, 0x00, 0x04, + 0x00, 0x06, 0x30, 0x0F, 0x00, 0x00, 0x00, 0x07, 0x05, 0x02, 0x02, 0x00, 0x04, 0x00, + 0x06, 0x30, 0x0F, 0x00, 0x00, 0x00, + ]; + + let d = parse_usbfs_descriptors(data).expect("parse_usbfs_descriptors failed"); + + // The seemingly-redundant u16::from() calls avoid borrows of packed fields. + + assert_eq!(u16::from(d.bcdUSB), 0x03_00); + assert_eq!(d.bDeviceClass, 0x00); + assert_eq!(d.bDeviceSubClass, 0x00); + assert_eq!(d.bDeviceProtocol, 0x00); + assert_eq!(d.bMaxPacketSize0, 9); + assert_eq!(u16::from(d.idVendor), 0x0781); + assert_eq!(u16::from(d.idProduct), 0x5580); + assert_eq!(u16::from(d.bcdDevice), 0x00_10); + assert_eq!(d.iManufacturer, 1); + assert_eq!(d.iProduct, 2); + assert_eq!(d.iSerialNumber, 3); + assert_eq!(d.bNumConfigurations, 1); + + let c = d + .get_config_descriptor(1) + .expect("could not get config descriptor 1"); + assert_eq!(u16::from(c.wTotalLength), 44); + assert_eq!(c.bNumInterfaces, 1); + assert_eq!(c.bConfigurationValue, 1); + assert_eq!(c.iConfiguration, 0); + assert_eq!(c.bmAttributes, 0x80); + assert_eq!(c.bMaxPower, 50); + + let i = c + .get_interface_descriptor(0, 0) + .expect("could not get interface descriptor 0 alt setting 0"); + assert_eq!(i.bInterfaceNumber, 0); + assert_eq!(i.bAlternateSetting, 0); + assert_eq!(i.bNumEndpoints, 2); + assert_eq!(i.bInterfaceClass, 0x08); + assert_eq!(i.bInterfaceSubClass, 0x06); + assert_eq!(i.bInterfaceProtocol, 0x50); + assert_eq!(i.iInterface, 0); + + let e = i + .get_endpoint_descriptor(0) + .expect("could not get endpoint 0 descriptor"); + assert_eq!(e.bEndpointAddress, 0x81); + assert_eq!(e.bmAttributes, 0x02); + assert_eq!(u16::from(e.wMaxPacketSize), 0x0400); + assert_eq!(e.bInterval, 0); + + let e = i + .get_endpoint_descriptor(1) + .expect("could not get endpoint 1 descriptor"); + assert_eq!(e.bEndpointAddress, 0x02); + assert_eq!(e.bmAttributes, 0x02); + assert_eq!(u16::from(e.wMaxPacketSize), 0x0400); + assert_eq!(e.bInterval, 0); + } + + #[test] + fn parse_descriptors_servo() { + let data: &[u8] = &[ + 0x12, 0x01, 0x00, 0x02, 0x00, 0x00, 0x00, 0x40, 0xd1, 0x18, 0x1b, 0x50, 0x00, 0x01, + 0x01, 0x02, 0x03, 0x01, 0x09, 0x02, 0x7c, 0x00, 0x06, 0x01, 0x04, 0xc0, 0xfa, 0x09, + 0x04, 0x00, 0x00, 0x02, 0xff, 0x50, 0x01, 0x06, 0x07, 0x05, 0x81, 0x02, 0x40, 0x00, + 0x0a, 0x07, 0x05, 0x01, 0x02, 0x40, 0x00, 0x00, 0x09, 0x04, 0x02, 0x00, 0x02, 0xff, + 0x52, 0x01, 0x05, 0x07, 0x05, 0x83, 0x02, 0x40, 0x00, 0x0a, 0x07, 0x05, 0x03, 0x02, + 0x40, 0x00, 0x00, 0x09, 0x04, 0x03, 0x00, 0x02, 0xff, 0x50, 0x01, 0x07, 0x07, 0x05, + 0x84, 0x02, 0x10, 0x00, 0x0a, 0x07, 0x05, 0x04, 0x02, 0x10, 0x00, 0x00, 0x09, 0x04, + 0x04, 0x00, 0x02, 0xff, 0x50, 0x01, 0x08, 0x07, 0x05, 0x85, 0x02, 0x10, 0x00, 0x0a, + 0x07, 0x05, 0x05, 0x02, 0x10, 0x00, 0x00, 0x09, 0x04, 0x05, 0x00, 0x02, 0xff, 0x53, + 0xff, 0x09, 0x07, 0x05, 0x86, 0x02, 0x40, 0x00, 0x0a, 0x07, 0x05, 0x06, 0x02, 0x40, + 0x00, 0x00, + ]; + + // Note: configuration 1 has bNumInterfaces == 6, but it actually only contains 5 + // interface descriptors. This causes us to try to read beyond EOF, which should be + // silently ignored by parse_usbfs_descriptors so that we can use the rest of the + // descriptors. + let d = parse_usbfs_descriptors(data).expect("parse_usbfs_descriptors failed"); + + // The seemingly-redundant u16::from() calls avoid borrows of packed fields. + + assert_eq!(u16::from(d.bcdUSB), 0x02_00); + assert_eq!(d.bDeviceClass, 0x00); + assert_eq!(d.bDeviceSubClass, 0x00); + assert_eq!(d.bDeviceProtocol, 0x00); + assert_eq!(d.bMaxPacketSize0, 64); + assert_eq!(u16::from(d.idVendor), 0x18d1); + assert_eq!(u16::from(d.idProduct), 0x501b); + assert_eq!(u16::from(d.bcdDevice), 0x01_00); + assert_eq!(d.iManufacturer, 1); + assert_eq!(d.iProduct, 2); + assert_eq!(d.iSerialNumber, 3); + assert_eq!(d.bNumConfigurations, 1); + + let c = d + .get_config_descriptor(1) + .expect("could not get config descriptor 1"); + assert_eq!(u16::from(c.wTotalLength), 124); + assert_eq!(c.bNumInterfaces, 6); + assert_eq!(c.bConfigurationValue, 1); + assert_eq!(c.iConfiguration, 4); + assert_eq!(c.bmAttributes, 0xc0); + assert_eq!(c.bMaxPower, 250); + + let i = c + .get_interface_descriptor(0, 0) + .expect("could not get interface descriptor 0 alt setting 0"); + assert_eq!(i.bInterfaceNumber, 0); + assert_eq!(i.bAlternateSetting, 0); + assert_eq!(i.bNumEndpoints, 2); + assert_eq!(i.bInterfaceClass, 0xff); + assert_eq!(i.bInterfaceSubClass, 0x50); + assert_eq!(i.bInterfaceProtocol, 0x01); + assert_eq!(i.iInterface, 6); + + let e = i + .get_endpoint_descriptor(0) + .expect("could not get endpoint 0 descriptor"); + assert_eq!(e.bEndpointAddress, 0x81); + assert_eq!(e.bmAttributes, 0x02); + assert_eq!(u16::from(e.wMaxPacketSize), 0x0040); + assert_eq!(e.bInterval, 10); + + let e = i + .get_endpoint_descriptor(1) + .expect("could not get endpoint 1 descriptor"); + assert_eq!(e.bEndpointAddress, 0x01); + assert_eq!(e.bmAttributes, 0x02); + assert_eq!(u16::from(e.wMaxPacketSize), 0x0040); + assert_eq!(e.bInterval, 0); + + let i = c + .get_interface_descriptor(2, 0) + .expect("could not get interface descriptor 2 alt setting 0"); + assert_eq!(i.bInterfaceNumber, 2); + assert_eq!(i.bAlternateSetting, 0); + assert_eq!(i.bNumEndpoints, 2); + assert_eq!(i.bInterfaceClass, 0xff); + assert_eq!(i.bInterfaceSubClass, 0x52); + assert_eq!(i.bInterfaceProtocol, 0x01); + assert_eq!(i.iInterface, 5); + + let e = i + .get_endpoint_descriptor(0) + .expect("could not get endpoint 0 descriptor"); + assert_eq!(e.bEndpointAddress, 0x83); + assert_eq!(e.bmAttributes, 0x02); + assert_eq!(u16::from(e.wMaxPacketSize), 0x0040); + assert_eq!(e.bInterval, 10); + + let e = i + .get_endpoint_descriptor(1) + .expect("could not get endpoint 1 descriptor"); + assert_eq!(e.bEndpointAddress, 0x03); + assert_eq!(e.bmAttributes, 0x02); + assert_eq!(u16::from(e.wMaxPacketSize), 0x0040); + assert_eq!(e.bInterval, 0); + + let i = c + .get_interface_descriptor(3, 0) + .expect("could not get interface descriptor 3 alt setting 0"); + assert_eq!(i.bInterfaceNumber, 3); + assert_eq!(i.bAlternateSetting, 0); + assert_eq!(i.bNumEndpoints, 2); + assert_eq!(i.bInterfaceClass, 0xff); + assert_eq!(i.bInterfaceSubClass, 0x50); + assert_eq!(i.bInterfaceProtocol, 0x01); + assert_eq!(i.iInterface, 7); + + let e = i + .get_endpoint_descriptor(0) + .expect("could not get endpoint 0 descriptor"); + assert_eq!(e.bEndpointAddress, 0x84); + assert_eq!(e.bmAttributes, 0x02); + assert_eq!(u16::from(e.wMaxPacketSize), 0x0010); + assert_eq!(e.bInterval, 10); + + let e = i + .get_endpoint_descriptor(1) + .expect("could not get endpoint 1 descriptor"); + assert_eq!(e.bEndpointAddress, 0x04); + assert_eq!(e.bmAttributes, 0x02); + assert_eq!(u16::from(e.wMaxPacketSize), 0x0010); + assert_eq!(e.bInterval, 0); + + let i = c + .get_interface_descriptor(4, 0) + .expect("could not get interface descriptor 4 alt setting 0"); + assert_eq!(i.bInterfaceNumber, 4); + assert_eq!(i.bAlternateSetting, 0); + assert_eq!(i.bNumEndpoints, 2); + assert_eq!(i.bInterfaceClass, 0xff); + assert_eq!(i.bInterfaceSubClass, 0x50); + assert_eq!(i.bInterfaceProtocol, 0x01); + assert_eq!(i.iInterface, 8); + + let e = i + .get_endpoint_descriptor(0) + .expect("could not get endpoint 0 descriptor"); + assert_eq!(e.bEndpointAddress, 0x85); + assert_eq!(e.bmAttributes, 0x02); + assert_eq!(u16::from(e.wMaxPacketSize), 0x0010); + assert_eq!(e.bInterval, 10); + + let e = i + .get_endpoint_descriptor(1) + .expect("could not get endpoint 1 descriptor"); + assert_eq!(e.bEndpointAddress, 0x05); + assert_eq!(e.bmAttributes, 0x02); + assert_eq!(u16::from(e.wMaxPacketSize), 0x0010); + assert_eq!(e.bInterval, 0); + + let i = c + .get_interface_descriptor(5, 0) + .expect("could not get interface descriptor 5 alt setting 0"); + assert_eq!(i.bInterfaceNumber, 5); + assert_eq!(i.bAlternateSetting, 0); + assert_eq!(i.bNumEndpoints, 2); + assert_eq!(i.bInterfaceClass, 0xff); + assert_eq!(i.bInterfaceSubClass, 0x53); + assert_eq!(i.bInterfaceProtocol, 0xff); + assert_eq!(i.iInterface, 9); + + let e = i + .get_endpoint_descriptor(0) + .expect("could not get endpoint 0 descriptor"); + assert_eq!(e.bEndpointAddress, 0x86); + assert_eq!(e.bmAttributes, 0x02); + assert_eq!(u16::from(e.wMaxPacketSize), 0x0040); + assert_eq!(e.bInterval, 10); + + let e = i + .get_endpoint_descriptor(1) + .expect("could not get endpoint 1 descriptor"); + assert_eq!(e.bEndpointAddress, 0x06); + assert_eq!(e.bmAttributes, 0x02); + assert_eq!(u16::from(e.wMaxPacketSize), 0x0040); + assert_eq!(e.bInterval, 0); + } + + #[test] + fn parse_descriptors_adb() { + let data: &[u8] = &[ + 0x12, 0x01, 0x00, 0x02, 0x00, 0x00, 0x00, 0x40, 0xd1, 0x18, 0xe7, 0x4e, 0x10, 0x03, + 0x01, 0x02, 0x03, 0x01, 0x09, 0x02, 0x20, 0x00, 0x01, 0x01, 0x00, 0x80, 0xfa, 0x09, + 0x04, 0x00, 0x00, 0x02, 0xff, 0x42, 0x01, 0x05, 0x07, 0x05, 0x01, 0x02, 0x00, 0x02, + 0x00, 0x07, 0x05, 0x81, 0x02, 0x00, 0x02, 0x00, + ]; + + let d = parse_usbfs_descriptors(data).expect("parse_usbfs_descriptors failed"); + + // The seemingly-redundant u16::from() calls avoid borrows of packed fields. + + assert_eq!(u16::from(d.bcdUSB), 0x02_00); + assert_eq!(d.bDeviceClass, 0x00); + assert_eq!(d.bDeviceSubClass, 0x00); + assert_eq!(d.bDeviceProtocol, 0x00); + assert_eq!(d.bMaxPacketSize0, 64); + assert_eq!(u16::from(d.idVendor), 0x18d1); + assert_eq!(u16::from(d.idProduct), 0x4ee7); + assert_eq!(u16::from(d.bcdDevice), 0x03_10); + assert_eq!(d.iManufacturer, 1); + assert_eq!(d.iProduct, 2); + assert_eq!(d.iSerialNumber, 3); + assert_eq!(d.bNumConfigurations, 1); + + let c = d + .get_config_descriptor(1) + .expect("could not get config descriptor 1"); + assert_eq!(u16::from(c.wTotalLength), 32); + assert_eq!(c.bNumInterfaces, 1); + assert_eq!(c.bConfigurationValue, 1); + assert_eq!(c.iConfiguration, 0); + assert_eq!(c.bmAttributes, 0x80); + assert_eq!(c.bMaxPower, 250); + + let i = c + .get_interface_descriptor(0, 0) + .expect("could not get interface descriptor 0 alt setting 0"); + assert_eq!(i.bInterfaceNumber, 0); + assert_eq!(i.bAlternateSetting, 0); + assert_eq!(i.bNumEndpoints, 2); + assert_eq!(i.bInterfaceClass, 0xff); + assert_eq!(i.bInterfaceSubClass, 0x42); + assert_eq!(i.bInterfaceProtocol, 0x01); + assert_eq!(i.iInterface, 5); + + let e = i + .get_endpoint_descriptor(0) + .expect("could not get endpoint 0 descriptor"); + assert_eq!(e.bEndpointAddress, 0x01); + assert_eq!(e.bmAttributes, 0x02); + assert_eq!(u16::from(e.wMaxPacketSize), 0x200); + assert_eq!(e.bInterval, 0); + + let e = i + .get_endpoint_descriptor(1) + .expect("could not get endpoint 1 descriptor"); + assert_eq!(e.bEndpointAddress, 0x81); + assert_eq!(e.bmAttributes, 0x02); + assert_eq!(u16::from(e.wMaxPacketSize), 0x0200); + assert_eq!(e.bInterval, 0); + } +} diff --git a/usb_util/src/device.rs b/usb_util/src/device.rs new file mode 100644 index 0000000..3fc77e2 --- /dev/null +++ b/usb_util/src/device.rs @@ -0,0 +1,458 @@ +// Copyright 2019 The Chromium OS Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +use crate::{ + control_request_type, descriptor, ConfigDescriptorTree, + ControlRequestDataPhaseTransferDirection, ControlRequestRecipient, ControlRequestType, + DeviceDescriptor, DeviceDescriptorTree, Error, Result, StandardControlRequest, +}; +use libc::{EAGAIN, ENODEV, ENOENT}; +use std::convert::TryInto; +use std::fs::File; +use std::io::{Seek, SeekFrom}; +use std::mem::{size_of, size_of_val}; +use std::os::raw::{c_int, c_uint, c_ulong, c_void}; +use std::sync::Arc; +use sys_util::handle_eintr_errno; + +/// Device represents a USB device. +pub struct Device { + fd: Arc<File>, + device_descriptor_tree: DeviceDescriptorTree, +} + +/// Transfer contains the information necessary to submit a USB request +/// and, once it has been submitted and completed, contains the response. +pub struct Transfer { + // NOTE: This Vec is actually a single URB with a trailing + // variable-length field created by vec_with_array_field(). + urb: Vec<usb_sys::usbdevfs_urb>, + pub buffer: Vec<u8>, + callback: Option<Box<dyn Fn(Transfer) + Send + Sync>>, +} + +/// TransferHandle is a handle that allows cancellation of in-flight transfers +/// between submit_transfer() and get_completed_transfer(). +/// Attempting to cancel a transfer that has already completed is safe and will +/// return an error. +pub struct TransferHandle { + weak_transfer: std::sync::Weak<Transfer>, + fd: std::sync::Weak<File>, +} + +#[derive(PartialEq)] +pub enum TransferStatus { + Completed, + Error, + Cancelled, + NoDevice, +} + +impl Device { + /// Create a new `Device` from a file descriptor. + /// `fd` should be a file in usbdevfs (e.g. `/dev/bus/usb/001/002`). + pub fn new(mut fd: File) -> Result<Self> { + fd.seek(SeekFrom::Start(0)).map_err(Error::DescriptorRead)?; + let device_descriptor_tree = descriptor::parse_usbfs_descriptors(&mut fd)?; + + let device = Device { + fd: Arc::new(fd), + device_descriptor_tree, + }; + Ok(device) + } + + pub fn fd(&self) -> Arc<File> { + self.fd.clone() + } + + unsafe fn ioctl(&self, nr: c_ulong) -> Result<i32> { + let ret = handle_eintr_errno!(sys_util::ioctl(&*self.fd, nr)); + if ret < 0 { + return Err(Error::IoctlFailed(nr, sys_util::Error::last())); + } + Ok(ret) + } + + unsafe fn ioctl_with_ref<T>(&self, nr: c_ulong, arg: &T) -> Result<i32> { + let ret = handle_eintr_errno!(sys_util::ioctl_with_ref(&*self.fd, nr, arg)); + if ret < 0 { + return Err(Error::IoctlFailed(nr, sys_util::Error::last())); + } + Ok(ret) + } + + unsafe fn ioctl_with_mut_ref<T>(&self, nr: c_ulong, arg: &mut T) -> Result<i32> { + let ret = handle_eintr_errno!(sys_util::ioctl_with_mut_ref(&*self.fd, nr, arg)); + if ret < 0 { + return Err(Error::IoctlFailed(nr, sys_util::Error::last())); + } + Ok(ret) + } + + unsafe fn ioctl_with_mut_ptr<T>(&self, nr: c_ulong, arg: *mut T) -> Result<i32> { + let ret = handle_eintr_errno!(sys_util::ioctl_with_mut_ptr(&*self.fd, nr, arg)); + if ret < 0 { + return Err(Error::IoctlFailed(nr, sys_util::Error::last())); + } + Ok(ret) + } + + /// Submit a transfer to the device. + /// The transfer will be processed asynchronously by the device. + /// Call `poll_transfers()` on this device to check for completed transfers. + pub fn submit_transfer(&mut self, transfer: Transfer) -> Result<TransferHandle> { + let mut rc_transfer = Arc::new(transfer); + + // Technically, Arc::from_raw() should only be called on pointers returned + // from Arc::into_raw(). However, we need to stash this value inside the + // Arc<Transfer> itself, so we manually calculate the address that would be + // returned from Arc::into_raw() via Deref and then call Arc::into_raw() + // to forget the Arc without dropping its contents. + // Do not remove the into_raw() call! + let raw_transfer = (&*rc_transfer) as *const Transfer as usize; + match Arc::get_mut(&mut rc_transfer) { + Some(t) => t.urb_mut().usercontext = raw_transfer, + None => { + // This should never happen, since there is only one strong reference + // at this point. + return Err(Error::RcGetMutFailed); + } + } + let _ = Arc::into_raw(rc_transfer.clone()); + + let urb_ptr = rc_transfer.urb.as_ptr() as *mut usb_sys::usbdevfs_urb; + + // Safe because we control the lifetime of the URB via Arc::into_raw() and + // Arc::from_raw() in poll_transfers(). + unsafe { + self.ioctl_with_mut_ptr(usb_sys::USBDEVFS_SUBMITURB(), urb_ptr)?; + } + + let weak_transfer = Arc::downgrade(&rc_transfer); + + Ok(TransferHandle { + weak_transfer, + fd: Arc::downgrade(&self.fd), + }) + } + + /// Check for completed asynchronous transfers submitted via `submit_transfer()`. + /// The callback for each completed transfer will be called. + pub fn poll_transfers(&self) -> Result<()> { + // Reap completed transfers until we get EAGAIN. + loop { + let mut urb_ptr: *mut usb_sys::usbdevfs_urb = std::ptr::null_mut(); + // Safe because we provide a valid urb_ptr to be filled by the kernel. + let result = + unsafe { self.ioctl_with_mut_ref(usb_sys::USBDEVFS_REAPURBNDELAY(), &mut urb_ptr) }; + match result { + Err(Error::IoctlFailed(_nr, e)) => { + if e.errno() == EAGAIN { + // No more completed transfers right now. + break; + } + } + Err(e) => return Err(e), + Ok(_) => {} + } + + if urb_ptr.is_null() { + break; + } + + // Safe because the URB usercontext field is always set to the result of + // Arc::into_raw() in submit_transfer(). + let rc_transfer: Arc<Transfer> = + unsafe { Arc::from_raw((*urb_ptr).usercontext as *const Transfer) }; + + // There should always be exactly one strong reference to rc_transfer, + // so try_unwrap() should never fail. + let mut transfer = Arc::try_unwrap(rc_transfer).map_err(|_| Error::RcUnwrapFailed)?; + + if let Some(cb) = transfer.callback.take() { + cb(transfer); + } + } + + Ok(()) + } + + /// Perform a USB port reset to reinitialize a device. + pub fn reset(&self) -> Result<()> { + // Safe because self.fd is a valid usbdevfs file descriptor. + let result = unsafe { self.ioctl(usb_sys::USBDEVFS_RESET()) }; + + if let Err(Error::IoctlFailed(_nr, errno_err)) = result { + // The device may disappear after a reset if e.g. its firmware changed. + // Treat that as success. + if errno_err.errno() == libc::ENODEV { + return Ok(()); + } + } + + result?; + Ok(()) + } + + /// Claim an interface on this device. + pub fn claim_interface(&self, interface_number: u8) -> Result<()> { + let disconnect_claim = usb_sys::usbdevfs_disconnect_claim { + interface: interface_number.into(), + flags: 0, + driver: [0u8; 256], + }; + // Safe because self.fd is a valid usbdevfs file descriptor and we pass a valid + // pointer to a usbdevs_disconnect_claim structure. + unsafe { + self.ioctl_with_ref(usb_sys::USBDEVFS_DISCONNECT_CLAIM(), &disconnect_claim)?; + } + + Ok(()) + } + + /// Release an interface previously claimed with `claim_interface()`. + pub fn release_interface(&self, interface_number: u8) -> Result<()> { + let ifnum: c_uint = interface_number.into(); + // Safe because self.fd is a valid usbdevfs file descriptor and we pass a valid + // pointer to unsigned int. + unsafe { + self.ioctl_with_ref(usb_sys::USBDEVFS_RELEASEINTERFACE(), &ifnum)?; + } + + Ok(()) + } + + /// Activate an alternate setting for an interface. + pub fn set_interface_alt_setting( + &self, + interface_number: u8, + alternative_setting: u8, + ) -> Result<()> { + let setinterface = usb_sys::usbdevfs_setinterface { + interface: interface_number.into(), + altsetting: alternative_setting.into(), + }; + // Safe because self.fd is a valid usbdevfs file descriptor and we pass a valid + // pointer to a usbdevfs_setinterface structure. + unsafe { + self.ioctl_with_ref(usb_sys::USBDEVFS_SETINTERFACE(), &setinterface)?; + } + Ok(()) + } + + /// Set active configuration for this device. + pub fn set_active_configuration(&mut self, config: u8) -> Result<()> { + let config: c_int = config.into(); + // Safe because self.fd is a valid usbdevfs file descriptor and we pass a valid + // pointer to int. + unsafe { + self.ioctl_with_ref(usb_sys::USBDEVFS_SETCONFIGURATION(), &config)?; + } + + Ok(()) + } + + /// Get the device descriptor of this device. + pub fn get_device_descriptor(&self) -> Result<DeviceDescriptor> { + Ok(*self.device_descriptor_tree) + } + + /// Get active config descriptor of this device. + pub fn get_active_config_descriptor(&self) -> Result<ConfigDescriptorTree> { + let active_config = self.get_active_configuration()?; + match self + .device_descriptor_tree + .get_config_descriptor(active_config) + { + Some(config_descriptor) => Ok(config_descriptor.clone()), + None => Err(Error::NoSuchDescriptor), + } + } + + /// Get bConfigurationValue of the currently active configuration. + pub fn get_active_configuration(&self) -> Result<u8> { + // Send a synchronous control transfer to get the active configuration. + let mut active_config: u8 = 0; + let ctrl_transfer = usb_sys::usbdevfs_ctrltransfer { + bRequestType: control_request_type( + ControlRequestType::Standard, + ControlRequestDataPhaseTransferDirection::DeviceToHost, + ControlRequestRecipient::Device, + ), + bRequest: StandardControlRequest::GetConfiguration as u8, + wValue: 0, + wIndex: 0, + wLength: size_of_val(&active_config) as u16, + timeout: 5000, // milliseconds + data: &mut active_config as *mut u8 as *mut c_void, + }; + // Safe because self.fd is a valid usbdevfs file descriptor and we pass a valid + // pointer to a usbdevfs_ctrltransfer structure. + unsafe { + self.ioctl_with_ref(usb_sys::USBDEVFS_CONTROL(), &ctrl_transfer)?; + } + Ok(active_config) + } + + /// Clear the halt/stall condition for an endpoint. + pub fn clear_halt(&self, ep_addr: u8) -> Result<()> { + let endpoint: c_uint = ep_addr.into(); + // Safe because self.fd is a valid usbdevfs file descriptor and we pass a valid + // pointer to unsigned int. + unsafe { + self.ioctl_with_ref(usb_sys::USBDEVFS_CLEAR_HALT(), &endpoint)?; + } + + Ok(()) + } +} + +// Returns a `Vec<T>` with a size in bytes at least as large as `size_in_bytes`. +fn vec_with_size_in_bytes<T: Default>(size_in_bytes: usize) -> Vec<T> { + let rounded_size = (size_in_bytes + size_of::<T>() - 1) / size_of::<T>(); + let mut v = Vec::with_capacity(rounded_size); + for _ in 0..rounded_size { + v.push(T::default()) + } + v +} + +// This function has been borrowed from kvm - see the doc comment there for details. +fn vec_with_array_field<T: Default, F>(count: usize) -> Vec<T> { + let element_space = count * size_of::<F>(); + let vec_size_bytes = size_of::<T>() + element_space; + vec_with_size_in_bytes(vec_size_bytes) +} + +impl Transfer { + fn urb(&self) -> &usb_sys::usbdevfs_urb { + // self.urb is a Vec created with `vec_with_array_field`; the first entry is + // the URB itself. + &self.urb[0] + } + + fn urb_mut(&mut self) -> &mut usb_sys::usbdevfs_urb { + &mut self.urb[0] + } + + fn new( + transfer_type: u8, + endpoint: u8, + buffer: Vec<u8>, + iso_packets: &[usb_sys::usbdevfs_iso_packet_desc], + ) -> Result<Transfer> { + let mut transfer = Transfer { + urb: vec_with_array_field::<usb_sys::usbdevfs_urb, usb_sys::usbdevfs_iso_packet_desc>( + iso_packets.len(), + ), + buffer, + callback: None, + }; + + transfer.urb_mut().urb_type = transfer_type; + transfer.urb_mut().endpoint = endpoint; + transfer.urb_mut().buffer = transfer.buffer.as_mut_ptr() as *mut c_void; + transfer.urb_mut().buffer_length = transfer + .buffer + .len() + .try_into() + .map_err(Error::InvalidBufferLength)?; + + // Safe because we ensured there is enough space in transfer.urb to hold the number of + // isochronous frames required. + let iso_frame_desc = unsafe { + transfer + .urb_mut() + .iso_frame_desc + .as_mut_slice(iso_packets.len()) + }; + iso_frame_desc.copy_from_slice(iso_packets); + + Ok(transfer) + } + + /// Create a control transfer. + pub fn new_control(buffer: Vec<u8>) -> Result<Transfer> { + let endpoint = 0; + Self::new(usb_sys::USBDEVFS_URB_TYPE_CONTROL, endpoint, buffer, &[]) + } + + /// Create an interrupt transfer. + pub fn new_interrupt(endpoint: u8, buffer: Vec<u8>) -> Result<Transfer> { + Self::new(usb_sys::USBDEVFS_URB_TYPE_INTERRUPT, endpoint, buffer, &[]) + } + + /// Create a bulk transfer. + pub fn new_bulk(endpoint: u8, buffer: Vec<u8>) -> Result<Transfer> { + Self::new(usb_sys::USBDEVFS_URB_TYPE_BULK, endpoint, buffer, &[]) + } + + /// Create an isochronous transfer. + pub fn new_isochronous(endpoint: u8, buffer: Vec<u8>) -> Result<Transfer> { + // TODO(dverkamp): allow user to specify iso descriptors + Self::new(usb_sys::USBDEVFS_URB_TYPE_ISO, endpoint, buffer, &[]) + } + + /// Get the status of a completed transfer. + pub fn status(&self) -> TransferStatus { + let status = self.urb().status; + if status == 0 { + TransferStatus::Completed + } else if status == -ENODEV { + TransferStatus::NoDevice + } else if status == -ENOENT { + TransferStatus::Cancelled + } else { + TransferStatus::Error + } + } + + /// Get the actual amount of data transferred, which may be less than + /// the original length. + pub fn actual_length(&self) -> usize { + self.urb().actual_length as usize + } + + /// Set callback function for transfer completion. + pub fn set_callback<C: 'static + Fn(Transfer) + Send + Sync>(&mut self, cb: C) { + self.callback = Some(Box::new(cb)); + } +} + +impl TransferHandle { + /// Attempt to cancel the transfer associated with this `TransferHandle`. + /// Safe to call even if the transfer has already completed; + /// `Error::TransferAlreadyCompleted` will be returned in this case. + pub fn cancel(self) -> Result<()> { + let rc_transfer = match self.weak_transfer.upgrade() { + None => return Err(Error::TransferAlreadyCompleted), + Some(rc_transfer) => rc_transfer, + }; + + let urb_ptr = rc_transfer.urb.as_ptr() as *mut usb_sys::usbdevfs_urb; + let fd = match self.fd.upgrade() { + None => return Err(Error::NoDevice), + Some(fd) => fd, + }; + + // Safe because fd is a valid usbdevfs file descriptor and we pass a valid + // pointer to a usbdevfs_urb structure. + if unsafe { + handle_eintr_errno!(sys_util::ioctl_with_mut_ptr( + &*fd, + usb_sys::USBDEVFS_DISCARDURB(), + urb_ptr + )) + } < 0 + { + return Err(Error::IoctlFailed( + usb_sys::USBDEVFS_DISCARDURB(), + sys_util::Error::last(), + )); + } + + Ok(()) + } +} diff --git a/usb_util/src/device_handle.rs b/usb_util/src/device_handle.rs deleted file mode 100644 index 17b0f68..0000000 --- a/usb_util/src/device_handle.rs +++ /dev/null @@ -1,161 +0,0 @@ -// Copyright 2018 The Chromium OS Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -use std::os::raw::c_int; -use std::sync::Arc; - -use crate::bindings; -use crate::error::{Error, Result}; -use crate::libusb_context::LibUsbContextInner; -use crate::libusb_device::LibUsbDevice; -use crate::usb_transfer::{TransferCanceller, UsbTransfer, UsbTransferBuffer}; - -/// DeviceHandle wraps libusb_device_handle. -pub struct DeviceHandle { - _context: Arc<LibUsbContextInner>, - handle: *mut bindings::libusb_device_handle, -} - -unsafe impl Send for DeviceHandle {} - -impl Drop for DeviceHandle { - fn drop(&mut self) { - // Safe because self.handle is a valid pointer to libusb_device_handle. - unsafe { - bindings::libusb_close(self.handle); - } - } -} - -impl DeviceHandle { - /// Create a new DeviceHande. 'handle' should be a valid pointer to libusb_device_handle. - pub unsafe fn new( - ctx: Arc<LibUsbContextInner>, - handle: *mut bindings::libusb_device_handle, - ) -> DeviceHandle { - DeviceHandle { - _context: ctx, - handle, - } - } - - /// Get corresponding usb device. - pub fn get_device(&self) -> LibUsbDevice { - // Safe because 'self.handle' is a valid pointer to device handle and libusb_get_device() - // always returns a valid device. - unsafe { - LibUsbDevice::new( - self._context.clone(), - bindings::libusb_get_device(self.handle), - ) - } - } - - /// Reset this usb device. - pub fn reset(&self) -> Result<()> { - // Safe because 'self.handle' is a valid pointer to device handle. - try_libusb!(unsafe { bindings::libusb_reset_device(self.handle) }); - Ok(()) - } - /// Get bConfigurationValue of the currently active configuration. - pub fn get_active_configuration(&self) -> Result<i32> { - let mut config: c_int = 0; - // Safe because 'self.handle' is a valid pointer to device handle and '&mut config' is a - // valid output location. - try_libusb!(unsafe { bindings::libusb_get_configuration(self.handle, &mut config) }); - Ok(config as i32) - } - - /// Set active configuration for a device. - pub fn set_active_configuration(&mut self, config: i32) -> Result<()> { - // Safe because 'self.handle' is a valid pointer to device handle. - try_libusb!(unsafe { bindings::libusb_set_configuration(self.handle, config as c_int) }); - Ok(()) - } - - /// Claim an interface on this deivce handle. - pub fn claim_interface(&self, interface_number: i32) -> Result<()> { - // Safe because 'self.handle' is a valid pointer to device handle. - try_libusb!(unsafe { bindings::libusb_claim_interface(self.handle, interface_number) }); - Ok(()) - } - - /// Release an interface previously claimed with libusb_claim_interface. - pub fn release_interface(&self, interface_number: i32) -> Result<()> { - // Safe because 'self.handle' is a valid pointer to device handle. - try_libusb!(unsafe { bindings::libusb_release_interface(self.handle, interface_number) }); - Ok(()) - } - - /// Perform a USB port reset to reinitialize a device. - pub fn reset_device(&self) -> Result<()> { - // Safe because 'self.handle' is a valid pointer to device handle. - try_libusb!(unsafe { bindings::libusb_reset_device(self.handle) }); - Ok(()) - } - - /// Determine if a kernel driver is active on an interface. - pub fn kernel_driver_active(&self, interface_number: i32) -> Result<bool> { - // Safe because 'self.handle' is a valid pointer to device handle. - let v = try_libusb!(unsafe { - bindings::libusb_kernel_driver_active(self.handle, interface_number) - }); - Ok(v != 0) - } - - /// Detach a kernel driver from an interface. - pub fn detach_kernel_driver(&self, interface_number: i32) -> Result<()> { - // Safe because 'self.handle' is a valid pointer to device handle. - try_libusb!(unsafe { - bindings::libusb_detach_kernel_driver(self.handle, interface_number) - }); - Ok(()) - } - - /// Re-attach an interfae's kernel driver, which was previously detached using - /// detach_kernel_driver. - pub fn attach_kernel_driver(&self, interface_number: i32) -> Result<()> { - // Safe because 'self.handle' is a valid pointer to device handle. - try_libusb!(unsafe { - bindings::libusb_attach_kernel_driver(self.handle, interface_number) - }); - Ok(()) - } - - /// Active an alternate setting for an interface. - pub fn set_interface_alt_setting( - &self, - interface_number: i32, - alternative_setting: i32, - ) -> Result<()> { - // Safe because 'self.handle' is a valid pointer to device handle. - try_libusb!(unsafe { - bindings::libusb_set_interface_alt_setting( - self.handle, - interface_number, - alternative_setting, - ) - }); - Ok(()) - } - - /// Clear the halt/stall condition for an endpoint. - pub fn clear_halt(&self, endpoint: u8) -> Result<()> { - // Safe because 'self.handle' is a valid pointer to device handle. - try_libusb!(unsafe { bindings::libusb_clear_halt(self.handle, endpoint) }); - Ok(()) - } - - /// Libusb asynchronous I/O interface has a 5 step process. It gives lots of - /// flexibility but makes it hard to manage object life cycle and easy to - /// write unsafe code. We wrap this interface to a simple "transfer" and "cancel" - /// interface. Resubmission is not supported and deallocation is handled safely - /// here. - pub fn submit_async_transfer<T: UsbTransferBuffer>( - &self, - transfer: UsbTransfer<T>, - ) -> Result<TransferCanceller> { - unsafe { transfer.submit(self.handle) } - } -} diff --git a/usb_util/src/endpoint_descriptor.rs b/usb_util/src/endpoint_descriptor.rs deleted file mode 100644 index 29eb4ea..0000000 --- a/usb_util/src/endpoint_descriptor.rs +++ /dev/null @@ -1,57 +0,0 @@ -// Copyright 2018 The Chromium OS Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -use std::ops::Deref; - -use crate::bindings::libusb_endpoint_descriptor; -use crate::types::{EndpointDirection, EndpointType}; - -/// EndpointDescriptor wraps libusb_endpoint_descriptor. -pub struct EndpointDescriptor<'a>(&'a libusb_endpoint_descriptor); - -const ENDPOINT_DESCRIPTOR_DIRECTION_MASK: u8 = 1 << 7; -const ENDPOINT_DESCRIPTOR_NUMBER_MASK: u8 = 0xf; -const ENDPOINT_DESCRIPTOR_ATTRIBUTES_TYPE_MASK: u8 = 0x3; - -impl<'a> EndpointDescriptor<'a> { - // Create new endpoint descriptor. - pub fn new(descriptor: &libusb_endpoint_descriptor) -> EndpointDescriptor { - EndpointDescriptor(descriptor) - } - - // Get direction of this endpoint. - pub fn get_direction(&self) -> EndpointDirection { - let direction = self.0.bEndpointAddress & ENDPOINT_DESCRIPTOR_DIRECTION_MASK; - if direction > 0 { - EndpointDirection::DeviceToHost - } else { - EndpointDirection::HostToDevice - } - } - - // Get endpoint number. - pub fn get_endpoint_number(&self) -> u8 { - self.0.bEndpointAddress & ENDPOINT_DESCRIPTOR_NUMBER_MASK - } - - // Get endpoint type. - pub fn get_endpoint_type(&self) -> Option<EndpointType> { - let ep_type = self.0.bmAttributes & ENDPOINT_DESCRIPTOR_ATTRIBUTES_TYPE_MASK; - match ep_type { - 0 => Some(EndpointType::Control), - 1 => Some(EndpointType::Isochronous), - 2 => Some(EndpointType::Bulk), - 3 => Some(EndpointType::Interrupt), - _ => None, - } - } -} - -impl<'a> Deref for EndpointDescriptor<'a> { - type Target = libusb_endpoint_descriptor; - - fn deref(&self) -> &libusb_endpoint_descriptor { - self.0 - } -} diff --git a/usb_util/src/error.rs b/usb_util/src/error.rs index b6dd91e..24d8036 100644 --- a/usb_util/src/error.rs +++ b/usb_util/src/error.rs @@ -1,85 +1,52 @@ -// Copyright 2018 The Chromium OS Authors. All rights reserved. +// Copyright 2019 The Chromium OS Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +use libc::c_ulong; +use remain::sorted; use std; -use std::fmt; +use std::fmt::{self, Display}; +use std::io; +use std::num; -use crate::bindings; - -/// Error type for libusb. +#[sorted] +#[derive(Debug)] pub enum Error { - Success(i32), - IO, - InvalidParam, - Access, + DescriptorParse, + DescriptorRead(io::Error), + FdCloneFailed(io::Error), + InvalidActualLength(num::TryFromIntError), + InvalidBufferLength(num::TryFromIntError), + IoctlFailed(c_ulong, sys_util::Error), NoDevice, - NotFound, - Busy, - Timeout, - Overflow, - Pipe, - Interrupted, - NoMem, - NotSupported, - Other, + NoSuchDescriptor, + RcGetMutFailed, + RcUnwrapFailed, + TransferAlreadyCompleted, } -impl fmt::Debug for Error { +impl Display for Error { + #[remain::check] fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - match *self { - Error::Success(_v) => write!(f, "Success (no error)"), - Error::IO => write!(f, "Input/output error"), - Error::InvalidParam => write!(f, "Invalid parameter"), - Error::Access => write!(f, "Access denied (insufficient permissions)"), - Error::NoDevice => write!(f, "No such device (it may have been disconnected)"), - Error::NotFound => write!(f, "Entity not found"), - Error::Busy => write!(f, "Resource busy"), - Error::Timeout => write!(f, "Operation timed out"), - Error::Overflow => write!(f, "Overflow"), - Error::Pipe => write!(f, "Pipe error"), - Error::Interrupted => write!(f, "System call interrupted (perhaps due to signal)"), - Error::NoMem => write!(f, "Insufficient memory"), - Error::NotSupported => write!( - f, - "Operation not supported or unimplemented on this platform" - ), - Error::Other => write!(f, "Other error"), - } - } -} + use self::Error::*; -impl From<bindings::libusb_error> for Error { - fn from(e: bindings::libusb_error) -> Self { - match e { - bindings::LIBUSB_ERROR_IO => Error::IO, - bindings::LIBUSB_ERROR_INVALID_PARAM => Error::InvalidParam, - bindings::LIBUSB_ERROR_ACCESS => Error::Access, - bindings::LIBUSB_ERROR_NO_DEVICE => Error::NoDevice, - bindings::LIBUSB_ERROR_NOT_FOUND => Error::NotFound, - bindings::LIBUSB_ERROR_BUSY => Error::Busy, - bindings::LIBUSB_ERROR_TIMEOUT => Error::Timeout, - bindings::LIBUSB_ERROR_OVERFLOW => Error::Overflow, - bindings::LIBUSB_ERROR_PIPE => Error::Pipe, - bindings::LIBUSB_ERROR_INTERRUPTED => Error::Interrupted, - bindings::LIBUSB_ERROR_NO_MEM => Error::NoMem, - bindings::LIBUSB_ERROR_NOT_SUPPORTED => Error::NotSupported, - bindings::LIBUSB_ERROR_OTHER => Error::Other, - // All possible errors are defined above, other values mean success, - // see libusb_get_device_list for example. - _ => Error::Success(e), + #[sorted] + match self { + DescriptorParse => write!(f, "parsing descriptors failed"), + DescriptorRead(e) => write!(f, "reading descriptors from device failed: {}", e), + FdCloneFailed(e) => write!(f, "File::try_clone() failed: {}", e), + InvalidActualLength(e) => write!(f, "invalid actual_length in URB: {}", e), + InvalidBufferLength(e) => write!(f, "invalid transfer buffer length: {}", e), + IoctlFailed(nr, e) => write!(f, "USB ioctl 0x{:x} failed: {}", nr, e), + NoDevice => write!(f, "Device has been removed"), + NoSuchDescriptor => write!(f, "Requested descriptor not found"), + RcGetMutFailed => write!(f, "Rc::get_mut failed"), + RcUnwrapFailed => write!(f, "Rc::try_unwrap failed"), + TransferAlreadyCompleted => write!(f, "attempted to cancel already-completed transfer"), } } } pub type Result<T> = std::result::Result<T, Error>; -#[macro_export] -macro_rules! try_libusb { - ($x:expr) => { - match Error::from($x as i32) { - Error::Success(e) => e, - err => return Err(err), - } - }; -} +impl std::error::Error for Error {} diff --git a/usb_util/src/hotplug.rs b/usb_util/src/hotplug.rs deleted file mode 100644 index e131ab9..0000000 --- a/usb_util/src/hotplug.rs +++ /dev/null @@ -1,77 +0,0 @@ -// Copyright 2019 The Chromium OS Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -use std::os::raw::{c_int, c_void}; -use std::sync::Arc; - -use crate::bindings; -use crate::libusb_context::LibUsbContextInner; -use crate::libusb_device::LibUsbDevice; - -#[derive(PartialEq)] -pub enum HotplugEvent { - DeviceArrived, - DeviceLeft, -} - -impl HotplugEvent { - /// Create a new HotplugEvent from raw libusb_hotplug_event. - pub fn new(event: bindings::libusb_hotplug_event) -> Self { - match event { - bindings::LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED => HotplugEvent::DeviceArrived, - bindings::LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT => HotplugEvent::DeviceLeft, - _ => { - // TODO(jkwang) handle this with option. - // libusb_hotplug_event is a C enum. - panic!("Invaild libusb_hotplug_event"); - } - } - } -} - -pub trait UsbHotplugHandler: Send + Sync + 'static { - fn hotplug_event(&self, device: LibUsbDevice, event: HotplugEvent); -} - -/// UsbHotplugHandlerHolder owns UsbHotplugHandler and LibUsbContext. It will be passed as -/// user_data to libusb_hotplug_register_callback. -pub struct UsbHotplugHandlerHolder { - context: Arc<LibUsbContextInner>, - handler: Box<dyn UsbHotplugHandler>, -} - -impl UsbHotplugHandlerHolder { - /// Create UsbHotplugHandlerHodler from context and handler. - pub fn new<H: UsbHotplugHandler>( - context: Arc<LibUsbContextInner>, - handler: H, - ) -> Box<UsbHotplugHandlerHolder> { - let holder = UsbHotplugHandlerHolder { - context, - handler: Box::new(handler), - }; - Box::new(holder) - } -} - -/// This function is safe when: -/// libusb_device is allocated by libusb -/// user_data points to valid UsbHotPlugHandlerHolder released from Box. -/// -/// Do not invoke this function. It should only be used as a callback for -/// libusb_hotplug_register_callback. -pub unsafe extern "C" fn hotplug_cb( - _: *mut bindings::libusb_context, - device: *mut bindings::libusb_device, - event: bindings::libusb_hotplug_event, - user_data: *mut c_void, -) -> c_int { - // Safe because user_data was casted from holder. - let holder = &*(user_data as *mut UsbHotplugHandlerHolder); - let device = LibUsbDevice::new(holder.context.clone(), device); - let event = HotplugEvent::new(event); - holder.handler.hotplug_event(device, event); - // The handler should always succeed. - bindings::LIBUSB_SUCCESS -} diff --git a/usb_util/src/interface_descriptor.rs b/usb_util/src/interface_descriptor.rs deleted file mode 100644 index a2bf1b2..0000000 --- a/usb_util/src/interface_descriptor.rs +++ /dev/null @@ -1,40 +0,0 @@ -// Copyright 2018 The Chromium OS Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -use std::ops::Deref; - -use crate::bindings::libusb_interface_descriptor; -use crate::endpoint_descriptor::EndpointDescriptor; - -/// InterfaceDescriptor wraps libusb_interface_descriptor. -pub struct InterfaceDescriptor<'a>(&'a libusb_interface_descriptor); - -impl<'a> InterfaceDescriptor<'a> { - /// Create a new Interface descriptor. - pub fn new(descriptor: &'a libusb_interface_descriptor) -> InterfaceDescriptor<'a> { - InterfaceDescriptor(descriptor) - } - - /// Get endpoint descriptor at index. - pub fn endpoint_descriptor(&self, ep_idx: u8) -> Option<EndpointDescriptor> { - if ep_idx >= self.0.bNumEndpoints { - return None; - } - - // Safe because idx is checked. - unsafe { - Some(EndpointDescriptor::new( - &*(self.0.endpoint.offset(ep_idx as isize)), - )) - } - } -} - -impl<'a> Deref for InterfaceDescriptor<'a> { - type Target = libusb_interface_descriptor; - - fn deref(&self) -> &libusb_interface_descriptor { - self.0 - } -} diff --git a/usb_util/src/lib.rs b/usb_util/src/lib.rs index 07af5ad..2574d90 100644 --- a/usb_util/src/lib.rs +++ b/usb_util/src/lib.rs @@ -1,23 +1,18 @@ -// Copyright 2018 The Chromium OS Authors. All rights reserved. +// Copyright 2019 The Chromium OS Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// Generated with bindgen libusb.h -no-prepend-enum-name -o bindings.rs. -#![allow(dead_code)] -#![allow(non_camel_case_types)] -#![allow(non_snake_case)] -#![allow(non_upper_case_globals)] -#[allow(clippy::all)] -mod bindings; +mod descriptor; +mod device; +mod error; +mod types; -#[macro_use] -pub mod error; -pub mod config_descriptor; -pub mod device_handle; -pub mod endpoint_descriptor; -pub mod hotplug; -pub mod interface_descriptor; -pub mod libusb_context; -pub mod libusb_device; -pub mod types; -pub mod usb_transfer; +pub use self::descriptor::{ConfigDescriptorTree, DeviceDescriptorTree, InterfaceDescriptorTree}; +pub use self::device::{Device, Transfer, TransferStatus}; +pub use self::error::{Error, Result}; +pub use self::types::{ + control_request_type, ConfigDescriptor, ControlRequestDataPhaseTransferDirection, + ControlRequestRecipient, ControlRequestType, DeviceDescriptor, EndpointDescriptor, + EndpointDirection, EndpointType, InterfaceDescriptor, StandardControlRequest, UsbRequestSetup, + ENDPOINT_DIRECTION_OFFSET, +}; diff --git a/usb_util/src/libusb_context.rs b/usb_util/src/libusb_context.rs deleted file mode 100644 index 17a77f0..0000000 --- a/usb_util/src/libusb_context.rs +++ /dev/null @@ -1,268 +0,0 @@ -// Copyright 2018 The Chromium OS Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -use std; -#[allow(unused_imports)] -use std::os::raw::{c_long, c_short, c_void}; -use std::os::unix::io::RawFd; -use std::sync::Arc; - -use crate::bindings; -#[cfg(feature = "sandboxed-libusb")] -use crate::device_handle::DeviceHandle; -use crate::error::{Error, Result}; -use crate::hotplug::{hotplug_cb, UsbHotplugHandler, UsbHotplugHandlerHolder}; -use crate::libusb_device::LibUsbDevice; - -use sync::Mutex; - -pub struct LibUsbContextInner { - context: *mut bindings::libusb_context, - pollfd_change_handler: Mutex<Option<Box<PollfdChangeHandlerHolder>>>, -} - -// Safe because libusb_context could be accessed from multiple threads safely. -unsafe impl Send for LibUsbContextInner {} -unsafe impl Sync for LibUsbContextInner {} - -impl LibUsbContextInner { - /// Remove the previous registered notifiers. - pub fn remove_pollfd_notifiers(&self) { - // Safe because 'self.context' is valid. - unsafe { - bindings::libusb_set_pollfd_notifiers(self.context, None, None, std::ptr::null_mut()); - } - } -} - -impl Drop for LibUsbContextInner { - fn drop(&mut self) { - // Avoid pollfd change handler call when libusb_exit is called. - self.remove_pollfd_notifiers(); - // Safe beacuse 'self.context' points to a valid context allocated by libusb_init. - unsafe { - bindings::libusb_exit(self.context); - } - } -} - -/// Wrapper for libusb_context. The libusb libary initialization/deinitialization -/// is managed by this context. -/// See: http://libusb.sourceforge.net/api-1.0/group__libusb__lib.html -#[derive(Clone)] -pub struct LibUsbContext { - inner: Arc<LibUsbContextInner>, -} - -impl LibUsbContext { - /// Create a new LibUsbContext. - pub fn new() -> Result<LibUsbContext> { - let mut ctx: *mut bindings::libusb_context = std::ptr::null_mut(); - // Safe because '&mut ctx' points to a valid memory (on stack). - try_libusb!(unsafe { bindings::libusb_init(&mut ctx) }); - Ok(LibUsbContext { - inner: Arc::new(LibUsbContextInner { - context: ctx, - pollfd_change_handler: Mutex::new(None), - }), - }) - } - - #[cfg(feature = "sandboxed-libusb")] - pub fn handle_from_file(&self, f: std::fs::File) -> Result<DeviceHandle> { - use std::os::unix::io::IntoRawFd; - - let fd = f.into_raw_fd(); - let mut handle: *mut bindings::libusb_device_handle = std::ptr::null_mut(); - // Safe because fd is valid and owned, and '&mut handle' points to valid memory. - try_libusb!(unsafe { - bindings::libusb_wrap_sys_device(self.inner.context, fd as c_long, &mut handle) - }); - unsafe { Ok(DeviceHandle::new(self.inner.clone(), handle)) } - } - - /// Returns a list of USB devices currently attached to the system. - pub fn get_device_iter(&self) -> Result<DeviceIter> { - let mut list: *mut *mut bindings::libusb_device = std::ptr::null_mut(); - // Safe because 'inner.context' points to a valid context and '&mut list' points to a valid - // memory. - try_libusb!(unsafe { bindings::libusb_get_device_list(self.inner.context, &mut list) }); - - Ok(DeviceIter { - context: self.inner.clone(), - list, - index: 0, - }) - } - - /// Check at runtime if the loaded library has a given capability. - pub fn has_capability(&self, cap: u32) -> bool { - // Safe because libusb_init is called before this call happens. - unsafe { bindings::libusb_has_capability(cap) != 0 } - } - - /// Return an iter of poll fds. Those fds that should be polled to handle libusb events. - pub fn get_pollfd_iter(&self) -> PollFdIter { - // Safe because 'inner.context' is inited. - let list: *mut *const bindings::libusb_pollfd = - unsafe { bindings::libusb_get_pollfds(self.inner.context) }; - PollFdIter { list, index: 0 } - } - - /// Handle libusb events in a non block way. - pub fn handle_events_nonblock(&self) { - static mut zero_time: bindings::timeval = bindings::timeval { - tv_sec: 0, - tv_usec: 0, - }; - // Safe because 'inner.context' points to valid context. - unsafe { - bindings::libusb_handle_events_timeout_completed( - self.inner.context, - &mut zero_time as *mut bindings::timeval, - std::ptr::null_mut(), - ); - } - } - - /// Set a handler that could handle pollfd change events. - pub fn set_pollfd_notifiers(&self, handler: Box<dyn LibUsbPollfdChangeHandler>) { - // LibUsbContext is alive when any libusb related function is called. It owns the handler, - // thus the handler memory is always valid when callback is invoked. - let holder = Box::new(PollfdChangeHandlerHolder { handler }); - let raw_holder = Box::into_raw(holder); - unsafe { - bindings::libusb_set_pollfd_notifiers( - self.inner.context, - Some(pollfd_added_cb), - Some(pollfd_removed_cb), - raw_holder as *mut c_void, - ); - } - // Safe because raw_holder is from Boxed pointer. - let holder = unsafe { Box::from_raw(raw_holder) }; - *self.inner.pollfd_change_handler.lock() = Some(holder); - } - - /// Remove the previous registered notifiers. - pub fn remove_pollfd_notifiers(&self) { - self.inner.remove_pollfd_notifiers(); - } - - /// Set a callback that could handle hotplug events. Currently, this function listen to hotplug - /// event of all devices. - pub fn set_hotplug_cb<H: UsbHotplugHandler + Sized>(&self, handler: H) -> Result<()> { - let event = bindings::LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED - | bindings::LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT; - let holder = UsbHotplugHandlerHolder::new(self.inner.clone(), handler); - let raw_holder = Box::into_raw(holder); - // Safe becuase hotpulg cb is a vaild c function and raw_holder points to memory for that - // function argument. - try_libusb!(unsafe { - bindings::libusb_hotplug_register_callback( - self.inner.context, - event, - bindings::LIBUSB_HOTPLUG_NO_FLAGS, - bindings::LIBUSB_HOTPLUG_MATCH_ANY, - bindings::LIBUSB_HOTPLUG_MATCH_ANY, - bindings::LIBUSB_HOTPLUG_MATCH_ANY, - Some(hotplug_cb), - raw_holder as *mut c_void, - std::ptr::null_mut(), - ) - }); - Ok(()) - } -} - -/// Iterator for device list. -pub struct DeviceIter { - context: Arc<LibUsbContextInner>, - list: *mut *mut bindings::libusb_device, - index: isize, -} - -impl Drop for DeviceIter { - fn drop(&mut self) { - // Safe because 'self.list' is inited by a valid pointer from libusb_get_device_list. - unsafe { - bindings::libusb_free_device_list(self.list, 1); - } - } -} - -impl Iterator for DeviceIter { - type Item = LibUsbDevice; - - fn next(&mut self) -> Option<LibUsbDevice> { - // Safe becuase 'self.list' is valid, the list is null terminated. - unsafe { - let current_ptr = self.list.offset(self.index); - if (*current_ptr).is_null() { - return None; - } - self.index += 1; - Some(LibUsbDevice::new(self.context.clone(), *current_ptr)) - } - } -} - -/// Iterator for pollfds. -pub struct PollFdIter { - list: *mut *const bindings::libusb_pollfd, - index: isize, -} - -impl Drop for PollFdIter { - fn drop(&mut self) { - // Safe because 'self.list' points to valid memory of pollfd list. - unsafe { - bindings::libusb_free_pollfds(self.list); - } - } -} - -impl Iterator for PollFdIter { - type Item = bindings::libusb_pollfd; - - fn next(&mut self) -> Option<bindings::libusb_pollfd> { - // Safe because 'self.index' never grow out of the null pointer index. - unsafe { - let current_ptr = self.list.offset(self.index); - if (*current_ptr).is_null() { - return None; - } - - self.index += 1; - // Safe because '*current_ptr' is not null. - Some(**current_ptr) - } - } -} - -/// Trait for handler that handles Pollfd Change events. -pub trait LibUsbPollfdChangeHandler: Send + Sync + 'static { - fn add_poll_fd(&self, fd: RawFd, events: c_short); - fn remove_poll_fd(&self, fd: RawFd); -} - -// This struct owns LibUsbPollfdChangeHandler. We need it because it's not possible to cast void -// pointer to trait pointer. -struct PollfdChangeHandlerHolder { - handler: Box<dyn LibUsbPollfdChangeHandler>, -} - -// This function is safe when user_data points to valid PollfdChangeHandlerHolder. -unsafe extern "C" fn pollfd_added_cb(fd: RawFd, events: c_short, user_data: *mut c_void) { - // Safe because user_data was casted from holder. - let keeper = &*(user_data as *mut PollfdChangeHandlerHolder); - keeper.handler.add_poll_fd(fd, events); -} - -// This function is safe when user_data points to valid PollfdChangeHandlerHolder. -unsafe extern "C" fn pollfd_removed_cb(fd: RawFd, user_data: *mut c_void) { - // Safe because user_data was casted from holder. - let keeper = &*(user_data as *mut PollfdChangeHandlerHolder); - keeper.handler.remove_poll_fd(fd); -} diff --git a/usb_util/src/libusb_device.rs b/usb_util/src/libusb_device.rs deleted file mode 100644 index ad87b46..0000000 --- a/usb_util/src/libusb_device.rs +++ /dev/null @@ -1,108 +0,0 @@ -// Copyright 2018 The Chromium OS Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -use std; -use std::sync::Arc; - -use crate::bindings; -use crate::config_descriptor::ConfigDescriptor; -use crate::device_handle::DeviceHandle; -use crate::error::{Error, Result}; -use crate::libusb_context::LibUsbContextInner; -use crate::types::Speed; - -pub type DeviceDescriptor = bindings::libusb_device_descriptor; - -/// LibUsbDevice wraps libusb_device. -pub struct LibUsbDevice { - _context: Arc<LibUsbContextInner>, - device: *mut bindings::libusb_device, -} - -unsafe impl Send for LibUsbDevice {} - -impl Drop for LibUsbDevice { - fn drop(&mut self) { - // Safe because 'self.device' is a valid pointer and libusb_ref_device is invoked when - // 'self' is built. - unsafe { - bindings::libusb_unref_device(self.device); - } - } -} - -impl LibUsbDevice { - /// Create a new LibUsbDevice. 'device' should be a valid pointer to libusb_device. - pub unsafe fn new( - ctx: Arc<LibUsbContextInner>, - device: *mut bindings::libusb_device, - ) -> LibUsbDevice { - bindings::libusb_ref_device(device); - LibUsbDevice { - _context: ctx, - device, - } - } - - /// Get device descriptor of this device. - pub fn get_device_descriptor(&self) -> Result<DeviceDescriptor> { - // Safe because memory is initialized later. - let mut descriptor: bindings::libusb_device_descriptor = Default::default(); - // Safe because 'self.device' is valid and '&mut descriptor' is valid. - try_libusb!(unsafe { - bindings::libusb_get_device_descriptor(self.device, &mut descriptor) - }); - Ok(descriptor) - } - - /// Get config descriptor at index of idx. - pub fn get_config_descriptor(&self, idx: u8) -> Result<ConfigDescriptor> { - let mut descriptor: *mut bindings::libusb_config_descriptor = std::ptr::null_mut(); - // Safe because 'self.device' is valid and '&mut descriptor' is valid. - try_libusb!(unsafe { - bindings::libusb_get_config_descriptor(self.device, idx, &mut descriptor) - }); - // Safe because descriptor is inited with valid pointer. - Ok(unsafe { ConfigDescriptor::new(descriptor) }) - } - - /// Get active config descriptor of this device. - pub fn get_active_config_descriptor(&self) -> Result<ConfigDescriptor> { - let mut descriptor: *mut bindings::libusb_config_descriptor = std::ptr::null_mut(); - // Safe because 'self.device' is valid and '&mut descriptor' is valid. - try_libusb!(unsafe { - bindings::libusb_get_active_config_descriptor(self.device, &mut descriptor) - }); - // Safe becuase descriptor points to valid memory. - Ok(unsafe { ConfigDescriptor::new(descriptor) }) - } - - /// Get bus number of this device. - pub fn get_bus_number(&self) -> u8 { - // Safe because 'self.device' is valid. - unsafe { bindings::libusb_get_bus_number(self.device) } - } - - /// Get address of this device. - pub fn get_address(&self) -> u8 { - // Safe because 'self.device' is valid. - unsafe { bindings::libusb_get_device_address(self.device) } - } - - /// Get speed of this device. - pub fn get_speed(&self) -> Speed { - // Safe because 'self.device' is valid. - let speed = unsafe { bindings::libusb_get_device_speed(self.device) }; - Speed::from(speed as u32) - } - - /// Get device handle of this device. - pub fn open(&self) -> Result<DeviceHandle> { - let mut handle: *mut bindings::libusb_device_handle = std::ptr::null_mut(); - // Safe because 'self.device' is constructed from libusb device list and handle is on stack. - try_libusb!(unsafe { bindings::libusb_open(self.device, &mut handle) }); - // Safe because handle points to valid memory. - Ok(unsafe { DeviceHandle::new(self._context.clone(), handle) }) - } -} diff --git a/usb_util/src/types.rs b/usb_util/src/types.rs index f40dd6c..d669dcd 100644 --- a/usb_util/src/types.rs +++ b/usb_util/src/types.rs @@ -7,35 +7,159 @@ use data_model::DataInit; use std::mem::size_of; -use crate::bindings; - -/// Speed of usb device. See usb spec for more details. -#[derive(Debug)] -pub enum Speed { - /// The OS doesn't report or know the device speed. - Unknown, - /// The device is operating at low speed (1.5MBit/s). - Low, - /// The device is operating at full speed (12MBit/s). - Full, - /// The device is operating at high speed (480MBit/s). - High, - /// The device is operating at super speed (5000MBit/s). - Super, -} - -impl From<bindings::libusb_speed> for Speed { - fn from(speed: bindings::libusb_speed) -> Speed { - match speed { - bindings::LIBUSB_SPEED_LOW => Speed::Low, - bindings::LIBUSB_SPEED_FULL => Speed::Full, - bindings::LIBUSB_SPEED_HIGH => Speed::High, - bindings::LIBUSB_SPEED_SUPER => Speed::Super, - _ => Speed::Unknown, - } +/// Standard USB descriptor types. +pub enum DescriptorType { + Device = 0x01, + Configuration = 0x02, + Interface = 0x04, + Endpoint = 0x05, +} + +/// Trait describing USB descriptors. +pub trait Descriptor { + /// Get the expected bDescriptorType value for this type of descriptor. + fn descriptor_type() -> DescriptorType; +} + +/// Standard USB descriptor header common to all descriptor types. +#[allow(non_snake_case)] +#[derive(Copy, Clone, Debug, Default)] +#[repr(C, packed)] +pub struct DescriptorHeader { + pub bLength: u8, + pub bDescriptorType: u8, +} + +// Safe because it only has data and has no implicit padding. +unsafe impl DataInit for DescriptorHeader {} + +fn _assert_descriptor_header() { + const_assert!(size_of::<DescriptorHeader>() == 2); +} + +/// Standard USB device descriptor as defined in USB 2.0 chapter 9, +/// not including the standard header. +#[allow(non_snake_case)] +#[derive(Copy, Clone, Debug, Default)] +#[repr(C, packed)] +pub struct DeviceDescriptor { + pub bcdUSB: u16, + pub bDeviceClass: u8, + pub bDeviceSubClass: u8, + pub bDeviceProtocol: u8, + pub bMaxPacketSize0: u8, + pub idVendor: u16, + pub idProduct: u16, + pub bcdDevice: u16, + pub iManufacturer: u8, + pub iProduct: u8, + pub iSerialNumber: u8, + pub bNumConfigurations: u8, +} + +impl Descriptor for DeviceDescriptor { + fn descriptor_type() -> DescriptorType { + DescriptorType::Device + } +} + +// Safe because it only has data and has no implicit padding. +unsafe impl DataInit for DeviceDescriptor {} + +fn _assert_device_descriptor() { + const_assert!(size_of::<DeviceDescriptor>() == 18 - 2); +} + +/// Standard USB configuration descriptor as defined in USB 2.0 chapter 9, +/// not including the standard header. +#[allow(non_snake_case)] +#[derive(Copy, Clone, Debug, Default)] +#[repr(C, packed)] +pub struct ConfigDescriptor { + pub wTotalLength: u16, + pub bNumInterfaces: u8, + pub bConfigurationValue: u8, + pub iConfiguration: u8, + pub bmAttributes: u8, + pub bMaxPower: u8, +} + +impl Descriptor for ConfigDescriptor { + fn descriptor_type() -> DescriptorType { + DescriptorType::Configuration + } +} + +// Safe because it only has data and has no implicit padding. +unsafe impl DataInit for ConfigDescriptor {} + +fn _assert_config_descriptor() { + const_assert!(size_of::<ConfigDescriptor>() == 9 - 2); +} + +impl ConfigDescriptor { + pub fn num_interfaces(&self) -> u8 { + self.bNumInterfaces + } +} + +/// Standard USB interface descriptor as defined in USB 2.0 chapter 9, +/// not including the standard header. +#[allow(non_snake_case)] +#[derive(Copy, Clone, Debug, Default)] +#[repr(C, packed)] +pub struct InterfaceDescriptor { + pub bInterfaceNumber: u8, + pub bAlternateSetting: u8, + pub bNumEndpoints: u8, + pub bInterfaceClass: u8, + pub bInterfaceSubClass: u8, + pub bInterfaceProtocol: u8, + pub iInterface: u8, +} + +impl Descriptor for InterfaceDescriptor { + fn descriptor_type() -> DescriptorType { + DescriptorType::Interface + } +} + +// Safe because it only has data and has no implicit padding. +unsafe impl DataInit for InterfaceDescriptor {} + +fn _assert_interface_descriptor() { + const_assert!(size_of::<InterfaceDescriptor>() == 9 - 2); +} + +/// Standard USB endpoint descriptor as defined in USB 2.0 chapter 9, +/// not including the standard header. +#[allow(non_snake_case)] +#[derive(Copy, Clone, Debug, Default)] +#[repr(C, packed)] +pub struct EndpointDescriptor { + pub bEndpointAddress: u8, + pub bmAttributes: u8, + pub wMaxPacketSize: u16, + pub bInterval: u8, +} + +impl Descriptor for EndpointDescriptor { + fn descriptor_type() -> DescriptorType { + DescriptorType::Endpoint } } +// Safe because it only has data and has no implicit padding. +unsafe impl DataInit for EndpointDescriptor {} + +fn _assert_endpoint_descriptor() { + const_assert!(size_of::<EndpointDescriptor>() == 7 - 2); +} + +const ENDPOINT_DESCRIPTOR_DIRECTION_MASK: u8 = 1 << 7; +const ENDPOINT_DESCRIPTOR_NUMBER_MASK: u8 = 0xf; +const ENDPOINT_DESCRIPTOR_ATTRIBUTES_TYPE_MASK: u8 = 0x3; + /// Endpoint types. #[derive(PartialEq)] pub enum EndpointType { @@ -54,6 +178,35 @@ pub enum EndpointDirection { /// Endpoint direction offset. pub const ENDPOINT_DIRECTION_OFFSET: u8 = 7; +impl EndpointDescriptor { + // Get direction of this endpoint. + pub fn get_direction(&self) -> EndpointDirection { + let direction = self.bEndpointAddress & ENDPOINT_DESCRIPTOR_DIRECTION_MASK; + if direction != 0 { + EndpointDirection::DeviceToHost + } else { + EndpointDirection::HostToDevice + } + } + + // Get endpoint number. + pub fn get_endpoint_number(&self) -> u8 { + self.bEndpointAddress & ENDPOINT_DESCRIPTOR_NUMBER_MASK + } + + // Get endpoint type. + pub fn get_endpoint_type(&self) -> Option<EndpointType> { + let ep_type = self.bmAttributes & ENDPOINT_DESCRIPTOR_ATTRIBUTES_TYPE_MASK; + match ep_type { + 0 => Some(EndpointType::Control), + 1 => Some(EndpointType::Isochronous), + 2 => Some(EndpointType::Bulk), + 3 => Some(EndpointType::Interrupt), + _ => None, + } + } +} + /// Offset of data phase transfer direction. pub const DATA_PHASE_DIRECTION_OFFSET: u8 = 7; /// Bit mask of data phase transfer direction. @@ -118,7 +271,7 @@ pub struct UsbRequestSetup { pub length: u16, // wLength } -fn _assert() { +fn _assert_usb_request_setup() { const_assert!(size_of::<UsbRequestSetup>() == 8); } @@ -194,3 +347,55 @@ impl UsbRequestSetup { } } } + +/// Construct a bmRequestType value for a control request. +pub fn control_request_type( + type_: ControlRequestType, + dir: ControlRequestDataPhaseTransferDirection, + recipient: ControlRequestRecipient, +) -> u8 { + ((type_ as u8) << CONTROL_REQUEST_TYPE_OFFSET) + | ((dir as u8) << DATA_PHASE_DIRECTION_OFFSET) + | (recipient as u8) +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn control_request_types() { + assert_eq!( + control_request_type( + ControlRequestType::Standard, + ControlRequestDataPhaseTransferDirection::HostToDevice, + ControlRequestRecipient::Device + ), + 0b0_00_00000 + ); + assert_eq!( + control_request_type( + ControlRequestType::Standard, + ControlRequestDataPhaseTransferDirection::DeviceToHost, + ControlRequestRecipient::Device + ), + 0b1_00_00000 + ); + assert_eq!( + control_request_type( + ControlRequestType::Standard, + ControlRequestDataPhaseTransferDirection::HostToDevice, + ControlRequestRecipient::Interface + ), + 0b0_00_00001 + ); + assert_eq!( + control_request_type( + ControlRequestType::Class, + ControlRequestDataPhaseTransferDirection::HostToDevice, + ControlRequestRecipient::Device + ), + 0b0_01_00000 + ); + } +} diff --git a/usb_util/src/usb_transfer.rs b/usb_util/src/usb_transfer.rs deleted file mode 100644 index e3ca623..0000000 --- a/usb_util/src/usb_transfer.rs +++ /dev/null @@ -1,382 +0,0 @@ -// Copyright 2018 The Chromium OS Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -use std::mem::size_of; -use std::os::raw::c_void; -use std::sync::{Arc, Weak}; - -use crate::bindings::{ - libusb_alloc_transfer, libusb_cancel_transfer, libusb_device_handle, libusb_free_transfer, - libusb_submit_transfer, libusb_transfer, libusb_transfer_status, LIBUSB_TRANSFER_CANCELLED, - LIBUSB_TRANSFER_COMPLETED, LIBUSB_TRANSFER_ERROR, LIBUSB_TRANSFER_NO_DEVICE, - LIBUSB_TRANSFER_OVERFLOW, LIBUSB_TRANSFER_STALL, LIBUSB_TRANSFER_TIMED_OUT, - LIBUSB_TRANSFER_TYPE_BULK, LIBUSB_TRANSFER_TYPE_CONTROL, LIBUSB_TRANSFER_TYPE_INTERRUPT, -}; -use crate::error::{Error, Result}; -use crate::types::UsbRequestSetup; - -/// Status of transfer. -#[derive(PartialEq)] -pub enum TransferStatus { - Completed, - Error, - TimedOut, - Cancelled, - Stall, - NoDevice, - Overflow, -} - -impl From<libusb_transfer_status> for TransferStatus { - fn from(s: libusb_transfer_status) -> Self { - match s { - LIBUSB_TRANSFER_COMPLETED => TransferStatus::Completed, - LIBUSB_TRANSFER_ERROR => TransferStatus::Error, - LIBUSB_TRANSFER_TIMED_OUT => TransferStatus::TimedOut, - LIBUSB_TRANSFER_CANCELLED => TransferStatus::Cancelled, - LIBUSB_TRANSFER_STALL => TransferStatus::Stall, - LIBUSB_TRANSFER_NO_DEVICE => TransferStatus::NoDevice, - LIBUSB_TRANSFER_OVERFLOW => TransferStatus::Overflow, - _ => TransferStatus::Error, - } - } -} - -/// Trait for usb transfer buffer. -pub trait UsbTransferBuffer: Send { - fn as_ptr(&mut self) -> *mut u8; - fn len(&self) -> i32; -} - -/// Default buffer size for control data transfer. -const CONTROL_DATA_BUFFER_SIZE: usize = 1024; - -/// Buffer type for control transfer. The first 8-bytes is a UsbRequestSetup struct. -#[repr(C, packed)] -pub struct ControlTransferBuffer { - pub setup_buffer: UsbRequestSetup, - pub data_buffer: [u8; CONTROL_DATA_BUFFER_SIZE], -} - -impl ControlTransferBuffer { - fn new() -> ControlTransferBuffer { - ControlTransferBuffer { - setup_buffer: UsbRequestSetup { - request_type: 0, - request: 0, - value: 0, - index: 0, - length: 0, - }, - data_buffer: [0; CONTROL_DATA_BUFFER_SIZE], - } - } - - /// Set request setup for this control buffer. - pub fn set_request_setup(&mut self, request_setup: &UsbRequestSetup) { - self.setup_buffer = *request_setup; - } -} - -impl UsbTransferBuffer for ControlTransferBuffer { - fn as_ptr(&mut self) -> *mut u8 { - self as *mut ControlTransferBuffer as *mut u8 - } - - fn len(&self) -> i32 { - if self.setup_buffer.length as usize > CONTROL_DATA_BUFFER_SIZE { - panic!("Setup packet has an oversize length"); - } - self.setup_buffer.length as i32 + size_of::<UsbRequestSetup>() as i32 - } -} - -/// Buffer type for Bulk transfer. -pub struct BulkTransferBuffer { - buffer: Vec<u8>, -} - -impl BulkTransferBuffer { - fn with_size(buffer_size: usize) -> Self { - BulkTransferBuffer { - buffer: vec![0; buffer_size], - } - } - - /// Get mutable interal slice of this buffer. - pub fn as_mut_slice(&mut self) -> &mut [u8] { - &mut self.buffer - } - - /// Get interal slice of this buffer. - pub fn as_slice(&self) -> &[u8] { - &self.buffer - } -} - -impl UsbTransferBuffer for BulkTransferBuffer { - fn as_ptr(&mut self) -> *mut u8 { - if self.buffer.len() == 0 { - // Vec::as_mut_ptr() won't give 0x0 even if len() is 0. - std::ptr::null_mut() - } else { - self.buffer.as_mut_ptr() - } - } - - fn len(&self) -> i32 { - self.buffer.len() as i32 - } -} - -type UsbTransferCompletionCallback<T> = dyn Fn(UsbTransfer<T>) + Send + 'static; - -// This wraps libusb_transfer pointer. -struct LibUsbTransfer { - ptr: *mut libusb_transfer, -} - -impl Drop for LibUsbTransfer { - fn drop(&mut self) { - // Safe because 'self.ptr' is allocated by libusb_alloc_transfer. - unsafe { - libusb_free_transfer(self.ptr); - } - } -} - -// It is safe to invoke libusb functions from multiple threads. -// We cannot modify libusb_transfer safely from multiple threads. All the modifications happens -// in construct (UsbTransfer::new) or consume (UsbTransfer::into_raw), we can consider this thread -// safe. -unsafe impl Send for LibUsbTransfer {} -unsafe impl Sync for LibUsbTransfer {} - -/// TransferCanceller can cancel the transfer. -pub struct TransferCanceller { - transfer: Weak<LibUsbTransfer>, -} - -impl TransferCanceller { - /// Return false if fail to cancel. - pub fn try_cancel(&self) -> bool { - match self.transfer.upgrade() { - Some(t) => { - // Safe because self.transfer has ownership of the raw pointer. - let r = unsafe { libusb_cancel_transfer(t.ptr) }; - if r == 0 { - true - } else { - false - } - } - None => false, - } - } -} - -struct UsbTransferInner<T: UsbTransferBuffer> { - transfer: Arc<LibUsbTransfer>, - callback: Option<Box<UsbTransferCompletionCallback<T>>>, - buffer: T, -} - -/// UsbTransfer owns a LibUsbTransfer, it's buffer and callback. -pub struct UsbTransfer<T: UsbTransferBuffer> { - inner: Box<UsbTransferInner<T>>, -} - -/// Build a control transfer. -pub fn control_transfer(timeout: u32) -> UsbTransfer<ControlTransferBuffer> { - UsbTransfer::<ControlTransferBuffer>::new( - 0, - LIBUSB_TRANSFER_TYPE_CONTROL as u8, - timeout, - ControlTransferBuffer::new(), - ) -} - -/// Build a data transfer. -pub fn bulk_transfer(endpoint: u8, timeout: u32, size: usize) -> UsbTransfer<BulkTransferBuffer> { - UsbTransfer::<BulkTransferBuffer>::new( - endpoint, - LIBUSB_TRANSFER_TYPE_BULK as u8, - timeout, - BulkTransferBuffer::with_size(size), - ) -} - -/// Build a data transfer. -pub fn interrupt_transfer( - endpoint: u8, - timeout: u32, - size: usize, -) -> UsbTransfer<BulkTransferBuffer> { - UsbTransfer::<BulkTransferBuffer>::new( - endpoint, - LIBUSB_TRANSFER_TYPE_INTERRUPT as u8, - timeout, - BulkTransferBuffer::with_size(size), - ) -} - -impl<T: UsbTransferBuffer> UsbTransfer<T> { - fn new(endpoint: u8, type_: u8, timeout: u32, buffer: T) -> Self { - // Safe because alloc is safe. - let transfer: *mut libusb_transfer = unsafe { libusb_alloc_transfer(0) }; - // Just panic on OOM. - assert!(!transfer.is_null()); - let inner = Box::new(UsbTransferInner { - transfer: Arc::new(LibUsbTransfer { ptr: transfer }), - callback: None, - buffer, - }); - // Safe because we inited transfer. - let raw_transfer: &mut libusb_transfer = unsafe { &mut *(inner.transfer.ptr) }; - raw_transfer.endpoint = endpoint; - raw_transfer.type_ = type_; - raw_transfer.timeout = timeout; - raw_transfer.callback = Some(UsbTransfer::<T>::on_transfer_completed); - UsbTransfer { inner } - } - - /// Set callback function for transfer completion. - pub fn set_callback<C: 'static + Fn(UsbTransfer<T>) + Send>(&mut self, cb: C) { - self.inner.callback = Some(Box::new(cb)); - } - - /// Get a reference to the buffer. - pub fn buffer(&self) -> &T { - &self.inner.buffer - } - - /// Get a mutable reference to the buffer. - pub fn buffer_mut(&mut self) -> &mut T { - &mut self.inner.buffer - } - - /// Get actual length of data that was transferred. - pub fn actual_length(&self) -> i32 { - let transfer = self.inner.transfer.ptr; - // Safe because inner.ptr is always allocated by libusb_alloc_transfer. - unsafe { (*transfer).actual_length } - } - - /// Get the transfer status of this transfer. - pub fn status(&self) -> TransferStatus { - let transfer = self.inner.transfer.ptr; - // Safe because inner.ptr is always allocated by libusb_alloc_transfer. - unsafe { TransferStatus::from((*transfer).status) } - } - - /// Submit this transfer to device handle. 'self' is consumed. On success, the memory will be - /// 'leaked' (and stored in user_data) and sent to libusb, when the async operation is done, - /// on_transfer_completed will recreate 'self' and deliver it to callback/free 'self'. On - /// faliure, 'self' is returned with an error. - /// - /// # Safety - /// - /// Assumes libusb_device_handle is an handled opened by libusb, self.inner.transfer.ptr is - /// initialized with correct buffer and length. - pub unsafe fn submit(self, handle: *mut libusb_device_handle) -> Result<TransferCanceller> { - let weak_transfer = Arc::downgrade(&self.inner.transfer); - let transfer = self.into_raw(); - (*transfer).dev_handle = handle; - match Error::from(libusb_submit_transfer(transfer)) { - Error::Success(_e) => Ok(TransferCanceller { - transfer: weak_transfer, - }), - err => { - UsbTransfer::<T>::from_raw(transfer); - Err(err) - } - } - } - - /// Invoke callback when transfer is completed. - /// - /// # Safety - /// - /// Assumes libusb_tranfser is finished. This function is called by libusb, don't call it - /// manually. - unsafe extern "C" fn on_transfer_completed(transfer: *mut libusb_transfer) { - let mut transfer = UsbTransfer::<T>::from_raw(transfer); - // Callback is reset to None. - if let Some(cb) = transfer.inner.callback.take() { - cb(transfer); - } - } - - fn into_raw(mut self) -> *mut libusb_transfer { - let transfer: *mut libusb_transfer = self.inner.transfer.ptr; - // Safe because transfer is allocated by libusb_alloc_transfer. - unsafe { - (*transfer).buffer = self.buffer_mut().as_ptr(); - (*transfer).length = self.buffer_mut().len(); - (*transfer).user_data = Box::into_raw(self.inner) as *mut c_void; - } - transfer - } - - unsafe fn from_raw(transfer: *mut libusb_transfer) -> Self { - UsbTransfer { - inner: Box::<UsbTransferInner<T>>::from_raw( - (*transfer).user_data as *mut UsbTransferInner<T>, - ), - } - } -} - -#[cfg(test)] -mod tests { - use super::*; - use std::sync::Mutex; - - pub fn fake_submit_transfer<T: UsbTransferBuffer>(transfer: UsbTransfer<T>) { - let transfer = transfer.into_raw(); - unsafe { - match (*transfer).callback { - Some(cb) => cb(transfer), - // Although no callback is invoked, we still need on_transfer_completed to - // free memory. - None => panic!("Memory leak!"), - }; - } - } - - #[test] - fn check_control_buffer_size() { - assert_eq!( - size_of::<ControlTransferBuffer>(), - size_of::<UsbRequestSetup>() + CONTROL_DATA_BUFFER_SIZE - ); - } - - #[test] - fn submit_transfer_no_callback_test() { - let t = control_transfer(0); - fake_submit_transfer(t); - let t = bulk_transfer(0, 0, 1); - fake_submit_transfer(t); - } - - struct FakeTransferController { - data: Mutex<u8>, - } - - #[test] - fn submit_transfer_with_callback() { - let c = Arc::new(FakeTransferController { - data: Mutex::new(0), - }); - let c1 = Arc::downgrade(&c); - let mut t = control_transfer(0); - t.set_callback(move |_t| { - let c = c1.upgrade().unwrap(); - *c.data.lock().unwrap() = 3; - }); - fake_submit_transfer(t); - assert_eq!(*c.data.lock().unwrap(), 3); - } -} |