added (untested) isochronous support to glibusb
diff --git a/aos/common/glibusb/glibusb_endpoint.cc b/aos/common/glibusb/glibusb_endpoint.cc
index ee69ec9..2346893 100644
--- a/aos/common/glibusb/glibusb_endpoint.cc
+++ b/aos/common/glibusb/glibusb_endpoint.cc
@@ -216,11 +216,11 @@
   int r;
 
   unsigned char transfer_type = LibUsbTransferType(transfer());
-  r = do_sync_bulk_transfer(libusb_context_,
-                            handle_, endpoint_address_and_direction(),
-                            static_cast<unsigned char *>(p), length,
-                            &transferred, timeout, transfer_type,
-                            quit);
+  r = do_sync_transfer(libusb_context_,
+                       handle_, endpoint_address_and_direction(),
+                       static_cast<unsigned char *>(p), length,
+                       &transferred, timeout, transfer_type,
+                       quit);
 
   switch (r) {
   case LIBUSB_SUCCESS:
@@ -236,20 +236,25 @@
   case LIBUSB_ERROR_TIMEOUT:
     LOG(DEBUG, "libusb_%s_transfer timeout\n",
         TransferTypeName(transfer()));
+    out->Resize(0);
     return kTimeout;
   case LIBUSB_ERROR_IO:
     LOG(DEBUG, "device I/O error\n");
+    out->Resize(0);
     return kFail;
   case LIBUSB_ERROR_NO_DEVICE:
     LOG(DEBUG, "device disconnected\n");
+    out->Resize(0);
     return kNoDevice;
   case LIBUSB_ERROR_OTHER:
     LOG(INFO, "libusb_%s_transfer other error\n", TransferTypeName(transfer()));
+    out->Resize(0);
     return kUnknown;
   default:
     // Most of these are more esoteric.
     LOG(INFO, "libusb_%s_transfer failed with %d: %s\n",
         TransferTypeName(transfer()), r, libusb_error_name(r));
+    out->Resize(0);
     return kFail;
   }
 }
diff --git a/aos/common/glibusb/glibusb_transfer.cc b/aos/common/glibusb/glibusb_transfer.cc
index ec4cd2c..95a6222 100644
--- a/aos/common/glibusb/glibusb_transfer.cc
+++ b/aos/common/glibusb/glibusb_transfer.cc
@@ -22,31 +22,49 @@
 namespace glibusb {
 
 namespace {
+
 // Static code from libusb1/sync.c
-void bulk_transfer_cb(struct libusb_transfer *transfer) {
+void transfer_cb(struct libusb_transfer *transfer) {
   int *completed = static_cast<int*>(transfer->user_data);
   *completed = 1;
   LOG(DEBUG, "actual_length=%d\n", transfer->actual_length);
   /* caller interprets results and frees transfer */
 }
+
+// How many isochronous packets we're going to deal with.
+// TODO(brians): Make this settable per endpoint instead of a constant.
+const int kNumIsoPackets = 1;
+
 }  // namespace
 
-int do_sync_bulk_transfer(
+int do_sync_transfer(
     struct libusb_context *context,
     struct libusb_device_handle *dev_handle,
     unsigned char endpoint, unsigned char *buffer, int length,
     int *transferred, unsigned int timeout, unsigned char type,
     Notification *quit) {
-  struct libusb_transfer *transfer = libusb_alloc_transfer(0);
+  bool isochronous = type == LIBUSB_TRANSFER_TYPE_ISOCHRONOUS;
+  struct libusb_transfer *transfer =
+      libusb_alloc_transfer(isochronous ? kNumIsoPackets : 0);
   int completed = 0;
   int r;
 
   if (!transfer)
     return LIBUSB_ERROR_NO_MEM;
 
-  libusb_fill_bulk_transfer(transfer, dev_handle, endpoint, buffer, length,
-    bulk_transfer_cb, &completed, timeout);
-  transfer->type = type;
+  switch (type) {
+    case LIBUSB_TRANSFER_TYPE_BULK:
+    case LIBUSB_TRANSFER_TYPE_INTERRUPT:
+      libusb_fill_bulk_transfer(transfer, dev_handle, endpoint, buffer, length,
+                                transfer_cb, &completed, timeout);
+    case LIBUSB_TRANSFER_TYPE_ISOCHRONOUS:
+      libusb_fill_iso_transfer(transfer, dev_handle, endpoint, buffer, length,
+                               kNumIsoPackets, transfer_cb, &completed,
+                               timeout);
+      transfer->iso_packet_desc[0].length = length;
+    default:
+      LOG(FATAL, "unhandled transfer type %hhd\n", type);
+  }
 
   r = libusb_submit_transfer(transfer);
   if (r < 0) {
@@ -82,7 +100,8 @@
     }
   }
 
-  *transferred = transfer->actual_length;
+  *transferred = isochronous ? transfer->iso_packet_desc[0].actual_length :
+      transfer->actual_length;
   switch (transfer->status) {
     case LIBUSB_TRANSFER_COMPLETED:
       r = 0;
diff --git a/aos/common/glibusb/glibusb_transfer.h b/aos/common/glibusb/glibusb_transfer.h
index 9218049..81af49e 100644
--- a/aos/common/glibusb/glibusb_transfer.h
+++ b/aos/common/glibusb/glibusb_transfer.h
@@ -1,5 +1,7 @@
 // Copyright 2012 Google Inc. All Rights Reserved.
 //
+// Modified by FRC Team 971.
+//
 // Alternative libusb call to do transfers that quits when
 // a notification is notified.
 
@@ -15,13 +17,14 @@
 
 namespace glibusb {
 
-// Bulk transfer code cribbed from libusb1/sync.c
+// Transfer code cribbed from libusb1/sync.c and modified.
+// It supports bulk, isochronous, and interrupt transfers.
 // The difference between this and the original code is that the
 // transfer now accepts a notification to poll for the quit message.
 // When it receives a quit message on the notification, it cancels the transfer.
 // The provided API's don't support better reuse of the existing code from what
-// I can tell.
-int do_sync_bulk_transfer(
+// I can tell. It has also been modified to support isochronous transfers.
+int do_sync_transfer(
     struct libusb_context *context,
     struct libusb_device_handle *dev_handle,
     unsigned char endpoint, unsigned char *buffer, int length,