system/core
Revision | c745f09b33804242c43f823242f0112645ed3a98 (tree) |
---|---|
Zeit | 2019-06-22 11:49:07 |
Autor | Josh Gao <jmgao@goog...> |
Commiter | android-build-merger |
Merge changes Ibb3f46b8,I875b87a0,I2d005e17 into qt-dev
am: 64e64eb990
Change-Id: I9541e903885ed2fd5fc1b431f881d4aa33f03411
@@ -16,6 +16,8 @@ | ||
16 | 16 | * limitations under the License. |
17 | 17 | */ |
18 | 18 | |
19 | +#include <linux/usb/functionfs.h> | |
20 | + | |
19 | 21 | #include <atomic> |
20 | 22 | #include <condition_variable> |
21 | 23 | #include <mutex> |
@@ -62,5 +64,9 @@ struct usb_handle { | ||
62 | 64 | }; |
63 | 65 | |
64 | 66 | usb_handle *create_usb_handle(unsigned num_bufs, unsigned io_size); |
67 | + | |
68 | +struct usb_functionfs_event; | |
69 | +const char* ffs_event_to_string(enum usb_functionfs_event_type type); | |
70 | +bool read_functionfs_setup(int fd, usb_functionfs_event* event); | |
65 | 71 | bool open_functionfs(android::base::unique_fd* control, android::base::unique_fd* bulk_out, |
66 | 72 | android::base::unique_fd* bulk_in); |
@@ -66,25 +66,6 @@ static constexpr size_t kUsbReadSize = 4 * PAGE_SIZE; | ||
66 | 66 | static constexpr size_t kUsbWriteQueueDepth = 8; |
67 | 67 | static constexpr size_t kUsbWriteSize = 4 * PAGE_SIZE; |
68 | 68 | |
69 | -static const char* to_string(enum usb_functionfs_event_type type) { | |
70 | - switch (type) { | |
71 | - case FUNCTIONFS_BIND: | |
72 | - return "FUNCTIONFS_BIND"; | |
73 | - case FUNCTIONFS_UNBIND: | |
74 | - return "FUNCTIONFS_UNBIND"; | |
75 | - case FUNCTIONFS_ENABLE: | |
76 | - return "FUNCTIONFS_ENABLE"; | |
77 | - case FUNCTIONFS_DISABLE: | |
78 | - return "FUNCTIONFS_DISABLE"; | |
79 | - case FUNCTIONFS_SETUP: | |
80 | - return "FUNCTIONFS_SETUP"; | |
81 | - case FUNCTIONFS_SUSPEND: | |
82 | - return "FUNCTIONFS_SUSPEND"; | |
83 | - case FUNCTIONFS_RESUME: | |
84 | - return "FUNCTIONFS_RESUME"; | |
85 | - } | |
86 | -} | |
87 | - | |
88 | 69 | enum class TransferDirection : uint64_t { |
89 | 70 | READ = 0, |
90 | 71 | WRITE = 1, |
@@ -169,12 +150,12 @@ struct ScopedAioContext { | ||
169 | 150 | }; |
170 | 151 | |
171 | 152 | struct UsbFfsConnection : public Connection { |
172 | - UsbFfsConnection(unique_fd control, unique_fd read, unique_fd write, | |
153 | + UsbFfsConnection(unique_fd* control, unique_fd read, unique_fd write, | |
173 | 154 | std::promise<void> destruction_notifier) |
174 | 155 | : worker_started_(false), |
175 | 156 | stopped_(false), |
176 | 157 | destruction_notifier_(std::move(destruction_notifier)), |
177 | - control_fd_(std::move(control)), | |
158 | + control_fd_(control), | |
178 | 159 | read_fd_(std::move(read)), |
179 | 160 | write_fd_(std::move(write)) { |
180 | 161 | LOG(INFO) << "UsbFfsConnection constructed"; |
@@ -183,11 +164,6 @@ struct UsbFfsConnection : public Connection { | ||
183 | 164 | PLOG(FATAL) << "failed to create eventfd"; |
184 | 165 | } |
185 | 166 | |
186 | - monitor_event_fd_.reset(eventfd(0, EFD_CLOEXEC)); | |
187 | - if (monitor_event_fd_ == -1) { | |
188 | - PLOG(FATAL) << "failed to create eventfd"; | |
189 | - } | |
190 | - | |
191 | 167 | aio_context_ = ScopedAioContext::Create(kUsbReadQueueDepth + kUsbWriteQueueDepth); |
192 | 168 | } |
193 | 169 |
@@ -199,7 +175,6 @@ struct UsbFfsConnection : public Connection { | ||
199 | 175 | // We need to explicitly close our file descriptors before we notify our destruction, |
200 | 176 | // because the thread listening on the future will immediately try to reopen the endpoint. |
201 | 177 | aio_context_.reset(); |
202 | - control_fd_.reset(); | |
203 | 178 | read_fd_.reset(); |
204 | 179 | write_fd_.reset(); |
205 | 180 |
@@ -246,13 +221,6 @@ struct UsbFfsConnection : public Connection { | ||
246 | 221 | PLOG(FATAL) << "failed to notify worker eventfd to stop UsbFfsConnection"; |
247 | 222 | } |
248 | 223 | CHECK_EQ(static_cast<size_t>(rc), sizeof(notify)); |
249 | - | |
250 | - rc = adb_write(monitor_event_fd_.get(), ¬ify, sizeof(notify)); | |
251 | - if (rc < 0) { | |
252 | - PLOG(FATAL) << "failed to notify monitor eventfd to stop UsbFfsConnection"; | |
253 | - } | |
254 | - | |
255 | - CHECK_EQ(static_cast<size_t>(rc), sizeof(notify)); | |
256 | 224 | } |
257 | 225 | |
258 | 226 | private: |
@@ -271,33 +239,24 @@ struct UsbFfsConnection : public Connection { | ||
271 | 239 | monitor_thread_ = std::thread([this]() { |
272 | 240 | adb_thread_setname("UsbFfs-monitor"); |
273 | 241 | |
274 | - bool bound = false; | |
275 | 242 | bool enabled = false; |
276 | 243 | bool running = true; |
277 | 244 | while (running) { |
278 | 245 | adb_pollfd pfd[2] = { |
279 | - { .fd = control_fd_.get(), .events = POLLIN, .revents = 0 }, | |
280 | - { .fd = monitor_event_fd_.get(), .events = POLLIN, .revents = 0 }, | |
246 | + {.fd = control_fd_->get(), .events = POLLIN, .revents = 0}, | |
281 | 247 | }; |
282 | 248 | |
283 | - // If we don't see our first bind within a second, try again. | |
284 | - int timeout_ms = bound ? -1 : 1000; | |
285 | - | |
286 | - int rc = TEMP_FAILURE_RETRY(adb_poll(pfd, 2, timeout_ms)); | |
249 | + int rc = TEMP_FAILURE_RETRY(adb_poll(pfd, 2, -1)); | |
287 | 250 | if (rc == -1) { |
288 | 251 | PLOG(FATAL) << "poll on USB control fd failed"; |
289 | - } else if (rc == 0) { | |
290 | - LOG(WARNING) << "timed out while waiting for FUNCTIONFS_BIND, trying again"; | |
291 | - break; | |
292 | 252 | } |
293 | 253 | |
294 | 254 | if (pfd[1].revents) { |
295 | - // We were told to die. | |
296 | - break; | |
255 | + // We were told to die, continue reading until FUNCTIONFS_UNBIND. | |
297 | 256 | } |
298 | 257 | |
299 | 258 | struct usb_functionfs_event event; |
300 | - rc = TEMP_FAILURE_RETRY(adb_read(control_fd_.get(), &event, sizeof(event))); | |
259 | + rc = TEMP_FAILURE_RETRY(adb_read(control_fd_->get(), &event, sizeof(event))); | |
301 | 260 | if (rc == -1) { |
302 | 261 | PLOG(FATAL) << "failed to read functionfs event"; |
303 | 262 | } else if (rc == 0) { |
@@ -309,32 +268,15 @@ struct UsbFfsConnection : public Connection { | ||
309 | 268 | } |
310 | 269 | |
311 | 270 | LOG(INFO) << "USB event: " |
312 | - << to_string(static_cast<usb_functionfs_event_type>(event.type)); | |
271 | + << ffs_event_to_string( | |
272 | + static_cast<usb_functionfs_event_type>(event.type)); | |
313 | 273 | |
314 | 274 | switch (event.type) { |
315 | 275 | case FUNCTIONFS_BIND: |
316 | - if (bound) { | |
317 | - LOG(WARNING) << "received FUNCTIONFS_BIND while already bound?"; | |
318 | - running = false; | |
319 | - break; | |
320 | - } | |
321 | - | |
322 | - if (enabled) { | |
323 | - LOG(WARNING) << "received FUNCTIONFS_BIND while already enabled?"; | |
324 | - running = false; | |
325 | - break; | |
326 | - } | |
327 | - | |
328 | - bound = true; | |
276 | + LOG(FATAL) << "received FUNCTIONFS_BIND after already opened?"; | |
329 | 277 | break; |
330 | 278 | |
331 | 279 | case FUNCTIONFS_ENABLE: |
332 | - if (!bound) { | |
333 | - LOG(WARNING) << "received FUNCTIONFS_ENABLE while not bound?"; | |
334 | - running = false; | |
335 | - break; | |
336 | - } | |
337 | - | |
338 | 280 | if (enabled) { |
339 | 281 | LOG(WARNING) << "received FUNCTIONFS_ENABLE while already enabled?"; |
340 | 282 | running = false; |
@@ -346,10 +288,6 @@ struct UsbFfsConnection : public Connection { | ||
346 | 288 | break; |
347 | 289 | |
348 | 290 | case FUNCTIONFS_DISABLE: |
349 | - if (!bound) { | |
350 | - LOG(WARNING) << "received FUNCTIONFS_DISABLE while not bound?"; | |
351 | - } | |
352 | - | |
353 | 291 | if (!enabled) { |
354 | 292 | LOG(WARNING) << "received FUNCTIONFS_DISABLE while not enabled?"; |
355 | 293 | } |
@@ -363,44 +301,12 @@ struct UsbFfsConnection : public Connection { | ||
363 | 301 | LOG(WARNING) << "received FUNCTIONFS_UNBIND while still enabled?"; |
364 | 302 | } |
365 | 303 | |
366 | - if (!bound) { | |
367 | - LOG(WARNING) << "received FUNCTIONFS_UNBIND when not bound?"; | |
368 | - } | |
369 | - | |
370 | - bound = false; | |
371 | 304 | running = false; |
372 | 305 | break; |
373 | 306 | |
374 | 307 | case FUNCTIONFS_SETUP: { |
375 | - LOG(INFO) << "received FUNCTIONFS_SETUP control transfer: bRequestType = " | |
376 | - << static_cast<int>(event.u.setup.bRequestType) | |
377 | - << ", bRequest = " << static_cast<int>(event.u.setup.bRequest) | |
378 | - << ", wValue = " << static_cast<int>(event.u.setup.wValue) | |
379 | - << ", wIndex = " << static_cast<int>(event.u.setup.wIndex) | |
380 | - << ", wLength = " << static_cast<int>(event.u.setup.wLength); | |
381 | - | |
382 | - if ((event.u.setup.bRequestType & USB_DIR_IN)) { | |
383 | - LOG(INFO) << "acking device-to-host control transfer"; | |
384 | - ssize_t rc = adb_write(control_fd_.get(), "", 0); | |
385 | - if (rc != 0) { | |
386 | - PLOG(ERROR) << "failed to write empty packet to host"; | |
387 | - break; | |
388 | - } | |
389 | - } else { | |
390 | - std::string buf; | |
391 | - buf.resize(event.u.setup.wLength + 1); | |
392 | - | |
393 | - ssize_t rc = adb_read(control_fd_.get(), buf.data(), buf.size()); | |
394 | - if (rc != event.u.setup.wLength) { | |
395 | - LOG(ERROR) | |
396 | - << "read " << rc | |
397 | - << " bytes when trying to read control request, expected " | |
398 | - << event.u.setup.wLength; | |
399 | - } | |
400 | - | |
401 | - LOG(INFO) << "control request contents: " << buf; | |
402 | - break; | |
403 | - } | |
308 | + read_functionfs_setup(*control_fd_, &event); | |
309 | + break; | |
404 | 310 | } |
405 | 311 | } |
406 | 312 | } |
@@ -426,6 +332,12 @@ struct UsbFfsConnection : public Connection { | ||
426 | 332 | uint64_t dummy; |
427 | 333 | ssize_t rc = adb_read(worker_event_fd_.get(), &dummy, sizeof(dummy)); |
428 | 334 | if (rc == -1) { |
335 | + if (errno == EINTR) { | |
336 | + // We were interrupted either to stop, or because of a backtrace. | |
337 | + // Check stopped_ again to see if we need to exit. | |
338 | + continue; | |
339 | + } | |
340 | + | |
429 | 341 | PLOG(FATAL) << "failed to read from eventfd"; |
430 | 342 | } else if (rc == 0) { |
431 | 343 | LOG(FATAL) << "hit EOF on eventfd"; |
@@ -462,6 +374,7 @@ struct UsbFfsConnection : public Connection { | ||
462 | 374 | } |
463 | 375 | |
464 | 376 | worker_thread_.join(); |
377 | + worker_started_ = false; | |
465 | 378 | } |
466 | 379 | |
467 | 380 | void PrepareReadBlock(IoBlock* block, uint64_t id) { |
@@ -509,14 +422,16 @@ struct UsbFfsConnection : public Connection { | ||
509 | 422 | } |
510 | 423 | |
511 | 424 | if (id.direction == TransferDirection::READ) { |
512 | - HandleRead(id, event.res); | |
425 | + if (!HandleRead(id, event.res)) { | |
426 | + return; | |
427 | + } | |
513 | 428 | } else { |
514 | 429 | HandleWrite(id); |
515 | 430 | } |
516 | 431 | } |
517 | 432 | } |
518 | 433 | |
519 | - void HandleRead(TransferId id, int64_t size) { | |
434 | + bool HandleRead(TransferId id, int64_t size) { | |
520 | 435 | uint64_t read_idx = id.id % kUsbReadQueueDepth; |
521 | 436 | IoBlock* block = &read_requests_[read_idx]; |
522 | 437 | block->pending = false; |
@@ -526,7 +441,7 @@ struct UsbFfsConnection : public Connection { | ||
526 | 441 | if (block->id().id != needed_read_id_) { |
527 | 442 | LOG(VERBOSE) << "read " << block->id().id << " completed while waiting for " |
528 | 443 | << needed_read_id_; |
529 | - return; | |
444 | + return true; | |
530 | 445 | } |
531 | 446 | |
532 | 447 | for (uint64_t id = needed_read_id_;; ++id) { |
@@ -535,15 +450,22 @@ struct UsbFfsConnection : public Connection { | ||
535 | 450 | if (current_block->pending) { |
536 | 451 | break; |
537 | 452 | } |
538 | - ProcessRead(current_block); | |
453 | + if (!ProcessRead(current_block)) { | |
454 | + return false; | |
455 | + } | |
539 | 456 | ++needed_read_id_; |
540 | 457 | } |
458 | + | |
459 | + return true; | |
541 | 460 | } |
542 | 461 | |
543 | - void ProcessRead(IoBlock* block) { | |
462 | + bool ProcessRead(IoBlock* block) { | |
544 | 463 | if (!block->payload->empty()) { |
545 | 464 | if (!incoming_header_.has_value()) { |
546 | - CHECK_EQ(sizeof(amessage), block->payload->size()); | |
465 | + if (block->payload->size() != sizeof(amessage)) { | |
466 | + HandleError("received packet of unexpected length while reading header"); | |
467 | + return false; | |
468 | + } | |
547 | 469 | amessage msg; |
548 | 470 | memcpy(&msg, block->payload->data(), sizeof(amessage)); |
549 | 471 | LOG(DEBUG) << "USB read:" << dump_header(&msg); |
@@ -551,7 +473,10 @@ struct UsbFfsConnection : public Connection { | ||
551 | 473 | } else { |
552 | 474 | size_t bytes_left = incoming_header_->data_length - incoming_payload_.size(); |
553 | 475 | Block payload = std::move(*block->payload); |
554 | - CHECK_LE(payload.size(), bytes_left); | |
476 | + if (block->payload->size() > bytes_left) { | |
477 | + HandleError("received too many bytes while waiting for payload"); | |
478 | + return false; | |
479 | + } | |
555 | 480 | incoming_payload_.append(std::make_unique<Block>(std::move(payload))); |
556 | 481 | } |
557 | 482 |
@@ -570,6 +495,7 @@ struct UsbFfsConnection : public Connection { | ||
570 | 495 | |
571 | 496 | PrepareReadBlock(block, block->id().id + kUsbReadQueueDepth); |
572 | 497 | SubmitRead(block); |
498 | + return true; | |
573 | 499 | } |
574 | 500 | |
575 | 501 | bool SubmitRead(IoBlock* block) { |
@@ -679,10 +605,13 @@ struct UsbFfsConnection : public Connection { | ||
679 | 605 | std::once_flag error_flag_; |
680 | 606 | |
681 | 607 | unique_fd worker_event_fd_; |
682 | - unique_fd monitor_event_fd_; | |
683 | 608 | |
684 | 609 | ScopedAioContext aio_context_; |
685 | - unique_fd control_fd_; | |
610 | + | |
611 | + // We keep a pointer to the control fd, so that we can reuse it to avoid USB reconfiguration, | |
612 | + // and still be able to reset it to force a reopen after FUNCTIONFS_UNBIND or running into an | |
613 | + // unexpected situation. | |
614 | + unique_fd* control_fd_; | |
686 | 615 | unique_fd read_fd_; |
687 | 616 | unique_fd write_fd_; |
688 | 617 |
@@ -711,15 +640,16 @@ void usb_init_legacy(); | ||
711 | 640 | static void usb_ffs_open_thread() { |
712 | 641 | adb_thread_setname("usb ffs open"); |
713 | 642 | |
643 | + unique_fd control; | |
644 | + unique_fd bulk_out; | |
645 | + unique_fd bulk_in; | |
646 | + | |
714 | 647 | while (true) { |
715 | 648 | if (gFfsAioSupported.has_value() && !gFfsAioSupported.value()) { |
716 | 649 | LOG(INFO) << "failed to use nonblocking ffs, falling back to legacy"; |
717 | 650 | return usb_init_legacy(); |
718 | 651 | } |
719 | 652 | |
720 | - unique_fd control; | |
721 | - unique_fd bulk_out; | |
722 | - unique_fd bulk_in; | |
723 | 653 | if (!open_functionfs(&control, &bulk_out, &bulk_in)) { |
724 | 654 | std::this_thread::sleep_for(1s); |
725 | 655 | continue; |
@@ -730,7 +660,7 @@ static void usb_ffs_open_thread() { | ||
730 | 660 | std::promise<void> destruction_notifier; |
731 | 661 | std::future<void> future = destruction_notifier.get_future(); |
732 | 662 | transport->SetConnection(std::make_unique<UsbFfsConnection>( |
733 | - std::move(control), std::move(bulk_out), std::move(bulk_in), | |
663 | + &control, std::move(bulk_out), std::move(bulk_in), | |
734 | 664 | std::move(destruction_notifier))); |
735 | 665 | register_transport(transport); |
736 | 666 | future.wait(); |
@@ -208,6 +208,56 @@ static const struct { | ||
208 | 208 | }; |
209 | 209 | // clang-format on |
210 | 210 | |
211 | +const char* ffs_event_to_string(enum usb_functionfs_event_type type) { | |
212 | + switch (type) { | |
213 | + case FUNCTIONFS_BIND: | |
214 | + return "FUNCTIONFS_BIND"; | |
215 | + case FUNCTIONFS_UNBIND: | |
216 | + return "FUNCTIONFS_UNBIND"; | |
217 | + case FUNCTIONFS_ENABLE: | |
218 | + return "FUNCTIONFS_ENABLE"; | |
219 | + case FUNCTIONFS_DISABLE: | |
220 | + return "FUNCTIONFS_DISABLE"; | |
221 | + case FUNCTIONFS_SETUP: | |
222 | + return "FUNCTIONFS_SETUP"; | |
223 | + case FUNCTIONFS_SUSPEND: | |
224 | + return "FUNCTIONFS_SUSPEND"; | |
225 | + case FUNCTIONFS_RESUME: | |
226 | + return "FUNCTIONFS_RESUME"; | |
227 | + } | |
228 | +} | |
229 | + | |
230 | +bool read_functionfs_setup(int fd, usb_functionfs_event* event) { | |
231 | + LOG(INFO) << "received FUNCTIONFS_SETUP control transfer: bRequestType = " | |
232 | + << static_cast<int>(event->u.setup.bRequestType) | |
233 | + << ", bRequest = " << static_cast<int>(event->u.setup.bRequest) | |
234 | + << ", wValue = " << static_cast<int>(event->u.setup.wValue) | |
235 | + << ", wIndex = " << static_cast<int>(event->u.setup.wIndex) | |
236 | + << ", wLength = " << static_cast<int>(event->u.setup.wLength); | |
237 | + | |
238 | + if ((event->u.setup.bRequestType & USB_DIR_IN)) { | |
239 | + LOG(INFO) << "acking device-to-host control transfer"; | |
240 | + ssize_t rc = adb_write(fd, "", 0); | |
241 | + if (rc != 0) { | |
242 | + PLOG(ERROR) << "failed to write empty packet to host"; | |
243 | + return false; | |
244 | + } | |
245 | + } else { | |
246 | + std::string buf; | |
247 | + buf.resize(event->u.setup.wLength + 1); | |
248 | + | |
249 | + ssize_t rc = adb_read(fd, buf.data(), buf.size()); | |
250 | + if (rc != event->u.setup.wLength) { | |
251 | + LOG(ERROR) << "read " << rc << " bytes when trying to read control request, expected " | |
252 | + << event->u.setup.wLength; | |
253 | + } | |
254 | + | |
255 | + LOG(INFO) << "control request contents: " << buf; | |
256 | + } | |
257 | + | |
258 | + return true; | |
259 | +} | |
260 | + | |
211 | 261 | bool open_functionfs(android::base::unique_fd* out_control, android::base::unique_fd* out_bulk_out, |
212 | 262 | android::base::unique_fd* out_bulk_in) { |
213 | 263 | unique_fd control, bulk_out, bulk_in; |
@@ -255,8 +305,35 @@ bool open_functionfs(android::base::unique_fd* out_control, android::base::uniqu | ||
255 | 305 | PLOG(ERROR) << "failed to write USB strings"; |
256 | 306 | return false; |
257 | 307 | } |
258 | - // Signal only when writing the descriptors to ffs | |
308 | + | |
309 | + // Signal init after we've written our descriptors. | |
259 | 310 | android::base::SetProperty("sys.usb.ffs.ready", "1"); |
311 | + *out_control = std::move(control); | |
312 | + } | |
313 | + | |
314 | + // Read until we get FUNCTIONFS_BIND from the control endpoint. | |
315 | + while (true) { | |
316 | + struct usb_functionfs_event event; | |
317 | + ssize_t rc = TEMP_FAILURE_RETRY(adb_read(*out_control, &event, sizeof(event))); | |
318 | + | |
319 | + if (rc == -1) { | |
320 | + PLOG(FATAL) << "failed to read from FFS control fd"; | |
321 | + } else if (rc == 0) { | |
322 | + LOG(WARNING) << "hit EOF on functionfs control fd during initialization"; | |
323 | + } else if (rc != sizeof(event)) { | |
324 | + LOG(FATAL) << "read functionfs event of unexpected size, expected " << sizeof(event) | |
325 | + << ", got " << rc; | |
326 | + } | |
327 | + | |
328 | + LOG(INFO) << "USB event: " | |
329 | + << ffs_event_to_string(static_cast<usb_functionfs_event_type>(event.type)); | |
330 | + if (event.type == FUNCTIONFS_BIND) { | |
331 | + break; | |
332 | + } else if (event.type == FUNCTIONFS_SETUP) { | |
333 | + read_functionfs_setup(out_control->get(), &event); | |
334 | + } else { | |
335 | + continue; | |
336 | + } | |
260 | 337 | } |
261 | 338 | |
262 | 339 | bulk_out.reset(adb_open(USB_FFS_ADB_OUT, O_RDONLY)); |
@@ -271,7 +348,6 @@ bool open_functionfs(android::base::unique_fd* out_control, android::base::uniqu | ||
271 | 348 | return false; |
272 | 349 | } |
273 | 350 | |
274 | - *out_control = std::move(control); | |
275 | 351 | *out_bulk_in = std::move(bulk_in); |
276 | 352 | *out_bulk_out = std::move(bulk_out); |
277 | 353 | return true; |