aboutsummaryrefslogtreecommitdiff
path: root/hardinfo
diff options
context:
space:
mode:
Diffstat (limited to 'hardinfo')
-rw-r--r--hardinfo/dt_util.c30
-rw-r--r--hardinfo/gg_key_file_parse_string_as_value.c109
-rw-r--r--hardinfo/gpu_util.c18
-rw-r--r--hardinfo/info.c13
-rw-r--r--hardinfo/udisks2_util.c2
-rw-r--r--hardinfo/usb_util.c101
-rw-r--r--hardinfo/util.c32
-rw-r--r--hardinfo/vendor.c19
8 files changed, 240 insertions, 84 deletions
diff --git a/hardinfo/dt_util.c b/hardinfo/dt_util.c
index da38fd91..2d1b60a0 100644
--- a/hardinfo/dt_util.c
+++ b/hardinfo/dt_util.c
@@ -27,6 +27,7 @@
#include <endian.h>
#include "hardinfo.h"
#include "dt_util.h"
+#include "appf.h"
static struct {
char *name; int type;
@@ -682,14 +683,14 @@ char *dtr_list_override(dtr_obj *obj) {
src += 4; consumed += 4;
l = strlen(src) + 1; /* consume the null */
str = dtr_list_str0(src, l);
- ret = appf(ret, "<%s -> %s>", ph, str);
+ ret = appfsp(ret, "<%s -> %s>", ph, str);
src += l; consumed += l;
free(ph);
free(str);
}
if (consumed < obj->length) {
str = dtr_list_byte((uint8_t*)src, obj->length - consumed);
- ret = appf(ret, "%s", str);
+ ret = appfsp(ret, "%s", str);
free(str);
}
return ret;
@@ -720,7 +721,7 @@ char *dtr_list_phref(dtr_obj *obj, char *ext_cell_prop) {
ph = dtr_elem_phref(obj->dt, obj->data_int[i], 0, NULL); i++;
if (ext_cells > count - i) ext_cells = count - i;
ext = dtr_list_hex((obj->data_int + i), ext_cells); i+=ext_cells;
- ret = appf(ret, "<%s%s%s>",
+ ret = appfsp(ret, "<%s%s%s>",
ph, (ext_cells) ? " " : "", ext);
g_free(ph);
g_free(ext);
@@ -748,7 +749,7 @@ char *dtr_list_interrupts(dtr_obj *obj) {
while (i < count) {
icells = UMIN(icells, count - i);
ext = dtr_list_hex((obj->data_int + i), icells); i+=icells;
- ret = appf(ret, "<%s>", ext);
+ ret = appfsp(ret, "<%s>", ext);
}
return ret;
@@ -782,7 +783,7 @@ char *dtr_list_reg(dtr_obj *obj) {
consumed = 0;
while (consumed + (tup_len * 4) <= obj->length) {
tup_str = dtr_list_hex(next, tup_len);
- ret = appf(ret, "<%s>", tup_str);
+ ret = appfsp(ret, "<%s>", tup_str);
free(tup_str);
consumed += (tup_len * 4);
next += tup_len;
@@ -1184,22 +1185,3 @@ char *dtr_maps_info(dtr *s) {
g_free(sy_map);
return ret;
}
-
-char *appf(char *src, char *fmt, ...) {
- gchar *buf, *ret;
- va_list args;
-
- va_start(args, fmt);
- buf = g_strdup_vprintf(fmt, args);
- va_end(args);
-
- if (src != NULL) {
- ret = g_strdup_printf("%s%s%s", src, sp_sep(src), buf);
- g_free(buf);
- g_free(src);
- } else
- ret = buf;
-
- return ret;
-}
-
diff --git a/hardinfo/gg_key_file_parse_string_as_value.c b/hardinfo/gg_key_file_parse_string_as_value.c
new file mode 100644
index 00000000..496b1d35
--- /dev/null
+++ b/hardinfo/gg_key_file_parse_string_as_value.c
@@ -0,0 +1,109 @@
+/* From: gkeyfile.c - key file parser
+ *
+ * Copyright 2004 Red Hat, Inc.
+ * Copyright 2009-2010 Collabora Ltd.
+ * Copyright 2009 Nokia Corporation
+ *
+ * Written by Ray Strode <rstrode@redhat.com>
+ * Matthias Clasen <mclasen@redhat.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+static gchar *
+gg_key_file_parse_string_as_value (const gchar *string, const gchar list_separator)
+{
+ gchar *value, *p, *q;
+ gsize length;
+ gboolean parsing_leading_space;
+
+ length = strlen (string) + 1;
+
+ /* Worst case would be that every character needs to be escaped.
+ * In other words every character turns to two characters. */
+ value = g_new (gchar, 2 * length);
+
+ p = (gchar *) string;
+ q = value;
+ parsing_leading_space = TRUE;
+ while (p < (string + length - 1))
+ {
+ gchar escaped_character[3] = { '\\', 0, 0 };
+
+ switch (*p)
+ {
+ case ' ':
+ if (parsing_leading_space)
+ {
+ escaped_character[1] = 's';
+ strcpy (q, escaped_character);
+ q += 2;
+ }
+ else
+ {
+ *q = *p;
+ q++;
+ }
+ break;
+ case '\t':
+ if (parsing_leading_space)
+ {
+ escaped_character[1] = 't';
+ strcpy (q, escaped_character);
+ q += 2;
+ }
+ else
+ {
+ *q = *p;
+ q++;
+ }
+ break;
+ case '\n':
+ escaped_character[1] = 'n';
+ strcpy (q, escaped_character);
+ q += 2;
+ break;
+ case '\r':
+ escaped_character[1] = 'r';
+ strcpy (q, escaped_character);
+ q += 2;
+ break;
+ case '\\':
+ escaped_character[1] = '\\';
+ strcpy (q, escaped_character);
+ q += 2;
+ parsing_leading_space = FALSE;
+ break;
+ default:
+ if (list_separator && *p == list_separator)
+ {
+ escaped_character[1] = list_separator;
+ strcpy (q, escaped_character);
+ q += 2;
+ parsing_leading_space = TRUE;
+ }
+ else
+ {
+ *q = *p;
+ q++;
+ parsing_leading_space = FALSE;
+ }
+ break;
+ }
+ p++;
+ }
+ *q = '\0';
+
+ return value;
+}
diff --git a/hardinfo/gpu_util.c b/hardinfo/gpu_util.c
index 17c79a73..b203b426 100644
--- a/hardinfo/gpu_util.c
+++ b/hardinfo/gpu_util.c
@@ -20,7 +20,7 @@
#include "hardinfo.h"
#include "gpu_util.h"
-
+#include "nice_name.h"
#include "cpu_util.h" /* for EMPIFNULL() */
nvgpu *nvgpu_new() {
@@ -229,16 +229,12 @@ static void make_nice_name(gpud *s) {
/* try and a get a "short name" for the vendor */
vendor_str = vendor_get_shortest_name(vendor_str);
- /* These two former special cases are currently handled by the vendor_get_shortest_name()
- * function well enough, but the notes are preserved here. */
- /* nvidia PCI strings are pretty nice already,
- * just shorten the company name */
- // s->nice_name = g_strdup_printf("%s %s", "nVidia", device_str);
- /* Intel Graphics may have very long names, like "Intel Corporation Seventh Generation Something Core Something Something Integrated Graphics Processor Revision Ninety-four"
- * but for now at least shorten "Intel Corporation" to just "Intel" */
- // s->nice_name = g_strdup_printf("%s %s", "Intel", device_str);
-
- if (strstr(vendor_str, "AMD")) {
+ if (strstr(vendor_str, "Intel")) {
+ gchar *device_str_clean = strdup(device_str);
+ nice_name_intel_gpu_device(device_str_clean);
+ s->nice_name = g_strdup_printf("%s %s", vendor_str, device_str_clean);
+ g_free(device_str_clean);
+ } else if (strstr(vendor_str, "AMD")) {
/* AMD PCI strings are crazy stupid because they use the exact same
* chip and device id for a zillion "different products" */
char *full_name = strdup(device_str);
diff --git a/hardinfo/info.c b/hardinfo/info.c
index bfc11fc2..cf6af9f9 100644
--- a/hardinfo/info.c
+++ b/hardinfo/info.c
@@ -17,6 +17,13 @@
*/
#include "hardinfo.h"
+#include "util_sysobj.h" /* for SEQ() */
+
+/* Using a slightly modified gg_key_file_parse_string_as_value()
+ * from GLib in flatten(), to escape characters and the separator.
+ * The function is not public in GLib and we don't have a GKeyFile
+ * to pass it anyway. */
+#include "gg_key_file_parse_string_as_value.c"
static const gchar *info_column_titles[] = {
"TextValue", "Value", "Progress", "Extra1", "Extra2"
@@ -267,7 +274,9 @@ static void flatten_group(GString *output, const struct InfoGroup *group, guint
tp);
}
- g_string_append_printf(output, "%s=%s\n", field->name, field->value);
+ gchar *escaped_value = gg_key_file_parse_string_as_value(field->value, '|');
+ g_string_append_printf(output, "%s=%s\n", field->name, escaped_value);
+ g_free(escaped_value);
}
} else if (group->computed) {
g_string_append_printf(output, "%s\n", group->computed);
@@ -369,8 +378,6 @@ gchar *info_flatten(struct Info *info)
return g_string_free(values, FALSE);
}
-#define SEQ(a,b) (g_strcmp0(a,b) == 0)
-
struct InfoField *info_find_field(struct Info *info, const gchar *tag, const gchar *name) {
struct InfoGroup *group;
struct InfoField *field;
diff --git a/hardinfo/udisks2_util.c b/hardinfo/udisks2_util.c
index 0687b14a..8aa54f72 100644
--- a/hardinfo/udisks2_util.c
+++ b/hardinfo/udisks2_util.c
@@ -30,7 +30,7 @@ void find_sdcard_ids_file() {
};
int n;
for(n = 0; file_search_order[n]; n++) {
- if (!access(file_search_order[n], R_OK))
+ if (!sdcard_ids_file && !access(file_search_order[n], R_OK))
sdcard_ids_file = file_search_order[n];
else
g_free(file_search_order[n]);
diff --git a/hardinfo/usb_util.c b/hardinfo/usb_util.c
index cc839b9a..a758026f 100644
--- a/hardinfo/usb_util.c
+++ b/hardinfo/usb_util.c
@@ -21,9 +21,12 @@
#include "hardinfo.h"
#include "usb_util.h"
+#include "util_ids.h"
#define SYSFS_DIR_USB_DEVICES "/sys/bus/usb/devices"
+gchar *usb_ids_file = NULL;
+
usbi *usbi_new() {
return g_new0(usbi, 1);
}
@@ -61,8 +64,10 @@ void usbd_free(usbd *s) {
g_free(s->device);
g_free(s->usb_version);
g_free(s->device_version);
+ g_free(s->serial);
g_free(s->dev_class_str);
g_free(s->dev_subclass_str);
+ g_free(s->dev_protocol_str);
g_free(s);
}
}
@@ -203,6 +208,19 @@ static gboolean usb_get_device_lsusb(int bus, int dev, usbd *s) {
s->dev_subclass = atoi(l);
if (t = strchr(l, ' '))
s->dev_subclass_str = g_strdup(t + 1);
+ } else if (l = lsusb_line_value(p, "bDeviceProtocol")) {
+ s->dev_protocol = atoi(l);
+ if (t = strchr(l, ' '))
+ s->dev_protocol_str = g_strdup(t + 1);
+ } else if (l = lsusb_line_value(p, "iManufacturer")) {
+ if (t = strchr(l, ' '))
+ s->manufacturer = g_strdup(t + 1);
+ } else if (l = lsusb_line_value(p, "iProduct")) {
+ if (t = strchr(l, ' '))
+ s->device = g_strdup(t + 1);
+ } else if (l = lsusb_line_value(p, "iSerial")) {
+ if (t = strchr(l, ' '))
+ s->serial = g_strdup(t + 1);
// interface info
} else if (l = lsusb_line_value(p, "bInterfaceNumber")) {
@@ -254,6 +272,7 @@ static gboolean usb_get_device_lsusb(int bus, int dev, usbd *s) {
static gboolean usb_get_interface_sysfs(int conf, int number,
const char* devpath, usbi *intf){
gchar *ifpath, *drvpath, *tmp;
+ ids_query_result result = {};
ifpath = g_strdup_printf("%s:%d.%d", devpath, conf, number);
if (!g_file_test(ifpath, G_FILE_TEST_EXISTS)){
@@ -279,17 +298,53 @@ static gboolean usb_get_interface_sysfs(int conf, int number,
if (intf->if_label == NULL)
intf->if_label = h_sysfs_read_string(ifpath, "interface");
+ if (intf->if_class_str == NULL && intf->if_subclass_str == NULL
+ && intf->if_protocol_str == NULL) {
+ tmp = g_strdup_printf("C %02x/%02x/%02x", intf->if_class,
+ intf->if_subclass, intf->if_protocol);
+ scan_ids_file(usb_ids_file, tmp, &result, -1);
+ if (result.results[0])
+ intf->if_class_str = g_strdup(result.results[0]);
+ if (result.results[1])
+ intf->if_subclass_str = g_strdup(result.results[1]);
+ if (result.results[2])
+ intf->if_protocol_str = g_strdup(result.results[2]);
+ g_free(tmp);
+ }
+
g_free(ifpath);
return TRUE;
}
+void find_usb_ids_file() {
+ if (usb_ids_file) return;
+ char *file_search_order[] = {
+ g_build_filename(g_get_user_config_dir(), "hardinfo", "usb.ids", NULL),
+ g_build_filename(params.path_data, "usb.ids", NULL),
+ NULL
+ };
+ int n;
+ for(n = 0; file_search_order[n]; n++) {
+ if (!usb_ids_file && !access(file_search_order[n], R_OK))
+ usb_ids_file = file_search_order[n];
+ else
+ g_free(file_search_order[n]);
+ }
+}
+
static gboolean usb_get_device_sysfs(int bus, int dev, const char* sysfspath, usbd *s) {
usbi *intf;
gboolean ok;
- int i, if_count = 0, conf = 0;
+ int i, if_count = 0, conf = 0, ver;
+ ids_query_result result = {};
+ gchar *qpath;
+
if (sysfspath == NULL)
return FALSE;
+ if (!usb_ids_file)
+ find_usb_ids_file();
+
s->bus = bus;
s->dev = dev;
s->dev_class = h_sysfs_read_hex(sysfspath, "bDeviceClass");
@@ -300,13 +355,48 @@ static gboolean usb_get_device_sysfs(int bus, int dev, const char* sysfspath, us
s->max_curr_ma = h_sysfs_read_int(sysfspath, "bMaxPower");
s->dev_class = h_sysfs_read_hex(sysfspath, "bDeviceClass");
s->dev_subclass = h_sysfs_read_hex(sysfspath, "bDeviceSubClass");
+ s->dev_protocol = h_sysfs_read_hex(sysfspath, "bDeviceProtocol");
s->speed_mbs = h_sysfs_read_int(sysfspath, "speed");
+ if (s->product == NULL && s->vendor == NULL) {
+ qpath = g_strdup_printf("%04x/%04x", s->vendor_id, s->product_id);
+ scan_ids_file(usb_ids_file, qpath, &result, -1);
+ if (result.results[0])
+ s->vendor = g_strdup(result.results[0]);
+ if (result.results[1])
+ s->product = g_strdup(result.results[1]);
+ g_free(qpath);
+ }
+
+ if (s->dev_class_str == NULL && s->dev_subclass_str == NULL
+ && s->dev_protocol_str == NULL) {
+ qpath = g_strdup_printf("C %02x/%02x/%02x", s->dev_class,
+ s->dev_subclass, s->dev_protocol);
+ scan_ids_file(usb_ids_file, qpath, &result, -1);
+ if (result.results[0])
+ s->dev_class_str = g_strdup(result.results[0]);
+ if (result.results[1])
+ s->dev_subclass_str = g_strdup(result.results[1]);
+ if (result.results[2])
+ s->dev_protocol_str = g_strdup(result.results[2]);
+ g_free(qpath);
+ }
+
conf = h_sysfs_read_hex(sysfspath, "bConfigurationValue");
if (s->usb_version == NULL)
s->usb_version = h_sysfs_read_string(sysfspath, "version");
+ if (s->serial == NULL)
+ s->serial = h_sysfs_read_string(sysfspath, "serial");
+
+ if (s->device_version == NULL) {
+ ver = h_sysfs_read_int(sysfspath, "bcdDevice");
+ if (ver > 0){
+ s->device_version = g_strdup_printf("%d.%02d", ver/100, ver%100);
+ }
+ }
+
if (s->if_list == NULL){ // create interfaces list
if_count = h_sysfs_read_int(sysfspath, "bNumInterfaces");
for (i = 0; i <= if_count; i++){
@@ -337,11 +427,12 @@ usbd *usb_get_device(int bus, int dev, const gchar* sysfspath) {
usbd *s = usbd_new();
int ok = 0;
if (s) {
- /* try lsusb */
- ok = usb_get_device_lsusb(bus, dev, s);
/* try sysfs */
- ok |= usb_get_device_sysfs(bus, dev, sysfspath, s);
-
+ ok = usb_get_device_sysfs(bus, dev, sysfspath, s);
+ if (!ok) {
+ /* try lsusb */
+ ok = usb_get_device_lsusb(bus, dev, s);
+ }
if (!ok) {
usbd_free(s);
s = NULL;
diff --git a/hardinfo/util.c b/hardinfo/util.c
index b35b2461..1b92457c 100644
--- a/hardinfo/util.c
+++ b/hardinfo/util.c
@@ -539,38 +539,6 @@ gboolean ui_init(int *argc, char ***argv)
return gtk_init_check(argc, argv);
}
-void open_url(gchar * url)
-{
- const gchar *browsers[] = {
- "xdg-open", "gnome-open", "kfmclient openURL",
- "sensible-browser", "firefox", "epiphany",
- "iceweasel", "seamonkey", "galeon", "mozilla",
- "opera", "konqueror", "netscape", "links -g",
- NULL
- };
- gint i = 0;
- gchar *browser = (gchar *)g_getenv("BROWSER");
-
- if (!browser || *browser == '\0') {
- browser = (gchar *)browsers[i++];
- }
-
- do {
- gchar *cmdline = g_strdup_printf("%s '%s'", browser, url);
-
- if (g_spawn_command_line_async(cmdline, NULL)) {
- g_free(cmdline);
- return;
- }
-
- g_free(cmdline);
-
- browser = (gchar *)browsers[i++];
- } while (browser);
-
- g_warning(_("Couldn't find a Web browser to open URL %s."), url);
-}
-
/* Copyright: Jens Låås, SLU 2002 */
gchar *strreplacechr(gchar * string, gchar * replace, gchar new_char)
{
diff --git a/hardinfo/vendor.c b/hardinfo/vendor.c
index bd2642d8..83c99fcf 100644
--- a/hardinfo/vendor.c
+++ b/hardinfo/vendor.c
@@ -26,9 +26,7 @@
#include "config.h"
#include "hardinfo.h"
#include "strstr_word.h"
-
-#include "dt_util.h" /* for appf() */
-#define SEQ(a,b) (g_strcmp0(a,b) == 0)
+#include "util_sysobj.h" /* for appfsp() and SEQ() */
/* { match_string, match_rule, name, url } */
static Vendor vendors_builtin[] = {
@@ -347,14 +345,14 @@ const Vendor *vendor_match(const gchar *id_str, ...) {
if (id_str) {
c++;
tl += strlen(id_str);
- tmp = appf(tmp, "%s", id_str);
+ tmp = appfsp(tmp, "%s", id_str);
va_start(ap, id_str);
p = va_arg(ap, gchar*);
while(p) {
c++;
tl += strlen(p);
- tmp = appf(tmp, "%s", p);
+ tmp = appfsp(tmp, "%s", p);
p = va_arg(ap, gchar*);
}
va_end(ap);
@@ -425,6 +423,11 @@ gchar *vendor_get_link(const gchar *id_str)
gchar *vendor_get_link_from_vendor(const Vendor *v)
{
+ gboolean label_link_ok = FALSE;
+#if GTK_CHECK_VERSION(2, 18, 0)
+ label_link_ok = TRUE;
+#endif
+
if (!v) {
return g_strdup(_("Unknown"));
}
@@ -433,7 +436,7 @@ gchar *vendor_get_link_from_vendor(const Vendor *v)
return g_strdup(v->name);
}
- if (params.markup_ok) {
+ if (params.markup_ok && label_link_ok) {
const gchar *prefix;
if (!strncmp(v->url, "http://", sizeof("http://") - 1) ||
@@ -506,14 +509,14 @@ vendor_list vendors_match(const gchar *id_str, ...) {
if (id_str) {
c++;
tl += strlen(id_str);
- tmp = appf(tmp, "%s", id_str);
+ tmp = appfsp(tmp, "%s", id_str);
va_start(ap, id_str);
p = va_arg(ap, gchar*);
while(p) {
c++;
tl += strlen(p);
- tmp = appf(tmp, "%s", p);
+ tmp = appfsp(tmp, "%s", p);
p = va_arg(ap, gchar*);
}
va_end(ap);