1#!/usr/bin/env python3
2
3# SPDX-FileCopyrightText: 2021 Pino Toscano <pino@debian.org>
4# SPDX-License-Identifier: GPL-2.0-or-later
5
6import os
7import re
8import sys
9from collections import namedtuple
10
11
12UsbIds = namedtuple('UsbIds',
13                    ['classes', 'subclasses', 'protocols', 'date'])
14
15
16def parse(fn):
17    classes = []
18    subclasses = []
19    protocols = []
20    date = None
21
22    class_re = re.compile("^C ([0-9a-fA-F]{2})\\s+(.+)$")
23    subclass_re = re.compile("^\t([0-9a-fA-F]{2})\\s+(.+)$")
24    protocol_re = re.compile("^\t\t([0-9a-fA-F]{2})\\s+(.+)$")
25
26    with open(fn, 'r', encoding='iso-8859-1') as f:
27        in_class = False
28        in_subclass = False
29        for line in f:
30            line = line.rstrip('\n')
31            line_len = len(line)
32
33            if line_len > 0 and line[0] == '#':
34                if line.startswith('# Date:'):
35                    date = line.split(':', maxsplit=1)[1].strip()
36                continue
37
38            if line_len == 0 or (line[0].isalnum() and line[0] != 'C'):
39                in_class = False
40                in_subclass = False
41                continue
42
43            m = class_re.fullmatch(line)
44            if m:
45                classes.append(m[2].rstrip())
46                in_class = True
47                continue
48            if in_class:
49                m = subclass_re.fullmatch(line)
50                if m:
51                    in_subclass = True
52                    subclasses.append(m[2].rstrip())
53                    continue
54            if in_class and in_subclass:
55                m = protocol_re.fullmatch(line)
56                if m:
57                    protocols.append(m[2].rstrip())
58                    continue
59
60            in_class = False
61            in_subclass = False
62
63    parsed = UsbIds(classes, subclasses, protocols, date)
64
65    return parsed
66
67
68def output(strings, context):
69    for s in strings:
70        print('i18nc("{}", "{}");'.format(context, s))
71
72
73if __name__ == '__main__':
74    if len(sys.argv) != 2:
75        print('Usage: {} /path/to/usb.ids'.format(sys.argv[0]),
76              file=sys.stderr)
77        sys.exit(1)
78
79    filename = sys.argv[1]
80    parsed = parse(filename)
81    classes = sorted(list(set(parsed.classes)))
82    subclasses = sorted(list(set(parsed.subclasses)))
83    if parsed.date:
84        date_str = parsed.date
85    else:
86        date_str = 'n/a'
87    print('// Generated from {} with date \'{}\''.format(
88              os.path.basename(filename), date_str))
89    output(classes, 'USB device class')
90    output(subclasses, 'USB device subclass')
91