summary refs log tree commit diff
path: root/usb_util
diff options
context:
space:
mode:
Diffstat (limited to 'usb_util')
-rw-r--r--usb_util/Cargo.toml12
-rw-r--r--usb_util/build.rs10
-rw-r--r--usb_util/src/bindings.rs4638
-rw-r--r--usb_util/src/config_descriptor.rs66
-rw-r--r--usb_util/src/descriptor.rs499
-rw-r--r--usb_util/src/device.rs458
-rw-r--r--usb_util/src/device_handle.rs161
-rw-r--r--usb_util/src/endpoint_descriptor.rs57
-rw-r--r--usb_util/src/error.rs103
-rw-r--r--usb_util/src/hotplug.rs77
-rw-r--r--usb_util/src/interface_descriptor.rs40
-rw-r--r--usb_util/src/lib.rs33
-rw-r--r--usb_util/src/libusb_context.rs268
-rw-r--r--usb_util/src/libusb_device.rs108
-rw-r--r--usb_util/src/types.rs259
-rw-r--r--usb_util/src/usb_transfer.rs382
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);
-    }
-}