Use multiline attribute to check for IA2_STATE_MULTILINE.
[chromium-blink-merge.git] / device / hid / hid_connection.cc
blob208a565a1569f0dc62fe3432e1841a1d07c1e0bd
1 // Copyright (c) 2014 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.
5 #include "device/hid/hid_connection.h"
7 #include <algorithm>
9 #include "components/device_event_log/device_event_log.h"
11 namespace device {
13 namespace {
15 // Functor used to filter collections by report ID.
16 struct CollectionHasReportId {
17 explicit CollectionHasReportId(uint8_t report_id) : report_id_(report_id) {}
19 bool operator()(const HidCollectionInfo& info) const {
20 if (info.report_ids.size() == 0 ||
21 report_id_ == HidConnection::kNullReportId)
22 return false;
24 if (report_id_ == HidConnection::kAnyReportId)
25 return true;
27 return std::find(info.report_ids.begin(),
28 info.report_ids.end(),
29 report_id_) != info.report_ids.end();
32 private:
33 const uint8_t report_id_;
36 // Functor returning true if collection has a protected usage.
37 struct CollectionIsProtected {
38 bool operator()(const HidCollectionInfo& info) const {
39 return info.usage.IsProtected();
43 bool FindCollectionByReportId(const std::vector<HidCollectionInfo>& collections,
44 uint8_t report_id,
45 HidCollectionInfo* collection_info) {
46 std::vector<HidCollectionInfo>::const_iterator collection_iter = std::find_if(
47 collections.begin(), collections.end(), CollectionHasReportId(report_id));
48 if (collection_iter != collections.end()) {
49 if (collection_info) {
50 *collection_info = *collection_iter;
52 return true;
55 return false;
58 bool HasProtectedCollection(const std::vector<HidCollectionInfo>& collections) {
59 return std::find_if(collections.begin(), collections.end(),
60 CollectionIsProtected()) != collections.end();
63 } // namespace
65 HidConnection::HidConnection(scoped_refptr<HidDeviceInfo> device_info)
66 : device_info_(device_info), closed_(false) {
67 has_protected_collection_ =
68 HasProtectedCollection(device_info->collections());
71 HidConnection::~HidConnection() {
72 DCHECK(thread_checker_.CalledOnValidThread());
73 DCHECK(closed_);
76 void HidConnection::Close() {
77 DCHECK(thread_checker_.CalledOnValidThread());
78 DCHECK(!closed_);
80 PlatformClose();
81 closed_ = true;
84 void HidConnection::Read(const ReadCallback& callback) {
85 DCHECK(thread_checker_.CalledOnValidThread());
86 if (device_info_->max_input_report_size() == 0) {
87 HID_LOG(USER) << "This device does not support input reports.";
88 callback.Run(false, NULL, 0);
89 return;
92 PlatformRead(callback);
95 void HidConnection::Write(scoped_refptr<net::IOBuffer> buffer,
96 size_t size,
97 const WriteCallback& callback) {
98 DCHECK(thread_checker_.CalledOnValidThread());
99 if (device_info_->max_output_report_size() == 0) {
100 HID_LOG(USER) << "This device does not support output reports.";
101 callback.Run(false);
102 return;
104 if (size > device_info_->max_output_report_size() + 1) {
105 HID_LOG(USER) << "Output report buffer too long (" << size << " > "
106 << (device_info_->max_output_report_size() + 1) << ").";
107 callback.Run(false);
108 return;
110 DCHECK_GE(size, 1u);
111 uint8_t report_id = buffer->data()[0];
112 if (device_info_->has_report_id() != (report_id != 0)) {
113 HID_LOG(USER) << "Invalid output report ID.";
114 callback.Run(false);
115 return;
117 if (IsReportIdProtected(report_id)) {
118 HID_LOG(USER) << "Attempt to set a protected output report.";
119 callback.Run(false);
120 return;
123 PlatformWrite(buffer, size, callback);
126 void HidConnection::GetFeatureReport(uint8_t report_id,
127 const ReadCallback& callback) {
128 DCHECK(thread_checker_.CalledOnValidThread());
129 if (device_info_->max_feature_report_size() == 0) {
130 HID_LOG(USER) << "This device does not support feature reports.";
131 callback.Run(false, NULL, 0);
132 return;
134 if (device_info_->has_report_id() != (report_id != 0)) {
135 HID_LOG(USER) << "Invalid feature report ID.";
136 callback.Run(false, NULL, 0);
137 return;
139 if (IsReportIdProtected(report_id)) {
140 HID_LOG(USER) << "Attempt to get a protected feature report.";
141 callback.Run(false, NULL, 0);
142 return;
145 PlatformGetFeatureReport(report_id, callback);
148 void HidConnection::SendFeatureReport(scoped_refptr<net::IOBuffer> buffer,
149 size_t size,
150 const WriteCallback& callback) {
151 DCHECK(thread_checker_.CalledOnValidThread());
152 if (device_info_->max_feature_report_size() == 0) {
153 HID_LOG(USER) << "This device does not support feature reports.";
154 callback.Run(false);
155 return;
157 DCHECK_GE(size, 1u);
158 uint8_t report_id = buffer->data()[0];
159 if (device_info_->has_report_id() != (report_id != 0)) {
160 HID_LOG(USER) << "Invalid feature report ID.";
161 callback.Run(false);
162 return;
164 if (IsReportIdProtected(report_id)) {
165 HID_LOG(USER) << "Attempt to set a protected feature report.";
166 callback.Run(false);
167 return;
170 PlatformSendFeatureReport(buffer, size, callback);
173 bool HidConnection::CompleteRead(scoped_refptr<net::IOBuffer> buffer,
174 size_t size,
175 const ReadCallback& callback) {
176 DCHECK_GE(size, 1u);
177 uint8_t report_id = buffer->data()[0];
178 if (IsReportIdProtected(report_id)) {
179 HID_LOG(EVENT) << "Filtered a protected input report.";
180 return false;
183 callback.Run(true, buffer, size);
184 return true;
187 bool HidConnection::IsReportIdProtected(uint8_t report_id) {
188 HidCollectionInfo collection_info;
189 if (FindCollectionByReportId(device_info_->collections(), report_id,
190 &collection_info)) {
191 return collection_info.usage.IsProtected();
194 return has_protected_collection();
197 PendingHidReport::PendingHidReport() {}
199 PendingHidReport::~PendingHidReport() {}
201 PendingHidRead::PendingHidRead() {}
203 PendingHidRead::~PendingHidRead() {}
205 } // namespace device