diff options
author | Josh Gao | 2017-05-15 15:51:16 -0500 |
---|---|---|
committer | android-build-merger | 2017-05-15 15:51:16 -0500 |
commit | 66ca192ac3ab2c31e27f91edd19e82a2ed4f60f1 (patch) | |
tree | 6c350e86689242339256cf95638aef04234365e9 | |
parent | daae7558e82e7b6a68fd9748b476386426a7524f (diff) | |
parent | 55ddb99527be17b509f307e2c2727a80535f4b22 (diff) | |
download | platform-system-core-66ca192ac3ab2c31e27f91edd19e82a2ed4f60f1.tar.gz platform-system-core-66ca192ac3ab2c31e27f91edd19e82a2ed4f60f1.tar.xz platform-system-core-66ca192ac3ab2c31e27f91edd19e82a2ed4f60f1.zip |
Merge changes I8e8e0963,I3c714f63,Id157412e,Ib7c26fbd
am: 55ddb99527
Change-Id: If947b8e8efd9ad873defabe3f6fea3caacf394ed
-rw-r--r-- | adb/adb.cpp | 6 | ||||
-rw-r--r-- | adb/client/usb_libusb.cpp | 115 |
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 | ||
1260 | void adb_notify_device_scan_complete() { | 1256 | void 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 { | |||
151 | static auto& usb_handles = *new std::unordered_map<std::string, std::unique_ptr<usb_handle>>(); | 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(); | 152 | static auto& usb_handles_mutex = *new std::mutex(); |
153 | 153 | ||
154 | static std::thread* device_poll_thread = nullptr; | 154 | static libusb_hotplug_callback_handle hotplug_handle; |
155 | static bool terminate_device_poll_thread = false; | ||
156 | static auto& device_poll_mutex = *new std::mutex(); | ||
157 | static auto& device_poll_cv = *new std::condition_variable(); | ||
158 | 155 | ||
159 | static std::string get_device_address(libusb_device* device) { | 156 | static 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 | |||
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 | |||
183 | static 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 | ||
180 | static bool endpoint_is_output(uint8_t endpoint) { | 188 | static 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 | ||
378 | static void poll_for_devices() { | 385 | static 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) { | 387 | static 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(); | 413 | static 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 | ||
428 | static 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 | |||
401 | void usb_init() { | 438 | void 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 | ||
422 | void usb_cleanup() { | 472 | void 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. |