From a19dc5122799254344007aeaf7971d32dc4e42b2 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Mon, 25 Jun 2012 09:30:31 -0700 Subject: qmimodem: Add support for shared services with same client id --- drivers/qmimodem/qmi.c | 100 +++++++++++++++++++++++++++++++++++++++++++++---- drivers/qmimodem/qmi.h | 3 ++ 2 files changed, 96 insertions(+), 7 deletions(-) (limited to 'drivers/qmimodem') diff --git a/drivers/qmimodem/qmi.c b/drivers/qmimodem/qmi.c index ff611ec4..12a183f8 100644 --- a/drivers/qmimodem/qmi.c +++ b/drivers/qmimodem/qmi.c @@ -65,6 +65,7 @@ struct qmi_device { struct qmi_service { int ref_count; struct qmi_device *device; + bool shared; uint8_t type; uint16_t major; uint16_t minor; @@ -223,6 +224,21 @@ static gint __notify_compare(gconstpointer a, gconstpointer b) return notify->id - id; } +static gboolean __service_compare_shared(gpointer key, gpointer value, + gpointer user_data) +{ + struct qmi_service *service = value; + uint8_t type = GPOINTER_TO_UINT(user_data); + + if (!service->shared) + return FALSE; + + if (service->type == type) + return TRUE; + + return FALSE; +} + static void __hexdump(const char dir, const unsigned char *buf, size_t len, qmi_debug_func_t function, void *user_data) { @@ -1353,6 +1369,7 @@ bool qmi_result_get_uint64(struct qmi_result *result, uint8_t type, struct service_create_data { struct qmi_device *device; + bool shared; uint8_t type; uint16_t major; uint16_t minor; @@ -1412,6 +1429,7 @@ static void service_create_callback(uint16_t message, uint16_t length, service->ref_count = 1; service->device = data->device; + service->shared = data->shared; service->type = data->type; service->major = data->major; @@ -1479,26 +1497,22 @@ static void service_create_discover(uint8_t count, __request_submit(device, req, hdr->transaction); } -bool qmi_service_create(struct qmi_device *device, +static bool service_create(struct qmi_device *device, bool shared, uint8_t type, qmi_create_func_t func, void *user_data, qmi_destroy_func_t destroy) { struct service_create_data *data; - if (!device || !func) - return false; - - if (type == QMI_SERVICE_CONTROL) - return false; - data = g_try_new0(struct service_create_data, 1); if (!data) return false; data->device = device; + data->shared = shared; data->type = type; data->func = func; data->user_data = user_data; + data->destroy = destroy; if (device->version_list) { service_create_discover(device->version_count, @@ -1519,6 +1533,78 @@ done: return true; } +bool qmi_service_create(struct qmi_device *device, + uint8_t type, qmi_create_func_t func, + void *user_data, qmi_destroy_func_t destroy) +{ + if (!device || !func) + return false; + + if (type == QMI_SERVICE_CONTROL) + return false; + + return service_create(device, false, type, func, user_data, destroy); +} + +struct service_create_shared_data { + struct qmi_service *service; + qmi_create_func_t func; + void *user_data; + qmi_destroy_func_t destroy; +}; + +static gboolean service_create_shared_reply(gpointer user_data) +{ + struct service_create_shared_data *data = user_data; + + data->func(data->service, data->user_data); + + qmi_service_unref(data->service); + + if (data->destroy) + data->destroy(data->user_data); + + g_free(data); + + return FALSE; +} + +bool qmi_service_create_shared(struct qmi_device *device, + uint8_t type, qmi_create_func_t func, + void *user_data, qmi_destroy_func_t destroy) +{ + struct qmi_service *service; + unsigned int type_val = type; + + if (!device || !func) + return false; + + if (type == QMI_SERVICE_CONTROL) + return false; + + service = g_hash_table_find(device->service_list, + __service_compare_shared, GUINT_TO_POINTER(type_val)); + if (service) { + struct service_create_shared_data *data; + + data = g_try_new0(struct service_create_shared_data, 1); + if (!data) + return false; + + data->service = qmi_service_ref(service); + + data->func = func; + data->user_data = user_data; + data->destroy = destroy; + + g_timeout_add(0, service_create_shared_reply, data); + + return 0; + } + + return service_create(device, true, type, func, user_data, destroy); +} + static void service_release_callback(uint16_t message, uint16_t length, const void *buffer, void *user_data) { diff --git a/drivers/qmimodem/qmi.h b/drivers/qmimodem/qmi.h index b2aa9d60..3e51a829 100644 --- a/drivers/qmimodem/qmi.h +++ b/drivers/qmimodem/qmi.h @@ -127,6 +127,9 @@ typedef void (*qmi_create_func_t)(struct qmi_service *service, void *user_data); bool qmi_service_create(struct qmi_device *device, uint8_t type, qmi_create_func_t func, void *user_data, qmi_destroy_func_t destroy); +bool qmi_service_create_shared(struct qmi_device *device, + uint8_t type, qmi_create_func_t func, + void *user_data, qmi_destroy_func_t destroy); struct qmi_service *qmi_service_ref(struct qmi_service *service); void qmi_service_unref(struct qmi_service *service); -- cgit v1.2.3