aboutsummaryrefslogtreecommitdiff
path: root/deps/sysobj_early
diff options
context:
space:
mode:
authorBurt P <pburt0@gmail.com>2019-08-16 22:55:18 -0500
committerLeandro A. F. Pereira <leandro@hardinfo.org>2019-08-18 23:49:29 +0200
commite49e438270cdffc4a80a2676c73ad95bedce33d4 (patch)
tree769017d433a3004202ea6769d4d0fca40f3099d1 /deps/sysobj_early
parentd55a8f33188eb35e918d5c6c355d686867315337 (diff)
Devices/Monitors
Signed-off-by: Burt P <pburt0@gmail.com>
Diffstat (limited to 'deps/sysobj_early')
-rw-r--r--deps/sysobj_early/data/edid.ids98
-rw-r--r--deps/sysobj_early/include/util_edid.h68
-rw-r--r--deps/sysobj_early/src/appf.c8
-rw-r--r--deps/sysobj_early/src/util_edid.c319
4 files changed, 492 insertions, 1 deletions
diff --git a/deps/sysobj_early/data/edid.ids b/deps/sysobj_early/data/edid.ids
new file mode 100644
index 00000000..575287b6
--- /dev/null
+++ b/deps/sysobj_early/data/edid.ids
@@ -0,0 +1,98 @@
+#
+# https://github.com/bp0/verbose-spork/blob/master/data/edid.ids
+#
+# List of known/observed EDID three-letter vendor codes
+# See http://edid.tv/manufacturer
+# These codes are also the three-letter "EISA" or "PNP" codes.
+# See http://uefi.org/sites/default/files/resources/PNPID_List.pdf
+#
+# Syntax:
+# VEN Vendor Name
+#
+# Please keep sorted.
+#
+
+AAA Avolites
+ACI Ancor Communications
+ACR Acer Technologies
+ADA Addi-Data GmbH
+AGO AlgolTek
+AOC AOC International
+APP Apple Computer
+ATO ASTRO DESIGN
+AUO AU Optronics
+AVT Avtek
+BMD Blackmagic Design
+BNO Bang & Olufsen
+BNQ BenQ
+BOE BOE
+CMN Chimei Innolux Corporation
+CMO Chi Mei Optoelectronics
+CRO Extraordinary Technologies
+CUK Calibre UK
+DEL Dell
+DGC Data General Corporation
+DON DENON
+ENC Eizo Nanao Corporation
+EPH Epiphan Systems
+EXP Data Export Corporation
+FNI Funai Electric
+FUS Fujitsu Siemens Computers
+GSM Goldstar Company
+HIQ Kaohsiung Opto Electronics Americas
+HPN Hewlett-Packard Company
+HSD HannStar Display Corporation
+HTC Hitachi
+HWP Hewlett-Packard Company
+IBM International Business Machines
+INO Innolab Pte Ltd
+INT Interphase Corporation
+INX Communications Supply Corporation (A division of WESCO)
+ITE Integrated Tech Express
+IVM Iiyama North America
+JVC Victor Company of Japan (JVC)
+KTC Kingston Tech Corporation
+LEN Lenovo Group
+LGD LG Display
+LNX The Linux Foundation
+LWR Lightware Visual Engineering
+MAX Rogen Tech Distribution
+MEG Abeam Tech
+MEI Panasonic Industry Company
+MGW Magewell
+MST MS Telematica
+MTC Mars-Tech Corporation
+MTX Matrox
+NEC NEC Corporation
+NEX Nexgen Mediatech
+ONK ONKYO Corporation
+ORN ORION ELECTRIC
+OTM Optoma Corporation
+OVR Oculus VR
+PHL Koninklijke Philips
+PIO Pioneer Electronic Corporation
+PLN Planar
+PNR Planar Systems
+QDS Quanta Display
+RAT Rent-A-Tech
+REN Renesas Technology Corporation
+SAM Samsung Electric Company
+SAN Sanyo Electric Company
+SEC Seiko Epson Corporation
+SHP Sharp Corporation
+SII Silicon Image
+SNY Sony
+STD STD Computer
+SVS AMX (Harman, SVSI)
+SYN Synaptics
+TCL Technical Concepts
+TDC Teradici
+TOP Orion Communications Company
+TSB Toshiba Corporation
+TST Transtream
+VES Vestel Elektronik Sanayi ve Ticaret A. S.
+VIT Visitech
+VIZ Vizio
+VSC ViewSonic Corporation
+WDE Westinghouse Digital Electronics
+YMH Yamaha Corporation
diff --git a/deps/sysobj_early/include/util_edid.h b/deps/sysobj_early/include/util_edid.h
new file mode 100644
index 00000000..3d54fa0d
--- /dev/null
+++ b/deps/sysobj_early/include/util_edid.h
@@ -0,0 +1,68 @@
+/*
+ * 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_EDID_H__
+#define __UTIL_EDID_H__
+
+#include <stdint.h> /* for *int*_t types */
+
+#define EDID_MAX_EXT_BLOCKS 254
+
+/* just enough edid decoding */
+struct edid {
+ int ver_major, ver_minor;
+ char ven[4];
+
+ int d_type[4];
+ char d_text[4][14];
+
+ /* point into d_text */
+ char *name;
+ char *serial;
+ char *ut1;
+ char *ut2;
+
+ int a_or_d; /* 0 = analog, 1 = digital */
+ int bpc;
+
+ uint16_t product;
+ uint32_t n_serial;
+ int week, year;
+
+ int horiz_cm, vert_cm;
+ float diag_cm, diag_in;
+
+ int size; /* bytes */
+ int checksum_ok; /* block 0 */
+
+ int ext_blocks, ext_blocks_ok, ext_blocks_fail;
+ uint8_t ext[EDID_MAX_EXT_BLOCKS][2]; /* block type, checksum_ok */
+};
+
+int edid_fill(struct edid *id_out, const void *edid_bytes, int edid_len);
+int edid_fill_xrandr(struct edid *id_out, const char *xrandr_edid_dump);
+
+int edid_hex_to_bin(void **edid_bytes, int *edid_len, const char *hex_string);
+char *edid_bin_to_hex(const void *edid_bytes, int edid_len);
+
+const char *edid_descriptor_type(int type);
+char *edid_dump(struct edid *id);
+
+#endif
diff --git a/deps/sysobj_early/src/appf.c b/deps/sysobj_early/src/appf.c
index 432e0f30..5969d945 100644
--- a/deps/sysobj_early/src/appf.c
+++ b/deps/sysobj_early/src/appf.c
@@ -18,12 +18,18 @@
*
*/
-#include "appf.h"
#define _GNU_SOURCE /* for vasprintf() */
#include <stdlib.h>
#include <stdarg.h>
#include <stdio.h>
#include <string.h>
+#include "appf.h"
+
+/* FIXME: if this isn't here, hardinfo will crash,
+ * I don't have the slightest idea why */
+void wtf() {
+ edid_fill(NULL, NULL, 0);
+}
char *appf(char *str, const char *sep, const char *fmt, ...) {
char *buf = NULL;
diff --git a/deps/sysobj_early/src/util_edid.c b/deps/sysobj_early/src/util_edid.c
new file mode 100644
index 00000000..3f953191
--- /dev/null
+++ b/deps/sysobj_early/src/util_edid.c
@@ -0,0 +1,319 @@
+/*
+ * 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.
+ *
+ */
+
+#define _GNU_SOURCE
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <math.h>
+#include <endian.h>
+#include <stdio.h>
+#include "util_edid.h"
+#include "util_sysobj.h"
+#include "gettext.h"
+
+/* block must be 128 bytes */
+int block_check(const void *edid_block_bytes) {
+ if (!edid_block_bytes) return 0;
+ uint8_t sum = 0;
+ uint8_t *data = (uint8_t*)edid_block_bytes;
+ int i;
+ for(i=0; i<128; i++)
+ sum += data[i];
+ return sum == 0 ? 1 : 0;
+}
+
+int edid_fill(struct edid *id_out, const void *edid_bytes, int edid_len) {
+ int i;
+
+ if (!id_out) return 0;
+
+ memset(id_out, 0, sizeof(struct edid));
+ id_out->size = edid_len;
+
+ if (edid_len >= 128) {
+ uint8_t *u8 = (uint8_t*)edid_bytes;
+ uint16_t *u16 = (uint16_t*)edid_bytes;
+ uint32_t *u32 = (uint32_t*)edid_bytes;
+
+ id_out->ver_major = u8[18]; /* byte 18 */
+ id_out->ver_minor = u8[19]; /* byte 19 */
+
+ /* checksum first block */
+ id_out->checksum_ok = block_check(edid_bytes);
+ if (edid_len > 128) {
+ int blocks = edid_len / 128;
+ if (blocks > EDID_MAX_EXT_BLOCKS) blocks = EDID_MAX_EXT_BLOCKS;
+ blocks--;
+ id_out->ext_blocks = blocks;
+ for(; blocks; blocks--) {
+ id_out->ext[blocks-1][0] = *(u8 + (blocks * 128));
+ int r = block_check(u8 + (blocks * 128));
+ id_out->ext[blocks-1][1] = (uint8_t)r;
+ if (r) id_out->ext_blocks_ok++;
+ else id_out->ext_blocks_fail++;
+ }
+ }
+
+ /* expect 1.3 */
+
+ uint16_t vid = be16toh(u16[4]); /* bytes 8-9 */
+ id_out->ven[2] = 64 + (vid & 0x1f);
+ id_out->ven[1] = 64 + ((vid >> 5) & 0x1f);
+ id_out->ven[0] = 64 + ((vid >> 10) & 0x1f);
+
+ id_out->product = le16toh(u16[5]); /* bytes 10-11 */
+ id_out->n_serial = le32toh(u32[3]);/* bytes 12-15 */
+ id_out->week = u8[16]; /* byte 16 */
+ id_out->year = u8[17] + 1990; /* byte 17 */
+
+ if (id_out->week >= 52)
+ id_out->week = 0;
+
+ id_out->a_or_d = (u8[20] & 0x80) ? 1 : 0;
+ if (id_out->a_or_d == 1) {
+ /* digital */
+ switch((u8[20] >> 4) & 0x7) {
+ case 0x1: id_out->bpc = 6; break;
+ case 0x2: id_out->bpc = 8; break;
+ case 0x3: id_out->bpc = 10; break;
+ case 0x4: id_out->bpc = 12; break;
+ case 0x5: id_out->bpc = 14; break;
+ case 0x6: id_out->bpc = 16; break;
+ }
+ }
+
+ if (u8[21] && u8[22]) {
+ id_out->horiz_cm = u8[21];
+ id_out->vert_cm = u8[22];
+ id_out->diag_cm =
+ sqrt( (id_out->horiz_cm * id_out->horiz_cm)
+ + (id_out->vert_cm * id_out->vert_cm) );
+ id_out->diag_in = id_out->diag_cm / 2.54;
+ }
+
+ uint16_t dh, dl;
+
+ /* descriptor at byte 54 */
+ dh = be16toh(u16[54/2]);
+ dl = be16toh(u16[54/2+1]);
+ id_out->d_type[0] = (dh << 16) + dl;
+ switch(id_out->d_type[0]) {
+ case 0xfc: case 0xff: case 0xfe:
+ strncpy(id_out->d_text[0], (char*)u8+54+5, 13);
+ }
+
+ /* descriptor at byte 72 */
+ dh = be16toh(u16[72/2]);
+ dl = be16toh(u16[72/2+1]);
+ id_out->d_type[1] = (dh << 16) + dl;
+ switch(id_out->d_type[1]) {
+ case 0xfc: case 0xff: case 0xfe:
+ strncpy(id_out->d_text[1], (char*)u8+72+5, 13);
+ }
+
+ /* descriptor at byte 90 */
+ dh = be16toh(u16[90/2]);
+ dl = be16toh(u16[90/2+1]);
+ id_out->d_type[2] = (dh << 16) + dl;
+ switch(id_out->d_type[2]) {
+ case 0xfc: case 0xff: case 0xfe:
+ strncpy(id_out->d_text[2], (char*)u8+90+5, 13);
+ }
+
+ /* descriptor at byte 108 */
+ dh = be16toh(u16[108/2]);
+ dl = be16toh(u16[108/2+1]);
+ id_out->d_type[3] = (dh << 16) + dl;
+ switch(id_out->d_type[3]) {
+ case 0xfc: case 0xff: case 0xfe:
+ strncpy(id_out->d_text[3], (char*)u8+108+5, 13);
+ }
+
+ for(i = 0; i < 4; i++) {
+ g_strstrip(id_out->d_text[i]);
+ switch(id_out->d_type[i]) {
+ case 0xfc:
+ id_out->name = id_out->d_text[i];
+ break;
+ case 0xff:
+ id_out->serial = id_out->d_text[i];
+ break;
+ case 0xfe:
+ if (id_out->ut1)
+ id_out->ut2 = id_out->d_text[i];
+ else
+ id_out->ut1 = id_out->d_text[i];
+ break;
+ }
+ }
+
+ if (!id_out->name) {
+ if (SEQ(id_out->ut1, "LG Display") && id_out->ut2)
+ /* LG may use "uspecified text" for name and model */
+ id_out->name = id_out->ut2;
+ else if (SEQ(id_out->ut1, "AUO") && id_out->ut2)
+ /* Same with AUO */
+ id_out->name = id_out->ut2;
+ else {
+ if (id_out->ut1) id_out->name = id_out->ut1;
+ if (id_out->ut2 && !id_out->serial) id_out->serial = id_out->ut2;
+ }
+ }
+ }
+ return 1;
+}
+
+int edid_hex_to_bin(void **edid_bytes, int *edid_len, const char *hex_string) {
+ int blen = strlen(hex_string) / 2;
+ uint8_t *buffer = malloc(blen), *n = buffer;
+ memset(buffer, 0, blen);
+ int len = 0;
+
+ const char *p = hex_string;
+ char byte[3] = "..";
+
+ while(p && *p) {
+ if (isxdigit(p[0]) && isxdigit(p[1])) {
+ byte[0] = p[0];
+ byte[1] = p[1];
+ *n = strtol(byte, NULL, 16);
+ n++;
+ len++;
+ p += 2;
+ } else
+ p++;
+ }
+
+ *edid_bytes = (void *)buffer;
+ *edid_len = len;
+ return 1;
+}
+
+int edid_fill_xrandr(struct edid *id_out, const char *xrandr_edid_dump) {
+ void *buffer = NULL;
+ int len = 0;
+ edid_hex_to_bin(&buffer, &len, xrandr_edid_dump);
+ return edid_fill(id_out, buffer, len);
+}
+
+const char *edid_ext_block_type(int type) {
+ switch(type) {
+ case 0xf0:
+ return N_("extension block map");
+ case 0x02:
+ return N_("EIA/CEA-861 extension block");
+ }
+ return N_("unknown block type");
+}
+
+const char *edid_descriptor_type(int type) {
+ switch(type) {
+ case 0xff:
+ return N_("display serial number");
+ case 0xfe:
+ return N_("unspecified text");
+ case 0xfd:
+ return N_("display range limits");
+ case 0xfc:
+ return N_("display name");
+ case 0xfb:
+ return N_("additional white point");
+ case 0xfa:
+ return N_("additional standard timing identifiers");
+ case 0xf9:
+ return N_("Display Color Management");
+ case 0xf8:
+ return N_("CVT 3-byte timing codes");
+ case 0xf7:
+ return N_("additional standard timing");
+ case 0x10:
+ return N_("dummy");
+ }
+ if (type < 0x0f) return N_("manufacturer reserved descriptor");
+ return N_("detailed timing descriptor");
+}
+
+char *edid_dump(struct edid *id) {
+ char *ret = NULL;
+ int i;
+
+ if (!id) return NULL;
+ ret = appfnl(ret, "edid_version: %d.%d (%d bytes)", id->ver_major, id->ver_minor, id->size);
+
+ ret = appfnl(ret, "mfg: %s, model: %u, n_serial: %u", id->ven, id->product, id->n_serial);
+ if (id->week && id->year)
+ ret = appf(ret, "", ", dom: week %d of %d", id->week, id->year);
+ else if (id->year)
+ ret = appf(ret, "", ", dom: %d", id->year);
+
+ ret = appfnl(ret, "type: %s", id->a_or_d ? "digital" : "analog");
+ if (id->bpc)
+ ret = appfnl(ret, "bits per color channel: %d", id->bpc);
+
+ if (id->horiz_cm && id->vert_cm)
+ ret = appfnl(ret, "size: %d cm × %d cm", id->horiz_cm, id->vert_cm);
+ if (id->diag_cm)
+ ret = appfnl(ret, "diagonal: %0.2f cm (%0.2f in)", id->diag_cm, id->diag_in);
+
+ ret = appfnl(ret, "checksum %s", id->checksum_ok ? "ok" : "failed!");
+ if (id->ext_blocks_ok || id->ext_blocks_fail)
+ ret = appf(ret, "", ", extension blocks: %d of %d ok", id->ext_blocks_ok, id->ext_blocks_ok + id->ext_blocks_fail);
+
+ for(i = 0; i < 4; i++)
+ ret = appfnl(ret, "descriptor[%d] (%s): %s", i, _(edid_descriptor_type(id->d_type[i])), *id->d_text[i] ? id->d_text[i] : "{...}");
+
+ for(i = 0; i < EDID_MAX_EXT_BLOCKS; i++) {
+ if (id->ext[i][0]) {
+ ret = appfnl(ret, "ext_block[%d]: (%s): %s", i, _(edid_ext_block_type(id->ext[i][0])), id->ext[i][1] ? "ok" : "fail");
+ }
+ }
+
+ return ret;
+}
+
+char *edid_bin_to_hex(const void *edid_bytes, int edid_len) {
+ int lines = edid_len / 16;
+ int blen = lines * 35 + 1;
+ int pc = 0;
+ char *ret = malloc(blen);
+ memset(ret, 0, blen);
+ uint8_t *u8 = (uint8_t*)edid_bytes;
+ char *p = ret;
+ for(; lines; lines--) {
+ sprintf(p, "\t\t");
+ p+=2;
+ int i;
+ for(i = 0; i < 16; i++) {
+ sprintf(p, "%02x", (unsigned int)*u8);
+ p+=2;
+ u8++;
+ pc++;
+ if (pc == blen-1) {
+ sprintf(p, "\n");
+ goto edid_print_done;
+ }
+ }
+ sprintf(p, "\n");
+ p++;
+ }
+edid_print_done:
+ return ret;
+}