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"
9 #include "components/device_event_log/device_event_log.h"
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
)
24 if (report_id_
== HidConnection::kAnyReportId
)
27 return std::find(info
.report_ids
.begin(),
28 info
.report_ids
.end(),
29 report_id_
) != info
.report_ids
.end();
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
,
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
;
58 bool HasProtectedCollection(const std::vector
<HidCollectionInfo
>& collections
) {
59 return std::find_if(collections
.begin(), collections
.end(),
60 CollectionIsProtected()) != collections
.end();
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());
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 HID_LOG(USER
) << "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 HID_LOG(USER
) << "This device does not support output reports.";
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) << ").";
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.";
117 if (IsReportIdProtected(report_id
)) {
118 HID_LOG(USER
) << "Attempt to set a protected output report.";
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);
134 if (device_info_
->has_report_id() != (report_id
!= 0)) {
135 HID_LOG(USER
) << "Invalid feature report ID.";
136 callback
.Run(false, NULL
, 0);
139 if (IsReportIdProtected(report_id
)) {
140 HID_LOG(USER
) << "Attempt to get a protected feature report.";
141 callback
.Run(false, NULL
, 0);
145 PlatformGetFeatureReport(report_id
, callback
);
148 void HidConnection::SendFeatureReport(scoped_refptr
<net::IOBuffer
> buffer
,
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.";
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.";
164 if (IsReportIdProtected(report_id
)) {
165 HID_LOG(USER
) << "Attempt to set a protected feature report.";
170 PlatformSendFeatureReport(buffer
, size
, callback
);
173 bool HidConnection::CompleteRead(scoped_refptr
<net::IOBuffer
> buffer
,
175 const ReadCallback
& callback
) {
177 uint8_t report_id
= buffer
->data()[0];
178 if (IsReportIdProtected(report_id
)) {
179 HID_LOG(EVENT
) << "Filtered a protected input report.";
183 callback
.Run(true, buffer
, size
);
187 bool HidConnection::IsReportIdProtected(uint8_t report_id
) {
188 HidCollectionInfo collection_info
;
189 if (FindCollectionByReportId(device_info_
->collections(), report_id
,
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