aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAleksander Morgado <aleksander@aleksander.es>2020-10-25 09:06:41 +0100
committerAleksander Morgado <aleksander@aleksander.es>2020-11-09 18:41:57 +0100
commit56fca1447324f6ac47f2c7e7c9534c49f1bf1da3 (patch)
treec20d1e55f36892e568fa7300409c30c7957a8304
parent2a6b596bcfa83a91d93c07046dc067f1e1d08a6c (diff)
base-modem: refactor port grabbing logic
Split in its own method the per-subsystem port creation mechanism, and apply all common AT port settings (e.g. response parser, flags) in a single place.
-rw-r--r--src/mm-base-modem.c344
1 files changed, 152 insertions, 192 deletions
diff --git a/src/mm-base-modem.c b/src/mm-base-modem.c
index c350febb..fa13548e 100644
--- a/src/mm-base-modem.c
+++ b/src/mm-base-modem.c
@@ -123,17 +123,12 @@ mm_base_modem_get_dbus_id (MMBaseModem *self)
return self->priv->dbus_id;
}
-static gchar *
-get_hash_key (const gchar *subsys,
- const gchar *name)
-{
- return g_strdup_printf ("%s%s", subsys, name);
-}
+/******************************************************************************/
static void
serial_port_timed_out_cb (MMPortSerial *port,
- guint n_consecutive_timeouts,
- MMBaseModem *self)
+ guint n_consecutive_timeouts,
+ MMBaseModem *self)
{
/* If reached the maximum number of timeouts, invalidate modem */
if (n_consecutive_timeouts >= self->priv->max_timeouts) {
@@ -150,6 +145,105 @@ serial_port_timed_out_cb (MMPortSerial *port,
n_consecutive_timeouts);
}
+static MMPort *
+base_modem_create_ignored_port (MMBaseModem *self,
+ const gchar *name)
+{
+ return MM_PORT (g_object_new (MM_TYPE_PORT,
+ MM_PORT_DEVICE, name,
+ MM_PORT_TYPE, MM_PORT_TYPE_IGNORED,
+ NULL));
+}
+
+static MMPort *
+base_modem_create_net_port (MMBaseModem *self,
+ const gchar *name)
+{
+ return MM_PORT (g_object_new (MM_TYPE_PORT,
+ MM_PORT_DEVICE, name,
+ MM_PORT_SUBSYS, MM_PORT_SUBSYS_NET,
+ MM_PORT_TYPE, MM_PORT_TYPE_NET,
+ NULL));
+}
+
+static MMPort *
+base_modem_create_tty_port (MMBaseModem *self,
+ const gchar *name,
+ MMKernelDevice *kernel_device,
+ MMPortType ptype)
+{
+ MMPort *port = NULL;
+ const gchar *flow_control_tag;
+
+ if (ptype == MM_PORT_TYPE_QCDM)
+ port = MM_PORT (mm_port_serial_qcdm_new (name));
+ else if (ptype == MM_PORT_TYPE_GPS)
+ port = MM_PORT (mm_port_serial_gps_new (name));
+ else if (ptype == MM_PORT_TYPE_AUDIO)
+ port = MM_PORT (mm_port_serial_new (name, ptype));
+ else if (ptype == MM_PORT_TYPE_AT)
+ port = MM_PORT (mm_port_serial_at_new (name, MM_PORT_SUBSYS_TTY));
+
+ if (!port)
+ return NULL;
+
+ /* Enable port timeout checks if requested to do so */
+ if (self->priv->max_timeouts > 0)
+ g_signal_connect (port,
+ "timed-out",
+ G_CALLBACK (serial_port_timed_out_cb),
+ self);
+
+ /* Optional user-provided baudrate */
+ if (mm_kernel_device_has_property (kernel_device, ID_MM_TTY_BAUDRATE))
+ g_object_set (port,
+ MM_PORT_SERIAL_BAUD, mm_kernel_device_get_property_as_int (kernel_device, ID_MM_TTY_BAUDRATE),
+ NULL);
+
+ /* Optional user-provided flow control */
+ flow_control_tag = mm_kernel_device_get_property (kernel_device, ID_MM_TTY_FLOW_CONTROL);
+ if (flow_control_tag) {
+ MMFlowControl flow_control;
+ g_autoptr(GError) inner_error = NULL;
+
+ flow_control = mm_flow_control_from_string (flow_control_tag, &inner_error);
+ if (flow_control != MM_FLOW_CONTROL_UNKNOWN)
+ g_object_set (port,
+ MM_PORT_SERIAL_FLOW_CONTROL, flow_control,
+ NULL);
+ else
+ mm_obj_warn (self, "unsupported flow control settings in port %s: %s",
+ name, inner_error->message);
+ }
+
+ return port;
+}
+
+static MMPort *
+base_modem_create_usbmisc_port (MMBaseModem *self,
+ const gchar *name,
+ MMPortType ptype)
+{
+#if defined WITH_QMI
+ if (ptype == MM_PORT_TYPE_QMI)
+ return MM_PORT (mm_port_qmi_new (name));
+#endif
+#if defined WITH_MBIM
+ if (ptype == MM_PORT_TYPE_MBIM)
+ return MM_PORT (mm_port_mbim_new (name));
+#endif
+ if (ptype == MM_PORT_TYPE_AT)
+ return MM_PORT (mm_port_serial_at_new (name, MM_PORT_SUBSYS_USBMISC));
+ return NULL;
+}
+
+static MMPort *
+base_modem_create_virtual_port (MMBaseModem *self,
+ const gchar *name)
+{
+ return MM_PORT (mm_port_serial_at_new (name, MM_PORT_SUBSYS_UNIX));
+}
+
gboolean
mm_base_modem_grab_port (MMBaseModem *self,
MMKernelDevice *kernel_device,
@@ -157,218 +251,84 @@ mm_base_modem_grab_port (MMBaseModem *self,
MMPortSerialAtFlag at_pflags,
GError **error)
{
- MMPort *port;
- gchar *key;
- const gchar *subsys;
- const gchar *name;
-
- g_return_val_if_fail (MM_IS_BASE_MODEM (self), FALSE);
- g_return_val_if_fail (MM_IS_KERNEL_DEVICE (kernel_device), FALSE);
+ MMPort *port;
+ const gchar *subsys;
+ const gchar *name;
+ g_autofree gchar *key = NULL;
subsys = mm_kernel_device_get_subsystem (kernel_device);
name = mm_kernel_device_get_name (kernel_device);
- g_return_val_if_fail (subsys != NULL, FALSE);
- g_return_val_if_fail (name != NULL, FALSE);
-
- /* Only allow 'tty', 'net' and 'cdc-wdm' ports */
- if (!g_str_equal (subsys, "net") &&
- !g_str_equal (subsys, "tty") &&
- !(g_str_has_prefix (subsys, "usb") && g_str_has_prefix (name, "cdc-wdm")) &&
- !g_str_equal (subsys, "virtual")) {
- g_set_error (error,
- MM_CORE_ERROR,
- MM_CORE_ERROR_UNSUPPORTED,
- "Cannot add port '%s/%s', unhandled subsystem",
- subsys,
- name);
- return FALSE;
- }
-
/* Check whether we already have it stored */
- key = get_hash_key (subsys, name);
+ key = g_strdup_printf ("%s%s", subsys, name);
port = g_hash_table_lookup (self->priv->ports, key);
if (port) {
- g_set_error (error,
- MM_CORE_ERROR,
- MM_CORE_ERROR_UNSUPPORTED,
- "Cannot add port '%s/%s', already exists",
- subsys,
- name);
- g_free (key);
+ g_set_error (error, MM_CORE_ERROR, MM_CORE_ERROR_UNSUPPORTED,
+ "Cannot add port '%s/%s', already exists", subsys, name);
return FALSE;
}
/* Explicitly ignored ports, grab them but explicitly flag them as ignored
* right away, all the same way (i.e. regardless of subsystem). */
- if (ptype == MM_PORT_TYPE_IGNORED) {
- port = MM_PORT (g_object_new (MM_TYPE_PORT,
- MM_PORT_DEVICE, name,
- MM_PORT_TYPE, MM_PORT_TYPE_IGNORED,
- NULL));
- }
- /* Serial ports... */
- else if (g_str_equal (subsys, "tty")) {
- const gchar *flow_control_tag;
-
- if (ptype == MM_PORT_TYPE_QCDM)
- /* QCDM port */
- port = MM_PORT (mm_port_serial_qcdm_new (name));
- else if (ptype == MM_PORT_TYPE_AT) {
- /* AT port */
- port = MM_PORT (mm_port_serial_at_new (name, MM_PORT_SUBSYS_TTY));
-
- /* Set common response parser */
- mm_port_serial_at_set_response_parser (MM_PORT_SERIAL_AT (port),
- mm_serial_parser_v1_parse,
- mm_serial_parser_v1_new (),
- mm_serial_parser_v1_destroy);
-
- /* Prefer plugin-provided flags to the generic ones */
- if (at_pflags == MM_PORT_SERIAL_AT_FLAG_NONE) {
- if (mm_kernel_device_get_property_as_boolean (kernel_device, ID_MM_PORT_TYPE_AT_PRIMARY)) {
- mm_obj_dbg (self, "AT port '%s/%s' flagged as primary", subsys, name);
- at_pflags = MM_PORT_SERIAL_AT_FLAG_PRIMARY;
- } else if (mm_kernel_device_get_property_as_boolean (kernel_device, ID_MM_PORT_TYPE_AT_SECONDARY)) {
- mm_obj_dbg (self, "AT port '%s/%s' flagged as secondary", subsys, name);
- at_pflags = MM_PORT_SERIAL_AT_FLAG_SECONDARY;
- } else if (mm_kernel_device_get_property_as_boolean (kernel_device, ID_MM_PORT_TYPE_AT_PPP)) {
- mm_obj_dbg (self, "AT port '%s/%s' flagged as PPP", subsys, name);
- at_pflags = MM_PORT_SERIAL_AT_FLAG_PPP;
- }
- }
-
- /* The plugin may specify NONE_NO_GENERIC to avoid the generic
- * port type hints from being applied. */
- if (at_pflags == MM_PORT_SERIAL_AT_FLAG_NONE_NO_GENERIC)
- at_pflags = MM_PORT_SERIAL_AT_FLAG_NONE;
-
- mm_port_serial_at_set_flags (MM_PORT_SERIAL_AT (port), at_pflags);
-
- } else if (ptype == MM_PORT_TYPE_GPS) {
- /* Raw GPS port */
- port = MM_PORT (mm_port_serial_gps_new (name));
- } else if (ptype == MM_PORT_TYPE_AUDIO) {
- /* Generic audio port */
- port = MM_PORT (mm_port_serial_new (name, ptype));
- } else {
- g_set_error (error,
- MM_CORE_ERROR,
- MM_CORE_ERROR_UNSUPPORTED,
- "Cannot add port '%s/%s', unhandled serial type",
- subsys,
- name);
- g_free (key);
- return FALSE;
- }
-
- /* For serial ports, enable port timeout checks if requested to do so */
- if (self->priv->max_timeouts > 0)
- g_signal_connect (port,
- "timed-out",
- G_CALLBACK (serial_port_timed_out_cb),
- self);
-
- /* For serial ports, optionally use a specific baudrate and flow control */
- if (mm_kernel_device_has_property (kernel_device, ID_MM_TTY_BAUDRATE))
- g_object_set (port,
- MM_PORT_SERIAL_BAUD, mm_kernel_device_get_property_as_int (kernel_device, ID_MM_TTY_BAUDRATE),
- NULL);
-
- flow_control_tag = mm_kernel_device_get_property (kernel_device, ID_MM_TTY_FLOW_CONTROL);
- if (flow_control_tag) {
- MMFlowControl flow_control;
- GError *inner_error = NULL;
-
- flow_control = mm_flow_control_from_string (flow_control_tag, &inner_error);
- if (flow_control == MM_FLOW_CONTROL_UNKNOWN) {
- mm_obj_warn (self, "unsupported flow control settings in port %s: %s",
- name, inner_error->message);
- g_error_free (inner_error);
- } else {
- g_object_set (port,
- MM_PORT_SERIAL_FLOW_CONTROL, flow_control,
- NULL);
- }
- }
- }
- /* Net ports... */
- else if (g_str_equal (subsys, "net")) {
- port = MM_PORT (g_object_new (MM_TYPE_PORT,
- MM_PORT_DEVICE, name,
- MM_PORT_SUBSYS, MM_PORT_SUBSYS_NET,
- MM_PORT_TYPE, MM_PORT_TYPE_NET,
- NULL));
+ if (ptype == MM_PORT_TYPE_IGNORED)
+ port = base_modem_create_ignored_port (self, name);
+ else if (g_str_equal (subsys, "net"))
+ port = base_modem_create_net_port (self, name);
+ else if (g_str_equal (subsys, "tty"))
+ port = base_modem_create_tty_port (self, name, kernel_device, ptype);
+ else if (g_str_has_prefix (subsys, "usb") && g_str_has_prefix (name, "cdc-wdm"))
+ port = base_modem_create_usbmisc_port (self, name, ptype);
+ else if (g_str_equal (subsys, "virtual"))
+ port = base_modem_create_virtual_port (self, name);
+
+ if (!port) {
+ g_set_error (error, MM_CORE_ERROR, MM_CORE_ERROR_UNSUPPORTED,
+ "Cannot add port '%s/%s', unhandled port type", subsys, name);
+ return FALSE;
}
- /* cdc-wdm ports... */
- else if (g_str_has_prefix (subsys, "usb") &&
- g_str_has_prefix (name, "cdc-wdm")) {
-#if defined WITH_QMI
- if (ptype == MM_PORT_TYPE_QMI)
- port = MM_PORT (mm_port_qmi_new (name));
-#endif
-#if defined WITH_MBIM
- if (!port && ptype == MM_PORT_TYPE_MBIM)
- port = MM_PORT (mm_port_mbim_new (name));
-#endif
- /* Non-serial AT port */
- if (!port && ptype == MM_PORT_TYPE_AT) {
- port = MM_PORT (mm_port_serial_at_new (name, MM_PORT_SUBSYS_USBMISC));
-
- /* Set common response parser */
- mm_port_serial_at_set_response_parser (MM_PORT_SERIAL_AT (port),
- mm_serial_parser_v1_parse,
- mm_serial_parser_v1_new (),
- mm_serial_parser_v1_destroy);
- /* Store flags already */
- mm_port_serial_at_set_flags (MM_PORT_SERIAL_AT (port), at_pflags);
- }
+ /* Store kernel device */
+ g_object_set (port, MM_PORT_KERNEL_DEVICE, kernel_device, NULL);
- if (!port) {
- g_set_error (error,
- MM_CORE_ERROR,
- MM_CORE_ERROR_UNSUPPORTED,
- "Cannot add port '%s/%s', unsupported",
- subsys,
- name);
- g_free (key);
- return FALSE;
- }
- }
- /* Virtual ports... */
- else if (g_str_equal (subsys, "virtual")) {
- port = MM_PORT (mm_port_serial_at_new (name, MM_PORT_SUBSYS_UNIX));
+ /* Set owner ID */
+ mm_log_object_set_owner_id (MM_LOG_OBJECT (port), mm_log_object_get_id (MM_LOG_OBJECT (self)));
- /* Set common response parser */
+ /* Common setup for all AT ports from all subsystems */
+ if (MM_IS_PORT_SERIAL_AT (port)) {
mm_port_serial_at_set_response_parser (MM_PORT_SERIAL_AT (port),
mm_serial_parser_v1_parse,
mm_serial_parser_v1_new (),
mm_serial_parser_v1_destroy);
- /* Store flags already */
+ /* Prefer plugin-provided flags to the generic ones */
+ if (at_pflags == MM_PORT_SERIAL_AT_FLAG_NONE) {
+ if (mm_kernel_device_get_property_as_boolean (kernel_device, ID_MM_PORT_TYPE_AT_PRIMARY)) {
+ mm_obj_dbg (port, "AT port flagged as primary");
+ at_pflags = MM_PORT_SERIAL_AT_FLAG_PRIMARY;
+ } else if (mm_kernel_device_get_property_as_boolean (kernel_device, ID_MM_PORT_TYPE_AT_SECONDARY)) {
+ mm_obj_dbg (port, "AT port flagged as secondary");
+ at_pflags = MM_PORT_SERIAL_AT_FLAG_SECONDARY;
+ } else if (mm_kernel_device_get_property_as_boolean (kernel_device, ID_MM_PORT_TYPE_AT_PPP)) {
+ mm_obj_dbg (port, "AT port flagged as PPP");
+ at_pflags = MM_PORT_SERIAL_AT_FLAG_PPP;
+ }
+ }
+ /* The plugin may specify NONE_NO_GENERIC to avoid the generic
+ * port type hints from being applied. */
+ if (at_pflags == MM_PORT_SERIAL_AT_FLAG_NONE_NO_GENERIC)
+ at_pflags = MM_PORT_SERIAL_AT_FLAG_NONE;
+
mm_port_serial_at_set_flags (MM_PORT_SERIAL_AT (port), at_pflags);
}
- else
- /* We already filter out before all non-tty, non-net, non-cdc-wdm ports */
- g_assert_not_reached ();
-
- mm_obj_dbg (self, "grabbed port '%s/%s'", name, mm_port_type_get_string (ptype));
/* Add it to the tracking HT.
* Note: 'key' and 'port' now owned by the HT. */
- g_hash_table_insert (self->priv->ports, key, port);
-
- /* Store kernel device */
- g_object_set (port,
- MM_PORT_KERNEL_DEVICE, kernel_device,
- NULL);
-
- /* Set owner ID */
- mm_log_object_set_owner_id (MM_LOG_OBJECT (port), mm_log_object_get_id (MM_LOG_OBJECT (self)));
-
+ mm_obj_dbg (port, "port grabbed");
+ g_hash_table_insert (self->priv->ports, g_steal_pointer (&key), port);
return TRUE;
}
+/******************************************************************************/
+
gboolean
mm_base_modem_disable_finish (MMBaseModem *self,
GAsyncResult *res,