diff options
author | Steve Schrock <steve.schrock@getcruise.com> | 2024-04-08 16:34:38 -0500 |
---|---|---|
committer | Denis Kenzior <denkenz@gmail.com> | 2024-04-08 17:13:20 -0500 |
commit | 296347f8a4f1c5809b6dfa36472931ad1f7ab266 (patch) | |
tree | ec35524b6318faac5aff284251d956e722a44fb0 | |
parent | 6d4a89bbf07cf13d70009955ac613754259c754c (diff) | |
download | ofono-296347f8a4f1c5809b6dfa36472931ad1f7ab266.tar.gz |
udevng: Detect embedded qmi QRTR modems
Embedded qmi QRTR modems are identified by the existence of
rmnet_ipaX and rmnet_dataX devices. Add a new "embedded" modem type
so that these devices can be collected during enumeration and then
configured for use by the gobi plugin. Modems of this type will be
exposed as /gobiqrtr_X.
-rw-r--r-- | plugins/gobi.c | 19 | ||||
-rw-r--r-- | plugins/udevng.c | 105 |
2 files changed, 119 insertions, 5 deletions
diff --git a/plugins/gobi.c b/plugins/gobi.c index 7a07b080d..431df17e2 100644 --- a/plugins/gobi.c +++ b/plugins/gobi.c @@ -420,16 +420,27 @@ static void discover_cb(void *user_data) static int gobi_enable(struct ofono_modem *modem) { struct gobi_data *data = ofono_modem_get_data(modem); - const char *device; + const char *kernel_driver; int r; DBG("%p", modem); - device = ofono_modem_get_string(modem, "Device"); - if (!device) + kernel_driver = ofono_modem_get_string(modem, "KernelDriver"); + if (!kernel_driver) return -EINVAL; - data->device = qmi_device_new_qmux(device); + if (!strcmp(kernel_driver, "qrtr")) + data->device = qmi_device_new_qrtr(); + else { + const char *device; + + device = ofono_modem_get_string(modem, "Device"); + if (!device) + return -EINVAL; + + data->device = qmi_device_new_qmux(device); + } + if (!data->device) return -EIO; diff --git a/plugins/udevng.c b/plugins/udevng.c index 8bdcf0dbb..14ae2f392 100644 --- a/plugins/udevng.c +++ b/plugins/udevng.c @@ -43,6 +43,7 @@ enum modem_type { MODEM_TYPE_USB, MODEM_TYPE_SERIAL, MODEM_TYPE_PCIE, + MODEM_TYPE_EMBEDDED, }; struct modem_info { @@ -206,7 +207,10 @@ static int setup_qmi(struct modem_info *modem, const struct device_info *qmi, DBG("qmi: %s net: %s kernel_driver: %s interface_number: %s", qmi->devnode, net->devnode, net->kernel_driver, net->number); - if (!qmi->kernel_driver || !net->number) + if (!qmi->kernel_driver) + return -EINVAL; + + if (!net->number && modem->type != MODEM_TYPE_EMBEDDED) return -EINVAL; attr_value = udev_device_get_sysattr_value(net->udev_device, @@ -234,6 +238,9 @@ static int setup_qmi(struct modem_info *modem, const struct device_info *qmi, case MODEM_TYPE_PCIE: ofono_modem_set_string(modem->modem, "Bus", "pcie"); break; + case MODEM_TYPE_EMBEDDED: + ofono_modem_set_string(modem->modem, "Bus", "embedded"); + break; case MODEM_TYPE_SERIAL: break; } @@ -241,6 +248,75 @@ static int setup_qmi(struct modem_info *modem, const struct device_info *qmi, return 0; } +static gboolean setup_gobi_qrtr_premux(struct modem_info *modem, + const char *name, int premux_index) +{ + const char *rmnet_data_prefix = "rmnet_data"; + int rmnet_data_prefix_length = strlen(rmnet_data_prefix); + char buf[256]; + int r; + uint32_t data_id; + uint32_t mux_id; + + r = l_safe_atou32(name + rmnet_data_prefix_length, &data_id); + if (r < 0) + return FALSE; + + mux_id = data_id + 1; + + DBG("Adding premux interface %s, mux id: %d", name, mux_id); + sprintf(buf, "PremuxInterface%d", premux_index); + ofono_modem_set_string(modem->modem, buf, name); + sprintf(buf, "PremuxInterface%dMuxId", premux_index); + ofono_modem_set_integer(modem->modem, buf, mux_id); + + return TRUE; +} + +static gboolean setup_gobi_qrtr(struct modem_info *modem) +{ + const struct device_info *ipa_info = NULL; + int premux_count = 0; + int r; + GSList *list; + + DBG("%s", modem->syspath); + + for (list = modem->devices; list; list = list->next) { + struct device_info *info = list->data; + const char *name; + + name = udev_device_get_sysname(info->udev_device); + if (l_str_has_prefix(name, "rmnet_ipa")) + ipa_info = info; + else if (l_str_has_prefix(name, "rmnet_data")) { + int premux_index = premux_count + 1; + + if (setup_gobi_qrtr_premux(modem, name, premux_index)) + premux_count++; + } + } + + if (premux_count < 3) { + DBG("Not enough rmnet_data interfaces found"); + return FALSE; + } + + ofono_modem_set_integer(modem->modem, "NumPremuxInterfaces", + premux_count); + + if (!ipa_info) { + DBG("No rmnet_ipa interface found"); + return FALSE; + } + + r = setup_qmi(modem, ipa_info, ipa_info); + if (r < 0) + return FALSE; + + return TRUE; +} + static gboolean setup_gobi(struct modem_info *modem) { const struct device_info *qmi = NULL; @@ -1594,6 +1670,7 @@ static struct { { "wavecom", setup_wavecom }, { "tc65", setup_tc65 }, { "ehs6", setup_ehs6 }, + { "gobiqrtr", setup_gobi_qrtr }, { } }; @@ -1644,6 +1721,7 @@ static void destroy_modem(gpointer data) switch (modem->type) { case MODEM_TYPE_USB: case MODEM_TYPE_PCIE: + case MODEM_TYPE_EMBEDDED: for (list = modem->devices; list; list = list->next) { struct device_info *info = list->data; @@ -1688,6 +1766,9 @@ static gboolean check_remove(gpointer key, gpointer value, gpointer user_data) if (g_strcmp0(modem->serial->devpath, devpath) == 0) return TRUE; break; + case MODEM_TYPE_EMBEDDED: + /* Embedded modems cannot be removed. */ + break; } return FALSE; @@ -2133,6 +2214,26 @@ static void check_pci_device(struct udev_device *device) device, kernel_driver); } +static void check_net_device(struct udev_device *device) +{ + char path[32]; + const char *name; + const char *iflink; + + name = udev_device_get_sysname(device); + if (!l_str_has_prefix(name, "rmnet_")) + return; + + iflink = udev_device_get_sysattr_value(device, "iflink"); + if (!iflink) + return; + + /* Collect all rmnet devices with this iflink under a common path. */ + sprintf(path, "/embedded/qrtr/%s", iflink); + add_device(path, NULL, "gobiqrtr", NULL, NULL, MODEM_TYPE_EMBEDDED, + device, "qrtr"); +} + static void check_device(struct udev_device *device) { const char *bus; @@ -2149,6 +2250,8 @@ static void check_device(struct udev_device *device) check_usb_device(device); else if (g_str_equal(bus, "pci") == TRUE) check_pci_device(device); + else if (g_str_equal(bus, "net") == TRUE) + check_net_device(device); else add_serial_device(device); |