diff options
author | Aleksander Morgado <aleksander@aleksander.es> | 2014-02-13 11:55:59 +0100 |
---|---|---|
committer | Aleksander Morgado <aleksander@aleksander.es> | 2014-02-13 11:56:09 +0100 |
commit | c9e2b46b2124afcf710736900ba1848711126a83 (patch) | |
tree | bc629534ac8884d2b56e15b4d36bb61638bb4e26 | |
parent | e60485a4aaede4d5a85b941574bd3e12143cb501 (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.c | 119 |
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; } |