Commit 5911ee14 authored by Reilly Grant's avatar Reilly Grant Committed by Commit Bot

Switch //services/device/hid to use base::RefCountedBytes

This patch changes //services/device/hid to use base::RefCountedBytes
instead of net::IOBuffer and net::IOBufferWithSize. This has a couple
advantages:

1) base::RefCountedBytes always has a size which means in a follow-up
   patch we can stop passing separate length parameters.

2) base::RefCountedBytes is convertable to and from an
   std::vector<uint8_t> which reduces the mismatch between the C++ and
   Mojo interfaces.

3) base::RefCountedBytes holds unsigned data which is more correct for
   managing buffers (operations on signed values lead to bugs).

This patch makes as few changes as possible to effect this conversion.
Follow-up patches will take more advantage of the above to further
simplify the code.

Change-Id: I290b0415f74c0551f52bd59120a3c6012315681d
Reviewed-on: https://chromium-review.googlesource.com/798018
Commit-Queue: Reilly Grant <reillyg@chromium.org>
Reviewed-by: default avatarJun Cai <juncai@chromium.org>
Cr-Commit-Position: refs/heads/master@{#524230}
parent 7ed8d6eb
......@@ -37,7 +37,6 @@ source_set("hid") {
"//base",
"//components/device_event_log",
"//device/base",
"//net",
"//services/device/public/cpp/hid",
"//services/device/public/interfaces",
]
......@@ -76,6 +75,7 @@ source_set("mocks") {
public_deps = [
":hid",
"//base",
]
}
......
include_rules = [
"+chromeos/dbus",
"+components/device_event_log",
"+net/base",
]
......@@ -6,6 +6,7 @@
#include <algorithm>
#include "base/memory/ref_counted_memory.h"
#include "base/stl_util.h"
#include "components/device_event_log/device_event_log.h"
#include "services/device/public/cpp/hid/hid_usage_and_page.h"
......@@ -92,7 +93,7 @@ void HidConnection::Read(ReadCallback callback) {
PlatformRead(std::move(callback));
}
void HidConnection::Write(scoped_refptr<net::IOBuffer> buffer,
void HidConnection::Write(scoped_refptr<base::RefCountedBytes> buffer,
size_t size,
WriteCallback callback) {
DCHECK(thread_checker_.CalledOnValidThread());
......@@ -144,9 +145,10 @@ void HidConnection::GetFeatureReport(uint8_t report_id, ReadCallback callback) {
PlatformGetFeatureReport(report_id, std::move(callback));
}
void HidConnection::SendFeatureReport(scoped_refptr<net::IOBuffer> buffer,
size_t size,
WriteCallback callback) {
void HidConnection::SendFeatureReport(
scoped_refptr<base::RefCountedBytes> buffer,
size_t size,
WriteCallback callback) {
DCHECK(thread_checker_.CalledOnValidThread());
if (device_info_->max_feature_report_size() == 0) {
HID_LOG(USER) << "This device does not support feature reports.";
......
......@@ -8,13 +8,16 @@
#include <stddef.h>
#include <stdint.h>
#include "base/callback.h"
#include "base/callback_forward.h"
#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "base/threading/thread_checker.h"
#include "net/base/io_buffer.h"
#include "services/device/hid/hid_device_info.h"
namespace base {
class RefCountedBytes;
}
namespace device {
class HidConnection : public base::RefCountedThreadSafe<HidConnection> {
......@@ -24,8 +27,10 @@ class HidConnection : public base::RefCountedThreadSafe<HidConnection> {
kAnyReportId = 0xFF,
};
using ReadCallback = base::OnceCallback<
void(bool success, scoped_refptr<net::IOBuffer> buffer, size_t size)>;
using ReadCallback =
base::OnceCallback<void(bool success,
scoped_refptr<base::RefCountedBytes> buffer,
size_t size)>;
using WriteCallback = base::OnceCallback<void(bool success)>;
......@@ -43,7 +48,7 @@ class HidConnection : public base::RefCountedThreadSafe<HidConnection> {
// The report ID (or 0 if report IDs are not supported by the device) is
// always expected in the first byte of the buffer.
void Write(scoped_refptr<net::IOBuffer> buffer,
void Write(scoped_refptr<base::RefCountedBytes> buffer,
size_t size,
WriteCallback callback);
......@@ -54,7 +59,7 @@ class HidConnection : public base::RefCountedThreadSafe<HidConnection> {
// The report ID (or 0 if report IDs are not supported by the device) is
// always expected in the first byte of the buffer.
void SendFeatureReport(scoped_refptr<net::IOBuffer> buffer,
void SendFeatureReport(scoped_refptr<base::RefCountedBytes> buffer,
size_t size,
WriteCallback callback);
......@@ -66,14 +71,15 @@ class HidConnection : public base::RefCountedThreadSafe<HidConnection> {
virtual void PlatformClose() = 0;
virtual void PlatformRead(ReadCallback callback) = 0;
virtual void PlatformWrite(scoped_refptr<net::IOBuffer> buffer,
virtual void PlatformWrite(scoped_refptr<base::RefCountedBytes> buffer,
size_t size,
WriteCallback callback) = 0;
virtual void PlatformGetFeatureReport(uint8_t report_id,
ReadCallback callback) = 0;
virtual void PlatformSendFeatureReport(scoped_refptr<net::IOBuffer> buffer,
size_t size,
WriteCallback callback) = 0;
virtual void PlatformSendFeatureReport(
scoped_refptr<base::RefCountedBytes> buffer,
size_t size,
WriteCallback callback) = 0;
bool IsReportIdProtected(uint8_t report_id);
......@@ -91,7 +97,7 @@ struct PendingHidReport {
PendingHidReport(const PendingHidReport& other);
~PendingHidReport();
scoped_refptr<net::IOBuffer> buffer;
scoped_refptr<base::RefCountedBytes> buffer;
size_t size;
};
......
......@@ -6,6 +6,7 @@
#include "base/bind.h"
#include "base/memory/ptr_util.h"
#include "base/memory/ref_counted_memory.h"
namespace device {
......@@ -30,7 +31,7 @@ void HidConnectionImpl::Read(ReadCallback callback) {
void HidConnectionImpl::OnRead(ReadCallback callback,
bool success,
scoped_refptr<net::IOBuffer> buffer,
scoped_refptr<base::RefCountedBytes> buffer,
size_t size) {
if (!success) {
std::move(callback).Run(false, 0, base::nullopt);
......@@ -38,7 +39,7 @@ void HidConnectionImpl::OnRead(ReadCallback callback,
}
DCHECK(buffer);
std::vector<uint8_t> data(buffer->data() + 1, buffer->data() + size);
std::vector<uint8_t> data(buffer->front() + 1, buffer->front() + size);
std::move(callback).Run(true, buffer->data()[0], data);
}
......@@ -48,11 +49,10 @@ void HidConnectionImpl::Write(uint8_t report_id,
DCHECK(hid_connection_);
auto io_buffer =
base::MakeRefCounted<net::IOBufferWithSize>(buffer.size() + 1);
base::MakeRefCounted<base::RefCountedBytes>(buffer.size() + 1);
io_buffer->data()[0] = report_id;
const char* data = reinterpret_cast<const char*>(buffer.data());
memcpy(io_buffer->data() + 1, data, buffer.size());
memcpy(io_buffer->front() + 1, buffer.data(), buffer.size());
hid_connection_->Write(
io_buffer, io_buffer->size(),
......@@ -73,17 +73,18 @@ void HidConnectionImpl::GetFeatureReport(uint8_t report_id,
weak_factory_.GetWeakPtr(), std::move(callback)));
}
void HidConnectionImpl::OnGetFeatureReport(GetFeatureReportCallback callback,
bool success,
scoped_refptr<net::IOBuffer> buffer,
size_t size) {
void HidConnectionImpl::OnGetFeatureReport(
GetFeatureReportCallback callback,
bool success,
scoped_refptr<base::RefCountedBytes> buffer,
size_t size) {
if (!success) {
std::move(callback).Run(false, base::nullopt);
return;
}
DCHECK(buffer);
std::vector<uint8_t> data(buffer->data(), buffer->data() + size);
std::vector<uint8_t> data(buffer->front(), buffer->front() + size);
std::move(callback).Run(true, data);
}
......@@ -93,11 +94,10 @@ void HidConnectionImpl::SendFeatureReport(uint8_t report_id,
DCHECK(hid_connection_);
auto io_buffer =
base::MakeRefCounted<net::IOBufferWithSize>(buffer.size() + 1);
base::MakeRefCounted<base::RefCountedBytes>(buffer.size() + 1);
io_buffer->data()[0] = report_id;
const char* data = reinterpret_cast<const char*>(buffer.data());
memcpy(io_buffer->data() + 1, data, buffer.size());
memcpy(io_buffer->front() + 1, buffer.data(), buffer.size());
hid_connection_->SendFeatureReport(
io_buffer, io_buffer->size(),
......
......@@ -6,7 +6,6 @@
#define DEVICE_HID_HID_CONNECTION_IMPL_H_
#include "base/memory/ref_counted.h"
#include "net/base/io_buffer.h"
#include "services/device/hid/hid_connection.h"
#include "services/device/public/interfaces/hid.mojom.h"
......@@ -34,12 +33,12 @@ class HidConnectionImpl : public mojom::HidConnection {
private:
void OnRead(ReadCallback callback,
bool success,
scoped_refptr<net::IOBuffer> buffer,
scoped_refptr<base::RefCountedBytes> buffer,
size_t size);
void OnWrite(WriteCallback callback, bool success);
void OnGetFeatureReport(GetFeatureReportCallback callback,
bool success,
scoped_refptr<net::IOBuffer> buffer,
scoped_refptr<base::RefCountedBytes> buffer,
size_t size);
void OnSendFeatureReport(SendFeatureReportCallback callback, bool success);
......
......@@ -16,6 +16,7 @@
#include "base/files/file_descriptor_watcher_posix.h"
#include "base/macros.h"
#include "base/memory/ptr_util.h"
#include "base/memory/ref_counted_memory.h"
#include "base/posix/eintr_wrapper.h"
#include "base/threading/thread_restrictions.h"
#include "base/threading/thread_task_runner_handle.h"
......@@ -59,11 +60,11 @@ class HidConnectionLinux::BlockingTaskHelper {
base::Unretained(this)));
}
void Write(scoped_refptr<net::IOBuffer> buffer,
void Write(scoped_refptr<base::RefCountedBytes> buffer,
size_t size,
WriteCallback callback) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
ssize_t result = HANDLE_EINTR(write(fd_.get(), buffer->data(), size));
ssize_t result = HANDLE_EINTR(write(fd_.get(), buffer->front(), size));
if (result < 0) {
HID_PLOG(EVENT) << "Write failed";
origin_task_runner_->PostTask(FROM_HERE,
......@@ -77,11 +78,11 @@ class HidConnectionLinux::BlockingTaskHelper {
}
void GetFeatureReport(uint8_t report_id,
scoped_refptr<net::IOBufferWithSize> buffer,
scoped_refptr<base::RefCountedBytes> buffer,
ReadCallback callback) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
int result = HANDLE_EINTR(
ioctl(fd_.get(), HIDIOCGFEATURE(buffer->size()), buffer->data()));
ioctl(fd_.get(), HIDIOCGFEATURE(buffer->size()), buffer->front()));
if (result < 0) {
HID_PLOG(EVENT) << "Failed to get feature report";
origin_task_runner_->PostTask(
......@@ -92,8 +93,9 @@ class HidConnectionLinux::BlockingTaskHelper {
FROM_HERE, base::BindOnce(std::move(callback), false, nullptr, 0));
} else if (report_id == 0) {
// Linux adds a 0 to the beginning of the data received from the device.
scoped_refptr<net::IOBuffer> copied_buffer(new net::IOBuffer(result - 1));
memcpy(copied_buffer->data(), buffer->data() + 1, result - 1);
auto copied_buffer =
base::MakeRefCounted<base::RefCountedBytes>(result - 1);
memcpy(copied_buffer->front(), buffer->front() + 1, result - 1);
origin_task_runner_->PostTask(
FROM_HERE,
base::BindOnce(std::move(callback), true, copied_buffer, result - 1));
......@@ -103,12 +105,12 @@ class HidConnectionLinux::BlockingTaskHelper {
}
}
void SendFeatureReport(scoped_refptr<net::IOBuffer> buffer,
void SendFeatureReport(scoped_refptr<base::RefCountedBytes> buffer,
size_t size,
WriteCallback callback) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
int result =
HANDLE_EINTR(ioctl(fd_.get(), HIDIOCSFEATURE(size), buffer->data()));
HANDLE_EINTR(ioctl(fd_.get(), HIDIOCSFEATURE(size), buffer->front()));
if (result < 0) {
HID_PLOG(EVENT) << "Failed to send feature report";
origin_task_runner_->PostTask(FROM_HERE,
......@@ -123,8 +125,9 @@ class HidConnectionLinux::BlockingTaskHelper {
void OnFileCanReadWithoutBlocking() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
scoped_refptr<net::IOBuffer> buffer(new net::IOBuffer(report_buffer_size_));
char* data = buffer->data();
auto buffer =
base::MakeRefCounted<base::RefCountedBytes>(report_buffer_size_);
uint8_t* data = buffer->front();
size_t length = report_buffer_size_;
if (!has_report_id_) {
// Linux will not prefix the buffer with a report ID if report IDs are not
......@@ -205,9 +208,10 @@ void HidConnectionLinux::PlatformRead(ReadCallback callback) {
ProcessReadQueue();
}
void HidConnectionLinux::PlatformWrite(scoped_refptr<net::IOBuffer> buffer,
size_t size,
WriteCallback callback) {
void HidConnectionLinux::PlatformWrite(
scoped_refptr<base::RefCountedBytes> buffer,
size_t size,
WriteCallback callback) {
// Linux expects the first byte of the buffer to always be a report ID so the
// buffer can be used directly.
blocking_task_runner_->PostTask(
......@@ -221,8 +225,8 @@ void HidConnectionLinux::PlatformGetFeatureReport(uint8_t report_id,
// The first byte of the destination buffer is the report ID being requested
// and is overwritten by the feature report.
DCHECK_GT(device_info()->max_feature_report_size(), 0u);
scoped_refptr<net::IOBufferWithSize> buffer(
new net::IOBufferWithSize(device_info()->max_feature_report_size() + 1));
auto buffer = base::MakeRefCounted<base::RefCountedBytes>(
device_info()->max_feature_report_size() + 1);
buffer->data()[0] = report_id;
blocking_task_runner_->PostTask(
......@@ -232,7 +236,7 @@ void HidConnectionLinux::PlatformGetFeatureReport(uint8_t report_id,
}
void HidConnectionLinux::PlatformSendFeatureReport(
scoped_refptr<net::IOBuffer> buffer,
scoped_refptr<base::RefCountedBytes> buffer,
size_t size,
WriteCallback callback) {
// Linux expects the first byte of the buffer to always be a report ID so the
......@@ -243,8 +247,9 @@ void HidConnectionLinux::PlatformSendFeatureReport(
std::move(callback)));
}
void HidConnectionLinux::ProcessInputReport(scoped_refptr<net::IOBuffer> buffer,
size_t size) {
void HidConnectionLinux::ProcessInputReport(
scoped_refptr<base::RefCountedBytes> buffer,
size_t size) {
DCHECK(thread_checker().CalledOnValidThread());
DCHECK_GE(size, 1u);
......
......@@ -37,16 +37,17 @@ class HidConnectionLinux : public HidConnection {
// HidConnection implementation.
void PlatformClose() override;
void PlatformRead(ReadCallback callback) override;
void PlatformWrite(scoped_refptr<net::IOBuffer> buffer,
void PlatformWrite(scoped_refptr<base::RefCountedBytes> buffer,
size_t size,
WriteCallback callback) override;
void PlatformGetFeatureReport(uint8_t report_id,
ReadCallback callback) override;
void PlatformSendFeatureReport(scoped_refptr<net::IOBuffer> buffer,
void PlatformSendFeatureReport(scoped_refptr<base::RefCountedBytes> buffer,
size_t size,
WriteCallback callback) override;
void ProcessInputReport(scoped_refptr<net::IOBuffer> buffer, size_t size);
void ProcessInputReport(scoped_refptr<base::RefCountedBytes> buffer,
size_t size);
void ProcessReadQueue();
// |helper_| lives on the sequence to which |blocking_task_runner_| posts
......
......@@ -7,6 +7,7 @@
#include "base/bind.h"
#include "base/location.h"
#include "base/mac/foundation_util.h"
#include "base/memory/ref_counted_memory.h"
#include "base/numerics/safe_math.h"
#include "base/single_thread_task_runner.h"
#include "base/strings/stringprintf.h"
......@@ -80,9 +81,10 @@ void HidConnectionMac::PlatformRead(ReadCallback callback) {
ProcessReadQueue();
}
void HidConnectionMac::PlatformWrite(scoped_refptr<net::IOBuffer> buffer,
size_t size,
WriteCallback callback) {
void HidConnectionMac::PlatformWrite(
scoped_refptr<base::RefCountedBytes> buffer,
size_t size,
WriteCallback callback) {
blocking_task_runner_->PostTask(
FROM_HERE, base::BindOnce(&HidConnectionMac::SetReportAsync, this,
kIOHIDReportTypeOutput, buffer, size,
......@@ -97,7 +99,7 @@ void HidConnectionMac::PlatformGetFeatureReport(uint8_t report_id,
}
void HidConnectionMac::PlatformSendFeatureReport(
scoped_refptr<net::IOBuffer> buffer,
scoped_refptr<base::RefCountedBytes> buffer,
size_t size,
WriteCallback callback) {
blocking_task_runner_->PostTask(
......@@ -120,26 +122,25 @@ void HidConnectionMac::InputReportCallback(void* context,
return;
}
scoped_refptr<net::IOBufferWithSize> buffer;
scoped_refptr<base::RefCountedBytes> buffer;
if (connection->device_info()->has_report_id()) {
// report_id is already contained in report_bytes
buffer =
new net::IOBufferWithSize(base::checked_cast<size_t>(report_length));
memcpy(buffer->data(), report_bytes, report_length);
buffer = base::MakeRefCounted<base::RefCountedBytes>(
report_bytes, base::checked_cast<size_t>(report_length));
} else {
buffer = new net::IOBufferWithSize(static_cast<size_t>(
(base::CheckedNumeric<size_t>(report_length) + 1).ValueOrDie()));
buffer->data()[0] = 0;
memcpy(buffer->data() + 1, report_bytes, report_length);
buffer = base::MakeRefCounted<base::RefCountedBytes>(
(base::CheckedNumeric<size_t>(report_length) + 1).ValueOrDie());
buffer->front()[0] = 0;
memcpy(buffer->front() + 1, report_bytes, report_length);
}
connection->ProcessInputReport(buffer);
}
void HidConnectionMac::ProcessInputReport(
scoped_refptr<net::IOBufferWithSize> buffer) {
scoped_refptr<base::RefCountedBytes> buffer) {
DCHECK(thread_checker().CalledOnValidThread());
DCHECK_GE(buffer->size(), 1);
DCHECK_GE(buffer->size(), 1u);
uint8_t report_id = buffer->data()[0];
if (IsReportIdProtected(report_id))
......@@ -170,8 +171,8 @@ void HidConnectionMac::ProcessReadQueue() {
void HidConnectionMac::GetFeatureReportAsync(uint8_t report_id,
ReadCallback callback) {
scoped_refptr<net::IOBufferWithSize> buffer(
new net::IOBufferWithSize(device_info()->max_feature_report_size() + 1));
auto buffer = base::MakeRefCounted<base::RefCountedBytes>(
device_info()->max_feature_report_size() + 1);
CFIndex report_size = buffer->size();
// The IOHIDDevice object is shared with the UI thread and so this function
......@@ -179,9 +180,9 @@ void HidConnectionMac::GetFeatureReportAsync(uint8_t report_id,
// version is NOT IMPLEMENTED. I've examined the open source implementation
// of this function and believe it is a simple enough wrapper around the
// kernel API that this is safe.
IOReturn result = IOHIDDeviceGetReport(
device_.get(), kIOHIDReportTypeFeature, report_id,
reinterpret_cast<uint8_t*>(buffer->data()), &report_size);
IOReturn result =
IOHIDDeviceGetReport(device_.get(), kIOHIDReportTypeFeature, report_id,
buffer->front(), &report_size);
if (result == kIOReturnSuccess) {
task_runner_->PostTask(
FROM_HERE, base::BindOnce(&HidConnectionMac::ReturnAsyncResult, this,
......@@ -196,11 +197,12 @@ void HidConnectionMac::GetFeatureReportAsync(uint8_t report_id,
}
}
void HidConnectionMac::SetReportAsync(IOHIDReportType report_type,
scoped_refptr<net::IOBuffer> buffer,
size_t size,
WriteCallback callback) {
uint8_t* data = reinterpret_cast<uint8_t*>(buffer->data());
void HidConnectionMac::SetReportAsync(
IOHIDReportType report_type,
scoped_refptr<base::RefCountedBytes> buffer,
size_t size,
WriteCallback callback) {
uint8_t* data = buffer->front();
DCHECK_GE(size, 1u);
uint8_t report_id = data[0];
if (report_id == 0) {
......
......@@ -19,10 +19,6 @@ namespace base {
class SequencedTaskRunner;
}
namespace net {
class IOBuffer;
}
namespace device {
class HidConnectionMac : public HidConnection {
......@@ -36,12 +32,12 @@ class HidConnectionMac : public HidConnection {
// HidConnection implementation.
void PlatformClose() override;
void PlatformRead(ReadCallback callback) override;
void PlatformWrite(scoped_refptr<net::IOBuffer> buffer,
void PlatformWrite(scoped_refptr<base::RefCountedBytes> buffer,
size_t size,
WriteCallback callback) override;
void PlatformGetFeatureReport(uint8_t report_id,
ReadCallback callback) override;
void PlatformSendFeatureReport(scoped_refptr<net::IOBuffer> buffer,
void PlatformSendFeatureReport(scoped_refptr<base::RefCountedBytes> buffer,
size_t size,
WriteCallback callback) override;
......@@ -52,11 +48,11 @@ class HidConnectionMac : public HidConnection {
uint32_t report_id,
uint8_t* report_bytes,
CFIndex report_length);
void ProcessInputReport(scoped_refptr<net::IOBufferWithSize> buffer);
void ProcessInputReport(scoped_refptr<base::RefCountedBytes> buffer);
void ProcessReadQueue();
void GetFeatureReportAsync(uint8_t report_id, ReadCallback callback);
void SetReportAsync(IOHIDReportType report_type,
scoped_refptr<net::IOBuffer> buffer,
scoped_refptr<base::RefCountedBytes> buffer,
size_t size,
WriteCallback callback);
void ReturnAsyncResult(base::OnceClosure callback);
......
......@@ -12,6 +12,7 @@
#include "base/bind.h"
#include "base/callback.h"
#include "base/memory/ref_counted_memory.h"
#include "base/run_loop.h"
#include "base/scoped_observer.h"
#include "base/strings/utf_string_conversions.h"
......@@ -19,7 +20,6 @@
#include "base/test/test_io_thread.h"
#include "device/test/usb_test_gadget.h"
#include "device/usb/usb_device.h"
#include "net/base/io_buffer.h"
#include "services/device/hid/hid_service.h"
#include "services/device/public/interfaces/hid.mojom.h"
#include "testing/gtest/include/gtest/gtest.h"
......@@ -28,8 +28,6 @@ namespace device {
namespace {
using net::IOBufferWithSize;
// Helper class that can be used to block until a HID device with a particular
// serial number is available. Example usage:
//
......@@ -109,7 +107,7 @@ class TestIoCallback {
~TestIoCallback() {}
void SetReadResult(bool success,
scoped_refptr<net::IOBuffer> buffer,
scoped_refptr<base::RefCountedBytes> buffer,
size_t size) {
result_ = success;
buffer_ = buffer;
......@@ -135,14 +133,14 @@ class TestIoCallback {
return base::BindOnce(&TestIoCallback::SetWriteResult,
base::Unretained(this));
}
scoped_refptr<net::IOBuffer> buffer() const { return buffer_; }
scoped_refptr<base::RefCountedBytes> buffer() const { return buffer_; }
size_t size() const { return size_; }
private:
base::RunLoop run_loop_;
bool result_;
size_t size_;
scoped_refptr<net::IOBuffer> buffer_;
scoped_refptr<base::RefCountedBytes> buffer_;
};
} // namespace
......@@ -190,7 +188,7 @@ TEST_F(HidConnectionTest, ReadWrite) {
const char kBufferSize = 9;
for (char i = 0; i < 8; ++i) {
scoped_refptr<IOBufferWithSize> buffer(new IOBufferWithSize(kBufferSize));
auto buffer = base::MakeRefCounted<base::RefCountedBytes>(kBufferSize);
buffer->data()[0] = 0;
for (unsigned char j = 1; j < kBufferSize; ++j) {
buffer->data()[j] = i + j - 1;
......
......@@ -11,6 +11,7 @@
#include "base/files/file.h"
#include "base/macros.h"
#include "base/memory/ptr_util.h"
#include "base/memory/ref_counted_memory.h"
#include "base/numerics/safe_conversions.h"
#include "base/win/object_watcher.h"
#include "components/device_event_log/device_event_log.h"
......@@ -33,7 +34,8 @@ class PendingHidTransfer : public base::win::ObjectWatcher::Delegate {
public:
typedef base::OnceCallback<void(PendingHidTransfer*, bool)> Callback;
PendingHidTransfer(scoped_refptr<net::IOBuffer> buffer, Callback callback);
PendingHidTransfer(scoped_refptr<base::RefCountedBytes> buffer,
Callback callback);
~PendingHidTransfer() override;
void TakeResultFromWindowsAPI(BOOL result);
......@@ -46,7 +48,7 @@ class PendingHidTransfer : public base::win::ObjectWatcher::Delegate {
private:
// The buffer isn't used by this object but it's important that a reference
// to it is held until the transfer completes.
scoped_refptr<net::IOBuffer> buffer_;
scoped_refptr<base::RefCountedBytes> buffer_;
Callback callback_;
OVERLAPPED overlapped_;
base::win::ScopedHandle event_;
......@@ -55,8 +57,9 @@ class PendingHidTransfer : public base::win::ObjectWatcher::Delegate {
DISALLOW_COPY_AND_ASSIGN(PendingHidTransfer);
};
PendingHidTransfer::PendingHidTransfer(scoped_refptr<net::IOBuffer> buffer,
PendingHidTransfer::Callback callback)
PendingHidTransfer::PendingHidTransfer(
scoped_refptr<base::RefCountedBytes> buffer,
PendingHidTransfer::Callback callback)
: buffer_(buffer),
callback_(std::move(callback)),
event_(CreateEvent(NULL, FALSE, FALSE, NULL)) {
......@@ -102,29 +105,29 @@ void HidConnectionWin::PlatformClose() {
void HidConnectionWin::PlatformRead(HidConnection::ReadCallback callback) {
// Windows will always include the report ID (including zero if report IDs
// are not in use) in the buffer.
scoped_refptr<net::IOBufferWithSize> buffer = new net::IOBufferWithSize(
base::checked_cast<int>(device_info()->max_input_report_size() + 1));
auto buffer = base::MakeRefCounted<base::RefCountedBytes>(
device_info()->max_input_report_size() + 1);
transfers_.push_back(std::make_unique<PendingHidTransfer>(
buffer, base::BindOnce(&HidConnectionWin::OnReadComplete, this, buffer,
std::move(callback))));
transfers_.back()->TakeResultFromWindowsAPI(
ReadFile(file_.Get(), buffer->data(), static_cast<DWORD>(buffer->size()),
ReadFile(file_.Get(), buffer->front(), static_cast<DWORD>(buffer->size()),
NULL, transfers_.back()->GetOverlapped()));
}
void HidConnectionWin::PlatformWrite(scoped_refptr<net::IOBuffer> buffer,
size_t size,
WriteCallback callback) {
void HidConnectionWin::PlatformWrite(
scoped_refptr<base::RefCountedBytes> buffer,
size_t size,
WriteCallback callback) {
size_t expected_size = device_info()->max_output_report_size() + 1;
DCHECK(size <= expected_size);
// The Windows API always wants either a report ID (if supported) or zero at
// the front of every output report and requires that the buffer size be equal
// to the maximum output report size supported by this collection.
if (size < expected_size) {
scoped_refptr<net::IOBuffer> tmp_buffer =
new net::IOBuffer(base::checked_cast<int>(expected_size));
memcpy(tmp_buffer->data(), buffer->data(), size);
memset(tmp_buffer->data() + size, 0, expected_size - size);
auto tmp_buffer =
base::MakeRefCounted<base::RefCountedBytes>(expected_size);
memcpy(tmp_buffer->front(), buffer->front(), size);
buffer = tmp_buffer;
size = expected_size;
}
......@@ -132,15 +135,15 @@ void HidConnectionWin::PlatformWrite(scoped_refptr<net::IOBuffer> buffer,
buffer, base::BindOnce(&HidConnectionWin::OnWriteComplete, this,
std::move(callback))));
transfers_.back()->TakeResultFromWindowsAPI(
WriteFile(file_.Get(), buffer->data(), static_cast<DWORD>(size), NULL,
WriteFile(file_.Get(), buffer->front(), static_cast<DWORD>(size), NULL,
transfers_.back()->GetOverlapped()));
}
void HidConnectionWin::PlatformGetFeatureReport(uint8_t report_id,
ReadCallback callback) {
// The first byte of the destination buffer is the report ID being requested.
scoped_refptr<net::IOBufferWithSize> buffer = new net::IOBufferWithSize(
base::checked_cast<int>(device_info()->max_feature_report_size() + 1));
auto buffer = base::MakeRefCounted<base::RefCountedBytes>(
device_info()->max_feature_report_size() + 1);
buffer->data()[0] = report_id;
transfers_.push_back(std::make_unique<PendingHidTransfer>(
......@@ -148,12 +151,12 @@ void HidConnectionWin::PlatformGetFeatureReport(uint8_t report_id,
buffer, std::move(callback))));
transfers_.back()->TakeResultFromWindowsAPI(
DeviceIoControl(file_.Get(), IOCTL_HID_GET_FEATURE, NULL, 0,
buffer->data(), static_cast<DWORD>(buffer->size()), NULL,
buffer->front(), static_cast<DWORD>(buffer->size()), NULL,
transfers_.back()->GetOverlapped()));
}
void HidConnectionWin::PlatformSendFeatureReport(
scoped_refptr<net::IOBuffer> buffer,
scoped_refptr<base::RefCountedBytes> buffer,
size_t size,
WriteCallback callback) {
// The Windows API always wants either a report ID (if supported) or
......@@ -162,15 +165,16 @@ void HidConnectionWin::PlatformSendFeatureReport(
buffer, base::BindOnce(&HidConnectionWin::OnWriteComplete, this,
std::move(callback))));
transfers_.back()->TakeResultFromWindowsAPI(
DeviceIoControl(file_.Get(), IOCTL_HID_SET_FEATURE, buffer->data(),
DeviceIoControl(file_.Get(), IOCTL_HID_SET_FEATURE, buffer->front(),
static_cast<DWORD>(size), NULL, 0, NULL,
transfers_.back()->GetOverlapped()));
}
void HidConnectionWin::OnReadComplete(scoped_refptr<net::IOBuffer> buffer,
ReadCallback callback,
PendingHidTransfer* transfer_raw,
bool signaled) {
void HidConnectionWin::OnReadComplete(
scoped_refptr<base::RefCountedBytes> buffer,
ReadCallback callback,
PendingHidTransfer* transfer_raw,
bool signaled) {
if (!file_.IsValid()) {
std::move(callback).Run(false, nullptr, 0);
return;
......@@ -201,7 +205,7 @@ void HidConnectionWin::OnReadComplete(scoped_refptr<net::IOBuffer> buffer,
}
void HidConnectionWin::OnReadFeatureComplete(
scoped_refptr<net::IOBuffer> buffer,
scoped_refptr<base::RefCountedBytes> buffer,
ReadCallback callback,
PendingHidTransfer* transfer_raw,
bool signaled) {
......
......@@ -33,20 +33,20 @@ class HidConnectionWin : public HidConnection {
// HidConnection implementation.
void PlatformClose() override;
void PlatformRead(ReadCallback callback) override;
void PlatformWrite(scoped_refptr<net::IOBuffer> buffer,
void PlatformWrite(scoped_refptr<base::RefCountedBytes> buffer,
size_t size,
WriteCallback callback) override;
void PlatformGetFeatureReport(uint8_t report_id,
ReadCallback callback) override;
void PlatformSendFeatureReport(scoped_refptr<net::IOBuffer> buffer,
void PlatformSendFeatureReport(scoped_refptr<base::RefCountedBytes> buffer,
size_t size,
WriteCallback callback) override;
void OnReadComplete(scoped_refptr<net::IOBuffer> buffer,
void OnReadComplete(scoped_refptr<base::RefCountedBytes> buffer,
ReadCallback callback,
PendingHidTransfer* transfer,
bool signaled);
void OnReadFeatureComplete(scoped_refptr<net::IOBuffer> buffer,
void OnReadFeatureComplete(scoped_refptr<base::RefCountedBytes> buffer,
ReadCallback callback,
PendingHidTransfer* transfer,
bool signaled);
......
......@@ -25,7 +25,6 @@
#include "base/task_scheduler/post_task.h"
#include "base/threading/sequenced_task_runner_handle.h"
#include "components/device_event_log/device_event_log.h"
#include "net/base/io_buffer.h"
#include "services/device/hid/hid_connection_win.h"
#include "services/device/hid/hid_device_info.h"
......
......@@ -3,6 +3,8 @@
// found in the LICENSE file.
#include "services/device/hid/mock_hid_connection.h"
#include "base/memory/ref_counted_memory.h"
#include "services/device/hid/hid_device_info.h"
namespace device {
......@@ -16,30 +18,30 @@ MockHidConnection::~MockHidConnection() {}
void MockHidConnection::PlatformClose() {}
void MockHidConnection::PlatformRead(ReadCallback callback) {
const char data[] = "TestRead";
auto buffer = base::MakeRefCounted<net::IOBuffer>(sizeof(data));
// report_id.
buffer->data()[0] = 1;
memcpy(buffer->data() + 1, data, sizeof(data) - 1);
std::move(callback).Run(true, buffer, sizeof(data));
// The first byte is the report id.
const uint8_t data[] = "\1TestRead";
auto buffer =
base::MakeRefCounted<base::RefCountedBytes>(data, sizeof(data) - 1);
std::move(callback).Run(true, buffer, buffer->size());
}
void MockHidConnection::PlatformWrite(scoped_refptr<net::IOBuffer> buffer,
size_t size,
WriteCallback callback) {
void MockHidConnection::PlatformWrite(
scoped_refptr<base::RefCountedBytes> buffer,
size_t size,
WriteCallback callback) {
std::move(callback).Run(true);
}
void MockHidConnection::PlatformGetFeatureReport(uint8_t report_id,
ReadCallback callback) {
const char data[] = "TestGetFeatureReport";
auto buffer = base::MakeRefCounted<net::IOBuffer>(sizeof(data) - 1);
memcpy(buffer->data(), data, sizeof(data) - 1);
std::move(callback).Run(true, buffer, sizeof(data) - 1);
const uint8_t data[] = "TestGetFeatureReport";
auto buffer =
base::MakeRefCounted<base::RefCountedBytes>(data, sizeof(data) - 1);
std::move(callback).Run(true, buffer, buffer->size());
}
void MockHidConnection::PlatformSendFeatureReport(
scoped_refptr<net::IOBuffer> buffer,
scoped_refptr<base::RefCountedBytes> buffer,
size_t size,
WriteCallback callback) {
std::move(callback).Run(true);
......
......@@ -18,12 +18,12 @@ class MockHidConnection : public HidConnection {
// HidConnection implementation.
void PlatformClose() override;
void PlatformRead(ReadCallback callback) override;
void PlatformWrite(scoped_refptr<net::IOBuffer> buffer,
void PlatformWrite(scoped_refptr<base::RefCountedBytes> buffer,
size_t size,
WriteCallback callback) override;
void PlatformGetFeatureReport(uint8_t report_id,
ReadCallback callback) override;
void PlatformSendFeatureReport(scoped_refptr<net::IOBuffer> buffer,
void PlatformSendFeatureReport(scoped_refptr<base::RefCountedBytes> buffer,
size_t size,
WriteCallback callback) override;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment