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

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

Issue 143883005: HID backend (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@hid-impl-base
Patch Set: Bug fixes Created 6 years, 11 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
(Empty)
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.
4
5 #include "device/hid/hid_connection_win.h"
6
7 #include <cstring>
8
9 #include "base/message_loop/message_loop.h"
10 #include "base/stl_util.h"
11 #include "base/threading/thread_restrictions.h"
12 #include "device/hid/hid_service.h"
13 #include "device/hid/hid_service_win.h"
14 #include "net/base/io_buffer.h"
15
16 #if defined(OS_WIN)
17
18 #define INITGUID
19
20 #include <windows.h>
21 #include <hidclass.h>
22
23 extern "C" {
24
25 #include <hidsdi.h>
26
27 }
28
29 #include <setupapi.h>
30 #include <winioctl.h>
31 #include "base/win/scoped_handle.h"
32
33 #endif // defined(OS_WIN)
34
35 namespace device {
36
37 HidConnectionWin::PendingTransfer::PendingTransfer(
38 scoped_refptr<HidConnectionWin> conn,
39 scoped_refptr<net::IOBuffer> target,
40 scoped_refptr<net::IOBuffer> receiving,
41 bool is_input,
42 IOCallback callback)
43 : conn_(conn),
44 is_input_(is_input),
45 target_(target),
46 receiving_(receiving),
47 callback_(callback),
48 event_(CreateEvent(NULL, FALSE, FALSE, NULL)) {
49 memset(&overlapped_, 0, sizeof(OVERLAPPED));
50 overlapped_.hEvent = event_.Get();
51 }
52 HidConnectionWin::PendingTransfer::~PendingTransfer() {
53 base::MessageLoop::current()->RemoveDestructionObserver(this);
54 }
55
56 void HidConnectionWin::PendingTransfer::TakeResultFromWindowsAPI(BOOL result) {
57 if (result || GetLastError() != ERROR_IO_PENDING) {
58 conn_->OnTransferFinished(this);
59 } else {
60 base::MessageLoop::current()->AddDestructionObserver(this);
61 AddRef();
62 watcher_.StartWatching(event_.Get(), this);
63 }
64 }
65
66 void HidConnectionWin::PendingTransfer::OnObjectSignaled(HANDLE event_handle) {
67 conn_->OnTransferFinished(this);
68 Release();
69 }
70
71 void HidConnectionWin::PendingTransfer::WillDestroyCurrentMessageLoop() {
72 watcher_.StopWatching();
73 conn_->OnTransferCanceled(this);
74 }
75
76 void HidConnectionWin::OnTransferFinished(
77 scoped_refptr<PendingTransfer> transfer) {
78 DWORD bytes_transfered;
miket_OOO 2014/02/03 18:42:19 I think the preferred spelling has a double-r, not
79 transfers_.erase(transfer);
80 if (GetOverlappedResult(file_,
81 transfer->GetOverlapped(),
82 &bytes_transfered,
83 FALSE)) {
84 if (transfer->is_input_ && !device_info_.has_report_id) {
85 // Move one byte forward.
86 --bytes_transfered;
87 memcpy(transfer->target_->data(),
88 transfer->receiving_->data() + 1,
89 bytes_transfered);
90 }
91 transfer->callback_.Run(true, bytes_transfered);
92 } else {
93 transfer->callback_.Run(false, 0);
94 }
95 }
96
97 void HidConnectionWin::OnTransferCanceled(
98 scoped_refptr<PendingTransfer> transfer) {
99 transfers_.erase(transfer);
100 transfer->callback_.Run(false, 0);
101 }
102
103 HidConnectionWin::HidConnectionWin(HidDeviceInfo device_info)
104 : HidConnection(device_info),
105 available_(false) {
106 DCHECK(thread_checker_.CalledOnValidThread());
107 file_.Set(CreateFileA(device_info.device_id.c_str(),
108 GENERIC_WRITE | GENERIC_READ,
109 FILE_SHARE_READ | FILE_SHARE_WRITE,
110 NULL,
111 OPEN_EXISTING,
112 FILE_FLAG_OVERLAPPED,
113 NULL));
114 available_ = file_.IsValid();
115 }
116
117 HidConnectionWin::~HidConnectionWin() {
118 DCHECK(thread_checker_.CalledOnValidThread());
119 CancelIo(file_.Get());
120 }
121
122 void HidConnectionWin::Read(scoped_refptr<net::IOBuffer> buffer,
123 size_t size,
124 const HidConnection::IOCallback& callback) {
125 DCHECK(thread_checker_.CalledOnValidThread());
126 size_t report_size = device_info_.input_report_size;
127 if (report_size == 0) {
128 // The device does not supoort input reports.
129 callback.Run(false, 0);
130 return;
131 }
132
133 if (size + !device_info_.has_report_id < report_size) {
miket_OOO 2014/02/03 18:42:19 that is weird logic (boolean cast to int)
134 // Buffer too short.
135 callback.Run(false, 0);
136 return;
137 }
138
139 scoped_refptr<net::IOBuffer> expanded_buffer;
140 if (!device_info_.has_report_id) {
141 ++size;
142 expanded_buffer = new net::IOBuffer(size);
143 }
144
145 scoped_refptr<PendingTransfer> transfer(
146 new PendingTransfer(this, buffer, expanded_buffer, true, callback));
147 transfers_.insert(transfer);
148 transfer->TakeResultFromWindowsAPI(ReadFile(file_.Get(),
149 device_info_.has_report_id ?
150 buffer->data() :
151 expanded_buffer->data(),
152 size,
153 NULL,
154 transfer->GetOverlapped()));
155 }
156
157 void HidConnectionWin::Write(scoped_refptr<net::IOBuffer> buffer,
158 size_t size,
159 const HidConnection::IOCallback& callback) {
160 DCHECK(thread_checker_.CalledOnValidThread());
161 size_t report_size = device_info_.output_report_size;
162 if (report_size == 0) {
163 // The device does not supoort output reports.
164 callback.Run(false, 0);
165 return;
166 }
167
168 if (size + !device_info_.has_report_id > report_size) {
169 // Size of report too long.
170 callback.Run(false, 0);
171 return;
172 }
173
174 scoped_refptr<net::IOBuffer> expanded_buffer;
175 if (!device_info_.has_report_id) {
176 expanded_buffer = new net::IOBuffer(device_info_.output_report_size);
177 memset(expanded_buffer->data(), 0, device_info_.output_report_size);
178 memcpy(expanded_buffer->data() + 1,
179 buffer->data(),
180 size);
181 size++;
182 }
183
184 scoped_refptr<PendingTransfer> transfer(
185 new PendingTransfer(this, buffer, expanded_buffer, false, callback));
186 transfers_.insert(transfer);
187 transfer->TakeResultFromWindowsAPI(WriteFile(file_.Get(),
188 device_info_.has_report_id ?
189 buffer->data() :
190 expanded_buffer->data(),
191 device_info_.output_report_size,
192 NULL,
193 transfer->GetOverlapped()));
194 }
195
196 void HidConnectionWin::GetFeatureReport(scoped_refptr<net::IOBuffer> buffer,
197 size_t size,
198 const IOCallback& callback) {
199 DCHECK(thread_checker_.CalledOnValidThread());
200 size_t report_size = device_info_.feature_report_size;
201 if (report_size == 0) {
202 // The device does not supoort input reports.
203 callback.Run(false, 0);
204 return;
205 }
206
207 if (size + !device_info_.has_report_id < report_size) {
208 // Buffer too short.
209 callback.Run(false, 0);
210 return;
211 }
212
213 scoped_refptr<net::IOBuffer> expanded_buffer;
214 if (!device_info_.has_report_id) {
215 ++size;
216 expanded_buffer = new net::IOBuffer(size);
217 }
218
219 scoped_refptr<PendingTransfer> transfer(
220 new PendingTransfer(this, buffer, expanded_buffer, true, callback));
221 transfers_.insert(transfer);
222 transfer->TakeResultFromWindowsAPI(
223 DeviceIoControl(file_.Get(),
224 IOCTL_HID_GET_FEATURE,
225 NULL,
226 0,
227 device_info_.has_report_id ?
228 buffer->data() :
229 expanded_buffer->data(),
230 size,
231 NULL,
232 transfer->GetOverlapped()));
233 }
234
235 void HidConnectionWin::SendFeatureReport(scoped_refptr<net::IOBuffer> buffer,
236 size_t size,
237 const IOCallback& callback) {
238 DCHECK(thread_checker_.CalledOnValidThread());
239 size_t report_size = device_info_.feature_report_size;
240 if (report_size == 0) {
241 // The device does not supoort output reports.
242 callback.Run(false, 0);
243 return;
244 }
245
246 if (size + !device_info_.has_report_id > report_size) {
247 // Size of report too long.
248 callback.Run(false, 0);
249 return;
250 }
251
252 scoped_refptr<net::IOBuffer> expanded_buffer;
253 if (!device_info_.has_report_id) {
254 expanded_buffer = new net::IOBuffer(device_info_.feature_report_size);
255 memset(expanded_buffer->data(), 0, device_info_.feature_report_size);
256 memcpy(expanded_buffer->data() + 1,
257 buffer->data(),
258 size);
259 size++;
260 }
261
262 scoped_refptr<PendingTransfer> transfer(
263 new PendingTransfer(this, buffer, expanded_buffer, false, callback));
264 transfer->TakeResultFromWindowsAPI(
265 DeviceIoControl(file_.Get(),
266 IOCTL_HID_SET_FEATURE,
267 device_info_.has_report_id ?
268 buffer->data() :
269 expanded_buffer->data(),
270 device_info_.output_report_size,
271 NULL,
272 0,
273 NULL,
274 transfer->GetOverlapped()));
275 }
276
277 } // namespace device
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698