aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAleksander Morgado <aleksander@aleksander.es>2014-02-13 11:55:59 +0100
committerAleksander Morgado <aleksander@aleksander.es>2014-02-13 11:56:09 +0100
commitc9e2b46b2124afcf710736900ba1848711126a83 (patch)
treebc629534ac8884d2b56e15b4d36bb61638bb4e26
parente60485a4aaede4d5a85b941574bd3e12143cb501 (diff)
cinterion: try to gather port type for devices with multiple tty ports
The new PHS8 or PXS8 devices may expose multiple tty ports, but only one is supposed to be used for PPP. So, query which port that is and flag it before grabbing it in the modem.
-rw-r--r--plugins/cinterion/mm-plugin-cinterion.c119
1 files changed, 119 insertions, 0 deletions
diff --git a/plugins/cinterion/mm-plugin-cinterion.c b/plugins/cinterion/mm-plugin-cinterion.c
index 45f88d52..8baa317f 100644
--- a/plugins/cinterion/mm-plugin-cinterion.c
+++ b/plugins/cinterion/mm-plugin-cinterion.c
@@ -40,6 +40,95 @@ G_DEFINE_TYPE (MMPluginCinterion, mm_plugin_cinterion, MM_TYPE_PLUGIN)
int mm_plugin_major_version = MM_PLUGIN_MAJOR_VERSION;
int mm_plugin_minor_version = MM_PLUGIN_MINOR_VERSION;
+/*****************************************************************************/
+/* Custom init */
+
+#define TAG_CINTERION_APP_PORT "cinterion-app-port"
+#define TAG_CINTERION_MODEM_PORT "cinterion-modem-port"
+
+typedef struct {
+ MMPortProbe *probe;
+ MMAtSerialPort *port;
+ GCancellable *cancellable;
+ GSimpleAsyncResult *result;
+} CinterionCustomInitContext;
+
+static void
+cinterion_custom_init_context_complete_and_free (CinterionCustomInitContext *ctx)
+{
+ g_simple_async_result_complete (ctx->result);
+
+ if (ctx->cancellable)
+ g_object_unref (ctx->cancellable);
+ g_object_unref (ctx->port);
+ g_object_unref (ctx->probe);
+ g_object_unref (ctx->result);
+ g_slice_free (CinterionCustomInitContext, ctx);
+}
+
+static gboolean
+cinterion_custom_init_finish (MMPortProbe *probe,
+ GAsyncResult *result,
+ GError **error)
+{
+ return !g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (result), error);
+}
+
+static void
+sqport_ready (MMAtSerialPort *port,
+ GString *response,
+ GError *error,
+ CinterionCustomInitContext *ctx)
+{
+ /* Ignore errors, just avoid tagging */
+ if (error) {
+ g_simple_async_result_set_op_res_gboolean (ctx->result, TRUE);
+ cinterion_custom_init_context_complete_and_free (ctx);
+ return;
+ }
+
+ /* A valid reply to AT^SQPORT tells us this is an AT port already */
+ mm_port_probe_set_result_at (ctx->probe, TRUE);
+
+ if (strstr (response->str, "Application"))
+ g_object_set_data (G_OBJECT (ctx->probe), TAG_CINTERION_APP_PORT, GUINT_TO_POINTER (TRUE));
+ else if (strstr (response->str, "Modem"))
+ g_object_set_data (G_OBJECT (ctx->probe), TAG_CINTERION_MODEM_PORT, GUINT_TO_POINTER (TRUE));
+
+ g_simple_async_result_set_op_res_gboolean (ctx->result, TRUE);
+ cinterion_custom_init_context_complete_and_free (ctx);
+}
+
+static void
+cinterion_custom_init (MMPortProbe *probe,
+ MMAtSerialPort *port,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ CinterionCustomInitContext *ctx;
+
+ ctx = g_slice_new (CinterionCustomInitContext);
+ ctx->result = g_simple_async_result_new (G_OBJECT (probe),
+ callback,
+ user_data,
+ cinterion_custom_init);
+ ctx->probe = g_object_ref (probe);
+ ctx->port = g_object_ref (port);
+ ctx->cancellable = cancellable ? g_object_ref (cancellable) : NULL;
+
+ mm_at_serial_port_queue_command (
+ ctx->port,
+ "AT^SQPORT?",
+ 3,
+ FALSE, /* raw */
+ ctx->cancellable,
+ (MMAtSerialResponseFn)sqport_ready,
+ ctx);
+}
+
+/*****************************************************************************/
+
static MMBaseModem *
create_modem (MMPlugin *self,
const gchar *sysfs_path,
@@ -67,6 +156,30 @@ create_modem (MMPlugin *self,
product));
}
+static gboolean
+grab_port (MMPlugin *self,
+ MMBaseModem *modem,
+ MMPortProbe *probe,
+ GError **error)
+{
+ MMAtPortFlag pflags = MM_AT_PORT_FLAG_NONE;
+ MMPortType ptype;
+
+ ptype = mm_port_probe_get_port_type (probe);
+
+ if (g_object_get_data (G_OBJECT (probe), TAG_CINTERION_APP_PORT))
+ pflags = MM_AT_PORT_FLAG_PRIMARY;
+ else if (g_object_get_data (G_OBJECT (probe), TAG_CINTERION_MODEM_PORT))
+ pflags = MM_AT_PORT_FLAG_PPP;
+
+ return mm_base_modem_grab_port (modem,
+ mm_port_probe_get_port_subsys (probe),
+ mm_port_probe_get_port_name (probe),
+ ptype,
+ pflags,
+ error);
+}
+
/*****************************************************************************/
G_MODULE_EXPORT MMPlugin *
@@ -75,6 +188,10 @@ mm_plugin_create (void)
static const gchar *subsystems[] = { "tty", "net", "usb", NULL };
static const gchar *vendor_strings[] = { "cinterion", "siemens", NULL };
static const guint16 vendor_ids[] = { 0x1e2d, 0x0681, 0 };
+ static const MMAsyncMethod custom_init = {
+ .async = G_CALLBACK (cinterion_custom_init),
+ .finish = G_CALLBACK (cinterion_custom_init_finish),
+ };
return MM_PLUGIN (
g_object_new (MM_TYPE_PLUGIN_CINTERION,
@@ -84,6 +201,7 @@ mm_plugin_create (void)
MM_PLUGIN_ALLOWED_VENDOR_IDS, vendor_ids,
MM_PLUGIN_ALLOWED_AT, TRUE,
MM_PLUGIN_ALLOWED_QMI, TRUE,
+ MM_PLUGIN_CUSTOM_INIT, &custom_init,
NULL));
}
@@ -98,4 +216,5 @@ mm_plugin_cinterion_class_init (MMPluginCinterionClass *klass)
MMPluginClass *plugin_class = MM_PLUGIN_CLASS (klass);
plugin_class->create_modem = create_modem;
+ plugin_class->grab_port = grab_port;
}