diff options
author | L. Pereira <l@tia.mat.br> | 2023-07-29 13:08:52 -0700 |
---|---|---|
committer | L. Pereira <l@tia.mat.br> | 2023-07-29 23:27:52 -0700 |
commit | a2ac044128305c426235de1b9d3f83ba27c36407 (patch) | |
tree | ba3dd2739c9307e36a731f0e60c2272d4e748fe2 /modules | |
parent | 45fa969ad76a8909db5d4f41e5d3fa25e656b888 (diff) |
Show kernel module icons even without modules present on filesystem
This is common on Arch Linux systems when the kernel is updated (the
running kernel modules are removed from disk).
This table was created using modules from Linux 6.3.8, with the same
rules as the fallback mechanism uses (longest string prefix match), and
is updatable using the sync manager.
Diffstat (limited to 'modules')
-rw-r--r-- | modules/computer.c | 1 | ||||
-rw-r--r-- | modules/computer/modules.c | 212 |
2 files changed, 176 insertions, 37 deletions
diff --git a/modules/computer.c b/modules/computer.c index e516cd54..da18b5c2 100644 --- a/modules/computer.c +++ b/modules/computer.c @@ -1074,6 +1074,7 @@ void hi_module_init(void) { computer = g_new0(Computer, 1); init_memory_labels(); + kernel_module_icon_init(); } const ModuleAbout *hi_module_get_about(void) diff --git a/modules/computer/modules.c b/modules/computer/modules.c index 15ffa4b7..451b5c1b 100644 --- a/modules/computer/modules.c +++ b/modules/computer/modules.c @@ -18,7 +18,9 @@ #include <string.h> #include <sys/utsname.h> +#include <json-glib/json-glib.h> +#include "syncmanager.h" #include "computer.h" #include "cpu_util.h" /* for STRIFNULL() */ #include "hardinfo.h" @@ -33,48 +35,184 @@ GHashTable *_module_hash_table = NULL; static gchar *kernel_modules_dir = NULL; +enum icons { + ICON_INVALID = 0, + + ICON_AUDIO, + ICON_BLUETOOTH, + ICON_CAMERA_WEB, + ICON_CDROM, + ICON_CRYPTOHASH, + ICON_DEVICES, + ICON_HDD, + ICON_INPUTDEVICES, + ICON_JOYSTICK, + ICON_KEYBOARD, + ICON_MEDIA_FLOPPY, + ICON_MEDIA_REMOVABLE, + ICON_MEMORY, + ICON_MONITOR, + ICON_MOUSE, + ICON_NETWORK, + ICON_NETWORK_CONNECTIONS, + ICON_NETWORK_INTERFACE, + ICON_THERM, + ICON_USB, + ICON_WIRELESS, + + ICON_MAX, +}; + +static const char *icon_table[ICON_MAX] = { + [ICON_AUDIO] = "audio", + [ICON_BLUETOOTH] = "bluetooth", + [ICON_CAMERA_WEB] = "camera-web", + [ICON_CDROM] = "cdrom", + [ICON_CRYPTOHASH] = "cryptohash", + [ICON_DEVICES] = "devices", + [ICON_HDD] = "hdd", + [ICON_INPUTDEVICES] = "inputdevices", + [ICON_JOYSTICK] = "joystick", + [ICON_KEYBOARD] = "keyboard", + [ICON_MEDIA_FLOPPY] = "media-floppy", + [ICON_MEDIA_REMOVABLE] = "media-removable", + [ICON_MEMORY] = "memory", + [ICON_MONITOR] = "monitor", + [ICON_MOUSE] = "mouse", + [ICON_NETWORK] = "network", + [ICON_NETWORK_CONNECTIONS] = "network-connections", + [ICON_NETWORK_INTERFACE] = "network-interface", + [ICON_THERM] = "therm", + [ICON_USB] = "usb", + [ICON_WIRELESS] = "wireless", +}; + /* Keep this sorted by reverse strlen(dir)! */ static const struct { const gchar *dir; - const gchar *icon; + enum icons icon; } modules_icons[] = { - { "drivers/input/joystick/", "joystick" }, - { "drivers/input/keyboard/", "keyboard" }, - { "drivers/media/usb/uvc/", "camera-web" }, - { "drivers/net/wireless/", "wireless" }, - { "drivers/net/ethernet/", "network-interface" }, - { "drivers/input/mouse/", "mouse" }, - { "drivers/bluetooth/", "bluetooth" }, - { "drivers/media/v4l", "camera-web" }, - { "arch/x86/crypto/", "cryptohash" }, - { "drivers/crypto/", "cryptohash" }, - { "net/bluetooth/", "bluetooth" }, - { "drivers/input/", "inputdevices" }, - { "drivers/cdrom/", "cdrom" }, - { "drivers/hwmon/", "therm" }, - { "drivers/iommu/", "memory" }, - { "net/wireless/", "wireless" }, - { "drivers/nvme/", "hdd" }, - { "net/ethernet/", "network-interface" }, - { "drivers/scsi/", "hdd" }, - { "drivers/edac/", "memory" }, - { "drivers/hid/", "inputdevices" }, - { "drivers/gpu/", "monitor" }, - { "drivers/i2c/", "memory" }, - { "drivers/ata/", "hdd" }, - { "drivers/usb/", "usb" }, - { "drivers/pci/", "devices" }, - { "drivers/net/", "network" }, - { "drivers/mmc/", "media-removable" }, - { "crypto/", "cryptohash" }, - { "sound/", "audio" }, - { "net/", "network-connections" }, - { "fs/", "media-floppy" }, - { } + {"drivers/input/joystick/", ICON_JOYSTICK}, + {"drivers/input/keyboard/", ICON_KEYBOARD}, + {"drivers/media/usb/uvc/", ICON_CAMERA_WEB}, + {"drivers/net/wireless/", ICON_WIRELESS}, + {"drivers/net/ethernet/", ICON_NETWORK_INTERFACE}, + {"drivers/input/mouse/", ICON_MOUSE}, + {"drivers/bluetooth/", ICON_BLUETOOTH}, + {"drivers/media/v4l", ICON_CAMERA_WEB}, + {"arch/x86/crypto/", ICON_CRYPTOHASH}, + {"drivers/crypto/", ICON_CRYPTOHASH}, + {"net/bluetooth/", ICON_BLUETOOTH}, + {"drivers/input/", ICON_INPUTDEVICES}, + {"drivers/cdrom/", ICON_CDROM}, + {"drivers/hwmon/", ICON_THERM}, + {"drivers/iommu/", ICON_MEMORY}, + {"net/wireless/", ICON_WIRELESS}, + {"drivers/nvme/", ICON_HDD}, + {"net/ethernet/", ICON_NETWORK_INTERFACE}, + {"drivers/scsi/", ICON_HDD}, + {"drivers/edac/", ICON_MEMORY}, + {"drivers/hid/", ICON_INPUTDEVICES}, + {"drivers/gpu/", ICON_MONITOR}, + {"drivers/i2c/", ICON_MEMORY}, + {"drivers/ata/", ICON_HDD}, + {"drivers/usb/", ICON_USB}, + {"drivers/pci/", ICON_DEVICES}, + {"drivers/net/", ICON_NETWORK}, + {"drivers/mmc/", ICON_MEDIA_REMOVABLE}, + {"crypto/", ICON_CRYPTOHASH}, + {"sound/", ICON_AUDIO}, + {"net/", ICON_NETWORK_CONNECTIONS}, + {"fs/", ICON_MEDIA_FLOPPY}, + {}, }; -static const gchar* get_module_icon(const char *path) +static GHashTable *module_icons; + +static void build_icon_table_iter(JsonObject *object, + const gchar *key, + JsonNode *value, + gpointer user_data) +{ + char *key_copy = g_strdup(key); + char *p; + + for (p = key_copy; *p; p++) { + if (*p == '_') + *p = '-'; + } + + enum icons icon; + const gchar *value_str = json_node_get_string(value); + for (icon = ICON_INVALID; icon < ICON_MAX; icon++) { + const char *icon_name = icon_table[icon]; + + if (!icon_name) + continue; + + if (g_str_equal(value_str, icon_name)) { + g_hash_table_insert(module_icons, + key_copy, GINT_TO_POINTER(icon)); + return; + } + } + + g_free(key_copy); +} + +void kernel_module_icon_init(void) +{ + gchar *icon_json; + + static SyncEntry sync_entry = { + .name = N_("Update kernel module icon table"), + .file_name = "kernel-module-icons.json", + }; + sync_manager_add_entry(&sync_entry); + + icon_json = g_build_filename(g_get_user_config_dir(), + "hardinfo", "kernel-module-icons.json", + NULL); + + module_icons = g_hash_table_new(g_str_hash, g_str_equal); + + if (!g_file_test(icon_json, G_FILE_TEST_EXISTS)) + goto out; + + JsonParser *parser = json_parser_new(); + if (!json_parser_load_from_file(parser, icon_json, NULL)) + goto out_destroy_parser; + + JsonNode *root = json_parser_get_root(parser); + if (json_node_get_node_type(root) != JSON_NODE_OBJECT) + goto out_destroy_parser; + + JsonObject *icons = json_node_get_object(root); + if (!icons) + goto out_destroy_parser; + + json_object_foreach_member(icons, build_icon_table_iter, NULL); + +out_destroy_parser: + g_object_unref(parser); + +out: + g_free(icon_json); +} + +static const gchar* get_module_icon(const char *modname, const char *path) { + char *modname_temp = g_strdup(modname); + char *p; + for (p = modname_temp; *p; p++) { + if (*p == '_') + *p = '-'; + } + gpointer icon = g_hash_table_lookup(module_icons, modname_temp); + g_free(modname_temp); + if (icon) + return icon_table[GPOINTER_TO_INT(icon)]; + if (path == NULL) /* modinfo couldn't find module path */ return NULL; @@ -93,7 +231,7 @@ static const gchar* get_module_icon(const char *path) for (i = 0; modules_icons[i].dir; i++) { if (g_str_has_prefix(path_no_prefix, modules_icons[i].dir)) - return modules_icons[i].icon; + return icon_table[modules_icons[i].icon]; } return NULL; @@ -185,7 +323,7 @@ void scan_modules_do(void) { /* append this module to the list of modules */ module_list = h_strdup_cprintf("$%s$%s=%s\n", module_list, hashkey, modname, description ? description : ""); - icon = get_module_icon(filename); + icon = get_module_icon(modname, filename); module_icons = h_strdup_cprintf("Icon$%s$%s=%s.png\n", module_icons, hashkey, modname, icon ? icon: "module"); |