Add new idevice_events_subscribe/unsubscribe API with context
The older API idevice_event_subscribe/unsubscribe can only be used
by a single instance. With the addition of a context, is is now possible
to register multiple callback functions in different threads.
For backwards compatibility the old API will still be available for a while
before being removed in a future release.
diff --git a/include/libimobiledevice/libimobiledevice.h b/include/libimobiledevice/libimobiledevice.h
index c3b87cd..6851145 100644
--- a/include/libimobiledevice/libimobiledevice.h
+++ b/include/libimobiledevice/libimobiledevice.h
@@ -94,6 +94,9 @@
/** Callback to notifiy if a device was added or removed. */
typedef void (*idevice_event_cb_t) (const idevice_event_t *event, void *user_data);
+/** Event subscription context type */
+typedef struct idevice_subscription_context* idevice_subscription_context_t;
+
/* functions */
/**
@@ -104,9 +107,36 @@
void idevice_set_debug_level(int level);
/**
- * Register a callback function that will be called when device add/remove
+ * Subscribe a callback function that will be called when device add/remove
* events occur.
*
+ * @param context A pointer to a idevice_subscription_context_t that will be
+ * set upon creation of the subscription. The returned context must be
+ * passed to idevice_events_unsubscribe() to unsubscribe the callback.
+ * @param callback Callback function to call.
+ * @param user_data Application-specific data passed as parameter
+ * to the registered callback function.
+ *
+ * @return IDEVICE_E_SUCCESS on success or an error value when an error occurred.
+ */
+idevice_error_t idevice_events_subscribe(idevice_subscription_context_t *context, idevice_event_cb_t callback, void *user_data);
+
+/**
+ * Unsubscribe the event callback function that has been registered with
+ * idevice_events_subscribe().
+ *
+ * @param context A valid context as returned from idevice_events_subscribe().
+ *
+ * @return IDEVICE_E_SUCCESS on success or an error value when an error occurred.
+ */
+idevice_error_t idevice_events_unsubscribe(idevice_subscription_context_t context);
+
+/**
+ * (DEPRECATED) Register a callback function that will be called when device add/remove
+ * events occur.
+ *
+ * @deprecated Use idevice_events_subscribe() instead.
+ *
* @param callback Callback function to call.
* @param user_data Application-specific data passed as parameter
* to the registered callback function.
@@ -116,9 +146,11 @@
idevice_error_t idevice_event_subscribe(idevice_event_cb_t callback, void *user_data);
/**
- * Release the event callback function that has been registered with
+ * (DEPRECATED) Release the event callback function that has been registered with
* idevice_event_subscribe().
*
+ * @deprecated Use idevice_events_unsubscribe() instead.
+ *
* @return IDEVICE_E_SUCCESS on success or an error value when an error occurred.
*/
idevice_error_t idevice_event_unsubscribe(void);
diff --git a/src/idevice.c b/src/idevice.c
index 22d57e3..c8574fc 100644
--- a/src/idevice.c
+++ b/src/idevice.c
@@ -215,10 +215,17 @@
#warning No compiler support for constructor/destructor attributes, some features might not be available.
#endif
-static idevice_event_cb_t event_cb = NULL;
+struct idevice_subscription_context {
+ idevice_event_cb_t callback;
+ void *user_data;
+ usbmuxd_subscription_context_t ctx;
+};
+
+static idevice_subscription_context_t event_ctx = NULL;
static void usbmux_event_cb(const usbmuxd_event_t *event, void *user_data)
{
+ idevice_subscription_context_t context = (idevice_subscription_context_t)user_data;
idevice_event_t ev;
ev.event = event->event;
@@ -232,34 +239,66 @@
debug_info("Unknown connection type %d", event->device.conn_type);
}
- if (event_cb) {
- event_cb(&ev, user_data);
+ if (context->callback) {
+ context->callback(&ev, context->user_data);
}
}
-LIBIMOBILEDEVICE_API idevice_error_t idevice_event_subscribe(idevice_event_cb_t callback, void *user_data)
+LIBIMOBILEDEVICE_API idevice_error_t idevice_events_subscribe(idevice_subscription_context_t *context, idevice_event_cb_t callback, void *user_data)
{
- event_cb = callback;
- int res = usbmuxd_subscribe(usbmux_event_cb, user_data);
+ if (!context || !callback) {
+ return IDEVICE_E_INVALID_ARG;
+ }
+ *context = malloc(sizeof(struct idevice_subscription_context));
+ if (!*context) {
+ debug_info("ERROR: %s: Failed to allocate subscription context\n", __func__);
+ return IDEVICE_E_UNKNOWN_ERROR;
+ }
+ (*context)->callback = callback;
+ (*context)->user_data = user_data;
+ int res = usbmuxd_events_subscribe(&(*context)->ctx, usbmux_event_cb, *context);
if (res != 0) {
- event_cb = NULL;
+ free(*context);
+ *context = NULL;
debug_info("ERROR: usbmuxd_subscribe() returned %d!", res);
return IDEVICE_E_UNKNOWN_ERROR;
}
return IDEVICE_E_SUCCESS;
}
-LIBIMOBILEDEVICE_API idevice_error_t idevice_event_unsubscribe(void)
+LIBIMOBILEDEVICE_API idevice_error_t idevice_events_unsubscribe(idevice_subscription_context_t context)
{
- event_cb = NULL;
- int res = usbmuxd_unsubscribe();
+ if (!context) {
+ return IDEVICE_E_INVALID_ARG;
+ }
+ int res = usbmuxd_events_unsubscribe(context->ctx);
if (res != 0) {
debug_info("ERROR: usbmuxd_unsubscribe() returned %d!", res);
return IDEVICE_E_UNKNOWN_ERROR;
}
+ if (context == event_ctx) {
+ event_ctx = NULL;
+ }
+ free(context);
return IDEVICE_E_SUCCESS;
}
+LIBIMOBILEDEVICE_API idevice_error_t idevice_event_subscribe(idevice_event_cb_t callback, void *user_data)
+{
+ if (event_ctx) {
+ idevice_events_unsubscribe(event_ctx);
+ }
+ return idevice_events_subscribe(&event_ctx, callback, user_data);
+}
+
+LIBIMOBILEDEVICE_API idevice_error_t idevice_event_unsubscribe(void)
+{
+ if (!event_ctx) {
+ return IDEVICE_E_SUCCESS;
+ }
+ return idevice_events_unsubscribe(event_ctx);
+}
+
LIBIMOBILEDEVICE_API idevice_error_t idevice_get_device_list_extended(idevice_info_t **devices, int *count)
{
usbmuxd_device_info_t *dev_list;
diff --git a/tools/idevicebtlogger.c b/tools/idevicebtlogger.c
index 421ce98..8de6b22 100644
--- a/tools/idevicebtlogger.c
+++ b/tools/idevicebtlogger.c
@@ -440,13 +440,14 @@
assert(0);
return -2;
}
- idevice_event_subscribe(device_event_cb, NULL);
+ idevice_subscription_context_t context = NULL;
+ idevice_events_subscribe(&context, device_event_cb, NULL);
while (!quit_flag) {
sleep(1);
}
- idevice_event_unsubscribe();
+ idevice_events_unsubscribe(context);
stop_logging();
fclose(packetlogger_file);
diff --git a/tools/idevicesyslog.c b/tools/idevicesyslog.c
index f85c7cc..3084b97 100644
--- a/tools/idevicesyslog.c
+++ b/tools/idevicesyslog.c
@@ -709,12 +709,13 @@
line_buffer_size = 1024;
line = malloc(line_buffer_size);
- idevice_event_subscribe(device_event_cb, NULL);
+ idevice_subscription_context_t context = NULL;
+ idevice_events_subscribe(&context, device_event_cb, NULL);
while (!quit_flag) {
sleep(1);
}
- idevice_event_unsubscribe();
+ idevice_events_unsubscribe(context);
stop_logging();
if (num_proc_filters > 0) {