ChildAccountService[Java] delegates everything to native side.
[chromium-blink-merge.git] / device / devices_app / usb / device_impl.cc
blob73c5d77adbf47953b43cc2283c50de5761469a39
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<UsbDevice> device,
43 mojo::InterfaceRequest<Device> request)
44 : binding_(this, request.Pass()), device_(device), weak_factory_(this) {}
46 DeviceImpl::~DeviceImpl() {
47 CloseHandle();
50 void DeviceImpl::CloseHandle() {
51 if (device_handle_)
52 device_handle_->Close();
53 device_handle_ = nullptr;
56 void DeviceImpl::OnOpen(const OpenCallback& callback,
57 scoped_refptr<UsbDeviceHandle> handle) {
58 device_handle_ = handle;
59 callback.Run(handle ? OPEN_DEVICE_ERROR_OK : OPEN_DEVICE_ERROR_ACCESS_DENIED);
62 void DeviceImpl::OnTransferIn(const MojoTransferInCallback& callback,
63 UsbTransferStatus status,
64 scoped_refptr<net::IOBuffer> buffer,
65 size_t buffer_size) {
66 mojo::Array<uint8_t> data;
67 if (buffer) {
68 // TODO(rockot/reillyg): We should change UsbDeviceHandle to use a
69 // std::vector<uint8_t> instead of net::IOBuffer. Then we could move
70 // instead of copy.
71 std::vector<uint8_t> bytes(buffer_size);
72 std::copy(buffer->data(), buffer->data() + buffer_size, bytes.begin());
73 data.Swap(&bytes);
75 callback.Run(mojo::ConvertTo<TransferStatus>(status), data.Pass());
78 void DeviceImpl::OnTransferOut(const MojoTransferOutCallback& callback,
79 UsbTransferStatus status,
80 scoped_refptr<net::IOBuffer> buffer,
81 size_t buffer_size) {
82 callback.Run(mojo::ConvertTo<TransferStatus>(status));
85 void DeviceImpl::OnIsochronousTransferIn(
86 const IsochronousTransferInCallback& callback,
87 uint32_t packet_size,
88 UsbTransferStatus status,
89 scoped_refptr<net::IOBuffer> buffer,
90 size_t buffer_size) {
91 size_t num_packets = buffer_size / packet_size;
92 mojo::Array<mojo::Array<uint8_t>> packets(num_packets);
93 if (buffer) {
94 for (size_t i = 0; i < num_packets; ++i) {
95 size_t packet_index = i * packet_size;
96 std::vector<uint8_t> bytes(packet_size);
97 std::copy(buffer->data() + packet_index,
98 buffer->data() + packet_index + packet_size, bytes.begin());
99 packets[i].Swap(&bytes);
102 callback.Run(mojo::ConvertTo<TransferStatus>(status), packets.Pass());
105 void DeviceImpl::OnIsochronousTransferOut(
106 const MojoTransferOutCallback& callback,
107 UsbTransferStatus status,
108 scoped_refptr<net::IOBuffer> buffer,
109 size_t buffer_size) {
110 callback.Run(mojo::ConvertTo<TransferStatus>(status));
113 void DeviceImpl::GetDeviceInfo(const GetDeviceInfoCallback& callback) {
114 callback.Run(DeviceInfo::From(*device_));
117 void DeviceImpl::GetConfiguration(const GetConfigurationCallback& callback) {
118 const UsbConfigDescriptor* config = device_->GetActiveConfiguration();
119 callback.Run(config ? ConfigurationInfo::From(*config) : nullptr);
122 void DeviceImpl::Open(const OpenCallback& callback) {
123 device_->Open(
124 base::Bind(&DeviceImpl::OnOpen, weak_factory_.GetWeakPtr(), callback));
127 void DeviceImpl::Close(const CloseCallback& callback) {
128 CloseHandle();
129 callback.Run();
132 void DeviceImpl::SetConfiguration(uint8_t value,
133 const SetConfigurationCallback& callback) {
134 if (!device_handle_) {
135 callback.Run(false);
136 return;
139 device_handle_->SetConfiguration(value, WrapMojoCallback(callback));
142 void DeviceImpl::ClaimInterface(uint8_t interface_number,
143 const ClaimInterfaceCallback& callback) {
144 if (!device_handle_) {
145 callback.Run(false);
146 return;
149 device_handle_->ClaimInterface(interface_number, WrapMojoCallback(callback));
152 void DeviceImpl::ReleaseInterface(uint8_t interface_number,
153 const ReleaseInterfaceCallback& callback) {
154 if (!device_handle_) {
155 callback.Run(false);
156 return;
159 callback.Run(device_handle_->ReleaseInterface(interface_number));
162 void DeviceImpl::SetInterfaceAlternateSetting(
163 uint8_t interface_number,
164 uint8_t alternate_setting,
165 const SetInterfaceAlternateSettingCallback& callback) {
166 if (!device_handle_) {
167 callback.Run(false);
168 return;
171 device_handle_->SetInterfaceAlternateSetting(
172 interface_number, alternate_setting, WrapMojoCallback(callback));
175 void DeviceImpl::Reset(const ResetCallback& callback) {
176 if (!device_handle_) {
177 callback.Run(false);
178 return;
181 device_handle_->ResetDevice(WrapMojoCallback(callback));
184 void DeviceImpl::ClearHalt(uint8_t endpoint,
185 const ClearHaltCallback& callback) {
186 if (!device_handle_) {
187 callback.Run(false);
188 return;
191 device_handle_->ClearHalt(endpoint, WrapMojoCallback(callback));
194 void DeviceImpl::ControlTransferIn(ControlTransferParamsPtr params,
195 uint32_t length,
196 uint32_t timeout,
197 const ControlTransferInCallback& callback) {
198 if (!device_handle_) {
199 callback.Run(TRANSFER_STATUS_ERROR, mojo::Array<uint8_t>());
200 return;
203 scoped_refptr<net::IOBuffer> buffer = CreateTransferBuffer(length);
204 device_handle_->ControlTransfer(
205 USB_DIRECTION_INBOUND,
206 mojo::ConvertTo<UsbDeviceHandle::TransferRequestType>(params->type),
207 mojo::ConvertTo<UsbDeviceHandle::TransferRecipient>(params->recipient),
208 params->request, params->value, params->index, buffer, length, timeout,
209 base::Bind(&DeviceImpl::OnTransferIn, weak_factory_.GetWeakPtr(),
210 callback));
213 void DeviceImpl::ControlTransferOut(
214 ControlTransferParamsPtr params,
215 mojo::Array<uint8_t> data,
216 uint32_t timeout,
217 const ControlTransferOutCallback& callback) {
218 if (!device_handle_) {
219 callback.Run(TRANSFER_STATUS_ERROR);
220 return;
223 scoped_refptr<net::IOBuffer> buffer = CreateTransferBuffer(data.size());
224 const std::vector<uint8_t>& storage = data.storage();
225 std::copy(storage.begin(), storage.end(), buffer->data());
226 device_handle_->ControlTransfer(
227 USB_DIRECTION_OUTBOUND,
228 mojo::ConvertTo<UsbDeviceHandle::TransferRequestType>(params->type),
229 mojo::ConvertTo<UsbDeviceHandle::TransferRecipient>(params->recipient),
230 params->request, params->value, params->index, buffer, data.size(),
231 timeout, base::Bind(&DeviceImpl::OnTransferOut,
232 weak_factory_.GetWeakPtr(), callback));
235 void DeviceImpl::GenericTransferIn(uint8_t endpoint_number,
236 uint32_t length,
237 uint32_t timeout,
238 const GenericTransferInCallback& callback) {
239 if (!device_handle_) {
240 callback.Run(TRANSFER_STATUS_ERROR, mojo::Array<uint8_t>());
241 return;
244 uint8_t endpoint_address = endpoint_number | 0x80;
245 scoped_refptr<net::IOBuffer> buffer = CreateTransferBuffer(length);
246 device_handle_->GenericTransfer(
247 USB_DIRECTION_INBOUND, endpoint_address, buffer, length, timeout,
248 base::Bind(&DeviceImpl::OnTransferIn, weak_factory_.GetWeakPtr(),
249 callback));
252 void DeviceImpl::GenericTransferOut(
253 uint8_t endpoint_number,
254 mojo::Array<uint8_t> data,
255 uint32_t timeout,
256 const GenericTransferOutCallback& callback) {
257 if (!device_handle_) {
258 callback.Run(TRANSFER_STATUS_ERROR);
259 return;
262 uint8_t endpoint_address = endpoint_number;
263 scoped_refptr<net::IOBuffer> buffer = CreateTransferBuffer(data.size());
264 const std::vector<uint8_t>& storage = data.storage();
265 std::copy(storage.begin(), storage.end(), buffer->data());
266 device_handle_->GenericTransfer(
267 USB_DIRECTION_OUTBOUND, endpoint_address, buffer, data.size(), timeout,
268 base::Bind(&DeviceImpl::OnTransferOut, weak_factory_.GetWeakPtr(),
269 callback));
272 void DeviceImpl::IsochronousTransferIn(
273 uint8_t endpoint_number,
274 uint32_t num_packets,
275 uint32_t packet_length,
276 uint32_t timeout,
277 const IsochronousTransferInCallback& callback) {
278 if (!device_handle_) {
279 callback.Run(TRANSFER_STATUS_ERROR, mojo::Array<mojo::Array<uint8_t>>());
280 return;
283 uint8_t endpoint_address = endpoint_number | 0x80;
284 size_t transfer_size = static_cast<size_t>(num_packets) * packet_length;
285 scoped_refptr<net::IOBuffer> buffer = CreateTransferBuffer(transfer_size);
286 device_handle_->IsochronousTransfer(
287 USB_DIRECTION_INBOUND, endpoint_address, buffer, transfer_size,
288 num_packets, packet_length, timeout,
289 base::Bind(&DeviceImpl::OnIsochronousTransferIn,
290 weak_factory_.GetWeakPtr(), callback, packet_length));
293 void DeviceImpl::IsochronousTransferOut(
294 uint8_t endpoint_number,
295 mojo::Array<mojo::Array<uint8_t>> packets,
296 uint32_t timeout,
297 const IsochronousTransferOutCallback& callback) {
298 if (!device_handle_) {
299 callback.Run(TRANSFER_STATUS_ERROR);
300 return;
303 uint8_t endpoint_address = endpoint_number;
304 uint32_t packet_size = 0;
305 for (size_t i = 0; i < packets.size(); ++i) {
306 packet_size =
307 std::max(packet_size, static_cast<uint32_t>(packets[i].size()));
309 size_t transfer_size = packet_size * packets.size();
310 scoped_refptr<net::IOBuffer> buffer = CreateTransferBuffer(transfer_size);
311 memset(buffer->data(), 0, transfer_size);
312 for (size_t i = 0; i < packets.size(); ++i) {
313 uint8_t* packet =
314 reinterpret_cast<uint8_t*>(&buffer->data()[i * packet_size]);
315 DCHECK_LE(packets[i].size(), static_cast<size_t>(packet_size));
316 memcpy(packet, packets[i].storage().data(), packets[i].size());
318 device_handle_->IsochronousTransfer(
319 USB_DIRECTION_OUTBOUND, endpoint_address, buffer, transfer_size,
320 static_cast<uint32_t>(packets.size()), packet_size, timeout,
321 base::Bind(&DeviceImpl::OnIsochronousTransferOut,
322 weak_factory_.GetWeakPtr(), callback));
325 } // namespace usb
326 } // namespace device