]> git.ipfire.org Git - thirdparty/systemd.git/blobdiff - hwdb/ids_parser.py
cgroup v2: Don't require CPU controller for CPU accounting in 4.15+
[thirdparty/systemd.git] / hwdb / ids_parser.py
index 691b7fa48fa207f39a99ec2b87ffe414e28d1587..c80d22258a35fd675368a9a3b18754c668ec5a49 100755 (executable)
@@ -117,143 +117,188 @@ def header(file, *sources):
                                     '\n#   '.join(sources)),
           file=file)
 
+def add_item(items, key, value):
+    if key in items:
+        print(f'Ignoring duplicate entry: {key} = "{items[key]}", "{value}"')
+    else:
+        items[key] = value
+
 def usb_vendor_model(p):
+    items = {}
+
+    for vendor_group in p.VENDORS:
+        vendor = vendor_group.VENDOR.vendor.upper()
+        text = vendor_group.VENDOR.text.strip()
+        add_item(items, (vendor,), text)
+
+        for vendor_dev in vendor_group.VENDOR_DEV:
+            device = vendor_dev.device.upper()
+            text = vendor_dev.text.strip()
+            add_item(items, (vendor, device), text)
+
     with open('20-usb-vendor-model.hwdb', 'wt') as out:
         header(out, 'http://www.linux-usb.org/usb.ids')
 
-        for vendor_group in p.VENDORS:
-            vendor = vendor_group.VENDOR.vendor.upper()
-            text = vendor_group.VENDOR.text.strip()
-            print(f'',
-                  f'usb:v{vendor}*',
-                  f' ID_VENDOR_FROM_DATABASE={text}', sep='\n', file=out)
-
-            for vendor_dev in vendor_group.VENDOR_DEV:
-                device = vendor_dev.device.upper()
-                text = vendor_dev.text.strip()
-                print(f'',
-                      f'usb:v{vendor}p{device}*',
-                      f' ID_MODEL_FROM_DATABASE={text}', sep='\n', file=out)
+        for key in sorted(items):
+            if len(key) == 1:
+                p, n = 'usb:v{}*', 'VENDOR'
+            else:
+                p, n = 'usb:v{}p{}*', 'MODEL',
+            print('', p.format(*key),
+                  f' ID_{n}_FROM_DATABASE={items[key]}', sep='\n', file=out)
+
     print(f'Wrote {out.name}')
 
 def usb_classes(p):
+    items = {}
+
+    for klass_group in p.CLASSES:
+        klass = klass_group.KLASS.klass.upper()
+        text = klass_group.KLASS.text.strip()
+
+        if klass != '00' and not re.match(r'(\?|None|Unused)\s*$', text):
+            add_item(items, (klass,), text)
+
+        for subclass_group in klass_group.SUBCLASSES:
+            subclass = subclass_group.subclass.upper()
+            text = subclass_group.text.strip()
+            if subclass != '00' and not re.match(r'(\?|None|Unused)\s*$', text):
+                add_item(items, (klass, subclass), text)
+
+            for protocol_group in subclass_group.PROTOCOLS:
+                protocol = protocol_group.protocol.upper()
+                text = protocol_group.name.strip()
+                if klass != '00' and not re.match(r'(\?|None|Unused)\s*$', text):
+                    add_item(items, (klass, subclass, protocol), text)
+
     with open('20-usb-classes.hwdb', 'wt') as out:
         header(out, 'http://www.linux-usb.org/usb.ids')
 
-        for klass_group in p.CLASSES:
-            klass = klass_group.KLASS.klass.upper()
-            text = klass_group.KLASS.text.strip()
-
-            if klass != '00' and not re.match(r'(\?|None|Unused)\s*$', text):
-                print(f'',
-                      f'usb:v*p*d*dc{klass}*',
-                      f' ID_USB_CLASS_FROM_DATABASE={text}', sep='\n', file=out)
-
-            for subclass_group in klass_group.SUBCLASSES:
-                subclass = subclass_group.subclass.upper()
-                text = subclass_group.text.strip()
-                if subclass != '00' and not re.match(r'(\?|None|Unused)\s*$', text):
-                    print(f'',
-                          f'usb:v*p*d*dc{klass}dsc{subclass}*',
-                          f' ID_USB_SUBCLASS_FROM_DATABASE={text}', sep='\n', file=out)
-
-                for protocol_group in subclass_group.PROTOCOLS:
-                    protocol = protocol_group.protocol.upper()
-                    text = protocol_group.name.strip()
-                    if klass != '00' and not re.match(r'(\?|None|Unused)\s*$', text):
-                        print(f'',
-                              f'usb:v*p*d*dc{klass}dsc{subclass}dp{protocol}*',
-                              f' ID_USB_PROTOCOL_FROM_DATABASE={text}', sep='\n', file=out)
+        for key in sorted(items):
+            if len(key) == 1:
+                p, n = 'usb:v*p*d*dc{}*', 'CLASS'
+            elif len(key) == 2:
+                p, n = 'usb:v*p*d*dc{}dsc{}*', 'SUBCLASS'
+            else:
+                p, n = 'usb:v*p*d*dc{}dsc{}dp{}*', 'PROTOCOL'
+            print('', p.format(*key),
+                  f' ID_USB_{n}_FROM_DATABASE={items[key]}', sep='\n', file=out)
+
     print(f'Wrote {out.name}')
 
 def pci_vendor_model(p):
+    items = {}
+
+    for vendor_group in p.VENDORS:
+        vendor = vendor_group.VENDOR.vendor.upper()
+        text = vendor_group.VENDOR.text.strip()
+        add_item(items, (vendor,), text)
+
+        for device_group in vendor_group.DEVICES:
+            device = device_group.device.upper()
+            text = device_group.text.strip()
+            add_item(items, (vendor, device), text)
+
+            for subvendor_group in device_group.SUBVENDORS:
+                sub_vendor = subvendor_group.a.upper()
+                sub_model = subvendor_group.b.upper()
+                sub_text = subvendor_group.name.strip()
+                if sub_text.startswith(text):
+                    sub_text = sub_text[len(text):].lstrip()
+                if sub_text:
+                    sub_text = f' ({sub_text})'
+                add_item(items, (vendor, device, sub_vendor, sub_model), text + sub_text)
+
     with open('20-pci-vendor-model.hwdb', 'wt') as out:
         header(out, 'http://pci-ids.ucw.cz/v2.2/pci.ids')
 
-        for vendor_group in p.VENDORS:
-            vendor = vendor_group.VENDOR.vendor.upper()
-            text = vendor_group.VENDOR.text.strip()
-            print(f'',
-                  f'pci:v0000{vendor}*',
-                  f' ID_VENDOR_FROM_DATABASE={text}', sep='\n', file=out)
-
-            for device_group in vendor_group.DEVICES:
-                device = device_group.device.upper()
-                text = device_group.text.strip()
-                print(f'',
-                      f'pci:v0000{vendor}d0000{device}*',
-                      f' ID_MODEL_FROM_DATABASE={text}', sep='\n', file=out)
-
-                for subvendor_group in device_group.SUBVENDORS:
-                    sub_vendor = subvendor_group.a.upper()
-                    sub_model = subvendor_group.b.upper()
-                    sub_text = subvendor_group.name.strip()
-                    if sub_text.startswith(text):
-                        sub_text = sub_text[len(text):].lstrip()
-                    if sub_text:
-                        sub_text = f' ({sub_text})'
-                    print(f'',
-                          f'pci:v0000{vendor}d0000{device}sv0000{sub_vendor}sd0000{sub_model}*',
-                          f' ID_MODEL_FROM_DATABASE={text}{sub_text}', sep='\n', file=out)
+        for key in sorted(items):
+            if len(key) == 1:
+                p, n = 'pci:v0000{}*', 'VENDOR'
+            elif len(key) == 2:
+                p, n = 'pci:v0000{}d0000{}*', 'MODEL'
+            else:
+                p, n = 'pci:v0000{}d0000{}sv0000{}sd0000{}*', 'MODEL'
+            print('', p.format(*key),
+                  f' ID_{n}_FROM_DATABASE={items[key]}', sep='\n', file=out)
+
     print(f'Wrote {out.name}')
 
 def pci_classes(p):
+    items = {}
+
+    for klass_group in p.CLASSES:
+        klass = klass_group.KLASS.klass.upper()
+        text = klass_group.KLASS.text.strip()
+        add_item(items, (klass,), text)
+
+        for subclass_group in klass_group.SUBCLASSES:
+            subclass = subclass_group.subclass.upper()
+            text = subclass_group.text.strip()
+            add_item(items, (klass, subclass), text)
+
+            for protocol_group in subclass_group.PROTOCOLS:
+                protocol = protocol_group.protocol.upper()
+                text = protocol_group.name.strip()
+                add_item(items, (klass, subclass, protocol), text)
+
     with open('20-pci-classes.hwdb', 'wt') as out:
         header(out, 'http://pci-ids.ucw.cz/v2.2/pci.ids')
 
-        for klass_group in p.CLASSES:
-            klass = klass_group.KLASS.klass.upper()
-            text = klass_group.KLASS.text.strip()
+        for key in sorted(items):
+            if len(key) == 1:
+                p, n = 'pci:v*d*sv*sd*bc{}*', 'CLASS'
+            elif len(key) == 2:
+                p, n = 'pci:v*d*sv*sd*bc{}sc{}*', 'SUBCLASS'
+            else:
+                p, n = 'pci:v*d*sv*sd*bc{}sc{}i{}*', 'INTERFACE'
+            print('', p.format(*key),
+                  f' ID_PCI_{n}_FROM_DATABASE={items[key]}', sep='\n', file=out)
 
-            print(f'',
-                  f'pci:v*d*sv*sd*bc{klass}*',
-                  f' ID_PCI_CLASS_FROM_DATABASE={text}', sep='\n', file=out)
-
-            for subclass_group in klass_group.SUBCLASSES:
-                subclass = subclass_group.subclass.upper()
-                text = subclass_group.text.strip()
-                print(f'',
-                      f'pci:v*d*sv*sd*bc{klass}sc{subclass}*',
-                      f' ID_PCI_SUBCLASS_FROM_DATABASE={text}', sep='\n', file=out)
-
-                for protocol_group in subclass_group.PROTOCOLS:
-                    protocol = protocol_group.protocol.upper()
-                    text = protocol_group.name.strip()
-                    print(f'',
-                          f'pci:v*d*sv*sd*bc{klass}sc{subclass}i{protocol}*',
-                          f' ID_PCI_INTERFACE_FROM_DATABASE={text}', sep='\n', file=out)
     print(f'Wrote {out.name}')
 
 def sdio_vendor_model(p):
+    items = {}
+
+    for vendor_group in p.VENDORS:
+        vendor = vendor_group.VENDOR.vendor.upper()
+        text = vendor_group.VENDOR.text.strip()
+        add_item(items, (vendor,), text)
+
+        for device_group in vendor_group.DEVICES:
+            device = device_group.device.upper()
+            text = device_group.text.strip()
+            add_item(items, (vendor, device), text)
+
     with open('20-sdio-vendor-model.hwdb', 'wt') as out:
         header(out, 'hwdb/sdio.ids')
 
-        for vendor_group in p.VENDORS:
-            vendor = vendor_group.VENDOR.vendor.upper()
-            text = vendor_group.VENDOR.text.strip()
-            print(f'',
-                  f'sdio:c*v{vendor}*',
-                  f' ID_VENDOR_FROM_DATABASE={text}', sep='\n', file=out)
-
-            for device_group in vendor_group.DEVICES:
-                device = device_group.device.upper()
-                text = device_group.text.strip()
-                print(f'',
-                      f'sdio:c*v{vendor}d{device}*',
-                      f' ID_MODEL_FROM_DATABASE={text}', sep='\n', file=out)
+        for key in sorted(items):
+            if len(key) == 1:
+                p, n = 'sdio:c*v{}*', 'VENDOR'
+            else:
+                p, n = 'sdio:c*v{}d{}*', 'MODEL'
+            print('', p.format(*key),
+                  f' ID_{n}_FROM_DATABASE={items[key]}', sep='\n', file=out)
+
     print(f'Wrote {out.name}')
 
 def sdio_classes(p):
+    items = {}
+
+    for klass_group in p.CLASSES:
+        klass = klass_group.KLASS.klass.upper()
+        text = klass_group.KLASS.text.strip()
+        add_item(items, klass, text)
+
     with open('20-sdio-classes.hwdb', 'wt') as out:
         header(out, 'hwdb/sdio.ids')
 
-        for klass_group in p.CLASSES:
-            klass = klass_group.KLASS.klass.upper()
-            text = klass_group.KLASS.text.strip()
-
+        for klass in sorted(items):
             print(f'',
                   f'sdio:c{klass}v*d*',
-                  f' ID_SDIO_CLASS_FROM_DATABASE={text}', sep='\n', file=out)
+                  f' ID_SDIO_CLASS_FROM_DATABASE={items[klass]}', sep='\n', file=out)
+
     print(f'Wrote {out.name}')
 
 # MAC Address Block Large/Medium/Small
@@ -261,49 +306,60 @@ def sdio_classes(p):
 # Medium MA-M 28/20 bit (OUI prefix owned by IEEE)
 # Small  MA-S 36/12 bit (OUI prefix owned by IEEE)
 def oui(p1, p2, p3):
+    prefixes = set()
+    items = {}
+
+    for p, check in ((p1, False), (p2, False), (p3, True)):
+        for vendor_group in p.VENDORS:
+            prefix = vendor_group.prefix.upper()
+            if check:
+                if prefix in prefixes:
+                    continue
+            else:
+                prefixes.add(prefix)
+            start = vendor_group.start.upper()
+            end = vendor_group.end.upper()
+
+            if end and start != end:
+                print(f'{prefix:} {start} != {end}', file=sys.stderr)
+            text = vendor_group.text.strip()
+
+            key = prefix + start if end else prefix
+            add_item(items, key, text)
+
     with open('20-OUI.hwdb', 'wt') as out:
         header(out,
                'https://services13.ieee.org/RST/standards-ra-web/rest/assignments/download/?registry=MA-L&format=txt',
                'https://services13.ieee.org/RST/standards-ra-web/rest/assignments/download/?registry=MA-M&format=txt',
                'https://services13.ieee.org/RST/standards-ra-web/rest/assignments/download/?registry=MA-S&format=txt')
 
-        prefixes = set()
-
-        for p, check in ((p1, False), (p2, False), (p3, True)):
-            for vendor_group in p.VENDORS:
-                prefix = vendor_group.prefix.upper()
-                if check:
-                    if prefix in prefixes:
-                        continue
-                else:
-                    prefixes.add(prefix)
-                start = vendor_group.start.upper()
-                end = vendor_group.end.upper()
-
-                if end and start != end:
-                    print(f'{prefix:} {start} != {end}', file=sys.stderr)
-                text = vendor_group.text.strip()
-
-                print(f'',
-                      f'OUI:{prefix}{start if end else ""}*',
-                      f' ID_OUI_FROM_DATABASE={text}', sep='\n', file=out)
+        for pattern in sorted(items):
+            print(f'',
+                  f'OUI:{pattern}*',
+                  f' ID_OUI_FROM_DATABASE={items[pattern]}', sep='\n', file=out)
+
     print(f'Wrote {out.name}')
 
 if __name__ == '__main__':
-    p = usb_ids_grammar().parseFile(open('usb.ids'))
-    usb_vendor_model(p)
-    usb_classes(p)
-
-    p = pci_ids_grammar().parseFile(open('pci.ids'))
-    pci_vendor_model(p)
-    pci_classes(p)
-
-    p = pci_ids_grammar().parseFile(open('sdio.ids'))
-    sdio_vendor_model(p)
-    sdio_classes(p)
-
-    p = oui_grammar('small').parseFile(open('ma-small.txt'))
-    p2 = oui_grammar('medium').parseFile(open('ma-medium.txt'))
-    p3 = oui_grammar('large').parseFile(open('ma-large.txt'))
-
-    oui(p, p2, p3)
+    args = sys.argv[1:]
+
+    if not args or 'usb' in args:
+        p = usb_ids_grammar().parseFile(open('usb.ids', errors='replace'))
+        usb_vendor_model(p)
+        usb_classes(p)
+
+    if not args or 'pci' in args:
+        p = pci_ids_grammar().parseFile(open('pci.ids', errors='replace'))
+        pci_vendor_model(p)
+        pci_classes(p)
+
+    if not args or 'sdio' in args:
+        p = pci_ids_grammar().parseFile(open('sdio.ids', errors='replace'))
+        sdio_vendor_model(p)
+        sdio_classes(p)
+
+    if not args or 'oui' in args:
+        p = oui_grammar('small').parseFile(open('ma-small.txt'))
+        p2 = oui_grammar('medium').parseFile(open('ma-medium.txt'))
+        p3 = oui_grammar('large').parseFile(open('ma-large.txt'))
+        oui(p, p2, p3)