summary refs log tree commit diff
path: root/usb_util
diff options
context:
space:
mode:
authorDaniel Verkamp <dverkamp@chromium.org>2019-07-09 17:21:54 -0700
committerCommit Bot <commit-bot@chromium.org>2019-10-17 00:20:24 +0000
commit6494117e1766337f5d688b98bfc3df999932c3ac (patch)
tree0c8b6fd24a615ae146bb0a2d6f4d8ce332f5cc42 /usb_util
parentbed8b0017d2cb283c20dc50241adb4f5b2668489 (diff)
downloadcrosvm-6494117e1766337f5d688b98bfc3df999932c3ac.tar
crosvm-6494117e1766337f5d688b98bfc3df999932c3ac.tar.gz
crosvm-6494117e1766337f5d688b98bfc3df999932c3ac.tar.bz2
crosvm-6494117e1766337f5d688b98bfc3df999932c3ac.tar.lz
crosvm-6494117e1766337f5d688b98bfc3df999932c3ac.tar.xz
crosvm-6494117e1766337f5d688b98bfc3df999932c3ac.tar.zst
crosvm-6494117e1766337f5d688b98bfc3df999932c3ac.zip
usb: replace libusb with Rust usb_util library
Drop the dependency on libusb and reimplement the host USB backend using
usb_sys to wrap the Linux usbdevfs ioctls.

This allows sandboxing to work without any dependency on libusb patches,
and it gives us the flexibility to modify and update the USB backend
without depending on an external third-party library.

BUG=chromium:987833
TEST=`adb logcat` on nami with Nexus 5 attached
TEST=deploy app to phone with Android Studio
TEST=Run EdgeTPU USB accelerator demo (including DFU mode transition)

Cq-Depend: chromium:1773695
Change-Id: I4321c2b6142caac15f48f197795a37d59d268831
Signed-off-by: Daniel Verkamp <dverkamp@chromium.org>
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/crosvm/+/1783601
Reviewed-by: Zach Reizner <zachr@chromium.org>
Tested-by: kokoro <noreply+kokoro@google.com>
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);
-    }
-}