diff options
-rw-r--r-- | CMakeLists.txt | 2 | ||||
-rw-r--r-- | deps/sysobj_early/data/sdcard.ids | 48 | ||||
-rw-r--r-- | deps/sysobj_early/include/util_ids.h | 66 | ||||
-rw-r--r-- | deps/sysobj_early/src/util_ids.c | 189 | ||||
-rw-r--r-- | hardinfo/udisks2_util.c | 114 | ||||
-rw-r--r-- | includes/udisks2_util.h | 3 |
6 files changed, 422 insertions, 0 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index e0749f9e..e9fff9f9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -121,6 +121,7 @@ set(HARDINFO_RESOURCES "data/benchmark.conf" "data/benchmark.data" "data/vendor.ids" + "deps/sysobj_early/data/sdcard.ids" ) set(HARDINFO_MANPAGES @@ -218,6 +219,7 @@ add_library(sysobj_early STATIC deps/sysobj_early/src/gg_slist.c deps/sysobj_early/src/strstr_word.c deps/sysobj_early/src/auto_free.c + deps/sysobj_early/src/util_ids.c deps/sysobj_early/gui/uri_handler.c ) set_target_properties(sysobj_early PROPERTIES COMPILE_FLAGS "-std=c99 -Wall -Wextra -Wno-parentheses -Wno-unused-function") diff --git a/deps/sysobj_early/data/sdcard.ids b/deps/sysobj_early/data/sdcard.ids new file mode 100644 index 00000000..8827f673 --- /dev/null +++ b/deps/sysobj_early/data/sdcard.ids @@ -0,0 +1,48 @@ +# +# https://github.com/bp0/verbose-spork/blob/master/data/sdcard.ids +# + +# +# List of known/observed SD card manfid's +# +# Syntax: +# MANFID id manufacturer_name(s) + +MANFID 000001 Panasonic +MANFID 000002 Toshiba +MANFID 000003 SanDisk +MANFID 00001b Samsung +MANFID 00001d ADATA +MANFID 000027 Phison +MANFID 000028 Lexar +MANFID 000031 Silicon Power +MANFID 000041 Kingston +MANFID 000074 Transcend Information +MANFID 000076 Patriot Memory +MANFID 000082 Sony +MANFID 00009c Angelbird / Hoodman + +# +# List of known/observed SD card oemid's +# +# Syntax: +# OEMID id vendor_name(s) +# +# The id is normally composed of two ascii +# characters read as a big-endian 16-bit +# value. + +OEMID 3432 Kingston # "42" +OEMID 4144 ADATA # "AD" +OEMID 4245 Lexar / Angelbird / Hoodman # "BE" +OEMID 4a45 Transcend # "JE" +OEMID 4a54 Sony # "JT" +OEMID 4a60 Transcend Information # "J`" +OEMID 5041 Panasonic # "PA" +OEMID 5048 Phison # "PH" +OEMID 5054 SanDisk # "PT" +OEMID 5344 SanDisk # "SD" +OEMID 534d Samsung # "SM" +OEMID 534f Angelbird / Hoodman # "SO" +OEMID 5350 Silicon Power # "SP" +OEMID 544d Toshiba # "TM" diff --git a/deps/sysobj_early/include/util_ids.h b/deps/sysobj_early/include/util_ids.h new file mode 100644 index 00000000..53656443 --- /dev/null +++ b/deps/sysobj_early/include/util_ids.h @@ -0,0 +1,66 @@ +/* + * sysobj - https://github.com/bp0/verbose-spork + * Copyright (C) 2018 Burt P. <pburt0@gmail.com> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#ifndef _UTIL_IDS_H_ +#define _UTIL_IDS_H_ + +#include <glib.h> + +#define IDS_LOOKUP_BUFF_SIZE 220 +#define IDS_LOOKUP_MAX_DEPTH 4 + +/* may be static, all results[] are NULL or point into _strs */ +typedef struct { + gchar *results[IDS_LOOKUP_MAX_DEPTH+1]; /* last always NULL */ + gchar _strs[IDS_LOOKUP_BUFF_SIZE*IDS_LOOKUP_MAX_DEPTH]; +} ids_query_result; +#define ids_query_result_new() g_new0(ids_query_result, 1) +#define ids_query_result_free(s) g_free(s); + +/* Given a qpath "/X/Y/Z", find names as: + * X <name> ->result[0] + * \tY <name> ->result[1] + * \t\tZ <name> ->result[2] + * + * Works with: + * - pci.ids "<vendor>/<device>/<subvendor> <subdevice>" or "C <class>/<subclass>/<prog-if>" + * ... need to query "<subvendor>" separately + * - arm.ids "<implementer>/<part>" + * - sdio.ids "<vendor>/<device>", "C <class>" + * - sdcard.ids "OEMID <code>", "MANFID <code>" + * - usb.ids "<vendor>/<device>", "C <class>" etc. + */ +long scan_ids_file(const gchar *file, const gchar *qpath, ids_query_result *result, long start_offset); + +typedef struct { + gchar *qpath; + ids_query_result result; +} ids_query; + +ids_query *ids_query_new(const gchar *qpath); +void ids_query_free(ids_query *s); +typedef GSList* ids_query_list; + +/* query_list is a GSList of ids_query* */ +long scan_ids_file_list(const gchar *file, ids_query_list query_list, long start_offset); +/* after scan_ids_file_list(), count hits */ +int query_list_count_found(ids_query_list query_list); + +#endif diff --git a/deps/sysobj_early/src/util_ids.c b/deps/sysobj_early/src/util_ids.c new file mode 100644 index 00000000..00ff63c5 --- /dev/null +++ b/deps/sysobj_early/src/util_ids.c @@ -0,0 +1,189 @@ +/* + * sysobj - https://github.com/bp0/verbose-spork + * Copyright (C) 2018 Burt P. <pburt0@gmail.com> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#include "util_ids.h" +#include <glib.h> +#include <stdio.h> +#include <string.h> +#include <ctype.h> + +#define ids_msg(msg, ...) fprintf (stderr, "[%s] " msg "\n", __FUNCTION__, ##__VA_ARGS__) /**/ + +ids_query *ids_query_new(const gchar *qpath) { + ids_query *s = g_new0(ids_query, 1); + s->qpath = qpath ? g_strdup(qpath) : NULL; + return s; +} + +void ids_query_free(ids_query *s) { + if (s) g_free(s->qpath); + g_free(s); +} + +/* c001 < C 01 */ +//TODO: compare more than the first char +static int ids_cmp(const char *s1, const char *s2) { + int cmp = (s2 ? 1 : 0) - (s1 ? 1 : 0); + if (cmp == 0 && isalpha(*s1) && isalpha(*s2)) + cmp = (islower(*s2) ? 1 : 0) - (islower(*s1) ? 1 : 0); + if (cmp == 0) + return g_strcmp0(s1, s2); + else + return cmp; +} + +/* Given a qpath "/X/Y/Z", find names as: + * X <name> ->result[0] + * \tY <name> ->result[1] + * \t\tZ <name> ->result[2] + * + * Works with: + * - pci.ids "<vendor>/<device>/<subvendor> <subdevice>" or "C <class>/<subclass>/<prog-if>" + * - arm.ids "<implementer>/<part>" + * - sdio.ids "<vendor>/<device>", "C <class>" + * - usb.ids "<vendor>/<device>", "C <class>" etc + */ +long scan_ids_file(const gchar *file, const gchar *qpath, ids_query_result *result, long start_offset) { + gchar **qparts = NULL; + gchar buff[IDS_LOOKUP_BUFF_SIZE] = ""; + ids_query_result ret = {}; + gchar *p = NULL; + + FILE *fd; + int tabs; + int qdepth; + int qpartlen[IDS_LOOKUP_MAX_DEPTH]; + long last_root_fpos = -1, fpos, line = -1; + + if (!qpath) + return -1; + + fd = fopen(file, "r"); + if (!fd) { + ids_msg("file could not be read: %s", file); + return -1; + } + + qparts = g_strsplit(qpath, "/", -1); + qdepth = g_strv_length(qparts); + if (qdepth > IDS_LOOKUP_MAX_DEPTH) { + ids_msg("qdepth (%d) > ids_max_depth (%d) for %s", qdepth, IDS_LOOKUP_MAX_DEPTH, qpath); + qdepth = IDS_LOOKUP_MAX_DEPTH; + } + for(int i = 0; i < qdepth; i++) + qpartlen[i] = strlen(qparts[i]); + + if (start_offset > 0) + fseek(fd, start_offset, SEEK_SET); + + for (fpos = ftell(fd); fgets(buff, IDS_LOOKUP_BUFF_SIZE, fd); fpos = ftell(fd)) { + p = strchr(buff, '\n'); + if (!p) + ids_msg("line longer than IDS_LOOKUP_BUFF_SIZE (%d), file: %s, offset: %ld", IDS_LOOKUP_BUFF_SIZE, file, fpos); + line++; + + /* line ends at comment */ + p = strchr(buff, '#'); + if (p) *p = 0; + /* trim trailing white space */ + if (!p) p = buff + strlen(buff); + p--; + while(p > buff && isspace((unsigned char)*p)) p--; + *(p+1) = 0; + p = buff; + + if (buff[0] == 0) continue; /* empty line */ + if (buff[0] == '\n') continue; /* empty line */ + + /* scan for fields */ + tabs = 0; + while(*p == '\t') { tabs++; p++; } + + if (tabs >= qdepth) continue; /* too deep */ + if (tabs != 0 && !ret.results[tabs-1]) + continue; /* not looking at this depth, yet */ + + //ids_msg("looking at (%d) %s...", tabs, p); + + if (g_str_has_prefix(p, qparts[tabs]) + && isspace(*(p + qpartlen[tabs])) ) { + /* found */ + p += qpartlen[tabs]; + while(isspace((unsigned char)*p)) p++; /* ffwd */ + + if (tabs == 0) { + last_root_fpos = fpos; + ret.results[tabs] = ret._strs; + strncpy(ret.results[tabs], p, IDS_LOOKUP_BUFF_SIZE-1); + } else { + ret.results[tabs] = ret.results[tabs-1] + strlen(ret.results[tabs-1]) + 1; + strncpy(ret.results[tabs], p, IDS_LOOKUP_BUFF_SIZE-1); + } + continue; + } + + if (ids_cmp(p, qparts[tabs]) == 1) { + //ids_msg("will not be found p = %s (%d) qparts[tabs] = %s", p, qparts[tabs]); + goto ids_lookup_done; /* will not be found */ + } + + } /* for each line */ + +ids_lookup_done: + //ids_msg("bailed at line %ld...", line); + fclose(fd); + + if (result) { + memcpy(result, &ret, sizeof(ids_query_result)); + for(int i = 0; result->results[i]; i++) + result->results[i] = result->_strs + (ret.results[i] - ret._strs); + + return last_root_fpos; + } + return last_root_fpos; +} + +static gint _ids_query_list_cmp(const ids_query *ql1, const ids_query *ql2) { + return g_strcmp0(ql1->qpath, ql2->qpath); +} + +long scan_ids_file_list(const gchar *file, ids_query_list query_list, long start_offset) { + GSList *tmp = g_slist_copy(query_list); + tmp = g_slist_sort(tmp, (GCompareFunc)_ids_query_list_cmp); + + long offset = start_offset; + for (GSList *l = query_list; l; l = l->next) { + ids_query *q = l->data; + offset = scan_ids_file(file, q->qpath, &(q->result), offset); + if (offset == -1) + break; + } + g_slist_free(tmp); + return offset; +} + +int query_list_count_found(ids_query_list query_list) { + long count = 0; + for (GSList *l = query_list; l; l = l->next) { + ids_query *q = l->data; + if (q->result.results[0]) count++; + } + return count; +} diff --git a/hardinfo/udisks2_util.c b/hardinfo/udisks2_util.c index 37870fd9..0687b14a 100644 --- a/hardinfo/udisks2_util.c +++ b/hardinfo/udisks2_util.c @@ -1,6 +1,7 @@ #include <gio/gio.h> #include "udisks2_util.h" #include "hardinfo.h" +#include "util_ids.h" #define UDISKS2_INTERFACE "org.freedesktop.UDisks2" #define UDISKS2_MANAGER_INTERFACE "org.freedesktop.UDisks2.Manager" @@ -18,6 +19,109 @@ GDBusConnection* udisks2_conn = NULL; +gchar *sdcard_ids_file = NULL; + +void find_sdcard_ids_file() { + if (sdcard_ids_file) return; + char *file_search_order[] = { + g_build_filename(g_get_user_config_dir(), "hardinfo", "sdcard.ids", NULL), + g_build_filename(params.path_data, "sdcard.ids", NULL), + NULL + }; + int n; + for(n = 0; file_search_order[n]; n++) { + if (!access(file_search_order[n], R_OK)) + sdcard_ids_file = file_search_order[n]; + else + g_free(file_search_order[n]); + } +} + +void check_sdcard_vendor(udiskd *d) { + if (!d) return; + if (!d->media) return; + if (! (g_str_has_prefix(d->media, "flash_sd") + || g_str_has_prefix(d->media, "flash_mmc") )) return; + if (d->vendor && d->vendor[0]) return; + if (!d->block_dev) return; + + if (!sdcard_ids_file) + find_sdcard_ids_file(); + + gchar *qpath = NULL; + ids_query_result result = {}; + + gchar *oemid_path = g_strdup_printf("/sys/block/%s/device/oemid", d->block_dev); + gchar *manfid_path = g_strdup_printf("/sys/block/%s/device/manfid", d->block_dev); + gchar *oemid = NULL, *manfid = NULL; + g_file_get_contents(oemid_path, &oemid, NULL, NULL); + g_file_get_contents(manfid_path, &manfid, NULL, NULL); + + unsigned int id = strtol(oemid, NULL, 16); + char c2 = id & 0xff, c1 = (id >> 8) & 0xff; + + qpath = g_strdup_printf("OEMID %02x%02x", (unsigned int)c1, (unsigned int)c2); + scan_ids_file(sdcard_ids_file, qpath, &result, -1); + g_free(oemid); + if (result.results[0]) + oemid = g_strdup(result.results[0]); + else + oemid = g_strdup_printf("OEM %02x%02x \"%c%c\"", + (unsigned int)c1, (unsigned int)c2, + isprint(c1) ? c1 : '.', isprint(c2) ? c2 : '.'); + g_free(qpath); + + id = strtol(manfid, NULL, 16); + qpath = g_strdup_printf("MANFID %06x", id); + scan_ids_file(sdcard_ids_file, qpath, &result, -1); + g_free(manfid); + if (result.results[0]) + manfid = g_strdup(result.results[0]); + else + manfid = g_strdup_printf("MANF %06x", id); + g_free(qpath); + + vendor_list vl = NULL; + const Vendor *v = NULL; + v = vendor_match(oemid, NULL); + if (v) vl = vendor_list_append(vl, v); + v = vendor_match(manfid, NULL); + if (v) vl = vendor_list_append(vl, v); + vl = vendor_list_remove_duplicates_deep(vl); + d->vendors = vendor_list_concat(d->vendors, vl); + + g_free(d->vendor); + if (g_strcmp0(oemid, manfid) == 0) + d->vendor = g_strdup(oemid); + else + d->vendor = g_strdup_printf("%s / %s", oemid, manfid); + + g_free(oemid); + g_free(manfid); + g_free(oemid_path); + g_free(manfid_path); + + if (d->revision && d->revision[0]) return; + + /* bonus: revision */ + gchar *fwrev_path = g_strdup_printf("/sys/block/%s/device/fwrev", d->block_dev); + gchar *hwrev_path = g_strdup_printf("/sys/block/%s/device/hwrev", d->block_dev); + gchar *fwrev = NULL, *hwrev = NULL; + g_file_get_contents(fwrev_path, &fwrev, NULL, NULL); + g_file_get_contents(hwrev_path, &hwrev, NULL, NULL); + + unsigned int fw = fwrev ? strtol(fwrev, NULL, 16) : 0; + unsigned int hw = hwrev ? strtol(hwrev, NULL, 16) : 0; + g_free(d->revision); + d->revision = g_strdup_printf("%02x.%02x", hw, fw); + + g_free(fwrev); + g_free(hwrev); + g_free(fwrev_path); + g_free(hwrev_path); + +} + GVariant* get_dbus_property(GDBusProxy* proxy, const gchar *interface, const gchar *property) { GVariant *result, *v = NULL; @@ -493,6 +597,15 @@ gpointer get_udisks2_drive_info(const char *blockdev, GDBusProxy *block, GDBusPr g_variant_unref(v); } + check_sdcard_vendor(u); + + if (!u->vendors) { + const Vendor *v = NULL; + v = vendor_match(u->vendor, NULL); + if (v) + u->vendors = vendor_list_append(u->vendors, v); + } + return u; } @@ -515,4 +628,5 @@ void udisks2_shutdown(){ g_object_unref(udisks2_conn); udisks2_conn = NULL; } + g_free(sdcard_ids_file); } diff --git a/includes/udisks2_util.h b/includes/udisks2_util.h index 9998a76c..813825cb 100644 --- a/includes/udisks2_util.h +++ b/includes/udisks2_util.h @@ -1,3 +1,5 @@ +#include "vendor.h" + typedef struct udiskp { gchar *block; gchar *type; @@ -31,6 +33,7 @@ typedef struct udiskd { guint64 smart_poweron; gint64 smart_bad_sectors; gint32 smart_temperature; + vendor_list vendors; } udiskd; typedef struct udiskt { |