build: move plugins directory to src/plugins
We are going to allow including the plugin sources built within the ModemManager daemon binary; moving the sources within the daemon sources directory makes it easier.
This commit is contained in:
committed by
Aleksander Morgado
parent
072d7ac906
commit
e14b904cbd
@@ -0,0 +1,78 @@
|
||||
# do not edit this file, it will be overwritten on update
|
||||
ACTION!="add|change|move|bind", GOTO="mm_ublox_port_types_end"
|
||||
SUBSYSTEMS=="usb", ATTRS{idVendor}=="1546", GOTO="mm_ublox_port_types"
|
||||
GOTO="mm_ublox_port_types_end"
|
||||
|
||||
LABEL="mm_ublox_port_types"
|
||||
|
||||
SUBSYSTEMS=="usb", ATTRS{bInterfaceNumber}=="?*", ENV{.MM_USBIFNUM}="$attr{bInterfaceNumber}"
|
||||
|
||||
# Fully ignore u-blox GPS devices
|
||||
ATTRS{idVendor}=="1546", ATTRS{idProduct}=="01a5", ENV{ID_MM_DEVICE_IGNORE}="1"
|
||||
ATTRS{idVendor}=="1546", ATTRS{idProduct}=="01a6", ENV{ID_MM_DEVICE_IGNORE}="1"
|
||||
ATTRS{idVendor}=="1546", ATTRS{idProduct}=="01a7", ENV{ID_MM_DEVICE_IGNORE}="1"
|
||||
ATTRS{idVendor}=="1546", ATTRS{idProduct}=="01a8", ENV{ID_MM_DEVICE_IGNORE}="1"
|
||||
ATTRS{idVendor}=="1546", ATTRS{idProduct}=="01a9", ENV{ID_MM_DEVICE_IGNORE}="1"
|
||||
|
||||
# Toby-L4 port types
|
||||
# ttyACM0 (if #2): secondary (ignore)
|
||||
# ttyACM1 (if #4): debug port (ignore)
|
||||
# ttyACM2 (if #6): primary
|
||||
# Wait up to 20s for the +READY URC
|
||||
# ttyACM3 (if #8): AT port for FOTA (ignore)
|
||||
ATTRS{idVendor}=="1546", ATTRS{idProduct}=="1010", ENV{.MM_USBIFNUM}=="02", ENV{ID_MM_PORT_IGNORE}="1"
|
||||
ATTRS{idVendor}=="1546", ATTRS{idProduct}=="1010", ENV{.MM_USBIFNUM}=="04", ENV{ID_MM_PORT_IGNORE}="1"
|
||||
ATTRS{idVendor}=="1546", ATTRS{idProduct}=="1010", ENV{.MM_USBIFNUM}=="06", ENV{ID_MM_UBLOX_PORT_READY_DELAY}="20"
|
||||
ATTRS{idVendor}=="1546", ATTRS{idProduct}=="1010", ENV{.MM_USBIFNUM}=="08", ENV{ID_MM_PORT_IGNORE}="1"
|
||||
|
||||
# TOBY-L200
|
||||
# Wait up to 20s before probing AT ports
|
||||
ATTRS{idVendor}=="1546", ATTRS{idProduct}=="1141", ENV{ID_MM_UBLOX_PORT_READY_DELAY}="20"
|
||||
ATTRS{idVendor}=="1546", ATTRS{idProduct}=="1143", ENV{ID_MM_UBLOX_PORT_READY_DELAY}="20"
|
||||
ATTRS{idVendor}=="1546", ATTRS{idProduct}=="1146", ENV{ID_MM_UBLOX_PORT_READY_DELAY}="20"
|
||||
|
||||
# TOBY-R2 port types
|
||||
# ttyACM0 (if #0): primary
|
||||
# ttyACM1 (if #2): secondary
|
||||
# ttyACM2 (if #4): tertiary
|
||||
# ttyACM3 (if #6): GNSS Tunneling (ignore)
|
||||
# ttyACM4 (if #8): SIM Access Profile (ignore)
|
||||
# ttyACM5 (if #10): Primary Log for diagnostics (ignore)
|
||||
ATTRS{idVendor}=="1546", ATTRS{idProduct}=="1107", ENV{.MM_USBIFNUM}=="06", ENV{ID_MM_PORT_IGNORE}="1"
|
||||
ATTRS{idVendor}=="1546", ATTRS{idProduct}=="1107", ENV{.MM_USBIFNUM}=="08", ENV{ID_MM_PORT_IGNORE}="1"
|
||||
ATTRS{idVendor}=="1546", ATTRS{idProduct}=="1107", ENV{.MM_USBIFNUM}=="0a", ENV{ID_MM_PORT_IGNORE}="1"
|
||||
|
||||
# LARA-R2 port types
|
||||
# ttyACM0 (if #0): primary
|
||||
# ttyACM1 (if #2): secondary
|
||||
# ttyACM2 (if #4): tertiary
|
||||
# ttyACM3 (if #6): GNSS Tunneling (ignore)
|
||||
# ttyACM4 (if #8): SIM Access Profile (ignore)
|
||||
# ttyACM5 (if #10): Primary Log for diagnostics (ignore)
|
||||
ATTRS{idVendor}=="1546", ATTRS{idProduct}=="110a", ENV{.MM_USBIFNUM}=="06", ENV{ID_MM_PORT_IGNORE}="1"
|
||||
ATTRS{idVendor}=="1546", ATTRS{idProduct}=="110a", ENV{.MM_USBIFNUM}=="08", ENV{ID_MM_PORT_IGNORE}="1"
|
||||
ATTRS{idVendor}=="1546", ATTRS{idProduct}=="110a", ENV{.MM_USBIFNUM}=="0a", ENV{ID_MM_PORT_IGNORE}="1"
|
||||
|
||||
# LISA-U2 / SARA-U2 port types
|
||||
# ttyACM0 (if #0): primary
|
||||
# ttyACM1 (if #2): secondary
|
||||
# ttyACM2 (if #4): tertiary
|
||||
# ttyACM3 (if #6): GNSS Tunneling (ignore)
|
||||
# ttyACM4 (if #8): Primary Log for diagnostics (ignore)
|
||||
# ttyACM5 (if #10): Secondary Log for diagnostics (ignore)
|
||||
# ttyACM6 (if #12): SAP (SIM Access Profile) (ignore)
|
||||
ATTRS{idVendor}=="1546", ATTRS{idProduct}=="1102", ENV{.MM_USBIFNUM}=="06", ENV{ID_MM_PORT_IGNORE}="1"
|
||||
ATTRS{idVendor}=="1546", ATTRS{idProduct}=="1102", ENV{.MM_USBIFNUM}=="08", ENV{ID_MM_PORT_IGNORE}="1"
|
||||
ATTRS{idVendor}=="1546", ATTRS{idProduct}=="1102", ENV{.MM_USBIFNUM}=="0a", ENV{ID_MM_PORT_IGNORE}="1"
|
||||
ATTRS{idVendor}=="1546", ATTRS{idProduct}=="1102", ENV{.MM_USBIFNUM}=="0c", ENV{ID_MM_PORT_IGNORE}="1"
|
||||
|
||||
# LISA-U2 / SARA-U2 (alternative configuration) port types
|
||||
# ttyACM0 (if #0): primary
|
||||
# ttyACM1 (if #2): GNSS Tunneling (ignore)
|
||||
# ttyACM2 (if #4): Primary Log for diagnostics (ignore)
|
||||
# ttyACM3 (if #6): SAP (SIM Access Profile) (ignore)
|
||||
ATTRS{idVendor}=="1546", ATTRS{idProduct}=="1104", ENV{.MM_USBIFNUM}=="02", ENV{ID_MM_PORT_IGNORE}="1"
|
||||
ATTRS{idVendor}=="1546", ATTRS{idProduct}=="1104", ENV{.MM_USBIFNUM}=="04", ENV{ID_MM_PORT_IGNORE}="1"
|
||||
ATTRS{idVendor}=="1546", ATTRS{idProduct}=="1104", ENV{.MM_USBIFNUM}=="06", ENV{ID_MM_PORT_IGNORE}="1"
|
||||
|
||||
LABEL="mm_ublox_port_types_end"
|
||||
@@ -0,0 +1,162 @@
|
||||
|
||||
The 'ublox' plugin is originally targeted for the u-blox TOBY-L2 series,
|
||||
although it may be used with other kind of devices likely without many issues.
|
||||
|
||||
=====================================
|
||||
USB profiles and networking modes
|
||||
=====================================
|
||||
|
||||
The TOBY-L2 devices may work in multiple different USB profiles:
|
||||
|
||||
* AT+UUSBCONF=0: fairly back-compatible profile, where only cdc-acm TTYs are
|
||||
exposed. ModemManager will default to PPP for the connection setup when in
|
||||
this profile.
|
||||
|
||||
* AT+UUSBCONF=2: ECM profile, where multiple cdc-acm TTYs are exposed along
|
||||
with a ECM network interface.
|
||||
|
||||
* AT+UUSBCONF=3: RNDIS profile, where one cdc-acm TTY and a RNDIS network
|
||||
interface are exposed. This is the default factory-programmed value.
|
||||
|
||||
When a profile with a network interface (ECM or RNDIS) is in use, the device may
|
||||
work in multiple networking modes:
|
||||
|
||||
* AT+UBMCONF=1: Router mode, with a built-in DHCP server running behind the
|
||||
network interface. The network interface will be assigned an IP address from
|
||||
a subnet managed by the device itself. This is the default factory-programmed
|
||||
value. E.g.:
|
||||
|
||||
$ ip addr
|
||||
9: usb0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UNKNOWN group default qlen 1000
|
||||
link/ether 02:07:01:15:00:0b brd ff:ff:ff:ff:ff:ff
|
||||
inet 192.168.1.100/24 brd 192.168.1.255 scope global dynamic usb0
|
||||
valid_lft 43009sec preferred_lft 43009sec
|
||||
|
||||
$ ip route
|
||||
default via 192.168.1.1 dev usb0 proto static metric 700
|
||||
192.168.1.0/24 dev usb0 proto kernel scope link src 192.168.1.100 metric 700
|
||||
|
||||
* AT+UBMCONF=2: Bridge mode, where static IP addressing and routing must be
|
||||
performed once connected. The network interface will be assigned the same IP
|
||||
address provided by the network operator. The plugin uses 'AT+UIPADDR=N' the
|
||||
default gateway IP settings and 'AT++CGCONTRDP=N' to retrieve the interface
|
||||
IP settings and DNS setup.
|
||||
|
||||
$ ip addr
|
||||
11: usb0: <BROADCAST,MULTICAST,NOARP,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UNKNOWN group default qlen 1000
|
||||
link/ether 02:07:01:15:00:0b brd ff:ff:ff:ff:ff:ff
|
||||
inet 47.59.109.26/32 brd 47.59.109.26 scope global usb0
|
||||
valid_lft forever preferred_lft forever
|
||||
|
||||
$ ip route
|
||||
default via 47.59.109.229 dev usb0 proto static metric 700
|
||||
47.59.109.26 dev usb0 proto kernel scope link src 47.59.109.26 metric 700
|
||||
47.59.109.229 dev usb0 proto static scope link metric 700
|
||||
|
||||
The 'ublox' plugin in ModemManager works with any of the previous combinations
|
||||
seamlessly. It is assumed that the device doesn't change either USB profile or
|
||||
networking mode once it has been detected and processed by ModemManager.
|
||||
|
||||
NOTE: If manually selecting different USB profiles or networking modes, remember
|
||||
to reset the module before assuming the new settings have been applied. E.g.,
|
||||
using plain mmcli commands:
|
||||
$ sudo mmcli -m 0 --command="AT+UUSBCONF=3"
|
||||
$ sudo mmcli -m 0 --reset
|
||||
|
||||
=================================
|
||||
Connection setup
|
||||
=================================
|
||||
|
||||
The plugin allows to connect to specific APNs in the usual way (i.e. by creating
|
||||
a PDP context for the specific APN), and then activating the PDP context with
|
||||
'AT+CGACT=[CID]'.
|
||||
|
||||
Authentication settings of the APN (user, password, authentication type) are
|
||||
also supported via the 'AT+UAUTHREQ' command.
|
||||
|
||||
The plugin doesn't currently support reporting as auto-connected the default LTE
|
||||
bearer.
|
||||
|
||||
========================================
|
||||
Connection monitoring and statistics
|
||||
========================================
|
||||
|
||||
The status of the connection of the specific PDP context is monitored
|
||||
periodically using 'AT+CGACT?', in order to detect network-originated
|
||||
disconnections. This implementation is given in the Generic broadband bearer
|
||||
implementation, and is not ublox-specific.
|
||||
|
||||
If the device supports it, connection TX/RX statistics will also be periodically
|
||||
loaded using the AT+UGCNTRD command. Note, though, that the TOBY-L2 doesn't seem
|
||||
to support this information via control commands.
|
||||
|
||||
===========================================
|
||||
Supported and current mode combinations
|
||||
===========================================
|
||||
|
||||
The full list of supported mode combinations is loaded using 'AT+URAT=?', and
|
||||
then filtered by device product name to remove technologies not supported in
|
||||
several devices. E.g. the standard TOBY-L2 list of supported mode combinations
|
||||
will include all 2G, 3G and 4G, but if the device is a L201, 2G support will be
|
||||
removed from the list.
|
||||
|
||||
The current mode combination in use is loaded using 'AT+URAT?', and the setting
|
||||
may be changed using the 'AT+URAT=X' request.
|
||||
|
||||
In order to be able to update this setting, the device will be put in low-power
|
||||
mode ('AT+CFUN=4'), then the setting update will be run, and finally the device
|
||||
will recover the previous functionality mode it was in (e.g. 'AT+CFUN=1' if it
|
||||
was in full functionality mode).
|
||||
|
||||
===============================
|
||||
Supported and current bands
|
||||
===============================
|
||||
|
||||
The full list of supported bands is hardcoded based on the supported modes of the
|
||||
device. There is no runtime loading of which are the supported bands because the
|
||||
'AT+UBANDSEL=?' command gives different results depending on the current access
|
||||
technology (i.e. there is no single full list of supported bands reported).
|
||||
|
||||
The current list of bands is loaded via the 'AT+UBANDSEL?' command, and the
|
||||
setting may be changed using the 'AT+UBANDSEL=X' request.
|
||||
|
||||
In order to be able to update this setting, the device will be put in low-power
|
||||
mode ('AT+CFUN=4'), then the setting update will be run, and finally the device
|
||||
will recover the previous functionality mode it was in (e.g. 'AT+CFUN=1' if it
|
||||
was in full functionality mode).
|
||||
|
||||
======================
|
||||
Functionality mode
|
||||
======================
|
||||
|
||||
The plugin implements a custom 'AT+CFUN?' response parser because it provides
|
||||
multiple modes that may be treated as 'low-power' by ModemManager (e.g. mode
|
||||
'0' is minimum functionality, mode '4' is airplane mode and mode '19' is
|
||||
minimum functionality with SIM deactivated).
|
||||
|
||||
The plugin implements power-on ('AT+CFUN=1'), power-down ('AT+CFUN=4'), reset
|
||||
('AT+CFUN=16') and power-off ('AT+CPWROFF'). As usual, a reset will trigger a
|
||||
power cycle of the device, and the power-off will render the modem unusable
|
||||
until it's power cycled externally.
|
||||
|
||||
====================================
|
||||
Network registration and quality
|
||||
====================================
|
||||
|
||||
The LTE specific 'AT+CEREG' registration checks will be enabled by default if
|
||||
the module supports LTE. Additionally, a custom 'CREG/CGREG/CEREG' state number
|
||||
parser is provided to support u-blox specific reported states (e.g. state '6'
|
||||
to indicate 'sms only registration' on the '+CREG' indications for the CS
|
||||
network when on LTE).
|
||||
|
||||
The plugin implements the extended Signal interface, providing RSSI, RSCP, Ec/Io
|
||||
and RSRQ measurements obtained with the 'AT+CESQ' command.
|
||||
|
||||
==================
|
||||
PIN management
|
||||
==================
|
||||
|
||||
A custom method to load the PIN/PUK remaining attempts is implemented based on
|
||||
the 'AT+UPINCNT' command.
|
||||
|
||||
Have fun!
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,63 @@
|
||||
/* -*- 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) 2016 Aleksander Morgado <aleksander@aleksander.es>
|
||||
*/
|
||||
|
||||
#ifndef MM_BROADBAND_BEARER_UBLOX_H
|
||||
#define MM_BROADBAND_BEARER_UBLOX_H
|
||||
|
||||
#include <glib.h>
|
||||
#include <glib-object.h>
|
||||
|
||||
#define _LIBMM_INSIDE_MM
|
||||
#include <libmm-glib.h>
|
||||
|
||||
#include "mm-broadband-bearer.h"
|
||||
#include "mm-modem-helpers-ublox.h"
|
||||
|
||||
#define MM_TYPE_BROADBAND_BEARER_UBLOX (mm_broadband_bearer_ublox_get_type ())
|
||||
#define MM_BROADBAND_BEARER_UBLOX(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MM_TYPE_BROADBAND_BEARER_UBLOX, MMBroadbandBearerUblox))
|
||||
#define MM_BROADBAND_BEARER_UBLOX_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), MM_TYPE_BROADBAND_BEARER_UBLOX, MMBroadbandBearerUbloxClass))
|
||||
#define MM_IS_BROADBAND_BEARER_UBLOX(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MM_TYPE_BROADBAND_BEARER_UBLOX))
|
||||
#define MM_IS_BROADBAND_BEARER_UBLOX_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), MM_TYPE_BROADBAND_BEARER_UBLOX))
|
||||
#define MM_BROADBAND_BEARER_UBLOX_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), MM_TYPE_BROADBAND_BEARER_UBLOX, MMBroadbandBearerUbloxClass))
|
||||
|
||||
#define MM_BROADBAND_BEARER_UBLOX_USB_PROFILE "broadband-bearer-ublox-usb-profile"
|
||||
#define MM_BROADBAND_BEARER_UBLOX_NETWORKING_MODE "broadband-bearer-ublox-networking-mode"
|
||||
|
||||
typedef struct _MMBroadbandBearerUblox MMBroadbandBearerUblox;
|
||||
typedef struct _MMBroadbandBearerUbloxClass MMBroadbandBearerUbloxClass;
|
||||
typedef struct _MMBroadbandBearerUbloxPrivate MMBroadbandBearerUbloxPrivate;
|
||||
|
||||
struct _MMBroadbandBearerUblox {
|
||||
MMBroadbandBearer parent;
|
||||
MMBroadbandBearerUbloxPrivate *priv;
|
||||
};
|
||||
|
||||
struct _MMBroadbandBearerUbloxClass {
|
||||
MMBroadbandBearerClass parent;
|
||||
};
|
||||
|
||||
GType mm_broadband_bearer_ublox_get_type (void);
|
||||
|
||||
void mm_broadband_bearer_ublox_new (MMBroadbandModem *modem,
|
||||
MMUbloxUsbProfile profile,
|
||||
MMUbloxNetworkingMode mode,
|
||||
MMBearerProperties *config,
|
||||
GCancellable *cancellable,
|
||||
GAsyncReadyCallback callback,
|
||||
gpointer user_data);
|
||||
MMBaseBearer *mm_broadband_bearer_ublox_new_finish (GAsyncResult *res,
|
||||
GError **error);
|
||||
|
||||
#endif /* MM_BROADBAND_BEARER_UBLOX_H */
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,49 @@
|
||||
/* -*- 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) 2016 Aleksander Morgado <aleksander@aleksander.es>
|
||||
*/
|
||||
|
||||
#ifndef MM_BROADBAND_MODEM_UBLOX_H
|
||||
#define MM_BROADBAND_MODEM_UBLOX_H
|
||||
|
||||
#include "mm-broadband-modem.h"
|
||||
|
||||
#define MM_TYPE_BROADBAND_MODEM_UBLOX (mm_broadband_modem_ublox_get_type ())
|
||||
#define MM_BROADBAND_MODEM_UBLOX(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MM_TYPE_BROADBAND_MODEM_UBLOX, MMBroadbandModemUblox))
|
||||
#define MM_BROADBAND_MODEM_UBLOX_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), MM_TYPE_BROADBAND_MODEM_UBLOX, MMBroadbandModemUbloxClass))
|
||||
#define MM_IS_BROADBAND_MODEM_UBLOX(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MM_TYPE_BROADBAND_MODEM_UBLOX))
|
||||
#define MM_IS_BROADBAND_MODEM_UBLOX_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), MM_TYPE_BROADBAND_MODEM_UBLOX))
|
||||
#define MM_BROADBAND_MODEM_UBLOX_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), MM_TYPE_BROADBAND_MODEM_UBLOX, MMBroadbandModemUbloxClass))
|
||||
|
||||
typedef struct _MMBroadbandModemUblox MMBroadbandModemUblox;
|
||||
typedef struct _MMBroadbandModemUbloxClass MMBroadbandModemUbloxClass;
|
||||
typedef struct _MMBroadbandModemUbloxPrivate MMBroadbandModemUbloxPrivate;
|
||||
|
||||
struct _MMBroadbandModemUblox {
|
||||
MMBroadbandModem parent;
|
||||
MMBroadbandModemUbloxPrivate *priv;
|
||||
};
|
||||
|
||||
struct _MMBroadbandModemUbloxClass{
|
||||
MMBroadbandModemClass parent;
|
||||
};
|
||||
|
||||
GType mm_broadband_modem_ublox_get_type (void);
|
||||
|
||||
MMBroadbandModemUblox *mm_broadband_modem_ublox_new (const gchar *device,
|
||||
const gchar **drivers,
|
||||
const gchar *plugin,
|
||||
guint16 vendor_id,
|
||||
guint16 product_id);
|
||||
|
||||
#endif /* MM_BROADBAND_MODEM_UBLOX_H */
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,213 @@
|
||||
/* -*- 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) 2016 Aleksander Morgado <aleksander@aleksander.es>
|
||||
*/
|
||||
|
||||
#ifndef MM_MODEM_HELPERS_UBLOX_H
|
||||
#define MM_MODEM_HELPERS_UBLOX_H
|
||||
|
||||
#include <glib.h>
|
||||
#include <ModemManager.h>
|
||||
|
||||
/*****************************************************************************/
|
||||
/* AT Commands Support */
|
||||
|
||||
typedef enum {
|
||||
FEATURE_SUPPORT_UNKNOWN,
|
||||
FEATURE_SUPPORTED,
|
||||
FEATURE_UNSUPPORTED,
|
||||
} FeatureSupport;
|
||||
|
||||
typedef enum {
|
||||
SETTINGS_UPDATE_METHOD_UNKNOWN,
|
||||
SETTINGS_UPDATE_METHOD_CFUN,
|
||||
SETTINGS_UPDATE_METHOD_COPS,
|
||||
} SettingsUpdateMethod;
|
||||
|
||||
typedef struct UbloxSupportConfig {
|
||||
gboolean loaded;
|
||||
SettingsUpdateMethod method;
|
||||
FeatureSupport uact;
|
||||
FeatureSupport ubandsel;
|
||||
} UbloxSupportConfig;
|
||||
|
||||
/*****************************************************************************/
|
||||
/* +UPINCNT response parser */
|
||||
|
||||
gboolean mm_ublox_parse_upincnt_response (const gchar *response,
|
||||
guint *out_pin_attempts,
|
||||
guint *out_pin2_attempts,
|
||||
guint *out_puk_attempts,
|
||||
guint *out_puk2_attempts,
|
||||
GError **error);
|
||||
|
||||
/*****************************************************************************/
|
||||
/* UUSBCONF? response parser */
|
||||
|
||||
typedef enum { /*< underscore_name=mm_ublox_usb_profile >*/
|
||||
MM_UBLOX_USB_PROFILE_UNKNOWN,
|
||||
MM_UBLOX_USB_PROFILE_RNDIS,
|
||||
MM_UBLOX_USB_PROFILE_ECM,
|
||||
MM_UBLOX_USB_PROFILE_BACK_COMPATIBLE,
|
||||
} MMUbloxUsbProfile;
|
||||
|
||||
gboolean mm_ublox_parse_uusbconf_response (const gchar *response,
|
||||
MMUbloxUsbProfile *out_profile,
|
||||
GError **error);
|
||||
|
||||
/*****************************************************************************/
|
||||
/* UBMCONF? response parser */
|
||||
|
||||
typedef enum { /*< underscore_name=mm_ublox_networking_mode >*/
|
||||
MM_UBLOX_NETWORKING_MODE_UNKNOWN,
|
||||
MM_UBLOX_NETWORKING_MODE_ROUTER,
|
||||
MM_UBLOX_NETWORKING_MODE_BRIDGE,
|
||||
} MMUbloxNetworkingMode;
|
||||
|
||||
gboolean mm_ublox_parse_ubmconf_response (const gchar *response,
|
||||
MMUbloxNetworkingMode *out_mode,
|
||||
GError **error);
|
||||
|
||||
/*****************************************************************************/
|
||||
/* UIPADDR=N response parser */
|
||||
|
||||
gboolean mm_ublox_parse_uipaddr_response (const gchar *response,
|
||||
guint *out_cid,
|
||||
gchar **out_if_name,
|
||||
gchar **out_ipv4_address,
|
||||
gchar **out_ipv4_subnet,
|
||||
gchar **out_ipv6_global_address,
|
||||
gchar **out_ipv6_link_local_address,
|
||||
GError **error);
|
||||
|
||||
/*****************************************************************************/
|
||||
/* CFUN? response parser */
|
||||
|
||||
gboolean mm_ublox_parse_cfun_response (const gchar *response,
|
||||
MMModemPowerState *out_state,
|
||||
GError **error);
|
||||
|
||||
/*****************************************************************************/
|
||||
/* URAT=? response parser */
|
||||
|
||||
GArray *mm_ublox_parse_urat_test_response (const gchar *response,
|
||||
gpointer log_object,
|
||||
GError **error);
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Model-based config support loading */
|
||||
|
||||
gboolean mm_ublox_get_support_config (const gchar *model,
|
||||
UbloxSupportConfig *config,
|
||||
GError **error);
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Model-based supported modes filtering */
|
||||
|
||||
GArray *mm_ublox_filter_supported_modes (const gchar *model,
|
||||
GArray *combinations,
|
||||
gpointer logger,
|
||||
GError **error);
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Model-based supported bands loading */
|
||||
|
||||
GArray *mm_ublox_get_supported_bands (const gchar *model,
|
||||
gpointer log_object,
|
||||
GError **error);
|
||||
|
||||
/*****************************************************************************/
|
||||
/* UBANDSEL? response parser */
|
||||
|
||||
GArray *mm_ublox_parse_ubandsel_response (const gchar *response,
|
||||
const gchar *model,
|
||||
gpointer log_object,
|
||||
GError **error);
|
||||
|
||||
/*****************************************************************************/
|
||||
/* UBANDSEL=X command builder */
|
||||
|
||||
gchar *mm_ublox_build_ubandsel_set_command (GArray *bands,
|
||||
const gchar *model,
|
||||
GError **error);
|
||||
|
||||
/*****************************************************************************/
|
||||
/* UACT? response parser */
|
||||
|
||||
GArray *mm_ublox_parse_uact_response (const gchar *response,
|
||||
GError **error);
|
||||
|
||||
/*****************************************************************************/
|
||||
/* UACT=? test parser */
|
||||
|
||||
gboolean mm_ublox_parse_uact_test (const gchar *response,
|
||||
gpointer log_object,
|
||||
GArray **bands_2g,
|
||||
GArray **bands_3g,
|
||||
GArray **bands_4g,
|
||||
GError **error);
|
||||
|
||||
/*****************************************************************************/
|
||||
/* UACT=X command builder */
|
||||
|
||||
gchar *mm_ublox_build_uact_set_command (GArray *bands,
|
||||
GError **error);
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Get mode to apply when ANY */
|
||||
|
||||
MMModemMode mm_ublox_get_modem_mode_any (const GArray *combinations);
|
||||
|
||||
/*****************************************************************************/
|
||||
/* URAT? response parser */
|
||||
|
||||
gboolean mm_ublox_parse_urat_read_response (const gchar *response,
|
||||
gpointer log_object,
|
||||
MMModemMode *out_allowed,
|
||||
MMModemMode *out_preferred,
|
||||
GError **error);
|
||||
|
||||
/*****************************************************************************/
|
||||
/* URAT=X command builder */
|
||||
|
||||
gchar *mm_ublox_build_urat_set_command (MMModemMode allowed,
|
||||
MMModemMode preferred,
|
||||
GError **error);
|
||||
|
||||
/*****************************************************************************/
|
||||
/* +UAUTHREQ=? test parser */
|
||||
|
||||
typedef enum { /*< underscore_name=mm_ublox_bearer_allowed_auth >*/
|
||||
MM_UBLOX_BEARER_ALLOWED_AUTH_UNKNOWN = 0,
|
||||
MM_UBLOX_BEARER_ALLOWED_AUTH_NONE = 1 << 0,
|
||||
MM_UBLOX_BEARER_ALLOWED_AUTH_PAP = 1 << 1,
|
||||
MM_UBLOX_BEARER_ALLOWED_AUTH_CHAP = 1 << 2,
|
||||
MM_UBLOX_BEARER_ALLOWED_AUTH_AUTO = 1 << 3,
|
||||
} MMUbloxBearerAllowedAuth;
|
||||
|
||||
MMUbloxBearerAllowedAuth mm_ublox_parse_uauthreq_test (const char *response,
|
||||
gpointer log_object,
|
||||
GError **error);
|
||||
|
||||
/*****************************************************************************/
|
||||
/* +UGCNTRD response parser */
|
||||
|
||||
gboolean mm_ublox_parse_ugcntrd_response_for_cid (const gchar *response,
|
||||
guint in_cid,
|
||||
guint64 *session_tx_bytes,
|
||||
guint64 *session_rx_bytes,
|
||||
guint64 *total_tx_bytes,
|
||||
guint64 *total_rx_bytes,
|
||||
GError **error);
|
||||
|
||||
#endif /* MM_MODEM_HELPERS_UBLOX_H */
|
||||
@@ -0,0 +1,265 @@
|
||||
/* -*- 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) 2016 Aleksander Morgado <aleksander@aleksander.es>
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include <gmodule.h>
|
||||
|
||||
#define _LIBMM_INSIDE_MM
|
||||
#include <libmm-glib.h>
|
||||
|
||||
#include "mm-log-object.h"
|
||||
#include "mm-serial-parsers.h"
|
||||
#include "mm-broadband-modem-ublox.h"
|
||||
#include "mm-plugin-ublox.h"
|
||||
|
||||
G_DEFINE_TYPE (MMPluginUblox, mm_plugin_ublox, MM_TYPE_PLUGIN)
|
||||
|
||||
MM_PLUGIN_DEFINE_MAJOR_VERSION
|
||||
MM_PLUGIN_DEFINE_MINOR_VERSION
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
static MMBaseModem *
|
||||
create_modem (MMPlugin *self,
|
||||
const gchar *sysfs_path,
|
||||
const gchar **drivers,
|
||||
guint16 vendor,
|
||||
guint16 product,
|
||||
guint16 subsystem_vendor,
|
||||
GList *probes,
|
||||
GError **error)
|
||||
{
|
||||
return MM_BASE_MODEM (mm_broadband_modem_ublox_new (sysfs_path,
|
||||
drivers,
|
||||
mm_plugin_get_name (self),
|
||||
vendor,
|
||||
product));
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Custom init context */
|
||||
|
||||
typedef struct {
|
||||
MMPortSerialAt *port;
|
||||
GRegex *ready_regex;
|
||||
guint timeout_id;
|
||||
gint wait_timeout_secs;
|
||||
} CustomInitContext;
|
||||
|
||||
static void
|
||||
custom_init_context_free (CustomInitContext *ctx)
|
||||
{
|
||||
g_assert (!ctx->timeout_id);
|
||||
g_regex_unref (ctx->ready_regex);
|
||||
g_object_unref (ctx->port);
|
||||
g_slice_free (CustomInitContext, ctx);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
ublox_custom_init_finish (MMPortProbe *probe,
|
||||
GAsyncResult *result,
|
||||
GError **error)
|
||||
{
|
||||
return g_task_propagate_boolean (G_TASK (result), error);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
ready_timeout (GTask *task)
|
||||
{
|
||||
CustomInitContext *ctx;
|
||||
MMPortProbe *probe;
|
||||
|
||||
ctx = g_task_get_task_data (task);
|
||||
probe = g_task_get_source_object (task);
|
||||
|
||||
ctx->timeout_id = 0;
|
||||
|
||||
mm_port_serial_at_add_unsolicited_msg_handler (ctx->port, ctx->ready_regex,
|
||||
NULL, NULL, NULL);
|
||||
|
||||
mm_obj_dbg (probe, "timed out waiting for READY unsolicited message");
|
||||
|
||||
/* not an error really, we didn't probe anything yet, that's all */
|
||||
g_task_return_boolean (task, TRUE);
|
||||
g_object_unref (task);
|
||||
|
||||
return G_SOURCE_REMOVE;
|
||||
}
|
||||
|
||||
static void
|
||||
ready_received (MMPortSerialAt *port,
|
||||
GMatchInfo *info,
|
||||
GTask *task)
|
||||
{
|
||||
CustomInitContext *ctx;
|
||||
MMPortProbe *probe;
|
||||
|
||||
ctx = g_task_get_task_data (task);
|
||||
probe = g_task_get_source_object (task);
|
||||
|
||||
g_source_remove (ctx->timeout_id);
|
||||
ctx->timeout_id = 0;
|
||||
|
||||
mm_obj_dbg (probe, "received READY: port is AT");
|
||||
|
||||
/* Flag as an AT port right away */
|
||||
mm_port_probe_set_result_at (probe, TRUE);
|
||||
|
||||
g_task_return_boolean (task, TRUE);
|
||||
g_object_unref (task);
|
||||
}
|
||||
|
||||
static void
|
||||
wait_for_ready (GTask *task)
|
||||
{
|
||||
CustomInitContext *ctx;
|
||||
MMPortProbe *probe;
|
||||
|
||||
ctx = g_task_get_task_data (task);
|
||||
probe = g_task_get_source_object (task);
|
||||
|
||||
mm_obj_dbg (probe, "waiting for READY unsolicited message...");
|
||||
|
||||
/* Configure a regex on the TTY, so that we stop the custom init
|
||||
* as soon as +READY URC is received */
|
||||
mm_port_serial_at_add_unsolicited_msg_handler (ctx->port,
|
||||
ctx->ready_regex,
|
||||
(MMPortSerialAtUnsolicitedMsgFn) ready_received,
|
||||
task,
|
||||
NULL);
|
||||
|
||||
mm_obj_dbg (probe, "waiting %d seconds for init timeout", ctx->wait_timeout_secs);
|
||||
|
||||
/* Otherwise, let the custom init timeout in some seconds. */
|
||||
ctx->timeout_id = g_timeout_add_seconds (ctx->wait_timeout_secs, (GSourceFunc) ready_timeout, task);
|
||||
}
|
||||
|
||||
static void
|
||||
quick_at_ready (MMPortSerialAt *port,
|
||||
GAsyncResult *res,
|
||||
GTask *task)
|
||||
{
|
||||
MMPortProbe *probe;
|
||||
g_autoptr(GError) error = NULL;
|
||||
|
||||
probe = g_task_get_source_object (task);
|
||||
|
||||
mm_port_serial_at_command_finish (port, res, &error);
|
||||
if (error) {
|
||||
/* On a timeout error, wait for READY URC */
|
||||
if (g_error_matches (error, MM_SERIAL_ERROR, MM_SERIAL_ERROR_RESPONSE_TIMEOUT)) {
|
||||
wait_for_ready (task);
|
||||
return;
|
||||
}
|
||||
/* On an unknown error, make it fatal */
|
||||
if (!mm_serial_parser_v1_is_known_error (error)) {
|
||||
mm_obj_warn (probe, "custom port initialization logic failed: %s", error->message);
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
mm_obj_dbg (probe, "port is AT");
|
||||
mm_port_probe_set_result_at (probe, TRUE);
|
||||
|
||||
out:
|
||||
g_task_return_boolean (task, TRUE);
|
||||
g_object_unref (task);
|
||||
}
|
||||
|
||||
static void
|
||||
ublox_custom_init (MMPortProbe *probe,
|
||||
MMPortSerialAt *port,
|
||||
GCancellable *cancellable,
|
||||
GAsyncReadyCallback callback,
|
||||
gpointer user_data)
|
||||
{
|
||||
GTask *task;
|
||||
CustomInitContext *ctx;
|
||||
gint wait_timeout_secs;
|
||||
|
||||
task = g_task_new (probe, cancellable, callback, user_data);
|
||||
|
||||
/* If no explicit READY_DELAY configured, we don't need a custom init procedure */
|
||||
wait_timeout_secs = mm_kernel_device_get_property_as_int (mm_port_probe_peek_port (probe), "ID_MM_UBLOX_PORT_READY_DELAY");
|
||||
if (wait_timeout_secs <= 0) {
|
||||
g_task_return_boolean (task, TRUE);
|
||||
g_object_unref (task);
|
||||
return;
|
||||
}
|
||||
|
||||
ctx = g_slice_new0 (CustomInitContext);
|
||||
ctx->wait_timeout_secs = wait_timeout_secs;
|
||||
ctx->port = g_object_ref (port);
|
||||
ctx->ready_regex = g_regex_new ("\\r\\n\\+AT:\\s*READY\\r\\n",
|
||||
G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, NULL);
|
||||
g_task_set_task_data (task, ctx, (GDestroyNotify) custom_init_context_free);
|
||||
|
||||
/* If the device hasn't been plugged in right away, we assume it was already
|
||||
* running for some time. We validate the assumption with a quick AT probe,
|
||||
* and if it times out, we run the explicit READY wait from scratch (e.g.
|
||||
* to cope with the case where MM starts after the TTY has been exposed but
|
||||
* where the device was also just reseted) */
|
||||
if (!mm_device_get_hotplugged (mm_port_probe_peek_device (probe))) {
|
||||
mm_port_serial_at_command (ctx->port,
|
||||
"AT",
|
||||
1,
|
||||
FALSE, /* raw */
|
||||
FALSE, /* allow_cached */
|
||||
g_task_get_cancellable (task),
|
||||
(GAsyncReadyCallback)quick_at_ready,
|
||||
task);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Device hotplugged and has a defined ready delay, wait for READY URC */
|
||||
wait_for_ready (task);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
G_MODULE_EXPORT MMPlugin *
|
||||
mm_plugin_create (void)
|
||||
{
|
||||
static const gchar *subsystems[] = { "tty", "net", NULL };
|
||||
static const guint16 vendor_ids[] = { 0x1546, 0 };
|
||||
static const gchar *vendor_strings[] = { "u-blox", NULL };
|
||||
static const MMAsyncMethod custom_init = {
|
||||
.async = G_CALLBACK (ublox_custom_init),
|
||||
.finish = G_CALLBACK (ublox_custom_init_finish),
|
||||
};
|
||||
|
||||
return MM_PLUGIN (g_object_new (MM_TYPE_PLUGIN_UBLOX,
|
||||
MM_PLUGIN_NAME, MM_MODULE_NAME,
|
||||
MM_PLUGIN_ALLOWED_SUBSYSTEMS, subsystems,
|
||||
MM_PLUGIN_ALLOWED_VENDOR_IDS, vendor_ids,
|
||||
MM_PLUGIN_ALLOWED_VENDOR_STRINGS, vendor_strings,
|
||||
MM_PLUGIN_ALLOWED_AT, TRUE,
|
||||
MM_PLUGIN_SEND_DELAY, (guint64) 0,
|
||||
MM_PLUGIN_CUSTOM_INIT, &custom_init,
|
||||
NULL));
|
||||
}
|
||||
|
||||
static void
|
||||
mm_plugin_ublox_init (MMPluginUblox *self)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
mm_plugin_ublox_class_init (MMPluginUbloxClass *klass)
|
||||
{
|
||||
MMPluginClass *plugin_class = MM_PLUGIN_CLASS (klass);
|
||||
|
||||
plugin_class->create_modem = create_modem;
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
/* -*- 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) 2016 Aleksander Morgado <aleksander@aleksander.es>
|
||||
*/
|
||||
|
||||
#ifndef MM_PLUGIN_UBLOX_H
|
||||
#define MM_PLUGIN_UBLOX_H
|
||||
|
||||
#include "mm-plugin.h"
|
||||
|
||||
#define MM_TYPE_PLUGIN_UBLOX (mm_plugin_ublox_get_type ())
|
||||
#define MM_PLUGIN_UBLOX(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MM_TYPE_PLUGIN_UBLOX, MMPluginUblox))
|
||||
#define MM_PLUGIN_UBLOX_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), MM_TYPE_PLUGIN_UBLOX, MMPluginUbloxClass))
|
||||
#define MM_IS_PLUGIN_UBLOX(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MM_TYPE_PLUGIN_UBLOX))
|
||||
#define MM_IS_PLUGIN_UBLOX_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), MM_TYPE_PLUGIN_UBLOX))
|
||||
#define MM_PLUGIN_UBLOX_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), MM_TYPE_PLUGIN_UBLOX, MMPluginUbloxClass))
|
||||
|
||||
typedef struct {
|
||||
MMPlugin parent;
|
||||
} MMPluginUblox;
|
||||
|
||||
typedef struct {
|
||||
MMPluginClass parent;
|
||||
} MMPluginUbloxClass;
|
||||
|
||||
GType mm_plugin_ublox_get_type (void);
|
||||
|
||||
G_MODULE_EXPORT MMPlugin *mm_plugin_create (void);
|
||||
|
||||
#endif /* MM_PLUGIN_UBLOX_H */
|
||||
@@ -0,0 +1,163 @@
|
||||
/* -*- 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,
|
||||
"active", TRUE, /* by default always active */
|
||||
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;
|
||||
}
|
||||
@@ -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 */
|
||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user