1# Copyright (c) 2012 The Chromium Authors. All rights reserved.
2# Use of this source code is governed by a BSD-style license that can be
3# found in the LICENSE file.
4
5import io
6import itertools
7import optparse
8import re
9
10VENDOR_PATTERN = re.compile(r"^(?P<id>[0-9a-fA-F]{4})\s+(?P<name>.+)$")
11PRODUCT_PATTERN = re.compile(r"^\t(?P<id>[0-9a-fA-F]{4})\s+(?P<name>.+)$")
12
13def EscapeName(name):
14  name = name.replace("\\", "\\\\")
15  name = name.replace('"', r'\"')
16  name = name.replace("?", r"\?")
17  return name
18
19def ParseTable(input_path):
20  input_file = io.open(input_path, "r", encoding="ascii", errors="ignore")
21  input = input_file.read().split("\n")
22  input_file.close()
23
24  table = {}
25  vendor = None
26
27  for line in input:
28    vendor_match = VENDOR_PATTERN.match(line)
29    if vendor_match:
30      if vendor:
31        table[vendor["id"]] = vendor
32      vendor = {}
33      vendor["id"] = int(vendor_match.group("id"), 16)
34      vendor["name"] = vendor_match.group("name")
35      vendor["products"] = []
36      continue
37
38    product_match = PRODUCT_PATTERN.match(line)
39    if product_match:
40      if not vendor:
41        raise Exception("Product seems to appear before vendor.")
42      product = {}
43      product["id"] = int(product_match.group("id"), 16)
44      product["name"] = product_match.group("name")
45      vendor["products"].append(product)
46
47  return table
48
49def GenerateDeviceDefinitions(table):
50  output = ""
51
52  for vendor_id in sorted(table.keys()):
53    vendor = table[vendor_id]
54    if len(vendor["products"]) == 0:
55      continue
56
57    output += "static const UsbProduct vendor_%.4x_products[] = {\n" % \
58        vendor["id"]
59    for product in vendor["products"]:
60      output += "  {0x%.4x, \"%s\"},\n" % (product["id"],
61                                           EscapeName(product["name"]))
62    output += "};\n"
63
64  return output
65
66def GenerateVendorDefinitions(table):
67  output = "const size_t UsbIds::vendor_size_ = %d;\n" % len(table.keys())
68  output += "const UsbVendor UsbIds::vendors_[] = {\n"
69
70  for vendor_id in sorted(table.keys()):
71    vendor = table[vendor_id]
72
73    product_table = "nullptr"
74    if len(vendor["products"]) != 0:
75      product_table = "vendor_%.4x_products" % (vendor["id"])
76    output += "  {\"%s\", %s, 0x%.4x, %d},\n" % (EscapeName(vendor["name"]),
77                                                 product_table,
78                                                 vendor["id"],
79                                                 len(vendor["products"]))
80
81  output += "};\n"
82  return output
83
84if __name__ == "__main__":
85  parser = optparse.OptionParser(
86      description="Generates a C++ USB ID lookup table.")
87  parser.add_option("-i", "--input", help="Path to usb.ids")
88  parser.add_option("-o", "--output", help="Output file path")
89
90  (opts, args) = parser.parse_args()
91  table = ParseTable(opts.input)
92
93  output = """// Generated from %s
94#ifndef GENERATED_USB_IDS_H_
95#define GENERATED_USB_IDS_H_
96
97#include <stddef.h>
98
99#include "services/device/public/cpp/usb/usb_ids.h"
100
101namespace device {
102
103""" % (opts.input)
104  output += GenerateDeviceDefinitions(table)
105  output += GenerateVendorDefinitions(table)
106  output += """
107
108}  // namespace device
109
110#endif  // GENERATED_USB_IDS_H_
111"""
112
113  output_file = open(opts.output, "w+")
114  output_file.write(output)
115  output_file.close()
116