1 /*
2 * Copyright (C) 2017 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16 #include <glog/logging.h>
17
18 #include "host/commands/virtual_usb_manager/vadb/usb_cmd_data_transfer.h"
19
20 namespace vadb {
USBCmdDataTransfer(uint8_t bus_id,uint8_t dev_id,uint8_t endpoint,bool is_host_to_device,uint32_t deadline,std::vector<uint8_t> data,usbip::Device::AsyncTransferReadyCB callback)21 USBCmdDataTransfer::USBCmdDataTransfer(
22 uint8_t bus_id, uint8_t dev_id, uint8_t endpoint, bool is_host_to_device,
23 uint32_t deadline, std::vector<uint8_t> data,
24 usbip::Device::AsyncTransferReadyCB callback)
25 : data_(std::move(data)), callback_(std::move(callback)) {
26 req_.bus_id = bus_id;
27 req_.dev_id = dev_id;
28 req_.endpoint_id = endpoint;
29 req_.is_host_to_device = is_host_to_device;
30 req_.length = data_.size();
31 req_.timeout = deadline;
32 }
33
OnRequest(const cvd::SharedFD & fd)34 bool USBCmdDataTransfer::OnRequest(const cvd::SharedFD& fd) {
35 if (fd->Write(&req_, sizeof(req_)) != sizeof(req_)) {
36 LOG(ERROR) << "Short write: " << fd->StrError();
37 return false;
38 }
39
40 if (req_.is_host_to_device && data_.size() > 0) {
41 if (static_cast<size_t>(fd->Write(data_.data(), data_.size())) !=
42 data_.size()) {
43 LOG(ERROR) << "Short write: " << fd->StrError();
44 return false;
45 }
46 }
47
48 return true;
49 }
50
OnResponse(bool is_success,const cvd::SharedFD & fd)51 bool USBCmdDataTransfer::OnResponse(bool is_success, const cvd::SharedFD& fd) {
52 if (!is_success) {
53 callback_(false, std::move(data_));
54 return true;
55 }
56
57 if (!req_.is_host_to_device) {
58 int32_t len;
59 if (fd->Read(&len, sizeof(len)) != sizeof(len)) {
60 LOG(ERROR) << "Short read: " << fd->StrError();
61 callback_(false, std::move(data_));
62 return false;
63 }
64
65 if (len > 0) {
66 data_.resize(len);
67 int32_t got = 0;
68 // Virtio sends data in 32k packets. We may have to do a few reads.
69 while (got < len) {
70 auto packetsize = fd->Read(&data_[got], len - got);
71 got += packetsize;
72
73 if (fd->GetErrno() != 0) {
74 // This could, technically, also be a disconnect.
75 LOG(ERROR) << "Read failed: " << fd->StrError();
76 return false;
77 } else if (packetsize == 0) {
78 LOG(ERROR) << "Short read; remote end disconnected.";
79 return false;
80 }
81 }
82 }
83 }
84
85 callback_(true, std::move(data_));
86 return true;
87 }
88 } // namespace vadb
89