diff options
author | Aleksander Morgado <aleksandermj@chromium.org> | 2022-12-08 13:37:55 +0000 |
---|---|---|
committer | Aleksander Morgado <aleksander@aleksander.es> | 2023-01-03 13:56:25 +0000 |
commit | e14b904cbd6816cb0227d519d308ae71ddaf6e07 (patch) | |
tree | 4997ab68cc606fdf4d72a571e821cec0c8df42ef /src/plugins/foxconn | |
parent | 072d7ac9065f444e83b390a1e2af5471ac0d48f6 (diff) |
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.
Diffstat (limited to 'src/plugins/foxconn')
-rw-r--r-- | src/plugins/foxconn/77-mm-foxconn-port-types.rules | 26 | ||||
-rw-r--r-- | src/plugins/foxconn/mm-broadband-modem-mbim-foxconn.c | 612 | ||||
-rw-r--r-- | src/plugins/foxconn/mm-broadband-modem-mbim-foxconn.h | 49 | ||||
-rw-r--r-- | src/plugins/foxconn/mm-foxconn-t77w968-carrier-mapping.conf | 319 | ||||
-rw-r--r-- | src/plugins/foxconn/mm-plugin-foxconn.c | 121 | ||||
-rw-r--r-- | src/plugins/foxconn/mm-plugin-foxconn.h | 46 | ||||
-rw-r--r-- | src/plugins/foxconn/mm-shared.c | 20 |
7 files changed, 1193 insertions, 0 deletions
diff --git a/src/plugins/foxconn/77-mm-foxconn-port-types.rules b/src/plugins/foxconn/77-mm-foxconn-port-types.rules new file mode 100644 index 00000000..344df152 --- /dev/null +++ b/src/plugins/foxconn/77-mm-foxconn-port-types.rules @@ -0,0 +1,26 @@ +# do not edit this file, it will be overwritten on update + +ACTION!="add|change|move|bind", GOTO="mm_foxconn_port_types_end" + +SUBSYSTEMS=="usb", ATTRS{idVendor}=="0489", GOTO="mm_foxconn_vendorcheck" +GOTO="mm_foxconn_port_types_end" + +LABEL="mm_foxconn_vendorcheck" +SUBSYSTEMS=="usb", ATTRS{bInterfaceNumber}=="?*", ENV{.MM_USBIFNUM}="$attr{bInterfaceNumber}" + +# Foxconn T77w968 (default 0xe0b4, with esim support 0xe0b5) +# if 02: primary port +# if 03: secondary port +# if 04: raw NMEA port +# if 05: diag/qcdm port +ATTRS{idVendor}=="0489", ATTRS{idProduct}=="e0b4", ENV{.MM_USBIFNUM}=="02", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_PRIMARY}="1" +ATTRS{idVendor}=="0489", ATTRS{idProduct}=="e0b4", ENV{.MM_USBIFNUM}=="03", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_SECONDARY}="1" +ATTRS{idVendor}=="0489", ATTRS{idProduct}=="e0b4", ENV{.MM_USBIFNUM}=="04", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_GPS}="1" +ATTRS{idVendor}=="0489", ATTRS{idProduct}=="e0b4", ENV{.MM_USBIFNUM}=="05", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_QCDM}="1" +ATTRS{idVendor}=="0489", ATTRS{idProduct}=="e0b5", ENV{.MM_USBIFNUM}=="02", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_PRIMARY}="1" +ATTRS{idVendor}=="0489", ATTRS{idProduct}=="e0b5", ENV{.MM_USBIFNUM}=="03", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_SECONDARY}="1" +ATTRS{idVendor}=="0489", ATTRS{idProduct}=="e0b5", ENV{.MM_USBIFNUM}=="04", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_GPS}="1" +ATTRS{idVendor}=="0489", ATTRS{idProduct}=="e0b5", ENV{.MM_USBIFNUM}=="05", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_QCDM}="1" + +GOTO="mm_foxconn_port_types_end" +LABEL="mm_foxconn_port_types_end" diff --git a/src/plugins/foxconn/mm-broadband-modem-mbim-foxconn.c b/src/plugins/foxconn/mm-broadband-modem-mbim-foxconn.c new file mode 100644 index 00000000..cec1c617 --- /dev/null +++ b/src/plugins/foxconn/mm-broadband-modem-mbim-foxconn.c @@ -0,0 +1,612 @@ +/* -*- 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-2019 Aleksander Morgado <aleksander@aleksander.es> + */ + +#include <config.h> + +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <unistd.h> +#include <ctype.h> +#include <time.h> + +#include <ModemManager.h> +#define _LIBMM_INSIDE_MM +#include <libmm-glib.h> + +#include "mm-errors-types.h" +#include "mm-modem-helpers.h" +#include "mm-base-modem-at.h" +#include "mm-iface-modem.h" +#include "mm-iface-modem-location.h" +#include "mm-broadband-modem-mbim-foxconn.h" + +#if defined WITH_QMI && QMI_MBIM_QMUX_SUPPORTED +# include "mm-iface-modem-firmware.h" +# include "mm-shared-qmi.h" +# include "mm-log.h" +#endif + +static void iface_modem_location_init (MMIfaceModemLocation *iface); + +#if defined WITH_QMI && QMI_MBIM_QMUX_SUPPORTED +static void iface_modem_firmware_init (MMIfaceModemFirmware *iface); +#endif + +static MMIfaceModemLocation *iface_modem_location_parent; + +G_DEFINE_TYPE_EXTENDED (MMBroadbandModemMbimFoxconn, mm_broadband_modem_mbim_foxconn, MM_TYPE_BROADBAND_MODEM_MBIM, 0, +#if defined WITH_QMI && QMI_MBIM_QMUX_SUPPORTED + G_IMPLEMENT_INTERFACE (MM_TYPE_IFACE_MODEM_FIRMWARE, iface_modem_firmware_init) +#endif + G_IMPLEMENT_INTERFACE (MM_TYPE_IFACE_MODEM_LOCATION, iface_modem_location_init)) + +typedef enum { + FEATURE_SUPPORT_UNKNOWN, + FEATURE_NOT_SUPPORTED, + FEATURE_SUPPORTED +} FeatureSupport; + +struct _MMBroadbandModemMbimFoxconnPrivate { + FeatureSupport unmanaged_gps_support; +}; + + +#if defined WITH_QMI && QMI_MBIM_QMUX_SUPPORTED + +/*****************************************************************************/ +/* Firmware update settings + * + * We only support reporting firmware update settings when QMI support is built, + * because this is the only clean way to get the expected firmware version to + * report. + */ + +static MMFirmwareUpdateSettings * +firmware_load_update_settings_finish (MMIfaceModemFirmware *self, + GAsyncResult *res, + GError **error) +{ + return g_task_propagate_pointer (G_TASK (res), error); +} + +static gboolean +needs_qdu_and_mcfg_apps_version (MMIfaceModemFirmware *self) +{ + guint vendor_id; + guint product_id; + + /* 0x105b is the T99W175 module, T99W175 supports QDU and requires MCFG+APPS version. + * T99W265(0x0489:0xe0da ; 0x0489:0xe0db): supports QDU and requires MCFG+APPS version. + * else support FASTBOOT and QMI PDC, and require only MCFG version. + */ + vendor_id = mm_base_modem_get_vendor_id (MM_BASE_MODEM (self)); + product_id = mm_base_modem_get_product_id (MM_BASE_MODEM (self)); + return (vendor_id == 0x105b || (vendor_id == 0x0489 && (product_id == 0xe0da || product_id == 0xe0db))); +} + +/*****************************************************************************/ +/* Need APPS version for the development of different functions when T77W968 support FASTBOOT and QMI PDC. + * Such as: T77W968.F1.0.0.5.2.GC.013.037 and T77W968.F1.0.0.5.2.GC.013.049, the MCFG version(T77W968.F1.0.0.5.2.GC.013) is same, + * but the APPS version(037 and 049) is different. + * + * For T77W968.F1.0.0.5.2.GC.013.049, before the change, "fwupdmgr get-devices" can obtain Current version is T77W968.F1.0.0.5.2.GC.013, + * it only include the MCFG version. + * After add need APPS version, it shows Current version is T77W968.F1.0.0.5.2.GC.013.049, including the MCFG+APPS version. + */ + +static gboolean +needs_fastboot_and_qmi_pdc_mcfg_apps_version (MMIfaceModemFirmware *self) +{ + guint vendor_id; + guint product_id; + + /* T77W968(0x413c:0x81d7 ; 0x413c:0x81e0 ; 0x413c:0x81e4 ; 0x413c:0x81e6): supports FASTBOOT and QMI PDC, + * and requires MCFG+APPS version. + * else support FASTBOOT and QMI PDC, and require only MCFG version. + */ + vendor_id = mm_base_modem_get_vendor_id (MM_BASE_MODEM (self)); + product_id = mm_base_modem_get_product_id (MM_BASE_MODEM (self)); + return (vendor_id == 0x413c && (product_id == 0x81d7 || product_id == 0x81e0 || product_id == 0x81e4 || product_id == 0x81e6)); +} + +static MMFirmwareUpdateSettings * +create_update_settings (MMIfaceModemFirmware *self, + const gchar *version_str) +{ + MMModemFirmwareUpdateMethod methods = MM_MODEM_FIRMWARE_UPDATE_METHOD_NONE; + MMFirmwareUpdateSettings *update_settings = NULL; + + if (needs_qdu_and_mcfg_apps_version (self)) + methods = MM_MODEM_FIRMWARE_UPDATE_METHOD_MBIM_QDU; + else + methods = MM_MODEM_FIRMWARE_UPDATE_METHOD_FASTBOOT | MM_MODEM_FIRMWARE_UPDATE_METHOD_QMI_PDC; + + update_settings = mm_firmware_update_settings_new (methods); + if (methods & MM_MODEM_FIRMWARE_UPDATE_METHOD_FASTBOOT) + mm_firmware_update_settings_set_fastboot_at (update_settings, "AT^FASTBOOT"); + mm_firmware_update_settings_set_version (update_settings, version_str); + return update_settings; +} + +static void +dms_foxconn_get_firmware_version_ready (QmiClientDms *client, + GAsyncResult *res, + GTask *task) +{ + g_autoptr(QmiMessageDmsFoxconnGetFirmwareVersionOutput) output = NULL; + GError *error = NULL; + const gchar *str; + + output = qmi_client_dms_foxconn_get_firmware_version_finish (client, res, &error); + if (!output || !qmi_message_dms_foxconn_get_firmware_version_output_get_result (output, &error)) { + g_task_return_error (task, error); + g_object_unref (task); + return; + } + + qmi_message_dms_foxconn_get_firmware_version_output_get_version (output, &str, NULL); + + g_task_return_pointer (task, + create_update_settings (g_task_get_source_object (task), str), + g_object_unref); + g_object_unref (task); +} + +static void +fox_get_firmware_version_ready (QmiClientFox *client, + GAsyncResult *res, + GTask *task) +{ + g_autoptr(QmiMessageFoxGetFirmwareVersionOutput) output = NULL; + GError *error = NULL; + const gchar *str; + + output = qmi_client_fox_get_firmware_version_finish (client, res, &error); + if (!output || !qmi_message_fox_get_firmware_version_output_get_result (output, &error)) { + g_task_return_error (task, error); + g_object_unref (task); + return; + } + + qmi_message_fox_get_firmware_version_output_get_version (output, &str, NULL); + + g_task_return_pointer (task, + create_update_settings (g_task_get_source_object (task), str), + g_object_unref); + g_object_unref (task); +} + +static void +mbim_port_allocate_qmi_client_ready (MMPortMbim *mbim, + GAsyncResult *res, + GTask *task) +{ + MMIfaceModemFirmware *self; + QmiClient *fox_client = NULL; + QmiClient *dms_client = NULL; + g_autoptr(GError) error = NULL; + + self = g_task_get_source_object (task); + + if (!mm_port_mbim_allocate_qmi_client_finish (mbim, res, &error)) + mm_obj_dbg (self, "Allocate FOX client failed: %s", error->message); + + /* Try to get firmware version over fox service, if it failed to peek client, try dms service. */ + fox_client = mm_shared_qmi_peek_client (MM_SHARED_QMI (self), QMI_SERVICE_FOX, MM_PORT_QMI_FLAG_DEFAULT, NULL); + if (!fox_client) { + dms_client = mm_shared_qmi_peek_client (MM_SHARED_QMI (self), QMI_SERVICE_DMS, MM_PORT_QMI_FLAG_DEFAULT, NULL); + if (!dms_client) { + g_task_return_new_error (task, MM_CORE_ERROR, MM_CORE_ERROR_FAILED, + "Unable to load version info: no FOX or DMS client available"); + g_object_unref (task); + return; + } + } + + if (fox_client) { + g_autoptr(QmiMessageFoxGetFirmwareVersionInput) input = NULL; + + input = qmi_message_fox_get_firmware_version_input_new (); + qmi_message_fox_get_firmware_version_input_set_version_type (input, + (needs_qdu_and_mcfg_apps_version (self) ? + QMI_FOX_FIRMWARE_VERSION_TYPE_FIRMWARE_MCFG_APPS : + QMI_FOX_FIRMWARE_VERSION_TYPE_FIRMWARE_MCFG), + NULL); + qmi_client_fox_get_firmware_version (QMI_CLIENT_FOX (fox_client), + input, + 10, + NULL, + (GAsyncReadyCallback)fox_get_firmware_version_ready, + task); + return; + } + + if (dms_client) { + g_autoptr(QmiMessageDmsFoxconnGetFirmwareVersionInput) input = NULL; + + input = qmi_message_dms_foxconn_get_firmware_version_input_new (); + qmi_message_dms_foxconn_get_firmware_version_input_set_version_type (input, + ((needs_qdu_and_mcfg_apps_version (self) || needs_fastboot_and_qmi_pdc_mcfg_apps_version (self)) ? + QMI_DMS_FOXCONN_FIRMWARE_VERSION_TYPE_FIRMWARE_MCFG_APPS: + QMI_DMS_FOXCONN_FIRMWARE_VERSION_TYPE_FIRMWARE_MCFG), + NULL); + qmi_client_dms_foxconn_get_firmware_version (QMI_CLIENT_DMS (dms_client), + input, + 10, + NULL, + (GAsyncReadyCallback)dms_foxconn_get_firmware_version_ready, + task); + return; + } + + g_assert_not_reached (); +} + +static void +firmware_load_update_settings (MMIfaceModemFirmware *self, + GAsyncReadyCallback callback, + gpointer user_data) +{ + GTask *task; + MMPortMbim *mbim; + + task = g_task_new (self, NULL, callback, user_data); + + mbim = mm_broadband_modem_mbim_peek_port_mbim (MM_BROADBAND_MODEM_MBIM (self)); + mm_port_mbim_allocate_qmi_client (mbim, + QMI_SERVICE_FOX, + NULL, + (GAsyncReadyCallback)mbim_port_allocate_qmi_client_ready, + task); +} + +#endif + +/*****************************************************************************/ +/* Location capabilities loading (Location interface) */ + +static MMModemLocationSource +location_load_capabilities_finish (MMIfaceModemLocation *self, + GAsyncResult *res, + GError **error) +{ + GError *inner_error = NULL; + gssize value; + + value = g_task_propagate_int (G_TASK (res), &inner_error); + if (inner_error) { + g_propagate_error (error, inner_error); + return MM_MODEM_LOCATION_SOURCE_NONE; + } + return (MMModemLocationSource)value; +} + +static void +custom_location_load_capabilities (GTask *task, + MMModemLocationSource sources) +{ + MMBroadbandModemMbimFoxconn *self; + + self = g_task_get_source_object (task); + + /* If we have a GPS port and an AT port, enable unmanaged GPS support */ + if (mm_base_modem_peek_port_primary (MM_BASE_MODEM (self)) && + mm_base_modem_peek_port_gps (MM_BASE_MODEM (self))) { + self->priv->unmanaged_gps_support = FEATURE_SUPPORTED; + sources |= MM_MODEM_LOCATION_SOURCE_GPS_UNMANAGED; + } + + /* So we're done, complete */ + g_task_return_int (task, sources); + g_object_unref (task); +} + +static void +parent_load_capabilities_ready (MMIfaceModemLocation *self, + GAsyncResult *res, + GTask *task) +{ + MMModemLocationSource sources; + GError *error = NULL; + + sources = iface_modem_location_parent->load_capabilities_finish (self, res, &error); + if (error) { + g_task_return_error (task, error); + g_object_unref (task); + return; + } + + custom_location_load_capabilities (task, sources); +} + +static void +location_load_capabilities (MMIfaceModemLocation *self, + GAsyncReadyCallback callback, + gpointer user_data) +{ + GTask *task; + + task = g_task_new (self, NULL, callback, user_data); + + /* Chain up parent's setup, if any. If MM is built without QMI support, + * the MBIM modem won't have any location capabilities. */ + if (iface_modem_location_parent && + iface_modem_location_parent->load_capabilities && + iface_modem_location_parent->load_capabilities_finish) { + iface_modem_location_parent->load_capabilities (self, + (GAsyncReadyCallback)parent_load_capabilities_ready, + task); + return; + } + + custom_location_load_capabilities (task, MM_MODEM_LOCATION_SOURCE_NONE); +} + +/*****************************************************************************/ +/* Disable location gathering (Location interface) */ + +static gboolean +disable_location_gathering_finish (MMIfaceModemLocation *self, + GAsyncResult *res, + GError **error) +{ + return g_task_propagate_boolean (G_TASK (res), error); +} + +static void +parent_disable_location_gathering_ready (MMIfaceModemLocation *self, + GAsyncResult *res, + GTask *task) +{ + GError *error = NULL; + + if (!iface_modem_location_parent->disable_location_gathering_finish (self, res, &error)) + g_task_return_error (task, error); + else + g_task_return_boolean (task, TRUE); + g_object_unref (task); +} + +static void +parent_disable_location_gathering (GTask *task) +{ + MMIfaceModemLocation *self; + MMModemLocationSource source; + + self = MM_IFACE_MODEM_LOCATION (g_task_get_source_object (task)); + source = GPOINTER_TO_UINT (g_task_get_task_data (task)); + + if (iface_modem_location_parent && + iface_modem_location_parent->disable_location_gathering && + iface_modem_location_parent->disable_location_gathering_finish) { + iface_modem_location_parent->disable_location_gathering ( + self, + source, + (GAsyncReadyCallback)parent_disable_location_gathering_ready, + task); + return; + } + + g_task_return_boolean (task, TRUE); + g_object_unref (task); +} + +static void +unmanaged_gps_disabled_ready (MMBaseModem *self, + GAsyncResult *res, + GTask *task) +{ + GError *error = NULL; + + if (!mm_base_modem_at_command_finish (self, res, &error)) { + g_task_return_error (task, error); + g_object_unref (task); + return; + } + + parent_disable_location_gathering (task); +} + +static void +disable_location_gathering (MMIfaceModemLocation *_self, + MMModemLocationSource source, + GAsyncReadyCallback callback, + gpointer user_data) +{ + MMBroadbandModemMbimFoxconn *self = MM_BROADBAND_MODEM_MBIM_FOXCONN (_self); + GTask *task; + + task = g_task_new (self, NULL, callback, user_data); + g_task_set_task_data (task, GUINT_TO_POINTER (source), NULL); + + /* We only support Unmanaged GPS at this level */ + if ((self->priv->unmanaged_gps_support != FEATURE_SUPPORTED) || + (source != MM_MODEM_LOCATION_SOURCE_GPS_UNMANAGED)) { + parent_disable_location_gathering (task); + return; + } + + mm_base_modem_at_command (MM_BASE_MODEM (_self), + "^NV=30007,01,\"00\"", + 3, + FALSE, + (GAsyncReadyCallback)unmanaged_gps_disabled_ready, + task); +} + +/*****************************************************************************/ +/* Enable location gathering (Location interface) */ + +static gboolean +enable_location_gathering_finish (MMIfaceModemLocation *self, + GAsyncResult *res, + GError **error) +{ + return g_task_propagate_boolean (G_TASK (res), error); +} + +static void +unmanaged_gps_enabled_ready (MMBaseModem *self, + GAsyncResult *res, + GTask *task) +{ + GError *error = NULL; + + if (!mm_base_modem_at_command_finish (self, res, &error)) + g_task_return_error (task, error); + else + g_task_return_boolean (task, TRUE); + g_object_unref (task); +} + +static void +custom_enable_location_gathering (GTask *task) +{ + MMBroadbandModemMbimFoxconn *self; + MMModemLocationSource source; + + self = g_task_get_source_object (task); + source = GPOINTER_TO_UINT (g_task_get_task_data (task)); + + /* We only support Unmanaged GPS at this level */ + if ((self->priv->unmanaged_gps_support != FEATURE_SUPPORTED) || + (source != MM_MODEM_LOCATION_SOURCE_GPS_UNMANAGED)) { + g_task_return_boolean (task, TRUE); + g_object_unref (task); + return; + } + + mm_base_modem_at_command (MM_BASE_MODEM (self), + "^NV=30007,01,\"01\"", + 3, + FALSE, + (GAsyncReadyCallback)unmanaged_gps_enabled_ready, + task); +} + +static void +parent_enable_location_gathering_ready (MMIfaceModemLocation *self, + GAsyncResult *res, + GTask *task) +{ + GError *error = NULL; + + if (!iface_modem_location_parent->enable_location_gathering_finish (self, res, &error)) { + g_task_return_error (task, error); + g_object_unref (task); + return; + } + + custom_enable_location_gathering (task); +} + +static void +enable_location_gathering (MMIfaceModemLocation *self, + MMModemLocationSource source, + GAsyncReadyCallback callback, + gpointer user_data) +{ + GTask *task; + + task = g_task_new (self, NULL, callback, user_data); + g_task_set_task_data (task, GUINT_TO_POINTER (source), NULL); + + /* Chain up parent's gathering enable */ + if (iface_modem_location_parent && + iface_modem_location_parent->enable_location_gathering && + iface_modem_location_parent->enable_location_gathering_finish) { + iface_modem_location_parent->enable_location_gathering ( + self, + source, + (GAsyncReadyCallback)parent_enable_location_gathering_ready, + task); + return; + } + + custom_enable_location_gathering (task); +} + +/*****************************************************************************/ + +MMBroadbandModemMbimFoxconn * +mm_broadband_modem_mbim_foxconn_new (const gchar *device, + const gchar **drivers, + const gchar *plugin, + guint16 vendor_id, + guint16 product_id) +{ + const gchar *carrier_config_mapping = NULL; + + /* T77W968 (DW5821e/DW5829e is also T77W968) modules use t77w968 carrier mapping table. */ + if ((vendor_id == 0x0489 && (product_id == 0xe0b4 || product_id == 0xe0b5)) || + (vendor_id == 0x413c && (product_id == 0x81d7 || product_id == 0x81e0 || product_id == 0x81e4 || product_id == 0x81e6))) + carrier_config_mapping = PKGDATADIR "/mm-foxconn-t77w968-carrier-mapping.conf"; + + return g_object_new (MM_TYPE_BROADBAND_MODEM_MBIM_FOXCONN, + MM_BASE_MODEM_DEVICE, device, + MM_BASE_MODEM_DRIVERS, drivers, + MM_BASE_MODEM_PLUGIN, plugin, + MM_BASE_MODEM_VENDOR_ID, vendor_id, + MM_BASE_MODEM_PRODUCT_ID, product_id, + /* MBIM bearer supports NET only */ + MM_BASE_MODEM_DATA_NET_SUPPORTED, TRUE, + MM_BASE_MODEM_DATA_TTY_SUPPORTED, FALSE, + MM_IFACE_MODEM_SIM_HOT_SWAP_SUPPORTED, TRUE, + MM_IFACE_MODEM_PERIODIC_SIGNAL_CHECK_DISABLED, TRUE, + MM_IFACE_MODEM_LOCATION_ALLOW_GPS_UNMANAGED_ALWAYS, TRUE, + MM_IFACE_MODEM_CARRIER_CONFIG_MAPPING, carrier_config_mapping, + NULL); +} + +static void +mm_broadband_modem_mbim_foxconn_init (MMBroadbandModemMbimFoxconn *self) +{ + /* Initialize private data */ + self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, MM_TYPE_BROADBAND_MODEM_MBIM_FOXCONN, MMBroadbandModemMbimFoxconnPrivate); + self->priv->unmanaged_gps_support = FEATURE_SUPPORT_UNKNOWN; +} + +static void +iface_modem_location_init (MMIfaceModemLocation *iface) +{ + iface_modem_location_parent = g_type_interface_peek_parent (iface); + + iface->load_capabilities = location_load_capabilities; + iface->load_capabilities_finish = location_load_capabilities_finish; + iface->enable_location_gathering = enable_location_gathering; + iface->enable_location_gathering_finish = enable_location_gathering_finish; + iface->disable_location_gathering = disable_location_gathering; + iface->disable_location_gathering_finish = disable_location_gathering_finish; +} + +#if defined WITH_QMI && QMI_MBIM_QMUX_SUPPORTED + +static void +iface_modem_firmware_init (MMIfaceModemFirmware *iface) +{ + iface->load_update_settings = firmware_load_update_settings; + iface->load_update_settings_finish = firmware_load_update_settings_finish; +} + +#endif + +static void +mm_broadband_modem_mbim_foxconn_class_init (MMBroadbandModemMbimFoxconnClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + g_type_class_add_private (object_class, sizeof (MMBroadbandModemMbimFoxconnPrivate)); +} diff --git a/src/plugins/foxconn/mm-broadband-modem-mbim-foxconn.h b/src/plugins/foxconn/mm-broadband-modem-mbim-foxconn.h new file mode 100644 index 00000000..374599e4 --- /dev/null +++ b/src/plugins/foxconn/mm-broadband-modem-mbim-foxconn.h @@ -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) 2018-2019 Aleksander Morgado <aleksander@aleksander.es> + */ + +#ifndef MM_BROADBAND_MODEM_MBIM_FOXCONN_H +#define MM_BROADBAND_MODEM_MBIM_FOXCONN_H + +#include "mm-broadband-modem-mbim.h" + +#define MM_TYPE_BROADBAND_MODEM_MBIM_FOXCONN (mm_broadband_modem_mbim_foxconn_get_type ()) +#define MM_BROADBAND_MODEM_MBIM_FOXCONN(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MM_TYPE_BROADBAND_MODEM_MBIM_FOXCONN, MMBroadbandModemMbimFoxconn)) +#define MM_BROADBAND_MODEM_MBIM_FOXCONN_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), MM_TYPE_BROADBAND_MODEM_MBIM_FOXCONN, MMBroadbandModemMbimFoxconnClass)) +#define MM_IS_BROADBAND_MODEM_MBIM_FOXCONN(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MM_TYPE_BROADBAND_MODEM_MBIM_FOXCONN)) +#define MM_IS_BROADBAND_MODEM_MBIM_FOXCONN_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), MM_TYPE_BROADBAND_MODEM_MBIM_FOXCONN)) +#define MM_BROADBAND_MODEM_MBIM_FOXCONN_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), MM_TYPE_BROADBAND_MODEM_MBIM_FOXCONN, MMBroadbandModemMbimFoxconnClass)) + +typedef struct _MMBroadbandModemMbimFoxconn MMBroadbandModemMbimFoxconn; +typedef struct _MMBroadbandModemMbimFoxconnClass MMBroadbandModemMbimFoxconnClass; +typedef struct _MMBroadbandModemMbimFoxconnPrivate MMBroadbandModemMbimFoxconnPrivate; + +struct _MMBroadbandModemMbimFoxconn { + MMBroadbandModemMbim parent; + MMBroadbandModemMbimFoxconnPrivate *priv; +}; + +struct _MMBroadbandModemMbimFoxconnClass{ + MMBroadbandModemMbimClass parent; +}; + +GType mm_broadband_modem_mbim_foxconn_get_type (void); + +MMBroadbandModemMbimFoxconn *mm_broadband_modem_mbim_foxconn_new (const gchar *device, + const gchar **driver, + const gchar *plugin, + guint16 vendor_id, + guint16 product_id); + +#endif /* MM_BROADBAND_MODEM_MBIM_FOXCONN_H */ diff --git a/src/plugins/foxconn/mm-foxconn-t77w968-carrier-mapping.conf b/src/plugins/foxconn/mm-foxconn-t77w968-carrier-mapping.conf new file mode 100644 index 00000000..79b12c1e --- /dev/null +++ b/src/plugins/foxconn/mm-foxconn-t77w968-carrier-mapping.conf @@ -0,0 +1,319 @@ + +# +# T77W968 carrier mapping table +# +# This table maps the MCCMNC of the SIM card with the corresponding +# configuration description as reported by the QMI PDC service in +# this module. +# + +[foxconn t77w968] + +# AT&T +302220=ATT +302221=ATT +31030=ATT +31070=ATT +31090=ATT +310150=ATT +310170=ATT +310280=ATT +310380=ATT +310410=ATT +310560=ATT +310650=ATT +310680=ATT +310980=ATT +311180=ATT +90118=ATT + +# FirstNet +312670=A2 +313100=A2 +313110=A2 +313120=A2 +313130=A2 +313140=A2 + +# Verizon +310590=Verizon +310890=Verizon +311270=Verizon +311480=Verizon +312770=Verizon + +# Vodafone +20205=Vodafone +20404=Vodafone +20601=Vodafone +20810=Vodafone +21401=Vodafone +21670=Vodafone +21910=Vodafone +22005=Vodafone +22210=Vodafone +22601=Vodafone +23003=Vodafone +23201=Vodafone +23415=Vodafone +23801=Vodafone +24405=Vodafone +24602=Vodafone +24705=Vodafone +24802=Vodafone +25001=Vodafone +26202=Vodafone +26209=Vodafone +26801=Vodafone +27077=Vodafone +27201=Vodafone +27402=Vodafone +27602=Vodafone +27801=Vodafone +28001=Vodafone +28401=Vodafone +28602=Vodafone +28802=Vodafone +29340=Vodafone +29403=Vodafone +40004=Vodafone +40401=Vodafone +40405=Vodafone +40411=Vodafone +40413=Vodafone +40415=Vodafone +40420=Vodafone +40427=Vodafone +40430=Vodafone +40443=Vodafone +40446=Vodafone +40460=Vodafone +40484=Vodafone +40486=Vodafone +40488=Vodafone +40566=Vodafone +40567=Vodafone +405750=Vodafone +405751=Vodafone +405752=Vodafone +405753=Vodafone +405754=Vodafone +405755=Vodafone +405756=Vodafone +41302=Vodafone +42403=Vodafone +42602=Vodafone +42702=Vodafone +46601=Vodafone +46603=Vodafone +50213=Vodafone +50219=Vodafone +50503=Vodafone +52503=Vodafone +52505=Vodafone +53001=Vodafone +54201=Vodafone +60202=Vodafone +62002=Vodafone +63001=Vodafone +63902=Vodafone +64004=Vodafone +64304=Vodafone +64710=Vodafone +65101=Vodafone +65501=Vodafone +73001=Vodafone +90128=Vodafone + +# Orange +20610=Orange +20801=Orange +20802=Orange +21403=Orange +21409=Orange +22610=Orange +23101=Orange +23105=Orange +23430=Orange +23433=Orange +23434=Orange +25901=Orange +26003=Orange +26005=Orange +27099=Orange +28310=Orange + +# Telefonica Movistar +21405=Telefonica +21407=Telefonica + +# Swisscom +22801=Swisscom +29501=Swisscom + +# Telstra +50501=Telstra +50506=Telstra +50571=Telstra +50572=Telstra + +# Sprint +310120=Sprint + +# Optus +50202=Optus + +# NTT DoCoMo +44002=Docomo +44003=Docomo +44009=Docomo +44010=Docomo +44011=Docomo +44012=Docomo +44013=Docomo +44014=Docomo +44015=Docomo +44016=Docomo +44017=Docomo +44018=Docomo +44019=Docomo +44022=Docomo +44023=Docomo +44024=Docomo +44025=Docomo +44026=Docomo +44027=Docomo +44028=Docomo +44029=Docomo +44030=Docomo +44031=Docomo +44032=Docomo +44033=Docomo +44034=Docomo +44035=Docomo +44036=Docomo +44037=Docomo +44038=Docomo +44039=Docomo +44049=Docomo +44058=Docomo +44060=Docomo +44061=Docomo +44062=Docomo +44063=Docomo +44064=Docomo +44065=Docomo +44066=Docomo +44067=Docomo +44068=Docomo +44069=Docomo +44087=Docomo +44099=Docomo +44140=Docomo +44141=Docomo +44142=Docomo +44143=Docomo +44144=Docomo +44145=Docomo +44190=Docomo +44101=Docomo +44192=Docomo +44193=Docomo +44194=Docomo +44198=Docomo +44199=Docomo + +# KDDI +44007=KDDI +44008=KDDI +44050=KDDI +44051=KDDI +44052=KDDI +44053=KDDI +44054=KDDI +44055=KDDI +44056=KDDI +44070=KDDI +44071=KDDI +44072=KDDI +44073=KDDI +44074=KDDI +44075=KDDI +44076=KDDI +44077=KDDI +44078=KDDI +44079=KDDI +44080=KDDI +44081=KDDI +44082=KDDI +44083=KDDI +44084=KDDI +44085=KDDI +44086=KDDI +44088=KDDI +44089=KDDI +44150=KDDI +44151=KDDI +44170=KDDI + +# SoftBank +44000=SBM +44004=SBM +44006=SBM +44020=SBM +44021=SBM +44040=SBM +44041=SBM +44042=SBM +44043=SBM +44044=SBM +44045=SBM +44046=SBM +44047=SBM +44048=SBM +44090=SBM +44092=SBM +44093=SBM +44094=SBM +44095=SBM +44096=SBM +44097=SBM +44098=SBM +44101=SBM +44161=SBM +44162=SBM +44163=SBM +44164=SBM +44165=SBM + +# EE UK +23430=EE +23431=EE +23432=EE +23433=EE +23434=EE +23476=EE +23501=EE +23502=EE +23577=EE + +# Deutsche Telekom +20201=DT +20416=DT +20420=DT +21630=DT +21901=DT +22603=DT +22606=DT +23001=DT +23102=DT +23203=DT +23207=DT +26002=DT +26201=DT +27601=DT +29401=DT +29702=DT + +# Others +generic=GCF diff --git a/src/plugins/foxconn/mm-plugin-foxconn.c b/src/plugins/foxconn/mm-plugin-foxconn.c new file mode 100644 index 00000000..d248fb05 --- /dev/null +++ b/src/plugins/foxconn/mm-plugin-foxconn.c @@ -0,0 +1,121 @@ +/* -*- 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. + * + * You should have received a copy of the GNU General Public + * License along with this program; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + * Copyright (C) 2019 Aleksander Morgado <aleksander@aleksander.es> + */ + +#include <string.h> +#include <gmodule.h> + +#define _LIBMM_INSIDE_MM +#include <libmm-glib.h> + +#include "mm-plugin-foxconn.h" +#include "mm-log-object.h" +#include "mm-broadband-modem.h" + +#if defined WITH_QMI +#include "mm-broadband-modem-qmi.h" +#endif + +#if defined WITH_MBIM +#include "mm-broadband-modem-mbim-foxconn.h" +#endif + +G_DEFINE_TYPE (MMPluginFoxconn, mm_plugin_foxconn, MM_TYPE_PLUGIN) + +MM_PLUGIN_DEFINE_MAJOR_VERSION +MM_PLUGIN_DEFINE_MINOR_VERSION + +/*****************************************************************************/ + +static MMBaseModem * +create_modem (MMPlugin *self, + const gchar *uid, + const gchar **drivers, + guint16 vendor, + guint16 product, + guint16 subsystem_vendor, + GList *probes, + GError **error) +{ +#if defined WITH_QMI + if (mm_port_probe_list_has_qmi_port (probes)) { + mm_obj_dbg (self, "QMI-powered Foxconn-branded modem found..."); + return MM_BASE_MODEM (mm_broadband_modem_qmi_new (uid, + drivers, + mm_plugin_get_name (self), + vendor, + product)); + } +#endif + +#if defined WITH_MBIM + if (mm_port_probe_list_has_mbim_port (probes)) { + mm_obj_dbg (self, "MBIM-powered Foxconn-branded modem found..."); + return MM_BASE_MODEM (mm_broadband_modem_mbim_foxconn_new (uid, + drivers, + mm_plugin_get_name (self), + vendor, + product)); + } +#endif + + mm_obj_dbg (self, "Foxconn-branded generic modem found..."); + return MM_BASE_MODEM (mm_broadband_modem_new (uid, + drivers, + mm_plugin_get_name (self), + vendor, + product)); +} + +/*****************************************************************************/ + +G_MODULE_EXPORT MMPlugin * +mm_plugin_create (void) +{ + static const gchar *subsystems[] = { "tty", "net", "usbmisc", "wwan", NULL }; + static const guint16 vendor_ids[] = { + 0x0489, /* usb vid */ + 0x105b, /* pci vid */ + 0 }; + + return MM_PLUGIN ( + g_object_new (MM_TYPE_PLUGIN_FOXCONN, + MM_PLUGIN_NAME, MM_MODULE_NAME, + MM_PLUGIN_ALLOWED_SUBSYSTEMS, subsystems, + MM_PLUGIN_ALLOWED_VENDOR_IDS, vendor_ids, + MM_PLUGIN_ALLOWED_AT, TRUE, + MM_PLUGIN_ALLOWED_QCDM, TRUE, + MM_PLUGIN_ALLOWED_QMI, TRUE, + MM_PLUGIN_ALLOWED_MBIM, TRUE, + NULL)); +} + +static void +mm_plugin_foxconn_init (MMPluginFoxconn *self) +{ +} + +static void +mm_plugin_foxconn_class_init (MMPluginFoxconnClass *klass) +{ + MMPluginClass *plugin_class = MM_PLUGIN_CLASS (klass); + + plugin_class->create_modem = create_modem; +} diff --git a/src/plugins/foxconn/mm-plugin-foxconn.h b/src/plugins/foxconn/mm-plugin-foxconn.h new file mode 100644 index 00000000..4a22ceeb --- /dev/null +++ b/src/plugins/foxconn/mm-plugin-foxconn.h @@ -0,0 +1,46 @@ +/* -*- 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. + * + * You should have received a copy of the GNU General Public + * License along with this program; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + * Copyright (C) 2019 Aleksander Morgado <aleksander@aleksander.es> + */ + +#ifndef MM_PLUGIN_FOXCONN_H +#define MM_PLUGIN_FOXCONN_H + +#include "mm-plugin.h" + +#define MM_TYPE_PLUGIN_FOXCONN (mm_plugin_foxconn_get_type ()) +#define MM_PLUGIN_FOXCONN(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MM_TYPE_PLUGIN_FOXCONN, MMPluginFoxconn)) +#define MM_PLUGIN_FOXCONN_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), MM_TYPE_PLUGIN_FOXCONN, MMPluginFoxconnClass)) +#define MM_IS_PLUGIN_FOXCONN(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MM_TYPE_PLUGIN_FOXCONN)) +#define MM_IS_PLUGIN_FOXCONN_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), MM_TYPE_PLUGIN_FOXCONN)) +#define MM_PLUGIN_FOXCONN_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), MM_TYPE_PLUGIN_FOXCONN, MMPluginFoxconnClass)) + +typedef struct { + MMPlugin parent; +} MMPluginFoxconn; + +typedef struct { + MMPluginClass parent; +} MMPluginFoxconnClass; + +GType mm_plugin_foxconn_get_type (void); + +G_MODULE_EXPORT MMPlugin *mm_plugin_create (void); + +#endif /* MM_PLUGIN_FOXCONN_H */ diff --git a/src/plugins/foxconn/mm-shared.c b/src/plugins/foxconn/mm-shared.c new file mode 100644 index 00000000..3b017574 --- /dev/null +++ b/src/plugins/foxconn/mm-shared.c @@ -0,0 +1,20 @@ +/* -*- 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) 2019 Aleksander Morgado <aleksander@aleksander.es> + */ + +#include "mm-shared.h" + +MM_SHARED_DEFINE_MAJOR_VERSION +MM_SHARED_DEFINE_MINOR_VERSION +MM_SHARED_DEFINE_NAME(Foxconn) |