last attempt at getting reading stuff to work nicely (doesn't work)
diff --git a/aos/common/sensors/sensor_receiver-tmpl.h b/aos/common/sensors/sensor_receiver-tmpl.h
index e3840c4..2220496 100644
--- a/aos/common/sensors/sensor_receiver-tmpl.h
+++ b/aos/common/sensors/sensor_receiver-tmpl.h
@@ -6,7 +6,7 @@
 
 template<class Values>
 const time::Time SensorReceiver<Values>::kJitterDelay =
-    time::Time::InSeconds(0.00225);
+    time::Time::InSeconds(0.003);
 // Not a multiple of kSensorSendFrequency to unwedge ourself if we hit some bug
 // where it needs to get off of that frequency to work.
 template<class Values>
diff --git a/aos/common/sensors/sensor_receiver.h b/aos/common/sensors/sensor_receiver.h
index 9cd24e1..335ff08 100644
--- a/aos/common/sensors/sensor_receiver.h
+++ b/aos/common/sensors/sensor_receiver.h
@@ -40,10 +40,10 @@
   // How many cycles not to send data out to make sure that we're in phase
   // (during this time, the code verifies that <= 1 cycle is not within 1
   // cycle's time of kJitterDelay).
-  static const int kTestCycles = 10;
+  static const int kTestCycles = 8;
   // How many cycles that we need (consecutively) of another packet being closer
   // to the right time than the ones we're reading before we switch.
-  static const int kBadCyclesToSwitch = 15;
+  static const int kBadCyclesToSwitch = 8;
   // If we don't get a good packet in this long, then we Synchronize() again.
   static const time::Time kGiveupTime;
 
diff --git a/frc971/input/gyro_sensor_receiver.cc b/frc971/input/gyro_sensor_receiver.cc
index aedc9a3..55fa085 100644
--- a/frc971/input/gyro_sensor_receiver.cc
+++ b/frc971/input/gyro_sensor_receiver.cc
@@ -203,6 +203,7 @@
     // Loop and then return once we get a good one.
     while (true) {
       int read_bytes;
+      ::aos::time::SleepFor(::aos::time::Time::InSeconds(0.0005));
       int r = dev_handle_->interrupt_transfer(
           kEndpoint, data_, sizeof(data_), &read_bytes, kReadTimeout);
 
diff --git a/gyro_board/src/libusb-driver/libusb_wrap.cc b/gyro_board/src/libusb-driver/libusb_wrap.cc
index 13a5e31..a297a9b 100644
--- a/gyro_board/src/libusb-driver/libusb_wrap.cc
+++ b/gyro_board/src/libusb-driver/libusb_wrap.cc
@@ -77,6 +77,13 @@
   libusb_exit(ctx_);
 }
 
+void LibUSB::HandleEvents() {
+  int ret = libusb_handle_events(ctx_);
+  if (ret != 0) {
+    LOG(FATAL, "libusb_handle_events(%p) returned %d\n", ctx_, ret);
+  }
+}
+
 LibUSBDeviceHandle::LibUSBDeviceHandle(
     libusb_device_handle *dev_handle) : dev_handle_(dev_handle) { }
 
@@ -103,3 +110,57 @@
   return libusb_bulk_transfer(dev_handle_, endpoint, data, length,
                               transferred, timeout);
 }
+
+namespace libusb {
+
+Transfer::Transfer(size_t data_length,
+                   void (*callback)(Transfer *, void *),
+                   void *user_data)
+    : transfer_(libusb_alloc_transfer(0)),
+      data_(new uint8_t[data_length]),
+      data_length_(data_length),
+      callback_(callback),
+      user_data_(user_data) {
+}
+Transfer::~Transfer() {
+  libusb_free_transfer(transfer_);
+  delete data_;
+}
+
+void Transfer::FillInterrupt(LibUSBDeviceHandle *device,
+                             unsigned char endpoint,
+                             unsigned int timeout) {
+  libusb_fill_interrupt_transfer(transfer_,
+                                 device->dev_handle_,
+                                 endpoint,
+                                 data_,
+                                 data_length_,
+                                 StaticTransferCallback,
+                                 this,
+                                 timeout);
+}
+
+void Transfer::Submit() {
+  int ret = libusb_submit_transfer(transfer_);
+  if (ret != 0) {
+    if (ret == LIBUSB_ERROR_BUSY) {
+      LOG(FATAL, "transfer %p already submitted\n", this);
+    }
+    LOG(FATAL, "libusb error %d submitting transfer %p\n",
+        ret, this);
+  }
+}
+
+void Transfer::Cancel() {
+  int ret = libusb_cancel_transfer(transfer_);
+  if (ret != 0) {
+    LOG(FATAL, "libusb error %d cancelling transfer %p\n",
+        ret, this);
+  }
+}
+
+void Transfer::TransferCallback() {
+  callback_(this, user_data_);
+}
+
+}  // namespace libusb
diff --git a/gyro_board/src/libusb-driver/libusb_wrap.h b/gyro_board/src/libusb-driver/libusb_wrap.h
index 074408d..9713534 100644
--- a/gyro_board/src/libusb-driver/libusb_wrap.h
+++ b/gyro_board/src/libusb-driver/libusb_wrap.h
@@ -3,18 +3,28 @@
 
 #include <libusb-1.0/libusb.h>
 
+#include "aos/common/macros.h"
+
 class LibUSBDeviceHandle;
+namespace libusb {
+class Transfer;
+}
 
 class LibUSB {
  public:
   explicit LibUSB();
-  virtual ~LibUSB();
+  ~LibUSB();
+
   // Return a device handle or NULL with the correct VID and PID.
   LibUSBDeviceHandle *FindDeviceWithVIDPID(
       int vid, int pid);
 
+  void HandleEvents();
+
  private:
   libusb_context *ctx_;
+
+  DISALLOW_COPY_AND_ASSIGN(LibUSB);
 };
 
 class LibUSBDeviceHandle {
@@ -30,9 +40,57 @@
 
  private:
   friend class LibUSB; // For constructor
+  friend class libusb::Transfer;  // for access to dev_handle_
   // Takes ownership of the device handle and frees it when destructed.
   explicit LibUSBDeviceHandle(libusb_device_handle *dev_handle);
- libusb_device_handle *dev_handle_;
+  libusb_device_handle *dev_handle_;
+
+ DISALLOW_COPY_AND_ASSIGN(LibUSBDeviceHandle);
 };
 
+// TODO(brians): move everything in here
+namespace libusb {
+
+// Wraps a libusb_transfer*.
+// Represents an asynchronous transfer.
+// Only designed to support interrupt and bulk transfers because they are very
+// similar and simple.
+class Transfer {
+ public:
+  Transfer(size_t data_length,
+           void (*callback)(Transfer *, void *),
+           void *user_data);
+  ~Transfer();
+
+  void FillInterrupt(LibUSBDeviceHandle *device,
+                     unsigned char endpoint,
+                     unsigned int timeout);
+
+  void Submit();
+  void Cancel();
+
+  libusb_transfer_status status() { return transfer_->status; }
+  int read_bytes() { return transfer_->actual_length; }
+
+  const uint8_t *data() { return data_; }
+
+ private:
+  static void StaticTransferCallback(libusb_transfer *self) {
+    static_cast<Transfer *>(self->user_data)->TransferCallback();
+  }
+  void TransferCallback();
+
+  libusb_transfer *const transfer_;
+
+  uint8_t *const data_;
+  size_t data_length_;
+
+  void (*const callback_)(Transfer *, void *);
+  void *const user_data_;
+
+  DISALLOW_COPY_AND_ASSIGN(Transfer);
+};
+
+}  // namespace libusb
+
 #endif  // LIBUSB_H_