Home | History | Annotate | Download | only in client
      1 /*
      2  * Copyright (C) 2016 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 #include "usb.h"
     18 
     19 #include "sysdeps.h"
     20 
     21 #include <stdint.h>
     22 #include <stdlib.h>
     23 
     24 #include <atomic>
     25 #include <chrono>
     26 #include <condition_variable>
     27 #include <memory>
     28 #include <mutex>
     29 #include <string>
     30 #include <thread>
     31 #include <unordered_map>
     32 
     33 #include <libusb/libusb.h>
     34 
     35 #include <android-base/file.h>
     36 #include <android-base/logging.h>
     37 #include <android-base/stringprintf.h>
     38 #include <android-base/strings.h>
     39 
     40 #include "adb.h"
     41 #include "adb_utils.h"
     42 #include "transport.h"
     43 #include "usb.h"
     44 
     45 using android::base::StringPrintf;
     46 
     47 // RAII wrappers for libusb.
     48 struct ConfigDescriptorDeleter {
     49     void operator()(libusb_config_descriptor* desc) {
     50         libusb_free_config_descriptor(desc);
     51     }
     52 };
     53 
     54 using unique_config_descriptor = std::unique_ptr<libusb_config_descriptor, ConfigDescriptorDeleter>;
     55 
     56 struct DeviceHandleDeleter {
     57     void operator()(libusb_device_handle* h) {
     58         libusb_close(h);
     59     }
     60 };
     61 
     62 using unique_device_handle = std::unique_ptr<libusb_device_handle, DeviceHandleDeleter>;
     63 
     64 struct transfer_info {
     65     transfer_info(const char* name, uint16_t zero_mask, bool is_bulk_out)
     66         : name(name),
     67           transfer(libusb_alloc_transfer(0)),
     68           is_bulk_out(is_bulk_out),
     69           zero_mask(zero_mask) {}
     70 
     71     ~transfer_info() {
     72         libusb_free_transfer(transfer);
     73     }
     74 
     75     const char* name;
     76     libusb_transfer* transfer;
     77     bool is_bulk_out;
     78     bool transfer_complete;
     79     std::condition_variable cv;
     80     std::mutex mutex;
     81     uint16_t zero_mask;
     82 
     83     void Notify() {
     84         LOG(DEBUG) << "notifying " << name << " transfer complete";
     85         transfer_complete = true;
     86         cv.notify_one();
     87     }
     88 };
     89 
     90 namespace libusb {
     91 struct usb_handle : public ::usb_handle {
     92     usb_handle(const std::string& device_address, const std::string& serial,
     93                unique_device_handle&& device_handle, uint8_t interface, uint8_t bulk_in,
     94                uint8_t bulk_out, size_t zero_mask, size_t max_packet_size)
     95         : device_address(device_address),
     96           serial(serial),
     97           closing(false),
     98           device_handle(device_handle.release()),
     99           read("read", zero_mask, false),
    100           write("write", zero_mask, true),
    101           interface(interface),
    102           bulk_in(bulk_in),
    103           bulk_out(bulk_out),
    104           max_packet_size(max_packet_size) {}
    105 
    106     ~usb_handle() {
    107         Close();
    108     }
    109 
    110     void Close() {
    111         std::unique_lock<std::mutex> lock(device_handle_mutex);
    112         // Cancelling transfers will trigger more Closes, so make sure this only happens once.
    113         if (closing) {
    114             return;
    115         }
    116         closing = true;
    117 
    118         // Make sure that no new transfers come in.
    119         libusb_device_handle* handle = device_handle;
    120         if (!handle) {
    121             return;
    122         }
    123 
    124         device_handle = nullptr;
    125 
    126         // Cancel already dispatched transfers.
    127         libusb_cancel_transfer(read.transfer);
    128         libusb_cancel_transfer(write.transfer);
    129 
    130         libusb_release_interface(handle, interface);
    131         libusb_close(handle);
    132     }
    133 
    134     std::string device_address;
    135     std::string serial;
    136 
    137     std::atomic<bool> closing;
    138     std::mutex device_handle_mutex;
    139     libusb_device_handle* device_handle;
    140 
    141     transfer_info read;
    142     transfer_info write;
    143 
    144     uint8_t interface;
    145     uint8_t bulk_in;
    146     uint8_t bulk_out;
    147 
    148     size_t max_packet_size;
    149 };
    150 
    151 static auto& usb_handles = *new std::unordered_map<std::string, std::unique_ptr<usb_handle>>();
    152 static auto& usb_handles_mutex = *new std::mutex();
    153 
    154 static libusb_hotplug_callback_handle hotplug_handle;
    155 
    156 static std::string get_device_address(libusb_device* device) {
    157     return StringPrintf("usb:%d:%d", libusb_get_bus_number(device),
    158                         libusb_get_device_address(device));
    159 }
    160 
    161 #if defined(__linux__)
    162 static std::string get_device_serial_path(libusb_device* device) {
    163     uint8_t ports[7];
    164     int port_count = libusb_get_port_numbers(device, ports, 7);
    165     if (port_count < 0) return "";
    166 
    167     std::string path =
    168         StringPrintf("/sys/bus/usb/devices/%d-%d", libusb_get_bus_number(device), ports[0]);
    169     for (int port = 1; port < port_count; ++port) {
    170         path += StringPrintf(".%d", ports[port]);
    171     }
    172     path += "/serial";
    173     return path;
    174 }
    175 
    176 static std::string get_device_dev_path(libusb_device* device) {
    177     uint8_t ports[7];
    178     int port_count = libusb_get_port_numbers(device, ports, 7);
    179     if (port_count < 0) return "";
    180     return StringPrintf("/dev/bus/usb/%03u/%03u", libusb_get_bus_number(device), ports[0]);
    181 }
    182 #endif
    183 
    184 static bool endpoint_is_output(uint8_t endpoint) {
    185     return (endpoint & LIBUSB_ENDPOINT_DIR_MASK) == LIBUSB_ENDPOINT_OUT;
    186 }
    187 
    188 static bool should_perform_zero_transfer(uint8_t endpoint, size_t write_length, uint16_t zero_mask) {
    189     return endpoint_is_output(endpoint) && write_length != 0 && zero_mask != 0 &&
    190            (write_length & zero_mask) == 0;
    191 }
    192 
    193 static void process_device(libusb_device* device) {
    194     std::string device_address = get_device_address(device);
    195     std::string device_serial;
    196 
    197     // Figure out if we want to open the device.
    198     libusb_device_descriptor device_desc;
    199     int rc = libusb_get_device_descriptor(device, &device_desc);
    200     if (rc != 0) {
    201         LOG(WARNING) << "failed to get device descriptor for device at " << device_address << ": "
    202                      << libusb_error_name(rc);
    203         return;
    204     }
    205 
    206     if (device_desc.bDeviceClass != LIBUSB_CLASS_PER_INTERFACE) {
    207         // Assume that all Android devices have the device class set to per interface.
    208         // TODO: Is this assumption valid?
    209         LOG(VERBOSE) << "skipping device with incorrect class at " << device_address;
    210         return;
    211     }
    212 
    213     libusb_config_descriptor* config_raw;
    214     rc = libusb_get_active_config_descriptor(device, &config_raw);
    215     if (rc != 0) {
    216         LOG(WARNING) << "failed to get active config descriptor for device at " << device_address
    217                      << ": " << libusb_error_name(rc);
    218         return;
    219     }
    220     const unique_config_descriptor config(config_raw);
    221 
    222     // Use size_t for interface_num so <iostream>s don't mangle it.
    223     size_t interface_num;
    224     uint16_t zero_mask = 0;
    225     uint8_t bulk_in = 0, bulk_out = 0;
    226     size_t packet_size = 0;
    227     bool found_adb = false;
    228 
    229     for (interface_num = 0; interface_num < config->bNumInterfaces; ++interface_num) {
    230         const libusb_interface& interface = config->interface[interface_num];
    231         if (interface.num_altsetting != 1) {
    232             // Assume that interfaces with alternate settings aren't adb interfaces.
    233             // TODO: Is this assumption valid?
    234             LOG(VERBOSE) << "skipping interface with incorrect num_altsetting at " << device_address
    235                          << " (interface " << interface_num << ")";
    236             continue;
    237         }
    238 
    239         const libusb_interface_descriptor& interface_desc = interface.altsetting[0];
    240         if (!is_adb_interface(interface_desc.bInterfaceClass, interface_desc.bInterfaceSubClass,
    241                               interface_desc.bInterfaceProtocol)) {
    242             LOG(VERBOSE) << "skipping non-adb interface at " << device_address << " (interface "
    243                          << interface_num << ")";
    244             continue;
    245         }
    246 
    247         LOG(VERBOSE) << "found potential adb interface at " << device_address << " (interface "
    248                      << interface_num << ")";
    249 
    250         bool found_in = false;
    251         bool found_out = false;
    252         for (size_t endpoint_num = 0; endpoint_num < interface_desc.bNumEndpoints; ++endpoint_num) {
    253             const auto& endpoint_desc = interface_desc.endpoint[endpoint_num];
    254             const uint8_t endpoint_addr = endpoint_desc.bEndpointAddress;
    255             const uint8_t endpoint_attr = endpoint_desc.bmAttributes;
    256 
    257             const uint8_t transfer_type = endpoint_attr & LIBUSB_TRANSFER_TYPE_MASK;
    258 
    259             if (transfer_type != LIBUSB_TRANSFER_TYPE_BULK) {
    260                 continue;
    261             }
    262 
    263             if (endpoint_is_output(endpoint_addr) && !found_out) {
    264                 found_out = true;
    265                 bulk_out = endpoint_addr;
    266                 zero_mask = endpoint_desc.wMaxPacketSize - 1;
    267             } else if (!endpoint_is_output(endpoint_addr) && !found_in) {
    268                 found_in = true;
    269                 bulk_in = endpoint_addr;
    270             }
    271 
    272             size_t endpoint_packet_size = endpoint_desc.wMaxPacketSize;
    273             CHECK(endpoint_packet_size != 0);
    274             if (packet_size == 0) {
    275                 packet_size = endpoint_packet_size;
    276             } else {
    277                 CHECK(packet_size == endpoint_packet_size);
    278             }
    279         }
    280 
    281         if (found_in && found_out) {
    282             found_adb = true;
    283             break;
    284         } else {
    285             LOG(VERBOSE) << "rejecting potential adb interface at " << device_address
    286                          << "(interface " << interface_num << "): missing bulk endpoints "
    287                          << "(found_in = " << found_in << ", found_out = " << found_out << ")";
    288         }
    289     }
    290 
    291     if (!found_adb) {
    292         LOG(VERBOSE) << "skipping device with no adb interfaces at " << device_address;
    293         return;
    294     }
    295 
    296     {
    297         std::unique_lock<std::mutex> lock(usb_handles_mutex);
    298         if (usb_handles.find(device_address) != usb_handles.end()) {
    299             LOG(VERBOSE) << "device at " << device_address
    300                          << " has already been registered, skipping";
    301             return;
    302         }
    303     }
    304 
    305     bool writable = true;
    306     libusb_device_handle* handle_raw = nullptr;
    307     rc = libusb_open(device, &handle_raw);
    308     unique_device_handle handle(handle_raw);
    309     if (rc == 0) {
    310         LOG(DEBUG) << "successfully opened adb device at " << device_address << ", "
    311                    << StringPrintf("bulk_in = %#x, bulk_out = %#x", bulk_in, bulk_out);
    312 
    313         device_serial.resize(255);
    314         rc = libusb_get_string_descriptor_ascii(handle_raw, device_desc.iSerialNumber,
    315                                                 reinterpret_cast<unsigned char*>(&device_serial[0]),
    316                                                 device_serial.length());
    317         if (rc == 0) {
    318             LOG(WARNING) << "received empty serial from device at " << device_address;
    319             return;
    320         } else if (rc < 0) {
    321             LOG(WARNING) << "failed to get serial from device at " << device_address
    322                          << libusb_error_name(rc);
    323             return;
    324         }
    325         device_serial.resize(rc);
    326 
    327         // WARNING: this isn't released via RAII.
    328         rc = libusb_claim_interface(handle.get(), interface_num);
    329         if (rc != 0) {
    330             LOG(WARNING) << "failed to claim adb interface for device '" << device_serial << "'"
    331                          << libusb_error_name(rc);
    332             return;
    333         }
    334 
    335         rc = libusb_set_interface_alt_setting(handle.get(), interface_num, 0);
    336         if (rc != 0) {
    337             LOG(WARNING) << "failed to set interface alt setting for device '" << device_serial
    338                          << "'" << libusb_error_name(rc);
    339             return;
    340         }
    341 
    342         for (uint8_t endpoint : {bulk_in, bulk_out}) {
    343             rc = libusb_clear_halt(handle.get(), endpoint);
    344             if (rc != 0) {
    345                 LOG(WARNING) << "failed to clear halt on device '" << device_serial
    346                              << "' endpoint 0x" << std::hex << endpoint << ": "
    347                              << libusb_error_name(rc);
    348                 libusb_release_interface(handle.get(), interface_num);
    349                 return;
    350             }
    351         }
    352     } else {
    353         LOG(WARNING) << "failed to open usb device at " << device_address << ": "
    354                      << libusb_error_name(rc);
    355         writable = false;
    356 
    357 #if defined(__linux__)
    358         // libusb doesn't think we should be messing around with devices we don't have
    359         // write access to, but Linux at least lets us get the serial number anyway.
    360         if (!android::base::ReadFileToString(get_device_serial_path(device), &device_serial)) {
    361             // We don't actually want to treat an unknown serial as an error because
    362             // devices aren't able to communicate a serial number in early bringup.
    363             // http://b/20883914
    364             device_serial = "unknown";
    365         }
    366         device_serial = android::base::Trim(device_serial);
    367 #else
    368         // On Mac OS and Windows, we're screwed. But I don't think this situation actually
    369         // happens on those OSes.
    370         return;
    371 #endif
    372     }
    373 
    374     std::unique_ptr<usb_handle> result(new usb_handle(device_address, device_serial,
    375                                                       std::move(handle), interface_num, bulk_in,
    376                                                       bulk_out, zero_mask, packet_size));
    377     usb_handle* usb_handle_raw = result.get();
    378 
    379     {
    380         std::unique_lock<std::mutex> lock(usb_handles_mutex);
    381         usb_handles[device_address] = std::move(result);
    382 
    383         register_usb_transport(usb_handle_raw, device_serial.c_str(), device_address.c_str(),
    384                                writable);
    385     }
    386     LOG(INFO) << "registered new usb device '" << device_serial << "'";
    387 }
    388 
    389 static std::atomic<int> connecting_devices(0);
    390 
    391 static void device_connected(libusb_device* device) {
    392 #if defined(__linux__)
    393     // Android's host linux libusb uses netlink instead of udev for device hotplug notification,
    394     // which means we can get hotplug notifications before udev has updated ownership/perms on the
    395     // device. Since we're not going to be able to link against the system's libudev any time soon,
    396     // hack around this by inserting a sleep.
    397     auto thread = std::thread([device]() {
    398         std::string device_path = get_device_dev_path(device);
    399         std::this_thread::sleep_for(std::chrono::seconds(1));
    400 
    401         process_device(device);
    402         if (--connecting_devices == 0) {
    403             adb_notify_device_scan_complete();
    404         }
    405     });
    406     thread.detach();
    407 #else
    408     process_device(device);
    409 #endif
    410 }
    411 
    412 static void device_disconnected(libusb_device* device) {
    413     std::string device_address = get_device_address(device);
    414 
    415     LOG(INFO) << "device disconnected: " << device_address;
    416     std::unique_lock<std::mutex> lock(usb_handles_mutex);
    417     auto it = usb_handles.find(device_address);
    418     if (it != usb_handles.end()) {
    419         if (!it->second->device_handle) {
    420             // If the handle is null, we were never able to open the device.
    421 
    422             // Temporarily release the usb handles mutex to avoid deadlock.
    423             std::unique_ptr<usb_handle> handle = std::move(it->second);
    424             usb_handles.erase(it);
    425             lock.unlock();
    426             unregister_usb_transport(handle.get());
    427             lock.lock();
    428         } else {
    429             // Closure of the transport will erase the usb_handle.
    430         }
    431     }
    432 }
    433 
    434 static auto& hotplug_queue = *new BlockingQueue<std::pair<libusb_hotplug_event, libusb_device*>>();
    435 static void hotplug_thread() {
    436     adb_thread_setname("libusb hotplug");
    437     while (true) {
    438         hotplug_queue.PopAll([](std::pair<libusb_hotplug_event, libusb_device*> pair) {
    439             libusb_hotplug_event event = pair.first;
    440             libusb_device* device = pair.second;
    441             if (event == LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED) {
    442                 device_connected(device);
    443             } else if (event == LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT) {
    444                 device_disconnected(device);
    445             }
    446         });
    447     }
    448 }
    449 
    450 static LIBUSB_CALL int hotplug_callback(libusb_context*, libusb_device* device,
    451                                         libusb_hotplug_event event, void*) {
    452     // We're called with the libusb lock taken. Call these on a separate thread outside of this
    453     // function so that the usb_handle mutex is always taken before the libusb mutex.
    454     static std::once_flag once;
    455     std::call_once(once, []() { std::thread(hotplug_thread).detach(); });
    456 
    457     if (event == LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED) {
    458         ++connecting_devices;
    459     }
    460     hotplug_queue.Push({event, device});
    461     return 0;
    462 }
    463 
    464 void usb_init() {
    465     LOG(DEBUG) << "initializing libusb...";
    466     int rc = libusb_init(nullptr);
    467     if (rc != 0) {
    468         LOG(FATAL) << "failed to initialize libusb: " << libusb_error_name(rc);
    469     }
    470 
    471     // Register the hotplug callback.
    472     rc = libusb_hotplug_register_callback(
    473         nullptr, static_cast<libusb_hotplug_event>(LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED |
    474                                                    LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT),
    475         LIBUSB_HOTPLUG_ENUMERATE, LIBUSB_HOTPLUG_MATCH_ANY, LIBUSB_HOTPLUG_MATCH_ANY,
    476         LIBUSB_CLASS_PER_INTERFACE, hotplug_callback, nullptr, &hotplug_handle);
    477 
    478     if (rc != LIBUSB_SUCCESS) {
    479         LOG(FATAL) << "failed to register libusb hotplug callback";
    480     }
    481 
    482     // Spawn a thread for libusb_handle_events.
    483     std::thread([]() {
    484         adb_thread_setname("libusb");
    485         while (true) {
    486             libusb_handle_events(nullptr);
    487         }
    488     }).detach();
    489 }
    490 
    491 void usb_cleanup() {
    492     libusb_hotplug_deregister_callback(nullptr, hotplug_handle);
    493 }
    494 
    495 static LIBUSB_CALL void transfer_callback(libusb_transfer* transfer) {
    496     transfer_info* info = static_cast<transfer_info*>(transfer->user_data);
    497 
    498     LOG(DEBUG) << info->name << " transfer callback entered";
    499 
    500     // Make sure that the original submitter has made it to the condition_variable wait.
    501     std::unique_lock<std::mutex> lock(info->mutex);
    502 
    503     LOG(DEBUG) << info->name << " callback successfully acquired lock";
    504 
    505     if (transfer->status != LIBUSB_TRANSFER_COMPLETED) {
    506         LOG(WARNING) << info->name << " transfer failed: " << libusb_error_name(transfer->status);
    507         info->Notify();
    508         return;
    509     }
    510 
    511     // usb_read() can return when receiving some data.
    512     if (info->is_bulk_out && transfer->actual_length != transfer->length) {
    513         LOG(DEBUG) << info->name << " transfer incomplete, resubmitting";
    514         transfer->length -= transfer->actual_length;
    515         transfer->buffer += transfer->actual_length;
    516         int rc = libusb_submit_transfer(transfer);
    517         if (rc != 0) {
    518             LOG(WARNING) << "failed to submit " << info->name
    519                          << " transfer: " << libusb_error_name(rc);
    520             transfer->status = LIBUSB_TRANSFER_ERROR;
    521             info->Notify();
    522         }
    523         return;
    524     }
    525 
    526     if (should_perform_zero_transfer(transfer->endpoint, transfer->length, info->zero_mask)) {
    527         LOG(DEBUG) << "submitting zero-length write";
    528         transfer->length = 0;
    529         int rc = libusb_submit_transfer(transfer);
    530         if (rc != 0) {
    531             LOG(WARNING) << "failed to submit zero-length write: " << libusb_error_name(rc);
    532             transfer->status = LIBUSB_TRANSFER_ERROR;
    533             info->Notify();
    534         }
    535         return;
    536     }
    537 
    538     LOG(VERBOSE) << info->name << "transfer fully complete";
    539     info->Notify();
    540 }
    541 
    542 // Dispatch a libusb transfer, unlock |device_lock|, and then wait for the result.
    543 static int perform_usb_transfer(usb_handle* h, transfer_info* info,
    544                                 std::unique_lock<std::mutex> device_lock) {
    545     libusb_transfer* transfer = info->transfer;
    546 
    547     transfer->user_data = info;
    548     transfer->callback = transfer_callback;
    549 
    550     LOG(DEBUG) << "locking " << info->name << " transfer_info mutex";
    551     std::unique_lock<std::mutex> lock(info->mutex);
    552     info->transfer_complete = false;
    553     LOG(DEBUG) << "submitting " << info->name << " transfer";
    554     int rc = libusb_submit_transfer(transfer);
    555     if (rc != 0) {
    556         LOG(WARNING) << "failed to submit " << info->name << " transfer: " << libusb_error_name(rc);
    557         errno = EIO;
    558         return -1;
    559     }
    560 
    561     LOG(DEBUG) << info->name << " transfer successfully submitted";
    562     device_lock.unlock();
    563     info->cv.wait(lock, [info]() { return info->transfer_complete; });
    564     if (transfer->status != 0) {
    565         errno = EIO;
    566         return -1;
    567     }
    568 
    569     return 0;
    570 }
    571 
    572 int usb_write(usb_handle* h, const void* d, int len) {
    573     LOG(DEBUG) << "usb_write of length " << len;
    574 
    575     std::unique_lock<std::mutex> lock(h->device_handle_mutex);
    576     if (!h->device_handle) {
    577         errno = EIO;
    578         return -1;
    579     }
    580 
    581     transfer_info* info = &h->write;
    582     info->transfer->dev_handle = h->device_handle;
    583     info->transfer->flags = 0;
    584     info->transfer->endpoint = h->bulk_out;
    585     info->transfer->type = LIBUSB_TRANSFER_TYPE_BULK;
    586     info->transfer->length = len;
    587     info->transfer->buffer = reinterpret_cast<unsigned char*>(const_cast<void*>(d));
    588     info->transfer->num_iso_packets = 0;
    589 
    590     int rc = perform_usb_transfer(h, info, std::move(lock));
    591     LOG(DEBUG) << "usb_write(" << len << ") = " << rc;
    592     return rc;
    593 }
    594 
    595 int usb_read(usb_handle* h, void* d, int len) {
    596     LOG(DEBUG) << "usb_read of length " << len;
    597 
    598     std::unique_lock<std::mutex> lock(h->device_handle_mutex);
    599     if (!h->device_handle) {
    600         errno = EIO;
    601         return -1;
    602     }
    603 
    604     transfer_info* info = &h->read;
    605     info->transfer->dev_handle = h->device_handle;
    606     info->transfer->flags = 0;
    607     info->transfer->endpoint = h->bulk_in;
    608     info->transfer->type = LIBUSB_TRANSFER_TYPE_BULK;
    609     info->transfer->length = len;
    610     info->transfer->buffer = reinterpret_cast<unsigned char*>(d);
    611     info->transfer->num_iso_packets = 0;
    612 
    613     int rc = perform_usb_transfer(h, info, std::move(lock));
    614     LOG(DEBUG) << "usb_read(" << len << ") = " << rc << ", actual_length "
    615                << info->transfer->actual_length;
    616     if (rc < 0) {
    617         return rc;
    618     }
    619     return info->transfer->actual_length;
    620 }
    621 
    622 int usb_close(usb_handle* h) {
    623     std::unique_lock<std::mutex> lock(usb_handles_mutex);
    624     auto it = usb_handles.find(h->device_address);
    625     if (it == usb_handles.end()) {
    626         LOG(FATAL) << "attempted to close unregistered usb_handle for '" << h->serial << "'";
    627     }
    628     usb_handles.erase(h->device_address);
    629     return 0;
    630 }
    631 
    632 void usb_kick(usb_handle* h) {
    633     h->Close();
    634 }
    635 
    636 size_t usb_get_max_packet_size(usb_handle* h) {
    637     CHECK(h->max_packet_size != 0);
    638     return h->max_packet_size;
    639 }
    640 
    641 } // namespace libusb
    642