From 2b48c417c5b4f2fa78ab0960eb718ff081fa48e6 Mon Sep 17 00:00:00 2001 From: Nikias Bassen Date: Mon, 9 May 2022 13:03:01 +0200 Subject: 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. --- include/libimobiledevice/libimobiledevice.h | 36 +++++++++++++++++- src/idevice.c | 59 ++++++++++++++++++++++++----- tools/idevicebtlogger.c | 5 ++- tools/idevicesyslog.c | 5 ++- 4 files changed, 89 insertions(+), 16 deletions(-) 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 @@ typedef struct { /** 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 @@ typedef void (*idevice_event_cb_t) (const idevice_event_t *event, void *user_dat 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 @@ void idevice_set_debug_level(int level); 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 @@ BOOL WINAPI DllMain(HINSTANCE hModule, DWORD dwReason, LPVOID lpReserved) #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 @@ static void usbmux_event_cb(const usbmuxd_event_t *event, void *user_data) 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 @@ int main(int argc, char *argv[]) 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 @@ int main(int argc, char *argv[]) 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) { -- cgit v1.1-32-gdbae