summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGravatar Nikias Bassen2013-02-28 16:04:44 +0100
committerGravatar Nikias Bassen2013-02-28 16:04:44 +0100
commit9da79e5dc1ba779b13b2d0d1f59e19d015af7a3e (patch)
treeee0eaa4dcded59b14beab76ab37a0a5ddb611fb9
parent6f6484fb4565cb7378f610d736ea8263652f67c5 (diff)
downloadusbmuxd-9da79e5dc1ba779b13b2d0d1f59e19d015af7a3e.tar.gz
usbmuxd-9da79e5dc1ba779b13b2d0d1f59e19d015af7a3e.tar.bz2
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.
-rw-r--r--libusbmuxd/libusbmuxd.c98
1 files 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;
}