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"
13 // Functor used to filter collections by report ID.
14 struct CollectionHasReportId
{
15 explicit CollectionHasReportId(uint8_t report_id
) : report_id_(report_id
) {}
17 bool operator()(const HidCollectionInfo
& info
) const {
18 if (info
.report_ids
.size() == 0 ||
19 report_id_
== HidConnection::kNullReportId
)
22 if (report_id_
== HidConnection::kAnyReportId
)
25 return std::find(info
.report_ids
.begin(),
26 info
.report_ids
.end(),
27 report_id_
) != info
.report_ids
.end();
31 const uint8_t report_id_
;
34 // Functor returning true if collection has a protected usage.
35 struct CollectionIsProtected
{
36 bool operator()(const HidCollectionInfo
& info
) const {
37 return info
.usage
.IsProtected();
41 bool FindCollectionByReportId(const HidDeviceInfo
& device_info
,
43 HidCollectionInfo
* collection_info
) {
44 std::vector
<HidCollectionInfo
>::const_iterator collection_iter
=
45 std::find_if(device_info
.collections
.begin(),
46 device_info
.collections
.end(),
47 CollectionHasReportId(report_id
));
48 if (collection_iter
!= device_info
.collections
.end()) {
49 if (collection_info
) {
50 *collection_info
= *collection_iter
;
58 bool HasProtectedCollection(const HidDeviceInfo
& device_info
) {
59 return std::find_if(device_info
.collections
.begin(),
60 device_info
.collections
.end(),
61 CollectionIsProtected()) != device_info
.collections
.end();
66 HidConnection::HidConnection(const HidDeviceInfo
& device_info
)
67 : device_info_(device_info
), closed_(false) {
68 has_protected_collection_
= HasProtectedCollection(device_info
);
71 HidConnection::~HidConnection() {
72 DCHECK(thread_checker_
.CalledOnValidThread());
76 void HidConnection::Close() {
77 DCHECK(thread_checker_
.CalledOnValidThread());
84 void HidConnection::Read(const ReadCallback
& callback
) {
85 DCHECK(thread_checker_
.CalledOnValidThread());
86 if (device_info_
.max_input_report_size
== 0) {
87 VLOG(1) << "This device does not support input reports.";
88 callback
.Run(false, NULL
, 0);
92 PlatformRead(callback
);
95 void HidConnection::Write(scoped_refptr
<net::IOBuffer
> buffer
,
97 const WriteCallback
& callback
) {
98 DCHECK(thread_checker_
.CalledOnValidThread());
99 if (device_info_
.max_output_report_size
== 0) {
100 VLOG(1) << "This device does not support output reports.";
105 uint8_t report_id
= buffer
->data()[0];
106 if (device_info().has_report_id
!= (report_id
!= 0)) {
107 VLOG(1) << "Invalid output report ID.";
111 if (IsReportIdProtected(report_id
)) {
112 VLOG(1) << "Attempt to set a protected output report.";
117 PlatformWrite(buffer
, size
, callback
);
120 void HidConnection::GetFeatureReport(uint8_t report_id
,
121 const ReadCallback
& callback
) {
122 DCHECK(thread_checker_
.CalledOnValidThread());
123 if (device_info_
.max_feature_report_size
== 0) {
124 VLOG(1) << "This device does not support feature reports.";
125 callback
.Run(false, NULL
, 0);
128 if (device_info().has_report_id
!= (report_id
!= 0)) {
129 VLOG(1) << "Invalid feature report ID.";
130 callback
.Run(false, NULL
, 0);
133 if (IsReportIdProtected(report_id
)) {
134 VLOG(1) << "Attempt to get a protected feature report.";
135 callback
.Run(false, NULL
, 0);
139 PlatformGetFeatureReport(report_id
, callback
);
142 void HidConnection::SendFeatureReport(scoped_refptr
<net::IOBuffer
> buffer
,
144 const WriteCallback
& callback
) {
145 DCHECK(thread_checker_
.CalledOnValidThread());
146 if (device_info_
.max_feature_report_size
== 0) {
147 VLOG(1) << "This device does not support feature reports.";
152 uint8_t report_id
= buffer
->data()[0];
153 if (device_info().has_report_id
!= (report_id
!= 0)) {
154 VLOG(1) << "Invalid feature report ID.";
158 if (IsReportIdProtected(report_id
)) {
159 VLOG(1) << "Attempt to set a protected feature report.";
164 PlatformSendFeatureReport(buffer
, size
, callback
);
167 bool HidConnection::CompleteRead(scoped_refptr
<net::IOBuffer
> buffer
,
169 const ReadCallback
& callback
) {
171 uint8_t report_id
= buffer
->data()[0];
172 if (IsReportIdProtected(report_id
)) {
173 VLOG(1) << "Filtered a protected input report.";
177 callback
.Run(true, buffer
, size
);
181 bool HidConnection::IsReportIdProtected(uint8_t report_id
) {
182 HidCollectionInfo collection_info
;
183 if (FindCollectionByReportId(device_info_
, report_id
, &collection_info
)) {
184 return collection_info
.usage
.IsProtected();
187 return has_protected_collection();
190 PendingHidReport::PendingHidReport() {}
192 PendingHidReport::~PendingHidReport() {}
194 PendingHidRead::PendingHidRead() {}
196 PendingHidRead::~PendingHidRead() {}
198 } // namespace device