| 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/usb/mojo/device_impl.h" | 5 #include "device/usb/mojo/device_impl.h" |
| 6 | 6 |
| 7 #include <stddef.h> | 7 #include <stddef.h> |
| 8 | 8 |
| 9 #include <algorithm> | 9 #include <algorithm> |
| 10 #include <memory> | 10 #include <memory> |
| 11 #include <numeric> | 11 #include <numeric> |
| 12 #include <utility> | 12 #include <utility> |
| 13 #include <vector> | 13 #include <vector> |
| 14 | 14 |
| 15 #include "base/bind.h" | 15 #include "base/bind.h" |
| 16 #include "base/callback.h" | 16 #include "base/callback.h" |
| 17 #include "base/memory/ptr_util.h" | 17 #include "base/memory/ptr_util.h" |
| 18 #include "base/stl_util.h" | 18 #include "base/stl_util.h" |
| 19 #include "device/usb/mojo/type_converters.h" | 19 #include "device/usb/mojo/type_converters.h" |
| 20 #include "device/usb/usb_descriptors.h" | 20 #include "device/usb/usb_descriptors.h" |
| 21 #include "device/usb/usb_device.h" | 21 #include "device/usb/usb_device.h" |
| 22 #include "mojo/common/common_type_converters.h" |
| 22 #include "net/base/io_buffer.h" | 23 #include "net/base/io_buffer.h" |
| 23 | 24 |
| 24 namespace device { | 25 namespace device { |
| 25 namespace usb { | 26 namespace usb { |
| 26 | 27 |
| 27 namespace { | 28 namespace { |
| 28 | 29 |
| 29 using MojoTransferInCallback = | |
| 30 base::Callback<void(TransferStatus, mojo::Array<uint8_t>)>; | |
| 31 | |
| 32 using MojoTransferOutCallback = base::Callback<void(TransferStatus)>; | |
| 33 | |
| 34 scoped_refptr<net::IOBuffer> CreateTransferBuffer(size_t size) { | 30 scoped_refptr<net::IOBuffer> CreateTransferBuffer(size_t size) { |
| 35 scoped_refptr<net::IOBuffer> buffer = new net::IOBuffer( | 31 return new net::IOBuffer( |
| 36 std::max(static_cast<size_t>(1u), static_cast<size_t>(size))); | 32 std::max(static_cast<size_t>(1u), static_cast<size_t>(size))); |
| 37 return buffer; | |
| 38 } | 33 } |
| 39 | 34 |
| 40 void OnTransferIn(std::unique_ptr<MojoTransferInCallback> callback, | 35 void OnTransferIn(std::unique_ptr<Device::GenericTransferInCallback> callback, |
| 41 UsbTransferStatus status, | 36 UsbTransferStatus status, |
| 42 scoped_refptr<net::IOBuffer> buffer, | 37 scoped_refptr<net::IOBuffer> buffer, |
| 43 size_t buffer_size) { | 38 size_t buffer_size) { |
| 44 mojo::Array<uint8_t> data; | 39 std::vector<uint8_t> data; |
| 45 if (buffer) { | 40 if (buffer) { |
| 46 // TODO(rockot/reillyg): We should change UsbDeviceHandle to use a | 41 // TODO(rockot/reillyg): We should change UsbDeviceHandle to use a |
| 47 // std::vector<uint8_t> instead of net::IOBuffer. Then we could move | 42 // std::vector<uint8_t> instead of net::IOBuffer. Then we could move |
| 48 // instead of copy. | 43 // instead of copy. |
| 49 std::vector<uint8_t> bytes(buffer_size); | 44 data.resize(buffer_size); |
| 50 std::copy(buffer->data(), buffer->data() + buffer_size, bytes.begin()); | 45 std::copy(buffer->data(), buffer->data() + buffer_size, data.begin()); |
| 51 data.Swap(&bytes); | |
| 52 } | 46 } |
| 53 callback->Run(mojo::ConvertTo<TransferStatus>(status), std::move(data)); | 47 callback->Run(mojo::ConvertTo<TransferStatus>(status), data); |
| 54 } | 48 } |
| 55 | 49 |
| 56 void OnTransferOut(std::unique_ptr<MojoTransferOutCallback> callback, | 50 void OnTransferOut(std::unique_ptr<Device::GenericTransferOutCallback> callback, |
| 57 UsbTransferStatus status, | 51 UsbTransferStatus status, |
| 58 scoped_refptr<net::IOBuffer> buffer, | 52 scoped_refptr<net::IOBuffer> buffer, |
| 59 size_t buffer_size) { | 53 size_t buffer_size) { |
| 60 callback->Run(mojo::ConvertTo<TransferStatus>(status)); | 54 callback->Run(mojo::ConvertTo<TransferStatus>(status)); |
| 61 } | 55 } |
| 62 | 56 |
| 63 mojo::Array<IsochronousPacketPtr> BuildIsochronousPacketArray( | 57 std::vector<IsochronousPacketPtr> BuildIsochronousPacketArray( |
| 64 mojo::Array<uint32_t> packet_lengths, | 58 const std::vector<uint32_t>& packet_lengths, |
| 65 TransferStatus status) { | 59 TransferStatus status) { |
| 66 mojo::Array<IsochronousPacketPtr> packets(packet_lengths.size()); | 60 std::vector<IsochronousPacketPtr> packets; |
| 67 for (size_t i = 0; i < packet_lengths.size(); ++i) { | 61 packets.reserve(packet_lengths.size()); |
| 68 packets[i] = IsochronousPacket::New(); | 62 for (uint32_t packet_length : packet_lengths) { |
| 69 packets[i]->length = packet_lengths[i]; | 63 auto packet = IsochronousPacket::New(); |
| 70 packets[i]->status = status; | 64 packet->length = packet_length; |
| 65 packet->status = status; |
| 66 packets.push_back(std::move(packet)); |
| 71 } | 67 } |
| 72 return packets; | 68 return packets; |
| 73 } | 69 } |
| 74 | 70 |
| 75 void OnIsochronousTransferIn( | 71 void OnIsochronousTransferIn( |
| 76 std::unique_ptr<Device::IsochronousTransferInCallback> callback, | 72 std::unique_ptr<Device::IsochronousTransferInCallback> callback, |
| 77 scoped_refptr<net::IOBuffer> buffer, | 73 scoped_refptr<net::IOBuffer> buffer, |
| 78 const std::vector<UsbDeviceHandle::IsochronousPacket>& packets) { | 74 const std::vector<UsbDeviceHandle::IsochronousPacket>& packets) { |
| 79 mojo::Array<uint8_t> data; | 75 std::vector<uint8_t> data; |
| 80 if (buffer) { | 76 if (buffer) { |
| 81 // TODO(rockot/reillyg): We should change UsbDeviceHandle to use a | 77 // TODO(rockot/reillyg): We should change UsbDeviceHandle to use a |
| 82 // std::vector<uint8_t> instead of net::IOBuffer. Then we could move | 78 // std::vector<uint8_t> instead of net::IOBuffer. Then we could move |
| 83 // instead of copy. | 79 // instead of copy. |
| 84 uint32_t buffer_size = | 80 uint32_t buffer_size = |
| 85 std::accumulate(packets.begin(), packets.end(), 0u, | 81 std::accumulate(packets.begin(), packets.end(), 0u, |
| 86 [](const uint32_t& a, | 82 [](const uint32_t& a, |
| 87 const UsbDeviceHandle::IsochronousPacket& packet) { | 83 const UsbDeviceHandle::IsochronousPacket& packet) { |
| 88 return a + packet.length; | 84 return a + packet.length; |
| 89 }); | 85 }); |
| 90 std::vector<uint8_t> bytes(buffer_size); | 86 data.resize(buffer_size); |
| 91 std::copy(buffer->data(), buffer->data() + buffer_size, bytes.begin()); | 87 std::copy(buffer->data(), buffer->data() + buffer_size, data.begin()); |
| 92 data.Swap(&bytes); | |
| 93 } | 88 } |
| 94 callback->Run(std::move(data), | 89 |
| 95 mojo::Array<IsochronousPacketPtr>::From(packets)); | 90 callback->Run(data, |
| 91 mojo::ConvertTo<std::vector<IsochronousPacketPtr>>(packets)); |
| 96 } | 92 } |
| 97 | 93 |
| 98 void OnIsochronousTransferOut( | 94 void OnIsochronousTransferOut( |
| 99 std::unique_ptr<Device::IsochronousTransferOutCallback> callback, | 95 std::unique_ptr<Device::IsochronousTransferOutCallback> callback, |
| 100 scoped_refptr<net::IOBuffer> buffer, | 96 scoped_refptr<net::IOBuffer> buffer, |
| 101 const std::vector<UsbDeviceHandle::IsochronousPacket>& packets) { | 97 const std::vector<UsbDeviceHandle::IsochronousPacket>& packets) { |
| 102 callback->Run(mojo::Array<IsochronousPacketPtr>::From(packets)); | 98 callback->Run(mojo::ConvertTo<std::vector<IsochronousPacketPtr>>(packets)); |
| 103 } | 99 } |
| 104 | 100 |
| 105 } // namespace | 101 } // namespace |
| 106 | 102 |
| 107 DeviceImpl::DeviceImpl(scoped_refptr<UsbDevice> device, | 103 DeviceImpl::DeviceImpl(scoped_refptr<UsbDevice> device, |
| 108 DeviceInfoPtr device_info, | 104 DeviceInfoPtr device_info, |
| 109 base::WeakPtr<PermissionProvider> permission_provider, | 105 base::WeakPtr<PermissionProvider> permission_provider, |
| 110 mojo::InterfaceRequest<Device> request) | 106 mojo::InterfaceRequest<Device> request) |
| 111 : device_(device), | 107 : device_(device), |
| 112 device_info_(std::move(device_info)), | 108 device_info_(std::move(device_info)), |
| (...skipping 202 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 315 } | 311 } |
| 316 | 312 |
| 317 device_handle_->ClearHalt(endpoint, callback); | 313 device_handle_->ClearHalt(endpoint, callback); |
| 318 } | 314 } |
| 319 | 315 |
| 320 void DeviceImpl::ControlTransferIn(ControlTransferParamsPtr params, | 316 void DeviceImpl::ControlTransferIn(ControlTransferParamsPtr params, |
| 321 uint32_t length, | 317 uint32_t length, |
| 322 uint32_t timeout, | 318 uint32_t timeout, |
| 323 const ControlTransferInCallback& callback) { | 319 const ControlTransferInCallback& callback) { |
| 324 if (!device_handle_) { | 320 if (!device_handle_) { |
| 325 callback.Run(TransferStatus::TRANSFER_ERROR, mojo::Array<uint8_t>()); | 321 callback.Run(TransferStatus::TRANSFER_ERROR, base::nullopt); |
| 326 return; | 322 return; |
| 327 } | 323 } |
| 328 | 324 |
| 329 if (HasControlTransferPermission(params->recipient, params->index)) { | 325 if (HasControlTransferPermission(params->recipient, params->index)) { |
| 330 scoped_refptr<net::IOBuffer> buffer = CreateTransferBuffer(length); | 326 scoped_refptr<net::IOBuffer> buffer = CreateTransferBuffer(length); |
| 331 auto callback_ptr = | 327 auto callback_ptr = |
| 332 base::WrapUnique(new ControlTransferInCallback(callback)); | 328 base::WrapUnique(new ControlTransferInCallback(callback)); |
| 333 device_handle_->ControlTransfer( | 329 device_handle_->ControlTransfer( |
| 334 USB_DIRECTION_INBOUND, | 330 USB_DIRECTION_INBOUND, |
| 335 mojo::ConvertTo<UsbDeviceHandle::TransferRequestType>(params->type), | 331 mojo::ConvertTo<UsbDeviceHandle::TransferRequestType>(params->type), |
| 336 mojo::ConvertTo<UsbDeviceHandle::TransferRecipient>(params->recipient), | 332 mojo::ConvertTo<UsbDeviceHandle::TransferRecipient>(params->recipient), |
| 337 params->request, params->value, params->index, buffer, length, timeout, | 333 params->request, params->value, params->index, buffer, length, timeout, |
| 338 base::Bind(&OnTransferIn, base::Passed(&callback_ptr))); | 334 base::Bind(&OnTransferIn, base::Passed(&callback_ptr))); |
| 339 } else { | 335 } else { |
| 340 mojo::Array<uint8_t> data; | 336 callback.Run(TransferStatus::PERMISSION_DENIED, base::nullopt); |
| 341 callback.Run(TransferStatus::PERMISSION_DENIED, std::move(data)); | |
| 342 } | 337 } |
| 343 } | 338 } |
| 344 | 339 |
| 345 void DeviceImpl::ControlTransferOut( | 340 void DeviceImpl::ControlTransferOut( |
| 346 ControlTransferParamsPtr params, | 341 ControlTransferParamsPtr params, |
| 347 mojo::Array<uint8_t> data, | 342 const std::vector<uint8_t>& data, |
| 348 uint32_t timeout, | 343 uint32_t timeout, |
| 349 const ControlTransferOutCallback& callback) { | 344 const ControlTransferOutCallback& callback) { |
| 350 if (!device_handle_) { | 345 if (!device_handle_) { |
| 351 callback.Run(TransferStatus::TRANSFER_ERROR); | 346 callback.Run(TransferStatus::TRANSFER_ERROR); |
| 352 return; | 347 return; |
| 353 } | 348 } |
| 354 | 349 |
| 355 if (HasControlTransferPermission(params->recipient, params->index)) { | 350 if (HasControlTransferPermission(params->recipient, params->index)) { |
| 356 scoped_refptr<net::IOBuffer> buffer = CreateTransferBuffer(data.size()); | 351 scoped_refptr<net::IOBuffer> buffer = CreateTransferBuffer(data.size()); |
| 357 const std::vector<uint8_t>& storage = data.storage(); | 352 std::copy(data.begin(), data.end(), buffer->data()); |
| 358 std::copy(storage.begin(), storage.end(), buffer->data()); | |
| 359 auto callback_ptr = | 353 auto callback_ptr = |
| 360 base::WrapUnique(new ControlTransferOutCallback(callback)); | 354 base::WrapUnique(new ControlTransferOutCallback(callback)); |
| 361 device_handle_->ControlTransfer( | 355 device_handle_->ControlTransfer( |
| 362 USB_DIRECTION_OUTBOUND, | 356 USB_DIRECTION_OUTBOUND, |
| 363 mojo::ConvertTo<UsbDeviceHandle::TransferRequestType>(params->type), | 357 mojo::ConvertTo<UsbDeviceHandle::TransferRequestType>(params->type), |
| 364 mojo::ConvertTo<UsbDeviceHandle::TransferRecipient>(params->recipient), | 358 mojo::ConvertTo<UsbDeviceHandle::TransferRecipient>(params->recipient), |
| 365 params->request, params->value, params->index, buffer, data.size(), | 359 params->request, params->value, params->index, buffer, data.size(), |
| 366 timeout, base::Bind(&OnTransferOut, base::Passed(&callback_ptr))); | 360 timeout, base::Bind(&OnTransferOut, base::Passed(&callback_ptr))); |
| 367 } else { | 361 } else { |
| 368 callback.Run(TransferStatus::PERMISSION_DENIED); | 362 callback.Run(TransferStatus::PERMISSION_DENIED); |
| 369 } | 363 } |
| 370 } | 364 } |
| 371 | 365 |
| 372 void DeviceImpl::GenericTransferIn(uint8_t endpoint_number, | 366 void DeviceImpl::GenericTransferIn(uint8_t endpoint_number, |
| 373 uint32_t length, | 367 uint32_t length, |
| 374 uint32_t timeout, | 368 uint32_t timeout, |
| 375 const GenericTransferInCallback& callback) { | 369 const GenericTransferInCallback& callback) { |
| 376 if (!device_handle_) { | 370 if (!device_handle_) { |
| 377 callback.Run(TransferStatus::TRANSFER_ERROR, mojo::Array<uint8_t>()); | 371 callback.Run(TransferStatus::TRANSFER_ERROR, base::nullopt); |
| 378 return; | 372 return; |
| 379 } | 373 } |
| 380 | 374 |
| 381 auto callback_ptr = base::WrapUnique(new GenericTransferInCallback(callback)); | 375 auto callback_ptr = base::WrapUnique(new GenericTransferInCallback(callback)); |
| 382 uint8_t endpoint_address = endpoint_number | 0x80; | 376 uint8_t endpoint_address = endpoint_number | 0x80; |
| 383 scoped_refptr<net::IOBuffer> buffer = CreateTransferBuffer(length); | 377 scoped_refptr<net::IOBuffer> buffer = CreateTransferBuffer(length); |
| 384 device_handle_->GenericTransfer( | 378 device_handle_->GenericTransfer( |
| 385 USB_DIRECTION_INBOUND, endpoint_address, buffer, length, timeout, | 379 USB_DIRECTION_INBOUND, endpoint_address, buffer, length, timeout, |
| 386 base::Bind(&OnTransferIn, base::Passed(&callback_ptr))); | 380 base::Bind(&OnTransferIn, base::Passed(&callback_ptr))); |
| 387 } | 381 } |
| 388 | 382 |
| 389 void DeviceImpl::GenericTransferOut( | 383 void DeviceImpl::GenericTransferOut( |
| 390 uint8_t endpoint_number, | 384 uint8_t endpoint_number, |
| 391 mojo::Array<uint8_t> data, | 385 const std::vector<uint8_t>& data, |
| 392 uint32_t timeout, | 386 uint32_t timeout, |
| 393 const GenericTransferOutCallback& callback) { | 387 const GenericTransferOutCallback& callback) { |
| 394 if (!device_handle_) { | 388 if (!device_handle_) { |
| 395 callback.Run(TransferStatus::TRANSFER_ERROR); | 389 callback.Run(TransferStatus::TRANSFER_ERROR); |
| 396 return; | 390 return; |
| 397 } | 391 } |
| 398 | 392 |
| 399 auto callback_ptr = | 393 auto callback_ptr = |
| 400 base::WrapUnique(new GenericTransferOutCallback(callback)); | 394 base::WrapUnique(new GenericTransferOutCallback(callback)); |
| 401 uint8_t endpoint_address = endpoint_number; | 395 uint8_t endpoint_address = endpoint_number; |
| 402 scoped_refptr<net::IOBuffer> buffer = CreateTransferBuffer(data.size()); | 396 scoped_refptr<net::IOBuffer> buffer = CreateTransferBuffer(data.size()); |
| 403 const std::vector<uint8_t>& storage = data.storage(); | 397 std::copy(data.begin(), data.end(), buffer->data()); |
| 404 std::copy(storage.begin(), storage.end(), buffer->data()); | |
| 405 device_handle_->GenericTransfer( | 398 device_handle_->GenericTransfer( |
| 406 USB_DIRECTION_OUTBOUND, endpoint_address, buffer, data.size(), timeout, | 399 USB_DIRECTION_OUTBOUND, endpoint_address, buffer, data.size(), timeout, |
| 407 base::Bind(&OnTransferOut, base::Passed(&callback_ptr))); | 400 base::Bind(&OnTransferOut, base::Passed(&callback_ptr))); |
| 408 } | 401 } |
| 409 | 402 |
| 410 void DeviceImpl::IsochronousTransferIn( | 403 void DeviceImpl::IsochronousTransferIn( |
| 411 uint8_t endpoint_number, | 404 uint8_t endpoint_number, |
| 412 mojo::Array<uint32_t> packet_lengths, | 405 const std::vector<uint32_t>& packet_lengths, |
| 413 uint32_t timeout, | 406 uint32_t timeout, |
| 414 const IsochronousTransferInCallback& callback) { | 407 const IsochronousTransferInCallback& callback) { |
| 415 if (!device_handle_) { | 408 if (!device_handle_) { |
| 416 callback.Run(mojo::Array<uint8_t>(), | 409 callback.Run(base::nullopt, |
| 417 BuildIsochronousPacketArray(std::move(packet_lengths), | 410 BuildIsochronousPacketArray(packet_lengths, |
| 418 TransferStatus::TRANSFER_ERROR)); | 411 TransferStatus::TRANSFER_ERROR)); |
| 419 return; | 412 return; |
| 420 } | 413 } |
| 421 | 414 |
| 422 auto callback_ptr = | 415 auto callback_ptr = |
| 423 base::WrapUnique(new IsochronousTransferInCallback(callback)); | 416 base::WrapUnique(new IsochronousTransferInCallback(callback)); |
| 424 uint8_t endpoint_address = endpoint_number | 0x80; | 417 uint8_t endpoint_address = endpoint_number | 0x80; |
| 425 device_handle_->IsochronousTransferIn( | 418 device_handle_->IsochronousTransferIn( |
| 426 endpoint_address, packet_lengths.storage(), timeout, | 419 endpoint_address, packet_lengths, timeout, |
| 427 base::Bind(&OnIsochronousTransferIn, base::Passed(&callback_ptr))); | 420 base::Bind(&OnIsochronousTransferIn, base::Passed(&callback_ptr))); |
| 428 } | 421 } |
| 429 | 422 |
| 430 void DeviceImpl::IsochronousTransferOut( | 423 void DeviceImpl::IsochronousTransferOut( |
| 431 uint8_t endpoint_number, | 424 uint8_t endpoint_number, |
| 432 mojo::Array<uint8_t> data, | 425 const std::vector<uint8_t>& data, |
| 433 mojo::Array<uint32_t> packet_lengths, | 426 const std::vector<uint32_t>& packet_lengths, |
| 434 uint32_t timeout, | 427 uint32_t timeout, |
| 435 const IsochronousTransferOutCallback& callback) { | 428 const IsochronousTransferOutCallback& callback) { |
| 436 if (!device_handle_) { | 429 if (!device_handle_) { |
| 437 callback.Run(BuildIsochronousPacketArray(std::move(packet_lengths), | 430 callback.Run(BuildIsochronousPacketArray(packet_lengths, |
| 438 TransferStatus::TRANSFER_ERROR)); | 431 TransferStatus::TRANSFER_ERROR)); |
| 439 return; | 432 return; |
| 440 } | 433 } |
| 441 | 434 |
| 442 auto callback_ptr = | 435 auto callback_ptr = |
| 443 base::WrapUnique(new IsochronousTransferOutCallback(callback)); | 436 base::WrapUnique(new IsochronousTransferOutCallback(callback)); |
| 444 uint8_t endpoint_address = endpoint_number; | 437 uint8_t endpoint_address = endpoint_number; |
| 445 scoped_refptr<net::IOBuffer> buffer = CreateTransferBuffer(data.size()); | 438 scoped_refptr<net::IOBuffer> buffer = CreateTransferBuffer(data.size()); |
| 446 { | 439 std::copy(data.begin(), data.end(), buffer->data()); |
| 447 const std::vector<uint8_t>& storage = data.storage(); | |
| 448 std::copy(storage.begin(), storage.end(), buffer->data()); | |
| 449 } | |
| 450 device_handle_->IsochronousTransferOut( | 440 device_handle_->IsochronousTransferOut( |
| 451 endpoint_address, buffer, packet_lengths.storage(), timeout, | 441 endpoint_address, buffer, packet_lengths, timeout, |
| 452 base::Bind(&OnIsochronousTransferOut, base::Passed(&callback_ptr))); | 442 base::Bind(&OnIsochronousTransferOut, base::Passed(&callback_ptr))); |
| 453 } | 443 } |
| 454 | 444 |
| 455 void DeviceImpl::OnDeviceRemoved(scoped_refptr<UsbDevice> device) { | 445 void DeviceImpl::OnDeviceRemoved(scoped_refptr<UsbDevice> device) { |
| 456 DCHECK_EQ(device_, device); | 446 DCHECK_EQ(device_, device); |
| 457 delete this; | 447 delete this; |
| 458 } | 448 } |
| 459 | 449 |
| 460 } // namespace usb | 450 } // namespace usb |
| 461 } // namespace device | 451 } // namespace device |
| OLD | NEW |