| OLD | NEW |
| 1 // Copyright (c) 2014 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "device/hid/hid_connection.h" | 5 #include "device/hid/hid_connection.h" |
| 6 | 6 |
| 7 #include <algorithm> | |
| 8 | |
| 9 namespace device { | 7 namespace device { |
| 10 | 8 |
| 11 namespace { | |
| 12 | |
| 13 // Functor used to filter collections by report ID. | |
| 14 struct CollectionHasReportId { | |
| 15 explicit CollectionHasReportId(const uint8_t report_id) | |
| 16 : report_id_(report_id) {} | |
| 17 | |
| 18 bool operator()(const HidCollectionInfo& info) const { | |
| 19 if (info.report_ids.size() == 0 || | |
| 20 report_id_ == HidConnection::kNullReportId) | |
| 21 return false; | |
| 22 | |
| 23 if (report_id_ == HidConnection::kAnyReportId) | |
| 24 return true; | |
| 25 | |
| 26 return std::find(info.report_ids.begin(), | |
| 27 info.report_ids.end(), | |
| 28 report_id_) != info.report_ids.end(); | |
| 29 } | |
| 30 | |
| 31 private: | |
| 32 const uint8_t report_id_; | |
| 33 }; | |
| 34 | |
| 35 // Functor returning true if collection has a protected usage. | |
| 36 struct CollectionIsProtected { | |
| 37 bool operator()(const HidCollectionInfo& info) const { | |
| 38 return info.usage.IsProtected(); | |
| 39 } | |
| 40 }; | |
| 41 | |
| 42 bool FindCollectionByReportId(const HidDeviceInfo& device_info, | |
| 43 const uint8_t report_id, | |
| 44 HidCollectionInfo* collection_info) { | |
| 45 std::vector<HidCollectionInfo>::const_iterator collection_iter = | |
| 46 std::find_if(device_info.collections.begin(), | |
| 47 device_info.collections.end(), | |
| 48 CollectionHasReportId(report_id)); | |
| 49 if (collection_iter != device_info.collections.end()) { | |
| 50 if (collection_info) { | |
| 51 *collection_info = *collection_iter; | |
| 52 } | |
| 53 return true; | |
| 54 } | |
| 55 | |
| 56 return false; | |
| 57 } | |
| 58 | |
| 59 bool HasReportId(const HidDeviceInfo& device_info) { | |
| 60 return FindCollectionByReportId( | |
| 61 device_info, HidConnection::kAnyReportId, NULL); | |
| 62 } | |
| 63 | |
| 64 bool HasProtectedCollection(const HidDeviceInfo& device_info) { | |
| 65 return std::find_if(device_info.collections.begin(), | |
| 66 device_info.collections.end(), | |
| 67 CollectionIsProtected()) != device_info.collections.end(); | |
| 68 } | |
| 69 | |
| 70 } // namespace | |
| 71 | |
| 72 HidConnection::HidConnection(const HidDeviceInfo& device_info) | |
| 73 : device_info_(device_info) { | |
| 74 has_protected_collection_ = HasProtectedCollection(device_info); | |
| 75 has_report_id_ = HasReportId(device_info); | |
| 76 } | |
| 77 | |
| 78 HidConnection::~HidConnection() { | |
| 79 DCHECK(thread_checker_.CalledOnValidThread()); | |
| 80 } | |
| 81 | |
| 82 void HidConnection::Read(scoped_refptr<net::IOBufferWithSize> buffer, | |
| 83 const IOCallback& callback) { | |
| 84 DCHECK(thread_checker_.CalledOnValidThread()); | |
| 85 if (device_info_.max_input_report_size == 0) { | |
| 86 // The device does not support input reports. | |
| 87 callback.Run(false, 0); | |
| 88 return; | |
| 89 } | |
| 90 int expected_buffer_size = device_info_.max_input_report_size; | |
| 91 if (!has_report_id()) { | |
| 92 expected_buffer_size--; | |
| 93 } | |
| 94 if (buffer->size() < expected_buffer_size) { | |
| 95 // Receive buffer is too small. | |
| 96 callback.Run(false, 0); | |
| 97 return; | |
| 98 } | |
| 99 | |
| 100 PlatformRead(buffer, callback); | |
| 101 } | |
| 102 | |
| 103 void HidConnection::Write(uint8_t report_id, | |
| 104 scoped_refptr<net::IOBufferWithSize> buffer, | |
| 105 const IOCallback& callback) { | |
| 106 DCHECK(thread_checker_.CalledOnValidThread()); | |
| 107 if (device_info_.max_output_report_size == 0) { | |
| 108 // The device does not support output reports. | |
| 109 callback.Run(false, 0); | |
| 110 return; | |
| 111 } | |
| 112 if (IsReportIdProtected(report_id)) { | |
| 113 callback.Run(false, 0); | |
| 114 return; | |
| 115 } | |
| 116 | |
| 117 PlatformWrite(report_id, buffer, callback); | |
| 118 } | |
| 119 | |
| 120 void HidConnection::GetFeatureReport( | |
| 121 uint8_t report_id, | |
| 122 scoped_refptr<net::IOBufferWithSize> buffer, | |
| 123 const IOCallback& callback) { | |
| 124 DCHECK(thread_checker_.CalledOnValidThread()); | |
| 125 if (device_info_.max_feature_report_size == 0) { | |
| 126 // The device does not support feature reports. | |
| 127 callback.Run(false, 0); | |
| 128 return; | |
| 129 } | |
| 130 if (IsReportIdProtected(report_id)) { | |
| 131 callback.Run(false, 0); | |
| 132 return; | |
| 133 } | |
| 134 int expected_buffer_size = device_info_.max_feature_report_size; | |
| 135 if (!has_report_id()) { | |
| 136 expected_buffer_size--; | |
| 137 } | |
| 138 if (buffer->size() < expected_buffer_size) { | |
| 139 // Receive buffer is too small. | |
| 140 callback.Run(false, 0); | |
| 141 return; | |
| 142 } | |
| 143 | |
| 144 PlatformGetFeatureReport(report_id, buffer, callback); | |
| 145 } | |
| 146 | |
| 147 void HidConnection::SendFeatureReport( | |
| 148 uint8_t report_id, | |
| 149 scoped_refptr<net::IOBufferWithSize> buffer, | |
| 150 const IOCallback& callback) { | |
| 151 DCHECK(thread_checker_.CalledOnValidThread()); | |
| 152 if (device_info_.max_feature_report_size == 0) { | |
| 153 // The device does not support feature reports. | |
| 154 callback.Run(false, 0); | |
| 155 return; | |
| 156 } | |
| 157 if (IsReportIdProtected(report_id)) { | |
| 158 callback.Run(false, 0); | |
| 159 return; | |
| 160 } | |
| 161 | |
| 162 PlatformSendFeatureReport(report_id, buffer, callback); | |
| 163 } | |
| 164 | |
| 165 bool HidConnection::CompleteRead(scoped_refptr<net::IOBufferWithSize> buffer, | |
| 166 const IOCallback& callback) { | |
| 167 if (buffer->size() == 0 || IsReportIdProtected(buffer->data()[0])) { | |
| 168 return false; | |
| 169 } | |
| 170 | |
| 171 callback.Run(true, buffer->size()); | |
| 172 return true; | |
| 173 } | |
| 174 | |
| 175 bool HidConnection::IsReportIdProtected(const uint8_t report_id) { | |
| 176 HidCollectionInfo collection_info; | |
| 177 if (FindCollectionByReportId(device_info_, report_id, &collection_info)) { | |
| 178 return collection_info.usage.IsProtected(); | |
| 179 } | |
| 180 | |
| 181 return has_protected_collection(); | |
| 182 } | |
| 183 | |
| 184 PendingHidReport::PendingHidReport() {} | 9 PendingHidReport::PendingHidReport() {} |
| 185 | 10 |
| 186 PendingHidReport::~PendingHidReport() {} | 11 PendingHidReport::~PendingHidReport() {} |
| 187 | 12 |
| 188 PendingHidRead::PendingHidRead() {} | 13 PendingHidRead::PendingHidRead() {} |
| 189 | 14 |
| 190 PendingHidRead::~PendingHidRead() {} | 15 PendingHidRead::~PendingHidRead() {} |
| 191 | 16 |
| 17 HidConnection::HidConnection(const HidDeviceInfo& device_info) |
| 18 : device_info_(device_info) {} |
| 19 |
| 20 HidConnection::~HidConnection() {} |
| 21 |
| 192 } // namespace device | 22 } // namespace device |
| OLD | NEW |