From bc31d222b36a1f6b442b9d6a53da0d116cb5cbcb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9mi=20Jouannet?= Date: Fri, 3 Apr 2026 18:23:45 +0200 Subject: [PATCH 1/4] add parsing of pci_class from pci.ids --- hwdata.py | 103 +++++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 98 insertions(+), 5 deletions(-) diff --git a/hwdata.py b/hwdata.py index b7120ea..b5889ca 100644 --- a/hwdata.py +++ b/hwdata.py @@ -19,7 +19,7 @@ # pylint: disable=misplaced-bare-raise class USB: - """ Interace to usb.ids from hwdata package """ + """ Interface to usb.ids from hwdata package """ filename = '/usr/share/hwdata/usb.ids' devices = None @@ -103,9 +103,10 @@ def get_device(self, vendor, device): raise NotImplementedError() class PCI: - """ Interace to pci.ids from hwdata package """ + """ Interface to pci.ids from hwdata package """ filename = '/usr/share/hwdata/pci.ids' devices = None + devices_class = None def __init__(self, filename=None): """ Load pci.ids from file to internal data structure. @@ -117,14 +118,22 @@ def __init__(self, filename=None): self.filename = PCI.filename self.cache = 1 - if self.cache and not PCI.devices: + if self.cache and not PCI.devices and not PCI.devices_class: # parse pci.ids PCI.devices = {} + PCI.devices_class = {} + f = open(self.filename, encoding='ISO8859-1') vendor = None device = None - for line in f.readlines(): + while True: + line = f.readline() + if not line: + break l = line.split() + + if line.startswith('# C class'): + break if line.startswith('#'): continue elif len(l) == 0: @@ -145,6 +154,36 @@ def __init__(self, filename=None): else: # this should not happen PCI.devices[vendor][0] = vendor_name + device_class = None + subclass = None + while True: + line = f.readline() + if not line: + break + l = line.split() + + if line.startswith('#'): + continue + elif len(l) == 0: + continue + elif line.startswith('\t\t'): + prog_if = l[0].lower() + prog_if_name = ' '.join(l[1:]) + PCI.devices_class[device_class][1][subclass][1][prog_if] = prog_if_name + elif line.startswith('\t'): + subclass = l[0].lower() + subclass_name = ' '.join(l[1:]) + PCI.devices_class[device_class][1][subclass] = [subclass_name, {}] + else: + device_class = l[1].lower() + device_class_name = ' '.join(l[2:]) + if not device_class in list(PCI.devices_class.keys()): + PCI.devices_class[device_class] = [device_class_name, {}] + else: + PCI.devices_class[device_class][0] = device_class_name + f.close() + + def get_vendor(self, vendor): """ Return description of vendor. Parameter is two byte code in hexa. If vendor is unknown None is returned. @@ -198,8 +237,62 @@ def get_subsystem(self, vendor, device, subsystem): else: raise NotImplementedError() + def get_class(self, device_class): + """ Return device_class name of pci_class. + 'device_class' and 'subclass' are two bytes code variables in hexa of pci_class. + If subclass is unknown None is returned. + """ + device_class = device_class.lower() + if self.cache: + if device_class in list(PCI.devices_class.keys()): + return PCI.devices_class[device_class][0] + else: + return None + else: + raise NotImplementedError() + + def get_subclass(self, device_class, subclass): + """ Return subclass name of pci_class. + 'device_class' and 'subclass' are two bytes code variables in hexa of pci_class. + If subclass is unknown None is returned. + """ + device_class = device_class.lower() + subclass = subclass.lower() + if self.cache: + if device_class in list(PCI.devices_class.keys()): + if subclass in list(PCI.devices_class[device_class][1].keys()): + return PCI.devices_class[device_class][1][subclass][0] + else: + return None + else: + return None + else: + raise NotImplementedError() + + def get_prog_if(self, device_class, subclass, prog_if): + """ Return prog_if name of pci_class. + 'device_class', 'subclass' and prog_if are three byte code variables in hexa of pci_class. + If prog_if is unknown None is returned. + """ + device_class = device_class.lower() + subclass = subclass.lower() + prog_if = prog_if.lower() + if self.cache: + if device_class in list(PCI.devices_class.keys()): + if subclass in list(PCI.devices_class[device_class][1].keys()): + if prog_if in list(PCI.devices_class[device_class][1][subclass][1].keys()): + return PCI.devices_class[device_class][1][subclass][1][prog_if][0] + else: + return None + else: + return None + else: + return None + else: + raise NotImplementedError() + class PNP: - """ Interace to pnp.ids from hwdata package """ + """ Interface to pnp.ids from hwdata package """ filename = '/usr/share/hwdata/pnp.ids' VENDORS = None From c6179b2d35e61f5cd06fbd314747c8653a7e31d8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9mi=20Jouannet?= Date: Fri, 3 Apr 2026 18:41:22 +0200 Subject: [PATCH 2/4] add example for pci class --- example.py | 7 ++++++- hwdata.py | 6 +++--- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/example.py b/example.py index ab1b0fd..fc7c491 100644 --- a/example.py +++ b/example.py @@ -7,7 +7,9 @@ pci_vendor_id = '1002' pci_device_id = '687f' pci_subsystem_id = '1043:04c4' - +pci_class = "" +pci_subclass = "" +pci_prog_if = "" usb_vendor_id = '03f0' usb_device_id = '1f12' @@ -16,6 +18,9 @@ print("Vendor: %s" % pci.get_vendor(pci_vendor_id)) print("Device: %s" % pci.get_device(pci_vendor_id, pci_device_id)) print("Subsystem: %s" % pci.get_subsystem(pci_vendor_id, pci_device_id, pci_subsystem_id)) +print("Class: %s" % pci.get_class("0c")) +print("subclass: %s" % pci.get_subclass("0c", "07")) +print("prog_if: %s" % pci.get_prog_if("0c", "07", "02")) usb = USB() diff --git a/hwdata.py b/hwdata.py index b5889ca..2a06be2 100644 --- a/hwdata.py +++ b/hwdata.py @@ -237,9 +237,9 @@ def get_subsystem(self, vendor, device, subsystem): else: raise NotImplementedError() - def get_class(self, device_class): + def get_class(self, device_class): """ Return device_class name of pci_class. - 'device_class' and 'subclass' are two bytes code variables in hexa of pci_class. + 'device_class' is a bytes code variables in hexa of pci_class. If subclass is unknown None is returned. """ device_class = device_class.lower() @@ -281,7 +281,7 @@ def get_prog_if(self, device_class, subclass, prog_if): if device_class in list(PCI.devices_class.keys()): if subclass in list(PCI.devices_class[device_class][1].keys()): if prog_if in list(PCI.devices_class[device_class][1][subclass][1].keys()): - return PCI.devices_class[device_class][1][subclass][1][prog_if][0] + return PCI.devices_class[device_class][1][subclass][1][prog_if] else: return None else: From 6655d1b45a3bd274913551643d8fca4623afe02f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9mi=20Jouannet?= Date: Fri, 3 Apr 2026 18:43:45 +0200 Subject: [PATCH 3/4] add example for pci class --- example.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/example.py b/example.py index fc7c491..0664a49 100644 --- a/example.py +++ b/example.py @@ -7,9 +7,9 @@ pci_vendor_id = '1002' pci_device_id = '687f' pci_subsystem_id = '1043:04c4' -pci_class = "" -pci_subclass = "" -pci_prog_if = "" +pci_class = "0c" +pci_subclass = "07" +pci_prog_if = "02" usb_vendor_id = '03f0' usb_device_id = '1f12' @@ -18,9 +18,9 @@ print("Vendor: %s" % pci.get_vendor(pci_vendor_id)) print("Device: %s" % pci.get_device(pci_vendor_id, pci_device_id)) print("Subsystem: %s" % pci.get_subsystem(pci_vendor_id, pci_device_id, pci_subsystem_id)) -print("Class: %s" % pci.get_class("0c")) -print("subclass: %s" % pci.get_subclass("0c", "07")) -print("prog_if: %s" % pci.get_prog_if("0c", "07", "02")) +print("Class: %s" % pci.get_class(pci_class)) +print("subclass: %s" % pci.get_subclass(pci_class, pci_subclass)) +print("prog_if: %s" % pci.get_prog_if(pci_class, pci_subclass, pci_prog_if)) usb = USB() From b9b1f2f142e2cf75aef0035a48eef7269711e692 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9mi=20Jouannet?= Date: Tue, 7 Apr 2026 11:16:11 +0200 Subject: [PATCH 4/4] add comment --- hwdata.py | 1 + 1 file changed, 1 insertion(+) diff --git a/hwdata.py b/hwdata.py index 2a06be2..eebfb3b 100644 --- a/hwdata.py +++ b/hwdata.py @@ -132,6 +132,7 @@ def __init__(self, filename=None): break l = line.split() + # Break to exit the loop and parse device classes if line.startswith('# C class'): break if line.startswith('#'):