From bf37375c4af9ab4ce765b9d894f0927d1c62e917 Mon Sep 17 00:00:00 2001 From: Mike Gilbert Date: Tue, 3 Oct 2017 15:25:59 -0400 Subject: [PATCH] Use new python script for udev database updates --- Makefile | 7 +- ids_parser.py | 365 ++++++++++++++++++++++++++++++++++++++++++ udev-hwdb-update.pl | 375 -------------------------------------------- 3 files changed, 369 insertions(+), 378 deletions(-) create mode 100644 ids_parser.py delete mode 100644 udev-hwdb-update.pl diff --git a/Makefile b/Makefile index 638e95a..80c3e5e 100644 --- a/Makefile +++ b/Makefile @@ -8,6 +8,7 @@ else endif PKG_CONFIG ?= pkg-config +PYTHON ?= python3 GZIP ?= yes NET ?= yes PCI ?= yes @@ -49,18 +50,18 @@ fetch: $(Q)curl -z ma-small.txt -o ma-small.txt -R http://standards-oui.ieee.org/oui36/oui36.txt $(Q)curl -z iab.txt -o iab.txt -R http://standards-oui.ieee.org/iab/iab.txt $(Q)curl -L -z sdio.ids -o sdio.ids -R $(SYSTEMD_SOURCE)/sdio.ids - $(Q)curl -L -z udev-hwdb-update.pl -o udev-hwdb-update.pl -R $(SYSTEMD_SOURCE)/ids-update.pl + $(Q)curl -L -z ids_parser.py -o ids_parser.py -R $(SYSTEMD_SOURCE)/ids_parser.py $(Q)for f in $(UDEV_FILES); do curl -L -z udev/$$f -o udev/$$f -R $(SYSTEMD_SOURCE)/$$f; done $(Q)$(STATUS) -PV ?= $(shell ( awk '$$2 == "Date:" { print $$3; nextfile }' pci.ids usb.ids; git log --format=format:%ci -1 -- oui.txt $(addprefix udev/,$(UDEV_FILES)) udev-hwdb-update.pl | cut -d ' ' -f1; ) | sort | tail -n 1 | tr -d -) +PV ?= $(shell ( awk '$$2 == "Date:" { print $$3; nextfile }' pci.ids usb.ids; git log --format=format:%ci -1 -- oui.txt $(addprefix udev/,$(UDEV_FILES)) ids_parser.py | cut -d ' ' -f1; ) | sort | tail -n 1 | tr -d -) P = hwids-$(PV) tag: git tag $(P) udev-hwdb: - perl ./udev-hwdb-update.pl && mv *.hwdb udev/ + $(PYTHON) ids_parser.py && mv *.hwdb udev/ compress: pci.ids.gz usb.ids.gz diff --git a/ids_parser.py b/ids_parser.py new file mode 100644 index 0000000..3c43649 --- /dev/null +++ b/ids_parser.py @@ -0,0 +1,365 @@ +#!/usr/bin/env python3 + +import re +import sys +from pyparsing import (Word, White, Literal, Regex, + LineEnd, SkipTo, + ZeroOrMore, OneOrMore, Combine, Optional, Suppress, + stringEnd, pythonStyleComment) + +EOL = LineEnd().suppress() +NUM1 = Word('0123456789abcdefABCDEF', exact=1) +NUM2 = Word('0123456789abcdefABCDEF', exact=2) +NUM3 = Word('0123456789abcdefABCDEF', exact=3) +NUM4 = Word('0123456789abcdefABCDEF', exact=4) +NUM6 = Word('0123456789abcdefABCDEF', exact=6) +TAB = White('\t', exact=1).suppress() +COMMENTLINE = pythonStyleComment + EOL +EMPTYLINE = LineEnd() +text_eol = lambda name: Regex(r'[^\n]+')(name) + EOL +# text_eol = lambda name: Word(printables + ' ' + '®üäßçõãİó ×²⁶´‐“\u200E\u200B')(name) + EOL + +def klass_grammar(): + klass_line = Literal('C ').suppress() + NUM2('klass') + text_eol('text') + subclass_line = TAB + NUM2('subclass') + text_eol('text') + protocol_line = TAB + TAB + NUM2('protocol') + text_eol('name') + subclass = (subclass_line('SUBCLASS') - + ZeroOrMore(protocol_line('PROTOCOLS*') + ^ COMMENTLINE.suppress())) + klass = (klass_line('KLASS') - + ZeroOrMore(subclass('SUBCLASSES*') + ^ COMMENTLINE.suppress())) + return klass + +def usb_ids_grammar(): + vendor_line = NUM4('vendor') + text_eol('text') + device_line = TAB + NUM4('device') + text_eol('text') + vendor = (vendor_line('VENDOR') + + ZeroOrMore(device_line('VENDOR_DEV*') ^ COMMENTLINE.suppress())) + + klass = klass_grammar() + + other_line = (Literal('AT ') ^ Literal('HID ') ^ Literal('R ') + ^ Literal('PHY ') ^ Literal('BIAS ') ^ Literal('HUT ') + ^ Literal('L ') ^ Literal('VT ') ^ Literal('HCC ')) + text_eol('text') + other_group = (other_line - ZeroOrMore(TAB + text_eol('text'))) + + commentgroup = OneOrMore(COMMENTLINE).suppress() ^ EMPTYLINE.suppress() + grammar = OneOrMore(vendor('VENDORS*') ^ klass('CLASSES*') + ^ other_group.suppress() ^ commentgroup) + stringEnd() + + grammar.parseWithTabs() + return grammar + +def pci_ids_grammar(): + vendor_line = NUM4('vendor') + text_eol('text') + device_line = TAB + NUM4('device') + text_eol('text') + subvendor_line = TAB + TAB + NUM4('a') + White(' ') + NUM4('b') + text_eol('name') + + device = (device_line('DEVICE') + + ZeroOrMore(subvendor_line('SUBVENDORS*') ^ COMMENTLINE.suppress())) + vendor = (vendor_line('VENDOR') + + ZeroOrMore(device('DEVICES*') ^ COMMENTLINE.suppress())) + + klass = klass_grammar() + + commentgroup = OneOrMore(COMMENTLINE).suppress() ^ EMPTYLINE.suppress() + grammar = OneOrMore(vendor('VENDORS*') ^ klass('CLASSES*') + ^ commentgroup) + stringEnd() + + grammar.parseWithTabs() + return grammar + +def sdio_ids_grammar(): + vendor_line = NUM4('vendor') + text_eol('text') + device_line = TAB + NUM4('device') + text_eol('text') + vendor = (vendor_line('VENDOR') + + ZeroOrMore(device_line('DEVICES*') ^ COMMENTLINE.suppress())) + + klass = klass_grammar() + + commentgroup = OneOrMore(COMMENTLINE).suppress() ^ EMPTYLINE.suppress() + grammar = OneOrMore(vendor('VENDORS*') ^ klass('CLASSES*') ^ commentgroup) + stringEnd() + + grammar.parseWithTabs() + return grammar + +def oui_grammar(type): + prefix_line = (Combine(NUM2 - Suppress('-') - NUM2 - Suppress('-') - NUM2)('prefix') + - Literal('(hex)') - text_eol('text')) + if type == 'small': + vendor_line = (NUM3('start') - '000-' - NUM3('end') - 'FFF' + - Literal('(base 16)') - text_eol('text2')) + elif type == 'medium': + vendor_line = (NUM1('start') - '00000-' - NUM1('end') - 'FFFFF' + - Literal('(base 16)') - text_eol('text2')) + else: + assert type == 'large' + vendor_line = (NUM6('start') + - Literal('(base 16)') - text_eol('text2')) + + extra_line = TAB - TAB - TAB - TAB - SkipTo(EOL) + vendor = prefix_line + vendor_line + ZeroOrMore(extra_line) + Optional(EMPTYLINE) + + grammar = (Literal('OUI') + text_eol('header') + + text_eol('header') + text_eol('header') + EMPTYLINE + + OneOrMore(vendor('VENDORS*')) + stringEnd()) + + grammar.parseWithTabs() + return grammar + + +def header(file, *sources): + print('''\ +# This file is part of systemd. +# +# Data imported from:{}{}'''.format(' ' if len(sources) == 1 else '\n# ', + '\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 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 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 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 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'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 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 in sorted(items): + print(f'', + f'sdio:c{klass}v*d*', + f' ID_SDIO_CLASS_FROM_DATABASE={items[klass]}', sep='\n', file=out) + + print(f'Wrote {out.name}') + +# MAC Address Block Large/Medium/Small +# Large MA-L 24/24 bit (OUI) +# 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') + + 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__': + args = sys.argv[1:] + + if not args or 'usb' in args: + p = usb_ids_grammar().parseFile(open('usb.ids')) + usb_vendor_model(p) + usb_classes(p) + + if not args or 'pci' in args: + p = pci_ids_grammar().parseFile(open('pci.ids')) + pci_vendor_model(p) + pci_classes(p) + + if not args or 'sdio' in args: + p = pci_ids_grammar().parseFile(open('sdio.ids')) + 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) diff --git a/udev-hwdb-update.pl b/udev-hwdb-update.pl deleted file mode 100644 index 03dd00b..0000000 --- a/udev-hwdb-update.pl +++ /dev/null @@ -1,375 +0,0 @@ -#!/usr/bin/perl - -use strict; -use warnings; - -sub usb_vendor { - my $vendor; - - open(IN, "<", "usb.ids"); - open(OUT, ">", "20-usb-vendor-model.hwdb"); - print(OUT "# This file is part of systemd.\n" . - "#\n" . - "# Data imported from: http://www.linux-usb.org/usb.ids\n"); - - while (my $line = ) { - $line =~ s/\s+$//; - $line =~ m/^([0-9a-f]{4})\s*(.+)$/; - if (defined $1) { - $vendor = uc $1; - my $text = $2; - print(OUT "\n"); - print(OUT "usb:v" . $vendor . "*\n"); - print(OUT " ID_VENDOR_FROM_DATABASE=" . $text . "\n"); - next; - } - - $line =~ m/^\t([0-9a-f]{4})\s*(.+)$/; - if (defined $1) { - my $model = uc $1; - my $text = $2; - print(OUT "\n"); - print(OUT "usb:v" . $vendor . "p" . $model . "*\n"); - print(OUT " ID_MODEL_FROM_DATABASE=" . $text . "\n"); - } - } - - close(IN); - close(OUT); -} - -sub usb_classes { - my $class; - my $subclass; - my $protocol; - - open(IN, "<", "usb.ids"); - open(OUT, ">", "20-usb-classes.hwdb"); - print(OUT "# This file is part of systemd.\n" . - "#\n" . - "# Data imported from: http://www.linux-usb.org/usb.ids\n"); - - while (my $line = ) { - $line =~ s/\s+$//; - - $line =~ m/^C\ ([0-9a-f]{2})\s*(.+)$/; - if (defined $1) { - $class = uc $1; - if ($class =~ m/^00$/) { - next; - } - my $text = $2; - print(OUT "\n"); - print(OUT "usb:v*p*d*dc" . $class . "*\n"); - print(OUT " ID_USB_CLASS_FROM_DATABASE=" . $text . "\n"); - next; - } - - if (not defined $class) { - next; - } elsif ($line =~ m/^$/) { - last; - } - - $line =~ m/^\t([0-9a-f]{2})\s*(.+)$/; - if (defined $1) { - $subclass = uc $1; - if ($subclass =~ m/^00$/) { - next; - } - my $text = $2; - if ($text =~ m/^(\?|None|Unused)$/) { - next; - } - print(OUT "\n"); - print(OUT "usb:v*p*d*dc" . $class . "dsc" . $subclass . "*\n"); - print(OUT " ID_USB_SUBCLASS_FROM_DATABASE=" . $text . "\n"); - next; - } - - $line =~ m/^\t\t([0-9a-f]{2})\s*(.+)$/; - if (defined $1) { - $protocol = uc $1; - my $text = $2; - if ($text =~ m/^(\?|None|Unused)$/) { - next; - } - print(OUT "\n"); - print(OUT "usb:v*p*d*dc" . $class . "dsc" . $subclass . "dp" . $protocol . "*\n"); - print(OUT " ID_USB_PROTOCOL_FROM_DATABASE=" . $text . "\n"); - } - } - - close(IN); - close(OUT); -} - -sub pci_vendor { - my $vendor; - my $device; - my $device_text; - - open(IN, "<", "pci.ids"); - open(OUT, ">", "20-pci-vendor-model.hwdb"); - print(OUT "# This file is part of systemd.\n" . - "#\n" . - "# Data imported from: http://pci-ids.ucw.cz/v2.2/pci.ids\n"); - - while (my $line = ) { - $line =~ s/\s+$//; - $line =~ m/^([0-9a-f]{4})\s*(.+)$/; - - if (defined $1) { - $vendor = uc $1; - my $text = $2; - print(OUT "\n"); - print(OUT "pci:v0000" . $vendor . "*\n"); - print(OUT " ID_VENDOR_FROM_DATABASE=" . $text . "\n"); - next; - } - - $line =~ m/^\t([0-9a-f]{4})\s*(.+)$/; - if (defined $1) { - $device = uc $1; - $device_text = $2; - print(OUT "\n"); - print(OUT "pci:v0000" . $vendor . "d0000" . $device . "*\n"); - print(OUT " ID_MODEL_FROM_DATABASE=" . $device_text . "\n"); - next; - } - - $line =~ m/^\t\t([0-9a-f]{4})\s*([0-9a-f]{4})\s*(.*)$/; - if (defined $1) { - my $sub_vendor = uc $1; - my $sub_device = uc $2; - my $sub_text = $3; - $sub_text =~ s/^\Q$device_text\E\s*//; - $sub_text =~ s/(.+)/\ ($1)/; - print(OUT "\n"); - print(OUT "pci:v0000" . $vendor . "d0000" . $device . "sv0000" . $sub_vendor . "sd0000" . $sub_device . "*\n"); - print(OUT " ID_MODEL_FROM_DATABASE=" . $device_text . $sub_text . "\n"); - } - } - - close(IN); - close(OUT); -} - -sub pci_classes { - my $class; - my $subclass; - my $interface; - - open(IN, "<", "pci.ids"); - open(OUT, ">", "20-pci-classes.hwdb"); - print(OUT "# This file is part of systemd.\n" . - "#\n" . - "# Data imported from: http://pci-ids.ucw.cz/v2.2/pci.ids\n"); - - while (my $line = ) { - $line =~ s/\s+$//; - - $line =~ m/^C\ ([0-9a-f]{2})\s*(.+)$/; - if (defined $1) { - $class = uc $1; - my $text = $2; - print(OUT "\n"); - print(OUT "pci:v*d*sv*sd*bc" . $class . "*\n"); - print(OUT " ID_PCI_CLASS_FROM_DATABASE=" . $text . "\n"); - next; - } - - if (not defined $class) { - next; - } elsif ($line =~ m/^$/) { - last; - } - - $line =~ m/^\t([0-9a-f]{2})\s*(.+)$/; - if (defined $1) { - $subclass = uc $1; - my $text = $2; - print(OUT "\n"); - print(OUT "pci:v*d*sv*sd*bc" . $class . "sc" . $subclass . "*\n"); - print(OUT " ID_PCI_SUBCLASS_FROM_DATABASE=" . $text . "\n"); - next; - } - - $line =~ m/^\t\t([0-9a-f]{2})\s*(.+)$/; - if (defined $1) { - $interface = uc $1; - my $text = $2; - print(OUT "\n"); - print(OUT "pci:v*d*sv*sd*bc" . $class . "sc" . $subclass . "i" . $interface . "*\n"); - print(OUT " ID_PCI_INTERFACE_FROM_DATABASE=" . $text . "\n"); - } - } - - close(IN); - close(OUT); -} - -sub sdio_vendor { - my $vendor; - my $device; - - open(IN, "<", "sdio.ids"); - open(OUT, ">", "20-sdio-vendor-model.hwdb"); - print(OUT "# This file is part of systemd.\n" . - "#\n" . - "# Data imported from: hwdb/sdio.ids\n"); - - while (my $line = ) { - $line =~ s/\s+$//; - $line =~ m/^([0-9a-f]{4})\s*(.+)$/; - - if (defined $1) { - $vendor = uc $1; - my $text = $2; - print(OUT "\n"); - print(OUT "sdio:c*v" . $vendor . "*\n"); - print(OUT " ID_VENDOR_FROM_DATABASE=" . $text . "\n"); - next; - } - - $line =~ m/^\t([0-9a-f]{4})\s*(.+)$/; - if (defined $1) { - $device = uc $1; - my $text = $2; - print(OUT "\n"); - print(OUT "sdio:c*v" . $vendor . "d" . $device . "*\n"); - print(OUT " ID_MODEL_FROM_DATABASE=" . $text . "\n"); - next; - } - } - - close(IN); - close(OUT); -} - -sub sdio_classes { - my $class; - my $subclass; - my $interface; - - open(IN, "<", "sdio.ids"); - open(OUT, ">", "20-sdio-classes.hwdb"); - print(OUT "# This file is part of systemd.\n" . - "#\n" . - "# Data imported from: hwdb/sdio.ids\n"); - - while (my $line = ) { - $line =~ s/\s+$//; - - $line =~ m/^C\ ([0-9a-f]{2})\s*(.+)$/; - if (defined $1) { - $class = uc $1; - my $text = $2; - print(OUT "\n"); - print(OUT "sdio:c" . $class . "v*d*\n"); - print(OUT " ID_SDIO_CLASS_FROM_DATABASE=" . $text . "\n"); - next; - } - } - - close(IN); - close(OUT); -} - -# MAC Address Block Large/Medium/Small -# Large MA-L 24/24 bit (OUI) -# Medium MA-M 28/20 bit (OUI prefix owned by IEEE) -# Small MA-S 36/12 bit (OUI prefix owned by IEEE) -sub oui { - my $prefix; - my %ieee_prefixes = (); - - open(OUT, ">", "20-OUI.hwdb"); - print(OUT "# This file is part of systemd.\n" . - "#\n" . - "# Data imported from:\n" . - "# https://services13.ieee.org/RST/standards-ra-web/rest/assignments/download/?registry=MA-L&format=txt\n" . - "# https://services13.ieee.org/RST/standards-ra-web/rest/assignments/download/?registry=MA-M&format=txt\n" . - "# https://services13.ieee.org/RST/standards-ra-web/rest/assignments/download/?registry=MA-S&format=txt\n"); - - open(IN, "<", "ma-small.txt"); - while (my $line = ) { - $line =~ s/^ +//; - $line =~ s/\s+$//; - $line =~ m/^([0-9A-F]{2})-([0-9A-F]{2})-([0-9A-F]{2})\s*\(hex\)\s*.+$/; - if (defined $1) { - $prefix = $1 . $2 . $3; - $ieee_prefixes{ $prefix } = 1; - next; - } - - $line =~ m/^([0-9A-F]{3})000-\g1FFF\s*\(base 16\)\s*(.+)$/; - if (defined $1) { - my $vendor = uc $1; - my $text = $2; - - print(OUT "\n"); - print(OUT "OUI:" . $prefix . $vendor . "*\n"); - print(OUT " ID_OUI_FROM_DATABASE=" . $text . "\n"); - } - } - close(IN); - - open(IN, "<", "ma-medium.txt"); - while (my $line = ) { - $line =~ s/^ +//; - $line =~ s/\s+$//; - $line =~ m/^([0-9A-F]{2})-([0-9A-F]{2})-([0-9A-F]{2})\s*\(hex\)\s*.+$/; - if (defined $1) { - $prefix = $1 . $2 . $3; - $ieee_prefixes{ $prefix } = 1; - next; - } - - $line =~ m/^([0-9A-F])00000-\g1FFFFF\s*\(base 16\)\s*(.+)$/; - if (defined $1) { - my $vendor = uc $1; - my $text = $2; - - print(OUT "\n"); - print(OUT "OUI:" . $prefix . $vendor . "*\n"); - print(OUT " ID_OUI_FROM_DATABASE=" . $text . "\n"); - } - } - - open(IN, "<", "ma-large.txt"); - while (my $line = ) { - $line =~ s/^ +//; - $line =~ s/\s+$//; - $line =~ m/^([0-9A-F]{6})\s*\(base 16\)\s*(.+)$/; - if (defined $1) { - my $vendor = uc $1; - my $text = $2; - - if ($text =~ m/^IEEE REGISTRATION AUTHORITY/) { - next; - } - - # skip the IEEE owned prefixes - if (! exists $ieee_prefixes{ $vendor }) { - print(OUT "\n"); - print(OUT "OUI:" . $vendor . "*\n"); - print(OUT " ID_OUI_FROM_DATABASE=" . $text . "\n"); - } - } - } - close(IN); - - close(OUT); -} - -usb_vendor(); -usb_classes(); - -pci_vendor(); -pci_classes(); - -sdio_vendor(); -sdio_classes(); - -oui(); -- 2.25.1