diff --git a/README.md b/README.md index 3076d86..70f3803 100644 --- a/README.md +++ b/README.md @@ -35,7 +35,12 @@ follows the [freedesktop.org Contributor Covenant]. ## Building -libdisplay-info is built using [Meson]. It has no dependencies. +libdisplay-info has the following dependencies: + +- [hwdata](https://github.com/vcrhonek/hwdata) for the PNP ID database + used at build-time only. + +libdisplay-info is built using [Meson]: meson setup build/ ninja -C build/ diff --git a/info.c b/info.c index 49c047a..f89f413 100644 --- a/info.c +++ b/info.c @@ -8,6 +8,10 @@ #include "info.h" #include "log.h" +/* Generated file pnp-id-table.c: */ +const char * +pnp_id_table(const char *key); + struct di_info * di_info_parse_edid(const void *data, size_t size) { @@ -136,6 +140,7 @@ di_info_get_make(const struct di_info *info) { const struct di_edid_vendor_product *evp; char pnp_id[(sizeof(evp->manufacturer)) + 1] = { 0, }; + const char *manuf; struct memory_stream m; if (!info->edid) @@ -147,7 +152,11 @@ di_info_get_make(const struct di_info *info) evp = di_edid_get_vendor_product(info->edid); memcpy(pnp_id, evp->manufacturer, sizeof(evp->manufacturer)); - /* TODO: use pnp.ids to convert to a company name */ + manuf = pnp_id_table(pnp_id); + if (manuf) { + encode_ascii_string(m.fp, manuf); + return memory_stream_close(&m); + } fputs("PNP(", m.fp); encode_ascii_string(m.fp, pnp_id); diff --git a/meson.build b/meson.build index 3e0f7ac..ebc3a13 100644 --- a/meson.build +++ b/meson.build @@ -10,6 +10,21 @@ project( ], ) +dep_hwdata = dependency('hwdata', required: false, native: true) +if dep_hwdata.found() + hwdata_dir = dep_hwdata.get_variable(pkgconfig: 'pkgdatadir') + pnp_ids = files(hwdata_dir / 'pnp.ids') +else + pnp_ids = files('/usr/share/hwdata/pnp.ids') +endif + +gen_search_table = find_program('tool/gen-search-table.py') +pnp_id_table = custom_target( + 'pnp-id-table.c', + command: [ gen_search_table, pnp_ids, '@OUTPUT@', 'pnp_id_table' ], + output: 'pnp-id-table.c', +) + cc = meson.get_compiler('c') math = cc.find_library('m', required: false) @@ -42,6 +57,7 @@ di_lib = library( 'gtf.c', 'info.c', 'log.c', + pnp_id_table, ], include_directories: include_directories('include'), dependencies: [math], diff --git a/test/data/acer-p1276.print b/test/data/acer-p1276.print index 1b82f1f..e0ef8ea 100644 --- a/test/data/acer-p1276.print +++ b/test/data/acer-p1276.print @@ -1,3 +1,3 @@ -make: PNP(ACR) +make: Acer Technologies model: P1276 serial: JGG110015900 diff --git a/test/data/apple-xdr-dp.print b/test/data/apple-xdr-dp.print index 60a75f0..a54556f 100644 --- a/test/data/apple-xdr-dp.print +++ b/test/data/apple-xdr-dp.print @@ -1,3 +1,3 @@ -make: PNP(APP) +make: Apple Computer Inc model: ProDisplayXDR serial: 0x250D0E02 diff --git a/test/data/custom-uncommon-cta-vesa.print b/test/data/custom-uncommon-cta-vesa.print index cfe972d..2462a6f 100644 --- a/test/data/custom-uncommon-cta-vesa.print +++ b/test/data/custom-uncommon-cta-vesa.print @@ -1,3 +1,3 @@ -make: PNP(LNX) +make: The Linux Foundation model: hdmi-4k-600 serial: {null} diff --git a/test/data/dell-2408wfp-dp.print b/test/data/dell-2408wfp-dp.print index c57d7cc..c9f58f9 100644 --- a/test/data/dell-2408wfp-dp.print +++ b/test/data/dell-2408wfp-dp.print @@ -1,3 +1,3 @@ -make: PNP(DEL) +make: Dell Inc. model: DELL 2408WFP serial: G283H8BI21MS diff --git a/test/data/goldstar-ite6604-hdmi.print b/test/data/goldstar-ite6604-hdmi.print index 2a427c6..002205e 100644 --- a/test/data/goldstar-ite6604-hdmi.print +++ b/test/data/goldstar-ite6604-hdmi.print @@ -1,3 +1,3 @@ -make: PNP(GSM) +make: LG Electronics model: ITE6604 serial: 0x01010101 diff --git a/test/data/hp-5dq99aa-hdmi.print b/test/data/hp-5dq99aa-hdmi.print index 84c6ba6..045a802 100644 --- a/test/data/hp-5dq99aa-hdmi.print +++ b/test/data/hp-5dq99aa-hdmi.print @@ -1,3 +1,3 @@ -make: PNP(HPN) +make: HP Inc. model: HP 27 QD serial: CN49120J6N diff --git a/test/data/msi-mag321curv-dp.print b/test/data/msi-mag321curv-dp.print index 35d5b43..f2e157b 100644 --- a/test/data/msi-mag321curv-dp.print +++ b/test/data/msi-mag321curv-dp.print @@ -1,3 +1,3 @@ -make: PNP(MSI) +make: Microstep model: MAG321CURV serial: DA2A019360041 diff --git a/test/data/panasonic-mei96a2-dp.print b/test/data/panasonic-mei96a2-dp.print index bf8142f..ab7408d 100644 --- a/test/data/panasonic-mei96a2-dp.print +++ b/test/data/panasonic-mei96a2-dp.print @@ -1,3 +1,3 @@ -make: PNP(MEI) +make: Panasonic Industry Company model: 0x96A2 serial: {null} diff --git a/test/data/samsung-s27a950d-dp.print b/test/data/samsung-s27a950d-dp.print index eb6ae6d..c43f26e 100644 --- a/test/data/samsung-s27a950d-dp.print +++ b/test/data/samsung-s27a950d-dp.print @@ -1,3 +1,3 @@ -make: PNP(SAM) +make: Samsung Electric Company model: S27A950D serial: {null} diff --git a/test/data/sun-gh19ps-dvi.print b/test/data/sun-gh19ps-dvi.print index 8651950..2a258a1 100644 --- a/test/data/sun-gh19ps-dvi.print +++ b/test/data/sun-gh19ps-dvi.print @@ -1,3 +1,3 @@ -make: PNP(SUN) +make: Sun Electronics Corporation model: GH19PS serial: 0432MR0406 diff --git a/test/data/viewsonic-vp2768-dp.print b/test/data/viewsonic-vp2768-dp.print index 989cfd3..6d4ba5d 100644 --- a/test/data/viewsonic-vp2768-dp.print +++ b/test/data/viewsonic-vp2768-dp.print @@ -1,3 +1,3 @@ -make: PNP(VSC) +make: ViewSonic Corporation model: VP2768 Series serial: UY5171500307 diff --git a/tool/gen-search-table.py b/tool/gen-search-table.py new file mode 100755 index 0000000..5e95c0d --- /dev/null +++ b/tool/gen-search-table.py @@ -0,0 +1,91 @@ +#!/usr/bin/env python3 + +""" +string to string mapping table + +License: MIT + +Copyright (c) 2020 Simon Ser +Copyright 2022 Collabora, Ltd. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +""" + +import sys + +def escape_for_c(s): + l = [c if c.isalnum() or c in ' .,' else '\\%03o' % ord(c) for c in s] + return ''.join(l) + +if len(sys.argv) != 4: + print('usage: ' + sys.argv[0] + ' ', file=sys.stderr) + sys.exit(1) + +infile = sys.argv[1] +outfile = sys.argv[2] +ident = sys.argv[3] + +records = {} + +with open(infile, 'r') as f: + for line in f: + [pnpid, name] = line.split(maxsplit=1) + + if len(pnpid) != 3: + print("Warning: skipping invalid PNP ID %s" % (repr(pnpid)), file=sys.stderr) + continue + + records[pnpid] = escape_for_c(name.strip()) + +with open(outfile, 'w') as f: + f.write( +f''' +#include +#include + +const char * +{ident}(const char *key); + +const char * +{ident}(const char *key) +{{ + size_t len = strlen(key); + size_t i; + uint32_t u = 0; + + if (len > 4) + return NULL; + + for (i = 0; i < len; i++) + u = (u << 8) | (uint8_t)key[i]; + + switch (u) {{ +''') + for id in sorted(records.keys()): + u = 0 + for c in id: + u = (u << 8) | ord(c) + f.write(f' case {u}: return "{records[id]}";\n') + f.write( +f''' + default: + return NULL; + }} +}} +''')