summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGreg Suarez <gpsuarez2512@gmail.com>2014-07-23 14:21:25 -0700
committerAleksander Morgado <aleksander@aleksander.es>2014-07-31 18:42:50 +0200
commit9adbfde7379a4aed19741fb447df74ed957c510b (patch)
tree2c317a3f618f537ac761ee6ad623a4b079d024e8
parentb2c7f2d9e6e40f24d0dfa943d0f14cb89ed156f9 (diff)
downloadlibmbim-9adbfde7379a4aed19741fb447df74ed957c510b.tar.gz
libmbim-glib,proxy: Allow for --no-close and --no-open options by mbimcli
To support the --no-close option the proxy will no longer send the close message to the device. The proxy will also only exit once all devices are removed. Thus the proxy connects to the MBIM_DEVICE_SIGNAL_REMOVED signal for each device. A new property, MBIM_PROXY_N_DEVICES, was added to indicate the number of devices the proxy is managing. To support the --no-open option the proxy now calls the mbim_device_new() upon receiving the MBIM_CID_PROXY_CONTROL_CONFIGURATION with the device path.
-rw-r--r--src/libmbim-glib/mbim-proxy.c287
-rw-r--r--src/libmbim-glib/mbim-proxy.h2
2 files changed, 157 insertions, 132 deletions
diff --git a/src/libmbim-glib/mbim-proxy.c b/src/libmbim-glib/mbim-proxy.c
index 5be5241..17ea7d9 100644
--- a/src/libmbim-glib/mbim-proxy.c
+++ b/src/libmbim-glib/mbim-proxy.c
@@ -47,6 +47,7 @@ G_DEFINE_TYPE (MbimProxy, mbim_proxy, G_TYPE_OBJECT)
enum {
PROP_0,
PROP_N_CLIENTS,
+ PROP_N_DEVICES,
PROP_LAST
};
@@ -82,6 +83,22 @@ mbim_proxy_get_n_clients (MbimProxy *self)
return g_list_length (self->priv->clients);
}
+/**
+ * mbim_proxy_get_n_devices:
+ * @self: a #MbimProxy.
+ *
+ * Get the number of devices currently connected to the proxy.
+ *
+ * Returns: a #guint.
+ */
+guint
+mbim_proxy_get_n_devices (MbimProxy *self)
+{
+ g_return_val_if_fail (MBIM_IS_PROXY (self), 0);
+
+ return g_list_length (self->priv->devices);
+}
+
/*****************************************************************************/
typedef struct {
@@ -96,6 +113,7 @@ typedef struct {
MbimDevice *device;
MbimMessage *internal_proxy_open_request;
guint indication_id;
+ guint device_removed_id;
gchar *device_file_path;
gboolean opening_device;
gboolean service_subscriber_list_enabled;
@@ -107,6 +125,12 @@ typedef struct {
Client *client;
} DeviceOpenContext;
+typedef struct {
+ MbimProxy *proxy;
+ Client *client;
+ MbimMessage *response;
+} DeviceNewContext;
+
static gboolean connection_readable_cb (GSocket *socket, GIOCondition condition, Client *client);
static void
@@ -118,6 +142,8 @@ client_free (Client *client)
if (client->device) {
if (g_signal_handler_is_connected (client->device, client->indication_id))
g_signal_handler_disconnect (client->device, client->indication_id);
+ if (g_signal_handler_is_connected (client->device, client->device_removed_id))
+ g_signal_handler_disconnect (client->device, client->device_removed_id);
g_object_unref (client->device);
}
@@ -139,25 +165,6 @@ client_free (Client *client)
g_slice_free (Client, client);
}
-static guint
-get_n_clients_with_device (MbimProxy *self,
- MbimDevice *device)
-{
- GList *l;
- guint n = 0;
- Client *client;
-
- for (l = self->priv->clients; l; l = g_list_next (l)) {
- client = l->data;
-
- if (device == client->device ||
- g_str_equal (mbim_device_get_path (device), mbim_device_get_path (client->device)))
- n++;
- }
-
- return n;
-}
-
static Client *
get_client (MbimProxy *self,
Client *client)
@@ -171,50 +178,6 @@ get_client (MbimProxy *self,
}
static void
-device_close_ready (MbimDevice *device,
- GAsyncResult *result)
-{
- GError *error = NULL;
-
- if (!mbim_device_close_finish (device, result, &error)) {
- g_debug ("error: couldn't close device: %s", error->message);
- g_error_free (error);
- } else
- g_debug ("Device closed");
-
- g_object_unref (device);
-}
-
-static void
-device_close (MbimProxy *self,
- MbimDevice *device)
-{
- if (!device)
- return;
-
- /* If no more clients using the device, close and cleanup */
- if (get_n_clients_with_device (self, device) == 0) {
- GList *l;
-
- for (l = self->priv->devices; l; l = g_list_next (l)) {
- MbimDevice *device_in_list = MBIM_DEVICE (l->data);
-
- if (device == device_in_list ||
- g_str_equal (mbim_device_get_path (device), mbim_device_get_path (device_in_list))) {
- g_debug ("closing device '%s': no longer used", mbim_device_get_path_display (device));
- mbim_device_close (device_in_list,
- 15,
- NULL,
- (GAsyncReadyCallback) device_close_ready,
- NULL);
- self->priv->devices = g_list_remove (self->priv->devices, device_in_list);
- break;
- }
- }
- }
-}
-
-static void
connection_close (Client *client)
{
MbimProxy *self;
@@ -223,10 +186,6 @@ connection_close (Client *client)
g_debug ("Client (%d) connection closed...", g_socket_get_fd (g_socket_connection_get_socket (client->connection)));
- /* Close device */
- if (client->device)
- device_close (self, client->device);
-
/* Remove client */
self->priv->clients = g_list_remove (self->priv->clients, client);
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_N_CLIENTS]);
@@ -345,12 +304,43 @@ indication_cb (MbimDevice *device,
}
static void
+proxy_device_removed_cb (MbimDevice *device,
+ MbimProxy *self)
+{
+ if (g_list_find (self->priv->devices, device)) {
+ self->priv->devices = g_list_remove (self->priv->devices, device);
+ g_object_unref (device);
+ g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_N_DEVICES]);
+ }
+}
+
+static void
+client_device_removed_cb (MbimDevice *device,
+ Client *client)
+{
+ connection_close (client);
+}
+
+
+static void
+client_device_connect_signals (Client *client)
+{
+ client->indication_id = g_signal_connect (client->device,
+ MBIM_DEVICE_SIGNAL_INDICATE_STATUS,
+ G_CALLBACK (indication_cb),
+ client);
+ client->device_removed_id = g_signal_connect (client->device,
+ MBIM_DEVICE_SIGNAL_REMOVED,
+ G_CALLBACK (client_device_removed_cb),
+ client);
+}
+
+static void
device_open_ready (MbimDevice *device,
GAsyncResult *res,
DeviceOpenContext *ctx)
{
MbimProxy *self = ctx->proxy;
- MbimDevice *existing;
Client *client;
GError *error = NULL;
@@ -358,7 +348,6 @@ device_open_ready (MbimDevice *device,
if (!client) {
/* client must've been disconnected */
mbim_device_open_finish (device, res, NULL);
- device_close (self, device);
g_slice_free (DeviceOpenContext, ctx);
return;
}
@@ -371,35 +360,31 @@ device_open_ready (MbimDevice *device,
return;
}
- /* Store device in the proxy independently */
- existing = find_device_for_path (self, mbim_device_get_path (client->device));
- if (existing) {
- /* Race condition, we created two MbimDevices for the same port, just skip ours, no big deal */
- g_object_unref (client->device);
- client->device = g_object_ref (existing);
- } else {
- /* Keep the newly added device in the proxy */
- self->priv->devices = g_list_append (self->priv->devices, g_object_ref (client->device));
- }
-
- /* Register for device indications */
- client->indication_id = g_signal_connect (client->device,
- MBIM_DEVICE_SIGNAL_INDICATE_STATUS,
- G_CALLBACK (indication_cb),
- client);
-
g_slice_free (DeviceOpenContext, ctx);
complete_internal_proxy_open (client);
}
static void
+complete_internal_proxy_config (Client *client,
+ MbimMessage *response)
+{
+ if (!send_message (client, response, NULL))
+ connection_close (client);
+
+ mbim_message_unref (response);
+}
+
+static void
device_new_ready (GObject *source,
GAsyncResult *res,
- DeviceOpenContext *ctx)
+ DeviceNewContext *ctx)
{
GError *error = NULL;
Client *client;
MbimDevice *device;
+ MbimDevice *existing;
+ MbimProxy *self = ctx->proxy;
+ MbimMessage *response = ctx->response;
device = mbim_device_new_finish (res, &error);
client = get_client (ctx->proxy, ctx->client);
@@ -407,25 +392,43 @@ device_new_ready (GObject *source,
/* client must've been disconnected */
if (!device)
g_error_free (error);
- device_close (ctx->proxy, device);
- g_slice_free (DeviceOpenContext, ctx);
+ mbim_message_unref (response);
+ g_slice_free (DeviceNewContext, ctx);
return;
}
+
client->device = device;
if (!client->device) {
g_debug ("couldn't open MBIM device: %s", error->message);
connection_close (client);
g_error_free (error);
- g_slice_free (DeviceOpenContext, ctx);
+ mbim_message_unref (response);
+ g_slice_free (DeviceNewContext, ctx);
return;
}
- mbim_device_open (client->device,
- 30,
- NULL,
- (GAsyncReadyCallback)device_open_ready,
- ctx);
+ /* Store device in the proxy independently */
+ existing = find_device_for_path (self, mbim_device_get_path (client->device));
+ if (existing) {
+ /* Race condition, we created two MbimDevices for the same port, just skip ours, no big deal */
+ g_object_unref (client->device);
+ client->device = g_object_ref (existing);
+ } else {
+ /* Keep the newly added device in the proxy */
+ self->priv->devices = g_list_append (self->priv->devices, g_object_ref (client->device));
+ g_signal_connect (client->device,
+ MBIM_DEVICE_SIGNAL_REMOVED,
+ G_CALLBACK (proxy_device_removed_cb),
+ self);
+ g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_N_DEVICES]);
+ }
+
+ /* Register for device indications */
+ client_device_connect_signals (client);
+
+ g_slice_free (DeviceNewContext, ctx);
+ complete_internal_proxy_config (client, response);
}
static gboolean
@@ -438,40 +441,25 @@ process_internal_proxy_open (Client *client,
/* Keep it */
client->internal_proxy_open_request = mbim_message_ref (message);
- if (client->device_file_path) {
- client->device = find_device_for_path (self, client->device_file_path);
- } else {
- g_debug ("missing device file path");
+ if (!client->device) {
+ /* device should've been created in process_internal_proxy_config() */
+ g_debug ("can't find device for path, send MBIM_CID_PROXY_CONTROL_CONFIGURATION first");
complete_internal_proxy_open (client);
return FALSE;
- }
-
- /* Need to create a device ourselves */
- if (!client->device) {
- GFile *file;
-
+ } else if (!mbim_device_is_open (client->device)) {
+ /* device found but not open, open it */
ctx = g_slice_new0 (DeviceOpenContext);
ctx->proxy = self;
ctx->client = client;
- file = g_file_new_for_path (client->device_file_path);
- mbim_device_new (file,
- NULL,
- (GAsyncReadyCallback)device_new_ready,
- ctx);
- g_object_unref (file);
+ mbim_device_open (client->device,
+ 30,
+ NULL,
+ (GAsyncReadyCallback)device_open_ready,
+ ctx);
return TRUE;
}
- /* register client for notifications */
- client->indication_id = g_signal_connect (client->device,
- MBIM_DEVICE_SIGNAL_INDICATE_STATUS,
- G_CALLBACK (indication_cb),
- client);
-
- /* Keep a reference to the device in the client */
- g_object_ref (client->device);
-
complete_internal_proxy_open (client);
return FALSE;
}
@@ -480,15 +468,9 @@ static gboolean
process_internal_proxy_close (Client *client,
MbimMessage *message)
{
- MbimProxy *self = client->proxy;
- MbimDevice *device;
MbimMessage *response;
GError *error = NULL;
- device = client->device ? g_object_ref (client->device) : NULL;
- device_close (self, device);
- g_object_unref (device);
-
response = mbim_message_close_done_new (mbim_message_get_transaction_id (message), MBIM_STATUS_ERROR_NONE);
if (!send_message (client, response, &error)) {
mbim_message_unref (response);
@@ -504,10 +486,11 @@ static gboolean
process_internal_proxy_config (Client *client,
MbimMessage *message)
{
+ MbimProxy *self = client->proxy;
+ DeviceNewContext *ctx;
MbimMessage *response;
MbimStatusError error_status_code;
struct command_done_message *command_done;
- GError *error = NULL;
if (mbim_message_command_get_command_type (message) == MBIM_MESSAGE_COMMAND_TYPE_SET) {
if (client->device_file_path)
@@ -528,13 +511,35 @@ process_internal_proxy_config (Client *client,
command_done->command_id = GUINT32_TO_LE (mbim_message_command_get_cid(message));
command_done->status_code = GUINT32_TO_LE (error_status_code);
- if (!send_message (client, response, &error)) {
- mbim_message_unref (response);
- connection_close (client);
- return FALSE;
+ /* create a device to allow clients access without sending the open */
+ if (client->device_file_path) {
+ client->device = find_device_for_path (self, client->device_file_path);
+ if (!client->device) {
+ GFile *file;
+
+ ctx = g_slice_new0 (DeviceNewContext);
+ ctx->proxy = self;
+ ctx->client = client;
+ ctx->response = response;
+
+ file = g_file_new_for_path (client->device_file_path);
+ mbim_device_new (file,
+ NULL,
+ (GAsyncReadyCallback)device_new_ready,
+ ctx);
+ g_object_unref (file);
+
+ return TRUE;
+ } else {
+ /* register client for notifications */
+ client_device_connect_signals (client);
+
+ /* Keep a reference to the device in the client */
+ g_object_ref (client->device);
+ }
}
- mbim_message_unref (response);
+ complete_internal_proxy_config (client, response);
return TRUE;
}
@@ -1068,6 +1073,9 @@ get_property (GObject *object,
case PROP_N_CLIENTS:
g_value_set_uint (value, g_list_length (self->priv->clients));
break;
+ case PROP_N_DEVICES:
+ g_value_set_uint (value, g_list_length (self->priv->devices));
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@@ -1084,6 +1092,11 @@ dispose (GObject *object)
priv->clients = NULL;
}
+ if (priv->devices) {
+ g_list_free_full (priv->devices, (GDestroyNotify) g_object_unref);
+ priv->devices = NULL;
+ }
+
if (priv->socket_service) {
if (g_socket_service_is_active (priv->socket_service))
g_socket_service_stop (priv->socket_service);
@@ -1116,4 +1129,14 @@ mbim_proxy_class_init (MbimProxyClass *proxy_class)
0,
G_PARAM_READABLE);
g_object_class_install_property (object_class, PROP_N_CLIENTS, properties[PROP_N_CLIENTS]);
+
+ properties[PROP_N_DEVICES] =
+ g_param_spec_uint (MBIM_PROXY_N_DEVICES,
+ "Number of devices",
+ "Number of devices currently managed by the proxy",
+ 0,
+ G_MAXUINT,
+ 0,
+ G_PARAM_READABLE);
+ g_object_class_install_property (object_class, PROP_N_DEVICES, properties[PROP_N_DEVICES]);
}
diff --git a/src/libmbim-glib/mbim-proxy.h b/src/libmbim-glib/mbim-proxy.h
index decd662..f874cc4 100644
--- a/src/libmbim-glib/mbim-proxy.h
+++ b/src/libmbim-glib/mbim-proxy.h
@@ -41,6 +41,7 @@ typedef struct _MbimProxyPrivate MbimProxyPrivate;
#define MBIM_PROXY_SOCKET_PATH "mbim-proxy"
#define MBIM_PROXY_N_CLIENTS "mbim-proxy-n-clients"
+#define MBIM_PROXY_N_DEVICES "mbim-proxy-n-devices"
struct _MbimProxy {
GObject parent;
@@ -55,5 +56,6 @@ GType mbim_proxy_get_type (void);
MbimProxy *mbim_proxy_new (GError **error);
guint mbim_proxy_get_n_clients (MbimProxy *self);
+guint mbim_proxy_get_n_devices (MbimProxy *self);
#endif /* MBIM_PROXY_H */