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

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: Really fix tests for lack of testing hardware; adapt to ancient libudev in the cros distro Created 6 years, 10 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;
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) {
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(static_cast<int>(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 static_cast<DWORD>(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(
177 static_cast<int>(device_info_.output_report_size));
178 memset(expanded_buffer->data(), 0, device_info_.output_report_size);
179 memcpy(expanded_buffer->data() + 1,
180 buffer->data(),
181 size);
182 size++;
183 }
184
185 scoped_refptr<PendingTransfer> transfer(
186 new PendingTransfer(this, buffer, expanded_buffer, false, callback));
187 transfers_.insert(transfer);
188 transfer->TakeResultFromWindowsAPI(
189 WriteFile(file_.Get(),
190 device_info_.has_report_id ?
191 buffer->data() : expanded_buffer->data(),
192 static_cast<DWORD>(device_info_.output_report_size),
193 NULL,
194 transfer->GetOverlapped()));
195 }
196
197 void HidConnectionWin::GetFeatureReport(scoped_refptr<net::IOBuffer> buffer,
198 size_t size,
199 const IOCallback& callback) {
200 DCHECK(thread_checker_.CalledOnValidThread());
201 size_t report_size = device_info_.feature_report_size;
202 if (report_size == 0) {
203 // The device does not supoort input reports.
204 callback.Run(false, 0);
205 return;
206 }
207
208 if (size + !device_info_.has_report_id < report_size) {
209 // Buffer too short.
210 callback.Run(false, 0);
211 return;
212 }
213
214 scoped_refptr<net::IOBuffer> expanded_buffer;
215 if (!device_info_.has_report_id) {
216 ++size;
217 expanded_buffer = new net::IOBuffer(static_cast<int>(size));
218 }
219
220 scoped_refptr<PendingTransfer> transfer(
221 new PendingTransfer(this, buffer, expanded_buffer, true, callback));
222 transfers_.insert(transfer);
223 transfer->TakeResultFromWindowsAPI(
224 DeviceIoControl(file_.Get(),
225 IOCTL_HID_GET_FEATURE,
226 NULL,
227 0,
228 device_info_.has_report_id ?
229 buffer->data() :
230 expanded_buffer->data(),
231 static_cast<DWORD>(size),
232 NULL,
233 transfer->GetOverlapped()));
234 }
235
236 void HidConnectionWin::SendFeatureReport(scoped_refptr<net::IOBuffer> buffer,
237 size_t size,
238 const IOCallback& callback) {
239 DCHECK(thread_checker_.CalledOnValidThread());
240 size_t report_size = device_info_.feature_report_size;
241 if (report_size == 0) {
242 // The device does not supoort output reports.
243 callback.Run(false, 0);
244 return;
245 }
246
247 if (size + !device_info_.has_report_id > report_size) {
248 // Size of report too long.
249 callback.Run(false, 0);
250 return;
251 }
252
253 scoped_refptr<net::IOBuffer> expanded_buffer;
254 if (!device_info_.has_report_id) {
255 expanded_buffer = new net::IOBuffer(
256 static_cast<int>(device_info_.feature_report_size));
257 memset(expanded_buffer->data(), 0, device_info_.feature_report_size);
258 memcpy(expanded_buffer->data() + 1,
259 buffer->data(),
260 size);
261 size++;
262 }
263
264 scoped_refptr<PendingTransfer> transfer(
265 new PendingTransfer(this, buffer, expanded_buffer, false, callback));
266 transfer->TakeResultFromWindowsAPI(
267 DeviceIoControl(file_.Get(),
268 IOCTL_HID_SET_FEATURE,
269 device_info_.has_report_id ?
270 buffer->data() :
271 expanded_buffer->data(),
272 static_cast<DWORD>(device_info_.output_report_size),
273 NULL,
274 0,
275 NULL,
276 transfer->GetOverlapped()));
277 }
278
279 } // namespace device
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698