summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJosh Gao2017-05-15 15:45:04 -0500
committerGerrit Code Review2017-05-15 15:45:06 -0500
commit55ddb99527be17b509f307e2c2727a80535f4b22 (patch)
tree6c350e86689242339256cf95638aef04234365e9
parent3d0186b97e0b559a2dbd75c558ff5834cc27cfc5 (diff)
parent425aefdcf0f1b2068f56ca091047af5f02ae3f3d (diff)
downloadplatform-system-core-55ddb99527be17b509f307e2c2727a80535f4b22.tar.gz
platform-system-core-55ddb99527be17b509f307e2c2727a80535f4b22.tar.xz
platform-system-core-55ddb99527be17b509f307e2c2727a80535f4b22.zip
Merge changes I8e8e0963,I3c714f63,Id157412e,Ib7c26fbd
* changes: adb: libusb: recognize devices with multiple interfaces. adb: libusb: wait for devices to become accessible. adb: libusb: switch to hotplug for device detection. adb: silence noise.
-rw-r--r--adb/adb.cpp6
-rw-r--r--adb/client/usb_libusb.cpp115
2 files changed, 78 insertions, 43 deletions
diff --git a/adb/adb.cpp b/adb/adb.cpp
index 23f6580e7..808d8ff2e 100644
--- a/adb/adb.cpp
+++ b/adb/adb.cpp
@@ -1241,10 +1241,7 @@ void update_transport_status() {
1241 return true; 1241 return true;
1242 }); 1242 });
1243 1243
1244 D("update_transport_status: transports_ready = %s", result ? "true" : "false");
1245
1246 bool ready; 1244 bool ready;
1247
1248 { 1245 {
1249 std::lock_guard<std::mutex> lock(init_mutex); 1246 std::lock_guard<std::mutex> lock(init_mutex);
1250 transports_ready = result; 1247 transports_ready = result;
@@ -1252,14 +1249,11 @@ void update_transport_status() {
1252 } 1249 }
1253 1250
1254 if (ready) { 1251 if (ready) {
1255 D("update_transport_status: notifying");
1256 init_cv.notify_all(); 1252 init_cv.notify_all();
1257 } 1253 }
1258} 1254}
1259 1255
1260void adb_notify_device_scan_complete() { 1256void adb_notify_device_scan_complete() {
1261 D("device scan complete");
1262
1263 { 1257 {
1264 std::lock_guard<std::mutex> lock(init_mutex); 1258 std::lock_guard<std::mutex> lock(init_mutex);
1265 device_scan_complete = true; 1259 device_scan_complete = true;
diff --git a/adb/client/usb_libusb.cpp b/adb/client/usb_libusb.cpp
index 18a8ff23a..fc32469fa 100644
--- a/adb/client/usb_libusb.cpp
+++ b/adb/client/usb_libusb.cpp
@@ -151,10 +151,7 @@ struct usb_handle : public ::usb_handle {
151static auto& usb_handles = *new std::unordered_map<std::string, std::unique_ptr<usb_handle>>(); 151static auto& usb_handles = *new std::unordered_map<std::string, std::unique_ptr<usb_handle>>();
152static auto& usb_handles_mutex = *new std::mutex(); 152static auto& usb_handles_mutex = *new std::mutex();
153 153
154static std::thread* device_poll_thread = nullptr; 154static libusb_hotplug_callback_handle hotplug_handle;
155static bool terminate_device_poll_thread = false;
156static auto& device_poll_mutex = *new std::mutex();
157static auto& device_poll_cv = *new std::condition_variable();
158 155
159static std::string get_device_address(libusb_device* device) { 156static std::string get_device_address(libusb_device* device) {
160 return StringPrintf("usb:%d:%d", libusb_get_bus_number(device), 157 return StringPrintf("usb:%d:%d", libusb_get_bus_number(device),
@@ -175,6 +172,17 @@ static std::string get_device_serial_path(libusb_device* device) {
175 path += "/serial"; 172 path += "/serial";
176 return path; 173 return path;
177} 174}
175
176static 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
183static bool is_device_accessible(libusb_device* device) {
184 return access(get_device_dev_path(device).c_str(), R_OK | W_OK) == 0;
185}
178#endif 186#endif
179 187
180static bool endpoint_is_output(uint8_t endpoint) { 188static bool endpoint_is_output(uint8_t endpoint) {
@@ -229,7 +237,7 @@ static void process_device(libusb_device* device) {
229 // TODO: Is this assumption valid? 237 // TODO: Is this assumption valid?
230 LOG(VERBOSE) << "skipping interface with incorrect num_altsetting at " << device_address 238 LOG(VERBOSE) << "skipping interface with incorrect num_altsetting at " << device_address
231 << " (interface " << interface_num << ")"; 239 << " (interface " << interface_num << ")";
232 return; 240 continue;
233 } 241 }
234 242
235 const libusb_interface_descriptor& interface_desc = interface.altsetting[0]; 243 const libusb_interface_descriptor& interface_desc = interface.altsetting[0];
@@ -237,7 +245,7 @@ static void process_device(libusb_device* device) {
237 interface_desc.bInterfaceProtocol)) { 245 interface_desc.bInterfaceProtocol)) {
238 LOG(VERBOSE) << "skipping non-adb interface at " << device_address << " (interface " 246 LOG(VERBOSE) << "skipping non-adb interface at " << device_address << " (interface "
239 << interface_num << ")"; 247 << interface_num << ")";
240 return; 248 continue;
241 } 249 }
242 250
243 LOG(VERBOSE) << "found potential adb interface at " << device_address << " (interface " 251 LOG(VERBOSE) << "found potential adb interface at " << device_address << " (interface "
@@ -253,7 +261,7 @@ static void process_device(libusb_device* device) {
253 const uint8_t transfer_type = endpoint_attr & LIBUSB_TRANSFER_TYPE_MASK; 261 const uint8_t transfer_type = endpoint_attr & LIBUSB_TRANSFER_TYPE_MASK;
254 262
255 if (transfer_type != LIBUSB_TRANSFER_TYPE_BULK) { 263 if (transfer_type != LIBUSB_TRANSFER_TYPE_BULK) {
256 return; 264 continue;
257 } 265 }
258 266
259 if (endpoint_is_output(endpoint_addr) && !found_out) { 267 if (endpoint_is_output(endpoint_addr) && !found_out) {
@@ -371,33 +379,62 @@ static void process_device(libusb_device* device) {
371 } 379 }
372 380
373 register_usb_transport(usb_handle_raw, device_serial.c_str(), device_address.c_str(), writable); 381 register_usb_transport(usb_handle_raw, device_serial.c_str(), device_address.c_str(), writable);
374
375 LOG(INFO) << "registered new usb device '" << device_serial << "'"; 382 LOG(INFO) << "registered new usb device '" << device_serial << "'";
376} 383}
377 384
378static void poll_for_devices() { 385static std::atomic<int> connecting_devices(0);
379 libusb_device** list;
380 adb_thread_setname("device poll");
381 while (true) {
382 const ssize_t device_count = libusb_get_device_list(nullptr, &list);
383
384 LOG(VERBOSE) << "found " << device_count << " attached devices";
385 386
386 for (ssize_t i = 0; i < device_count; ++i) { 387static void device_connected(libusb_device* device) {
387 process_device(list[i]); 388#if defined(__linux__)
389 // Android's host linux libusb uses netlink instead of udev for device hotplug notification,
390 // which means we can get hotplug notifications before udev has updated ownership/perms on the
391 // device. Since we're not going to be able to link against the system's libudev any time soon,
392 // hack around this by checking for accessibility in a loop.
393 ++connecting_devices;
394 auto thread = std::thread([device]() {
395 std::string device_path = get_device_dev_path(device);
396 auto start = std::chrono::steady_clock::now();
397 while (std::chrono::steady_clock::now() - start < 500ms) {
398 if (is_device_accessible(device)) {
399 break;
400 }
401 std::this_thread::sleep_for(10ms);
388 } 402 }
389 403
390 libusb_free_device_list(list, 1); 404 process_device(device);
405 --connecting_devices;
406 });
407 thread.detach();
408#else
409 process_device(device);
410#endif
411}
391 412
392 adb_notify_device_scan_complete(); 413static void device_disconnected(libusb_device* device) {
414 std::string device_address = get_device_address(device);
393 415
394 std::unique_lock<std::mutex> lock(device_poll_mutex); 416 LOG(INFO) << "device disconnected: " << device_address;
395 if (device_poll_cv.wait_for(lock, 500ms, []() { return terminate_device_poll_thread; })) { 417 std::unique_lock<std::mutex> lock(usb_handles_mutex);
396 return; 418 auto it = usb_handles.find(device_address);
419 if (it != usb_handles.end()) {
420 if (!it->second->device_handle) {
421 // If the handle is null, we were never able to open the device.
422 unregister_usb_transport(it->second.get());
397 } 423 }
424 usb_handles.erase(it);
398 } 425 }
399} 426}
400 427
428static int hotplug_callback(libusb_context*, libusb_device* device, libusb_hotplug_event event,
429 void*) {
430 if (event == LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED) {
431 device_connected(device);
432 } else if (event == LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT) {
433 device_disconnected(device);
434 }
435 return 0;
436}
437
401void usb_init() { 438void usb_init() {
402 LOG(DEBUG) << "initializing libusb..."; 439 LOG(DEBUG) << "initializing libusb...";
403 int rc = libusb_init(nullptr); 440 int rc = libusb_init(nullptr);
@@ -405,6 +442,24 @@ void usb_init() {
405 LOG(FATAL) << "failed to initialize libusb: " << libusb_error_name(rc); 442 LOG(FATAL) << "failed to initialize libusb: " << libusb_error_name(rc);
406 } 443 }
407 444
445 // Register the hotplug callback.
446 rc = libusb_hotplug_register_callback(
447 nullptr, static_cast<libusb_hotplug_event>(LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED |
448 LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT),
449 LIBUSB_HOTPLUG_ENUMERATE, LIBUSB_HOTPLUG_MATCH_ANY, LIBUSB_HOTPLUG_MATCH_ANY,
450 LIBUSB_CLASS_PER_INTERFACE, hotplug_callback, nullptr, &hotplug_handle);
451
452 if (rc != LIBUSB_SUCCESS) {
453 LOG(FATAL) << "failed to register libusb hotplug callback";
454 }
455
456 // Wait for all of the connecting devices to finish.
457 while (connecting_devices != 0) {
458 std::this_thread::sleep_for(10ms);
459 }
460
461 adb_notify_device_scan_complete();
462
408 // Spawn a thread for libusb_handle_events. 463 // Spawn a thread for libusb_handle_events.
409 std::thread([]() { 464 std::thread([]() {
410 adb_thread_setname("libusb"); 465 adb_thread_setname("libusb");
@@ -412,24 +467,10 @@ void usb_init() {
412 libusb_handle_events(nullptr); 467 libusb_handle_events(nullptr);
413 } 468 }
414 }).detach(); 469 }).detach();
415
416 // Spawn a thread to do device enumeration.
417 // TODO: Use libusb_hotplug_* instead?
418 std::unique_lock<std::mutex> lock(device_poll_mutex);
419 device_poll_thread = new std::thread(poll_for_devices);
420} 470}
421 471
422void usb_cleanup() { 472void usb_cleanup() {
423 { 473 libusb_hotplug_deregister_callback(nullptr, hotplug_handle);
424 std::unique_lock<std::mutex> lock(device_poll_mutex);
425 terminate_device_poll_thread = true;
426
427 if (!device_poll_thread) {
428 return;
429 }
430 }
431 device_poll_cv.notify_all();
432 device_poll_thread->join();
433} 474}
434 475
435// Dispatch a libusb transfer, unlock |device_lock|, and then wait for the result. 476// Dispatch a libusb transfer, unlock |device_lock|, and then wait for the result.