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

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

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

Powered by Google App Engine
This is Rietveld 408576698