port-qmi: support devices that only run in 802.3 mode

E.g. the ZTE MF190 has a very old QMI firmware that is not able to run
CTL Set Data Format (raw-ip).

   ModemManager[666366]: [/dev/cdc-wdm0] QMI Device supports 4 services:
   ModemManager[666366]: [/dev/cdc-wdm0]    ctl (1.2)
   ModemManager[666366]: [/dev/cdc-wdm0]    wds (1.3)
   ModemManager[666366]: [/dev/cdc-wdm0]    dms (1.2)
   ModemManager[666366]: [/dev/cdc-wdm0]    nas (1.0)
   ModemManager[666366]: [/dev/cdc-wdm0] Setting network port data format...
   ModemManager[666366]: [/dev/cdc-wdm0] Sent message...
   <<<<<< RAW:
   <<<<<<   length = 21
   <<<<<<   data   = 01:14:00:00:00:00:00:03:26:00:09:00:10:02:00:02:00:01:01:00:00
   ModemManager[666366]: [/dev/cdc-wdm0] Sent generic request (translated)...
   <<<<<< QMUX:
   <<<<<<   length  = 20
   <<<<<<   flags   = 0x00
   <<<<<<   service = "ctl"
   <<<<<<   client  = 0
   <<<<<< QMI:
   <<<<<<   flags       = "none"
   <<<<<<   transaction = 3
   <<<<<<   tlv_length  = 9
   <<<<<<   message     = "Set Data Format" (0x0026)
   <<<<<< TLV:
   <<<<<<   type       = "Protocol" (0x10)
   <<<<<<   length     = 2
   <<<<<<   value      = 02:00
   <<<<<<   translated = raw-ip
   <<<<<< TLV:
   <<<<<<   type       = "Format" (0x01)
   <<<<<<   length     = 1
   <<<<<<   value      = 00
   <<<<<<   translated = absent
   ModemManager[666366]: [/dev/cdc-wdm0] Received message...
   <<<<<< RAW:
   <<<<<<   length = 19
   <<<<<<   data   = 01:12:00:80:00:00:01:03:26:00:07:00:02:04:00:01:00:2D:00
   ModemManager[666366]: [/dev/cdc-wdm0] Received generic response (translated)...
   <<<<<< QMUX:
   <<<<<<   length  = 18
   <<<<<<   flags   = 0x80
   <<<<<<   service = "ctl"
   <<<<<<   client  = 0
   <<<<<< QMI:
   <<<<<<   flags       = "response"
   <<<<<<   transaction = 3
   <<<<<<   tlv_length  = 7
   <<<<<<   message     = "Set Data Format" (0x0026)
   <<<<<< TLV:
   <<<<<<   type       = "Result" (0x02)
   <<<<<<   length     = 4
   <<<<<<   value      = 01:00:2D:00
   <<<<<<   translated = FAILURE: InvalidDataFormat
   ModemManager[666366]: <debug> [1626961628.001354] [cdc-wdm0/qmi] QMI port open operation failed: QMI protocol error (45): 'InvalidDataFormat'
   ModemManager[666366]: <warn>  [1626961628.002563] [modem0] couldn't start initialization: QMI protocol error (45): 'InvalidDataFormat'
   ModemManager[666366]: <warn>  [1626961628.004181] [modem0] couldn't initialize: 'Modem is unusable, cannot fully initialize'
This commit is contained in:
Aleksander Morgado
2021-07-22 15:59:18 +02:00
parent 939cf166dd
commit 9be34affe2

View File

@@ -2118,6 +2118,7 @@ typedef struct {
PortOpenStep step;
gboolean set_data_format;
MMPortQmiKernelDataMode kernel_data_modes;
gboolean ctl_raw_ip_unsupported;
} PortOpenContext;
static void
@@ -2174,13 +2175,29 @@ qmi_device_open_second_ready (QmiDevice *qmi_device,
GAsyncResult *res,
GTask *task)
{
MMPortQmi *self;
PortOpenContext *ctx;
MMPortQmi *self;
PortOpenContext *ctx;
g_autoptr(GError) error = NULL;
self = g_task_get_source_object (task);
ctx = g_task_get_task_data (task);
if (qmi_device_open_finish (qmi_device, res, &ctx->error)) {
if (!qmi_device_open_finish (qmi_device, res, &error)) {
/* Not all devices support raw-ip, which is the first thing we try
* by default. Detect this case, and retry with 802.3 if so. */
if ((g_strcmp0 (self->priv->net_driver, "qmi_wwan") == 0) &&
g_error_matches (error, QMI_PROTOCOL_ERROR, QMI_PROTOCOL_ERROR_INVALID_DATA_FORMAT) &&
(ctx->kernel_data_modes & MM_PORT_QMI_KERNEL_DATA_MODE_RAW_IP)) {
/* switch to 802.3 right away, so that the logic can successfully go on after that */
qmi_device_set_expected_data_format (qmi_device, QMI_DEVICE_EXPECTED_DATA_FORMAT_802_3, NULL);
ctx->ctl_raw_ip_unsupported = TRUE;
port_open_step (task);
return;
}
/* Otherwise, fatal */
ctx->error = g_steal_pointer (&error);
} else {
/* If the open with CTL data format is sucessful, update all settings
* that we would have received with the internal setup data format
* process */
@@ -2415,6 +2432,10 @@ port_open_step (GTask *task)
ctx->kernel_data_modes = load_current_kernel_data_modes (self, ctx->device);
/* Skip trying raw-ip if we already tried and it failed */
if (ctx->ctl_raw_ip_unsupported)
ctx->kernel_data_modes &= ~MM_PORT_QMI_KERNEL_DATA_MODE_RAW_IP;
/* Need to reopen setting 802.3/raw-ip using CTL */
if (ctx->kernel_data_modes & MM_PORT_QMI_KERNEL_DATA_MODE_RAW_IP)
open_flags |= QMI_DEVICE_OPEN_FLAGS_NET_RAW_IP;