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
) {
68 has_protected_collection_
= HasProtectedCollection(device_info
);
71 HidConnection::~HidConnection() {
72 DCHECK(thread_checker_
.CalledOnValidThread());
75 void HidConnection::Read(const ReadCallback
& callback
) {
76 DCHECK(thread_checker_
.CalledOnValidThread());
77 if (device_info_
.max_input_report_size
== 0) {
78 VLOG(1) << "This device does not support input reports.";
79 callback
.Run(false, NULL
, 0);
83 PlatformRead(callback
);
86 void HidConnection::Write(scoped_refptr
<net::IOBuffer
> buffer
,
88 const WriteCallback
& callback
) {
89 DCHECK(thread_checker_
.CalledOnValidThread());
90 if (device_info_
.max_output_report_size
== 0) {
91 VLOG(1) << "This device does not support output reports.";
96 uint8_t report_id
= buffer
->data()[0];
97 if (device_info().has_report_id
!= (report_id
!= 0)) {
98 VLOG(1) << "Invalid output report ID.";
102 if (IsReportIdProtected(report_id
)) {
103 VLOG(1) << "Attempt to set a protected output report.";
108 PlatformWrite(buffer
, size
, callback
);
111 void HidConnection::GetFeatureReport(uint8_t report_id
,
112 const ReadCallback
& callback
) {
113 DCHECK(thread_checker_
.CalledOnValidThread());
114 if (device_info_
.max_feature_report_size
== 0) {
115 VLOG(1) << "This device does not support feature reports.";
116 callback
.Run(false, NULL
, 0);
119 if (device_info().has_report_id
!= (report_id
!= 0)) {
120 VLOG(1) << "Invalid feature report ID.";
121 callback
.Run(false, NULL
, 0);
124 if (IsReportIdProtected(report_id
)) {
125 VLOG(1) << "Attempt to get a protected feature report.";
126 callback
.Run(false, NULL
, 0);
130 PlatformGetFeatureReport(report_id
, callback
);
133 void HidConnection::SendFeatureReport(scoped_refptr
<net::IOBuffer
> buffer
,
135 const WriteCallback
& callback
) {
136 DCHECK(thread_checker_
.CalledOnValidThread());
137 if (device_info_
.max_feature_report_size
== 0) {
138 VLOG(1) << "This device does not support feature reports.";
143 uint8_t report_id
= buffer
->data()[0];
144 if (device_info().has_report_id
!= (report_id
!= 0)) {
145 VLOG(1) << "Invalid feature report ID.";
149 if (IsReportIdProtected(report_id
)) {
150 VLOG(1) << "Attempt to set a protected feature report.";
155 PlatformSendFeatureReport(buffer
, size
, callback
);
158 bool HidConnection::CompleteRead(scoped_refptr
<net::IOBuffer
> buffer
,
160 const ReadCallback
& callback
) {
162 uint8_t report_id
= buffer
->data()[0];
163 if (IsReportIdProtected(report_id
)) {
164 VLOG(1) << "Filtered a protected input report.";
168 callback
.Run(true, buffer
, size
);
172 bool HidConnection::IsReportIdProtected(uint8_t report_id
) {
173 HidCollectionInfo collection_info
;
174 if (FindCollectionByReportId(device_info_
, report_id
, &collection_info
)) {
175 return collection_info
.usage
.IsProtected();
178 return has_protected_collection();
181 PendingHidReport::PendingHidReport() {}
183 PendingHidReport::~PendingHidReport() {}
185 PendingHidRead::PendingHidRead() {}
187 PendingHidRead::~PendingHidRead() {}
189 } // namespace device