From c9e2b46b2124afcf710736900ba1848711126a83 Mon Sep 17 00:00:00 2001 From: Aleksander Morgado Date: Thu, 13 Feb 2014 11:55:59 +0100 Subject: [PATCH] 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. --- plugins/cinterion/mm-plugin-cinterion.c | 119 ++++++++++++++++++++++++ 1 file changed, 119 insertions(+) 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; }