diff options
author | Aleksander Morgado <aleksander@aleksander.es> | 2018-08-21 16:26:45 +0200 |
---|---|---|
committer | Dan Williams <dcbw@redhat.com> | 2018-09-12 17:17:36 +0000 |
commit | eb01914bd0cada5d2ed144d5f3f45fd17722e97c (patch) | |
tree | fc94f790e7346b54ced4ca6ed0699a120a92fd63 | |
parent | 02821232878d2a12bf248b7f2594c48076593810 (diff) | |
download | ModemManager-eb01914bd0cada5d2ed144d5f3f45fd17722e97c.tar.gz |
ublox: implement custom ICCID loading
Use AT+CCID to query the SIM ICCID, and fallback to parent's +CRSM
based method otherwise.
-rw-r--r-- | plugins/Makefile.am | 2 | ||||
-rw-r--r-- | plugins/ublox/mm-broadband-modem-ublox.c | 25 | ||||
-rw-r--r-- | plugins/ublox/mm-sim-ublox.c | 162 | ||||
-rw-r--r-- | plugins/ublox/mm-sim-ublox.h | 51 |
4 files changed, 240 insertions, 0 deletions
diff --git a/plugins/Makefile.am b/plugins/Makefile.am index 9b9de4778..fcb30dda8 100644 --- a/plugins/Makefile.am +++ b/plugins/Makefile.am @@ -998,6 +998,8 @@ libmm_plugin_ublox_la_SOURCES = \ ublox/mm-broadband-bearer-ublox.c \ ublox/mm-broadband-modem-ublox.h \ ublox/mm-broadband-modem-ublox.c \ + ublox/mm-sim-ublox.c \ + ublox/mm-sim-ublox.h \ $(NULL) libmm_plugin_ublox_la_CPPFLAGS = $(PLUGIN_COMMON_COMPILER_FLAGS) $(PLUGIN_UBLOX_COMPILER_FLAGS) libmm_plugin_ublox_la_LDFLAGS = $(PLUGIN_COMMON_LINKER_FLAGS) diff --git a/plugins/ublox/mm-broadband-modem-ublox.c b/plugins/ublox/mm-broadband-modem-ublox.c index 56441d77f..79688b2ff 100644 --- a/plugins/ublox/mm-broadband-modem-ublox.c +++ b/plugins/ublox/mm-broadband-modem-ublox.c @@ -29,6 +29,7 @@ #include "mm-broadband-bearer.h" #include "mm-broadband-modem-ublox.h" #include "mm-broadband-bearer-ublox.h" +#include "mm-sim-ublox.h" #include "mm-modem-helpers-ublox.h" #include "mm-ublox-enums-types.h" @@ -1000,6 +1001,28 @@ modem_create_bearer (MMIfaceModem *self, } /*****************************************************************************/ +/* Create SIM (Modem interface) */ + +static MMBaseSim * +modem_create_sim_finish (MMIfaceModem *self, + GAsyncResult *res, + GError **error) +{ + return mm_sim_ublox_new_finish (res, error); +} + +static void +modem_create_sim (MMIfaceModem *self, + GAsyncReadyCallback callback, + gpointer user_data) +{ + mm_sim_ublox_new (MM_BASE_MODEM (self), + NULL, /* cancellable */ + callback, + user_data); +} + +/*****************************************************************************/ /* Setup ports (Broadband modem class) */ static void @@ -1068,6 +1091,8 @@ mm_broadband_modem_ublox_init (MMBroadbandModemUblox *self) static void iface_modem_init (MMIfaceModem *iface) { + iface->create_sim = modem_create_sim; + iface->create_sim_finish = modem_create_sim_finish; iface->create_bearer = modem_create_bearer; iface->create_bearer_finish = modem_create_bearer_finish; iface->load_unlock_retries = load_unlock_retries; diff --git a/plugins/ublox/mm-sim-ublox.c b/plugins/ublox/mm-sim-ublox.c new file mode 100644 index 000000000..0e8006ccb --- /dev/null +++ b/plugins/ublox/mm-sim-ublox.c @@ -0,0 +1,162 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details: + * + * Copyright (C) 2018 Aleksander Morgado <aleksander@aleksander.es> + */ + +#include <config.h> +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <string.h> +#include <ctype.h> + +#include <ModemManager.h> +#define _LIBMM_INSIDE_MM +#include <libmm-glib.h> +#include "mm-log.h" +#include "mm-modem-helpers.h" +#include "mm-base-modem-at.h" + +#include "mm-sim-ublox.h" + +G_DEFINE_TYPE (MMSimUblox, mm_sim_ublox, MM_TYPE_BASE_SIM) + +/*****************************************************************************/ +/* SIM identifier loading */ + +static gchar * +load_sim_identifier_finish (MMBaseSim *self, + GAsyncResult *res, + GError **error) +{ + return g_task_propagate_pointer (G_TASK (res), error); +} + +static void +parent_load_sim_identifier_ready (MMSimUblox *self, + GAsyncResult *res, + GTask *task) +{ + GError *error = NULL; + gchar *simid; + + simid = MM_BASE_SIM_CLASS (mm_sim_ublox_parent_class)->load_sim_identifier_finish (MM_BASE_SIM (self), res, &error); + if (simid) + g_task_return_pointer (task, simid, g_free); + else + g_task_return_error (task, error); + g_object_unref (task); +} + +static void +ccid_ready (MMBaseModem *modem, + GAsyncResult *res, + GTask *task) +{ + MMBaseSim *self; + const gchar *response; + gchar *parsed; + + response = mm_base_modem_at_command_finish (modem, res, NULL); + if (!response) + goto error; + + response = mm_strip_tag (response, "+CCID:"); + if (!response) + goto error; + + parsed = mm_3gpp_parse_iccid (response, NULL); + if (parsed) { + g_task_return_pointer (task, parsed, g_free); + g_object_unref (task); + return; + } + +error: + /* Chain up to parent method to for devices that don't support +CCID properly */ + self = g_task_get_source_object (task); + MM_BASE_SIM_CLASS (mm_sim_ublox_parent_class)->load_sim_identifier (self, + (GAsyncReadyCallback) parent_load_sim_identifier_ready, + task); +} + +static void +load_sim_identifier (MMBaseSim *self, + GAsyncReadyCallback callback, + gpointer user_data) +{ + MMBaseModem *modem = NULL; + + g_object_get (self, + MM_BASE_SIM_MODEM, &modem, + NULL); + mm_base_modem_at_command ( + modem, + "+CCID", + 5, + FALSE, + (GAsyncReadyCallback)ccid_ready, + g_task_new (self, NULL, callback, user_data)); + g_object_unref (modem); +} + +/*****************************************************************************/ + +MMBaseSim * +mm_sim_ublox_new_finish (GAsyncResult *res, + GError **error) +{ + GObject *source; + GObject *sim; + + source = g_async_result_get_source_object (res); + sim = g_async_initable_new_finish (G_ASYNC_INITABLE (source), res, error); + g_object_unref (source); + + if (!sim) + return NULL; + + /* Only export valid SIMs */ + mm_base_sim_export (MM_BASE_SIM (sim)); + + return MM_BASE_SIM (sim); +} + +void +mm_sim_ublox_new (MMBaseModem *modem, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) +{ + g_async_initable_new_async (MM_TYPE_SIM_UBLOX, + G_PRIORITY_DEFAULT, + cancellable, + callback, + user_data, + MM_BASE_SIM_MODEM, modem, + NULL); +} + +static void +mm_sim_ublox_init (MMSimUblox *self) +{ +} + +static void +mm_sim_ublox_class_init (MMSimUbloxClass *klass) +{ + MMBaseSimClass *base_sim_class = MM_BASE_SIM_CLASS (klass); + + base_sim_class->load_sim_identifier = load_sim_identifier; + base_sim_class->load_sim_identifier_finish = load_sim_identifier_finish; +} diff --git a/plugins/ublox/mm-sim-ublox.h b/plugins/ublox/mm-sim-ublox.h new file mode 100644 index 000000000..31e2c98bc --- /dev/null +++ b/plugins/ublox/mm-sim-ublox.h @@ -0,0 +1,51 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details: + * + * Copyright (C) 2018 Aleksander Morgado <aleksander@aleksander.es> + */ + +#ifndef MM_SIM_UBLOX_H +#define MM_SIM_UBLOX_H + +#include <glib.h> +#include <glib-object.h> + +#include "mm-base-sim.h" + +#define MM_TYPE_SIM_UBLOX (mm_sim_ublox_get_type ()) +#define MM_SIM_UBLOX(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MM_TYPE_SIM_UBLOX, MMSimUblox)) +#define MM_SIM_UBLOX_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), MM_TYPE_SIM_UBLOX, MMSimUbloxClass)) +#define MM_IS_SIM_UBLOX(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MM_TYPE_SIM_UBLOX)) +#define MM_IS_SIM_UBLOX_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), MM_TYPE_SIM_UBLOX)) +#define MM_SIM_UBLOX_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), MM_TYPE_SIM_UBLOX, MMSimUbloxClass)) + +typedef struct _MMSimUblox MMSimUblox; +typedef struct _MMSimUbloxClass MMSimUbloxClass; + +struct _MMSimUblox { + MMBaseSim parent; +}; + +struct _MMSimUbloxClass { + MMBaseSimClass parent; +}; + +GType mm_sim_ublox_get_type (void); + +void mm_sim_ublox_new (MMBaseModem *modem, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data); +MMBaseSim *mm_sim_ublox_new_finish (GAsyncResult *res, + GError **error); + +#endif /* MM_SIM_UBLOX_H */ |