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