modem-manager: Copy the AT retry behaviour in ModemManager

Fixes https://github.com/fwupd/fwupd/issues/4319
This commit is contained in:
Richard Hughes 2022-02-22 10:24:39 +00:00
parent 6ec0646380
commit ccc897e574

View File

@ -32,6 +32,9 @@
* required (e.g. if switching from the default (DF) to generic (GC).*/ * required (e.g. if switching from the default (DF) to generic (GC).*/
#define FU_MM_DEVICE_REMOVE_DELAY_REPROBE 120000 /* ms */ #define FU_MM_DEVICE_REMOVE_DELAY_REPROBE 120000 /* ms */
#define FU_MM_DEVICE_AT_RETRIES 3
#define FU_MM_DEVICE_AT_DELAY 3000 /* ms */
/* Amount of time for the modem to get firmware version */ /* Amount of time for the modem to get firmware version */
#define MAX_WAIT_TIME_SECS 150 /* s */ #define MAX_WAIT_TIME_SECS 150 /* s */
@ -616,14 +619,21 @@ fu_mm_device_qcdm_cmd(FuMmDevice *self, const guint8 *cmd, gsize cmd_len, GError
} }
#endif /* MM_CHECK_VERSION(1,17,2) */ #endif /* MM_CHECK_VERSION(1,17,2) */
typedef struct {
const gchar *cmd;
gboolean has_response;
} FuMmDeviceAtCmdHelper;
static gboolean static gboolean
fu_mm_device_at_cmd(FuMmDevice *self, const gchar *cmd, gboolean has_response, GError **error) fu_mm_device_at_cmd_cb(FuDevice *device, gpointer user_data, GError **error)
{ {
FuMmDevice *self = FU_MM_DEVICE(device);
FuMmDeviceAtCmdHelper *helper = (FuMmDeviceAtCmdHelper *)user_data;
const gchar *buf; const gchar *buf;
gsize bufsz = 0; gsize bufsz = 0;
g_autoptr(GBytes) at_req = NULL; g_autoptr(GBytes) at_req = NULL;
g_autoptr(GBytes) at_res = NULL; g_autoptr(GBytes) at_res = NULL;
g_autofree gchar *cmd_cr = g_strdup_printf("%s\r\n", cmd); g_autofree gchar *cmd_cr = g_strdup_printf("%s\r\n", helper->cmd);
/* command */ /* command */
at_req = g_bytes_new(cmd_cr, strlen(cmd_cr)); at_req = g_bytes_new(cmd_cr, strlen(cmd_cr));
@ -634,13 +644,13 @@ fu_mm_device_at_cmd(FuMmDevice *self, const gchar *cmd, gboolean has_response, G
1500, 1500,
FU_IO_CHANNEL_FLAG_FLUSH_INPUT, FU_IO_CHANNEL_FLAG_FLUSH_INPUT,
error)) { error)) {
g_prefix_error(error, "failed to write %s: ", cmd); g_prefix_error(error, "failed to write %s: ", helper->cmd);
return FALSE; return FALSE;
} }
/* AT command has no response, return TRUE */ /* AT command has no response, return TRUE */
if (!has_response) { if (!helper->has_response) {
g_debug("No response expected for AT command: '%s', assuming succeed", cmd); g_debug("No response expected for AT command: '%s', assuming succeed", helper->cmd);
return TRUE; return TRUE;
} }
@ -651,7 +661,7 @@ fu_mm_device_at_cmd(FuMmDevice *self, const gchar *cmd, gboolean has_response, G
FU_IO_CHANNEL_FLAG_SINGLE_SHOT, FU_IO_CHANNEL_FLAG_SINGLE_SHOT,
error); error);
if (at_res == NULL) { if (at_res == NULL) {
g_prefix_error(error, "failed to read response for %s: ", cmd); g_prefix_error(error, "failed to read response for %s: ", helper->cmd);
return FALSE; return FALSE;
} }
if (g_getenv("FWUPD_MODEM_MANAGER_VERBOSE") != NULL) if (g_getenv("FWUPD_MODEM_MANAGER_VERBOSE") != NULL)
@ -662,7 +672,7 @@ fu_mm_device_at_cmd(FuMmDevice *self, const gchar *cmd, gboolean has_response, G
FWUPD_ERROR, FWUPD_ERROR,
FWUPD_ERROR_NOT_SUPPORTED, FWUPD_ERROR_NOT_SUPPORTED,
"failed to read valid response for %s", "failed to read valid response for %s",
cmd); helper->cmd);
return FALSE; return FALSE;
} }
@ -673,13 +683,13 @@ fu_mm_device_at_cmd(FuMmDevice *self, const gchar *cmd, gboolean has_response, G
FWUPD_ERROR, FWUPD_ERROR,
FWUPD_ERROR_NOT_SUPPORTED, FWUPD_ERROR_NOT_SUPPORTED,
"failed to read valid response for %s: %s", "failed to read valid response for %s: %s",
cmd, helper->cmd,
tmp); tmp);
return FALSE; return FALSE;
} }
/* set firmware branch if returned */ /* set firmware branch if returned */
if (self->branch_at != NULL && g_strcmp0(cmd, self->branch_at) == 0) { if (self->branch_at != NULL && g_strcmp0(helper->cmd, self->branch_at) == 0) {
/* /*
* example AT+GETFWBRANCH response: * example AT+GETFWBRANCH response:
* *
@ -700,9 +710,22 @@ fu_mm_device_at_cmd(FuMmDevice *self, const gchar *cmd, gboolean has_response, G
} }
} }
/* success */
return TRUE; return TRUE;
} }
static gboolean
fu_mm_device_at_cmd(FuMmDevice *self, const gchar *cmd, gboolean has_response, GError **error)
{
FuMmDeviceAtCmdHelper helper = {.cmd = cmd, .has_response = has_response};
return fu_device_retry_full(FU_DEVICE(self),
fu_mm_device_at_cmd_cb,
FU_MM_DEVICE_AT_RETRIES,
FU_MM_DEVICE_AT_DELAY,
&helper,
error);
}
static gboolean static gboolean
fu_mm_device_io_open(FuMmDevice *self, GError **error) fu_mm_device_io_open(FuMmDevice *self, GError **error)
{ {