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