Skip to content

Commit 09d5c9f

Browse files
committed
modem-manager: Fix an enumeration regression in 9d908d1
We only want to set the port to raw mode if ModemManager is ignoring the port. Fixes a regression to enumerate the EM160R.
1 parent 063d281 commit 09d5c9f

File tree

4 files changed

+168
-84
lines changed

4 files changed

+168
-84
lines changed

plugins/modem-manager/README.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,16 @@ although it requires that the firmware branch is also set in the firmware metada
4343

4444
Since: 1.9.8
4545

46+
### `Flags=make-serial-raw`
47+
48+
When using a port that was not previously configured by ModemManager (an 'ignored' port), we need
49+
to configure the serial port manually.
50+
51+
This is automatically added for any ports being used from `mm_modem_get_ignored_ports()` and should
52+
not need to be added in quirk files.
53+
54+
Since: 2.0.14
55+
4656
### `Flags=detach-at-fastboot-has-no-response`
4757

4858
If no AT response is expected when entering fastboot mode.

plugins/modem-manager/fu-mm-device.c

Lines changed: 156 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,10 @@
66

77
#include "config.h"
88

9+
#ifdef HAVE_TERMIOS_H
10+
#include <termios.h>
11+
#endif
12+
913
#include "fu-mm-common.h"
1014
#include "fu-mm-device.h"
1115

@@ -20,11 +24,22 @@
2024
/* not strictly last, but the last we care about */
2125
#define MM_MODEM_PORT_TYPE_LAST (MM_MODEM_PORT_TYPE_IGNORED + 1)
2226

27+
typedef enum {
28+
FU_MM_DEVICE_PORT_FLAG_NONE = 0,
29+
FU_MM_DEVICE_PORT_FLAG_MAKE_RAW = 1 << 0,
30+
} FuMmDevicePortFlags;
31+
32+
typedef struct {
33+
MMModemPortType type;
34+
gchar *device_file;
35+
FuMmDevicePortFlags flags;
36+
} FuMmDevicePort;
37+
2338
typedef struct {
2439
gboolean inhibited;
2540
gchar *branch_at;
2641
gchar *inhibition_uid;
27-
gchar *port[MM_MODEM_PORT_TYPE_LAST];
42+
GPtrArray *ports; /* element-type FuMmDevicePort */
2843
} FuMmDevicePrivate;
2944

3045
G_DEFINE_TYPE_WITH_PRIVATE(FuMmDevice, fu_mm_device, FU_TYPE_UDEV_DEVICE);
@@ -37,6 +52,13 @@ G_DEFINE_TYPE_WITH_PRIVATE(FuMmDevice, fu_mm_device, FU_TYPE_UDEV_DEVICE);
3752

3853
enum { PROP_0, PROP_INHIBITED, PROP_LAST };
3954

55+
static void
56+
fu_mm_device_port_free(FuMmDevicePort *port)
57+
{
58+
g_free(port->device_file);
59+
g_free(port);
60+
}
61+
4062
static void
4163
fu_mm_device_set_branch_at(FuMmDevice *self, const gchar *branch_at)
4264
{
@@ -55,12 +77,11 @@ fu_mm_device_to_string(FuDevice *device, guint idt, GString *str)
5577
fwupd_codec_string_append(str, idt, "BranchAt", priv->branch_at);
5678
fwupd_codec_string_append_bool(str, idt, "Inhibited", priv->inhibited);
5779
fwupd_codec_string_append(str, idt, "InhibitionUid", priv->inhibition_uid);
58-
for (guint i = 0; i < MM_MODEM_PORT_TYPE_LAST; i++) {
59-
if (priv->port[i] != NULL) {
60-
g_autofree gchar *title =
61-
g_strdup_printf("Port[%s]", fu_mm_device_port_type_to_string(i));
62-
fwupd_codec_string_append(str, idt, title, priv->port[i]);
63-
}
80+
for (guint i = 0; i < priv->ports->len; i++) {
81+
FuMmDevicePort *port = g_ptr_array_index(priv->ports, i);
82+
g_autofree gchar *title =
83+
g_strdup_printf("Port[%s]", fu_mm_device_port_type_to_string(port->type));
84+
fwupd_codec_string_append(str, idt, title, port->device_file);
6485
}
6586
}
6687

@@ -96,17 +117,27 @@ fu_mm_device_set_device_file(FuMmDevice *self, MMModemPortType port_type, GError
96117
{
97118
FuMmDevicePrivate *priv = GET_PRIVATE(self);
98119
g_return_val_if_fail(FU_IS_MM_DEVICE(self), FALSE);
99-
g_return_val_if_fail(port_type < MM_MODEM_PORT_TYPE_LAST, FALSE);
100-
if (priv->port[port_type] == NULL) {
101-
g_set_error(error,
102-
FWUPD_ERROR,
103-
FWUPD_ERROR_NOT_SUPPORTED,
104-
"no port for %s",
105-
fu_mm_device_port_type_to_string(port_type));
106-
return FALSE;
120+
121+
/* find port by type */
122+
for (guint i = 0; i < priv->ports->len; i++) {
123+
FuMmDevicePort *port = g_ptr_array_index(priv->ports, i);
124+
if (port_type == port->type) {
125+
if (port->flags & FU_MM_DEVICE_PORT_FLAG_MAKE_RAW) {
126+
fu_device_add_private_flag(FU_DEVICE(self),
127+
FU_MM_DEVICE_FLAG_MAKE_SERIAL_RAW);
128+
}
129+
fu_udev_device_set_device_file(FU_UDEV_DEVICE(self), port->device_file);
130+
return TRUE;
131+
}
107132
}
108-
fu_udev_device_set_device_file(FU_UDEV_DEVICE(self), priv->port[port_type]);
109-
return TRUE;
133+
134+
/* not found */
135+
g_set_error(error,
136+
FWUPD_ERROR,
137+
FWUPD_ERROR_NOT_SUPPORTED,
138+
"no port for %s",
139+
fu_mm_device_port_type_to_string(port_type));
140+
return FALSE;
110141
}
111142

112143
static gboolean
@@ -310,14 +341,30 @@ fu_mm_device_add_instance_id(FuMmDevice *self, const gchar *device_id, GError **
310341
}
311342

312343
static void
313-
fu_mm_device_add_port(FuMmDevice *self, MMModemPortType port_type, const gchar *device_file)
344+
fu_mm_device_add_port(FuMmDevice *self,
345+
MMModemPortType port_type,
346+
const gchar *device_file,
347+
FuMmDevicePortFlags flags)
314348
{
315349
FuMmDevicePrivate *priv = GET_PRIVATE(self);
350+
FuMmDevicePort *port;
351+
316352
if (port_type >= MM_MODEM_PORT_TYPE_LAST)
317353
return;
318-
if (priv->port[port_type] != NULL)
319-
return;
320-
priv->port[port_type] = g_strdup(device_file);
354+
355+
/* already exists */
356+
for (guint i = 0; i < priv->ports->len; i++) {
357+
port = g_ptr_array_index(priv->ports, i);
358+
if (port->type == port_type)
359+
return;
360+
}
361+
362+
/* create new */
363+
port = g_new0(FuMmDevicePort, 1);
364+
port->type = port_type;
365+
port->flags = flags;
366+
port->device_file = g_strdup(device_file);
367+
g_ptr_array_add(priv->ports, port);
321368
}
322369

323370
gboolean
@@ -389,9 +436,15 @@ fu_mm_device_probe_from_omodem(FuMmDevice *self, MMObject *omodem, GError **erro
389436
continue;
390437
if (used_ports[i].type == MM_MODEM_PORT_TYPE_IGNORED &&
391438
g_pattern_match_simple("wwan*qcdm*", used_ports[i].name)) {
392-
fu_mm_device_add_port(self, MM_MODEM_PORT_TYPE_QCDM, device_file);
439+
fu_mm_device_add_port(self,
440+
MM_MODEM_PORT_TYPE_QCDM,
441+
device_file,
442+
FU_MM_DEVICE_PORT_FLAG_NONE);
393443
} else {
394-
fu_mm_device_add_port(self, used_ports[i].type, device_file);
444+
fu_mm_device_add_port(self,
445+
used_ports[i].type,
446+
device_file,
447+
FU_MM_DEVICE_PORT_FLAG_NONE);
395448
}
396449
}
397450
mm_modem_port_info_array_free(used_ports, n_used_ports);
@@ -408,8 +461,10 @@ fu_mm_device_probe_from_omodem(FuMmDevice *self, MMObject *omodem, GError **erro
408461
g_autofree gchar *device_file = g_strdup_printf("/dev/%s", ignored_ports[i].name);
409462
if (ignored_ports[i].type >= MM_MODEM_PORT_TYPE_LAST)
410463
continue;
411-
412-
fu_mm_device_add_port(self, ignored_ports[i].type, device_file);
464+
fu_mm_device_add_port(self,
465+
ignored_ports[i].type,
466+
device_file,
467+
FU_MM_DEVICE_PORT_FLAG_MAKE_RAW);
413468
}
414469
mm_modem_port_info_array_free(ignored_ports, n_ignored_ports);
415470
#endif // MM_CHECK_VERSION(1, 26, 0)
@@ -686,6 +741,70 @@ fu_mm_device_ensure_payload(FuMmDevice *self)
686741
}
687742
}
688743

744+
static gboolean
745+
fu_mm_device_make_serial_raw(FuMmDevice *self, GError **error)
746+
{
747+
#ifdef HAVE_TERMIOS_H
748+
gint fd = fu_io_channel_unix_get_fd(fu_udev_device_get_io_channel(FU_UDEV_DEVICE(self)));
749+
struct termios tio;
750+
751+
if (tcgetattr(fd, &tio) != 0) {
752+
g_set_error(error,
753+
FWUPD_ERROR,
754+
#ifdef HAVE_ERRNO_H
755+
g_io_error_from_errno(errno),
756+
#else
757+
G_IO_ERROR_FAILED, /* nocheck:blocked */
758+
#endif
759+
"could not get termios attributes: %s",
760+
fwupd_strerror(errno));
761+
return FALSE;
762+
}
763+
764+
cfmakeraw(&tio);
765+
766+
if (tcsetattr(fd, TCSANOW, &tio) != 0) {
767+
g_set_error(error,
768+
FWUPD_ERROR,
769+
#ifdef HAVE_ERRNO_H
770+
g_io_error_from_errno(errno),
771+
#else
772+
G_IO_ERROR_FAILED, /* nocheck:blocked */
773+
#endif
774+
"could not set termios attributes: %s",
775+
fwupd_strerror(errno));
776+
return FALSE;
777+
}
778+
779+
return TRUE;
780+
#else
781+
g_set_error_literal(error,
782+
FWUPD_ERROR,
783+
FWUPD_ERROR_NOT_SUPPORTED,
784+
"Not supported as <termios.h> not found");
785+
return FALSE;
786+
#endif
787+
}
788+
789+
static gboolean
790+
fu_mm_device_open(FuDevice *device, GError **error)
791+
{
792+
FuMmDevice *self = FU_MM_DEVICE(device);
793+
794+
/* FuUdevDevice->open() */
795+
if (!FU_DEVICE_CLASS(fu_mm_device_parent_class)->open(device, error))
796+
return FALSE;
797+
798+
/* ignored ports have not previously been configured by ModemManager */
799+
if (fu_device_has_private_flag(device, FU_MM_DEVICE_FLAG_MAKE_SERIAL_RAW)) {
800+
if (!fu_mm_device_make_serial_raw(self, error))
801+
return FALSE;
802+
}
803+
804+
/* success */
805+
return TRUE;
806+
}
807+
689808
static gboolean
690809
fu_mm_device_setup(FuDevice *device, GError **error)
691810
{
@@ -757,7 +876,8 @@ fu_mm_device_from_json(FuDevice *device, JsonObject *json_object, GError **error
757876
const gchar *port_type = l->data;
758877
fu_mm_device_add_port(self,
759878
fu_mm_device_port_type_from_string(port_type),
760-
json_object_get_string_member(json_ports, port_type));
879+
json_object_get_string_member(json_ports, port_type),
880+
FU_MM_DEVICE_PORT_FLAG_NONE);
761881
}
762882
}
763883

@@ -808,12 +928,11 @@ fu_mm_device_add_json(FuDevice *device, JsonBuilder *builder, FwupdCodecFlags fl
808928
/* ports always specified */
809929
json_builder_set_member_name(builder, "Ports");
810930
json_builder_begin_object(builder);
811-
for (guint i = 0; i < MM_MODEM_PORT_TYPE_LAST; i++) {
812-
if (priv->port[i] != NULL) {
813-
fwupd_codec_json_append(builder,
814-
fu_mm_device_port_type_to_string(i),
815-
priv->port[i]);
816-
}
931+
for (guint i = 0; i < priv->ports->len; i++) {
932+
FuMmDevicePort *port = g_ptr_array_index(priv->ports, i);
933+
fwupd_codec_json_append(builder,
934+
fu_mm_device_port_type_to_string(port->type),
935+
port->device_file);
817936
}
818937
json_builder_end_object(builder);
819938
}
@@ -850,6 +969,7 @@ fu_mm_device_set_property(GObject *object, guint prop_id, const GValue *value, G
850969
static void
851970
fu_mm_device_init(FuMmDevice *self)
852971
{
972+
FuMmDevicePrivate *priv = GET_PRIVATE(self);
853973
fu_device_add_flag(FU_DEVICE(self), FWUPD_DEVICE_FLAG_UPDATABLE);
854974
fu_device_add_flag(FU_DEVICE(self), FWUPD_DEVICE_FLAG_REQUIRE_AC);
855975
fu_device_set_firmware_gtype(FU_DEVICE(self), FU_TYPE_ARCHIVE_FIRMWARE);
@@ -862,9 +982,11 @@ fu_mm_device_init(FuMmDevice *self)
862982
fu_device_set_summary(FU_DEVICE(self), "Mobile broadband device");
863983
fu_device_add_icon(FU_DEVICE(self), FU_DEVICE_ICON_MODEM);
864984
fu_device_register_private_flag(FU_DEVICE(self), FU_MM_DEVICE_FLAG_USE_BRANCH);
985+
fu_device_register_private_flag(FU_DEVICE(self), FU_MM_DEVICE_FLAG_MAKE_SERIAL_RAW);
865986
fu_device_add_possible_plugin(FU_DEVICE(self), "modem_manager");
866987
fu_udev_device_add_open_flag(FU_UDEV_DEVICE(self), FU_IO_CHANNEL_OPEN_FLAG_READ);
867988
fu_udev_device_add_open_flag(FU_UDEV_DEVICE(self), FU_IO_CHANNEL_OPEN_FLAG_WRITE);
989+
priv->ports = g_ptr_array_new_with_free_func((GDestroyNotify)fu_mm_device_port_free);
868990
}
869991

870992
static void
@@ -873,10 +995,9 @@ fu_mm_device_finalize(GObject *object)
873995
FuMmDevice *self = FU_MM_DEVICE(object);
874996
FuMmDevicePrivate *priv = GET_PRIVATE(self);
875997

876-
for (guint i = 0; i < MM_MODEM_PORT_TYPE_LAST; i++)
877-
g_free(priv->port[i]);
878998
g_free(priv->branch_at);
879999
g_free(priv->inhibition_uid);
1000+
g_ptr_array_unref(priv->ports);
8801001

8811002
G_OBJECT_CLASS(fu_mm_device_parent_class)->finalize(object);
8821003
}
@@ -896,6 +1017,7 @@ fu_mm_device_class_init(FuMmDeviceClass *klass)
8961017
device_class->set_quirk_kv = fu_mm_device_set_quirk_kv;
8971018
device_class->from_json = fu_mm_device_from_json;
8981019
device_class->add_json = fu_mm_device_add_json;
1020+
device_class->open = fu_mm_device_open;
8991021

9001022
pspec = g_param_spec_boolean("inhibited",
9011023
NULL,

plugins/modem-manager/fu-mm-device.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@ G_DECLARE_DERIVABLE_TYPE(FuMmDevice, fu_mm_device, FU, MM_DEVICE, FuUdevDevice)
1515

1616
#define FU_MM_DEVICE_FLAG_USE_BRANCH "use-branch"
1717

18+
#define FU_MM_DEVICE_FLAG_MAKE_SERIAL_RAW "make-serial-raw"
19+
1820
/* less ifdefs */
1921
#if !MM_CHECK_VERSION(1, 24, 0)
2022
#define MM_MODEM_FIRMWARE_UPDATE_METHOD_DFOTA (1 << 5)

0 commit comments

Comments
 (0)