blob: d8d7a6b69ec266aa2ce6ea47b90f59e14e7a98dc [file] [log] [blame]
reillygee658b72014-09-04 19:40:301// Copyright 2014 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/message_loop/message_loop.h"
7#include "base/run_loop.h"
8#include "base/strings/utf_string_conversions.h"
reillygb87cb272015-04-16 19:11:049#include "base/test/test_io_thread.h"
reillygee658b72014-09-04 19:40:3010#include "device/test/usb_test_gadget.h"
11#include "device/usb/usb_device.h"
12#include "device/usb/usb_device_handle.h"
13#include "testing/gtest/include/gtest/gtest.h"
14
15namespace device {
16
17namespace {
18
19class UsbDeviceHandleTest : public ::testing::Test {
20 public:
dcheng07c34a12014-10-29 18:55:1021 void SetUp() override {
reillygb87cb272015-04-16 19:11:0422 message_loop_.reset(new base::MessageLoopForUI);
23 io_thread_.reset(new base::TestIOThread(base::TestIOThread::kAutoStart));
reillygee658b72014-09-04 19:40:3024 }
25
26 protected:
reillygb87cb272015-04-16 19:11:0427 scoped_ptr<base::TestIOThread> io_thread_;
reillygee658b72014-09-04 19:40:3028
29 private:
reillygee658b72014-09-04 19:40:3030 scoped_ptr<base::MessageLoop> message_loop_;
31};
32
reillygb87cb272015-04-16 19:11:0433class TestOpenCallback {
34 public:
35 TestOpenCallback()
36 : callback_(
37 base::Bind(&TestOpenCallback::SetResult, base::Unretained(this))) {}
38
39 scoped_refptr<UsbDeviceHandle> WaitForResult() {
40 run_loop_.Run();
41 return device_handle_;
42 }
43
44 const UsbDevice::OpenCallback& callback() const { return callback_; }
45
46 private:
47 void SetResult(scoped_refptr<UsbDeviceHandle> device_handle) {
48 device_handle_ = device_handle;
49 run_loop_.Quit();
50 }
51
52 const UsbDevice::OpenCallback callback_;
53 base::RunLoop run_loop_;
54 scoped_refptr<UsbDeviceHandle> device_handle_;
55};
56
57class TestResultCallback {
58 public:
59 TestResultCallback()
60 : callback_(base::Bind(&TestResultCallback::SetResult,
61 base::Unretained(this))) {}
62
63 bool WaitForResult() {
64 run_loop_.Run();
65 return success_;
66 }
67
68 const UsbDeviceHandle::ResultCallback& callback() const { return callback_; }
69
70 private:
71 void SetResult(bool success) {
72 success_ = success;
73 run_loop_.Quit();
74 }
75
76 const UsbDeviceHandle::ResultCallback callback_;
77 base::RunLoop run_loop_;
78 bool success_;
79};
80
reillygee658b72014-09-04 19:40:3081class TestCompletionCallback {
82 public:
83 TestCompletionCallback()
84 : callback_(base::Bind(&TestCompletionCallback::SetResult,
85 base::Unretained(this))) {}
86
reillygb87cb272015-04-16 19:11:0487 void WaitForResult() { run_loop_.Run(); }
88
89 const UsbDeviceHandle::TransferCallback& callback() const {
90 return callback_;
91 }
92 UsbTransferStatus status() const { return status_; }
93 size_t transferred() const { return transferred_; }
94
95 private:
reillygee658b72014-09-04 19:40:3096 void SetResult(UsbTransferStatus status,
97 scoped_refptr<net::IOBuffer> buffer,
98 size_t transferred) {
99 status_ = status;
100 transferred_ = transferred;
101 run_loop_.Quit();
102 }
103
reillygb87cb272015-04-16 19:11:04104 const UsbDeviceHandle::TransferCallback callback_;
reillygee658b72014-09-04 19:40:30105 base::RunLoop run_loop_;
106 UsbTransferStatus status_;
107 size_t transferred_;
108};
109
110TEST_F(UsbDeviceHandleTest, InterruptTransfer) {
reillygb87cb272015-04-16 19:11:04111 if (!UsbTestGadget::IsTestEnabled()) {
reillygee658b72014-09-04 19:40:30112 return;
113 }
114
reillygb87cb272015-04-16 19:11:04115 scoped_ptr<UsbTestGadget> gadget =
116 UsbTestGadget::Claim(io_thread_->task_runner());
117 ASSERT_TRUE(gadget.get());
118 ASSERT_TRUE(gadget->SetType(UsbTestGadget::ECHO));
119
120 TestOpenCallback open_device;
121 gadget->GetDevice()->Open(open_device.callback());
122 scoped_refptr<UsbDeviceHandle> handle = open_device.WaitForResult();
123 ASSERT_TRUE(handle.get());
124
125 TestResultCallback claim_interface;
126 handle->ClaimInterface(0, claim_interface.callback());
127 ASSERT_TRUE(claim_interface.WaitForResult());
reillyg67650d62014-12-13 01:18:52128
reillygee658b72014-09-04 19:40:30129 scoped_refptr<net::IOBufferWithSize> in_buffer(new net::IOBufferWithSize(64));
130 TestCompletionCallback in_completion;
reillygb87cb272015-04-16 19:11:04131 handle->InterruptTransfer(USB_DIRECTION_INBOUND, 0x81, in_buffer.get(),
132 in_buffer->size(),
133 5000, // 5 second timeout
134 in_completion.callback());
reillygee658b72014-09-04 19:40:30135
136 scoped_refptr<net::IOBufferWithSize> out_buffer(
137 new net::IOBufferWithSize(in_buffer->size()));
138 TestCompletionCallback out_completion;
139 for (int i = 0; i < out_buffer->size(); ++i) {
140 out_buffer->data()[i] = i;
141 }
142
reillygb87cb272015-04-16 19:11:04143 handle->InterruptTransfer(USB_DIRECTION_OUTBOUND, 0x01, out_buffer.get(),
144 out_buffer->size(),
145 5000, // 5 second timeout
146 out_completion.callback());
reillygee658b72014-09-04 19:40:30147 out_completion.WaitForResult();
148 ASSERT_EQ(USB_TRANSFER_COMPLETED, out_completion.status());
reillyg67650d62014-12-13 01:18:52149 EXPECT_EQ(static_cast<size_t>(out_buffer->size()),
reillygee658b72014-09-04 19:40:30150 out_completion.transferred());
151
152 in_completion.WaitForResult();
153 ASSERT_EQ(USB_TRANSFER_COMPLETED, in_completion.status());
reillyg67650d62014-12-13 01:18:52154 EXPECT_EQ(static_cast<size_t>(in_buffer->size()),
reillygee658b72014-09-04 19:40:30155 in_completion.transferred());
reillyg67650d62014-12-13 01:18:52156 for (size_t i = 0; i < in_completion.transferred(); ++i) {
reillyg631048ab2015-07-06 21:27:47157 EXPECT_EQ(out_buffer->data()[i], in_buffer->data()[i])
158 << "Mismatch at index " << i << ".";
reillygee658b72014-09-04 19:40:30159 }
reillygb87cb272015-04-16 19:11:04160
161 handle->Close();
reillygee658b72014-09-04 19:40:30162}
163
164TEST_F(UsbDeviceHandleTest, BulkTransfer) {
reillygb87cb272015-04-16 19:11:04165 if (!UsbTestGadget::IsTestEnabled()) {
reillygee658b72014-09-04 19:40:30166 return;
167 }
168
reillygb87cb272015-04-16 19:11:04169 scoped_ptr<UsbTestGadget> gadget =
170 UsbTestGadget::Claim(io_thread_->task_runner());
171 ASSERT_TRUE(gadget.get());
172 ASSERT_TRUE(gadget->SetType(UsbTestGadget::ECHO));
173
174 TestOpenCallback open_device;
175 gadget->GetDevice()->Open(open_device.callback());
176 scoped_refptr<UsbDeviceHandle> handle = open_device.WaitForResult();
177 ASSERT_TRUE(handle.get());
178
179 TestResultCallback claim_interface;
180 handle->ClaimInterface(1, claim_interface.callback());
181 ASSERT_TRUE(claim_interface.WaitForResult());
reillyg67650d62014-12-13 01:18:52182
reillygee658b72014-09-04 19:40:30183 scoped_refptr<net::IOBufferWithSize> in_buffer(
184 new net::IOBufferWithSize(512));
185 TestCompletionCallback in_completion;
reillygb87cb272015-04-16 19:11:04186 handle->BulkTransfer(USB_DIRECTION_INBOUND, 0x82, in_buffer.get(),
187 in_buffer->size(),
188 5000, // 5 second timeout
189 in_completion.callback());
reillygee658b72014-09-04 19:40:30190
191 scoped_refptr<net::IOBufferWithSize> out_buffer(
192 new net::IOBufferWithSize(in_buffer->size()));
193 TestCompletionCallback out_completion;
194 for (int i = 0; i < out_buffer->size(); ++i) {
195 out_buffer->data()[i] = i;
196 }
197
reillygb87cb272015-04-16 19:11:04198 handle->BulkTransfer(USB_DIRECTION_OUTBOUND, 0x02, out_buffer.get(),
199 out_buffer->size(),
200 5000, // 5 second timeout
201 out_completion.callback());
reillygee658b72014-09-04 19:40:30202 out_completion.WaitForResult();
203 ASSERT_EQ(USB_TRANSFER_COMPLETED, out_completion.status());
reillyg67650d62014-12-13 01:18:52204 EXPECT_EQ(static_cast<size_t>(out_buffer->size()),
reillygee658b72014-09-04 19:40:30205 out_completion.transferred());
206
207 in_completion.WaitForResult();
208 ASSERT_EQ(USB_TRANSFER_COMPLETED, in_completion.status());
reillyg67650d62014-12-13 01:18:52209 EXPECT_EQ(static_cast<size_t>(in_buffer->size()),
reillygee658b72014-09-04 19:40:30210 in_completion.transferred());
reillyg67650d62014-12-13 01:18:52211 for (size_t i = 0; i < in_completion.transferred(); ++i) {
reillyg631048ab2015-07-06 21:27:47212 EXPECT_EQ(out_buffer->data()[i], in_buffer->data()[i])
213 << "Mismatch at index " << i << ".";
reillygee658b72014-09-04 19:40:30214 }
reillygb87cb272015-04-16 19:11:04215
216 handle->Close();
reillygee658b72014-09-04 19:40:30217}
218
reillyg631048ab2015-07-06 21:27:47219TEST_F(UsbDeviceHandleTest, SetInterfaceAlternateSetting) {
220 if (!UsbTestGadget::IsTestEnabled()) {
221 return;
222 }
223
224 scoped_ptr<UsbTestGadget> gadget =
225 UsbTestGadget::Claim(io_thread_->task_runner());
226 ASSERT_TRUE(gadget.get());
227 ASSERT_TRUE(gadget->SetType(UsbTestGadget::ECHO));
228
229 TestOpenCallback open_device;
230 gadget->GetDevice()->Open(open_device.callback());
231 scoped_refptr<UsbDeviceHandle> handle = open_device.WaitForResult();
232 ASSERT_TRUE(handle.get());
233
234 TestResultCallback claim_interface;
235 handle->ClaimInterface(2, claim_interface.callback());
236 ASSERT_TRUE(claim_interface.WaitForResult());
237
238 TestResultCallback set_interface;
239 handle->SetInterfaceAlternateSetting(2, 1, set_interface.callback());
240 ASSERT_TRUE(set_interface.WaitForResult());
241
242 handle->Close();
243}
244
reillygee658b72014-09-04 19:40:30245} // namespace
246
247} // namespace device