OLD | NEW |
1 // Copyright 2015 The Chromium Authors. All rights reserved. | 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 | 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/devices_app/usb/device_impl.h" | 5 #include "device/devices_app/usb/device_impl.h" |
6 | 6 |
7 #include <stddef.h> | 7 #include <stddef.h> |
8 | |
9 #include <algorithm> | |
10 #include <numeric> | |
11 #include <utility> | 8 #include <utility> |
12 #include <vector> | |
13 | 9 |
14 #include "base/bind.h" | 10 #include "base/bind.h" |
15 #include "base/callback.h" | 11 #include "base/callback.h" |
16 #include "base/stl_util.h" | 12 #include "base/stl_util.h" |
17 #include "device/devices_app/usb/type_converters.h" | 13 #include "device/devices_app/usb/type_converters.h" |
18 #include "device/usb/usb_descriptors.h" | 14 #include "device/usb/usb_descriptors.h" |
19 #include "device/usb/usb_device.h" | 15 #include "device/usb/usb_device.h" |
20 #include "net/base/io_buffer.h" | 16 #include "net/base/io_buffer.h" |
21 | 17 |
22 namespace device { | 18 namespace device { |
(...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
125 USB_DIRECTION_OUTBOUND, | 121 USB_DIRECTION_OUTBOUND, |
126 mojo::ConvertTo<UsbDeviceHandle::TransferRequestType>(params->type), | 122 mojo::ConvertTo<UsbDeviceHandle::TransferRequestType>(params->type), |
127 mojo::ConvertTo<UsbDeviceHandle::TransferRecipient>(params->recipient), | 123 mojo::ConvertTo<UsbDeviceHandle::TransferRecipient>(params->recipient), |
128 params->request, params->value, params->index, buffer, data.size(), | 124 params->request, params->value, params->index, buffer, data.size(), |
129 timeout, base::Bind(&OnTransferOut, base::Passed(&callback))); | 125 timeout, base::Bind(&OnTransferOut, base::Passed(&callback))); |
130 } else { | 126 } else { |
131 callback->Run(TransferStatus::PERMISSION_DENIED); | 127 callback->Run(TransferStatus::PERMISSION_DENIED); |
132 } | 128 } |
133 } | 129 } |
134 | 130 |
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( | 131 void OnIsochronousTransferIn( |
148 scoped_ptr<Device::IsochronousTransferInCallback> callback, | 132 scoped_ptr<Device::IsochronousTransferInCallback> callback, |
| 133 uint32_t packet_size, |
| 134 UsbTransferStatus status, |
149 scoped_refptr<net::IOBuffer> buffer, | 135 scoped_refptr<net::IOBuffer> buffer, |
150 const std::vector<UsbDeviceHandle::IsochronousPacket>& packets) { | 136 size_t buffer_size) { |
151 mojo::Array<uint8_t> data; | 137 size_t num_packets = buffer_size / packet_size; |
| 138 mojo::Array<mojo::Array<uint8_t>> packets(num_packets); |
152 if (buffer) { | 139 if (buffer) { |
153 // TODO(rockot/reillyg): We should change UsbDeviceHandle to use a | 140 for (size_t i = 0; i < num_packets; ++i) { |
154 // std::vector<uint8_t> instead of net::IOBuffer. Then we could move | 141 size_t packet_index = i * packet_size; |
155 // instead of copy. | 142 std::vector<uint8_t> bytes(packet_size); |
156 uint32_t buffer_size = | 143 std::copy(buffer->data() + packet_index, |
157 std::accumulate(packets.begin(), packets.end(), 0u, | 144 buffer->data() + packet_index + packet_size, bytes.begin()); |
158 [](const uint32_t& a, | 145 packets[i].Swap(&bytes); |
159 const UsbDeviceHandle::IsochronousPacket& packet) { | 146 } |
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 } | 147 } |
166 callback->Run(std::move(data), | 148 callback->Run(mojo::ConvertTo<TransferStatus>(status), std::move(packets)); |
167 mojo::Array<IsochronousPacketPtr>::From(packets)); | |
168 } | 149 } |
169 | 150 |
170 void OnIsochronousTransferOut( | 151 void OnIsochronousTransferOut( |
171 scoped_ptr<Device::IsochronousTransferOutCallback> callback, | 152 scoped_ptr<Device::IsochronousTransferOutCallback> callback, |
| 153 UsbTransferStatus status, |
172 scoped_refptr<net::IOBuffer> buffer, | 154 scoped_refptr<net::IOBuffer> buffer, |
173 const std::vector<UsbDeviceHandle::IsochronousPacket>& packets) { | 155 size_t buffer_size) { |
174 callback->Run(mojo::Array<IsochronousPacketPtr>::From(packets)); | 156 callback->Run(mojo::ConvertTo<TransferStatus>(status)); |
175 } | 157 } |
176 | 158 |
177 } // namespace | 159 } // namespace |
178 | 160 |
179 DeviceImpl::DeviceImpl(scoped_refptr<UsbDevice> device, | 161 DeviceImpl::DeviceImpl(scoped_refptr<UsbDevice> device, |
180 PermissionProviderPtr permission_provider, | 162 PermissionProviderPtr permission_provider, |
181 mojo::InterfaceRequest<Device> request) | 163 mojo::InterfaceRequest<Device> request) |
182 : binding_(this, std::move(request)), | 164 : binding_(this, std::move(request)), |
183 device_(device), | 165 device_(device), |
184 permission_provider_(std::move(permission_provider)), | 166 permission_provider_(std::move(permission_provider)), |
(...skipping 224 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
409 scoped_refptr<net::IOBuffer> buffer = CreateTransferBuffer(data.size()); | 391 scoped_refptr<net::IOBuffer> buffer = CreateTransferBuffer(data.size()); |
410 const std::vector<uint8_t>& storage = data.storage(); | 392 const std::vector<uint8_t>& storage = data.storage(); |
411 std::copy(storage.begin(), storage.end(), buffer->data()); | 393 std::copy(storage.begin(), storage.end(), buffer->data()); |
412 device_handle_->GenericTransfer( | 394 device_handle_->GenericTransfer( |
413 USB_DIRECTION_OUTBOUND, endpoint_address, buffer, data.size(), timeout, | 395 USB_DIRECTION_OUTBOUND, endpoint_address, buffer, data.size(), timeout, |
414 base::Bind(&OnTransferOut, base::Passed(&callback_ptr))); | 396 base::Bind(&OnTransferOut, base::Passed(&callback_ptr))); |
415 } | 397 } |
416 | 398 |
417 void DeviceImpl::IsochronousTransferIn( | 399 void DeviceImpl::IsochronousTransferIn( |
418 uint8_t endpoint_number, | 400 uint8_t endpoint_number, |
419 mojo::Array<uint32_t> packet_lengths, | 401 uint32_t num_packets, |
| 402 uint32_t packet_length, |
420 uint32_t timeout, | 403 uint32_t timeout, |
421 const IsochronousTransferInCallback& callback) { | 404 const IsochronousTransferInCallback& callback) { |
422 if (!device_handle_) { | 405 if (!device_handle_) { |
423 callback.Run(mojo::Array<uint8_t>(), | 406 callback.Run(TransferStatus::TRANSFER_ERROR, |
424 BuildIsochronousPacketArray(std::move(packet_lengths), | 407 mojo::Array<mojo::Array<uint8_t>>()); |
425 TransferStatus::TRANSFER_ERROR)); | |
426 return; | 408 return; |
427 } | 409 } |
428 | 410 |
429 auto callback_ptr = | 411 auto callback_ptr = |
430 make_scoped_ptr(new IsochronousTransferInCallback(callback)); | 412 make_scoped_ptr(new IsochronousTransferInCallback(callback)); |
431 uint8_t endpoint_address = endpoint_number | 0x80; | 413 uint8_t endpoint_address = endpoint_number | 0x80; |
432 device_handle_->IsochronousTransferIn( | 414 size_t transfer_size = static_cast<size_t>(num_packets) * packet_length; |
433 endpoint_address, packet_lengths.storage(), timeout, | 415 scoped_refptr<net::IOBuffer> buffer = CreateTransferBuffer(transfer_size); |
434 base::Bind(&OnIsochronousTransferIn, base::Passed(&callback_ptr))); | 416 device_handle_->IsochronousTransfer( |
| 417 USB_DIRECTION_INBOUND, endpoint_address, buffer, transfer_size, |
| 418 num_packets, packet_length, timeout, |
| 419 base::Bind(&OnIsochronousTransferIn, base::Passed(&callback_ptr), |
| 420 packet_length)); |
435 } | 421 } |
436 | 422 |
437 void DeviceImpl::IsochronousTransferOut( | 423 void DeviceImpl::IsochronousTransferOut( |
438 uint8_t endpoint_number, | 424 uint8_t endpoint_number, |
439 mojo::Array<uint8_t> data, | 425 mojo::Array<mojo::Array<uint8_t>> packets, |
440 mojo::Array<uint32_t> packet_lengths, | |
441 uint32_t timeout, | 426 uint32_t timeout, |
442 const IsochronousTransferOutCallback& callback) { | 427 const IsochronousTransferOutCallback& callback) { |
443 if (!device_handle_) { | 428 if (!device_handle_) { |
444 callback.Run(BuildIsochronousPacketArray(std::move(packet_lengths), | 429 callback.Run(TransferStatus::TRANSFER_ERROR); |
445 TransferStatus::TRANSFER_ERROR)); | |
446 return; | 430 return; |
447 } | 431 } |
448 | 432 |
449 auto callback_ptr = | 433 auto callback_ptr = |
450 make_scoped_ptr(new IsochronousTransferOutCallback(callback)); | 434 make_scoped_ptr(new IsochronousTransferOutCallback(callback)); |
451 uint8_t endpoint_address = endpoint_number; | 435 uint8_t endpoint_address = endpoint_number; |
452 scoped_refptr<net::IOBuffer> buffer = CreateTransferBuffer(data.size()); | 436 uint32_t packet_size = 0; |
453 { | 437 for (size_t i = 0; i < packets.size(); ++i) { |
454 const std::vector<uint8_t>& storage = data.storage(); | 438 packet_size = |
455 std::copy(storage.begin(), storage.end(), buffer->data()); | 439 std::max(packet_size, static_cast<uint32_t>(packets[i].size())); |
456 } | 440 } |
457 device_handle_->IsochronousTransferOut( | 441 size_t transfer_size = packet_size * packets.size(); |
458 endpoint_address, buffer, packet_lengths.storage(), timeout, | 442 scoped_refptr<net::IOBuffer> buffer = CreateTransferBuffer(transfer_size); |
| 443 memset(buffer->data(), 0, transfer_size); |
| 444 for (size_t i = 0; i < packets.size(); ++i) { |
| 445 uint8_t* packet = |
| 446 reinterpret_cast<uint8_t*>(&buffer->data()[i * packet_size]); |
| 447 DCHECK_LE(packets[i].size(), static_cast<size_t>(packet_size)); |
| 448 memcpy(packet, packets[i].storage().data(), packets[i].size()); |
| 449 } |
| 450 device_handle_->IsochronousTransfer( |
| 451 USB_DIRECTION_OUTBOUND, endpoint_address, buffer, transfer_size, |
| 452 static_cast<uint32_t>(packets.size()), packet_size, timeout, |
459 base::Bind(&OnIsochronousTransferOut, base::Passed(&callback_ptr))); | 453 base::Bind(&OnIsochronousTransferOut, base::Passed(&callback_ptr))); |
460 } | 454 } |
461 | 455 |
462 } // namespace usb | 456 } // namespace usb |
463 } // namespace device | 457 } // namespace device |
OLD | NEW |