Update V8 to version 4.6.55.
[chromium-blink-merge.git] / device / devices_app / usb / device_impl.cc
blob798c115765c58f8bbf3570e98d3dc9e21c8fd11a
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.
5 #include "device/devices_app/usb/device_impl.h"
7 #include "base/bind.h"
8 #include "base/callback.h"
9 #include "base/stl_util.h"
10 #include "device/devices_app/usb/type_converters.h"
11 #include "device/usb/usb_descriptors.h"
12 #include "device/usb/usb_device.h"
13 #include "net/base/io_buffer.h"
15 namespace device {
16 namespace usb {
18 namespace {
20 template <typename... Args>
21 void CallMojoCallback(const mojo::Callback<void(Args...)>& callback,
22 Args... args) {
23 callback.Run(args...);
26 // Generic wrapper to convert a Mojo callback to something we can rebind and
27 // pass around. This is only usable for callbacks with no move-only arguments.
28 template <typename... Args>
29 base::Callback<void(Args...)> WrapMojoCallback(
30 const mojo::Callback<void(Args...)>& callback) {
31 return base::Bind(&CallMojoCallback<Args...>, callback);
34 scoped_refptr<net::IOBuffer> CreateTransferBuffer(size_t size) {
35 scoped_refptr<net::IOBuffer> buffer = new net::IOBuffer(
36 std::max(static_cast<size_t>(1u), static_cast<size_t>(size)));
37 return buffer;
40 } // namespace
42 DeviceImpl::DeviceImpl(scoped_refptr<UsbDeviceHandle> device_handle,
43 mojo::InterfaceRequest<Device> request)
44 : binding_(this, request.Pass()),
45 device_handle_(device_handle),
46 weak_factory_(this) {
49 DeviceImpl::~DeviceImpl() {
50 CloseHandle();
53 void DeviceImpl::CloseHandle() {
54 if (device_handle_)
55 device_handle_->Close();
56 device_handle_ = nullptr;
59 void DeviceImpl::OnTransferIn(const MojoTransferInCallback& callback,
60 UsbTransferStatus status,
61 scoped_refptr<net::IOBuffer> buffer,
62 size_t buffer_size) {
63 mojo::Array<uint8_t> data;
64 if (buffer) {
65 // TODO(rockot/reillyg): We should change UsbDeviceHandle to use a
66 // std::vector<uint8_t> instead of net::IOBuffer. Then we could move
67 // instead of copy.
68 std::vector<uint8_t> bytes(buffer_size);
69 std::copy(buffer->data(), buffer->data() + buffer_size, bytes.begin());
70 data.Swap(&bytes);
72 callback.Run(mojo::ConvertTo<TransferStatus>(status), data.Pass());
75 void DeviceImpl::OnTransferOut(const MojoTransferOutCallback& callback,
76 UsbTransferStatus status,
77 scoped_refptr<net::IOBuffer> buffer,
78 size_t buffer_size) {
79 callback.Run(mojo::ConvertTo<TransferStatus>(status));
82 void DeviceImpl::OnIsochronousTransferIn(
83 const IsochronousTransferInCallback& callback,
84 uint32_t packet_size,
85 UsbTransferStatus status,
86 scoped_refptr<net::IOBuffer> buffer,
87 size_t buffer_size) {
88 size_t num_packets = buffer_size / packet_size;
89 mojo::Array<mojo::Array<uint8_t>> packets(num_packets);
90 if (buffer) {
91 for (size_t i = 0; i < num_packets; ++i) {
92 size_t packet_index = i * packet_size;
93 std::vector<uint8_t> bytes(packet_size);
94 std::copy(buffer->data() + packet_index,
95 buffer->data() + packet_index + packet_size, bytes.begin());
96 packets[i].Swap(&bytes);
99 callback.Run(mojo::ConvertTo<TransferStatus>(status), packets.Pass());
102 void DeviceImpl::OnIsochronousTransferOut(
103 const MojoTransferOutCallback& callback,
104 UsbTransferStatus status,
105 scoped_refptr<net::IOBuffer> buffer,
106 size_t buffer_size) {
107 callback.Run(mojo::ConvertTo<TransferStatus>(status));
110 void DeviceImpl::Close(const CloseCallback& callback) {
111 CloseHandle();
112 callback.Run();
115 void DeviceImpl::GetDeviceInfo(const GetDeviceInfoCallback& callback) {
116 if (!device_handle_) {
117 callback.Run(DeviceInfoPtr());
118 return;
121 // TODO(rockot/reillyg): Converting configuration info should be done in the
122 // TypeConverter, but GetConfiguration() is non-const so we do it here for
123 // now.
124 DeviceInfoPtr info = DeviceInfo::From(*device_handle_->GetDevice());
125 const std::vector<UsbConfigDescriptor>& configs =
126 device_handle_->GetDevice()->configurations();
127 info->configurations = mojo::Array<ConfigurationInfoPtr>::New(configs.size());
128 for (size_t i = 0; i < configs.size(); ++i) {
129 info->configurations[i] = ConfigurationInfo::From(configs[i]);
131 callback.Run(info.Pass());
134 void DeviceImpl::SetConfiguration(uint8_t value,
135 const SetConfigurationCallback& callback) {
136 if (!device_handle_) {
137 callback.Run(false);
138 return;
141 device_handle_->SetConfiguration(value, WrapMojoCallback(callback));
144 void DeviceImpl::ClaimInterface(uint8_t interface_number,
145 const ClaimInterfaceCallback& callback) {
146 if (!device_handle_) {
147 callback.Run(false);
148 return;
151 device_handle_->ClaimInterface(interface_number, WrapMojoCallback(callback));
154 void DeviceImpl::ReleaseInterface(uint8_t interface_number,
155 const ReleaseInterfaceCallback& callback) {
156 if (!device_handle_) {
157 callback.Run(false);
158 return;
161 callback.Run(device_handle_->ReleaseInterface(interface_number));
164 void DeviceImpl::SetInterfaceAlternateSetting(
165 uint8_t interface_number,
166 uint8_t alternate_setting,
167 const SetInterfaceAlternateSettingCallback& callback) {
168 if (!device_handle_) {
169 callback.Run(false);
170 return;
173 device_handle_->SetInterfaceAlternateSetting(
174 interface_number, alternate_setting, WrapMojoCallback(callback));
177 void DeviceImpl::Reset(const ResetCallback& callback) {
178 if (!device_handle_) {
179 callback.Run(false);
180 return;
183 device_handle_->ResetDevice(WrapMojoCallback(callback));
186 void DeviceImpl::ClearHalt(uint8_t endpoint,
187 const ClearHaltCallback& callback) {
188 if (!device_handle_) {
189 callback.Run(false);
190 return;
193 device_handle_->ClearHalt(endpoint, WrapMojoCallback(callback));
196 void DeviceImpl::ControlTransferIn(ControlTransferParamsPtr params,
197 uint32_t length,
198 uint32_t timeout,
199 const ControlTransferInCallback& callback) {
200 if (!device_handle_) {
201 callback.Run(TRANSFER_STATUS_ERROR, mojo::Array<uint8_t>());
202 return;
205 scoped_refptr<net::IOBuffer> buffer = CreateTransferBuffer(length);
206 device_handle_->ControlTransfer(
207 USB_DIRECTION_INBOUND,
208 mojo::ConvertTo<UsbDeviceHandle::TransferRequestType>(params->type),
209 mojo::ConvertTo<UsbDeviceHandle::TransferRecipient>(params->recipient),
210 params->request, params->value, params->index, buffer, length, timeout,
211 base::Bind(&DeviceImpl::OnTransferIn, weak_factory_.GetWeakPtr(),
212 callback));
215 void DeviceImpl::ControlTransferOut(
216 ControlTransferParamsPtr params,
217 mojo::Array<uint8_t> data,
218 uint32_t timeout,
219 const ControlTransferOutCallback& callback) {
220 if (!device_handle_) {
221 callback.Run(TRANSFER_STATUS_ERROR);
222 return;
225 scoped_refptr<net::IOBuffer> buffer = CreateTransferBuffer(data.size());
226 const std::vector<uint8_t>& storage = data.storage();
227 std::copy(storage.begin(), storage.end(), buffer->data());
228 device_handle_->ControlTransfer(
229 USB_DIRECTION_OUTBOUND,
230 mojo::ConvertTo<UsbDeviceHandle::TransferRequestType>(params->type),
231 mojo::ConvertTo<UsbDeviceHandle::TransferRecipient>(params->recipient),
232 params->request, params->value, params->index, buffer, data.size(),
233 timeout, base::Bind(&DeviceImpl::OnTransferOut,
234 weak_factory_.GetWeakPtr(), callback));
237 void DeviceImpl::BulkTransferIn(uint8_t endpoint_number,
238 uint32_t length,
239 uint32_t timeout,
240 const BulkTransferInCallback& callback) {
241 if (!device_handle_) {
242 callback.Run(TRANSFER_STATUS_ERROR, mojo::Array<uint8_t>());
243 return;
246 scoped_refptr<net::IOBuffer> buffer = CreateTransferBuffer(length);
247 device_handle_->BulkTransfer(
248 USB_DIRECTION_INBOUND, endpoint_number, buffer, length, timeout,
249 base::Bind(&DeviceImpl::OnTransferIn, weak_factory_.GetWeakPtr(),
250 callback));
253 void DeviceImpl::BulkTransferOut(uint8_t endpoint_number,
254 mojo::Array<uint8_t> data,
255 uint32_t timeout,
256 const BulkTransferOutCallback& callback) {
257 if (!device_handle_) {
258 callback.Run(TRANSFER_STATUS_ERROR);
259 return;
262 scoped_refptr<net::IOBuffer> buffer = CreateTransferBuffer(data.size());
263 const std::vector<uint8_t>& storage = data.storage();
264 std::copy(storage.begin(), storage.end(), buffer->data());
265 device_handle_->BulkTransfer(
266 USB_DIRECTION_OUTBOUND, endpoint_number, buffer, data.size(), timeout,
267 base::Bind(&DeviceImpl::OnTransferOut, weak_factory_.GetWeakPtr(),
268 callback));
271 void DeviceImpl::InterruptTransferIn(
272 uint8_t endpoint_number,
273 uint32_t length,
274 uint32_t timeout,
275 const InterruptTransferInCallback& callback) {
276 if (!device_handle_) {
277 callback.Run(TRANSFER_STATUS_ERROR, mojo::Array<uint8_t>());
278 return;
281 scoped_refptr<net::IOBuffer> buffer = CreateTransferBuffer(length);
282 device_handle_->InterruptTransfer(
283 USB_DIRECTION_INBOUND, endpoint_number, buffer, length, timeout,
284 base::Bind(&DeviceImpl::OnTransferIn, weak_factory_.GetWeakPtr(),
285 callback));
288 void DeviceImpl::InterruptTransferOut(
289 uint8_t endpoint_number,
290 mojo::Array<uint8_t> data,
291 uint32_t timeout,
292 const InterruptTransferOutCallback& callback) {
293 if (!device_handle_) {
294 callback.Run(TRANSFER_STATUS_ERROR);
295 return;
298 scoped_refptr<net::IOBuffer> buffer = CreateTransferBuffer(data.size());
299 const std::vector<uint8_t>& storage = data.storage();
300 std::copy(storage.begin(), storage.end(), buffer->data());
301 device_handle_->InterruptTransfer(
302 USB_DIRECTION_OUTBOUND, endpoint_number, buffer, data.size(), timeout,
303 base::Bind(&DeviceImpl::OnTransferOut, weak_factory_.GetWeakPtr(),
304 callback));
307 void DeviceImpl::IsochronousTransferIn(
308 uint8_t endpoint_number,
309 uint32_t num_packets,
310 uint32_t packet_length,
311 uint32_t timeout,
312 const IsochronousTransferInCallback& callback) {
313 if (!device_handle_) {
314 callback.Run(TRANSFER_STATUS_ERROR, mojo::Array<mojo::Array<uint8_t>>());
315 return;
318 size_t transfer_size = static_cast<size_t>(num_packets) * packet_length;
319 scoped_refptr<net::IOBuffer> buffer = CreateTransferBuffer(transfer_size);
320 device_handle_->IsochronousTransfer(
321 USB_DIRECTION_INBOUND, endpoint_number, buffer, transfer_size,
322 num_packets, packet_length, timeout,
323 base::Bind(&DeviceImpl::OnIsochronousTransferIn,
324 weak_factory_.GetWeakPtr(), callback, packet_length));
327 void DeviceImpl::IsochronousTransferOut(
328 uint8_t endpoint_number,
329 mojo::Array<mojo::Array<uint8_t>> packets,
330 uint32_t timeout,
331 const IsochronousTransferOutCallback& callback) {
332 if (!device_handle_) {
333 callback.Run(TRANSFER_STATUS_ERROR);
334 return;
337 uint32_t packet_size = 0;
338 for (size_t i = 0; i < packets.size(); ++i) {
339 packet_size =
340 std::max(packet_size, static_cast<uint32_t>(packets[i].size()));
342 size_t transfer_size = packet_size * packets.size();
343 scoped_refptr<net::IOBuffer> buffer = CreateTransferBuffer(transfer_size);
344 memset(buffer->data(), 0, transfer_size);
345 for (size_t i = 0; i < packets.size(); ++i) {
346 uint8_t* packet =
347 reinterpret_cast<uint8_t*>(&buffer->data()[i * packet_size]);
348 DCHECK_LE(packets[i].size(), static_cast<size_t>(packet_size));
349 memcpy(packet, packets[i].storage().data(), packets[i].size());
351 device_handle_->IsochronousTransfer(
352 USB_DIRECTION_OUTBOUND, endpoint_number, buffer, transfer_size,
353 static_cast<uint32_t>(packets.size()), packet_size, timeout,
354 base::Bind(&DeviceImpl::OnIsochronousTransferOut,
355 weak_factory_.GetWeakPtr(), callback));
358 } // namespace usb
359 } // namespace device