| Index: device/hid/hid_connection.cc
|
| diff --git a/device/hid/hid_connection.cc b/device/hid/hid_connection.cc
|
| index c134bf2702e96aca40ca0cc58b376d9b151a1aa2..76809d3292c2a2929106d67a60858839b5b5292d 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
|
|
|