summaryrefslogtreecommitdiffstats
path: root/drivers/qmimodem
diff options
context:
space:
mode:
authorMarcel Holtmann <marcel@holtmann.org>2012-06-25 09:30:31 -0700
committerMarcel Holtmann <marcel@holtmann.org>2012-06-25 09:30:31 -0700
commita19dc5122799254344007aeaf7971d32dc4e42b2 (patch)
tree3b6a4408137e6b0175f7404165bff22cd924764a /drivers/qmimodem
parentfa77d46f9db1c18069fd72c88b521197135d80cb (diff)
downloadofono-a19dc5122799254344007aeaf7971d32dc4e42b2.tar.bz2
qmimodem: Add support for shared services with same client id
Diffstat (limited to 'drivers/qmimodem')
-rw-r--r--drivers/qmimodem/qmi.c100
-rw-r--r--drivers/qmimodem/qmi.h3
2 files changed, 96 insertions, 7 deletions
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);