Skip to content

Commit fff6b3c

Browse files
Ruby ZhuangCQ Bot
Ruby Zhuang
authored and
CQ Bot
committed
[usb][adb][cdc] Fixes to enable cdc and adb simultaneously on Sorrel
1. Separate StartController, StopController from SetInterface 2. dwc3 fixes on reconnecting, including resetting state, etc. 3. dwc3 fix to read the proper data length 4. cdc fix to set configuration if configured does not match request 5. adb fix to only queue requests if both the endpoints are configured and the daemon is connected Bug: b/389146553 Bug: b/388298520 Test: tested on sorrel Test: tested on vim3 Test: usb-peripheral-unittest Test: usb-virtual-bus-unit-test Test: usb-virtual-bus-test Test: usb-hid-test Test: usb-adb-unittest Does not pass stress test Change-Id: Ie5b63d10db19a80937c29788ce835b6cd6a10b29 Reviewed-on: https://fuchsia-review.googlesource.com/c/fuchsia/+/1192555 API-Review: Suraj Malhotra <[email protected]> Reviewed-by: Sam Hansen <[email protected]> Reviewed-by: Suraj Malhotra <[email protected]> Commit-Queue: Ruby Zhuang <[email protected]>
1 parent 798d52e commit fff6b3c

File tree

16 files changed

+337
-229
lines changed

16 files changed

+337
-229
lines changed

sdk/fidl/fuchsia.hardware.usb.dci/usb-dci.fidl

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,14 @@ open protocol UsbDci {
2525
interface client_end:UsbDciInterface;
2626
}) -> () error zx.Status;
2727

28+
/// Start running in peripheral mode. Connects the device to the host. Usually called when all
29+
/// functions are ready.
30+
flexible StartController() -> () error zx.Status;
31+
32+
/// Stop running in peripheral mode. Disconnects the device from the host. Usually called when
33+
/// a function is cleared.
34+
flexible StopController() -> () error zx.Status;
35+
2836
/// Configure and endpoint with the given configuration.
2937
///
3038
/// See usb20 9.6.6

src/connectivity/ethernet/drivers/usb-cdc-function/cdc-eth-function.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -407,7 +407,7 @@ zx_status_t UsbCdc::UsbFunctionInterfaceControl(const usb_setup_t* setup,
407407
zx_status_t UsbCdc::UsbFunctionInterfaceSetConfigured(bool configured, usb_speed_t speed) {
408408
TRACE_DURATION("cdc_eth", __func__, "configured", configured, "speed", speed);
409409

410-
if (configured_) {
410+
if (configured_ == configured) {
411411
return ZX_OK;
412412
}
413413

src/developer/adb/drivers/usb-adb-function/adb-function-test.cc

Lines changed: 7 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,8 @@ class UsbAdbTest : public zxtest::Test {
137137

138138
void ReleaseFakeAdbDaemon(std::unique_ptr<FakeAdbDaemon>& fake_adb) {
139139
// Calls during Stop().
140+
mock_usb_.ExpectDisableEp(ZX_OK, kBulkOutEp);
141+
mock_usb_.ExpectDisableEp(ZX_OK, kBulkInEp);
140142
mock_usb_.ExpectSetInterface(ZX_OK, {});
141143

142144
libsync::Completion stop_sync;
@@ -148,7 +150,6 @@ class UsbAdbTest : public zxtest::Test {
148150
infra->fake_dev.fake_endpoint(kBulkOutEp).RequestComplete(ZX_ERR_IO_NOT_PRESENT, 0);
149151
}
150152
});
151-
released_ = true;
152153
stop_sync.Wait();
153154
}
154155

@@ -205,15 +206,6 @@ class UsbAdbTest : public zxtest::Test {
205206
}
206207

207208
void TearDown() override {
208-
mock_usb_.ExpectDisableEp(ZX_OK, kBulkOutEp);
209-
mock_usb_.ExpectDisableEp(ZX_OK, kBulkInEp);
210-
if (!released_) {
211-
incoming_.SyncCall([](IncomingNamespace* infra) {
212-
for (size_t i = 0; i < kBulkTxRxCount; i++) {
213-
infra->fake_dev.fake_endpoint(kBulkOutEp).RequestComplete(ZX_ERR_CANCELED, 0);
214-
}
215-
});
216-
}
217209
mock_usb_.ExpectSetInterface(ZX_OK, {});
218210

219211
ASSERT_OK(fdf::RunOnDispatcherSync(adb_dispatcher_->async_dispatcher(),
@@ -228,7 +220,6 @@ class UsbAdbTest : public zxtest::Test {
228220
fdf::UnownedSynchronizedDispatcher adb_dispatcher_ =
229221
mock_ddk::GetDriverRuntime()->StartBackgroundDispatcher();
230222
zx_device_t* dev_;
231-
bool released_ = false;
232223

233224
protected:
234225
async_patterns::TestDispatcherBound<IncomingNamespace> incoming_{incoming_loop_.dispatcher(),
@@ -292,7 +283,11 @@ void UsbAdbTest::SendTestData(std::unique_ptr<FakeAdbDaemon>& fake_adb, size_t s
292283
});
293284
}
294285

295-
TEST_F(UsbAdbTest, SetUpTearDown) { ASSERT_NO_FATAL_FAILURE(); }
286+
TEST_F(UsbAdbTest, SetUpTearDown) {
287+
ASSERT_NO_FATAL_FAILURE();
288+
mock_usb_.ExpectDisableEp(ZX_OK, kBulkOutEp);
289+
mock_usb_.ExpectDisableEp(ZX_OK, kBulkInEp);
290+
}
296291

297292
TEST_F(UsbAdbTest, StartStop) {
298293
auto fake_adb = CreateFakeAdbDaemon();

src/developer/adb/drivers/usb-adb-function/adb-function.cc

Lines changed: 69 additions & 100 deletions
Original file line numberDiff line numberDiff line change
@@ -48,29 +48,55 @@ void UsbAdbDevice::Start(StartRequestView request, StartCompleter::Sync& complet
4848
return CompleteTxn(completer, ZX_ERR_ALREADY_BOUND);
4949
}
5050

51+
// Reset interface and configure endpoints as adb binding is set now.
52+
zx_status_t status = function_.SetInterface(this, &usb_function_interface_protocol_ops_);
53+
if (status != ZX_OK && status != ZX_ERR_ALREADY_BOUND) {
54+
zxlogf(ERROR, "SetInterface failed %s", zx_status_get_string(status));
55+
CompleteTxn(completer, status);
56+
return;
57+
}
5158
adb_binding_.emplace(fdf::Dispatcher::GetCurrent()->async_dispatcher(),
5259
std::move(request->interface), this, [this](fidl::UnbindInfo info) {
5360
zxlogf(INFO, "Device closed with reason '%s'",
5461
info.FormatDescription().c_str());
5562
Stop();
5663
});
57-
// Reset interface and configure endpoints as adb binding is set now.
58-
zx_status_t status = function_.SetInterface(this, &usb_function_interface_protocol_ops_);
59-
if (status != ZX_OK && status != ZX_ERR_ALREADY_BOUND) {
60-
zxlogf(ERROR, "SetInterface failed %s", zx_status_get_string(status));
61-
CompleteTxn(completer, status);
64+
CompleteTxn(completer, ZX_OK);
65+
66+
Start();
67+
}
68+
69+
void UsbAdbDevice::Start() {
70+
if (!Online() || !adb_binding_) {
6271
return;
6372
}
73+
6474
auto result = fidl::WireSendEvent(adb_binding_.value())
6575
->OnStatusChanged(Online() ? fadb::StatusFlags::kOnline : fadb::StatusFlags(0));
6676
if (!result.ok()) {
6777
zxlogf(ERROR, "Could not call AdbInterface Status.");
68-
CompleteTxn(completer, result.error().status());
6978
return;
7079
}
71-
CompleteTxn(completer, status);
7280

73-
// Run receive to pass up messages received while disconnected.
81+
// queue RX requests
82+
std::vector<fuchsia_hardware_usb_request::Request> requests;
83+
while (auto req = bulk_out_ep_.GetRequest()) {
84+
req->reset_buffers(bulk_out_ep_.GetMapped());
85+
auto status = req->CacheFlushInvalidate(bulk_out_ep_.GetMapped());
86+
if (status != ZX_OK) {
87+
zxlogf(ERROR, "Cache flush and invalidate failed %d", status);
88+
}
89+
90+
requests.emplace_back(req->take_request());
91+
}
92+
if (!requests.empty()) {
93+
auto result = bulk_out_ep_->QueueRequests(std::move(requests));
94+
if (result.is_error()) {
95+
zxlogf(ERROR, "Failed to QueueRequests %s", result.error_value().FormatDescription().c_str());
96+
return;
97+
}
98+
}
99+
74100
std::lock_guard<std::mutex> _(bulk_out_ep_.mutex());
75101
ReceiveLocked();
76102
}
@@ -89,23 +115,10 @@ void UsbAdbDevice::Stop() {
89115
adb_binding_.reset();
90116
}
91117

92-
// Cancel all requests in the pipeline -- the completion handler will free these requests as they
93-
// come in.
94-
//
95-
// Do not hold locks when calling this method. It might result in deadlock as completion callbacks
96-
// could be invoked during this call.
97-
bulk_out_ep_->CancelAll().Then([](fidl::Result<fendpoint::Endpoint::CancelAll>& result) {
98-
if (result.is_error()) {
99-
zxlogf(ERROR, "Failed to cancel all for bulk out endpoint %s",
100-
result.error_value().FormatDescription().c_str());
101-
}
102-
});
103-
bulk_in_ep_->CancelAll().Then([](fidl::Result<fendpoint::Endpoint::CancelAll>& result) {
104-
if (result.is_error()) {
105-
zxlogf(ERROR, "Failed to cancel all for bulk in endpoint %s",
106-
result.error_value().FormatDescription().c_str());
107-
}
108-
});
118+
zx_status_t status = ConfigureEndpoints(false);
119+
if (status != ZX_OK) {
120+
zxlogf(ERROR, "Failed to unconifgure endpoints %s.", zx_status_get_string(status));
121+
}
109122

110123
{
111124
std::lock_guard<std::mutex> _(bulk_out_ep_.mutex());
@@ -127,7 +140,7 @@ void UsbAdbDevice::Stop() {
127140
}
128141
}
129142

130-
zx_status_t status = function_.SetInterface(nullptr, nullptr);
143+
status = function_.SetInterface(nullptr, nullptr);
131144
if (status != ZX_OK) {
132145
zxlogf(ERROR, "SetInterface failed %s", zx_status_get_string(status));
133146
}
@@ -137,13 +150,9 @@ void UsbAdbDevice::Stop() {
137150
ShutdownComplete();
138151
}
139152

140-
zx::result<> UsbAdbDevice::SendLocked() {
141-
if (tx_pending_reqs_.empty()) {
142-
return zx::ok();
143-
}
144-
145-
if (!Online()) {
146-
return zx::error(ZX_ERR_BAD_STATE);
153+
void UsbAdbDevice::SendLocked() {
154+
if (!Online() || tx_pending_reqs_.empty()) {
155+
return;
147156
}
148157

149158
auto& current = tx_pending_reqs_.front();
@@ -184,12 +193,10 @@ zx::result<> UsbAdbDevice::SendLocked() {
184193
CompleteTxn(current.completer, ZX_OK);
185194
tx_pending_reqs_.pop();
186195
}
187-
188-
return zx::ok();
189196
}
190197

191198
void UsbAdbDevice::ReceiveLocked() {
192-
if (pending_replies_.empty() || rx_requests_.empty()) {
199+
if (!Online() || pending_replies_.empty() || rx_requests_.empty()) {
193200
return;
194201
}
195202

@@ -234,7 +241,7 @@ void UsbAdbDevice::ReceiveLocked() {
234241
void UsbAdbDevice::QueueTx(QueueTxRequest& request, QueueTxCompleter::Sync& completer) {
235242
size_t length = request.data().size();
236243

237-
if (!Online() || length == 0) {
244+
if (length == 0) {
238245
zxlogf(INFO, "Invalid state - Online %d Length %zu", Online(), length);
239246
completer.Reply(fit::error(ZX_ERR_INVALID_ARGS));
240247
return;
@@ -244,19 +251,10 @@ void UsbAdbDevice::QueueTx(QueueTxRequest& request, QueueTxCompleter::Sync& comp
244251
tx_pending_reqs_.emplace(
245252
txn_req_t{.request = std::move(request), .start = 0, .completer = completer.ToAsync()});
246253

247-
auto result = SendLocked();
248-
if (result.is_error()) {
249-
zxlogf(INFO, "SendLocked failed %d", result.error_value());
250-
}
254+
SendLocked();
251255
}
252256

253257
void UsbAdbDevice::Receive(ReceiveCompleter::Sync& completer) {
254-
// Return early during shutdown.
255-
if (!Online()) {
256-
completer.Reply(fit::error(ZX_ERR_BAD_STATE));
257-
return;
258-
}
259-
260258
std::lock_guard<std::mutex> lock(bulk_out_ep_.mutex());
261259
rx_requests_.emplace(completer.ToAsync());
262260
ReceiveLocked();
@@ -302,10 +300,7 @@ void UsbAdbDevice::TxComplete(fendpoint::Completion completion) {
302300
return;
303301
}
304302

305-
auto result = SendLocked();
306-
if (result.is_error()) {
307-
zxlogf(ERROR, "Failed to SendLocked %d", result.error_value());
308-
}
303+
SendLocked();
309304
}
310305

311306
size_t UsbAdbDevice::UsbFunctionInterfaceGetDescriptorsSize() { return sizeof(descriptors_); }
@@ -329,10 +324,16 @@ zx_status_t UsbAdbDevice::UsbFunctionInterfaceControl(const usb_setup_t* setup,
329324
}
330325

331326
zx_status_t UsbAdbDevice::ConfigureEndpoints(bool enable) {
332-
zx_status_t status;
333-
// Configure endpoint if not already done.
334-
if (enable && !bulk_out_ep_.RequestsEmpty()) {
335-
status = function_.ConfigEp(&descriptors_.bulk_out_ep, nullptr);
327+
{
328+
std::lock_guard<std::mutex> _(lock_);
329+
if (status_ == fadb::StatusFlags(enable)) {
330+
return ZX_OK;
331+
}
332+
status_ = fadb::StatusFlags(enable);
333+
}
334+
335+
if (enable) {
336+
zx_status_t status = function_.ConfigEp(&descriptors_.bulk_out_ep, nullptr);
336337
if (status != ZX_OK) {
337338
zxlogf(ERROR, "Failed to Config BULK OUT ep - %d.", status);
338339
return status;
@@ -344,25 +345,10 @@ zx_status_t UsbAdbDevice::ConfigureEndpoints(bool enable) {
344345
return status;
345346
}
346347

347-
// queue RX requests
348-
std::vector<fuchsia_hardware_usb_request::Request> requests;
349-
while (auto req = bulk_out_ep_.GetRequest()) {
350-
req->reset_buffers(bulk_out_ep_.GetMapped());
351-
auto status = req->CacheFlushInvalidate(bulk_out_ep_.GetMapped());
352-
if (status != ZX_OK) {
353-
zxlogf(ERROR, "Cache flush and invalidate failed %d", status);
354-
}
355-
356-
requests.emplace_back(req->take_request());
357-
}
358-
auto result = bulk_out_ep_->QueueRequests(std::move(requests));
359-
if (result.is_error()) {
360-
zxlogf(ERROR, "Failed to QueueRequests %s", result.error_value().FormatDescription().c_str());
361-
return result.error_value().status();
362-
}
348+
Start();
363349
zxlogf(INFO, "ADB endpoints configured.");
364-
} else if (!enable) {
365-
status = function_.DisableEp(bulk_out_addr());
350+
} else {
351+
zx_status_t status = function_.DisableEp(bulk_out_addr());
366352
if (status != ZX_OK) {
367353
zxlogf(ERROR, "Failed to disable BULK OUT ep - %d.", status);
368354
return status;
@@ -373,27 +359,21 @@ zx_status_t UsbAdbDevice::ConfigureEndpoints(bool enable) {
373359
zxlogf(ERROR, "Failed to disable BULK IN ep - %d.", status);
374360
return status;
375361
}
376-
}
377362

378-
if (adb_binding_.has_value()) {
379-
auto result = fidl::WireSendEvent(adb_binding_.value())
380-
->OnStatusChanged(enable ? fadb::StatusFlags::kOnline : fadb::StatusFlags(0));
381-
if (!result.ok()) {
382-
zxlogf(ERROR, "Could not call AdbInterface Status.");
383-
return ZX_ERR_IO;
363+
if (adb_binding_.has_value()) {
364+
auto result =
365+
fidl::WireSendEvent(adb_binding_.value())->OnStatusChanged(fadb::StatusFlags(0));
366+
if (!result.ok()) {
367+
zxlogf(ERROR, "Could not call AdbInterface Status.");
368+
return ZX_ERR_IO;
369+
}
384370
}
385371
}
386-
387372
return ZX_OK;
388373
}
389374

390375
zx_status_t UsbAdbDevice::UsbFunctionInterfaceSetConfigured(bool configured, usb_speed_t speed) {
391376
zxlogf(INFO, "configured? - %d speed - %d.", configured, speed);
392-
{
393-
std::lock_guard<std::mutex> _(lock_);
394-
status_ = fadb::StatusFlags(configured);
395-
}
396-
397377
return ConfigureEndpoints(configured);
398378
}
399379

@@ -403,19 +383,7 @@ zx_status_t UsbAdbDevice::UsbFunctionInterfaceSetInterface(uint8_t interface, ui
403383
if (interface != descriptors_.adb_intf.b_interface_number || alt_setting > 1) {
404384
return ZX_ERR_INVALID_ARGS;
405385
}
406-
407-
auto status = ConfigureEndpoints(alt_setting);
408-
if (status != ZX_OK) {
409-
zxlogf(ERROR, "ConfigureEndpoints failed %d", status);
410-
return status;
411-
}
412-
413-
{
414-
std::lock_guard<std::mutex> _(lock_);
415-
status_ = alt_setting ? fadb::StatusFlags::kOnline : fadb::StatusFlags(0);
416-
}
417-
418-
return status;
386+
return ConfigureEndpoints(alt_setting);
419387
}
420388

421389
void UsbAdbDevice::ShutdownComplete() {
@@ -424,7 +392,8 @@ void UsbAdbDevice::ShutdownComplete() {
424392
// Only call the callback if all requests are returned.
425393
if (stop_completed_ && shutdown_callback_ && bulk_in_ep_.RequestsFull() &&
426394
bulk_out_ep_.RequestsFull()) {
427-
shutdown_callback_();
395+
auto callback = std::move(shutdown_callback_);
396+
callback();
428397
stop_completed_ = false;
429398
}
430399
}

src/developer/adb/drivers/usb-adb-function/adb-function.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,8 @@ class UsbAdbDevice : public UsbAdb,
7777
void Start(StartRequestView request, StartCompleter::Sync& completer) override;
7878
void Stop(StopCompleter::Sync& completer) override;
7979

80-
// Helper method called when fadb::Device closes.
80+
// Helper methods.
81+
void Start();
8182
void Stop();
8283

8384
// fadb::UsbAdbImpl methods.
@@ -107,7 +108,7 @@ class UsbAdbDevice : public UsbAdb,
107108
usb::EndpointClient<UsbAdbDevice>& ep);
108109

109110
// Helper method to get free request buffer and queue the request for transmitting.
110-
zx::result<> SendLocked() __TA_REQUIRES(bulk_in_ep_.mutex());
111+
void SendLocked() __TA_REQUIRES(bulk_in_ep_.mutex());
111112
// Helper method to get free request buffer and queue the request for receiving.
112113
void ReceiveLocked() __TA_REQUIRES(bulk_out_ep_.mutex());
113114

0 commit comments

Comments
 (0)