From 9da79e5dc1ba779b13b2d0d1f59e19d015af7a3e Mon Sep 17 00:00:00 2001 From: Nikias Bassen Date: Thu, 28 Feb 2013 16:04:44 +0100 Subject: libusbmuxd: use a monitor to handle device events and use a device list cache this greatly improves the lookup speed if a lot of devices are attached. --- libusbmuxd/libusbmuxd.c | 98 +++++++++++++++++++++++++++++++++++++------------ 1 file changed, 74 insertions(+), 24 deletions(-) diff --git a/libusbmuxd/libusbmuxd.c b/libusbmuxd/libusbmuxd.c index 956dd90..8470ddc 100644 --- a/libusbmuxd/libusbmuxd.c +++ b/libusbmuxd/libusbmuxd.c @@ -68,8 +68,13 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA static int libusbmuxd_debug = 0; #define DEBUG(x, y, ...) if (x <= libusbmuxd_debug) fprintf(stderr, (y), __VA_ARGS__); +static int libusbmuxd_initialized = 0; + static struct collection devices; +static int handle_events = 0; + static usbmuxd_event_cb_t event_cb = NULL; +static void* event_user_data = NULL; #ifdef WIN32 HANDLE devmon = NULL; CRITICAL_SECTION mutex; @@ -77,7 +82,7 @@ static int mutex_initialized = 0; #define LOCK if (!mutex_initialized) { InitializeCriticalSection(&mutex); mutex_initialized = 1; } EnterCriticalSection(&mutex); #define UNLOCK LeaveCriticalSection(&mutex); #else -pthread_t devmon; +pthread_t devmon = 0; pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; #define LOCK pthread_mutex_lock(&mutex) #define UNLOCK pthread_mutex_unlock(&mutex) @@ -619,15 +624,15 @@ static void *device_monitor(void *data) #ifndef WIN32 pthread_cleanup_push(device_monitor_cleanup, NULL); #endif - while (event_cb) { + while (handle_events) { listenfd = usbmuxd_listen(); if (listenfd < 0) { continue; } - while (event_cb) { - int res = get_next_event(listenfd, event_cb, data); + while (handle_events) { + int res = get_next_event(listenfd, event_cb, event_user_data); if (res < 0) { break; } @@ -642,34 +647,32 @@ static void *device_monitor(void *data) return NULL; } -int usbmuxd_subscribe(usbmuxd_event_cb_t callback, void *user_data) +int usbmuxd_init() { - int res; - - if (!callback) { - return -EINVAL; - } - event_cb = callback; - + int res = 0; + handle_events = 1; #ifdef WIN32 - res = 0; - devmon = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)device_monitor, user_data, 0, NULL); + devmon = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)device_monitor, NULL, 0, NULL); if (devmon == NULL) { res = GetLastError(); } #else - res = pthread_create(&devmon, NULL, device_monitor, user_data); + res = pthread_create(&devmon, NULL, device_monitor, NULL); #endif if (res != 0) { DEBUG(1, "%s: ERROR: Could not start device watcher thread!\n", __func__); + handle_events = 0; return res; } + struct timespec ts = {0, 250000000}; + nanosleep(&ts, NULL); + libusbmuxd_initialized = 1; return 0; } -int usbmuxd_unsubscribe() +int usbmuxd_deinit() { - event_cb = NULL; + handle_events = 0; shutdown_socket(listenfd, SHUT_RDWR); @@ -683,6 +686,33 @@ int usbmuxd_unsubscribe() pthread_join(devmon, NULL); } #endif + libusbmuxd_initialized = 0; + return 0; +} + +int usbmuxd_subscribe(usbmuxd_event_cb_t callback, void *user_data) +{ + if (!callback) { + return -EINVAL; + } + event_cb = callback; + event_user_data = user_data; + + if (!libusbmuxd_initialized) { + usbmuxd_init(); + } else { + FOREACH(usbmuxd_device_info_t *dev, &devices) { + generate_event(callback, dev, UE_DEVICE_ADD, user_data); + } ENDFOREACH + } + + return 0; +} + +int usbmuxd_unsubscribe() +{ + event_cb = NULL; + event_user_data = NULL; return 0; } @@ -711,14 +741,14 @@ retry: } use_tag++; - LOCK; + //LOCK; if (send_listen_packet(sfd, use_tag) > 0) { res = -1; // get response if (usbmuxd_get_result(sfd, use_tag, &res) && (res == 0)) { listen_success = 1; } else { - UNLOCK; + //UNLOCK; close_socket(sfd); #ifdef HAVE_PLIST if ((res == RESULT_BADVERSION) && (proto_version != 1)) { @@ -732,7 +762,7 @@ retry: } if (!listen_success) { - UNLOCK; + //UNLOCK; DEBUG(1, "%s: Could not send listen request!\n", __func__); return -1; } @@ -741,12 +771,12 @@ retry: // receive device list while (1) { - if (receive_packet(sfd, &hdr, &payload, 1000) > 0) { + if (receive_packet(sfd, &hdr, &payload, 250) > 0) { if (hdr.message == MESSAGE_DEVICE_ADD) { dev = payload; usbmuxd_device_info_t *devinfo = (usbmuxd_device_info_t*)malloc(sizeof(usbmuxd_device_info_t)); if (!devinfo) { - UNLOCK; + //UNLOCK; DEBUG(1, "%s: Out of memory!\n", __func__); free(payload); return -1; @@ -790,7 +820,7 @@ retry: break; } } - UNLOCK; + //UNLOCK; // explicitly close connection close_socket(sfd); @@ -824,16 +854,34 @@ int usbmuxd_device_list_free(usbmuxd_device_info_t **device_list) int usbmuxd_get_device_by_udid(const char *udid, usbmuxd_device_info_t *device) { usbmuxd_device_info_t *dev_list = NULL; + int result = 0; if (!device) { return -EINVAL; } + + if (!libusbmuxd_initialized) { + usbmuxd_init(); + } + + if (udid && devmon && (pthread_kill(devmon, 0) == 0)) { + result = -ENODEV; + FOREACH(usbmuxd_device_info_t *dev, &devices) { + if (dev && dev->udid && (strcmp(dev->udid, udid) == 0)) { + device->handle = dev->handle; + device->product_id = dev->product_id; + strcpy(device->udid, dev->udid); + result = 1; + break; + } + } ENDFOREACH + return result; + } else { if (usbmuxd_get_device_list(&dev_list) < 0) { return -ENODEV; } int i; - int result = 0; for (i = 0; dev_list[i].handle > 0; i++) { if (!udid) { device->handle = dev_list[i].handle; @@ -853,6 +901,8 @@ int usbmuxd_get_device_by_udid(const char *udid, usbmuxd_device_info_t *device) free(dev_list); + } + return result; } -- cgit v1.1-32-gdbae