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

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

Issue 1183443002: Reland: Introduce the devices Mojo app (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: gn check... Created 5 years, 6 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/usb/device_impl.h ('k') | device/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 "base/bind.h"
6 #include "base/callback.h"
7 #include "base/stl_util.h"
8 #include "device/usb/device_impl.h"
9 #include "device/usb/type_converters.h"
10 #include "device/usb/usb_descriptors.h"
11 #include "device/usb/usb_device.h"
12 #include "net/base/io_buffer.h"
13
14 namespace device {
15 namespace usb {
16
17 namespace {
18
19 template <typename... Args>
20 void CallMojoCallback(const mojo::Callback<void(Args...)>& callback,
21 Args... args) {
22 callback.Run(args...);
23 }
24
25 // Generic wrapper to convert a Mojo callback to something we can rebind and
26 // pass around. This is only usable for callbacks with no move-only arguments.
27 template <typename... Args>
28 base::Callback<void(Args...)> WrapMojoCallback(
29 const mojo::Callback<void(Args...)>& callback) {
30 return base::Bind(&CallMojoCallback<Args...>, callback);
31 }
32
33 scoped_refptr<net::IOBuffer> CreateTransferBuffer(size_t size) {
34 scoped_refptr<net::IOBuffer> buffer = new net::IOBuffer(
35 std::max(static_cast<size_t>(1u), static_cast<size_t>(size)));
36 return buffer;
37 }
38
39 } // namespace
40
41 DeviceImpl::DeviceImpl(scoped_refptr<UsbDeviceHandle> device_handle,
42 mojo::InterfaceRequest<Device> request)
43 : binding_(this, request.Pass()),
44 device_handle_(device_handle),
45 weak_factory_(this) {
46 }
47
48 DeviceImpl::~DeviceImpl() {
49 CloseHandle();
50 }
51
52 void DeviceImpl::CloseHandle() {
53 if (device_handle_)
54 device_handle_->Close();
55 device_handle_ = nullptr;
56 }
57
58 void DeviceImpl::OnTransferIn(const MojoTransferInCallback& callback,
59 UsbTransferStatus status,
60 scoped_refptr<net::IOBuffer> buffer,
61 size_t buffer_size) {
62 mojo::Array<uint8_t> data;
63 if (buffer) {
64 // TODO(rockot/reillyg): We should change UsbDeviceHandle to use a
65 // std::vector<uint8_t> instead of net::IOBuffer. Then we could move
66 // instead of copy.
67 std::vector<uint8_t> bytes(buffer_size);
68 std::copy(buffer->data(), buffer->data() + buffer_size, bytes.begin());
69 data.Swap(&bytes);
70 }
71 callback.Run(mojo::ConvertTo<TransferStatus>(status), data.Pass());
72 }
73
74 void DeviceImpl::OnTransferOut(const MojoTransferOutCallback& callback,
75 UsbTransferStatus status,
76 scoped_refptr<net::IOBuffer> buffer,
77 size_t buffer_size) {
78 callback.Run(mojo::ConvertTo<TransferStatus>(status));
79 }
80
81 void DeviceImpl::OnIsochronousTransferIn(
82 const IsochronousTransferInCallback& callback,
83 uint32_t packet_size,
84 UsbTransferStatus status,
85 scoped_refptr<net::IOBuffer> buffer,
86 size_t buffer_size) {
87 size_t num_packets = buffer_size / packet_size;
88 mojo::Array<mojo::Array<uint8_t>> packets(num_packets);
89 if (buffer) {
90 for (size_t i = 0; i < num_packets; ++i) {
91 size_t packet_index = i * packet_size;
92 std::vector<uint8_t> bytes(packet_size);
93 std::copy(buffer->data() + packet_index,
94 buffer->data() + packet_index + packet_size, bytes.begin());
95 packets[i].Swap(&bytes);
96 }
97 }
98 callback.Run(mojo::ConvertTo<TransferStatus>(status), packets.Pass());
99 }
100
101 void DeviceImpl::OnIsochronousTransferOut(
102 const MojoTransferOutCallback& callback,
103 UsbTransferStatus status,
104 scoped_refptr<net::IOBuffer> buffer,
105 size_t buffer_size) {
106 callback.Run(mojo::ConvertTo<TransferStatus>(status));
107 }
108
109 void DeviceImpl::Close(const CloseCallback& callback) {
110 CloseHandle();
111 callback.Run();
112 }
113
114 void DeviceImpl::GetDeviceInfo(const GetDeviceInfoCallback& callback) {
115 if (!device_handle_) {
116 callback.Run(DeviceInfoPtr());
117 return;
118 }
119
120 // TODO(rockot/reillyg): Support more than just the current configuration.
121 // Also, converting configuration info should be done in the TypeConverter,
122 // but GetConfiguration() is non-const so we do it here for now.
123 DeviceInfoPtr info = DeviceInfo::From(*device_handle_->GetDevice());
124 const UsbConfigDescriptor* config =
125 device_handle_->GetDevice()->GetConfiguration();
126 info->configurations = mojo::Array<ConfigurationInfoPtr>::New(0);
127 if (config)
128 info->configurations.push_back(ConfigurationInfo::From(*config));
129 callback.Run(info.Pass());
130 }
131
132 void DeviceImpl::SetConfiguration(uint8_t value,
133 const SetConfigurationCallback& callback) {
134 if (!device_handle_) {
135 callback.Run(false);
136 return;
137 }
138
139 device_handle_->SetConfiguration(value, WrapMojoCallback(callback));
140 }
141
142 void DeviceImpl::ClaimInterface(uint8_t interface_number,
143 const ClaimInterfaceCallback& callback) {
144 if (!device_handle_) {
145 callback.Run(false);
146 return;
147 }
148
149 device_handle_->ClaimInterface(interface_number, WrapMojoCallback(callback));
150 }
151
152 void DeviceImpl::ReleaseInterface(uint8_t interface_number,
153 const ReleaseInterfaceCallback& callback) {
154 if (!device_handle_) {
155 callback.Run(false);
156 return;
157 }
158
159 callback.Run(device_handle_->ReleaseInterface(interface_number));
160 }
161
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;
169 }
170
171 device_handle_->SetInterfaceAlternateSetting(
172 interface_number, alternate_setting, WrapMojoCallback(callback));
173 }
174
175 void DeviceImpl::Reset(const ResetCallback& callback) {
176 if (!device_handle_) {
177 callback.Run(false);
178 return;
179 }
180
181 device_handle_->ResetDevice(WrapMojoCallback(callback));
182 }
183
184 void DeviceImpl::ControlTransferIn(ControlTransferParamsPtr params,
185 uint32_t length,
186 uint32_t timeout,
187 const ControlTransferInCallback& callback) {
188 if (!device_handle_) {
189 callback.Run(TRANSFER_STATUS_ERROR, mojo::Array<uint8_t>());
190 return;
191 }
192
193 scoped_refptr<net::IOBuffer> buffer = CreateTransferBuffer(length);
194 device_handle_->ControlTransfer(
195 USB_DIRECTION_INBOUND,
196 mojo::ConvertTo<UsbDeviceHandle::TransferRequestType>(params->type),
197 mojo::ConvertTo<UsbDeviceHandle::TransferRecipient>(params->recipient),
198 params->request, params->value, params->index, buffer, length, timeout,
199 base::Bind(&DeviceImpl::OnTransferIn, weak_factory_.GetWeakPtr(),
200 callback));
201 }
202
203 void DeviceImpl::ControlTransferOut(
204 ControlTransferParamsPtr params,
205 mojo::Array<uint8_t> data,
206 uint32_t timeout,
207 const ControlTransferOutCallback& callback) {
208 if (!device_handle_) {
209 callback.Run(TRANSFER_STATUS_ERROR);
210 return;
211 }
212
213 scoped_refptr<net::IOBuffer> buffer = CreateTransferBuffer(data.size());
214 const std::vector<uint8_t>& storage = data.storage();
215 std::copy(storage.begin(), storage.end(), buffer->data());
216 device_handle_->ControlTransfer(
217 USB_DIRECTION_OUTBOUND,
218 mojo::ConvertTo<UsbDeviceHandle::TransferRequestType>(params->type),
219 mojo::ConvertTo<UsbDeviceHandle::TransferRecipient>(params->recipient),
220 params->request, params->value, params->index, buffer, data.size(),
221 timeout, base::Bind(&DeviceImpl::OnTransferOut,
222 weak_factory_.GetWeakPtr(), callback));
223 }
224
225 void DeviceImpl::BulkTransferIn(uint8_t endpoint_number,
226 uint32_t length,
227 uint32_t timeout,
228 const BulkTransferInCallback& callback) {
229 if (!device_handle_) {
230 callback.Run(TRANSFER_STATUS_ERROR, mojo::Array<uint8_t>());
231 return;
232 }
233
234 scoped_refptr<net::IOBuffer> buffer = CreateTransferBuffer(length);
235 device_handle_->BulkTransfer(
236 USB_DIRECTION_INBOUND, endpoint_number, buffer, length, timeout,
237 base::Bind(&DeviceImpl::OnTransferIn, weak_factory_.GetWeakPtr(),
238 callback));
239 }
240
241 void DeviceImpl::BulkTransferOut(uint8_t endpoint_number,
242 mojo::Array<uint8_t> data,
243 uint32_t timeout,
244 const BulkTransferOutCallback& callback) {
245 if (!device_handle_) {
246 callback.Run(TRANSFER_STATUS_ERROR);
247 return;
248 }
249
250 scoped_refptr<net::IOBuffer> buffer = CreateTransferBuffer(data.size());
251 const std::vector<uint8_t>& storage = data.storage();
252 std::copy(storage.begin(), storage.end(), buffer->data());
253 device_handle_->BulkTransfer(
254 USB_DIRECTION_OUTBOUND, endpoint_number, buffer, data.size(), timeout,
255 base::Bind(&DeviceImpl::OnTransferOut, weak_factory_.GetWeakPtr(),
256 callback));
257 }
258
259 void DeviceImpl::InterruptTransferIn(
260 uint8_t endpoint_number,
261 uint32_t length,
262 uint32_t timeout,
263 const InterruptTransferInCallback& callback) {
264 if (!device_handle_) {
265 callback.Run(TRANSFER_STATUS_ERROR, mojo::Array<uint8_t>());
266 return;
267 }
268
269 scoped_refptr<net::IOBuffer> buffer = CreateTransferBuffer(length);
270 device_handle_->InterruptTransfer(
271 USB_DIRECTION_INBOUND, endpoint_number, buffer, length, timeout,
272 base::Bind(&DeviceImpl::OnTransferIn, weak_factory_.GetWeakPtr(),
273 callback));
274 }
275
276 void DeviceImpl::InterruptTransferOut(
277 uint8_t endpoint_number,
278 mojo::Array<uint8_t> data,
279 uint32_t timeout,
280 const InterruptTransferOutCallback& callback) {
281 if (!device_handle_) {
282 callback.Run(TRANSFER_STATUS_ERROR);
283 return;
284 }
285
286 scoped_refptr<net::IOBuffer> buffer = CreateTransferBuffer(data.size());
287 const std::vector<uint8_t>& storage = data.storage();
288 std::copy(storage.begin(), storage.end(), buffer->data());
289 device_handle_->InterruptTransfer(
290 USB_DIRECTION_OUTBOUND, endpoint_number, buffer, data.size(), timeout,
291 base::Bind(&DeviceImpl::OnTransferOut, weak_factory_.GetWeakPtr(),
292 callback));
293 }
294
295 void DeviceImpl::IsochronousTransferIn(
296 uint8_t endpoint_number,
297 uint32_t num_packets,
298 uint32_t packet_length,
299 uint32_t timeout,
300 const IsochronousTransferInCallback& callback) {
301 if (!device_handle_) {
302 callback.Run(TRANSFER_STATUS_ERROR, mojo::Array<mojo::Array<uint8_t>>());
303 return;
304 }
305
306 size_t transfer_size = static_cast<size_t>(num_packets) * packet_length;
307 scoped_refptr<net::IOBuffer> buffer = CreateTransferBuffer(transfer_size);
308 device_handle_->IsochronousTransfer(
309 USB_DIRECTION_INBOUND, endpoint_number, buffer, transfer_size,
310 num_packets, packet_length, timeout,
311 base::Bind(&DeviceImpl::OnIsochronousTransferIn,
312 weak_factory_.GetWeakPtr(), callback, packet_length));
313 }
314
315 void DeviceImpl::IsochronousTransferOut(
316 uint8_t endpoint_number,
317 mojo::Array<mojo::Array<uint8_t>> packets,
318 uint32_t timeout,
319 const IsochronousTransferOutCallback& callback) {
320 if (!device_handle_) {
321 callback.Run(TRANSFER_STATUS_ERROR);
322 return;
323 }
324
325 uint32_t packet_size = 0;
326 for (size_t i = 0; i < packets.size(); ++i) {
327 packet_size =
328 std::max(packet_size, static_cast<uint32_t>(packets[i].size()));
329 }
330 size_t transfer_size = packet_size * packets.size();
331 scoped_refptr<net::IOBuffer> buffer = CreateTransferBuffer(transfer_size);
332 memset(buffer->data(), 0, transfer_size);
333 for (size_t i = 0; i < packets.size(); ++i) {
334 uint8_t* packet =
335 reinterpret_cast<uint8_t*>(&buffer->data()[i * packet_size]);
336 DCHECK_LE(packets[i].size(), static_cast<size_t>(packet_size));
337 memcpy(packet, packets[i].storage().data(), packets[i].size());
338 }
339 device_handle_->IsochronousTransfer(
340 USB_DIRECTION_OUTBOUND, endpoint_number, buffer, transfer_size,
341 static_cast<uint32_t>(packets.size()), packet_size, timeout,
342 base::Bind(&DeviceImpl::OnIsochronousTransferOut,
343 weak_factory_.GetWeakPtr(), callback));
344 }
345
346 } // namespace usb
347 } // namespace device
OLDNEW
« no previous file with comments | « device/usb/device_impl.h ('k') | device/usb/device_impl_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698