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

Side by Side Diff: device/devices_app/usb/device_impl.cc

Issue 1682363002: Remove //device/devices_app. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Remove two files that somehow survived in //device/devices_app. Created 4 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
« no previous file with comments | « device/devices_app/usb/device_impl.h ('k') | device/devices_app/usb/device_impl_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright 2015 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/devices_app/usb/device_impl.h"
6
7 #include <stddef.h>
8
9 #include <algorithm>
10 #include <numeric>
11 #include <utility>
12 #include <vector>
13
14 #include "base/bind.h"
15 #include "base/callback.h"
16 #include "base/stl_util.h"
17 #include "device/devices_app/usb/type_converters.h"
18 #include "device/usb/usb_descriptors.h"
19 #include "device/usb/usb_device.h"
20 #include "net/base/io_buffer.h"
21
22 namespace device {
23 namespace usb {
24
25 namespace {
26
27 using MojoTransferInCallback =
28 mojo::Callback<void(TransferStatus, mojo::Array<uint8_t>)>;
29
30 using MojoTransferOutCallback = mojo::Callback<void(TransferStatus)>;
31
32 template <typename... Args>
33 void CallMojoCallback(scoped_ptr<mojo::Callback<void(Args...)>> callback,
34 Args... args) {
35 callback->Run(args...);
36 }
37
38 // Generic wrapper to convert a Mojo callback to something we can rebind and
39 // pass around. This is only usable for callbacks with no move-only arguments.
40 template <typename... Args>
41 base::Callback<void(Args...)> WrapMojoCallback(
42 const mojo::Callback<void(Args...)>& callback) {
43 // mojo::Callback is not thread safe. By wrapping |callback| in a scoped_ptr
44 // we guarantee that it will be freed when CallMojoCallback is run and not
45 // retained until the base::Callback is destroyed, which could happen on any
46 // thread. This pattern is also used below in places where this generic
47 // wrapper is not used.
48 auto callback_ptr =
49 make_scoped_ptr(new mojo::Callback<void(Args...)>(callback));
50 return base::Bind(&CallMojoCallback<Args...>, base::Passed(&callback_ptr));
51 }
52
53 void OnPermissionCheckComplete(
54 const base::Callback<void(bool)>& callback,
55 const base::Callback<void(const base::Callback<void(bool)>&)>& action,
56 bool allowed) {
57 if (allowed)
58 action.Run(callback);
59 else
60 callback.Run(false);
61 }
62
63 scoped_refptr<net::IOBuffer> CreateTransferBuffer(size_t size) {
64 scoped_refptr<net::IOBuffer> buffer = new net::IOBuffer(
65 std::max(static_cast<size_t>(1u), static_cast<size_t>(size)));
66 return buffer;
67 }
68
69 void OnTransferIn(scoped_ptr<MojoTransferInCallback> callback,
70 UsbTransferStatus status,
71 scoped_refptr<net::IOBuffer> buffer,
72 size_t buffer_size) {
73 mojo::Array<uint8_t> data;
74 if (buffer) {
75 // TODO(rockot/reillyg): We should change UsbDeviceHandle to use a
76 // std::vector<uint8_t> instead of net::IOBuffer. Then we could move
77 // instead of copy.
78 std::vector<uint8_t> bytes(buffer_size);
79 std::copy(buffer->data(), buffer->data() + buffer_size, bytes.begin());
80 data.Swap(&bytes);
81 }
82 callback->Run(mojo::ConvertTo<TransferStatus>(status), std::move(data));
83 }
84
85 void OnControlTransferInPermissionCheckComplete(
86 scoped_refptr<UsbDeviceHandle> device_handle,
87 ControlTransferParamsPtr params,
88 int length,
89 int timeout,
90 scoped_ptr<Device::ControlTransferInCallback> callback,
91 bool allowed) {
92 if (allowed) {
93 scoped_refptr<net::IOBuffer> buffer = CreateTransferBuffer(length);
94 device_handle->ControlTransfer(
95 USB_DIRECTION_INBOUND,
96 mojo::ConvertTo<UsbDeviceHandle::TransferRequestType>(params->type),
97 mojo::ConvertTo<UsbDeviceHandle::TransferRecipient>(params->recipient),
98 params->request, params->value, params->index, buffer, length, timeout,
99 base::Bind(&OnTransferIn, base::Passed(&callback)));
100 } else {
101 mojo::Array<uint8_t> data;
102 callback->Run(TransferStatus::PERMISSION_DENIED, std::move(data));
103 }
104 }
105
106 void OnTransferOut(scoped_ptr<MojoTransferOutCallback> callback,
107 UsbTransferStatus status,
108 scoped_refptr<net::IOBuffer> buffer,
109 size_t buffer_size) {
110 callback->Run(mojo::ConvertTo<TransferStatus>(status));
111 }
112
113 void OnControlTransferOutPermissionCheckComplete(
114 scoped_refptr<UsbDeviceHandle> device_handle,
115 ControlTransferParamsPtr params,
116 mojo::Array<uint8_t> data,
117 int timeout,
118 scoped_ptr<Device::ControlTransferOutCallback> callback,
119 bool allowed) {
120 if (allowed) {
121 scoped_refptr<net::IOBuffer> buffer = CreateTransferBuffer(data.size());
122 const std::vector<uint8_t>& storage = data.storage();
123 std::copy(storage.begin(), storage.end(), buffer->data());
124 device_handle->ControlTransfer(
125 USB_DIRECTION_OUTBOUND,
126 mojo::ConvertTo<UsbDeviceHandle::TransferRequestType>(params->type),
127 mojo::ConvertTo<UsbDeviceHandle::TransferRecipient>(params->recipient),
128 params->request, params->value, params->index, buffer, data.size(),
129 timeout, base::Bind(&OnTransferOut, base::Passed(&callback)));
130 } else {
131 callback->Run(TransferStatus::PERMISSION_DENIED);
132 }
133 }
134
135 mojo::Array<IsochronousPacketPtr> BuildIsochronousPacketArray(
136 mojo::Array<uint32_t> packet_lengths,
137 TransferStatus status) {
138 mojo::Array<IsochronousPacketPtr> packets(packet_lengths.size());
139 for (size_t i = 0; i < packet_lengths.size(); ++i) {
140 packets[i] = IsochronousPacket::New();
141 packets[i]->length = packet_lengths[i];
142 packets[i]->status = status;
143 }
144 return packets;
145 }
146
147 void OnIsochronousTransferIn(
148 scoped_ptr<Device::IsochronousTransferInCallback> callback,
149 scoped_refptr<net::IOBuffer> buffer,
150 const std::vector<UsbDeviceHandle::IsochronousPacket>& packets) {
151 mojo::Array<uint8_t> data;
152 if (buffer) {
153 // TODO(rockot/reillyg): We should change UsbDeviceHandle to use a
154 // std::vector<uint8_t> instead of net::IOBuffer. Then we could move
155 // instead of copy.
156 uint32_t buffer_size =
157 std::accumulate(packets.begin(), packets.end(), 0u,
158 [](const uint32_t& a,
159 const UsbDeviceHandle::IsochronousPacket& packet) {
160 return a + packet.length;
161 });
162 std::vector<uint8_t> bytes(buffer_size);
163 std::copy(buffer->data(), buffer->data() + buffer_size, bytes.begin());
164 data.Swap(&bytes);
165 }
166 callback->Run(std::move(data),
167 mojo::Array<IsochronousPacketPtr>::From(packets));
168 }
169
170 void OnIsochronousTransferOut(
171 scoped_ptr<Device::IsochronousTransferOutCallback> callback,
172 scoped_refptr<net::IOBuffer> buffer,
173 const std::vector<UsbDeviceHandle::IsochronousPacket>& packets) {
174 callback->Run(mojo::Array<IsochronousPacketPtr>::From(packets));
175 }
176
177 } // namespace
178
179 DeviceImpl::DeviceImpl(scoped_refptr<UsbDevice> device,
180 PermissionProviderPtr permission_provider,
181 mojo::InterfaceRequest<Device> request)
182 : binding_(this, std::move(request)),
183 device_(device),
184 permission_provider_(std::move(permission_provider)),
185 weak_factory_(this) {
186 // This object owns itself and will be destroyed if either the message pipe
187 // it is bound to is closed or the PermissionProvider it depends on is
188 // unavailable.
189 binding_.set_connection_error_handler([this]() { delete this; });
190 permission_provider_.set_connection_error_handler([this]() { delete this; });
191 }
192
193 DeviceImpl::~DeviceImpl() {
194 CloseHandle();
195 }
196
197 void DeviceImpl::CloseHandle() {
198 if (device_handle_)
199 device_handle_->Close();
200 device_handle_ = nullptr;
201 }
202
203 void DeviceImpl::HasControlTransferPermission(
204 ControlTransferRecipient recipient,
205 uint16_t index,
206 const base::Callback<void(bool)>& callback) {
207 DCHECK(device_handle_);
208 const UsbConfigDescriptor* config = device_->GetActiveConfiguration();
209
210 if (recipient == ControlTransferRecipient::INTERFACE ||
211 recipient == ControlTransferRecipient::ENDPOINT) {
212 if (!config) {
213 callback.Run(false);
214 return;
215 }
216
217 uint8_t interface_number = index & 0xff;
218 if (recipient == ControlTransferRecipient::ENDPOINT) {
219 if (!device_handle_->FindInterfaceByEndpoint(index & 0xff,
220 &interface_number)) {
221 callback.Run(false);
222 return;
223 }
224 }
225
226 permission_provider_->HasInterfacePermission(
227 interface_number, config->configuration_value,
228 DeviceInfo::From(*device_), callback);
229 } else if (config) {
230 permission_provider_->HasConfigurationPermission(
231 config->configuration_value, DeviceInfo::From(*device_), callback);
232 } else {
233 // Client must already have device permission to have gotten this far.
234 callback.Run(true);
235 }
236 }
237
238 void DeviceImpl::OnOpen(const OpenCallback& callback,
239 scoped_refptr<UsbDeviceHandle> handle) {
240 device_handle_ = handle;
241 callback.Run(handle ? OpenDeviceError::OK : OpenDeviceError::ACCESS_DENIED);
242 }
243
244 void DeviceImpl::GetDeviceInfo(const GetDeviceInfoCallback& callback) {
245 callback.Run(DeviceInfo::From(*device_));
246 }
247
248 void DeviceImpl::GetConfiguration(const GetConfigurationCallback& callback) {
249 const UsbConfigDescriptor* config = device_->GetActiveConfiguration();
250 callback.Run(config ? config->configuration_value : 0);
251 }
252
253 void DeviceImpl::Open(const OpenCallback& callback) {
254 device_->Open(
255 base::Bind(&DeviceImpl::OnOpen, weak_factory_.GetWeakPtr(), callback));
256 }
257
258 void DeviceImpl::Close(const CloseCallback& callback) {
259 CloseHandle();
260 callback.Run();
261 }
262
263 void DeviceImpl::SetConfiguration(uint8_t value,
264 const SetConfigurationCallback& callback) {
265 if (!device_handle_) {
266 callback.Run(false);
267 return;
268 }
269
270 auto set_configuration =
271 base::Bind(&UsbDeviceHandle::SetConfiguration, device_handle_, value);
272 permission_provider_->HasConfigurationPermission(
273 value, DeviceInfo::From(*device_),
274 base::Bind(&OnPermissionCheckComplete, WrapMojoCallback(callback),
275 set_configuration));
276 }
277
278 void DeviceImpl::ClaimInterface(uint8_t interface_number,
279 const ClaimInterfaceCallback& callback) {
280 if (!device_handle_) {
281 callback.Run(false);
282 return;
283 }
284
285 const UsbConfigDescriptor* config = device_->GetActiveConfiguration();
286 if (!config) {
287 callback.Run(false);
288 return;
289 }
290
291 auto claim_interface = base::Bind(&UsbDeviceHandle::ClaimInterface,
292 device_handle_, interface_number);
293 permission_provider_->HasInterfacePermission(
294 interface_number, config->configuration_value, DeviceInfo::From(*device_),
295 base::Bind(&OnPermissionCheckComplete, WrapMojoCallback(callback),
296 claim_interface));
297 }
298
299 void DeviceImpl::ReleaseInterface(uint8_t interface_number,
300 const ReleaseInterfaceCallback& callback) {
301 if (!device_handle_) {
302 callback.Run(false);
303 return;
304 }
305
306 device_handle_->ReleaseInterface(interface_number,
307 WrapMojoCallback(callback));
308 }
309
310 void DeviceImpl::SetInterfaceAlternateSetting(
311 uint8_t interface_number,
312 uint8_t alternate_setting,
313 const SetInterfaceAlternateSettingCallback& callback) {
314 if (!device_handle_) {
315 callback.Run(false);
316 return;
317 }
318
319 device_handle_->SetInterfaceAlternateSetting(
320 interface_number, alternate_setting, WrapMojoCallback(callback));
321 }
322
323 void DeviceImpl::Reset(const ResetCallback& callback) {
324 if (!device_handle_) {
325 callback.Run(false);
326 return;
327 }
328
329 device_handle_->ResetDevice(WrapMojoCallback(callback));
330 }
331
332 void DeviceImpl::ClearHalt(uint8_t endpoint,
333 const ClearHaltCallback& callback) {
334 if (!device_handle_) {
335 callback.Run(false);
336 return;
337 }
338
339 device_handle_->ClearHalt(endpoint, WrapMojoCallback(callback));
340 }
341
342 void DeviceImpl::ControlTransferIn(ControlTransferParamsPtr params,
343 uint32_t length,
344 uint32_t timeout,
345 const ControlTransferInCallback& callback) {
346 if (!device_handle_) {
347 callback.Run(TransferStatus::TRANSFER_ERROR, mojo::Array<uint8_t>());
348 return;
349 }
350
351 auto callback_ptr = make_scoped_ptr(new ControlTransferInCallback(callback));
352 ControlTransferRecipient recipient = params->recipient;
353 uint16_t index = params->index;
354 HasControlTransferPermission(
355 recipient, index,
356 base::Bind(&OnControlTransferInPermissionCheckComplete, device_handle_,
357 base::Passed(&params), length, timeout,
358 base::Passed(&callback_ptr)));
359 }
360
361 void DeviceImpl::ControlTransferOut(
362 ControlTransferParamsPtr params,
363 mojo::Array<uint8_t> data,
364 uint32_t timeout,
365 const ControlTransferOutCallback& callback) {
366 if (!device_handle_) {
367 callback.Run(TransferStatus::TRANSFER_ERROR);
368 return;
369 }
370
371 auto callback_ptr = make_scoped_ptr(new ControlTransferOutCallback(callback));
372 ControlTransferRecipient recipient = params->recipient;
373 uint16_t index = params->index;
374 HasControlTransferPermission(
375 recipient, index,
376 base::Bind(&OnControlTransferOutPermissionCheckComplete, device_handle_,
377 base::Passed(&params), base::Passed(&data), timeout,
378 base::Passed(&callback_ptr)));
379 }
380
381 void DeviceImpl::GenericTransferIn(uint8_t endpoint_number,
382 uint32_t length,
383 uint32_t timeout,
384 const GenericTransferInCallback& callback) {
385 if (!device_handle_) {
386 callback.Run(TransferStatus::TRANSFER_ERROR, mojo::Array<uint8_t>());
387 return;
388 }
389
390 auto callback_ptr = make_scoped_ptr(new GenericTransferInCallback(callback));
391 uint8_t endpoint_address = endpoint_number | 0x80;
392 scoped_refptr<net::IOBuffer> buffer = CreateTransferBuffer(length);
393 device_handle_->GenericTransfer(
394 USB_DIRECTION_INBOUND, endpoint_address, buffer, length, timeout,
395 base::Bind(&OnTransferIn, base::Passed(&callback_ptr)));
396 }
397
398 void DeviceImpl::GenericTransferOut(
399 uint8_t endpoint_number,
400 mojo::Array<uint8_t> data,
401 uint32_t timeout,
402 const GenericTransferOutCallback& callback) {
403 if (!device_handle_) {
404 callback.Run(TransferStatus::TRANSFER_ERROR);
405 return;
406 }
407
408 auto callback_ptr = make_scoped_ptr(new GenericTransferOutCallback(callback));
409 uint8_t endpoint_address = endpoint_number;
410 scoped_refptr<net::IOBuffer> buffer = CreateTransferBuffer(data.size());
411 const std::vector<uint8_t>& storage = data.storage();
412 std::copy(storage.begin(), storage.end(), buffer->data());
413 device_handle_->GenericTransfer(
414 USB_DIRECTION_OUTBOUND, endpoint_address, buffer, data.size(), timeout,
415 base::Bind(&OnTransferOut, base::Passed(&callback_ptr)));
416 }
417
418 void DeviceImpl::IsochronousTransferIn(
419 uint8_t endpoint_number,
420 mojo::Array<uint32_t> packet_lengths,
421 uint32_t timeout,
422 const IsochronousTransferInCallback& callback) {
423 if (!device_handle_) {
424 callback.Run(mojo::Array<uint8_t>(),
425 BuildIsochronousPacketArray(std::move(packet_lengths),
426 TransferStatus::TRANSFER_ERROR));
427 return;
428 }
429
430 auto callback_ptr =
431 make_scoped_ptr(new IsochronousTransferInCallback(callback));
432 uint8_t endpoint_address = endpoint_number | 0x80;
433 device_handle_->IsochronousTransferIn(
434 endpoint_address, packet_lengths.storage(), timeout,
435 base::Bind(&OnIsochronousTransferIn, base::Passed(&callback_ptr)));
436 }
437
438 void DeviceImpl::IsochronousTransferOut(
439 uint8_t endpoint_number,
440 mojo::Array<uint8_t> data,
441 mojo::Array<uint32_t> packet_lengths,
442 uint32_t timeout,
443 const IsochronousTransferOutCallback& callback) {
444 if (!device_handle_) {
445 callback.Run(BuildIsochronousPacketArray(std::move(packet_lengths),
446 TransferStatus::TRANSFER_ERROR));
447 return;
448 }
449
450 auto callback_ptr =
451 make_scoped_ptr(new IsochronousTransferOutCallback(callback));
452 uint8_t endpoint_address = endpoint_number;
453 scoped_refptr<net::IOBuffer> buffer = CreateTransferBuffer(data.size());
454 {
455 const std::vector<uint8_t>& storage = data.storage();
456 std::copy(storage.begin(), storage.end(), buffer->data());
457 }
458 device_handle_->IsochronousTransferOut(
459 endpoint_address, buffer, packet_lengths.storage(), timeout,
460 base::Bind(&OnIsochronousTransferOut, base::Passed(&callback_ptr)));
461 }
462
463 } // namespace usb
464 } // namespace device
OLDNEW
« no previous file with comments | « device/devices_app/usb/device_impl.h ('k') | device/devices_app/usb/device_impl_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698