diff options
author | Aleksander Morgado <aleksander@aleksander.es> | 2020-10-25 09:06:41 +0100 |
---|---|---|
committer | Aleksander Morgado <aleksander@aleksander.es> | 2020-11-09 18:41:57 +0100 |
commit | 56fca1447324f6ac47f2c7e7c9534c49f1bf1da3 (patch) | |
tree | c20d1e55f36892e568fa7300409c30c7957a8304 | |
parent | 2a6b596bcfa83a91d93c07046dc067f1e1d08a6c (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.c | 344 |
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, |