summaryrefslogtreecommitdiffstats
path: root/device/hid
diff options
context:
space:
mode:
authorreillyg <reillyg@chromium.org>2014-08-28 22:52:48 -0700
committerCommit bot <commit-bot@chromium.org>2014-08-29 05:53:46 +0000
commitf4dc9d143de2350fc4879c178059737997944016 (patch)
treede808301f613297af60b8ce5bdee43cc2b511264 /device/hid
parent3a05d24b124114e117c2d81592edbd14bbcf1b1c (diff)
downloadchromium_src-f4dc9d143de2350fc4879c178059737997944016.zip
chromium_src-f4dc9d143de2350fc4879c178059737997944016.tar.gz
chromium_src-f4dc9d143de2350fc4879c178059737997944016.tar.bz2
Add more generic filters to the chrome.hid.getDevices API.
Instead of specifying each of the USB vendor and product ID pairs an app has permission to open this API extension allows filtering of devices by vendor and product IDs as well as HID usage pages and usages. The 'vendorId' and 'productId' properties of GetDevicesOptions are still supported for backwards compatibility. BUG= Review URL: https://codereview.chromium.org/514923002 Cr-Commit-Position: refs/heads/master@{#292577}
Diffstat (limited to 'device/hid')
-rw-r--r--device/hid/BUILD.gn2
-rw-r--r--device/hid/hid.gyp2
-rw-r--r--device/hid/hid_device_filter.cc89
-rw-r--r--device/hid/hid_device_filter.h43
-rw-r--r--device/hid/hid_device_filter_unittest.cc116
5 files changed, 252 insertions, 0 deletions
diff --git a/device/hid/BUILD.gn b/device/hid/BUILD.gn
index edd3ecb..bc450db 100644
--- a/device/hid/BUILD.gn
+++ b/device/hid/BUILD.gn
@@ -16,6 +16,8 @@ source_set("hid") {
"hid_connection_mac.h",
"hid_connection_win.cc",
"hid_connection_win.h",
+ "hid_device_filter.cc",
+ "hid_device_filter.h",
"hid_device_info.cc",
"hid_device_info.h",
"hid_report_descriptor.cc",
diff --git a/device/hid/hid.gyp b/device/hid/hid.gyp
index 2db80fd..1c01ca1 100644
--- a/device/hid/hid.gyp
+++ b/device/hid/hid.gyp
@@ -26,6 +26,8 @@
'hid_connection_mac.h',
'hid_connection_win.cc',
'hid_connection_win.h',
+ 'hid_device_filter.cc',
+ 'hid_device_filter.h',
'hid_device_info.cc',
'hid_device_info.h',
'hid_report_descriptor.cc',
diff --git a/device/hid/hid_device_filter.cc b/device/hid/hid_device_filter.cc
new file mode 100644
index 0000000..70ebcf4
--- /dev/null
+++ b/device/hid/hid_device_filter.cc
@@ -0,0 +1,89 @@
+// Copyright 2014 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/hid/hid_device_filter.h"
+
+#include "device/hid/hid_device_info.h"
+
+namespace device {
+
+HidDeviceFilter::HidDeviceFilter()
+ : vendor_id_set_(false),
+ product_id_set_(false),
+ usage_page_set_(false),
+ usage_set_(false) {
+}
+
+HidDeviceFilter::~HidDeviceFilter() {
+}
+
+void HidDeviceFilter::SetVendorId(uint16_t vendor_id) {
+ vendor_id_set_ = true;
+ vendor_id_ = vendor_id;
+}
+
+void HidDeviceFilter::SetProductId(uint16_t product_id) {
+ product_id_set_ = true;
+ product_id_ = product_id;
+}
+
+void HidDeviceFilter::SetUsagePage(uint16_t usage_page) {
+ usage_page_set_ = true;
+ usage_page_ = usage_page;
+}
+
+void HidDeviceFilter::SetUsage(uint16_t usage) {
+ usage_set_ = true;
+ usage_ = usage;
+}
+
+bool HidDeviceFilter::Matches(const HidDeviceInfo& device_info) const {
+ if (vendor_id_set_) {
+ if (device_info.vendor_id != vendor_id_) {
+ return false;
+ }
+
+ if (product_id_set_ && device_info.product_id != product_id_) {
+ return false;
+ }
+ }
+
+ if (usage_page_set_) {
+ bool found_matching_collection = false;
+ for (std::vector<HidCollectionInfo>::const_iterator i =
+ device_info.collections.begin();
+ i != device_info.collections.end() && !found_matching_collection;
+ ++i) {
+ const HidCollectionInfo& collection = *i;
+ if (collection.usage.usage_page != usage_page_) {
+ continue;
+ }
+ if (usage_set_ && collection.usage.usage != usage_) {
+ continue;
+ }
+ found_matching_collection = true;
+ }
+ if (!found_matching_collection) {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+// static
+bool HidDeviceFilter::MatchesAny(
+ const HidDeviceInfo& device_info,
+ const std::vector<HidDeviceFilter>& filters) {
+ for (std::vector<HidDeviceFilter>::const_iterator i = filters.begin();
+ i != filters.end();
+ ++i) {
+ if (i->Matches(device_info)) {
+ return true;
+ }
+ }
+ return false;
+}
+
+} // namespace device
diff --git a/device/hid/hid_device_filter.h b/device/hid/hid_device_filter.h
new file mode 100644
index 0000000..a0abbb7
--- /dev/null
+++ b/device/hid/hid_device_filter.h
@@ -0,0 +1,43 @@
+// Copyright 2014 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_HID_HID_DEVICE_FILTER_H_
+#define DEVICE_HID_HID_DEVICE_FILTER_H_
+
+#include <stdint.h>
+#include <vector>
+
+namespace device {
+
+struct HidDeviceInfo;
+
+class HidDeviceFilter {
+ public:
+ HidDeviceFilter();
+ ~HidDeviceFilter();
+
+ void SetVendorId(uint16_t vendor_id);
+ void SetProductId(uint16_t product_id);
+ void SetUsagePage(uint16_t usage_page);
+ void SetUsage(uint16_t usage);
+
+ bool Matches(const HidDeviceInfo& device_info) const;
+
+ static bool MatchesAny(const HidDeviceInfo& device_info,
+ const std::vector<HidDeviceFilter>& filters);
+
+ private:
+ uint16_t vendor_id_;
+ uint16_t product_id_;
+ uint16_t usage_page_;
+ uint16_t usage_;
+ bool vendor_id_set_ : 1;
+ bool product_id_set_ : 1;
+ bool usage_page_set_ : 1;
+ bool usage_set_ : 1;
+};
+
+} // namespace device
+
+#endif // DEVICE_HID_HID_DEVICE_FILTER_H_
diff --git a/device/hid/hid_device_filter_unittest.cc b/device/hid/hid_device_filter_unittest.cc
new file mode 100644
index 0000000..599dda4
--- /dev/null
+++ b/device/hid/hid_device_filter_unittest.cc
@@ -0,0 +1,116 @@
+// Copyright 2014 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/hid/hid_device_filter.h"
+#include "device/hid/hid_device_info.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace device {
+
+namespace {
+
+class HidFilterTest : public testing::Test {
+ public:
+ virtual void SetUp() OVERRIDE {
+ device_info_.vendor_id = 0x046d;
+ device_info_.product_id = 0xc31c;
+
+ HidCollectionInfo collection;
+ collection.usage.usage_page = HidUsageAndPage::kPageKeyboard;
+ collection.usage.usage = 0x01;
+ device_info_.collections.push_back(collection);
+ }
+
+ protected:
+ HidDeviceInfo device_info_;
+};
+
+TEST_F(HidFilterTest, MatchAny) {
+ HidDeviceFilter filter;
+ ASSERT_TRUE(filter.Matches(device_info_));
+}
+
+TEST_F(HidFilterTest, MatchVendorId) {
+ HidDeviceFilter filter;
+ filter.SetVendorId(0x046d);
+ ASSERT_TRUE(filter.Matches(device_info_));
+}
+
+TEST_F(HidFilterTest, MatchVendorIdNegative) {
+ HidDeviceFilter filter;
+ filter.SetVendorId(0x18d1);
+ ASSERT_FALSE(filter.Matches(device_info_));
+}
+
+TEST_F(HidFilterTest, MatchProductId) {
+ HidDeviceFilter filter;
+ filter.SetVendorId(0x046d);
+ filter.SetProductId(0xc31c);
+ ASSERT_TRUE(filter.Matches(device_info_));
+}
+
+TEST_F(HidFilterTest, MatchProductIdNegative) {
+ HidDeviceFilter filter;
+ filter.SetVendorId(0x046d);
+ filter.SetProductId(0x0801);
+ ASSERT_FALSE(filter.Matches(device_info_));
+}
+
+TEST_F(HidFilterTest, MatchUsagePage) {
+ HidDeviceFilter filter;
+ filter.SetUsagePage(HidUsageAndPage::kPageKeyboard);
+ ASSERT_TRUE(filter.Matches(device_info_));
+}
+
+TEST_F(HidFilterTest, MatchUsagePageNegative) {
+ HidDeviceFilter filter;
+ filter.SetUsagePage(HidUsageAndPage::kPageLed);
+ ASSERT_FALSE(filter.Matches(device_info_));
+}
+
+TEST_F(HidFilterTest, MatchVendorAndUsagePage) {
+ HidDeviceFilter filter;
+ filter.SetVendorId(0x046d);
+ filter.SetUsagePage(HidUsageAndPage::kPageKeyboard);
+ ASSERT_TRUE(filter.Matches(device_info_));
+}
+
+TEST_F(HidFilterTest, MatchUsageAndPage) {
+ HidDeviceFilter filter;
+ filter.SetUsagePage(HidUsageAndPage::kPageKeyboard);
+ filter.SetUsage(0x01);
+ ASSERT_TRUE(filter.Matches(device_info_));
+}
+
+TEST_F(HidFilterTest, MatchUsageAndPageNegative) {
+ HidDeviceFilter filter;
+ filter.SetUsagePage(HidUsageAndPage::kPageKeyboard);
+ filter.SetUsage(0x02);
+ ASSERT_FALSE(filter.Matches(device_info_));
+}
+
+TEST_F(HidFilterTest, MatchEmptyFilterListNegative) {
+ std::vector<HidDeviceFilter> filters;
+ ASSERT_FALSE(HidDeviceFilter::MatchesAny(device_info_, filters));
+}
+
+TEST_F(HidFilterTest, MatchFilterList) {
+ std::vector<HidDeviceFilter> filters;
+ HidDeviceFilter filter;
+ filter.SetUsagePage(HidUsageAndPage::kPageKeyboard);
+ filters.push_back(filter);
+ ASSERT_TRUE(HidDeviceFilter::MatchesAny(device_info_, filters));
+}
+
+TEST_F(HidFilterTest, MatchFilterListNegative) {
+ std::vector<HidDeviceFilter> filters;
+ HidDeviceFilter filter;
+ filter.SetUsagePage(HidUsageAndPage::kPageLed);
+ filters.push_back(filter);
+ ASSERT_FALSE(HidDeviceFilter::MatchesAny(device_info_, filters));
+}
+
+} // namespace
+
+} // namespace device