Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(33)

Side by Side Diff: device/hid/hid_connection_win.cc

Issue 317783010: chrome.hid: enrich model with report IDs (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Enrich JavaScript model (no incoming report filter) Created 6 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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_win.h" 5 #include "device/hid/hid_connection_win.h"
6 6
7 #include <cstring> 7 #include <cstring>
8 8
9 #include "base/files/file.h" 9 #include "base/files/file.h"
10 #include "base/message_loop/message_loop.h" 10 #include "base/message_loop/message_loop.h"
11 #include "base/stl_util.h" 11 #include "base/stl_util.h"
12 #include "base/threading/thread_restrictions.h" 12 #include "base/threading/thread_restrictions.h"
13 #include "base/win/object_watcher.h" 13 #include "base/win/object_watcher.h"
14 #include "base/win/scoped_handle.h" 14 #include "base/win/scoped_handle.h"
15 #include "device/hid/hid_service.h" 15 #include "device/hid/hid_service.h"
16 #include "device/hid/hid_service_win.h" 16 #include "device/hid/hid_service_win.h"
17 17
18 #define INITGUID 18 #define INITGUID
19 19
20 #include <windows.h> 20 #include <windows.h>
21 #include <hidclass.h> 21 #include <hidclass.h>
22 22
23 extern "C" { 23 extern "C" {
24 #include <hidsdi.h> 24 #include <hidsdi.h>
25 } 25 }
26 26
27 #include <setupapi.h> 27 #include <setupapi.h>
28 #include <winioctl.h> 28 #include <winioctl.h>
29 29
30 #include <algorithm>
31
30 namespace device { 32 namespace device {
31 33
34 namespace {
35
36 struct CollectionHasReportId {
37 bool operator()(const HidCollectionInfo& info) const {
38 return info.report_ids.size() > 0;
39 }
40 };
41
42 bool DeviceHasReportId(const HidDeviceInfo& device_info) {
Ken Rockot(use gerrit already) 2014/06/06 20:04:43 Very nice.
jracle (use Gerrit) 2014/06/07 12:56:21 Thx. Wish I could use lambdas and C++11 though. So
43 return std::find_if(device_info.collections.begin(),
44 device_info.collections.end(),
45 CollectionHasReportId()) != device_info.collections.end();
46 }
47
48 } // namespace
49
32 struct PendingHidTransfer : public base::RefCounted<PendingHidTransfer>, 50 struct PendingHidTransfer : public base::RefCounted<PendingHidTransfer>,
33 public base::win::ObjectWatcher::Delegate, 51 public base::win::ObjectWatcher::Delegate,
34 public base::MessageLoop::DestructionObserver { 52 public base::MessageLoop::DestructionObserver {
35 PendingHidTransfer(scoped_refptr<HidConnectionWin> connection, 53 PendingHidTransfer(scoped_refptr<HidConnectionWin> connection,
36 scoped_refptr<net::IOBufferWithSize> target_buffer, 54 scoped_refptr<net::IOBufferWithSize> target_buffer,
37 scoped_refptr<net::IOBufferWithSize> receive_buffer, 55 scoped_refptr<net::IOBufferWithSize> receive_buffer,
38 HidConnection::IOCallback callback); 56 HidConnection::IOCallback callback);
39 57
40 void TakeResultFromWindowsAPI(BOOL result); 58 void TakeResultFromWindowsAPI(BOOL result);
41 59
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after
129 } 147 }
130 148
131 HidConnectionWin::~HidConnectionWin() { 149 HidConnectionWin::~HidConnectionWin() {
132 DCHECK(thread_checker_.CalledOnValidThread()); 150 DCHECK(thread_checker_.CalledOnValidThread());
133 CancelIo(file_.Get()); 151 CancelIo(file_.Get());
134 } 152 }
135 153
136 void HidConnectionWin::Read(scoped_refptr<net::IOBufferWithSize> buffer, 154 void HidConnectionWin::Read(scoped_refptr<net::IOBufferWithSize> buffer,
137 const HidConnection::IOCallback& callback) { 155 const HidConnection::IOCallback& callback) {
138 DCHECK(thread_checker_.CalledOnValidThread()); 156 DCHECK(thread_checker_.CalledOnValidThread());
139 if (device_info().input_report_size == 0) { 157 if (device_info().max_input_report_size == 0) {
140 // The device does not support input reports. 158 // The device does not support input reports.
141 callback.Run(false, 0); 159 callback.Run(false, 0);
142 return; 160 return;
143 } 161 }
144 162
145 // This fairly awkward logic is correct: If Windows does not expect a device 163 // This fairly awkward logic is correct: If Windows does not expect a device
146 // to supply a report ID in its input reports, it requires the buffer to be 164 // to supply a report ID in its input reports, it requires the buffer to be
147 // 1 byte larger than what the device actually sends. 165 // 1 byte larger than what the device actually sends.
148 int receive_buffer_size = device_info().input_report_size; 166 int receive_buffer_size = device_info().max_input_report_size;
149 int expected_buffer_size = receive_buffer_size; 167 int expected_buffer_size = receive_buffer_size;
150 if (!device_info().has_report_id) 168 if (!DeviceHasReportId(device_info()))
151 expected_buffer_size -= 1; 169 expected_buffer_size -= 1;
Ken Rockot(use gerrit already) 2014/06/06 20:04:43 It's this adjust-by-1 logic which exists throughou
jracle (use Gerrit) 2014/06/07 12:56:21 I totally follow you on that point, and will valid
jracle (use Gerrit) 2014/06/10 14:07:40 Hi Ken, today I've ben given a special firmwar
152 170
153 if (buffer->size() < expected_buffer_size) { 171 if (buffer->size() < expected_buffer_size) {
154 callback.Run(false, 0); 172 callback.Run(false, 0);
155 return; 173 return;
156 } 174 }
157 175
158 scoped_refptr<net::IOBufferWithSize> receive_buffer(buffer); 176 scoped_refptr<net::IOBufferWithSize> receive_buffer(buffer);
159 if (receive_buffer_size != expected_buffer_size) 177 if (receive_buffer_size != expected_buffer_size)
160 receive_buffer = new net::IOBufferWithSize(receive_buffer_size); 178 receive_buffer = new net::IOBufferWithSize(receive_buffer_size);
161 scoped_refptr<PendingHidTransfer> transfer( 179 scoped_refptr<PendingHidTransfer> transfer(
162 new PendingHidTransfer(this, buffer, receive_buffer, callback)); 180 new PendingHidTransfer(this, buffer, receive_buffer, callback));
163 transfers_.insert(transfer); 181 transfers_.insert(transfer);
164 transfer->TakeResultFromWindowsAPI( 182 transfer->TakeResultFromWindowsAPI(
165 ReadFile(file_.Get(), 183 ReadFile(file_.Get(),
166 receive_buffer->data(), 184 receive_buffer->data(),
167 static_cast<DWORD>(receive_buffer->size()), 185 static_cast<DWORD>(receive_buffer->size()),
168 NULL, 186 NULL,
169 transfer->GetOverlapped())); 187 transfer->GetOverlapped()));
170 } 188 }
171 189
172 void HidConnectionWin::Write(uint8_t report_id, 190 void HidConnectionWin::Write(uint8_t report_id,
173 scoped_refptr<net::IOBufferWithSize> buffer, 191 scoped_refptr<net::IOBufferWithSize> buffer,
174 const HidConnection::IOCallback& callback) { 192 const HidConnection::IOCallback& callback) {
175 DCHECK(thread_checker_.CalledOnValidThread()); 193 DCHECK(thread_checker_.CalledOnValidThread());
176 if (device_info().output_report_size == 0) { 194 if (device_info().max_output_report_size == 0) {
177 // The device does not support output reports. 195 // The device does not support output reports.
178 callback.Run(false, 0); 196 callback.Run(false, 0);
179 return; 197 return;
180 } 198 }
181 199
182 // The Windows API always wants either a report ID (if supported) or 200 // The Windows API always wants either a report ID (if supported) or
183 // zero at the front of every output report. 201 // zero at the front of every output report.
184 scoped_refptr<net::IOBufferWithSize> output_buffer(buffer); 202 scoped_refptr<net::IOBufferWithSize> output_buffer(buffer);
185 output_buffer = new net::IOBufferWithSize(buffer->size() + 1); 203 output_buffer = new net::IOBufferWithSize(buffer->size() + 1);
186 output_buffer->data()[0] = report_id; 204 output_buffer->data()[0] = report_id;
187 memcpy(output_buffer->data() + 1, buffer->data(), buffer->size()); 205 memcpy(output_buffer->data() + 1, buffer->data(), buffer->size());
188 206
189 scoped_refptr<PendingHidTransfer> transfer( 207 scoped_refptr<PendingHidTransfer> transfer(
190 new PendingHidTransfer(this, output_buffer, NULL, callback)); 208 new PendingHidTransfer(this, output_buffer, NULL, callback));
191 transfers_.insert(transfer); 209 transfers_.insert(transfer);
192 transfer->TakeResultFromWindowsAPI( 210 transfer->TakeResultFromWindowsAPI(
193 WriteFile(file_.Get(), 211 WriteFile(file_.Get(),
194 output_buffer->data(), 212 output_buffer->data(),
195 static_cast<DWORD>(output_buffer->size()), 213 static_cast<DWORD>(output_buffer->size()),
196 NULL, 214 NULL,
197 transfer->GetOverlapped())); 215 transfer->GetOverlapped()));
198 } 216 }
199 217
200 void HidConnectionWin::GetFeatureReport( 218 void HidConnectionWin::GetFeatureReport(
201 uint8_t report_id, 219 uint8_t report_id,
202 scoped_refptr<net::IOBufferWithSize> buffer, 220 scoped_refptr<net::IOBufferWithSize> buffer,
203 const IOCallback& callback) { 221 const IOCallback& callback) {
204 DCHECK(thread_checker_.CalledOnValidThread()); 222 DCHECK(thread_checker_.CalledOnValidThread());
205 if (device_info().feature_report_size == 0) { 223 if (device_info().max_feature_report_size == 0) {
206 // The device does not support feature reports. 224 // The device does not support feature reports.
207 callback.Run(false, 0); 225 callback.Run(false, 0);
208 return; 226 return;
209 } 227 }
210 228
211 int receive_buffer_size = device_info().feature_report_size; 229 int receive_buffer_size = device_info().max_feature_report_size;
212 int expected_buffer_size = receive_buffer_size; 230 int expected_buffer_size = receive_buffer_size;
213 if (!device_info().has_report_id) 231 if (!DeviceHasReportId(device_info()))
214 expected_buffer_size -= 1; 232 expected_buffer_size -= 1;
215 if (buffer->size() < expected_buffer_size) { 233 if (buffer->size() < expected_buffer_size) {
216 callback.Run(false, 0); 234 callback.Run(false, 0);
217 return; 235 return;
218 } 236 }
219 237
220 scoped_refptr<net::IOBufferWithSize> receive_buffer(buffer); 238 scoped_refptr<net::IOBufferWithSize> receive_buffer(buffer);
221 if (receive_buffer_size != expected_buffer_size) 239 if (receive_buffer_size != expected_buffer_size)
222 receive_buffer = new net::IOBufferWithSize(receive_buffer_size); 240 receive_buffer = new net::IOBufferWithSize(receive_buffer_size);
223 241
(...skipping 11 matching lines...) Expand all
235 static_cast<DWORD>(receive_buffer->size()), 253 static_cast<DWORD>(receive_buffer->size()),
236 NULL, 254 NULL,
237 transfer->GetOverlapped())); 255 transfer->GetOverlapped()));
238 } 256 }
239 257
240 void HidConnectionWin::SendFeatureReport( 258 void HidConnectionWin::SendFeatureReport(
241 uint8_t report_id, 259 uint8_t report_id,
242 scoped_refptr<net::IOBufferWithSize> buffer, 260 scoped_refptr<net::IOBufferWithSize> buffer,
243 const IOCallback& callback) { 261 const IOCallback& callback) {
244 DCHECK(thread_checker_.CalledOnValidThread()); 262 DCHECK(thread_checker_.CalledOnValidThread());
245 if (device_info().feature_report_size == 0) { 263 if (device_info().max_feature_report_size == 0) {
246 // The device does not support feature reports. 264 // The device does not support feature reports.
247 callback.Run(false, 0); 265 callback.Run(false, 0);
248 return; 266 return;
249 } 267 }
250 268
251 // The Windows API always wants either a report ID (if supported) or 269 // The Windows API always wants either a report ID (if supported) or
252 // zero at the front of every output report. 270 // zero at the front of every output report.
253 scoped_refptr<net::IOBufferWithSize> output_buffer(buffer); 271 scoped_refptr<net::IOBufferWithSize> output_buffer(buffer);
254 output_buffer = new net::IOBufferWithSize(buffer->size() + 1); 272 output_buffer = new net::IOBufferWithSize(buffer->size() + 1);
255 output_buffer->data()[0] = report_id; 273 output_buffer->data()[0] = report_id;
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
294 } 312 }
295 } 313 }
296 314
297 void HidConnectionWin::OnTransferCanceled( 315 void HidConnectionWin::OnTransferCanceled(
298 scoped_refptr<PendingHidTransfer> transfer) { 316 scoped_refptr<PendingHidTransfer> transfer) {
299 transfers_.erase(transfer); 317 transfers_.erase(transfer);
300 transfer->callback_.Run(false, 0); 318 transfer->callback_.Run(false, 0);
301 } 319 }
302 320
303 } // namespace device 321 } // namespace device
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698