diff options
author | Daniele Palmas <dnlplm@gmail.com> | 2022-05-04 13:52:59 +0200 |
---|---|---|
committer | Daniele Palmas <dnlplm@gmail.com> | 2022-05-24 09:22:06 +0200 |
commit | ce71b580fc1e722d93c09cefaaeaf41e4ec6e545 (patch) | |
tree | 59430123a4a1e5372e41e980bb486c3351e1e536 /src | |
parent | 654c5f5014f90df7eb239b83ac88a1065e169731 (diff) |
filter: add vendor id/subsystem vendor id filter
Some PCI modems prefer customizing the subsytem vendor ID,
instead of the vendor ID.
Add a filter for the couple vendor/subsystem vendor IDs.
Diffstat (limited to 'src')
-rw-r--r-- | src/mm-filter.c | 46 | ||||
-rw-r--r-- | src/mm-filter.h | 17 | ||||
-rw-r--r-- | src/mm-plugin-manager.c | 22 | ||||
-rw-r--r-- | src/mm-plugin.c | 53 | ||||
-rw-r--r-- | src/mm-plugin.h | 70 |
5 files changed, 160 insertions, 48 deletions
diff --git a/src/mm-filter.c b/src/mm-filter.c index 2a98bb73..d2df289c 100644 --- a/src/mm-filter.c +++ b/src/mm-filter.c @@ -41,6 +41,7 @@ struct _MMFilterPrivate { GList *plugin_allowlist_tags; GArray *plugin_allowlist_vendor_ids; GArray *plugin_allowlist_product_ids; + GArray *plugin_allowlist_subsystem_vendor_ids; }; /*****************************************************************************/ @@ -101,6 +102,31 @@ mm_filter_register_plugin_allowlist_product_id (MMFilter *self, mm_obj_dbg (self, "registered plugin allowlist product id: %04x:%04x", vid, pid); } +void +mm_filter_register_plugin_allowlist_subsystem_vendor_id (MMFilter *self, + guint16 vid, + guint16 subsystem_vid) +{ + mm_uint16_pair new_item; + guint i; + + if (!self->priv->plugin_allowlist_subsystem_vendor_ids) + self->priv->plugin_allowlist_subsystem_vendor_ids = g_array_sized_new (FALSE, FALSE, sizeof (mm_uint16_pair), 10); + + for (i = 0; i < self->priv->plugin_allowlist_subsystem_vendor_ids->len; i++) { + mm_uint16_pair *item; + + item = &g_array_index (self->priv->plugin_allowlist_subsystem_vendor_ids, mm_uint16_pair, i); + if (item->l == vid && item->r == subsystem_vid) + return; + } + + new_item.l = vid; + new_item.r = subsystem_vid; + g_array_append_val (self->priv->plugin_allowlist_subsystem_vendor_ids, new_item); + mm_obj_dbg (self, "registered plugin allowlist subsystem vendor id: %04x:%04x", vid, subsystem_vid); +} + /*****************************************************************************/ gboolean @@ -136,6 +162,7 @@ mm_filter_port (MMFilter *self, GList *l; guint16 vid = 0; guint16 pid = 0; + guint16 subsystem_vid = 0; for (l = self->priv->plugin_allowlist_tags; l; l = g_list_next (l)) { if (mm_kernel_device_get_global_property_as_boolean (port, (const gchar *)(l->data)) || @@ -146,8 +173,10 @@ mm_filter_port (MMFilter *self, } vid = mm_kernel_device_get_physdev_vid (port); - if (vid) + if (vid) { pid = mm_kernel_device_get_physdev_pid (port); + subsystem_vid = mm_kernel_device_get_physdev_subsystem_vid (port); + } if (vid && pid && self->priv->plugin_allowlist_product_ids) { guint i; @@ -176,6 +205,20 @@ mm_filter_port (MMFilter *self, } } } + + if (vid && subsystem_vid && self->priv->plugin_allowlist_subsystem_vendor_ids) { + guint i; + + for (i = 0; i < self->priv->plugin_allowlist_subsystem_vendor_ids->len; i++) { + mm_uint16_pair *item; + + item = &g_array_index (self->priv->plugin_allowlist_subsystem_vendor_ids, mm_uint16_pair, i); + if (item->l == vid && item->r == subsystem_vid) { + mm_obj_dbg (self, "(%s/%s) port allowed: device is allowlisted by plugin (vid/subsystem vid)", subsystem, name); + return TRUE; + } + } + } } /* If this is a QRTR device, we always allow it. This check comes before @@ -517,6 +560,7 @@ finalize (GObject *object) g_clear_pointer (&self->priv->plugin_allowlist_vendor_ids, g_array_unref); g_clear_pointer (&self->priv->plugin_allowlist_product_ids, g_array_unref); + g_clear_pointer (&self->priv->plugin_allowlist_subsystem_vendor_ids, g_array_unref); g_list_free_full (self->priv->plugin_allowlist_tags, g_free); G_OBJECT_CLASS (mm_filter_parent_class)->finalize (object); diff --git a/src/mm-filter.h b/src/mm-filter.h index de561dab..d6e14d3d 100644 --- a/src/mm-filter.h +++ b/src/mm-filter.h @@ -101,13 +101,16 @@ gboolean mm_filter_device_and_port (MMFilter *self, MMDevice *device, MMKernelDevice *port); -void mm_filter_register_plugin_allowlist_tag (MMFilter *self, - const gchar *tag); -void mm_filter_register_plugin_allowlist_vendor_id (MMFilter *self, - guint16 vid); -void mm_filter_register_plugin_allowlist_product_id (MMFilter *self, - guint16 vid, - guint16 pid); +void mm_filter_register_plugin_allowlist_tag (MMFilter *self, + const gchar *tag); +void mm_filter_register_plugin_allowlist_vendor_id (MMFilter *self, + guint16 vid); +void mm_filter_register_plugin_allowlist_product_id (MMFilter *self, + guint16 vid, + guint16 pid); +void mm_filter_register_plugin_allowlist_subsystem_vendor_id (MMFilter *self, + guint16 vid, + guint16 subsystem_vid); gboolean mm_filter_check_rule_enabled (MMFilter *self, MMFilterRule rule); diff --git a/src/mm-plugin-manager.c b/src/mm-plugin-manager.c index 8ec85a57..0f454bb7 100644 --- a/src/mm-plugin-manager.c +++ b/src/mm-plugin-manager.c @@ -1666,6 +1666,21 @@ register_plugin_allowlist_product_ids (MMPluginManager *self, mm_filter_register_plugin_allowlist_product_id (self->priv->filter, product_ids[i].l, product_ids[i].r); } +static void +register_plugin_allowlist_subsystem_vendor_ids (MMPluginManager *self, + MMPlugin *plugin) +{ + const mm_uint16_pair *subsystem_vendor_ids; + guint i; + + if (!mm_filter_check_rule_enabled (self->priv->filter, MM_FILTER_RULE_PLUGIN_ALLOWLIST)) + return; + + subsystem_vendor_ids = mm_plugin_get_allowed_subsystem_vendor_ids (plugin); + for (i = 0; subsystem_vendor_ids && subsystem_vendor_ids[i].l; i++) + mm_filter_register_plugin_allowlist_subsystem_vendor_id (self->priv->filter, subsystem_vendor_ids[i].l, subsystem_vendor_ids[i].r); +} + static MMPlugin * load_plugin (MMPluginManager *self, const gchar *path) @@ -1869,9 +1884,10 @@ load_plugins (MMPluginManager *self, } /* Register plugin allowlist rules in filter, if any */ - register_plugin_allowlist_tags (self, plugin); - register_plugin_allowlist_vendor_ids (self, plugin); - register_plugin_allowlist_product_ids (self, plugin); + register_plugin_allowlist_tags (self, plugin); + register_plugin_allowlist_vendor_ids (self, plugin); + register_plugin_allowlist_product_ids (self, plugin); + register_plugin_allowlist_subsystem_vendor_ids (self, plugin); } /* Check the generic plugin once all looped */ diff --git a/src/mm-plugin.c b/src/mm-plugin.c index 354caf09..f4d84ad4 100644 --- a/src/mm-plugin.c +++ b/src/mm-plugin.c @@ -74,6 +74,7 @@ struct _MMPluginPrivate { gchar **forbidden_drivers; guint16 *vendor_ids; mm_uint16_pair *product_ids; + mm_uint16_pair *subsystem_vendor_ids; mm_uint16_pair *forbidden_product_ids; gchar **udev_tags; @@ -114,6 +115,7 @@ enum { PROP_FORBIDDEN_DRIVERS, PROP_ALLOWED_VENDOR_IDS, PROP_ALLOWED_PRODUCT_IDS, + PROP_ALLOWED_SUBSYSTEM_VENDOR_IDS, PROP_FORBIDDEN_PRODUCT_IDS, PROP_ALLOWED_VENDOR_STRINGS, PROP_ALLOWED_PRODUCT_STRINGS, @@ -170,6 +172,12 @@ mm_plugin_get_allowed_product_ids (MMPlugin *self) return self->priv->product_ids; } +const mm_uint16_pair * +mm_plugin_get_allowed_subsystem_vendor_ids (MMPlugin *self) +{ + return self->priv->subsystem_vendor_ids; +} + gboolean mm_plugin_is_generic (MMPlugin *self) { @@ -243,8 +251,10 @@ apply_pre_probing_filters (MMPlugin *self, { guint16 vendor; guint16 product; + guint16 subsystem_vendor; gboolean product_filtered = FALSE; gboolean vendor_filtered = FALSE; + gboolean subsystem_vendor_filtered = FALSE; guint i; *need_vendor_probing = FALSE; @@ -350,6 +360,7 @@ apply_pre_probing_filters (MMPlugin *self, vendor = mm_device_get_vendor (device); product = mm_device_get_product (device); + subsystem_vendor = mm_device_get_subsystem_vendor (device); /* The plugin may specify that only some vendor IDs are supported. If that * is the case, filter by vendor ID. */ @@ -394,12 +405,30 @@ apply_pre_probing_filters (MMPlugin *self, product_filtered = FALSE; } - /* If we got filtered by vendor or product IDs; mark it as unsupported only if: + /* The plugin may specify that a set of vendor IDs is valid only when going + * with a specific subsystem vendor IDs (PCI modems). + * If that is the case, filter by vendor+subsystem vendor ID pair */ + if (subsystem_vendor && self->priv->subsystem_vendor_ids) { + for (i = 0; self->priv->subsystem_vendor_ids[i].l; i++) + if (vendor == self->priv->subsystem_vendor_ids[i].l && + subsystem_vendor == self->priv->subsystem_vendor_ids[i].r) { + /* If device was filtered by vendor, we override that value, since + * we want to give priority to vendor/subsystem vendor match */ + vendor_filtered = FALSE; + break; + } + + /* If we didn't match any vendor/subsystem vendor: filtered */ + if (!self->priv->subsystem_vendor_ids[i].l) + subsystem_vendor_filtered = TRUE; + } + + /* If we got filtered by vendor/product/subsystem IDs; mark it as unsupported only if: * a) we do not have vendor or product strings to compare with (i.e. plugin * doesn't have explicit vendor/product strings * b) the port is NOT an AT port which we can use for AT probing */ - if ((vendor_filtered || product_filtered) && + if ((vendor_filtered || product_filtered || subsystem_vendor_filtered) && ((!self->priv->vendor_strings && !self->priv->product_strings && !self->priv->forbidden_product_strings) || @@ -430,7 +459,8 @@ apply_pre_probing_filters (MMPlugin *self, * already had vendor/product ID filters and we actually passed those. */ if ((!self->priv->vendor_ids && !self->priv->product_ids) || vendor_filtered || - product_filtered) { + product_filtered || + subsystem_vendor_filtered) { /* If product strings related filters around, we need to probe for both * vendor and product strings */ if (self->priv->product_strings || @@ -1172,6 +1202,10 @@ set_property (GObject *object, /* Construct only */ self->priv->product_ids = g_value_dup_boxed (value); break; + case PROP_ALLOWED_SUBSYSTEM_VENDOR_IDS: + /* Construct only */ + self->priv->subsystem_vendor_ids = g_value_dup_boxed (value); + break; case PROP_FORBIDDEN_PRODUCT_IDS: /* Construct only */ self->priv->forbidden_product_ids = g_value_dup_boxed (value); @@ -1292,6 +1326,9 @@ get_property (GObject *object, case PROP_ALLOWED_PRODUCT_IDS: g_value_set_boxed (value, self->priv->product_ids); break; + case PROP_ALLOWED_SUBSYSTEM_VENDOR_IDS: + g_value_set_boxed (value, self->priv->subsystem_vendor_ids); + break; case PROP_FORBIDDEN_PRODUCT_IDS: g_value_set_boxed (value, self->priv->forbidden_product_ids); break; @@ -1375,6 +1412,7 @@ finalize (GObject *object) _g_boxed_free0 (G_TYPE_STRV, self->priv->forbidden_drivers); _g_boxed_free0 (MM_TYPE_UINT16_ARRAY, self->priv->vendor_ids); _g_boxed_free0 (MM_TYPE_UINT16_PAIR_ARRAY, self->priv->product_ids); + _g_boxed_free0 (MM_TYPE_UINT16_PAIR_ARRAY, self->priv->subsystem_vendor_ids); _g_boxed_free0 (MM_TYPE_UINT16_PAIR_ARRAY, self->priv->forbidden_product_ids); _g_boxed_free0 (G_TYPE_STRV, self->priv->udev_tags); _g_boxed_free0 (G_TYPE_STRV, self->priv->vendor_strings); @@ -1468,6 +1506,15 @@ mm_plugin_class_init (MMPluginClass *klass) G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); g_object_class_install_property + (object_class, PROP_ALLOWED_SUBSYSTEM_VENDOR_IDS, + g_param_spec_boxed (MM_PLUGIN_ALLOWED_SUBSYSTEM_VENDOR_IDS, + "Allowed subsystem vendor IDs", + "List of vendor+subsystem vendor ID pairs this plugin can support, " + "should be an array of mm_uint16_pair finished with '0,0'", + MM_TYPE_UINT16_PAIR_ARRAY, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); + + g_object_class_install_property (object_class, PROP_FORBIDDEN_PRODUCT_IDS, g_param_spec_boxed (MM_PLUGIN_FORBIDDEN_PRODUCT_IDS, "Forbidden product IDs", diff --git a/src/mm-plugin.h b/src/mm-plugin.h index 89bac2e2..3c00ed1a 100644 --- a/src/mm-plugin.h +++ b/src/mm-plugin.h @@ -46,34 +46,35 @@ #define MM_IS_PLUGIN_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), MM_TYPE_PLUGIN)) #define MM_PLUGIN_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), MM_TYPE_PLUGIN, MMPluginClass)) -#define MM_PLUGIN_NAME "name" -#define MM_PLUGIN_IS_GENERIC "is-generic" -#define MM_PLUGIN_ALLOWED_SUBSYSTEMS "allowed-subsystems" -#define MM_PLUGIN_ALLOWED_DRIVERS "allowed-drivers" -#define MM_PLUGIN_FORBIDDEN_DRIVERS "forbidden-drivers" -#define MM_PLUGIN_ALLOWED_VENDOR_IDS "allowed-vendor-ids" -#define MM_PLUGIN_ALLOWED_PRODUCT_IDS "allowed-product-ids" -#define MM_PLUGIN_FORBIDDEN_PRODUCT_IDS "forbidden-product-ids" -#define MM_PLUGIN_ALLOWED_VENDOR_STRINGS "allowed-vendor-strings" -#define MM_PLUGIN_ALLOWED_PRODUCT_STRINGS "allowed-product-strings" -#define MM_PLUGIN_FORBIDDEN_PRODUCT_STRINGS "forbidden-product-strings" -#define MM_PLUGIN_ALLOWED_UDEV_TAGS "allowed-udev-tags" -#define MM_PLUGIN_ALLOWED_AT "allowed-at" -#define MM_PLUGIN_ALLOWED_SINGLE_AT "allowed-single-at" -#define MM_PLUGIN_ALLOWED_QCDM "allowed-qcdm" -#define MM_PLUGIN_ALLOWED_QMI "allowed-qmi" -#define MM_PLUGIN_ALLOWED_MBIM "allowed-mbim" -#define MM_PLUGIN_ICERA_PROBE "icera-probe" -#define MM_PLUGIN_ALLOWED_ICERA "allowed-icera" -#define MM_PLUGIN_FORBIDDEN_ICERA "forbidden-icera" -#define MM_PLUGIN_XMM_PROBE "xmm-probe" -#define MM_PLUGIN_ALLOWED_XMM "allowed-xmm" -#define MM_PLUGIN_FORBIDDEN_XMM "forbidden-xmm" -#define MM_PLUGIN_CUSTOM_INIT "custom-init" -#define MM_PLUGIN_CUSTOM_AT_PROBE "custom-at-probe" -#define MM_PLUGIN_SEND_DELAY "send-delay" -#define MM_PLUGIN_REMOVE_ECHO "remove-echo" -#define MM_PLUGIN_SEND_LF "send-lf" +#define MM_PLUGIN_NAME "name" +#define MM_PLUGIN_IS_GENERIC "is-generic" +#define MM_PLUGIN_ALLOWED_SUBSYSTEMS "allowed-subsystems" +#define MM_PLUGIN_ALLOWED_DRIVERS "allowed-drivers" +#define MM_PLUGIN_FORBIDDEN_DRIVERS "forbidden-drivers" +#define MM_PLUGIN_ALLOWED_VENDOR_IDS "allowed-vendor-ids" +#define MM_PLUGIN_ALLOWED_PRODUCT_IDS "allowed-product-ids" +#define MM_PLUGIN_ALLOWED_SUBSYSTEM_VENDOR_IDS "allowed-subsystem-vendor-ids" +#define MM_PLUGIN_FORBIDDEN_PRODUCT_IDS "forbidden-product-ids" +#define MM_PLUGIN_ALLOWED_VENDOR_STRINGS "allowed-vendor-strings" +#define MM_PLUGIN_ALLOWED_PRODUCT_STRINGS "allowed-product-strings" +#define MM_PLUGIN_FORBIDDEN_PRODUCT_STRINGS "forbidden-product-strings" +#define MM_PLUGIN_ALLOWED_UDEV_TAGS "allowed-udev-tags" +#define MM_PLUGIN_ALLOWED_AT "allowed-at" +#define MM_PLUGIN_ALLOWED_SINGLE_AT "allowed-single-at" +#define MM_PLUGIN_ALLOWED_QCDM "allowed-qcdm" +#define MM_PLUGIN_ALLOWED_QMI "allowed-qmi" +#define MM_PLUGIN_ALLOWED_MBIM "allowed-mbim" +#define MM_PLUGIN_ICERA_PROBE "icera-probe" +#define MM_PLUGIN_ALLOWED_ICERA "allowed-icera" +#define MM_PLUGIN_FORBIDDEN_ICERA "forbidden-icera" +#define MM_PLUGIN_XMM_PROBE "xmm-probe" +#define MM_PLUGIN_ALLOWED_XMM "allowed-xmm" +#define MM_PLUGIN_FORBIDDEN_XMM "forbidden-xmm" +#define MM_PLUGIN_CUSTOM_INIT "custom-init" +#define MM_PLUGIN_CUSTOM_AT_PROBE "custom-at-probe" +#define MM_PLUGIN_SEND_DELAY "send-delay" +#define MM_PLUGIN_REMOVE_ECHO "remove-echo" +#define MM_PLUGIN_SEND_LF "send-lf" typedef enum { MM_PLUGIN_SUPPORTS_PORT_UNKNOWN = -1, @@ -126,12 +127,13 @@ struct _MMPluginClass { GType mm_plugin_get_type (void); G_DEFINE_AUTOPTR_CLEANUP_FUNC (MMPlugin, g_object_unref) -const gchar *mm_plugin_get_name (MMPlugin *self); -const gchar **mm_plugin_get_allowed_subsystems (MMPlugin *self); -const gchar **mm_plugin_get_allowed_udev_tags (MMPlugin *self); -const guint16 *mm_plugin_get_allowed_vendor_ids (MMPlugin *self); -const mm_uint16_pair *mm_plugin_get_allowed_product_ids (MMPlugin *self); -gboolean mm_plugin_is_generic (MMPlugin *self); +const gchar *mm_plugin_get_name (MMPlugin *self); +const gchar **mm_plugin_get_allowed_subsystems (MMPlugin *self); +const gchar **mm_plugin_get_allowed_udev_tags (MMPlugin *self); +const guint16 *mm_plugin_get_allowed_vendor_ids (MMPlugin *self); +const mm_uint16_pair *mm_plugin_get_allowed_product_ids (MMPlugin *self); +const mm_uint16_pair *mm_plugin_get_allowed_subsystem_vendor_ids (MMPlugin *self); +gboolean mm_plugin_is_generic (MMPlugin *self); /* This method will run all pre-probing filters, to see if we can discard this * plugin from the probing logic as soon as possible. */ |