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:
Aleksander Morgado
2023-01-03 13:56:25 +00:00
committed by Aleksander Morgado
parent 072d7ac906
commit e14b904cbd
318 changed files with 5 additions and 3 deletions
@@ -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"
+162
View File
@@ -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
+213
View File
@@ -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 */
+265
View File
@@ -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;
}
+40
View File
@@ -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 */
+163
View File
@@ -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;
}
+51
View File
@@ -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