blob: 9a812f0cf68afae30b6e70b0de70297f7462055e [file] [log] [blame]
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001#include <stdio.h>
2#include <stdlib.h>
3#include <string.h>
4#include <errno.h>
5#include <limits.h>
6#include <stdarg.h>
7#include <zipfile/zipfile.h>
8#include <sys/types.h>
9#include <sys/stat.h>
10
11#include "sysdeps.h"
12
13#define TRACE_TAG TRACE_ADB
14#include "adb_client.h"
15
16static transport_type __adb_transport = kTransportAny;
17static const char* __adb_serial = NULL;
18
Stefan Hilzingerd0eacb82010-04-19 12:21:12 +010019static int __adb_server_port = DEFAULT_ADB_PORT;
20
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080021void adb_set_transport(transport_type type, const char* serial)
22{
23 __adb_transport = type;
24 __adb_serial = serial;
25}
26
Stefan Hilzingerd0eacb82010-04-19 12:21:12 +010027void adb_set_tcp_specifics(int server_port)
28{
29 __adb_server_port = server_port;
30}
31
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080032int adb_get_emulator_console_port(void)
33{
34 const char* serial = __adb_serial;
35 int port;
36
37 if (serial == NULL) {
38 /* if no specific device was specified, we need to look at */
39 /* the list of connected devices, and extract an emulator */
40 /* name from it. two emulators is an error */
41 char* tmp = adb_query("host:devices");
42 char* p = tmp;
43 if(!tmp) {
44 printf("no emulator connected\n");
45 return -1;
46 }
47 while (*p) {
48 char* q = strchr(p, '\n');
49 if (q != NULL)
50 *q++ = 0;
51 else
52 q = p + strlen(p);
53
54 if (!memcmp(p, LOCAL_CLIENT_PREFIX, sizeof(LOCAL_CLIENT_PREFIX)-1)) {
55 if (serial != NULL) { /* more than one emulator listed */
56 free(tmp);
57 return -2;
58 }
59 serial = p;
60 }
61
62 p = q;
63 }
64 free(tmp);
65
66 if (serial == NULL)
67 return -1; /* no emulator found */
68 }
69 else {
70 if (memcmp(serial, LOCAL_CLIENT_PREFIX, sizeof(LOCAL_CLIENT_PREFIX)-1) != 0)
71 return -1; /* not an emulator */
72 }
73
74 serial += sizeof(LOCAL_CLIENT_PREFIX)-1;
75 port = strtol(serial, NULL, 10);
76 return port;
77}
78
79static char __adb_error[256] = { 0 };
80
81const char *adb_error(void)
82{
83 return __adb_error;
84}
85
86static int switch_socket_transport(int fd)
87{
88 char service[64];
89 char tmp[5];
90 int len;
91
92 if (__adb_serial)
93 snprintf(service, sizeof service, "host:transport:%s", __adb_serial);
94 else {
95 char* transport_type = "???";
96
97 switch (__adb_transport) {
98 case kTransportUsb:
99 transport_type = "transport-usb";
100 break;
101 case kTransportLocal:
102 transport_type = "transport-local";
103 break;
104 case kTransportAny:
105 transport_type = "transport-any";
106 break;
107 case kTransportHost:
108 // no switch necessary
109 return 0;
110 break;
111 }
112
113 snprintf(service, sizeof service, "host:%s", transport_type);
114 }
115 len = strlen(service);
116 snprintf(tmp, sizeof tmp, "%04x", len);
117
118 if(writex(fd, tmp, 4) || writex(fd, service, len)) {
119 strcpy(__adb_error, "write failure during connection");
120 adb_close(fd);
121 return -1;
122 }
123 D("Switch transport in progress\n");
124
125 if(adb_status(fd)) {
126 adb_close(fd);
127 D("Switch transport failed\n");
128 return -1;
129 }
130 D("Switch transport success\n");
131 return 0;
132}
133
134int adb_status(int fd)
135{
136 unsigned char buf[5];
137 unsigned len;
138
139 if(readx(fd, buf, 4)) {
140 strcpy(__adb_error, "protocol fault (no status)");
141 return -1;
142 }
143
144 if(!memcmp(buf, "OKAY", 4)) {
145 return 0;
146 }
147
148 if(memcmp(buf, "FAIL", 4)) {
149 sprintf(__adb_error,
150 "protocol fault (status %02x %02x %02x %02x?!)",
151 buf[0], buf[1], buf[2], buf[3]);
152 return -1;
153 }
154
155 if(readx(fd, buf, 4)) {
156 strcpy(__adb_error, "protocol fault (status len)");
157 return -1;
158 }
159 buf[4] = 0;
160 len = strtoul((char*)buf, 0, 16);
161 if(len > 255) len = 255;
162 if(readx(fd, __adb_error, len)) {
163 strcpy(__adb_error, "protocol fault (status read)");
164 return -1;
165 }
166 __adb_error[len] = 0;
167 return -1;
168}
169
170int _adb_connect(const char *service)
171{
172 char tmp[5];
173 int len;
174 int fd;
175
176 D("_adb_connect: %s\n", service);
177 len = strlen(service);
178 if((len < 1) || (len > 1024)) {
179 strcpy(__adb_error, "service name too long");
180 return -1;
181 }
182 snprintf(tmp, sizeof tmp, "%04x", len);
183
Stefan Hilzingerd0eacb82010-04-19 12:21:12 +0100184 fd = socket_loopback_client(__adb_server_port, SOCK_STREAM);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800185 if(fd < 0) {
186 strcpy(__adb_error, "cannot connect to daemon");
187 return -2;
188 }
189
190 if (memcmp(service,"host",4) != 0 && switch_socket_transport(fd)) {
191 return -1;
192 }
193
194 if(writex(fd, tmp, 4) || writex(fd, service, len)) {
195 strcpy(__adb_error, "write failure during connection");
196 adb_close(fd);
197 return -1;
198 }
199
200 if(adb_status(fd)) {
201 adb_close(fd);
202 return -1;
203 }
204
JP Abgrall408fa572011-03-16 15:57:42 -0700205 D("_adb_connect: return fd %d\n", fd);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800206 return fd;
207}
208
209int adb_connect(const char *service)
210{
211 // first query the adb server's version
212 int fd = _adb_connect("host:version");
213
JP Abgrall408fa572011-03-16 15:57:42 -0700214 D("adb_connect: service %s\n", service);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800215 if(fd == -2) {
Stefan Hilzingerd0eacb82010-04-19 12:21:12 +0100216 fprintf(stdout,"* daemon not running. starting it now on port %d *\n",
217 __adb_server_port);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800218 start_server:
Stefan Hilzingerd0eacb82010-04-19 12:21:12 +0100219 if(launch_server(__adb_server_port)) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800220 fprintf(stderr,"* failed to start daemon *\n");
221 return -1;
222 } else {
223 fprintf(stdout,"* daemon started successfully *\n");
224 }
225 /* give the server some time to start properly and detect devices */
Xavier Ducroheta481d092009-05-21 17:47:43 -0700226 adb_sleep_ms(3000);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800227 // fall through to _adb_connect
228 } else {
229 // if server was running, check its version to make sure it is not out of date
230 char buf[100];
231 int n;
232 int version = ADB_SERVER_VERSION - 1;
233
234 // if we have a file descriptor, then parse version result
235 if(fd >= 0) {
236 if(readx(fd, buf, 4)) goto error;
237
238 buf[4] = 0;
239 n = strtoul(buf, 0, 16);
240 if(n > (int)sizeof(buf)) goto error;
241 if(readx(fd, buf, n)) goto error;
242 adb_close(fd);
243
244 if (sscanf(buf, "%04x", &version) != 1) goto error;
245 } else {
246 // if fd is -1, then check for "unknown host service",
247 // which would indicate a version of adb that does not support the version command
248 if (strcmp(__adb_error, "unknown host service") != 0)
249 return fd;
250 }
251
252 if(version != ADB_SERVER_VERSION) {
253 printf("adb server is out of date. killing...\n");
254 fd = _adb_connect("host:kill");
255 adb_close(fd);
256
257 /* XXX can we better detect its death? */
258 adb_sleep_ms(2000);
259 goto start_server;
260 }
261 }
262
263 // if the command is start-server, we are done.
264 if (!strcmp(service, "host:start-server"))
265 return 0;
266
267 fd = _adb_connect(service);
268 if(fd == -2) {
269 fprintf(stderr,"** daemon still not running");
270 }
JP Abgrall408fa572011-03-16 15:57:42 -0700271 D("adb_connect: return fd %d\n", fd);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800272
273 return fd;
274error:
275 adb_close(fd);
276 return -1;
277}
278
279
280int adb_command(const char *service)
281{
282 int fd = adb_connect(service);
283 if(fd < 0) {
284 return -1;
285 }
286
287 if(adb_status(fd)) {
288 adb_close(fd);
289 return -1;
290 }
291
292 return 0;
293}
294
295char *adb_query(const char *service)
296{
297 char buf[5];
298 unsigned n;
299 char *tmp;
300
301 D("adb_query: %s\n", service);
302 int fd = adb_connect(service);
303 if(fd < 0) {
304 fprintf(stderr,"error: %s\n", __adb_error);
305 return 0;
306 }
307
308 if(readx(fd, buf, 4)) goto oops;
309
310 buf[4] = 0;
311 n = strtoul(buf, 0, 16);
312 if(n > 1024) goto oops;
313
314 tmp = malloc(n + 1);
315 if(tmp == 0) goto oops;
316
317 if(readx(fd, tmp, n) == 0) {
318 tmp[n] = 0;
319 adb_close(fd);
320 return tmp;
321 }
322 free(tmp);
323
324oops:
325 adb_close(fd);
326 return 0;
327}