aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CMakeLists.txt2
-rw-r--r--deps/sysobj_early/data/sdcard.ids48
-rw-r--r--deps/sysobj_early/include/util_ids.h66
-rw-r--r--deps/sysobj_early/src/util_ids.c189
-rw-r--r--hardinfo/udisks2_util.c114
-rw-r--r--includes/udisks2_util.h3
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 {