Skip to content

Commit 96d885e

Browse files
committed
GPU: embed pci.ids into fastfetch
1 parent ae6817e commit 96d885e

File tree

8 files changed

+191
-38
lines changed

8 files changed

+191
-38
lines changed

CMakeLists.txt

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@ option(BUILD_TESTS "Build tests" OFF) # Also create test executables
8080
option(SET_TWEAK "Add tweak to project version" ON) # This is set to off by github actions for release builds
8181
option(IS_MUSL "Build with musl libc" OFF) # Used by Github Actions
8282
option(INSTALL_LICENSE "Install license into /usr/share/licenses" ON)
83+
option(ENABLE_EMBEDDED_PCIIDS "Embed pci.ids into fastfetch, requires `python`" OFF)
8384

8485
set(BINARY_LINK_TYPE_OPTIONS dlopen dynamic static)
8586
set(BINARY_LINK_TYPE dlopen CACHE STRING "How to link fastfetch")
@@ -254,6 +255,16 @@ else()
254255
file(READ "src/data/help.json" DATATEXT_JSON_HELP)
255256
endif()
256257

258+
if(ENABLE_EMBEDDED_PCIIDS AND NOT EXISTS "fastfetch_pciids.c.inc")
259+
if(Python_FOUND)
260+
execute_process(COMMAND ${Python_EXECUTABLE} "${CMAKE_CURRENT_SOURCE_DIR}/scripts/gen-pciids.py"
261+
OUTPUT_FILE "fastfetch_pciids.c.inc")
262+
else()
263+
message(STATUS "Python3 is not found, 'fastfetch_pciids.c.inc' will not be generated")
264+
set(ENABLE_EMBEDDED_PCIIDS OFF)
265+
endif()
266+
endif()
267+
257268
fastfetch_encode_c_string("${DATATEXT_JSON_HELP}" DATATEXT_JSON_HELP)
258269
fastfetch_load_text(src/data/structure.txt DATATEXT_STRUCTURE)
259270
fastfetch_load_text(src/data/help_footer.txt DATATEXT_HELP_FOOTER)
@@ -1130,14 +1141,17 @@ if(ENABLE_LIBZFS)
11301141
endif()
11311142
endif()
11321143

1133-
11341144
if(ENABLE_THREADS)
1135-
target_compile_definitions(libfastfetch PRIVATE FF_HAVE_THREADS)
1145+
target_compile_definitions(libfastfetch PRIVATE FF_HAVE_THREADS=1)
11361146
if(CMAKE_USE_PTHREADS_INIT) #Threads::Threads is not set for WIN32
11371147
target_link_libraries(libfastfetch PRIVATE Threads::Threads)
11381148
endif()
11391149
endif()
11401150

1151+
if(ENABLE_EMBEDDED_PCIIDS)
1152+
target_compile_definitions(libfastfetch PRIVATE FF_HAVE_EMBEDDED_PCIIDS=1)
1153+
endif()
1154+
11411155
if(LINUX)
11421156
target_link_libraries(libfastfetch
11431157
PRIVATE "m"

scripts/gen-pciids.py

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
from requests import get as http_get
2+
3+
class PciDeviceModel:
4+
def __init__(self, id: int, name: str):
5+
self.id = id
6+
self.name = name
7+
8+
class PciVendorModel:
9+
def __init__(self, id: int, name: str):
10+
self.id = id
11+
self.name = name
12+
self.devices: list[PciDeviceModel] = []
13+
14+
def main(keep_vendor_list: set[int]):
15+
vendors: list[PciVendorModel] = []
16+
try:
17+
with open('pci.ids', 'r') as f:
18+
full_text = f.read()
19+
except FileNotFoundError:
20+
response = http_get('https://pci-ids.ucw.cz/v2.2/pci.ids')
21+
full_text = response.text
22+
23+
dev_list_text = full_text[:full_text.rfind('\n\n\n')] # remove known classes
24+
for line in dev_list_text.split('\n'):
25+
if not line or line[0] == '#':
26+
continue
27+
if line[0] != '\t':
28+
id, name = line.split(' ', maxsplit=1)
29+
vendors.append(PciVendorModel(int(id, 16), name))
30+
elif line[1] != '\t':
31+
id, name = line[1:].split(' ', maxsplit=1)
32+
vendors[-1].devices.append(PciDeviceModel(int(id, 16), name))
33+
34+
code = """\
35+
#include <stdint.h>
36+
#include <stddef.h>
37+
38+
typedef struct FFPciDevice
39+
{
40+
const uint32_t id;
41+
const char* name;
42+
} FFPciDevice;
43+
44+
typedef struct FFPciVendor
45+
{
46+
const uint32_t id;
47+
const char* name;
48+
const FFPciDevice* devices;
49+
const uint32_t nDevices;
50+
} FFPciVendor;
51+
"""
52+
53+
if keep_vendor_list:
54+
vendors = [vendor for vendor in vendors if vendor.id in keep_vendor_list]
55+
56+
for vendor in vendors:
57+
if vendor.devices:
58+
code += f"""
59+
// {vendor.name}
60+
static const FFPciDevice pciDevices_{vendor.id:04X}[] = {{
61+
{',\n '.join(f'{{ 0x{device.id:04X}, "{device.name.replace('"', '\\"')}" }}' for device in vendor.devices)},
62+
{{}},
63+
}};
64+
"""
65+
66+
code += f"""
67+
const FFPciVendor ffPciVendors[] = {{
68+
{',\n '.join(f'{{ 0x{vendor.id:04X}, "{vendor.name.replace('"', '\\"')}", {vendor.devices and f"pciDevices_{vendor.id:04X}" or "NULL"}, {len(vendor.devices)} }}' for vendor in vendors)},
69+
{{}},
70+
}};"""
71+
72+
print(code)
73+
74+
if __name__ == '__main__':
75+
# From <src/detection/gpu/gpu.c>
76+
main({
77+
0x106b, # Apple
78+
0x1002, 0x1022, # AMD
79+
0x8086, 0x8087, 0x03e7, # Intel
80+
0x0955, 0x10de, 0x12d2, # Nvidia
81+
0x1ed5, # MThreads
82+
0x5143, # Qualcomm
83+
0x14c3, # MTK
84+
0x15ad, # VMware
85+
0x1af4, # RedHat
86+
0x1ab8, # Parallel
87+
0x1414, # Microsoft
88+
0x108e, # Oracle
89+
})

src/common/init.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -260,6 +260,9 @@ void ffListFeatures(void)
260260
#if FF_HAVE_LINUX_WIRELESS
261261
"linux/wireless\n"
262262
#endif
263+
#if FF_HAVE_EMBEDDED_PCIIDS
264+
"Embedded pciids\n"
265+
#endif
263266
""
264267
, stdout);
265268
}

src/detection/gpu/gpu.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,5 +49,5 @@ const char* ffDetectGPUImpl(const FFGPUOptions* options, FFlist* gpus);
4949
const char* ffGetGPUVendorString(unsigned vendorId);
5050

5151
#if defined(__linux__) || defined(__FreeBSD__) || defined(__sun)
52-
void ffGPUParsePciIds(uint8_t subclass, uint16_t vendor, uint16_t device, FFGPUResult* gpu);
52+
void ffGPUFillVendorAndName(uint8_t subclass, uint16_t vendor, uint16_t device, FFGPUResult* gpu);
5353
#endif

src/detection/gpu/gpu_bsd.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ const char* ffDetectGPUImpl(const FFGPUOptions* options, FFlist* gpus)
5858

5959
if (gpu->name.length == 0)
6060
{
61-
ffGPUParsePciIds(pc->pc_subclass, pc->pc_vendor, pc->pc_device, gpu);
61+
ffGPUFillVendorAndName(pc->pc_subclass, pc->pc_vendor, pc->pc_device, gpu);
6262
}
6363

6464
if (gpu->vendor.chars == FF_GPU_VENDOR_NAME_NVIDIA && (options->temp || options->driverSpecific))

src/detection/gpu/gpu_linux.c

Lines changed: 1 addition & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -228,29 +228,6 @@ static void pciDetectIntelSpecific(FFGPUResult* gpu, FFstrbuf* pciDir, FFstrbuf*
228228
gpu->frequency = (uint32_t) ffStrbufToUInt(buffer, 0);
229229
}
230230

231-
static bool loadPciIds(FFstrbuf* pciids)
232-
{
233-
#ifdef FF_CUSTOM_PCI_IDS_PATH
234-
235-
ffReadFileBuffer(FF_STR(FF_CUSTOM_PCI_IDS_PATH), pciids);
236-
if (pciids->length > 0) return true;
237-
238-
#else
239-
240-
ffReadFileBuffer(FASTFETCH_TARGET_DIR_USR "/share/hwdata/pci.ids", pciids);
241-
if (pciids->length > 0) return true;
242-
243-
ffReadFileBuffer(FASTFETCH_TARGET_DIR_USR "/share/misc/pci.ids", pciids); // debian?
244-
if (pciids->length > 0) return true;
245-
246-
ffReadFileBuffer(FASTFETCH_TARGET_DIR_USR "/local/share/hwdata/pci.ids", pciids);
247-
if (pciids->length > 0) return true;
248-
249-
#endif
250-
251-
return false;
252-
}
253-
254231
static const char* detectPci(const FFGPUOptions* options, FFlist* gpus, FFstrbuf* buffer, FFstrbuf* deviceDir, const char* drmKey)
255232
{
256233
const uint32_t drmDirPathLength = deviceDir->length;
@@ -303,7 +280,7 @@ static const char* detectPci(const FFGPUOptions* options, FFlist* gpus, FFstrbuf
303280

304281
if (gpu->name.length == 0)
305282
{
306-
ffGPUParsePciIds(subclassId, (uint16_t) vendorId, (uint16_t) deviceId, gpu);
283+
ffGPUFillVendorAndName(subclassId, (uint16_t) vendorId, (uint16_t) deviceId, gpu);
307284
}
308285

309286
pciDetectDriver(&gpu->driver, deviceDir, buffer, drmKey);

src/detection/gpu/gpu_pci.c

Lines changed: 79 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,21 @@
11
#include "gpu.h"
2+
#include "common/io/io.h"
23

4+
#include <stdlib.h>
35
#ifdef __FreeBSD__
46
#include <paths.h>
57
#endif
68

9+
#if FF_HAVE_EMBEDDED_PCIIDS
10+
#include "fastfetch_pciids.c.inc"
11+
#endif
12+
713
static const FFstrbuf* loadPciIds()
814
{
915
static FFstrbuf pciids;
1016

1117
if (pciids.chars) return &pciids;
12-
ffStrbufinit(&pciids);
18+
ffStrbufInit(&pciids);
1319

1420
#ifdef FF_CUSTOM_PCI_IDS_PATH
1521

@@ -18,16 +24,18 @@ static const FFstrbuf* loadPciIds()
1824
#else // FF_CUSTOM_PCI_IDS_PATH
1925

2026
#if __linux__
21-
ffReadFileBuffer(FASTFETCH_TARGET_DIR_USR "/share/hwdata/pci.ids", pciids);
27+
ffReadFileBuffer(FASTFETCH_TARGET_DIR_USR "/share/hwdata/pci.ids", &pciids);
2228
if (pciids.length == 0)
23-
ffReadFileBuffer(FASTFETCH_TARGET_DIR_USR "/share/misc/pci.ids", pciids); // debian?
24-
if (pciids.length == 0)
25-
ffReadFileBuffer(FASTFETCH_TARGET_DIR_USR "/local/share/hwdata/pci.ids", pciids);
29+
{
30+
ffReadFileBuffer(FASTFETCH_TARGET_DIR_USR "/share/misc/pci.ids", &pciids); // debian?
31+
if (pciids.length == 0)
32+
ffReadFileBuffer(FASTFETCH_TARGET_DIR_USR "/local/share/hwdata/pci.ids", &pciids);
33+
}
2634
#elif __FreeBSD__
2735
// https://github.com/freebsd/freebsd-src/blob/main/usr.sbin/pciconf/pathnames.h
28-
ffReadFileBuffer(_PATH_LOCALBASE "/share/pciids/pci.ids", pciids);
36+
ffReadFileBuffer(_PATH_LOCALBASE "/share/pciids/pci.ids", &pciids);
2937
if (pciids.length == 0)
30-
ffReadFileBuffer(FASTFETCH_TARGET_DIR_USR "/share/pciids/pci.ids", pciids);
38+
ffReadFileBuffer(FASTFETCH_TARGET_DIR_USR "/share/pciids/pci.ids", &pciids);
3139
#elif __sun
3240
ffReadFileBuffer(FASTFETCH_TARGET_DIR_ROOT "/usr/share/hwdata/pci.ids", &pciids);
3341
#endif
@@ -37,9 +45,8 @@ static const FFstrbuf* loadPciIds()
3745
return &pciids;
3846
}
3947

40-
void ffGPUParsePciIds(uint8_t subclass, uint16_t vendor, uint16_t device, FFGPUResult* gpu)
48+
static void parsePciIdsFile(const FFstrbuf* content, uint8_t subclass, uint16_t vendor, uint16_t device, FFGPUResult* gpu)
4149
{
42-
const FFstrbuf* content = loadPciIds();
4350
if (content->length)
4451
{
4552
char buffer[32];
@@ -112,3 +119,66 @@ void ffGPUParsePciIds(uint8_t subclass, uint16_t vendor, uint16_t device, FFGPUR
112119
ffStrbufSetF(&gpu->name, "%s Device %04X%s", gpu->vendor.length ? gpu->vendor.chars : "Unknown", device, subclassStr);
113120
}
114121
}
122+
123+
#if FF_HAVE_EMBEDDED_PCIIDS
124+
static inline int pciDeviceCmp(const FFPciDevice* a, const FFPciDevice* b)
125+
{
126+
return (int) a->id - (int) b->id;
127+
}
128+
129+
static bool loadPciidsInc(uint8_t subclass, uint16_t vendor, uint16_t device, FFGPUResult* gpu)
130+
{
131+
for (const FFPciVendor* pvendor = ffPciVendors; pvendor->name; pvendor++)
132+
{
133+
if (pvendor->id != vendor) continue;
134+
135+
if (!gpu->vendor.length)
136+
ffStrbufSetS(&gpu->vendor, pvendor->name);
137+
138+
const FFPciDevice* pdevice = (const FFPciDevice*) bsearch(&device, pvendor->devices, pvendor->nDevices, sizeof(FFPciDevice), (void*) pciDeviceCmp);
139+
140+
if (pdevice)
141+
{
142+
uint32_t nameLen = (uint32_t) strlen(pdevice->name);
143+
const char* closingBracket = pdevice->name + nameLen - 1;
144+
if (*closingBracket == ']')
145+
{
146+
const char* openingBracket = memrchr(pdevice->name, '[', nameLen - 1);
147+
if (openingBracket)
148+
{
149+
openingBracket++;
150+
ffStrbufSetNS(&gpu->name, (uint32_t) (closingBracket - openingBracket), openingBracket);
151+
}
152+
}
153+
if (!gpu->name.length)
154+
ffStrbufSetNS(&gpu->name, nameLen, pdevice->name);
155+
return true;
156+
}
157+
158+
if (!gpu->name.length)
159+
{
160+
const char* subclassStr;
161+
switch (subclass)
162+
{
163+
case 0 /*PCI_CLASS_DISPLAY_VGA*/: subclassStr = " (VGA compatible)"; break;
164+
case 1 /*PCI_CLASS_DISPLAY_XGA*/: subclassStr = " (XGA compatible)"; break;
165+
case 2 /*PCI_CLASS_DISPLAY_3D*/: subclassStr = " (3D)"; break;
166+
default: subclassStr = ""; break;
167+
}
168+
169+
ffStrbufSetF(&gpu->name, "%s Device %04X%s", gpu->vendor.length ? gpu->vendor.chars : "Unknown", device, subclassStr);
170+
}
171+
return true;
172+
}
173+
return false;
174+
}
175+
#endif
176+
177+
void ffGPUFillVendorAndName(uint8_t subclass, uint16_t vendor, uint16_t device, FFGPUResult* gpu)
178+
{
179+
#if FF_HAVE_EMBEDDED_PCIIDS
180+
bool ok = loadPciidsInc(subclass, vendor, device, gpu);
181+
if (ok) return;
182+
#endif
183+
return parsePciIdsFile(loadPciIds(), subclass, vendor, device, gpu);
184+
}

src/detection/gpu/gpu_sunos.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ const char* ffDetectGPUImpl(FF_MAYBE_UNUSED const FFGPUOptions* options, FFlist*
7373

7474
if (gpu->name.length == 0)
7575
{
76-
ffGPUParsePciIds((uint8_t) subclass, (uint16_t) vendorId, (uint16_t) deviceId, gpu);
76+
ffGPUFillVendorAndName((uint8_t) subclass, (uint16_t) vendorId, (uint16_t) deviceId, gpu);
7777
}
7878
}
7979

0 commit comments

Comments
 (0)