diff options
author | jracle@logitech.com <jracle@logitech.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-07-03 02:53:23 +0000 |
---|---|---|
committer | jracle@logitech.com <jracle@logitech.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-07-03 02:53:23 +0000 |
commit | 9ff38235dcea4a3a95e25b602c347f5646bdf4bb (patch) | |
tree | 8b3c0b46ea6699591de7e55e760b73b4753610ae /device/hid/hid_connection.cc | |
parent | 5a43fe6ffbd21cc9a494fa6ed841f877fa09e243 (diff) | |
download | chromium_src-9ff38235dcea4a3a95e25b602c347f5646bdf4bb.zip chromium_src-9ff38235dcea4a3a95e25b602c347f5646bdf4bb.tar.gz chromium_src-9ff38235dcea4a3a95e25b602c347f5646bdf4bb.tar.bz2 |
chrome.hid: enrich model with report IDs
- add report IDs and max report size
- don't expose sensitive usages
BUG=364423
R=rockot@chromium.org
TESTS=run device_unittests (HidReportDescriptorTest)
Review URL: https://codereview.chromium.org/317783010
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@281133 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'device/hid/hid_connection.cc')
-rw-r--r-- | device/hid/hid_connection.cc | 180 |
1 files changed, 175 insertions, 5 deletions
diff --git a/device/hid/hid_connection.cc b/device/hid/hid_connection.cc index c134bf2..76809d3 100644 --- a/device/hid/hid_connection.cc +++ b/device/hid/hid_connection.cc @@ -4,8 +4,183 @@ #include "device/hid/hid_connection.h" +#include <algorithm> + namespace device { +namespace { + +// Functor used to filter collections by report ID. +struct CollectionHasReportId { + explicit CollectionHasReportId(const uint8_t report_id) + : report_id_(report_id) {} + + bool operator()(const HidCollectionInfo& info) const { + if (info.report_ids.size() == 0 || + report_id_ == HidConnection::kNullReportId) + return false; + + if (report_id_ == HidConnection::kAnyReportId) + return true; + + return std::find(info.report_ids.begin(), + info.report_ids.end(), + report_id_) != info.report_ids.end(); + } + + private: + const uint8_t report_id_; +}; + +// Functor returning true if collection has a protected usage. +struct CollectionIsProtected { + bool operator()(const HidCollectionInfo& info) const { + return info.usage.IsProtected(); + } +}; + +bool FindCollectionByReportId(const HidDeviceInfo& device_info, + const uint8_t report_id, + HidCollectionInfo* collection_info) { + std::vector<HidCollectionInfo>::const_iterator collection_iter = + std::find_if(device_info.collections.begin(), + device_info.collections.end(), + CollectionHasReportId(report_id)); + if (collection_iter != device_info.collections.end()) { + if (collection_info) { + *collection_info = *collection_iter; + } + return true; + } + + return false; +} + +bool HasReportId(const HidDeviceInfo& device_info) { + return FindCollectionByReportId( + device_info, HidConnection::kAnyReportId, NULL); +} + +bool HasProtectedCollection(const HidDeviceInfo& device_info) { + return std::find_if(device_info.collections.begin(), + device_info.collections.end(), + CollectionIsProtected()) != device_info.collections.end(); +} + +} // namespace + +HidConnection::HidConnection(const HidDeviceInfo& device_info) + : device_info_(device_info) { + has_protected_collection_ = HasProtectedCollection(device_info); + has_report_id_ = HasReportId(device_info); +} + +HidConnection::~HidConnection() { + DCHECK(thread_checker_.CalledOnValidThread()); +} + +void HidConnection::Read(scoped_refptr<net::IOBufferWithSize> buffer, + const IOCallback& callback) { + DCHECK(thread_checker_.CalledOnValidThread()); + if (device_info_.max_input_report_size == 0) { + // The device does not support input reports. + callback.Run(false, 0); + return; + } + int expected_buffer_size = device_info_.max_input_report_size; + if (!has_report_id()) { + expected_buffer_size--; + } + if (buffer->size() < expected_buffer_size) { + // Receive buffer is too small. + callback.Run(false, 0); + return; + } + + PlatformRead(buffer, callback); +} + +void HidConnection::Write(uint8_t report_id, + scoped_refptr<net::IOBufferWithSize> buffer, + const IOCallback& callback) { + DCHECK(thread_checker_.CalledOnValidThread()); + if (device_info_.max_output_report_size == 0) { + // The device does not support output reports. + callback.Run(false, 0); + return; + } + if (IsReportIdProtected(report_id)) { + callback.Run(false, 0); + return; + } + + PlatformWrite(report_id, buffer, callback); +} + +void HidConnection::GetFeatureReport( + uint8_t report_id, + scoped_refptr<net::IOBufferWithSize> buffer, + const IOCallback& callback) { + DCHECK(thread_checker_.CalledOnValidThread()); + if (device_info_.max_feature_report_size == 0) { + // The device does not support feature reports. + callback.Run(false, 0); + return; + } + if (IsReportIdProtected(report_id)) { + callback.Run(false, 0); + return; + } + int expected_buffer_size = device_info_.max_feature_report_size; + if (!has_report_id()) { + expected_buffer_size--; + } + if (buffer->size() < expected_buffer_size) { + // Receive buffer is too small. + callback.Run(false, 0); + return; + } + + PlatformGetFeatureReport(report_id, buffer, callback); +} + +void HidConnection::SendFeatureReport( + uint8_t report_id, + scoped_refptr<net::IOBufferWithSize> buffer, + const IOCallback& callback) { + DCHECK(thread_checker_.CalledOnValidThread()); + if (device_info_.max_feature_report_size == 0) { + // The device does not support feature reports. + callback.Run(false, 0); + return; + } + if (IsReportIdProtected(report_id)) { + callback.Run(false, 0); + return; + } + + PlatformSendFeatureReport(report_id, buffer, callback); +} + +bool HidConnection::CompleteRead(scoped_refptr<net::IOBufferWithSize> buffer, + const IOCallback& callback) { + if (buffer->size() == 0 || IsReportIdProtected(buffer->data()[0])) { + return false; + } + + callback.Run(true, buffer->size()); + return true; +} + +bool HidConnection::IsReportIdProtected(const uint8_t report_id) { + HidCollectionInfo collection_info; + if (FindCollectionByReportId(device_info_, report_id, &collection_info)) { + return collection_info.usage.IsProtected(); + } + + return has_protected_collection(); +} + PendingHidReport::PendingHidReport() {} PendingHidReport::~PendingHidReport() {} @@ -14,9 +189,4 @@ PendingHidRead::PendingHidRead() {} PendingHidRead::~PendingHidRead() {} -HidConnection::HidConnection(const HidDeviceInfo& device_info) - : device_info_(device_info) {} - -HidConnection::~HidConnection() {} - } // namespace device |