• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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) {
252         LOG(ERROR) << "ClientUsbTransport: no handle";
253         return -1;
254     }
255     if (len > SSIZE_MAX) {
256         LOG(ERROR) << "ClientUsbTransport: maximum length exceeds bounds";
257         return -1;
258     }
259     char* char_data = static_cast<char*>(data);
260     size_t bytes_read_total = 0;
261     while (bytes_read_total < len) {
262         auto bytes_to_read = std::min(len - bytes_read_total, kFbFfsNumBufs * kFbFfsBufSize);
263         auto bytes_read_now =
264                 handle_->read(handle_.get(), char_data, bytes_to_read, true /* allow_partial */);
265         if (bytes_read_now < 0) {
266             PLOG(ERROR) << "ClientUsbTransport: read failed";
267             return bytes_read_total == 0 ? -1 : bytes_read_total;
268         }
269         bytes_read_total += bytes_read_now;
270         char_data += bytes_read_now;
271         if (static_cast<size_t>(bytes_read_now) < bytes_to_read) {
272             break;
273         }
274     }
275     return bytes_read_total;
276 }
277 
Write(const void * data,size_t len)278 ssize_t ClientUsbTransport::Write(const void* data, size_t len) {
279     if (handle_ == nullptr || len > SSIZE_MAX) {
280         return -1;
281     }
282     const char* char_data = reinterpret_cast<const char*>(data);
283     size_t bytes_written_total = 0;
284     while (bytes_written_total < len) {
285         auto bytes_to_write = std::min(len - bytes_written_total, kFbFfsNumBufs * kFbFfsBufSize);
286         auto bytes_written_now = handle_->write(handle_.get(), char_data, bytes_to_write);
287         if (bytes_written_now < 0) {
288             return bytes_written_total == 0 ? -1 : bytes_written_total;
289         }
290         bytes_written_total += bytes_written_now;
291         char_data += bytes_written_now;
292         if (static_cast<size_t>(bytes_written_now) < bytes_to_write) {
293             break;
294         }
295     }
296     return bytes_written_total;
297 }
298 
Close()299 int ClientUsbTransport::Close() {
300     if (handle_ == nullptr) {
301         return -1;
302     }
303     CloseFunctionFs(handle_.get());
304     return 0;
305 }
306 
Reset()307 int ClientUsbTransport::Reset() {
308     return 0;
309 }
310