blob: ce419b88d70836331f2e5797b973889f22a25197 [file] [log] [blame]
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001/*
2 * Copyright (C) 2007 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
Yabin Cui19bec5b2015-09-22 15:52:57 -070017#define TRACE_TAG TRANSPORT
Dan Albertdb6fe642015-03-19 15:21:08 -070018
19#include "sysdeps.h"
20#include "transport.h"
21
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -080022#include <stdio.h>
23#include <stdlib.h>
24#include <string.h>
25
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -080026#include "adb.h"
27
Yabin Cui3cf1b362017-03-10 16:01:01 -080028#if ADB_HOST
29
30static constexpr size_t MAX_USB_BULK_PACKET_SIZE = 1024u;
31
32// Call usb_read using a buffer having a multiple of MAX_USB_BULK_PACKET_SIZE bytes
33// to avoid overflow. See http://libusb.sourceforge.net/api-1.0/packetoverflow.html.
34static int UsbReadMessage(usb_handle* h, amessage* msg) {
35 D("UsbReadMessage");
36 char buffer[MAX_USB_BULK_PACKET_SIZE];
37 int n = usb_read(h, buffer, sizeof(buffer));
38 if (n == sizeof(*msg)) {
39 memcpy(msg, buffer, sizeof(*msg));
40 }
41 return n;
42}
43
44// Call usb_read using a buffer having a multiple of MAX_USB_BULK_PACKET_SIZE bytes
45// to avoid overflow. See http://libusb.sourceforge.net/api-1.0/packetoverflow.html.
46static int UsbReadPayload(usb_handle* h, apacket* p) {
47 D("UsbReadPayload");
48 size_t need_size = p->msg.data_length;
49 size_t data_pos = 0u;
50 while (need_size > 0u) {
51 int n = 0;
52 if (data_pos + MAX_USB_BULK_PACKET_SIZE <= sizeof(p->data)) {
53 // Read directly to p->data.
54 size_t rem_size = need_size % MAX_USB_BULK_PACKET_SIZE;
55 size_t direct_read_size = need_size - rem_size;
56 if (rem_size &&
57 data_pos + direct_read_size + MAX_USB_BULK_PACKET_SIZE <= sizeof(p->data)) {
58 direct_read_size += MAX_USB_BULK_PACKET_SIZE;
59 }
60 n = usb_read(h, &p->data[data_pos], direct_read_size);
61 if (n < 0) {
62 D("usb_read(size %zu) failed", direct_read_size);
63 return n;
64 }
65 } else {
66 // Read indirectly using a buffer.
67 char buffer[MAX_USB_BULK_PACKET_SIZE];
68 n = usb_read(h, buffer, sizeof(buffer));
69 if (n < 0) {
70 D("usb_read(size %zu) failed", sizeof(buffer));
71 return -1;
72 }
73 size_t copy_size = std::min(static_cast<size_t>(n), need_size);
74 D("usb read %d bytes, need %zu bytes, copy %zu bytes", n, need_size, copy_size);
75 memcpy(&p->data[data_pos], buffer, copy_size);
76 }
77 data_pos += n;
78 need_size -= std::min(static_cast<size_t>(n), need_size);
79 }
80 return static_cast<int>(data_pos);
81}
82
83static int remote_read(apacket* p, atransport* t) {
84 int n = UsbReadMessage(t->usb, &p->msg);
85 if (n < 0) {
86 D("remote usb: read terminated (message)");
87 return -1;
88 }
89 if (static_cast<size_t>(n) != sizeof(p->msg) || check_header(p, t)) {
90 D("remote usb: check_header failed, skip it");
91 goto err_msg;
92 }
93 if (t->GetConnectionState() == kCsOffline) {
94 // If we read a wrong msg header declaring a large message payload, don't read its payload.
95 // Otherwise we may miss true messages from the device.
96 if (p->msg.command != A_CNXN && p->msg.command != A_AUTH) {
97 goto err_msg;
98 }
99 }
100 if (p->msg.data_length) {
101 n = UsbReadPayload(t->usb, p);
102 if (n < 0) {
103 D("remote usb: terminated (data)");
104 return -1;
105 }
106 if (static_cast<uint32_t>(n) != p->msg.data_length) {
107 D("remote usb: read payload failed (need %u bytes, give %d bytes), skip it",
108 p->msg.data_length, n);
109 goto err_msg;
110 }
111 }
112 if (check_data(p)) {
113 D("remote usb: check_data failed, skip it");
114 goto err_msg;
115 }
116 return 0;
117
118err_msg:
119 p->msg.command = 0;
120 if (t->GetConnectionState() == kCsOffline) {
121 // If the data toggle of ep_out on device and ep_in on host are not the same, we may receive
122 // an error message. In this case, resend one A_CNXN message to connect the device.
123 if (t->SetSendConnectOnError()) {
124 SendConnectOnHost(t);
125 }
126 }
127 return 0;
128}
129
130#else
131
132// On Android devices, we rely on the kernel to provide buffered read.
133// So we can recover automatically from EOVERFLOW.
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800134static int remote_read(apacket *p, atransport *t)
135{
Yabin Cui3cf1b362017-03-10 16:01:01 -0800136 if (usb_read(t->usb, &p->msg, sizeof(amessage))) {
Yabin Cui815ad882015-09-02 17:44:28 -0700137 D("remote usb: read terminated (message)");
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800138 return -1;
139 }
140
Tamas Berghammera1c60c02015-07-13 19:12:28 +0100141 if(check_header(p, t)) {
Yabin Cui815ad882015-09-02 17:44:28 -0700142 D("remote usb: check_header failed");
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800143 return -1;
144 }
145
146 if(p->msg.data_length) {
Yabin Cui3cf1b362017-03-10 16:01:01 -0800147 if (usb_read(t->usb, p->data, p->msg.data_length)) {
Yabin Cui815ad882015-09-02 17:44:28 -0700148 D("remote usb: terminated (data)");
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800149 return -1;
150 }
151 }
152
153 if(check_data(p)) {
Yabin Cui815ad882015-09-02 17:44:28 -0700154 D("remote usb: check_data failed");
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800155 return -1;
156 }
157
158 return 0;
159}
Yabin Cui3cf1b362017-03-10 16:01:01 -0800160#endif
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800161
162static int remote_write(apacket *p, atransport *t)
163{
164 unsigned size = p->msg.data_length;
165
Yabin Cui3cf1b362017-03-10 16:01:01 -0800166 if (usb_write(t->usb, &p->msg, sizeof(amessage))) {
Yabin Cui815ad882015-09-02 17:44:28 -0700167 D("remote usb: 1 - write terminated");
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800168 return -1;
169 }
170 if(p->msg.data_length == 0) return 0;
Yabin Cui3cf1b362017-03-10 16:01:01 -0800171 if (usb_write(t->usb, &p->data, size)) {
Yabin Cui815ad882015-09-02 17:44:28 -0700172 D("remote usb: 2 - write terminated");
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800173 return -1;
174 }
175
176 return 0;
177}
178
179static void remote_close(atransport *t)
180{
181 usb_close(t->usb);
182 t->usb = 0;
183}
184
Yabin Cui3cf1b362017-03-10 16:01:01 -0800185static void remote_kick(atransport* t) {
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800186 usb_kick(t->usb);
187}
188
Yabin Cui3cf1b362017-03-10 16:01:01 -0800189void init_usb_transport(atransport* t, usb_handle* h) {
Yabin Cui815ad882015-09-02 17:44:28 -0700190 D("transport: usb");
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800191 t->close = remote_close;
Yabin Cuif2a9f9b2016-04-18 11:22:34 -0700192 t->SetKickFunction(remote_kick);
Yabin Cui3cf1b362017-03-10 16:01:01 -0800193 t->SetWriteFunction(remote_write);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800194 t->read_from_remote = remote_read;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800195 t->sync_token = 1;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800196 t->type = kTransportUsb;
197 t->usb = h;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800198}
199
Josh Gao08dda212016-09-26 21:18:58 -0700200int is_adb_interface(int usb_class, int usb_subclass, int usb_protocol)
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800201{
Elliott Hughes4b8538e2014-11-19 22:07:34 -0800202 return (usb_class == ADB_CLASS && usb_subclass == ADB_SUBCLASS && usb_protocol == ADB_PROTOCOL);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800203}
Josh Gao210b63f2017-02-22 17:07:01 -0800204
205bool should_use_libusb() {
206#if defined(_WIN32) || !ADB_HOST
207 return false;
208#else
Josh Gaof6ed63c2017-03-02 13:23:56 -0800209 static bool disable = getenv("ADB_LIBUSB") && strcmp(getenv("ADB_LIBUSB"), "0") == 0;
210 return !disable;
Josh Gao210b63f2017-02-22 17:07:01 -0800211#endif
212}