1 /*
2 * Copyright (C) 2018 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
17 #include "usb_client.h"
18
19 #include <endian.h>
20 #include <fcntl.h>
21 #include <linux/usb/ch9.h>
22 #include <linux/usb/functionfs.h>
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <sys/stat.h>
26 #include <sys/types.h>
27
28 #include <android-base/logging.h>
29 #include <android-base/properties.h>
30
31 constexpr int kMaxPacketSizeFs = 64;
32 constexpr int kMaxPacketSizeHs = 512;
33 constexpr int kMaxPacketsizeSs = 1024;
34
35 constexpr size_t kFbFfsNumBufs = 16;
36 constexpr size_t kFbFfsBufSize = 16384;
37
38 constexpr const char* kUsbFfsFastbootEp0 = "/dev/usb-ffs/fastboot/ep0";
39 constexpr const char* kUsbFfsFastbootOut = "/dev/usb-ffs/fastboot/ep1";
40 constexpr const char* kUsbFfsFastbootIn = "/dev/usb-ffs/fastboot/ep2";
41
42 struct FuncDesc {
43 struct usb_interface_descriptor intf;
44 struct usb_endpoint_descriptor_no_audio source;
45 struct usb_endpoint_descriptor_no_audio sink;
46 } __attribute__((packed));
47
48 struct SsFuncDesc {
49 struct usb_interface_descriptor intf;
50 struct usb_endpoint_descriptor_no_audio source;
51 struct usb_ss_ep_comp_descriptor source_comp;
52 struct usb_endpoint_descriptor_no_audio sink;
53 struct usb_ss_ep_comp_descriptor sink_comp;
54 } __attribute__((packed));
55
56 struct DescV2 {
57 struct usb_functionfs_descs_head_v2 header;
58 // The rest of the structure depends on the flags in the header.
59 __le32 fs_count;
60 __le32 hs_count;
61 __le32 ss_count;
62 struct FuncDesc fs_descs, hs_descs;
63 struct SsFuncDesc ss_descs;
64 } __attribute__((packed));
65
66 struct usb_interface_descriptor fastboot_interface = {
67 .bLength = USB_DT_INTERFACE_SIZE,
68 .bDescriptorType = USB_DT_INTERFACE,
69 .bInterfaceNumber = 0,
70 .bNumEndpoints = 2,
71 .bInterfaceClass = USB_CLASS_VENDOR_SPEC,
72 .bInterfaceSubClass = 66,
73 .bInterfaceProtocol = 3,
74 .iInterface = 1, /* first string from the provided table */
75 };
76
77 static struct FuncDesc fs_descriptors = {
78 .intf = fastboot_interface,
79 .source =
80 {
81 .bLength = sizeof(fs_descriptors.source),
82 .bDescriptorType = USB_DT_ENDPOINT,
83 .bEndpointAddress = 1 | USB_DIR_OUT,
84 .bmAttributes = USB_ENDPOINT_XFER_BULK,
85 .wMaxPacketSize = kMaxPacketSizeFs,
86 },
87 .sink =
88 {
89 .bLength = sizeof(fs_descriptors.sink),
90 .bDescriptorType = USB_DT_ENDPOINT,
91 .bEndpointAddress = 1 | USB_DIR_IN,
92 .bmAttributes = USB_ENDPOINT_XFER_BULK,
93 .wMaxPacketSize = kMaxPacketSizeFs,
94 },
95 };
96
97 static struct FuncDesc hs_descriptors = {
98 .intf = fastboot_interface,
99 .source =
100 {
101 .bLength = sizeof(hs_descriptors.source),
102 .bDescriptorType = USB_DT_ENDPOINT,
103 .bEndpointAddress = 1 | USB_DIR_OUT,
104 .bmAttributes = USB_ENDPOINT_XFER_BULK,
105 .wMaxPacketSize = kMaxPacketSizeHs,
106 },
107 .sink =
108 {
109 .bLength = sizeof(hs_descriptors.sink),
110 .bDescriptorType = USB_DT_ENDPOINT,
111 .bEndpointAddress = 1 | USB_DIR_IN,
112 .bmAttributes = USB_ENDPOINT_XFER_BULK,
113 .wMaxPacketSize = kMaxPacketSizeHs,
114 },
115 };
116
117 static struct SsFuncDesc ss_descriptors = {
118 .intf = fastboot_interface,
119 .source =
120 {
121 .bLength = sizeof(ss_descriptors.source),
122 .bDescriptorType = USB_DT_ENDPOINT,
123 .bEndpointAddress = 1 | USB_DIR_OUT,
124 .bmAttributes = USB_ENDPOINT_XFER_BULK,
125 .wMaxPacketSize = kMaxPacketsizeSs,
126 },
127 .source_comp =
128 {
129 .bLength = sizeof(ss_descriptors.source_comp),
130 .bDescriptorType = USB_DT_SS_ENDPOINT_COMP,
131 .bMaxBurst = 15,
132 },
133 .sink =
134 {
135 .bLength = sizeof(ss_descriptors.sink),
136 .bDescriptorType = USB_DT_ENDPOINT,
137 .bEndpointAddress = 1 | USB_DIR_IN,
138 .bmAttributes = USB_ENDPOINT_XFER_BULK,
139 .wMaxPacketSize = kMaxPacketsizeSs,
140 },
141 .sink_comp =
142 {
143 .bLength = sizeof(ss_descriptors.sink_comp),
144 .bDescriptorType = USB_DT_SS_ENDPOINT_COMP,
145 .bMaxBurst = 15,
146 },
147 };
148
149 #define STR_INTERFACE_ "fastbootd"
150
151 static const struct {
152 struct usb_functionfs_strings_head header;
153 struct {
154 __le16 code;
155 const char str1[sizeof(STR_INTERFACE_)];
156 } __attribute__((packed)) lang0;
157 } __attribute__((packed)) strings = {
158 .header =
159 {
160 .magic = htole32(FUNCTIONFS_STRINGS_MAGIC),
161 .length = htole32(sizeof(strings)),
162 .str_count = htole32(1),
163 .lang_count = htole32(1),
164 },
165 .lang0 =
166 {
167 htole16(0x0409), /* en-us */
168 STR_INTERFACE_,
169 },
170 };
171
172 static struct DescV2 v2_descriptor = {
173 .header =
174 {
175 .magic = htole32(FUNCTIONFS_DESCRIPTORS_MAGIC_V2),
176 .length = htole32(sizeof(v2_descriptor)),
177 .flags = FUNCTIONFS_HAS_FS_DESC | FUNCTIONFS_HAS_HS_DESC |
178 FUNCTIONFS_HAS_SS_DESC,
179 },
180 .fs_count = 3,
181 .hs_count = 3,
182 .ss_count = 5,
183 .fs_descs = fs_descriptors,
184 .hs_descs = hs_descriptors,
185 .ss_descs = ss_descriptors,
186 };
187
188 // Reimplementing since usb_ffs_close() does not close the control FD.
CloseFunctionFs(usb_handle * h)189 static void CloseFunctionFs(usb_handle* h) {
190 h->bulk_in.reset();
191 h->bulk_out.reset();
192 h->control.reset();
193 }
194
InitFunctionFs(usb_handle * h)195 static bool InitFunctionFs(usb_handle* h) {
196 LOG(INFO) << "initializing functionfs";
197
198 if (h->control < 0) { // might have already done this before
199 LOG(INFO) << "opening control endpoint " << kUsbFfsFastbootEp0;
200 h->control.reset(open(kUsbFfsFastbootEp0, O_RDWR));
201 if (h->control < 0) {
202 PLOG(ERROR) << "cannot open control endpoint " << kUsbFfsFastbootEp0;
203 goto err;
204 }
205
206 auto ret = write(h->control.get(), &v2_descriptor, sizeof(v2_descriptor));
207 if (ret < 0) {
208 PLOG(ERROR) << "cannot write descriptors " << kUsbFfsFastbootEp0;
209 goto err;
210 }
211
212 ret = write(h->control.get(), &strings, sizeof(strings));
213 if (ret < 0) {
214 PLOG(ERROR) << "cannot write strings " << kUsbFfsFastbootEp0;
215 goto err;
216 }
217 // Signal only when writing the descriptors to ffs
218 android::base::SetProperty("sys.usb.ffs.ready", "1");
219 }
220
221 h->bulk_out.reset(open(kUsbFfsFastbootOut, O_RDONLY));
222 if (h->bulk_out < 0) {
223 PLOG(ERROR) << "cannot open bulk-out endpoint " << kUsbFfsFastbootOut;
224 goto err;
225 }
226
227 h->bulk_in.reset(open(kUsbFfsFastbootIn, O_WRONLY));
228 if (h->bulk_in < 0) {
229 PLOG(ERROR) << "cannot open bulk-in endpoint " << kUsbFfsFastbootIn;
230 goto err;
231 }
232
233 h->read_aiob.fd = h->bulk_out.get();
234 h->write_aiob.fd = h->bulk_in.get();
235 h->reads_zero_packets = false;
236 return true;
237
238 err:
239 CloseFunctionFs(h);
240 return false;
241 }
242
ClientUsbTransport()243 ClientUsbTransport::ClientUsbTransport()
244 : handle_(std::unique_ptr<usb_handle>(create_usb_handle(kFbFfsNumBufs, kFbFfsBufSize))) {
245 if (!InitFunctionFs(handle_.get())) {
246 handle_.reset(nullptr);
247 }
248 }
249
Read(void * data,size_t len)250 ssize_t ClientUsbTransport::Read(void* data, size_t len) {
251 if (handle_ == nullptr || len > SSIZE_MAX) {
252 return -1;
253 }
254 char* char_data = static_cast<char*>(data);
255 size_t bytes_read_total = 0;
256 while (bytes_read_total < len) {
257 auto bytes_to_read = std::min(len - bytes_read_total, kFbFfsNumBufs * kFbFfsBufSize);
258 auto bytes_read_now =
259 handle_->read(handle_.get(), char_data, bytes_to_read, true /* allow_partial */);
260 if (bytes_read_now < 0) {
261 return bytes_read_total == 0 ? -1 : bytes_read_total;
262 }
263 bytes_read_total += bytes_read_now;
264 char_data += bytes_read_now;
265 if (static_cast<size_t>(bytes_read_now) < bytes_to_read) {
266 break;
267 }
268 }
269 return bytes_read_total;
270 }
271
Write(const void * data,size_t len)272 ssize_t ClientUsbTransport::Write(const void* data, size_t len) {
273 if (handle_ == nullptr || len > SSIZE_MAX) {
274 return -1;
275 }
276 const char* char_data = reinterpret_cast<const char*>(data);
277 size_t bytes_written_total = 0;
278 while (bytes_written_total < len) {
279 auto bytes_to_write = std::min(len - bytes_written_total, kFbFfsNumBufs * kFbFfsBufSize);
280 auto bytes_written_now = handle_->write(handle_.get(), data, bytes_to_write);
281 if (bytes_written_now < 0) {
282 return bytes_written_total == 0 ? -1 : bytes_written_total;
283 }
284 bytes_written_total += bytes_written_now;
285 char_data += bytes_written_now;
286 if (static_cast<size_t>(bytes_written_now) < bytes_to_write) {
287 break;
288 }
289 }
290 return bytes_written_total;
291 }
292
Close()293 int ClientUsbTransport::Close() {
294 if (handle_ == nullptr) {
295 return -1;
296 }
297 CloseFunctionFs(handle_.get());
298 return 0;
299 }
300
Reset()301 int ClientUsbTransport::Reset() {
302 return 0;
303 }
304