adb_client.c revision 408fa57864c01113deaa213e5c1848a9c594ae92
1#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
19static int __adb_server_port = DEFAULT_ADB_PORT;
20
21void adb_set_transport(transport_type type, const char* serial)
22{
23    __adb_transport = type;
24    __adb_serial = serial;
25}
26
27void adb_set_tcp_specifics(int server_port)
28{
29    __adb_server_port = server_port;
30}
31
32int  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
184    fd = socket_loopback_client(__adb_server_port, SOCK_STREAM);
185    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
205    D("_adb_connect: return fd %d\n", fd);
206    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
214    D("adb_connect: service %s\n", service);
215    if(fd == -2) {
216        fprintf(stdout,"* daemon not running. starting it now on port %d *\n",
217                __adb_server_port);
218    start_server:
219        if(launch_server(__adb_server_port)) {
220            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 */
226        adb_sleep_ms(3000);
227        // 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    }
271    D("adb_connect: return fd %d\n", fd);
272
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}
328