cinterion: add hardware revision read via AT for MV31 and MV32

Reading the hardware revision via the mbim interface returns an incorrect
hardware revision string. The output is always set to
'h/w revision: Thales Snapdragon X55'

  Hardware |            manufacturer: Cinterion
...
           |            h/w revision: Thales Snapdragon X55

This is an incorrect value returned by the MBIM interface. The MV31 and MV32
does have a dedicated AT Command to get the correct hardware revision
via 'AT+SKUID'. If the hardware revision is read via the AT command, the
output looks as follows.

  Hardware |            manufacturer: Cinterion
...
           |            h/w revision: V065

Signed-off-by: Florian Eckert <fe@dev.tdt.de>
This commit is contained in:
Florian Eckert
2025-07-30 12:41:22 -05:00
committed by Dan Williams
parent a107de32a8
commit 5d4b0d3516
@@ -183,6 +183,125 @@ load_revision (MMIfaceModem *self,
iface_modem_parent->load_revision (self, (GAsyncReadyCallback)mbim_load_revision_ready, task);
}
/*****************************************************************************/
/* Load hardware revision (Modem interface) */
static gchar *
load_hardware_revision_finish (MMIfaceModem *self,
GAsyncResult *res,
GError **error)
{
return g_task_propagate_pointer (G_TASK (res), error);
}
static void
at_load_hardware_revision_ready (MMBaseModem *self,
GAsyncResult *res,
GTask *task)
{
GError *error = NULL;
const gchar *output = NULL;
g_autofree gchar *revision = NULL;
g_autoptr(GMatchInfo) match_info = NULL;
g_autoptr(GRegex) r = NULL;
output = mm_base_modem_at_command_finish (self, res, &error);
if (error) {
mm_obj_dbg (self, "unable to get AT hardware revision output");
g_task_return_error (task, error);
g_object_unref (task);
return;
}
r = g_regex_new ("HW Revision:\\s*(.*)\\s*", G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, NULL);
if (!g_regex_match_full (r, output, strlen(output), 0, 0, &match_info, &error)) {
if (error)
g_task_return_error (task, error);
else
g_task_return_new_error (task,
MM_CORE_ERROR,
MM_CORE_ERROR_FAILED,
"Couldn't match 'HW Revision:' in reply: '%s'",
output);
g_object_unref (task);
return;
}
if (!g_match_info_matches (match_info)) {
g_task_return_new_error (
task,
MM_CORE_ERROR,
MM_CORE_ERROR_FAILED,
"Failed to parse 'AT+SKUID' reply: '%s'",
output);
g_object_unref (task);
return;
}
revision = mm_get_string_unquoted_from_match_info (match_info, 1);
if (revision == NULL) {
g_task_return_new_error (
task,
MM_CORE_ERROR,
MM_CORE_ERROR_FAILED,
"Could not find hardware revision in reply: '%s'",
output);
g_object_unref (task);
return;
}
mm_obj_dbg (self, "got AT hardware revision '%s'", revision);
g_task_return_pointer (task, g_strdup (revision), g_free);
g_object_unref (task);
}
static void
mbim_load_hardware_revision_ready (MMIfaceModem *self,
GAsyncResult *res,
GTask *task)
{
gchar *revision = NULL;
revision = iface_modem_parent->load_revision_finish (self, res, NULL);
mm_obj_dbg (self, "got mbim hardware revision '%s'", revision);
g_task_return_pointer (task, revision, g_free);
g_object_unref (task);
}
static void
load_hardware_revision (MMIfaceModem *self,
GAsyncReadyCallback callback,
gpointer user_data)
{
GTask *task;
MMPortSerialAt *at_port = NULL;
guint product_id;
task = g_task_new (self, NULL, callback, user_data);
at_port = mm_base_modem_peek_port_primary (MM_BASE_MODEM (self));
product_id = mm_base_modem_get_product_id (MM_BASE_MODEM(self));
if (at_port) {
/* MV31 or MV32 */
if ((product_id == 0x00f1) || (product_id == 0x00b3)) {
mm_base_modem_at_command (MM_BASE_MODEM(self),
"AT+SKUID",
3,
TRUE,
(GAsyncReadyCallback) at_load_hardware_revision_ready,
task);
return;
}
}
/*
* Only call parent function, if no AT port is available
* or the product ID does not match
*/
iface_modem_parent->load_revision (self, (GAsyncReadyCallback)mbim_load_hardware_revision_ready, task);
}
/*****************************************************************************/
MMBroadbandModemMbimCinterion *
@@ -219,10 +338,12 @@ iface_modem_init (MMIfaceModemInterface *iface)
{
iface_modem_parent = g_type_interface_peek_parent (iface);
iface->reset = mm_shared_cinterion_modem_reset;
iface->reset_finish = mm_shared_cinterion_modem_reset_finish;
iface->load_revision_finish = load_revision_finish;
iface->load_revision = load_revision;
iface->reset = mm_shared_cinterion_modem_reset;
iface->reset_finish = mm_shared_cinterion_modem_reset_finish;
iface->load_revision_finish = load_revision_finish;
iface->load_revision = load_revision;
iface->load_hardware_revision_finish = load_hardware_revision_finish;
iface->load_hardware_revision = load_hardware_revision;
}
static MMIfaceModemInterface *