diff options
-rw-r--r-- | chrome/chrome_browser_extensions.gypi | 1 | ||||
-rw-r--r-- | device/device.gyp | 36 | ||||
-rw-r--r-- | device/usb/OWNERS | 2 | ||||
-rw-r--r-- | device/usb/usb_ids.cc | 58 | ||||
-rw-r--r-- | device/usb/usb_ids.h | 58 | ||||
-rw-r--r-- | device/usb/usb_ids_unittest.cc | 31 | ||||
-rw-r--r-- | tools/usb_ids/usb_ids.py | 110 |
7 files changed, 296 insertions, 0 deletions
diff --git a/chrome/chrome_browser_extensions.gypi b/chrome/chrome_browser_extensions.gypi index 2fc5943..5d4efe1 100644 --- a/chrome/chrome_browser_extensions.gypi +++ b/chrome/chrome_browser_extensions.gypi @@ -31,6 +31,7 @@ '../content/content.gyp:content_browser', '../crypto/crypto.gyp:crypto', '../device/device.gyp:device_bluetooth', + '../device/device.gyp:device_usb', '../net/net.gyp:net', '../skia/skia.gyp:skia', '../sync/sync.gyp:sync_notifier', diff --git a/device/device.gyp b/device/device.gyp index 75902fc..08cac92 100644 --- a/device/device.gyp +++ b/device/device.gyp @@ -71,11 +71,46 @@ ], }, { + 'target_name': 'device_usb', + 'type': 'static_library', + 'sources': [ + 'usb/usb_ids.cc', + 'usb/usb_ids.h', + ], + 'include_dirs': [ + '..', + ], + 'actions': [ + { + 'action_name': 'generate_usb_ids', + 'variables': { + 'usb_ids_path%': '<(DEPTH)/third_party/usb_ids/usb.ids', + 'usb_ids_py_path': '<(DEPTH)/tools/usb_ids/usb_ids.py', + }, + 'inputs': [ + '<(usb_ids_path)', + '<(usb_ids_py_path)', + ], + 'outputs': [ + '<(SHARED_INTERMEDIATE_DIR)/device/usb/usb_ids_gen.cc', + ], + 'action': [ + 'python', + '<(usb_ids_py_path)', + '-i', '<(usb_ids_path)', + '-o', '<@(_outputs)', + ], + 'process_outputs_as_sources': 1, + }, + ], + }, + { 'target_name': 'device_unittests', 'type': '<(gtest_target_type)', 'dependencies': [ 'device_bluetooth', 'device_bluetooth_mocks', + 'device_usb', '../base/base.gyp:test_support_base', '../content/content.gyp:test_support_content', '../testing/gmock.gyp:gmock', @@ -90,6 +125,7 @@ 'test/device_test_suite.cc', 'test/device_test_suite.h', 'test/run_all_unittests.cc', + 'usb/usb_ids_unittest.cc', ], 'conditions': [ ['chromeos==1', { diff --git a/device/usb/OWNERS b/device/usb/OWNERS new file mode 100644 index 0000000..2ffd61a --- /dev/null +++ b/device/usb/OWNERS @@ -0,0 +1,2 @@ +gdk@chromium.org +bryeung@chromium.org diff --git a/device/usb/usb_ids.cc b/device/usb/usb_ids.cc new file mode 100644 index 0000000..fbb5b7e --- /dev/null +++ b/device/usb/usb_ids.cc @@ -0,0 +1,58 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "device/usb/usb_ids.h" + +#include <stdlib.h> + +#include "base/basictypes.h" + +namespace device { + +namespace { + +static int CompareVendors(const void* a, const void* b) { + const UsbVendor* vendor_a = static_cast<const UsbVendor*>(a); + const UsbVendor* vendor_b = static_cast<const UsbVendor*>(b); + return vendor_a->id - vendor_b->id; +} + +static int CompareProducts(const void* a, const void* b) { + const UsbProduct* product_a = static_cast<const UsbProduct*>(a); + const UsbProduct* product_b = static_cast<const UsbProduct*>(b); + return product_a->id - product_b->id; +} + +} // namespace + +const UsbVendor* UsbIds::FindVendor(uint16_t vendor_id) { + const UsbVendor key = {vendor_id, NULL, 0, NULL}; + void* result = bsearch(&key, vendors_, vendor_size_, sizeof(vendors_[0]), + &CompareVendors); + if (!result) + return NULL; + return static_cast<const UsbVendor*>(result); +} + +const char* UsbIds::GetVendorName(uint16_t vendor_id) { + const UsbVendor* vendor = FindVendor(vendor_id); + if (!vendor) + return NULL; + return vendor->name; +} + +const char* UsbIds::GetProductName(uint16_t vendor_id, uint16_t product_id) { + const UsbVendor* vendor = FindVendor(vendor_id); + if (!vendor) + return NULL; + + const UsbProduct key = {product_id, NULL}; + void* result = bsearch(&key, vendor->products, vendor->product_size, + sizeof(vendor->products[0]), &CompareProducts); + if (!result) + return NULL; + return static_cast<const UsbProduct*>(result)->name; +} + +} // namespace device diff --git a/device/usb/usb_ids.h b/device/usb/usb_ids.h new file mode 100644 index 0000000..2f6b950 --- /dev/null +++ b/device/usb/usb_ids.h @@ -0,0 +1,58 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef DEVICE_USB_USB_IDS_H_ +#define DEVICE_USB_USB_IDS_H_ + +#include <stdint.h> + +#include "base/basictypes.h" + +namespace device { + +struct UsbProduct { + const uint16_t id; + const char* name; +}; + +struct UsbVendor { + const uint16_t id; + const char* name; + const size_t product_size; + const UsbProduct* products; +}; + +// UsbIds provides a static mapping from a vendor ID to a name, as well as a +// mapping from a vendor/product ID pair to a product name. +class UsbIds { + public: + // Gets the name of the vendor who owns |vendor_id|. Returns NULL if the + // specified |vendor_id| does not exist. + static const char* GetVendorName(uint16_t vendor_id); + + // Gets the name of a product belonging to a specific vendor. If either + // |vendor_id| refers to a vendor that does not exist, or |vendor_id| is valid + // but |product_id| refers to a product that does not exist, this method + // returns NULL. + static const char* GetProductName(uint16_t vendor_id, uint16_t product_id); + + private: + UsbIds(); + ~UsbIds(); + + // Finds the static UsbVendor associated with |vendor_id|. Returns NULL if no + // such vendor exists. + static const UsbVendor* FindVendor(uint16_t vendor_id); + + // These fields are defined in a generated file. See device/device.gyp for + // more information on how they are generated. + static const size_t vendor_size_; + static const UsbVendor vendors_[]; + + DISALLOW_COPY_AND_ASSIGN(UsbIds); +}; + +} // namespace device + +#endif // DEVICE_USB_USB_IDS_H_ diff --git a/device/usb/usb_ids_unittest.cc b/device/usb/usb_ids_unittest.cc new file mode 100644 index 0000000..decce1e --- /dev/null +++ b/device/usb/usb_ids_unittest.cc @@ -0,0 +1,31 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include <string> + +#include "device/usb/usb_ids.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace { + +static const uint16_t kGoogleVendorId = 0x18d1; +static const uint16_t kNexusSProductId = 0x4e21; + +} // namespace + +namespace device { + +TEST(UsbIdsTest, GetVendorName) { + EXPECT_EQ(NULL, UsbIds::GetVendorName(0)); + EXPECT_EQ(std::string("Google Inc."), UsbIds::GetVendorName(kGoogleVendorId)); +} + +TEST(UsbIdsTest, GetProductName) { + EXPECT_EQ(NULL, UsbIds::GetProductName(0, 0)); + EXPECT_EQ(NULL, UsbIds::GetProductName(kGoogleVendorId, 0)); + EXPECT_EQ(std::string("Nexus S"), UsbIds::GetProductName(kGoogleVendorId, + kNexusSProductId)); +} + +} // namespace device diff --git a/tools/usb_ids/usb_ids.py b/tools/usb_ids/usb_ids.py new file mode 100644 index 0000000..e07bd4c --- /dev/null +++ b/tools/usb_ids/usb_ids.py @@ -0,0 +1,110 @@ +# Copyright (c) 2012 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +import itertools +import optparse +import re + +VENDOR_PATTERN = re.compile("^(?P<id>[0-9a-fA-F]{4})\s+(?P<name>.+)$") +PRODUCT_PATTERN = re.compile("^\t(?P<id>[0-9a-fA-F]{4})\s+(?P<name>.+)$") + +def EscapeName(name): + name = name.replace("\\", "\\\\") + name = name.replace("\"", "\\\"") + name = name.replace("?", "\?") + return name + +def ParseTable(input_path): + input_file = open(input_path, "r") + input = input_file.read().split("\n") + input_file.close() + + table = {} + vendor = None + + for line in input: + vendor_match = VENDOR_PATTERN.match(line) + if vendor_match: + if vendor: + table[vendor["id"]] = vendor + vendor = {} + vendor["id"] = int(vendor_match.group("id"), 16) + vendor["name"] = vendor_match.group("name") + vendor["products"] = [] + continue + + product_match = PRODUCT_PATTERN.match(line) + if product_match: + if not vendor: + raise Exception("Product seems to appear before vendor.") + product = {} + product["id"] = int(product_match.group("id"), 16) + product["name"] = product_match.group("name") + vendor["products"].append(product) + + return table + +def GenerateDeviceDefinitions(table): + output = "" + + for vendor_id in sorted(table.keys()): + vendor = table[vendor_id] + if len(vendor["products"]) == 0: + continue + + output += "static const UsbProduct vendor_%.4x_products[] = {\n" % \ + vendor["id"] + for product in vendor["products"]: + output += " {0x%.4x, \"%s\"},\n" % (product["id"], + EscapeName(product["name"])) + output += "};\n" + + return output + +def GenerateVendorDefinitions(table): + output = "const size_t UsbIds::vendor_size_ = %d;\n" % len(table.keys()) + output += "const UsbVendor UsbIds::vendors_[] = {\n" + + for vendor_id in sorted(table.keys()): + vendor = table[vendor_id] + + product_table = "NULL" + if len(vendor["products"]) != 0: + product_table = "vendor_%.4x_products" % (vendor["id"]) + output += " {0x%.4x, \"%s\", %d, %s},\n" % (vendor["id"], + EscapeName(vendor["name"]), len(vendor["products"]), product_table) + + output += "};\n" + return output + +if __name__ == "__main__": + parser = optparse.OptionParser( + description="Generates a C++ USB ID lookup table.") + parser.add_option("-i", "--input", help="Path to usb.ids") + parser.add_option("-o", "--output", help="Output file path") + + (opts, args) = parser.parse_args() + table = ParseTable(opts.input) + + output = """// Generated from %s +#ifndef GENERATED_USB_IDS_H_ +#define GENERATED_USB_IDS_H_ + +#include "device/usb/usb_ids.h" + +namespace device { + +""" % (opts.input) + output += GenerateDeviceDefinitions(table) + output += GenerateVendorDefinitions(table) + output += """ + +} // namespace device + +#endif // GENERATED_USB_IDS_H_ +""" + + output_file = open(opts.output, "w+") + output_file.write(output) + output_file.close() |