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