diff options
Diffstat (limited to 'minadbd')
-rw-r--r-- | minadbd/Android.mk | 44 | ||||
-rw-r--r-- | minadbd/README.txt | 37 | ||||
-rw-r--r-- | minadbd/adb.c | 402 | ||||
-rw-r--r-- | minadbd/adb.h | 424 | ||||
-rw-r--r-- | minadbd/adb_main.cpp (renamed from minadbd/transport.h) | 39 | ||||
-rw-r--r-- | minadbd/fdevent.c | 695 | ||||
-rw-r--r-- | minadbd/fdevent.h | 83 | ||||
-rw-r--r-- | minadbd/fuse_adb_provider.cpp (renamed from minadbd/fuse_adb_provider.c) | 21 | ||||
-rw-r--r-- | minadbd/fuse_adb_provider.h | 10 | ||||
-rw-r--r-- | minadbd/fuse_adb_provider_test.cpp | 88 | ||||
-rw-r--r-- | minadbd/mutex_list.h | 26 | ||||
-rw-r--r-- | minadbd/services.cpp (renamed from minadbd/services.c) | 76 | ||||
-rw-r--r-- | minadbd/sockets.c | 731 | ||||
-rw-r--r-- | minadbd/sysdeps.h | 494 | ||||
-rw-r--r-- | minadbd/transport.c | 803 | ||||
-rw-r--r-- | minadbd/transport_usb.c | 121 | ||||
-rw-r--r-- | minadbd/usb_linux_client.c | 493 | ||||
-rw-r--r-- | minadbd/utils.c | 106 | ||||
-rw-r--r-- | minadbd/utils.h | 68 |
19 files changed, 181 insertions, 4580 deletions
diff --git a/minadbd/Android.mk b/minadbd/Android.mk index 04956d870..cbfd76e4e 100644 --- a/minadbd/Android.mk +++ b/minadbd/Android.mk @@ -1,32 +1,36 @@ # Copyright 2005 The Android Open Source Project -# -# Android.mk for adb -# LOCAL_PATH:= $(call my-dir) -# minadbd library -# ========================================================= +minadbd_cflags := \ + -Wall -Werror \ + -Wno-unused-parameter \ + -Wno-missing-field-initializers \ + -DADB_HOST=0 \ include $(CLEAR_VARS) LOCAL_SRC_FILES := \ - adb.c \ - fdevent.c \ - fuse_adb_provider.c \ - transport.c \ - transport_usb.c \ - sockets.c \ - services.c \ - usb_linux_client.c \ - utils.c - -LOCAL_CFLAGS := -O2 -g -DADB_HOST=0 -Wall -Wno-unused-parameter -LOCAL_CFLAGS += -D_XOPEN_SOURCE -D_GNU_SOURCE -LOCAL_C_INCLUDES += bootable/recovery + adb_main.cpp \ + fuse_adb_provider.cpp \ + services.cpp \ LOCAL_MODULE := libminadbd - -LOCAL_STATIC_LIBRARIES := libfusesideload libcutils libc +LOCAL_CFLAGS := $(minadbd_cflags) +LOCAL_CONLY_FLAGS := -Wimplicit-function-declaration +LOCAL_C_INCLUDES := bootable/recovery system/core/adb +LOCAL_WHOLE_STATIC_LIBRARIES := libadbd include $(BUILD_STATIC_LIBRARY) + +include $(CLEAR_VARS) + +LOCAL_CLANG := true +LOCAL_MODULE := minadbd_test +LOCAL_SRC_FILES := fuse_adb_provider_test.cpp +LOCAL_CFLAGS := $(minadbd_cflags) +LOCAL_C_INCLUDES := $(LOCAL_PATH) system/core/adb +LOCAL_STATIC_LIBRARIES := libminadbd +LOCAL_SHARED_LIBRARIES := liblog + +include $(BUILD_NATIVE_TEST) diff --git a/minadbd/README.txt b/minadbd/README.txt index c9df484c3..e69dc87c6 100644 --- a/minadbd/README.txt +++ b/minadbd/README.txt @@ -1,39 +1,8 @@ -The contents of this directory are copied from system/core/adb, with -the following changes: +minadbd is now mostly built from libadbd. The fuse features are unique to +minadbd, and services.c has been modified as follows: -adb.c - - much support for host mode and non-linux OS's stripped out; this - version only runs as adbd on the device. - - always setuid/setgid's itself to the shell user - - only uses USB transport - - references to JDWP removed - - main() removed - - all ADB_HOST and win32 code removed - - removed listeners, logging code, background server (for host) - -adb.h - - minor changes to match adb.c changes - -sockets.c - - references to JDWP removed - - ADB_HOST code removed - -services.c - - all services except echo_service (which is commented out) removed + - all services removed - all host mode support removed - sideload_service() added; this is the only service supported. It receives a single blob of data, writes it to a fixed filename, and makes the process exit. - -Android.mk - - only builds in adbd mode; builds as static library instead of a - standalone executable. - -sysdeps.h - - changes adb_creat() to use O_NOFOLLOW - -transport.c - - removed ADB_HOST code - -transport_usb.c - - removed ADB_HOST code diff --git a/minadbd/adb.c b/minadbd/adb.c deleted file mode 100644 index 127d072be..000000000 --- a/minadbd/adb.c +++ /dev/null @@ -1,402 +0,0 @@ -/* - * Copyright (C) 2007 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#define TRACE_TAG TRACE_ADB - -#include <stdio.h> -#include <stdlib.h> -#include <ctype.h> -#include <stdarg.h> -#include <errno.h> -#include <string.h> -#include <time.h> -#include <sys/time.h> - -#include "sysdeps.h" -#include "adb.h" - -#include <private/android_filesystem_config.h> - -#if ADB_TRACE -ADB_MUTEX_DEFINE( D_lock ); -#endif - -int HOST = 0; - -static const char *adb_device_banner = "sideload"; - -void fatal(const char *fmt, ...) -{ - va_list ap; - va_start(ap, fmt); - fprintf(stderr, "error: "); - vfprintf(stderr, fmt, ap); - fprintf(stderr, "\n"); - va_end(ap); - exit(-1); -} - -void fatal_errno(const char *fmt, ...) -{ - va_list ap; - va_start(ap, fmt); - fprintf(stderr, "error: %s: ", strerror(errno)); - vfprintf(stderr, fmt, ap); - fprintf(stderr, "\n"); - va_end(ap); - exit(-1); -} - -int adb_trace_mask; - -/* read a comma/space/colum/semi-column separated list of tags - * from the ADB_TRACE environment variable and build the trace - * mask from it. note that '1' and 'all' are special cases to - * enable all tracing - */ -void adb_trace_init(void) -{ - const char* p = getenv("ADB_TRACE"); - const char* q; - - static const struct { - const char* tag; - int flag; - } tags[] = { - { "1", 0 }, - { "all", 0 }, - { "adb", TRACE_ADB }, - { "sockets", TRACE_SOCKETS }, - { "packets", TRACE_PACKETS }, - { "rwx", TRACE_RWX }, - { "usb", TRACE_USB }, - { "sync", TRACE_SYNC }, - { "sysdeps", TRACE_SYSDEPS }, - { "transport", TRACE_TRANSPORT }, - { "jdwp", TRACE_JDWP }, - { "services", TRACE_SERVICES }, - { NULL, 0 } - }; - - if (p == NULL) - return; - - /* use a comma/column/semi-colum/space separated list */ - while (*p) { - int len, tagn; - - q = strpbrk(p, " ,:;"); - if (q == NULL) { - q = p + strlen(p); - } - len = q - p; - - for (tagn = 0; tags[tagn].tag != NULL; tagn++) - { - int taglen = strlen(tags[tagn].tag); - - if (len == taglen && !memcmp(tags[tagn].tag, p, len) ) - { - int flag = tags[tagn].flag; - if (flag == 0) { - adb_trace_mask = ~0; - return; - } - adb_trace_mask |= (1 << flag); - break; - } - } - p = q; - if (*p) - p++; - } -} - - -apacket *get_apacket(void) -{ - apacket *p = malloc(sizeof(apacket)); - if(p == 0) fatal("failed to allocate an apacket"); - memset(p, 0, sizeof(apacket) - MAX_PAYLOAD); - return p; -} - -void put_apacket(apacket *p) -{ - free(p); -} - -void handle_online(void) -{ - D("adb: online\n"); -} - -void handle_offline(atransport *t) -{ - D("adb: offline\n"); - //Close the associated usb - run_transport_disconnects(t); -} - -#if TRACE_PACKETS -#define DUMPMAX 32 -void print_packet(const char *label, apacket *p) -{ - char *tag; - char *x; - unsigned count; - - switch(p->msg.command){ - case A_SYNC: tag = "SYNC"; break; - case A_CNXN: tag = "CNXN" ; break; - case A_OPEN: tag = "OPEN"; break; - case A_OKAY: tag = "OKAY"; break; - case A_CLSE: tag = "CLSE"; break; - case A_WRTE: tag = "WRTE"; break; - default: tag = "????"; break; - } - - fprintf(stderr, "%s: %s %08x %08x %04x \"", - label, tag, p->msg.arg0, p->msg.arg1, p->msg.data_length); - count = p->msg.data_length; - x = (char*) p->data; - if(count > DUMPMAX) { - count = DUMPMAX; - tag = "\n"; - } else { - tag = "\"\n"; - } - while(count-- > 0){ - if((*x >= ' ') && (*x < 127)) { - fputc(*x, stderr); - } else { - fputc('.', stderr); - } - x++; - } - fprintf(stderr, tag); -} -#endif - -static void send_ready(unsigned local, unsigned remote, atransport *t) -{ - D("Calling send_ready \n"); - apacket *p = get_apacket(); - p->msg.command = A_OKAY; - p->msg.arg0 = local; - p->msg.arg1 = remote; - send_packet(p, t); -} - -static void send_close(unsigned local, unsigned remote, atransport *t) -{ - D("Calling send_close \n"); - apacket *p = get_apacket(); - p->msg.command = A_CLSE; - p->msg.arg0 = local; - p->msg.arg1 = remote; - send_packet(p, t); -} - -static void send_connect(atransport *t) -{ - D("Calling send_connect \n"); - apacket *cp = get_apacket(); - cp->msg.command = A_CNXN; - cp->msg.arg0 = A_VERSION; - cp->msg.arg1 = MAX_PAYLOAD; - snprintf((char*) cp->data, sizeof cp->data, "%s::", - HOST ? "host" : adb_device_banner); - cp->msg.data_length = strlen((char*) cp->data) + 1; - send_packet(cp, t); -} - -void parse_banner(char *banner, atransport *t) -{ - char *type, *product, *end; - - D("parse_banner: %s\n", banner); - type = banner; - product = strchr(type, ':'); - if(product) { - *product++ = 0; - } else { - product = ""; - } - - /* remove trailing ':' */ - end = strchr(product, ':'); - if(end) *end = 0; - - /* save product name in device structure */ - if (t->product == NULL) { - t->product = strdup(product); - } else if (strcmp(product, t->product) != 0) { - free(t->product); - t->product = strdup(product); - } - - if(!strcmp(type, "bootloader")){ - D("setting connection_state to CS_BOOTLOADER\n"); - t->connection_state = CS_BOOTLOADER; - update_transports(); - return; - } - - if(!strcmp(type, "device")) { - D("setting connection_state to CS_DEVICE\n"); - t->connection_state = CS_DEVICE; - update_transports(); - return; - } - - if(!strcmp(type, "recovery")) { - D("setting connection_state to CS_RECOVERY\n"); - t->connection_state = CS_RECOVERY; - update_transports(); - return; - } - - if(!strcmp(type, "sideload")) { - D("setting connection_state to CS_SIDELOAD\n"); - t->connection_state = CS_SIDELOAD; - update_transports(); - return; - } - - t->connection_state = CS_HOST; -} - -void handle_packet(apacket *p, atransport *t) -{ - asocket *s; - - D("handle_packet() %c%c%c%c\n", ((char*) (&(p->msg.command)))[0], - ((char*) (&(p->msg.command)))[1], - ((char*) (&(p->msg.command)))[2], - ((char*) (&(p->msg.command)))[3]); - print_packet("recv", p); - - switch(p->msg.command){ - case A_SYNC: - if(p->msg.arg0){ - send_packet(p, t); - if(HOST) send_connect(t); - } else { - t->connection_state = CS_OFFLINE; - handle_offline(t); - send_packet(p, t); - } - return; - - case A_CNXN: /* CONNECT(version, maxdata, "system-id-string") */ - /* XXX verify version, etc */ - if(t->connection_state != CS_OFFLINE) { - t->connection_state = CS_OFFLINE; - handle_offline(t); - } - parse_banner((char*) p->data, t); - handle_online(); - if(!HOST) send_connect(t); - break; - - case A_OPEN: /* OPEN(local-id, 0, "destination") */ - if(t->connection_state != CS_OFFLINE) { - char *name = (char*) p->data; - name[p->msg.data_length > 0 ? p->msg.data_length - 1 : 0] = 0; - s = create_local_service_socket(name); - if(s == 0) { - send_close(0, p->msg.arg0, t); - } else { - s->peer = create_remote_socket(p->msg.arg0, t); - s->peer->peer = s; - send_ready(s->id, s->peer->id, t); - s->ready(s); - } - } - break; - - case A_OKAY: /* READY(local-id, remote-id, "") */ - if(t->connection_state != CS_OFFLINE) { - if((s = find_local_socket(p->msg.arg1))) { - if(s->peer == 0) { - s->peer = create_remote_socket(p->msg.arg0, t); - s->peer->peer = s; - } - s->ready(s); - } - } - break; - - case A_CLSE: /* CLOSE(local-id, remote-id, "") */ - if(t->connection_state != CS_OFFLINE) { - if((s = find_local_socket(p->msg.arg1))) { - s->close(s); - } - } - break; - - case A_WRTE: - if(t->connection_state != CS_OFFLINE) { - if((s = find_local_socket(p->msg.arg1))) { - unsigned rid = p->msg.arg0; - p->len = p->msg.data_length; - - if(s->enqueue(s, p) == 0) { - D("Enqueue the socket\n"); - send_ready(s->id, rid, t); - } - return; - } - } - break; - - default: - printf("handle_packet: what is %08x?!\n", p->msg.command); - } - - put_apacket(p); -} - -static void adb_cleanup(void) -{ - usb_cleanup(); -} - -int adb_main() -{ - atexit(adb_cleanup); -#if defined(HAVE_FORKEXEC) - // No SIGCHLD. Let the service subproc handle its children. - signal(SIGPIPE, SIG_IGN); -#endif - - init_transport_registration(); - - // The minimal version of adbd only uses USB. - if (access(USB_ADB_PATH, F_OK) == 0 || access(USB_FFS_ADB_EP0, F_OK) == 0) { - // listen on USB - usb_init(); - } - - D("Event loop starting\n"); - - fdevent_loop(); - - usb_cleanup(); - - return 0; -} diff --git a/minadbd/adb.h b/minadbd/adb.h deleted file mode 100644 index 714868f5c..000000000 --- a/minadbd/adb.h +++ /dev/null @@ -1,424 +0,0 @@ -/* - * Copyright (C) 2007 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef __ADB_H -#define __ADB_H - -#include <limits.h> - -#include "transport.h" /* readx(), writex() */ -#include "fdevent.h" - -#define MAX_PAYLOAD 4096 - -#define A_SYNC 0x434e5953 -#define A_CNXN 0x4e584e43 -#define A_OPEN 0x4e45504f -#define A_OKAY 0x59414b4f -#define A_CLSE 0x45534c43 -#define A_WRTE 0x45545257 - -#define A_VERSION 0x01000000 // ADB protocol version - -#define ADB_VERSION_MAJOR 1 // Used for help/version information -#define ADB_VERSION_MINOR 0 // Used for help/version information - -#define ADB_SERVER_VERSION 29 // Increment this when we want to force users to start a new adb server - -typedef struct amessage amessage; -typedef struct apacket apacket; -typedef struct asocket asocket; -typedef struct aservice aservice; -typedef struct atransport atransport; -typedef struct adisconnect adisconnect; -typedef struct usb_handle usb_handle; - -struct amessage { - unsigned command; /* command identifier constant */ - unsigned arg0; /* first argument */ - unsigned arg1; /* second argument */ - unsigned data_length; /* length of payload (0 is allowed) */ - unsigned data_check; /* checksum of data payload */ - unsigned magic; /* command ^ 0xffffffff */ -}; - -struct apacket -{ - apacket *next; - - unsigned len; - unsigned char *ptr; - - amessage msg; - unsigned char data[MAX_PAYLOAD]; -}; - -/* An asocket represents one half of a connection between a local and -** remote entity. A local asocket is bound to a file descriptor. A -** remote asocket is bound to the protocol engine. -*/ -struct asocket { - /* chain pointers for the local/remote list of - ** asockets that this asocket lives in - */ - asocket *next; - asocket *prev; - - /* the unique identifier for this asocket - */ - unsigned id; - - /* flag: set when the socket's peer has closed - ** but packets are still queued for delivery - */ - int closing; - - /* the asocket we are connected to - */ - - asocket *peer; - - /* For local asockets, the fde is used to bind - ** us to our fd event system. For remote asockets - ** these fields are not used. - */ - fdevent fde; - int fd; - - /* queue of apackets waiting to be written - */ - apacket *pkt_first; - apacket *pkt_last; - - /* enqueue is called by our peer when it has data - ** for us. It should return 0 if we can accept more - ** data or 1 if not. If we return 1, we must call - ** peer->ready() when we once again are ready to - ** receive data. - */ - int (*enqueue)(asocket *s, apacket *pkt); - - /* ready is called by the peer when it is ready for - ** us to send data via enqueue again - */ - void (*ready)(asocket *s); - - /* close is called by the peer when it has gone away. - ** we are not allowed to make any further calls on the - ** peer once our close method is called. - */ - void (*close)(asocket *s); - - /* socket-type-specific extradata */ - void *extra; - - /* A socket is bound to atransport */ - atransport *transport; -}; - - -/* the adisconnect structure is used to record a callback that -** will be called whenever a transport is disconnected (e.g. by the user) -** this should be used to cleanup objects that depend on the -** transport (e.g. remote sockets, etc...) -*/ -struct adisconnect -{ - void (*func)(void* opaque, atransport* t); - void* opaque; - adisconnect* next; - adisconnect* prev; -}; - - -/* a transport object models the connection to a remote device or emulator -** there is one transport per connected device/emulator. a "local transport" -** connects through TCP (for the emulator), while a "usb transport" through -** USB (for real devices) -** -** note that kTransportHost doesn't really correspond to a real transport -** object, it's a special value used to indicate that a client wants to -** connect to a service implemented within the ADB server itself. -*/ -typedef enum transport_type { - kTransportUsb, - kTransportLocal, - kTransportAny, - kTransportHost, -} transport_type; - -struct atransport -{ - atransport *next; - atransport *prev; - - int (*read_from_remote)(apacket *p, atransport *t); - int (*write_to_remote)(apacket *p, atransport *t); - void (*close)(atransport *t); - void (*kick)(atransport *t); - - int fd; - int transport_socket; - fdevent transport_fde; - int ref_count; - unsigned sync_token; - int connection_state; - transport_type type; - - /* usb handle or socket fd as needed */ - usb_handle *usb; - int sfd; - - /* used to identify transports for clients */ - char *serial; - char *product; - int adb_port; // Use for emulators (local transport) - - /* a list of adisconnect callbacks called when the transport is kicked */ - int kicked; - adisconnect disconnects; -}; - - -void print_packet(const char *label, apacket *p); - -asocket *find_local_socket(unsigned id); -void install_local_socket(asocket *s); -void remove_socket(asocket *s); -void close_all_sockets(atransport *t); - -#define LOCAL_CLIENT_PREFIX "emulator-" - -asocket *create_local_socket(int fd); -asocket *create_local_service_socket(const char *destination); - -asocket *create_remote_socket(unsigned id, atransport *t); -void connect_to_remote(asocket *s, const char *destination); -void connect_to_smartsocket(asocket *s); - -void fatal(const char *fmt, ...); -void fatal_errno(const char *fmt, ...); - -void handle_packet(apacket *p, atransport *t); -void send_packet(apacket *p, atransport *t); - -void get_my_path(char *s, size_t maxLen); -int launch_server(int server_port); -int adb_main(); - - -/* transports are ref-counted -** get_device_transport does an acquire on your behalf before returning -*/ -void init_transport_registration(void); -int list_transports(char *buf, size_t bufsize); -void update_transports(void); - -asocket* create_device_tracker(void); - -/* Obtain a transport from the available transports. -** If state is != CS_ANY, only transports in that state are considered. -** If serial is non-NULL then only the device with that serial will be chosen. -** If no suitable transport is found, error is set. -*/ -atransport *acquire_one_transport(int state, transport_type ttype, const char* serial, char **error_out); -void add_transport_disconnect( atransport* t, adisconnect* dis ); -void remove_transport_disconnect( atransport* t, adisconnect* dis ); -void run_transport_disconnects( atransport* t ); -void kick_transport( atransport* t ); - -/* initialize a transport object's func pointers and state */ -#if ADB_HOST -int get_available_local_transport_index(); -#endif -void init_usb_transport(atransport *t, usb_handle *usb, int state); - -/* for MacOS X cleanup */ -void close_usb_devices(); - -/* these should only be used for the "adb disconnect" command */ -void unregister_transport(atransport *t); -void unregister_all_tcp_transports(); - -void register_usb_transport(usb_handle *h, const char *serial, unsigned writeable); - -/* this should only be used for transports with connection_state == CS_NOPERM */ -void unregister_usb_transport(usb_handle *usb); - -atransport *find_transport(const char *serial); -#if ADB_HOST -atransport* find_emulator_transport_by_adb_port(int adb_port); -#endif - -int service_to_fd(const char *name); -#if ADB_HOST -asocket *host_service_to_socket(const char* name, const char *serial); -#endif - -#if !ADB_HOST -typedef enum { - BACKUP, - RESTORE -} BackupOperation; -int backup_service(BackupOperation operation, char* args); -void framebuffer_service(int fd, void *cookie); -void log_service(int fd, void *cookie); -void remount_service(int fd, void *cookie); -char * get_log_file_path(const char * log_name); -#endif - -/* packet allocator */ -apacket *get_apacket(void); -void put_apacket(apacket *p); - -int check_header(apacket *p); -int check_data(apacket *p); - -/* define ADB_TRACE to 1 to enable tracing support, or 0 to disable it */ - -#define ADB_TRACE 1 - -/* IMPORTANT: if you change the following list, don't - * forget to update the corresponding 'tags' table in - * the adb_trace_init() function implemented in adb.c - */ -typedef enum { - TRACE_ADB = 0, /* 0x001 */ - TRACE_SOCKETS, - TRACE_PACKETS, - TRACE_TRANSPORT, - TRACE_RWX, /* 0x010 */ - TRACE_USB, - TRACE_SYNC, - TRACE_SYSDEPS, - TRACE_JDWP, /* 0x100 */ - TRACE_SERVICES, -} AdbTrace; - -#if ADB_TRACE - - extern int adb_trace_mask; - extern unsigned char adb_trace_output_count; - void adb_trace_init(void); - -# define ADB_TRACING ((adb_trace_mask & (1 << TRACE_TAG)) != 0) - - /* you must define TRACE_TAG before using this macro */ -# define D(...) \ - do { \ - if (ADB_TRACING) { \ - int save_errno = errno; \ - adb_mutex_lock(&D_lock); \ - fprintf(stderr, "%s::%s():", \ - __FILE__, __FUNCTION__); \ - errno = save_errno; \ - fprintf(stderr, __VA_ARGS__ ); \ - fflush(stderr); \ - adb_mutex_unlock(&D_lock); \ - errno = save_errno; \ - } \ - } while (0) -# define DR(...) \ - do { \ - if (ADB_TRACING) { \ - int save_errno = errno; \ - adb_mutex_lock(&D_lock); \ - errno = save_errno; \ - fprintf(stderr, __VA_ARGS__ ); \ - fflush(stderr); \ - adb_mutex_unlock(&D_lock); \ - errno = save_errno; \ - } \ - } while (0) -#else -# define D(...) ((void)0) -# define DR(...) ((void)0) -# define ADB_TRACING 0 -#endif - - -#if !TRACE_PACKETS -#define print_packet(tag,p) do {} while (0) -#endif - -#if ADB_HOST_ON_TARGET -/* adb and adbd are coexisting on the target, so use 5038 for adb - * to avoid conflicting with adbd's usage of 5037 - */ -# define DEFAULT_ADB_PORT 5038 -#else -# define DEFAULT_ADB_PORT 5037 -#endif - -#define DEFAULT_ADB_LOCAL_TRANSPORT_PORT 5555 - -#define ADB_CLASS 0xff -#define ADB_SUBCLASS 0x42 -#define ADB_PROTOCOL 0x1 - - -void local_init(int port); -int local_connect(int port); -int local_connect_arbitrary_ports(int console_port, int adb_port); - -/* usb host/client interface */ -void usb_init(); -void usb_cleanup(); -int usb_write(usb_handle *h, const void *data, int len); -int usb_read(usb_handle *h, void *data, int len); -int usb_close(usb_handle *h); -void usb_kick(usb_handle *h); - -/* used for USB device detection */ -#if ADB_HOST -int is_adb_interface(int vid, int pid, int usb_class, int usb_subclass, int usb_protocol); -#endif - -unsigned host_to_le32(unsigned n); -int adb_commandline(int argc, char **argv); - -int connection_state(atransport *t); - -#define CS_ANY -1 -#define CS_OFFLINE 0 -#define CS_BOOTLOADER 1 -#define CS_DEVICE 2 -#define CS_HOST 3 -#define CS_RECOVERY 4 -#define CS_NOPERM 5 /* Insufficient permissions to communicate with the device */ -#define CS_SIDELOAD 6 -#define CS_UNAUTHORIZED 7 - -extern int HOST; -extern int SHELL_EXIT_NOTIFY_FD; - -#define CHUNK_SIZE (64*1024) - -#if !ADB_HOST -#define USB_ADB_PATH "/dev/android_adb" - -#define USB_FFS_ADB_PATH "/dev/usb-ffs/adb/" -#define USB_FFS_ADB_EP(x) USB_FFS_ADB_PATH#x - -#define USB_FFS_ADB_EP0 USB_FFS_ADB_EP(ep0) -#define USB_FFS_ADB_OUT USB_FFS_ADB_EP(ep1) -#define USB_FFS_ADB_IN USB_FFS_ADB_EP(ep2) -#endif - -int sendfailmsg(int fd, const char *reason); -int handle_host_request(char *service, transport_type ttype, char* serial, int reply_fd, asocket *s); - -#endif diff --git a/minadbd/transport.h b/minadbd/adb_main.cpp index 992e05285..f6e240108 100644 --- a/minadbd/transport.h +++ b/minadbd/adb_main.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2011 The Android Open Source Project + * Copyright (C) 2015 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,13 +14,32 @@ * limitations under the License. */ -#ifndef __TRANSPORT_H -#define __TRANSPORT_H +#include <errno.h> +#include <signal.h> +#include <stdio.h> +#include <stdlib.h> -/* convenience wrappers around read/write that will retry on -** EINTR and/or short read/write. Returns 0 on success, -1 -** on error or EOF. -*/ -int readx(int fd, void *ptr, size_t len); -int writex(int fd, const void *ptr, size_t len); -#endif /* __TRANSPORT_H */ +#define TRACE_TAG TRACE_ADB + +#include "sysdeps.h" + +#include "adb.h" +#include "transport.h" + +int adb_main(int is_daemon, int server_port) +{ + atexit(usb_cleanup); + + adb_device_banner = "sideload"; + + // No SIGCHLD. Let the service subproc handle its children. + signal(SIGPIPE, SIG_IGN); + + init_transport_registration(); + usb_init(); + + D("Event loop starting\n"); + fdevent_loop(); + + return 0; +} diff --git a/minadbd/fdevent.c b/minadbd/fdevent.c deleted file mode 100644 index 5c374a71b..000000000 --- a/minadbd/fdevent.c +++ /dev/null @@ -1,695 +0,0 @@ -/* http://frotznet.googlecode.com/svn/trunk/utils/fdevent.c -** -** Copyright 2006, Brian Swetland <swetland@frotz.net> -** -** Licensed under the Apache License, Version 2.0 (the "License"); -** you may not use this file except in compliance with the License. -** You may obtain a copy of the License at -** -** http://www.apache.org/licenses/LICENSE-2.0 -** -** Unless required by applicable law or agreed to in writing, software -** distributed under the License is distributed on an "AS IS" BASIS, -** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -** See the License for the specific language governing permissions and -** limitations under the License. -*/ - -#include <sys/ioctl.h> - -#include <stdlib.h> -#include <stdio.h> -#include <string.h> -#include <unistd.h> -#include <errno.h> - -#include <fcntl.h> - -#include <stdarg.h> -#include <stddef.h> - -#include "fdevent.h" -#include "transport.h" -#include "sysdeps.h" - - -/* !!! Do not enable DEBUG for the adb that will run as the server: -** both stdout and stderr are used to communicate between the client -** and server. Any extra output will cause failures. -*/ -#define DEBUG 0 /* non-0 will break adb server */ - -// This socket is used when a subproc shell service exists. -// It wakes up the fdevent_loop() and cause the correct handling -// of the shell's pseudo-tty master. I.e. force close it. -int SHELL_EXIT_NOTIFY_FD = -1; - -static void fatal(const char *fn, const char *fmt, ...) -{ - va_list ap; - va_start(ap, fmt); - fprintf(stderr, "%s:", fn); - vfprintf(stderr, fmt, ap); - va_end(ap); - abort(); -} - -#define FATAL(x...) fatal(__FUNCTION__, x) - -#if DEBUG -#define D(...) \ - do { \ - adb_mutex_lock(&D_lock); \ - int save_errno = errno; \ - fprintf(stderr, "%s::%s():", __FILE__, __FUNCTION__); \ - errno = save_errno; \ - fprintf(stderr, __VA_ARGS__); \ - adb_mutex_unlock(&D_lock); \ - errno = save_errno; \ - } while(0) -static void dump_fde(fdevent *fde, const char *info) -{ - adb_mutex_lock(&D_lock); - fprintf(stderr,"FDE #%03d %c%c%c %s\n", fde->fd, - fde->state & FDE_READ ? 'R' : ' ', - fde->state & FDE_WRITE ? 'W' : ' ', - fde->state & FDE_ERROR ? 'E' : ' ', - info); - adb_mutex_unlock(&D_lock); -} -#else -#define D(...) ((void)0) -#define dump_fde(fde, info) do { } while(0) -#endif - -#define FDE_EVENTMASK 0x00ff -#define FDE_STATEMASK 0xff00 - -#define FDE_ACTIVE 0x0100 -#define FDE_PENDING 0x0200 -#define FDE_CREATED 0x0400 - -static void fdevent_plist_enqueue(fdevent *node); -static void fdevent_plist_remove(fdevent *node); -static fdevent *fdevent_plist_dequeue(void); -static void fdevent_subproc_event_func(int fd, unsigned events, void *userdata); - -static fdevent list_pending = { - .next = &list_pending, - .prev = &list_pending, -}; - -static fdevent **fd_table = 0; -static int fd_table_max = 0; - -#ifdef CRAPTASTIC -//HAVE_EPOLL - -#include <sys/epoll.h> - -static int epoll_fd = -1; - -static void fdevent_init() -{ - /* XXX: what's a good size for the passed in hint? */ - epoll_fd = epoll_create(256); - - if(epoll_fd < 0) { - perror("epoll_create() failed"); - exit(1); - } - - /* mark for close-on-exec */ - fcntl(epoll_fd, F_SETFD, FD_CLOEXEC); -} - -static void fdevent_connect(fdevent *fde) -{ - struct epoll_event ev; - - memset(&ev, 0, sizeof(ev)); - ev.events = 0; - ev.data.ptr = fde; - -#if 0 - if(epoll_ctl(epoll_fd, EPOLL_CTL_ADD, fde->fd, &ev)) { - perror("epoll_ctl() failed\n"); - exit(1); - } -#endif -} - -static void fdevent_disconnect(fdevent *fde) -{ - struct epoll_event ev; - - memset(&ev, 0, sizeof(ev)); - ev.events = 0; - ev.data.ptr = fde; - - /* technically we only need to delete if we - ** were actively monitoring events, but let's - ** be aggressive and do it anyway, just in case - ** something's out of sync - */ - epoll_ctl(epoll_fd, EPOLL_CTL_DEL, fde->fd, &ev); -} - -static void fdevent_update(fdevent *fde, unsigned events) -{ - struct epoll_event ev; - int active; - - active = (fde->state & FDE_EVENTMASK) != 0; - - memset(&ev, 0, sizeof(ev)); - ev.events = 0; - ev.data.ptr = fde; - - if(events & FDE_READ) ev.events |= EPOLLIN; - if(events & FDE_WRITE) ev.events |= EPOLLOUT; - if(events & FDE_ERROR) ev.events |= (EPOLLERR | EPOLLHUP); - - fde->state = (fde->state & FDE_STATEMASK) | events; - - if(active) { - /* we're already active. if we're changing to *no* - ** events being monitored, we need to delete, otherwise - ** we need to just modify - */ - if(ev.events) { - if(epoll_ctl(epoll_fd, EPOLL_CTL_MOD, fde->fd, &ev)) { - perror("epoll_ctl() failed\n"); - exit(1); - } - } else { - if(epoll_ctl(epoll_fd, EPOLL_CTL_DEL, fde->fd, &ev)) { - perror("epoll_ctl() failed\n"); - exit(1); - } - } - } else { - /* we're not active. if we're watching events, we need - ** to add, otherwise we can just do nothing - */ - if(ev.events) { - if(epoll_ctl(epoll_fd, EPOLL_CTL_ADD, fde->fd, &ev)) { - perror("epoll_ctl() failed\n"); - exit(1); - } - } - } -} - -static void fdevent_process() -{ - struct epoll_event events[256]; - fdevent *fde; - int i, n; - - n = epoll_wait(epoll_fd, events, 256, -1); - - if(n < 0) { - if(errno == EINTR) return; - perror("epoll_wait"); - exit(1); - } - - for(i = 0; i < n; i++) { - struct epoll_event *ev = events + i; - fde = ev->data.ptr; - - if(ev->events & EPOLLIN) { - fde->events |= FDE_READ; - } - if(ev->events & EPOLLOUT) { - fde->events |= FDE_WRITE; - } - if(ev->events & (EPOLLERR | EPOLLHUP)) { - fde->events |= FDE_ERROR; - } - if(fde->events) { - if(fde->state & FDE_PENDING) continue; - fde->state |= FDE_PENDING; - fdevent_plist_enqueue(fde); - } - } -} - -#else /* USE_SELECT */ - -#ifdef HAVE_WINSOCK -#include <winsock2.h> -#else -#include <sys/select.h> -#endif - -static fd_set read_fds; -static fd_set write_fds; -static fd_set error_fds; - -static int select_n = 0; - -static void fdevent_init(void) -{ - FD_ZERO(&read_fds); - FD_ZERO(&write_fds); - FD_ZERO(&error_fds); -} - -static void fdevent_connect(fdevent *fde) -{ - if(fde->fd >= select_n) { - select_n = fde->fd + 1; - } -} - -static void fdevent_disconnect(fdevent *fde) -{ - int i, n; - - FD_CLR(fde->fd, &read_fds); - FD_CLR(fde->fd, &write_fds); - FD_CLR(fde->fd, &error_fds); - - for(n = 0, i = 0; i < select_n; i++) { - if(fd_table[i] != 0) n = i; - } - select_n = n + 1; -} - -static void fdevent_update(fdevent *fde, unsigned events) -{ - if(events & FDE_READ) { - FD_SET(fde->fd, &read_fds); - } else { - FD_CLR(fde->fd, &read_fds); - } - if(events & FDE_WRITE) { - FD_SET(fde->fd, &write_fds); - } else { - FD_CLR(fde->fd, &write_fds); - } - if(events & FDE_ERROR) { - FD_SET(fde->fd, &error_fds); - } else { - FD_CLR(fde->fd, &error_fds); - } - - fde->state = (fde->state & FDE_STATEMASK) | events; -} - -/* Looks at fd_table[] for bad FDs and sets bit in fds. -** Returns the number of bad FDs. -*/ -static int fdevent_fd_check(fd_set *fds) -{ - int i, n = 0; - fdevent *fde; - - for(i = 0; i < select_n; i++) { - fde = fd_table[i]; - if(fde == 0) continue; - if(fcntl(i, F_GETFL, NULL) < 0) { - FD_SET(i, fds); - n++; - // fde->state |= FDE_DONT_CLOSE; - - } - } - return n; -} - -#if !DEBUG -static inline void dump_all_fds(const char *extra_msg) {} -#else -static void dump_all_fds(const char *extra_msg) -{ -int i; - fdevent *fde; - // per fd: 4 digits (but really: log10(FD_SETSIZE)), 1 staus, 1 blank - char msg_buff[FD_SETSIZE*6 + 1], *pb=msg_buff; - size_t max_chars = FD_SETSIZE * 6 + 1; - int printed_out; -#define SAFE_SPRINTF(...) \ - do { \ - printed_out = snprintf(pb, max_chars, __VA_ARGS__); \ - if (printed_out <= 0) { \ - D("... snprintf failed.\n"); \ - return; \ - } \ - if (max_chars < (unsigned int)printed_out) { \ - D("... snprintf out of space.\n"); \ - return; \ - } \ - pb += printed_out; \ - max_chars -= printed_out; \ - } while(0) - - for(i = 0; i < select_n; i++) { - fde = fd_table[i]; - SAFE_SPRINTF("%d", i); - if(fde == 0) { - SAFE_SPRINTF("? "); - continue; - } - if(fcntl(i, F_GETFL, NULL) < 0) { - SAFE_SPRINTF("b"); - } - SAFE_SPRINTF(" "); - } - D("%s fd_table[]->fd = {%s}\n", extra_msg, msg_buff); -} -#endif - -static void fdevent_process() -{ - int i, n; - fdevent *fde; - unsigned events; - fd_set rfd, wfd, efd; - - memcpy(&rfd, &read_fds, sizeof(fd_set)); - memcpy(&wfd, &write_fds, sizeof(fd_set)); - memcpy(&efd, &error_fds, sizeof(fd_set)); - - dump_all_fds("pre select()"); - - n = select(select_n, &rfd, &wfd, &efd, NULL); - int saved_errno = errno; - D("select() returned n=%d, errno=%d\n", n, n<0?saved_errno:0); - - dump_all_fds("post select()"); - - if(n < 0) { - switch(saved_errno) { - case EINTR: return; - case EBADF: - // Can't trust the FD sets after an error. - FD_ZERO(&wfd); - FD_ZERO(&efd); - FD_ZERO(&rfd); - break; - default: - D("Unexpected select() error=%d\n", saved_errno); - return; - } - } - if(n <= 0) { - // We fake a read, as the rest of the code assumes - // that errors will be detected at that point. - n = fdevent_fd_check(&rfd); - } - - for(i = 0; (i < select_n) && (n > 0); i++) { - events = 0; - if(FD_ISSET(i, &rfd)) { events |= FDE_READ; n--; } - if(FD_ISSET(i, &wfd)) { events |= FDE_WRITE; n--; } - if(FD_ISSET(i, &efd)) { events |= FDE_ERROR; n--; } - - if(events) { - fde = fd_table[i]; - if(fde == 0) - FATAL("missing fde for fd %d\n", i); - - fde->events |= events; - - D("got events fde->fd=%d events=%04x, state=%04x\n", - fde->fd, fde->events, fde->state); - if(fde->state & FDE_PENDING) continue; - fde->state |= FDE_PENDING; - fdevent_plist_enqueue(fde); - } - } -} - -#endif - -static void fdevent_register(fdevent *fde) -{ - if(fde->fd < 0) { - FATAL("bogus negative fd (%d)\n", fde->fd); - } - - if(fde->fd >= fd_table_max) { - int oldmax = fd_table_max; - if(fde->fd > 32000) { - FATAL("bogus huuuuge fd (%d)\n", fde->fd); - } - if(fd_table_max == 0) { - fdevent_init(); - fd_table_max = 256; - } - while(fd_table_max <= fde->fd) { - fd_table_max *= 2; - } - fd_table = realloc(fd_table, sizeof(fdevent*) * fd_table_max); - if(fd_table == 0) { - FATAL("could not expand fd_table to %d entries\n", fd_table_max); - } - memset(fd_table + oldmax, 0, sizeof(int) * (fd_table_max - oldmax)); - } - - fd_table[fde->fd] = fde; -} - -static void fdevent_unregister(fdevent *fde) -{ - if((fde->fd < 0) || (fde->fd >= fd_table_max)) { - FATAL("fd out of range (%d)\n", fde->fd); - } - - if(fd_table[fde->fd] != fde) { - FATAL("fd_table out of sync [%d]\n", fde->fd); - } - - fd_table[fde->fd] = 0; - - if(!(fde->state & FDE_DONT_CLOSE)) { - dump_fde(fde, "close"); - adb_close(fde->fd); - } -} - -static void fdevent_plist_enqueue(fdevent *node) -{ - fdevent *list = &list_pending; - - node->next = list; - node->prev = list->prev; - node->prev->next = node; - list->prev = node; -} - -static void fdevent_plist_remove(fdevent *node) -{ - node->prev->next = node->next; - node->next->prev = node->prev; - node->next = 0; - node->prev = 0; -} - -static fdevent *fdevent_plist_dequeue(void) -{ - fdevent *list = &list_pending; - fdevent *node = list->next; - - if(node == list) return 0; - - list->next = node->next; - list->next->prev = list; - node->next = 0; - node->prev = 0; - - return node; -} - -static void fdevent_call_fdfunc(fdevent* fde) -{ - unsigned events = fde->events; - fde->events = 0; - if(!(fde->state & FDE_PENDING)) return; - fde->state &= (~FDE_PENDING); - dump_fde(fde, "callback"); - fde->func(fde->fd, events, fde->arg); -} - -static void fdevent_subproc_event_func(int fd, unsigned ev, void *userdata) -{ - - D("subproc handling on fd=%d ev=%04x\n", fd, ev); - - // Hook oneself back into the fde's suitable for select() on read. - if((fd < 0) || (fd >= fd_table_max)) { - FATAL("fd %d out of range for fd_table \n", fd); - } - fdevent *fde = fd_table[fd]; - fdevent_add(fde, FDE_READ); - - if(ev & FDE_READ){ - int subproc_fd; - - if(readx(fd, &subproc_fd, sizeof(subproc_fd))) { - FATAL("Failed to read the subproc's fd from fd=%d\n", fd); - } - if((subproc_fd < 0) || (subproc_fd >= fd_table_max)) { - D("subproc_fd %d out of range 0, fd_table_max=%d\n", - subproc_fd, fd_table_max); - return; - } - fdevent *subproc_fde = fd_table[subproc_fd]; - if(!subproc_fde) { - D("subproc_fd %d cleared from fd_table\n", subproc_fd); - return; - } - if(subproc_fde->fd != subproc_fd) { - // Already reallocated? - D("subproc_fd %d != fd_table[].fd %d\n", subproc_fd, subproc_fde->fd); - return; - } - - subproc_fde->force_eof = 1; - - int rcount = 0; - ioctl(subproc_fd, FIONREAD, &rcount); - D("subproc with fd=%d has rcount=%d err=%d\n", - subproc_fd, rcount, errno); - - if(rcount) { - // If there is data left, it will show up in the select(). - // This works because there is no other thread reading that - // data when in this fd_func(). - return; - } - - D("subproc_fde.state=%04x\n", subproc_fde->state); - subproc_fde->events |= FDE_READ; - if(subproc_fde->state & FDE_PENDING) { - return; - } - subproc_fde->state |= FDE_PENDING; - fdevent_call_fdfunc(subproc_fde); - } -} - -fdevent *fdevent_create(int fd, fd_func func, void *arg) -{ - fdevent *fde = (fdevent*) malloc(sizeof(fdevent)); - if(fde == 0) return 0; - fdevent_install(fde, fd, func, arg); - fde->state |= FDE_CREATED; - return fde; -} - -void fdevent_destroy(fdevent *fde) -{ - if(fde == 0) return; - if(!(fde->state & FDE_CREATED)) { - FATAL("fde %p not created by fdevent_create()\n", fde); - } - fdevent_remove(fde); -} - -void fdevent_install(fdevent *fde, int fd, fd_func func, void *arg) -{ - memset(fde, 0, sizeof(fdevent)); - fde->state = FDE_ACTIVE; - fde->fd = fd; - fde->force_eof = 0; - fde->func = func; - fde->arg = arg; - -#ifndef HAVE_WINSOCK - fcntl(fd, F_SETFL, O_NONBLOCK); -#endif - fdevent_register(fde); - dump_fde(fde, "connect"); - fdevent_connect(fde); - fde->state |= FDE_ACTIVE; -} - -void fdevent_remove(fdevent *fde) -{ - if(fde->state & FDE_PENDING) { - fdevent_plist_remove(fde); - } - - if(fde->state & FDE_ACTIVE) { - fdevent_disconnect(fde); - dump_fde(fde, "disconnect"); - fdevent_unregister(fde); - } - - fde->state = 0; - fde->events = 0; -} - - -void fdevent_set(fdevent *fde, unsigned events) -{ - events &= FDE_EVENTMASK; - - if((fde->state & FDE_EVENTMASK) == events) return; - - if(fde->state & FDE_ACTIVE) { - fdevent_update(fde, events); - dump_fde(fde, "update"); - } - - fde->state = (fde->state & FDE_STATEMASK) | events; - - if(fde->state & FDE_PENDING) { - /* if we're pending, make sure - ** we don't signal an event that - ** is no longer wanted. - */ - fde->events &= (~events); - if(fde->events == 0) { - fdevent_plist_remove(fde); - fde->state &= (~FDE_PENDING); - } - } -} - -void fdevent_add(fdevent *fde, unsigned events) -{ - fdevent_set( - fde, (fde->state & FDE_EVENTMASK) | (events & FDE_EVENTMASK)); -} - -void fdevent_del(fdevent *fde, unsigned events) -{ - fdevent_set( - fde, (fde->state & FDE_EVENTMASK) & (~(events & FDE_EVENTMASK))); -} - -void fdevent_subproc_setup() -{ - int s[2]; - - if(adb_socketpair(s)) { - FATAL("cannot create shell-exit socket-pair\n"); - } - SHELL_EXIT_NOTIFY_FD = s[0]; - fdevent *fde; - fde = fdevent_create(s[1], fdevent_subproc_event_func, NULL); - if(!fde) - FATAL("cannot create fdevent for shell-exit handler\n"); - fdevent_add(fde, FDE_READ); -} - -void fdevent_loop() -{ - fdevent *fde; - fdevent_subproc_setup(); - - for(;;) { - D("--- ---- waiting for events\n"); - - fdevent_process(); - - while((fde = fdevent_plist_dequeue())) { - fdevent_call_fdfunc(fde); - } - } -} diff --git a/minadbd/fdevent.h b/minadbd/fdevent.h deleted file mode 100644 index a0ebe2a7e..000000000 --- a/minadbd/fdevent.h +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Copyright (C) 2006 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef __FDEVENT_H -#define __FDEVENT_H - -#include <stdint.h> /* for int64_t */ - -/* events that may be observed */ -#define FDE_READ 0x0001 -#define FDE_WRITE 0x0002 -#define FDE_ERROR 0x0004 -#define FDE_TIMEOUT 0x0008 - -/* features that may be set (via the events set/add/del interface) */ -#define FDE_DONT_CLOSE 0x0080 - -typedef struct fdevent fdevent; - -typedef void (*fd_func)(int fd, unsigned events, void *userdata); - -/* Allocate and initialize a new fdevent object - * Note: use FD_TIMER as 'fd' to create a fd-less object - * (used to implement timers). -*/ -fdevent *fdevent_create(int fd, fd_func func, void *arg); - -/* Uninitialize and deallocate an fdevent object that was -** created by fdevent_create() -*/ -void fdevent_destroy(fdevent *fde); - -/* Initialize an fdevent object that was externally allocated -*/ -void fdevent_install(fdevent *fde, int fd, fd_func func, void *arg); - -/* Uninitialize an fdevent object that was initialized by -** fdevent_install() -*/ -void fdevent_remove(fdevent *item); - -/* Change which events should cause notifications -*/ -void fdevent_set(fdevent *fde, unsigned events); -void fdevent_add(fdevent *fde, unsigned events); -void fdevent_del(fdevent *fde, unsigned events); - -void fdevent_set_timeout(fdevent *fde, int64_t timeout_ms); - -/* loop forever, handling events. -*/ -void fdevent_loop(); - -struct fdevent -{ - fdevent *next; - fdevent *prev; - - int fd; - int force_eof; - - unsigned short state; - unsigned short events; - - fd_func func; - void *arg; -}; - - -#endif diff --git a/minadbd/fuse_adb_provider.c b/minadbd/fuse_adb_provider.cpp index f80533a8c..5da7fd76c 100644 --- a/minadbd/fuse_adb_provider.c +++ b/minadbd/fuse_adb_provider.cpp @@ -16,29 +16,28 @@ #include <stdlib.h> #include <stdio.h> +#include <string.h> #include <errno.h> +#include "sysdeps.h" + #include "adb.h" +#include "adb_io.h" +#include "fuse_adb_provider.h" #include "fuse_sideload.h" -struct adb_data { - int sfd; // file descriptor for the adb channel - - uint64_t file_size; - uint32_t block_size; -}; - -static int read_block_adb(void* cookie, uint32_t block, uint8_t* buffer, uint32_t fetch_size) { +int read_block_adb(void* cookie, uint32_t block, uint8_t* buffer, + uint32_t fetch_size) { struct adb_data* ad = (struct adb_data*)cookie; char buf[10]; snprintf(buf, sizeof(buf), "%08u", block); - if (writex(ad->sfd, buf, 8) < 0) { + if (!WriteStringFully(ad->sfd, buf)) { fprintf(stderr, "failed to write to adb host: %s\n", strerror(errno)); return -EIO; } - if (readx(ad->sfd, buffer, fetch_size) < 0) { + if (!ReadFdExactly(ad->sfd, buffer, fetch_size)) { fprintf(stderr, "failed to read from adb host: %s\n", strerror(errno)); return -EIO; } @@ -49,7 +48,7 @@ static int read_block_adb(void* cookie, uint32_t block, uint8_t* buffer, uint32_ static void close_adb(void* cookie) { struct adb_data* ad = (struct adb_data*)cookie; - writex(ad->sfd, "DONEDONE", 8); + WriteStringFully(ad->sfd, "DONEDONE"); } int run_adb_fuse(int sfd, uint64_t file_size, uint32_t block_size) { diff --git a/minadbd/fuse_adb_provider.h b/minadbd/fuse_adb_provider.h index 0eb1f79d1..9941709b9 100644 --- a/minadbd/fuse_adb_provider.h +++ b/minadbd/fuse_adb_provider.h @@ -17,6 +17,16 @@ #ifndef __FUSE_ADB_PROVIDER_H #define __FUSE_ADB_PROVIDER_H +#include <stdint.h> + +struct adb_data { + int sfd; // file descriptor for the adb channel + + uint64_t file_size; + uint32_t block_size; +}; + +int read_block_adb(void* cookie, uint32_t block, uint8_t* buffer, uint32_t fetch_size); int run_adb_fuse(int sfd, uint64_t file_size, uint32_t block_size); #endif diff --git a/minadbd/fuse_adb_provider_test.cpp b/minadbd/fuse_adb_provider_test.cpp new file mode 100644 index 000000000..0f2e881c7 --- /dev/null +++ b/minadbd/fuse_adb_provider_test.cpp @@ -0,0 +1,88 @@ +/* + * Copyright (C) 2015 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "fuse_adb_provider.h" + +#include <gtest/gtest.h> + +#include <errno.h> +#include <fcntl.h> +#include <sys/socket.h> + +#include <string> + +#include "adb_io.h" + +TEST(fuse_adb_provider, read_block_adb) { + adb_data data = {}; + int sockets[2]; + + ASSERT_EQ(0, socketpair(AF_UNIX, SOCK_STREAM, 0, sockets)); + data.sfd = sockets[0]; + + int host_socket = sockets[1]; + fcntl(host_socket, F_SETFL, O_NONBLOCK); + + const char expected_data[] = "foobar"; + char block_data[sizeof(expected_data)] = {}; + + // If we write the result of read_block_adb's request before the request is + // actually made we can avoid needing an extra thread for this test. + ASSERT_TRUE(WriteFdExactly(host_socket, expected_data, + strlen(expected_data))); + + uint32_t block = 1234U; + const char expected_block[] = "00001234"; + ASSERT_EQ(0, read_block_adb(reinterpret_cast<void*>(&data), block, + reinterpret_cast<uint8_t*>(block_data), + sizeof(expected_data) - 1)); + + // Check that read_block_adb requested the right block. + char block_req[sizeof(expected_block)] = {}; + ASSERT_TRUE(ReadFdExactly(host_socket, block_req, 8)); + ASSERT_EQ(0, block_req[8]); + ASSERT_EQ(8U, strlen(block_req)); + ASSERT_STREQ(expected_block, block_req); + + // Check that read_block_adb returned the right data. + ASSERT_EQ(0, block_req[8]); + ASSERT_STREQ(expected_data, block_data); + + // Check that nothing else was written to the socket. + char tmp; + errno = 0; + ASSERT_EQ(-1, read(host_socket, &tmp, 1)); + ASSERT_EQ(EWOULDBLOCK, errno); + + close(sockets[0]); + close(sockets[1]); +} + +TEST(fuse_adb_provider, read_block_adb_fail_write) { + adb_data data = {}; + int sockets[2]; + + ASSERT_EQ(0, socketpair(AF_UNIX, SOCK_STREAM, 0, sockets)); + data.sfd = sockets[0]; + + ASSERT_EQ(0, close(sockets[1])); + + char buf[1]; + ASSERT_EQ(-EIO, read_block_adb(reinterpret_cast<void*>(&data), 0, + reinterpret_cast<uint8_t*>(buf), 1)); + + close(sockets[0]); +} diff --git a/minadbd/mutex_list.h b/minadbd/mutex_list.h deleted file mode 100644 index 652dd7341..000000000 --- a/minadbd/mutex_list.h +++ /dev/null @@ -1,26 +0,0 @@ -/* the list of mutexes used by adb */ -/* #ifndef __MUTEX_LIST_H - * Do not use an include-guard. This file is included once to declare the locks - * and once in win32 to actually do the runtime initialization. - */ -#ifndef ADB_MUTEX -#error ADB_MUTEX not defined when including this file -#endif -ADB_MUTEX(dns_lock) -ADB_MUTEX(socket_list_lock) -ADB_MUTEX(transport_lock) -#if ADB_HOST -ADB_MUTEX(local_transports_lock) -#endif -ADB_MUTEX(usb_lock) - -// Sadly logging to /data/adb/adb-... is not thread safe. -// After modifying adb.h::D() to count invocations: -// DEBUG(jpa):0:Handling main() -// DEBUG(jpa):1:[ usb_init - starting thread ] -// (Oopsies, no :2:, and matching message is also gone.) -// DEBUG(jpa):3:[ usb_thread - opening device ] -// DEBUG(jpa):4:jdwp control socket started (10) -ADB_MUTEX(D_lock) - -#undef ADB_MUTEX diff --git a/minadbd/services.c b/minadbd/services.cpp index 218b84a38..a83256796 100644 --- a/minadbd/services.c +++ b/minadbd/services.cpp @@ -14,18 +14,19 @@ * limitations under the License. */ -#include <stdlib.h> +#include <errno.h> +#include <inttypes.h> #include <stdio.h> -#include <unistd.h> +#include <stdlib.h> #include <string.h> -#include <errno.h> +#include <unistd.h> #include "sysdeps.h" -#include "fdevent.h" -#include "fuse_adb_provider.h" #define TRACE_TAG TRACE_SERVICES #include "adb.h" +#include "fdevent.h" +#include "fuse_adb_provider.h" typedef struct stinfo stinfo; @@ -35,24 +36,22 @@ struct stinfo { void *cookie; }; - -void *service_bootstrap_func(void *x) -{ - stinfo *sti = x; +void* service_bootstrap_func(void* x) { + stinfo* sti = reinterpret_cast<stinfo*>(x); sti->func(sti->fd, sti->cookie); free(sti); return 0; } -static void sideload_host_service(int sfd, void* cookie) -{ +static void sideload_host_service(int sfd, void* cookie) { char* saveptr; - const char* s = strtok_r(cookie, ":", &saveptr); + const char* s = adb_strtok_r(reinterpret_cast<char*>(cookie), ":", &saveptr); uint64_t file_size = strtoull(s, NULL, 10); - s = strtok_r(NULL, ":", &saveptr); + s = adb_strtok_r(NULL, ":", &saveptr); uint32_t block_size = strtoul(s, NULL, 10); - printf("sideload-host file size %llu block size %lu\n", file_size, block_size); + printf("sideload-host file size %" PRIu64 " block size %" PRIu32 "\n", + file_size, block_size); int result = run_adb_fuse(sfd, file_size, block_size); @@ -61,58 +60,22 @@ static void sideload_host_service(int sfd, void* cookie) exit(result == 0 ? 0 : 1); } -#if 0 -static void echo_service(int fd, void *cookie) -{ - char buf[4096]; - int r; - char *p; - int c; - - for(;;) { - r = read(fd, buf, 4096); - if(r == 0) goto done; - if(r < 0) { - if(errno == EINTR) continue; - else goto done; - } - - c = r; - p = buf; - while(c > 0) { - r = write(fd, p, c); - if(r > 0) { - c -= r; - p += r; - continue; - } - if((r < 0) && (errno == EINTR)) continue; - goto done; - } - } -done: - close(fd); -} -#endif - static int create_service_thread(void (*func)(int, void *), void *cookie) { - stinfo *sti; - adb_thread_t t; int s[2]; - if(adb_socketpair(s)) { printf("cannot create service socket pair\n"); return -1; } - sti = malloc(sizeof(stinfo)); + stinfo* sti = reinterpret_cast<stinfo*>(malloc(sizeof(stinfo))); if(sti == 0) fatal("cannot allocate stinfo"); sti->func = func; sti->cookie = cookie; sti->fd = s[1]; - if(adb_thread_create( &t, service_bootstrap_func, sti)){ + adb_thread_t t; + if (adb_thread_create( &t, service_bootstrap_func, sti)){ free(sti); adb_close(s[0]); adb_close(s[1]); @@ -124,8 +87,7 @@ static int create_service_thread(void (*func)(int, void *), void *cookie) return s[0]; } -int service_to_fd(const char *name) -{ +int service_to_fd(const char* name) { int ret = -1; if (!strncmp(name, "sideload:", 9)) { @@ -135,10 +97,6 @@ int service_to_fd(const char *name) exit(3); } else if (!strncmp(name, "sideload-host:", 14)) { ret = create_service_thread(sideload_host_service, (void*)(name + 14)); -#if 0 - } else if(!strncmp(name, "echo:", 5)){ - ret = create_service_thread(echo_service, 0); -#endif } if (ret >= 0) { close_on_exec(ret); diff --git a/minadbd/sockets.c b/minadbd/sockets.c deleted file mode 100644 index 817410d13..000000000 --- a/minadbd/sockets.c +++ /dev/null @@ -1,731 +0,0 @@ -/* - * Copyright (C) 2007 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include <stdio.h> -#include <stdlib.h> -#include <unistd.h> -#include <errno.h> -#include <string.h> -#include <ctype.h> - -#include "sysdeps.h" - -#define TRACE_TAG TRACE_SOCKETS -#include "adb.h" - -ADB_MUTEX_DEFINE( socket_list_lock ); - -static void local_socket_close_locked(asocket *s); - -int sendfailmsg(int fd, const char *reason) -{ - char buf[9]; - int len; - len = strlen(reason); - if(len > 0xffff) len = 0xffff; - snprintf(buf, sizeof buf, "FAIL%04x", len); - if(writex(fd, buf, 8)) return -1; - return writex(fd, reason, len); -} - -//extern int online; - -static unsigned local_socket_next_id = 1; - -static asocket local_socket_list = { - .next = &local_socket_list, - .prev = &local_socket_list, -}; - -/* the the list of currently closing local sockets. -** these have no peer anymore, but still packets to -** write to their fd. -*/ -static asocket local_socket_closing_list = { - .next = &local_socket_closing_list, - .prev = &local_socket_closing_list, -}; - -asocket *find_local_socket(unsigned id) -{ - asocket *s; - asocket *result = NULL; - - adb_mutex_lock(&socket_list_lock); - for (s = local_socket_list.next; s != &local_socket_list; s = s->next) { - if (s->id == id) { - result = s; - break; - } - } - adb_mutex_unlock(&socket_list_lock); - - return result; -} - -static void -insert_local_socket(asocket* s, asocket* list) -{ - s->next = list; - s->prev = s->next->prev; - s->prev->next = s; - s->next->prev = s; -} - - -void install_local_socket(asocket *s) -{ - adb_mutex_lock(&socket_list_lock); - - s->id = local_socket_next_id++; - insert_local_socket(s, &local_socket_list); - - adb_mutex_unlock(&socket_list_lock); -} - -void remove_socket(asocket *s) -{ - // socket_list_lock should already be held - if (s->prev && s->next) - { - s->prev->next = s->next; - s->next->prev = s->prev; - s->next = 0; - s->prev = 0; - s->id = 0; - } -} - -void close_all_sockets(atransport *t) -{ - asocket *s; - - /* this is a little gross, but since s->close() *will* modify - ** the list out from under you, your options are limited. - */ - adb_mutex_lock(&socket_list_lock); -restart: - for(s = local_socket_list.next; s != &local_socket_list; s = s->next){ - if(s->transport == t || (s->peer && s->peer->transport == t)) { - local_socket_close_locked(s); - goto restart; - } - } - adb_mutex_unlock(&socket_list_lock); -} - -static int local_socket_enqueue(asocket *s, apacket *p) -{ - D("LS(%d): enqueue %d\n", s->id, p->len); - - p->ptr = p->data; - - /* if there is already data queue'd, we will receive - ** events when it's time to write. just add this to - ** the tail - */ - if(s->pkt_first) { - goto enqueue; - } - - /* write as much as we can, until we - ** would block or there is an error/eof - */ - while(p->len > 0) { - int r = adb_write(s->fd, p->ptr, p->len); - if(r > 0) { - p->len -= r; - p->ptr += r; - continue; - } - if((r == 0) || (errno != EAGAIN)) { - D( "LS(%d): not ready, errno=%d: %s\n", s->id, errno, strerror(errno) ); - s->close(s); - return 1; /* not ready (error) */ - } else { - break; - } - } - - if(p->len == 0) { - put_apacket(p); - return 0; /* ready for more data */ - } - -enqueue: - p->next = 0; - if(s->pkt_first) { - s->pkt_last->next = p; - } else { - s->pkt_first = p; - } - s->pkt_last = p; - - /* make sure we are notified when we can drain the queue */ - fdevent_add(&s->fde, FDE_WRITE); - - return 1; /* not ready (backlog) */ -} - -static void local_socket_ready(asocket *s) -{ - /* far side is ready for data, pay attention to - readable events */ - fdevent_add(&s->fde, FDE_READ); -// D("LS(%d): ready()\n", s->id); -} - -static void local_socket_close(asocket *s) -{ - adb_mutex_lock(&socket_list_lock); - local_socket_close_locked(s); - adb_mutex_unlock(&socket_list_lock); -} - -// be sure to hold the socket list lock when calling this -static void local_socket_destroy(asocket *s) -{ - apacket *p, *n; - D("LS(%d): destroying fde.fd=%d\n", s->id, s->fde.fd); - - /* IMPORTANT: the remove closes the fd - ** that belongs to this socket - */ - fdevent_remove(&s->fde); - - /* dispose of any unwritten data */ - for(p = s->pkt_first; p; p = n) { - D("LS(%d): discarding %d bytes\n", s->id, p->len); - n = p->next; - put_apacket(p); - } - remove_socket(s); - free(s); -} - - -static void local_socket_close_locked(asocket *s) -{ - D("entered. LS(%d) fd=%d\n", s->id, s->fd); - if(s->peer) { - D("LS(%d): closing peer. peer->id=%d peer->fd=%d\n", - s->id, s->peer->id, s->peer->fd); - s->peer->peer = 0; - // tweak to avoid deadlock - if (s->peer->close == local_socket_close) { - local_socket_close_locked(s->peer); - } else { - s->peer->close(s->peer); - } - s->peer = 0; - } - - /* If we are already closing, or if there are no - ** pending packets, destroy immediately - */ - if (s->closing || s->pkt_first == NULL) { - int id = s->id; - local_socket_destroy(s); - D("LS(%d): closed\n", id); - return; - } - - /* otherwise, put on the closing list - */ - D("LS(%d): closing\n", s->id); - s->closing = 1; - fdevent_del(&s->fde, FDE_READ); - remove_socket(s); - D("LS(%d): put on socket_closing_list fd=%d\n", s->id, s->fd); - insert_local_socket(s, &local_socket_closing_list); -} - -static void local_socket_event_func(int fd, unsigned ev, void *_s) -{ - asocket *s = _s; - - D("LS(%d): event_func(fd=%d(==%d), ev=%04x)\n", s->id, s->fd, fd, ev); - - /* put the FDE_WRITE processing before the FDE_READ - ** in order to simplify the code. - */ - if(ev & FDE_WRITE){ - apacket *p; - - while((p = s->pkt_first) != 0) { - while(p->len > 0) { - int r = adb_write(fd, p->ptr, p->len); - if(r > 0) { - p->ptr += r; - p->len -= r; - continue; - } - if(r < 0) { - /* returning here is ok because FDE_READ will - ** be processed in the next iteration loop - */ - if(errno == EAGAIN) return; - if(errno == EINTR) continue; - } - D(" closing after write because r=%d and errno is %d\n", r, errno); - s->close(s); - return; - } - - if(p->len == 0) { - s->pkt_first = p->next; - if(s->pkt_first == 0) s->pkt_last = 0; - put_apacket(p); - } - } - - /* if we sent the last packet of a closing socket, - ** we can now destroy it. - */ - if (s->closing) { - D(" closing because 'closing' is set after write\n"); - s->close(s); - return; - } - - /* no more packets queued, so we can ignore - ** writable events again and tell our peer - ** to resume writing - */ - fdevent_del(&s->fde, FDE_WRITE); - s->peer->ready(s->peer); - } - - - if(ev & FDE_READ){ - apacket *p = get_apacket(); - unsigned char *x = p->data; - size_t avail = MAX_PAYLOAD; - int r; - int is_eof = 0; - - while(avail > 0) { - r = adb_read(fd, x, avail); - D("LS(%d): post adb_read(fd=%d,...) r=%d (errno=%d) avail=%zu\n", - s->id, s->fd, r, r<0?errno:0, avail); - if(r > 0) { - avail -= r; - x += r; - continue; - } - if(r < 0) { - if(errno == EAGAIN) break; - if(errno == EINTR) continue; - } - - /* r = 0 or unhandled error */ - is_eof = 1; - break; - } - D("LS(%d): fd=%d post avail loop. r=%d is_eof=%d forced_eof=%d\n", - s->id, s->fd, r, is_eof, s->fde.force_eof); - if((avail == MAX_PAYLOAD) || (s->peer == 0)) { - put_apacket(p); - } else { - p->len = MAX_PAYLOAD - avail; - - r = s->peer->enqueue(s->peer, p); - D("LS(%d): fd=%d post peer->enqueue(). r=%d\n", s->id, s->fd, r); - - if(r < 0) { - /* error return means they closed us as a side-effect - ** and we must return immediately. - ** - ** note that if we still have buffered packets, the - ** socket will be placed on the closing socket list. - ** this handler function will be called again - ** to process FDE_WRITE events. - */ - return; - } - - if(r > 0) { - /* if the remote cannot accept further events, - ** we disable notification of READs. They'll - ** be enabled again when we get a call to ready() - */ - fdevent_del(&s->fde, FDE_READ); - } - } - /* Don't allow a forced eof if data is still there */ - if((s->fde.force_eof && !r) || is_eof) { - D(" closing because is_eof=%d r=%d s->fde.force_eof=%d\n", is_eof, r, s->fde.force_eof); - s->close(s); - } - } - - if(ev & FDE_ERROR){ - /* this should be caught be the next read or write - ** catching it here means we may skip the last few - ** bytes of readable data. - */ -// s->close(s); - D("LS(%d): FDE_ERROR (fd=%d)\n", s->id, s->fd); - - return; - } -} - -asocket *create_local_socket(int fd) -{ - asocket *s = calloc(1, sizeof(asocket)); - if (s == NULL) fatal("cannot allocate socket"); - s->fd = fd; - s->enqueue = local_socket_enqueue; - s->ready = local_socket_ready; - s->close = local_socket_close; - install_local_socket(s); - - fdevent_install(&s->fde, fd, local_socket_event_func, s); -/* fdevent_add(&s->fde, FDE_ERROR); */ - //fprintf(stderr, "Created local socket in create_local_socket \n"); - D("LS(%d): created (fd=%d)\n", s->id, s->fd); - return s; -} - -asocket *create_local_service_socket(const char *name) -{ - asocket *s; - int fd; - - fd = service_to_fd(name); - if(fd < 0) return 0; - - s = create_local_socket(fd); - D("LS(%d): bound to '%s' via %d\n", s->id, name, fd); - return s; -} - -/* a Remote socket is used to send/receive data to/from a given transport object -** it needs to be closed when the transport is forcibly destroyed by the user -*/ -typedef struct aremotesocket { - asocket socket; - adisconnect disconnect; -} aremotesocket; - -static int remote_socket_enqueue(asocket *s, apacket *p) -{ - D("entered remote_socket_enqueue RS(%d) WRITE fd=%d peer.fd=%d\n", - s->id, s->fd, s->peer->fd); - p->msg.command = A_WRTE; - p->msg.arg0 = s->peer->id; - p->msg.arg1 = s->id; - p->msg.data_length = p->len; - send_packet(p, s->transport); - return 1; -} - -static void remote_socket_ready(asocket *s) -{ - D("entered remote_socket_ready RS(%d) OKAY fd=%d peer.fd=%d\n", - s->id, s->fd, s->peer->fd); - apacket *p = get_apacket(); - p->msg.command = A_OKAY; - p->msg.arg0 = s->peer->id; - p->msg.arg1 = s->id; - send_packet(p, s->transport); -} - -static void remote_socket_close(asocket *s) -{ - D("entered remote_socket_close RS(%d) CLOSE fd=%d peer->fd=%d\n", - s->id, s->fd, s->peer?s->peer->fd:-1); - apacket *p = get_apacket(); - p->msg.command = A_CLSE; - if(s->peer) { - p->msg.arg0 = s->peer->id; - s->peer->peer = 0; - D("RS(%d) peer->close()ing peer->id=%d peer->fd=%d\n", - s->id, s->peer->id, s->peer->fd); - s->peer->close(s->peer); - } - p->msg.arg1 = s->id; - send_packet(p, s->transport); - D("RS(%d): closed\n", s->id); - remove_transport_disconnect( s->transport, &((aremotesocket*)s)->disconnect ); - free(s); -} - -static void remote_socket_disconnect(void* _s, atransport* t) -{ - asocket* s = _s; - asocket* peer = s->peer; - - D("remote_socket_disconnect RS(%d)\n", s->id); - if (peer) { - peer->peer = NULL; - peer->close(peer); - } - remove_transport_disconnect( s->transport, &((aremotesocket*)s)->disconnect ); - free(s); -} - -asocket *create_remote_socket(unsigned id, atransport *t) -{ - asocket *s = calloc(1, sizeof(aremotesocket)); - adisconnect* dis = &((aremotesocket*)s)->disconnect; - - if (s == NULL) fatal("cannot allocate socket"); - s->id = id; - s->enqueue = remote_socket_enqueue; - s->ready = remote_socket_ready; - s->close = remote_socket_close; - s->transport = t; - - dis->func = remote_socket_disconnect; - dis->opaque = s; - add_transport_disconnect( t, dis ); - D("RS(%d): created\n", s->id); - return s; -} - -void connect_to_remote(asocket *s, const char *destination) -{ - D("Connect_to_remote call RS(%d) fd=%d\n", s->id, s->fd); - apacket *p = get_apacket(); - int len = strlen(destination) + 1; - - if(len > (MAX_PAYLOAD-1)) { - fatal("destination oversized"); - } - - D("LS(%d): connect('%s')\n", s->id, destination); - p->msg.command = A_OPEN; - p->msg.arg0 = s->id; - p->msg.data_length = len; - strcpy((char*) p->data, destination); - send_packet(p, s->transport); -} - - -/* this is used by magic sockets to rig local sockets to - send the go-ahead message when they connect */ -static void local_socket_ready_notify(asocket *s) -{ - s->ready = local_socket_ready; - s->close = local_socket_close; - adb_write(s->fd, "OKAY", 4); - s->ready(s); -} - -/* this is used by magic sockets to rig local sockets to - send the failure message if they are closed before - connected (to avoid closing them without a status message) */ -static void local_socket_close_notify(asocket *s) -{ - s->ready = local_socket_ready; - s->close = local_socket_close; - sendfailmsg(s->fd, "closed"); - s->close(s); -} - -unsigned unhex(unsigned char *s, int len) -{ - unsigned n = 0, c; - - while(len-- > 0) { - switch((c = *s++)) { - case '0': case '1': case '2': - case '3': case '4': case '5': - case '6': case '7': case '8': - case '9': - c -= '0'; - break; - case 'a': case 'b': case 'c': - case 'd': case 'e': case 'f': - c = c - 'a' + 10; - break; - case 'A': case 'B': case 'C': - case 'D': case 'E': case 'F': - c = c - 'A' + 10; - break; - default: - return 0xffffffff; - } - - n = (n << 4) | c; - } - - return n; -} - -/* skip_host_serial return the position in a string - skipping over the 'serial' parameter in the ADB protocol, - where parameter string may be a host:port string containing - the protocol delimiter (colon). */ -char *skip_host_serial(char *service) { - char *first_colon, *serial_end; - - first_colon = strchr(service, ':'); - if (!first_colon) { - /* No colon in service string. */ - return NULL; - } - serial_end = first_colon; - if (isdigit(serial_end[1])) { - serial_end++; - while ((*serial_end) && isdigit(*serial_end)) { - serial_end++; - } - if ((*serial_end) != ':') { - // Something other than numbers was found, reset the end. - serial_end = first_colon; - } - } - return serial_end; -} - -static int smart_socket_enqueue(asocket *s, apacket *p) -{ - unsigned len; - - D("SS(%d): enqueue %d\n", s->id, p->len); - - if(s->pkt_first == 0) { - s->pkt_first = p; - s->pkt_last = p; - } else { - if((s->pkt_first->len + p->len) > MAX_PAYLOAD) { - D("SS(%d): overflow\n", s->id); - put_apacket(p); - goto fail; - } - - memcpy(s->pkt_first->data + s->pkt_first->len, - p->data, p->len); - s->pkt_first->len += p->len; - put_apacket(p); - - p = s->pkt_first; - } - - /* don't bother if we can't decode the length */ - if(p->len < 4) return 0; - - len = unhex(p->data, 4); - if((len < 1) || (len > 1024)) { - D("SS(%d): bad size (%d)\n", s->id, len); - goto fail; - } - - D("SS(%d): len is %d\n", s->id, len ); - /* can't do anything until we have the full header */ - if((len + 4) > p->len) { - D("SS(%d): waiting for %d more bytes\n", s->id, len+4 - p->len); - return 0; - } - - p->data[len + 4] = 0; - - D("SS(%d): '%s'\n", s->id, (char*) (p->data + 4)); - - if (s->transport == NULL) { - char* error_string = "unknown failure"; - s->transport = acquire_one_transport (CS_ANY, - kTransportAny, NULL, &error_string); - - if (s->transport == NULL) { - sendfailmsg(s->peer->fd, error_string); - goto fail; - } - } - - if(!(s->transport) || (s->transport->connection_state == CS_OFFLINE)) { - /* if there's no remote we fail the connection - ** right here and terminate it - */ - sendfailmsg(s->peer->fd, "device offline (x)"); - goto fail; - } - - - /* instrument our peer to pass the success or fail - ** message back once it connects or closes, then - ** detach from it, request the connection, and - ** tear down - */ - s->peer->ready = local_socket_ready_notify; - s->peer->close = local_socket_close_notify; - s->peer->peer = 0; - /* give him our transport and upref it */ - s->peer->transport = s->transport; - - connect_to_remote(s->peer, (char*) (p->data + 4)); - s->peer = 0; - s->close(s); - return 1; - -fail: - /* we're going to close our peer as a side-effect, so - ** return -1 to signal that state to the local socket - ** who is enqueueing against us - */ - s->close(s); - return -1; -} - -static void smart_socket_ready(asocket *s) -{ - D("SS(%d): ready\n", s->id); -} - -static void smart_socket_close(asocket *s) -{ - D("SS(%d): closed\n", s->id); - if(s->pkt_first){ - put_apacket(s->pkt_first); - } - if(s->peer) { - s->peer->peer = 0; - s->peer->close(s->peer); - s->peer = 0; - } - free(s); -} - -asocket *create_smart_socket(void (*action_cb)(asocket *s, const char *act)) -{ - D("Creating smart socket \n"); - asocket *s = calloc(1, sizeof(asocket)); - if (s == NULL) fatal("cannot allocate socket"); - s->enqueue = smart_socket_enqueue; - s->ready = smart_socket_ready; - s->close = smart_socket_close; - s->extra = action_cb; - - D("SS(%d): created %p\n", s->id, action_cb); - return s; -} - -void smart_socket_action(asocket *s, const char *act) -{ - -} - -void connect_to_smartsocket(asocket *s) -{ - D("Connecting to smart socket \n"); - asocket *ss = create_smart_socket(smart_socket_action); - s->peer = ss; - ss->peer = s; - s->ready(s); -} diff --git a/minadbd/sysdeps.h b/minadbd/sysdeps.h deleted file mode 100644 index 800ddb753..000000000 --- a/minadbd/sysdeps.h +++ /dev/null @@ -1,494 +0,0 @@ -/* - * Copyright (C) 2007 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/* this file contains system-dependent definitions used by ADB - * they're related to threads, sockets and file descriptors - */ -#ifndef _ADB_SYSDEPS_H -#define _ADB_SYSDEPS_H - -#ifdef __CYGWIN__ -# undef _WIN32 -#endif - -#ifdef _WIN32 - -#include <windows.h> -#include <winsock2.h> -#include <ws2tcpip.h> -#include <process.h> -#include <fcntl.h> -#include <io.h> -#include <sys/stat.h> -#include <errno.h> -#include <ctype.h> - -#define OS_PATH_SEPARATOR '\\' -#define OS_PATH_SEPARATOR_STR "\\" - -typedef CRITICAL_SECTION adb_mutex_t; - -#define ADB_MUTEX_DEFINE(x) adb_mutex_t x - -/* declare all mutexes */ -/* For win32, adb_sysdeps_init() will do the mutex runtime initialization. */ -#define ADB_MUTEX(x) extern adb_mutex_t x; -#include "mutex_list.h" - -extern void adb_sysdeps_init(void); - -static __inline__ void adb_mutex_lock( adb_mutex_t* lock ) -{ - EnterCriticalSection( lock ); -} - -static __inline__ void adb_mutex_unlock( adb_mutex_t* lock ) -{ - LeaveCriticalSection( lock ); -} - -typedef struct { unsigned tid; } adb_thread_t; - -typedef void* (*adb_thread_func_t)(void* arg); - -typedef void (*win_thread_func_t)(void* arg); - -static __inline__ int adb_thread_create( adb_thread_t *thread, adb_thread_func_t func, void* arg) -{ - thread->tid = _beginthread( (win_thread_func_t)func, 0, arg ); - if (thread->tid == (unsigned)-1L) { - return -1; - } - return 0; -} - -static __inline__ void close_on_exec(int fd) -{ - /* nothing really */ -} - -extern void disable_tcp_nagle(int fd); - -#define lstat stat /* no symlinks on Win32 */ - -#define S_ISLNK(m) 0 /* no symlinks on Win32 */ - -static __inline__ int adb_unlink(const char* path) -{ - int rc = unlink(path); - - if (rc == -1 && errno == EACCES) { - /* unlink returns EACCES when the file is read-only, so we first */ - /* try to make it writable, then unlink again... */ - rc = chmod(path, _S_IREAD|_S_IWRITE ); - if (rc == 0) - rc = unlink(path); - } - return rc; -} -#undef unlink -#define unlink ___xxx_unlink - -static __inline__ int adb_mkdir(const char* path, int mode) -{ - return _mkdir(path); -} -#undef mkdir -#define mkdir ___xxx_mkdir - -extern int adb_open(const char* path, int options); -extern int adb_creat(const char* path, int mode); -extern int adb_read(int fd, void* buf, int len); -extern int adb_write(int fd, const void* buf, int len); -extern int adb_lseek(int fd, int pos, int where); -extern int adb_shutdown(int fd); -extern int adb_close(int fd); - -static __inline__ int unix_close(int fd) -{ - return close(fd); -} -#undef close -#define close ____xxx_close - -static __inline__ int unix_read(int fd, void* buf, size_t len) -{ - return read(fd, buf, len); -} -#undef read -#define read ___xxx_read - -static __inline__ int unix_write(int fd, const void* buf, size_t len) -{ - return write(fd, buf, len); -} -#undef write -#define write ___xxx_write - -static __inline__ int adb_open_mode(const char* path, int options, int mode) -{ - return adb_open(path, options); -} - -static __inline__ int unix_open(const char* path, int options,...) -{ - if ((options & O_CREAT) == 0) - { - return open(path, options); - } - else - { - int mode; - va_list args; - va_start( args, options ); - mode = va_arg( args, int ); - va_end( args ); - return open(path, options, mode); - } -} -#define open ___xxx_unix_open - - -/* normally provided by <cutils/misc.h> */ -extern void* load_file(const char* pathname, unsigned* psize); - -/* normally provided by <cutils/sockets.h> */ -extern int socket_loopback_client(int port, int type); -extern int socket_network_client(const char *host, int port, int type); -extern int socket_loopback_server(int port, int type); -extern int socket_inaddr_any_server(int port, int type); - -/* normally provided by "fdevent.h" */ - -#define FDE_READ 0x0001 -#define FDE_WRITE 0x0002 -#define FDE_ERROR 0x0004 -#define FDE_DONT_CLOSE 0x0080 - -typedef struct fdevent fdevent; - -typedef void (*fd_func)(int fd, unsigned events, void *userdata); - -fdevent *fdevent_create(int fd, fd_func func, void *arg); -void fdevent_destroy(fdevent *fde); -void fdevent_install(fdevent *fde, int fd, fd_func func, void *arg); -void fdevent_remove(fdevent *item); -void fdevent_set(fdevent *fde, unsigned events); -void fdevent_add(fdevent *fde, unsigned events); -void fdevent_del(fdevent *fde, unsigned events); -void fdevent_loop(); - -struct fdevent { - fdevent *next; - fdevent *prev; - - int fd; - int force_eof; - - unsigned short state; - unsigned short events; - - fd_func func; - void *arg; -}; - -static __inline__ void adb_sleep_ms( int mseconds ) -{ - Sleep( mseconds ); -} - -extern int adb_socket_accept(int serverfd, struct sockaddr* addr, socklen_t *addrlen); - -#undef accept -#define accept ___xxx_accept - -static __inline__ int adb_socket_setbufsize( int fd, int bufsize ) -{ - int opt = bufsize; - return setsockopt(fd, SOL_SOCKET, SO_RCVBUF, (const char*)&opt, sizeof(opt)); -} - -extern int adb_socketpair( int sv[2] ); - -static __inline__ char* adb_dirstart( const char* path ) -{ - char* p = strchr(path, '/'); - char* p2 = strchr(path, '\\'); - - if ( !p ) - p = p2; - else if ( p2 && p2 > p ) - p = p2; - - return p; -} - -static __inline__ char* adb_dirstop( const char* path ) -{ - char* p = strrchr(path, '/'); - char* p2 = strrchr(path, '\\'); - - if ( !p ) - p = p2; - else if ( p2 && p2 > p ) - p = p2; - - return p; -} - -static __inline__ int adb_is_absolute_host_path( const char* path ) -{ - return isalpha(path[0]) && path[1] == ':' && path[2] == '\\'; -} - -#else /* !_WIN32 a.k.a. Unix */ - -#include "fdevent.h" -#include <cutils/sockets.h> -#include <cutils/properties.h> -#include <cutils/misc.h> -#include <signal.h> -#include <sys/wait.h> -#include <sys/stat.h> -#include <fcntl.h> - -#include <pthread.h> -#include <unistd.h> -#include <fcntl.h> -#include <stdarg.h> -#include <netinet/in.h> -#include <netinet/tcp.h> -#include <string.h> - -#define OS_PATH_SEPARATOR '/' -#define OS_PATH_SEPARATOR_STR "/" - -typedef pthread_mutex_t adb_mutex_t; - -#define ADB_MUTEX_INITIALIZER PTHREAD_MUTEX_INITIALIZER -#define adb_mutex_init pthread_mutex_init -#define adb_mutex_lock pthread_mutex_lock -#define adb_mutex_unlock pthread_mutex_unlock -#define adb_mutex_destroy pthread_mutex_destroy - -#define ADB_MUTEX_DEFINE(m) adb_mutex_t m = PTHREAD_MUTEX_INITIALIZER - -#define adb_cond_t pthread_cond_t -#define adb_cond_init pthread_cond_init -#define adb_cond_wait pthread_cond_wait -#define adb_cond_broadcast pthread_cond_broadcast -#define adb_cond_signal pthread_cond_signal -#define adb_cond_destroy pthread_cond_destroy - -/* declare all mutexes */ -#define ADB_MUTEX(x) extern adb_mutex_t x; -#include "mutex_list.h" - -static __inline__ void close_on_exec(int fd) -{ - fcntl( fd, F_SETFD, FD_CLOEXEC ); -} - -static __inline__ int unix_open(const char* path, int options,...) -{ - if ((options & O_CREAT) == 0) - { - return open(path, options); - } - else - { - int mode; - va_list args; - va_start( args, options ); - mode = va_arg( args, int ); - va_end( args ); - return open(path, options, mode); - } -} - -static __inline__ int adb_open_mode( const char* pathname, int options, int mode ) -{ - return open( pathname, options, mode ); -} - -static __inline__ int adb_creat(const char* path, int mode) -{ - int fd = open(path, O_CREAT|O_WRONLY|O_TRUNC|O_NOFOLLOW, mode); - - if ( fd < 0 ) - return -1; - - close_on_exec(fd); - return fd; -} -#undef creat -#define creat ___xxx_creat - -static __inline__ int adb_open( const char* pathname, int options ) -{ - int fd = open( pathname, options ); - if (fd < 0) - return -1; - close_on_exec( fd ); - return fd; -} -#undef open -#define open ___xxx_open - -static __inline__ int adb_shutdown(int fd) -{ - return shutdown(fd, SHUT_RDWR); -} -#undef shutdown -#define shutdown ____xxx_shutdown - -static __inline__ int adb_close(int fd) -{ - return close(fd); -} -#undef close -#define close ____xxx_close - - -static __inline__ int adb_read(int fd, void* buf, size_t len) -{ - return read(fd, buf, len); -} - -#undef read -#define read ___xxx_read - -static __inline__ int adb_write(int fd, const void* buf, size_t len) -{ - return write(fd, buf, len); -} -#undef write -#define write ___xxx_write - -static __inline__ int adb_lseek(int fd, int pos, int where) -{ - return lseek(fd, pos, where); -} -#undef lseek -#define lseek ___xxx_lseek - -static __inline__ int adb_unlink(const char* path) -{ - return unlink(path); -} -#undef unlink -#define unlink ___xxx_unlink - -static __inline__ int adb_socket_accept(int serverfd, struct sockaddr* addr, socklen_t *addrlen) -{ - int fd; - - fd = accept(serverfd, addr, addrlen); - if (fd >= 0) - close_on_exec(fd); - - return fd; -} - -#undef accept -#define accept ___xxx_accept - -#define unix_read adb_read -#define unix_write adb_write -#define unix_close adb_close - -typedef pthread_t adb_thread_t; - -typedef void* (*adb_thread_func_t)( void* arg ); - -static __inline__ int adb_thread_create( adb_thread_t *pthread, adb_thread_func_t start, void* arg ) -{ - pthread_attr_t attr; - - pthread_attr_init (&attr); - pthread_attr_setdetachstate (&attr, PTHREAD_CREATE_DETACHED); - - return pthread_create( pthread, &attr, start, arg ); -} - -static __inline__ int adb_socket_setbufsize( int fd, int bufsize ) -{ - int opt = bufsize; - return setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &opt, sizeof(opt)); -} - -static __inline__ void disable_tcp_nagle(int fd) -{ - int on = 1; - setsockopt( fd, IPPROTO_TCP, TCP_NODELAY, (void*)&on, sizeof(on) ); -} - - -static __inline__ int unix_socketpair( int d, int type, int protocol, int sv[2] ) -{ - return socketpair( d, type, protocol, sv ); -} - -static __inline__ int adb_socketpair( int sv[2] ) -{ - int rc; - - rc = unix_socketpair( AF_UNIX, SOCK_STREAM, 0, sv ); - if (rc < 0) - return -1; - - close_on_exec( sv[0] ); - close_on_exec( sv[1] ); - return 0; -} - -#undef socketpair -#define socketpair ___xxx_socketpair - -static __inline__ void adb_sleep_ms( int mseconds ) -{ - usleep( mseconds*1000 ); -} - -static __inline__ int adb_mkdir(const char* path, int mode) -{ - return mkdir(path, mode); -} -#undef mkdir -#define mkdir ___xxx_mkdir - -static __inline__ void adb_sysdeps_init(void) -{ -} - -static __inline__ char* adb_dirstart(const char* path) -{ - return strchr(path, '/'); -} - -static __inline__ char* adb_dirstop(const char* path) -{ - return strrchr(path, '/'); -} - -static __inline__ int adb_is_absolute_host_path( const char* path ) -{ - return path[0] == '/'; -} - -#endif /* !_WIN32 */ - -#endif /* _ADB_SYSDEPS_H */ diff --git a/minadbd/transport.c b/minadbd/transport.c deleted file mode 100644 index 92679f518..000000000 --- a/minadbd/transport.c +++ /dev/null @@ -1,803 +0,0 @@ -/* - * Copyright (C) 2007 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include <stdio.h> -#include <stdlib.h> -#include <unistd.h> -#include <string.h> -#include <errno.h> - -#include "sysdeps.h" - -#define TRACE_TAG TRACE_TRANSPORT -#include "adb.h" - -static void transport_unref(atransport *t); - -static atransport transport_list = { - .next = &transport_list, - .prev = &transport_list, -}; - -ADB_MUTEX_DEFINE( transport_lock ); - -#if ADB_TRACE -#define MAX_DUMP_HEX_LEN 16 -static void dump_hex( const unsigned char* ptr, size_t len ) -{ - int nn, len2 = len; - // Build a string instead of logging each character. - // MAX chars in 2 digit hex, one space, MAX chars, one '\0'. - char buffer[MAX_DUMP_HEX_LEN *2 + 1 + MAX_DUMP_HEX_LEN + 1 ], *pb = buffer; - - if (len2 > MAX_DUMP_HEX_LEN) len2 = MAX_DUMP_HEX_LEN; - - for (nn = 0; nn < len2; nn++) { - sprintf(pb, "%02x", ptr[nn]); - pb += 2; - } - sprintf(pb++, " "); - - for (nn = 0; nn < len2; nn++) { - int c = ptr[nn]; - if (c < 32 || c > 127) - c = '.'; - *pb++ = c; - } - *pb++ = '\0'; - DR("%s\n", buffer); -} -#endif - -void -kick_transport(atransport* t) -{ - if (t && !t->kicked) - { - int kicked; - - adb_mutex_lock(&transport_lock); - kicked = t->kicked; - if (!kicked) - t->kicked = 1; - adb_mutex_unlock(&transport_lock); - - if (!kicked) - t->kick(t); - } -} - -void -run_transport_disconnects(atransport* t) -{ - adisconnect* dis = t->disconnects.next; - - D("%s: run_transport_disconnects\n", t->serial); - while (dis != &t->disconnects) { - adisconnect* next = dis->next; - dis->func( dis->opaque, t ); - dis = next; - } -} - -#if ADB_TRACE -static void -dump_packet(const char* name, const char* func, apacket* p) -{ - unsigned command = p->msg.command; - int len = p->msg.data_length; - char cmd[9]; - char arg0[12], arg1[12]; - int n; - - for (n = 0; n < 4; n++) { - int b = (command >> (n*8)) & 255; - if (b < 32 || b >= 127) - break; - cmd[n] = (char)b; - } - if (n == 4) { - cmd[4] = 0; - } else { - /* There is some non-ASCII name in the command, so dump - * the hexadecimal value instead */ - snprintf(cmd, sizeof cmd, "%08x", command); - } - - if (p->msg.arg0 < 256U) - snprintf(arg0, sizeof arg0, "%d", p->msg.arg0); - else - snprintf(arg0, sizeof arg0, "0x%x", p->msg.arg0); - - if (p->msg.arg1 < 256U) - snprintf(arg1, sizeof arg1, "%d", p->msg.arg1); - else - snprintf(arg1, sizeof arg1, "0x%x", p->msg.arg1); - - D("%s: %s: [%s] arg0=%s arg1=%s (len=%d) ", - name, func, cmd, arg0, arg1, len); - dump_hex(p->data, len); -} -#endif /* ADB_TRACE */ - -static int -read_packet(int fd, const char* name, apacket** ppacket) -{ - char *p = (char*)ppacket; /* really read a packet address */ - int r; - int len = sizeof(*ppacket); - char buff[8]; - if (!name) { - snprintf(buff, sizeof buff, "fd=%d", fd); - name = buff; - } - while(len > 0) { - r = adb_read(fd, p, len); - if(r > 0) { - len -= r; - p += r; - } else { - D("%s: read_packet (fd=%d), error ret=%d errno=%d: %s\n", name, fd, r, errno, strerror(errno)); - if((r < 0) && (errno == EINTR)) continue; - return -1; - } - } - -#if ADB_TRACE - if (ADB_TRACING) { - dump_packet(name, "from remote", *ppacket); - } -#endif - return 0; -} - -static int -write_packet(int fd, const char* name, apacket** ppacket) -{ - char *p = (char*) ppacket; /* we really write the packet address */ - int r, len = sizeof(ppacket); - char buff[8]; - if (!name) { - snprintf(buff, sizeof buff, "fd=%d", fd); - name = buff; - } - -#if ADB_TRACE - if (ADB_TRACING) { - dump_packet(name, "to remote", *ppacket); - } -#endif - len = sizeof(ppacket); - while(len > 0) { - r = adb_write(fd, p, len); - if(r > 0) { - len -= r; - p += r; - } else { - D("%s: write_packet (fd=%d) error ret=%d errno=%d: %s\n", name, fd, r, errno, strerror(errno)); - if((r < 0) && (errno == EINTR)) continue; - return -1; - } - } - return 0; -} - -static void transport_socket_events(int fd, unsigned events, void *_t) -{ - atransport *t = _t; - D("transport_socket_events(fd=%d, events=%04x,...)\n", fd, events); - if(events & FDE_READ){ - apacket *p = 0; - if(read_packet(fd, t->serial, &p)){ - D("%s: failed to read packet from transport socket on fd %d\n", t->serial, fd); - } else { - handle_packet(p, (atransport *) _t); - } - } -} - -void send_packet(apacket *p, atransport *t) -{ - unsigned char *x; - unsigned sum; - unsigned count; - - p->msg.magic = p->msg.command ^ 0xffffffff; - - count = p->msg.data_length; - x = (unsigned char *) p->data; - sum = 0; - while(count-- > 0){ - sum += *x++; - } - p->msg.data_check = sum; - - print_packet("send", p); - - if (t == NULL) { - D("Transport is null \n"); - // Zap errno because print_packet() and other stuff have errno effect. - errno = 0; - fatal_errno("Transport is null"); - } - - if(write_packet(t->transport_socket, t->serial, &p)){ - fatal_errno("cannot enqueue packet on transport socket"); - } -} - -/* The transport is opened by transport_register_func before -** the input and output threads are started. -** -** The output thread issues a SYNC(1, token) message to let -** the input thread know to start things up. In the event -** of transport IO failure, the output thread will post a -** SYNC(0,0) message to ensure shutdown. -** -** The transport will not actually be closed until both -** threads exit, but the input thread will kick the transport -** on its way out to disconnect the underlying device. -*/ - -static void *output_thread(void *_t) -{ - atransport *t = _t; - apacket *p; - - D("%s: starting transport output thread on fd %d, SYNC online (%d)\n", - t->serial, t->fd, t->sync_token + 1); - p = get_apacket(); - p->msg.command = A_SYNC; - p->msg.arg0 = 1; - p->msg.arg1 = ++(t->sync_token); - p->msg.magic = A_SYNC ^ 0xffffffff; - if(write_packet(t->fd, t->serial, &p)) { - put_apacket(p); - D("%s: failed to write SYNC packet\n", t->serial); - goto oops; - } - - D("%s: data pump started\n", t->serial); - for(;;) { - p = get_apacket(); - - if(t->read_from_remote(p, t) == 0){ - D("%s: received remote packet, sending to transport\n", - t->serial); - if(write_packet(t->fd, t->serial, &p)){ - put_apacket(p); - D("%s: failed to write apacket to transport\n", t->serial); - goto oops; - } - } else { - D("%s: remote read failed for transport\n", t->serial); - put_apacket(p); - break; - } - } - - D("%s: SYNC offline for transport\n", t->serial); - p = get_apacket(); - p->msg.command = A_SYNC; - p->msg.arg0 = 0; - p->msg.arg1 = 0; - p->msg.magic = A_SYNC ^ 0xffffffff; - if(write_packet(t->fd, t->serial, &p)) { - put_apacket(p); - D("%s: failed to write SYNC apacket to transport", t->serial); - } - -oops: - D("%s: transport output thread is exiting\n", t->serial); - kick_transport(t); - transport_unref(t); - return 0; -} - -static void *input_thread(void *_t) -{ - atransport *t = _t; - apacket *p; - int active = 0; - - D("%s: starting transport input thread, reading from fd %d\n", - t->serial, t->fd); - - for(;;){ - if(read_packet(t->fd, t->serial, &p)) { - D("%s: failed to read apacket from transport on fd %d\n", - t->serial, t->fd ); - break; - } - if(p->msg.command == A_SYNC){ - if(p->msg.arg0 == 0) { - D("%s: transport SYNC offline\n", t->serial); - put_apacket(p); - break; - } else { - if(p->msg.arg1 == t->sync_token) { - D("%s: transport SYNC online\n", t->serial); - active = 1; - } else { - D("%s: transport ignoring SYNC %d != %d\n", - t->serial, p->msg.arg1, t->sync_token); - } - } - } else { - if(active) { - D("%s: transport got packet, sending to remote\n", t->serial); - t->write_to_remote(p, t); - } else { - D("%s: transport ignoring packet while offline\n", t->serial); - } - } - - put_apacket(p); - } - - // this is necessary to avoid a race condition that occured when a transport closes - // while a client socket is still active. - close_all_sockets(t); - - D("%s: transport input thread is exiting, fd %d\n", t->serial, t->fd); - kick_transport(t); - transport_unref(t); - return 0; -} - - -static int transport_registration_send = -1; -static int transport_registration_recv = -1; -static fdevent transport_registration_fde; - -void update_transports(void) -{ - // nothing to do on the device side -} - -typedef struct tmsg tmsg; -struct tmsg -{ - atransport *transport; - int action; -}; - -static int -transport_read_action(int fd, struct tmsg* m) -{ - char *p = (char*)m; - int len = sizeof(*m); - int r; - - while(len > 0) { - r = adb_read(fd, p, len); - if(r > 0) { - len -= r; - p += r; - } else { - if((r < 0) && (errno == EINTR)) continue; - D("transport_read_action: on fd %d, error %d: %s\n", - fd, errno, strerror(errno)); - return -1; - } - } - return 0; -} - -static int -transport_write_action(int fd, struct tmsg* m) -{ - char *p = (char*)m; - int len = sizeof(*m); - int r; - - while(len > 0) { - r = adb_write(fd, p, len); - if(r > 0) { - len -= r; - p += r; - } else { - if((r < 0) && (errno == EINTR)) continue; - D("transport_write_action: on fd %d, error %d: %s\n", - fd, errno, strerror(errno)); - return -1; - } - } - return 0; -} - -static void transport_registration_func(int _fd, unsigned ev, void *data) -{ - tmsg m; - adb_thread_t output_thread_ptr; - adb_thread_t input_thread_ptr; - int s[2]; - atransport *t; - - if(!(ev & FDE_READ)) { - return; - } - - if(transport_read_action(_fd, &m)) { - fatal_errno("cannot read transport registration socket"); - } - - t = m.transport; - - if(m.action == 0){ - D("transport: %s removing and free'ing %d\n", t->serial, t->transport_socket); - - /* IMPORTANT: the remove closes one half of the - ** socket pair. The close closes the other half. - */ - fdevent_remove(&(t->transport_fde)); - adb_close(t->fd); - - adb_mutex_lock(&transport_lock); - t->next->prev = t->prev; - t->prev->next = t->next; - adb_mutex_unlock(&transport_lock); - - run_transport_disconnects(t); - - if (t->product) - free(t->product); - if (t->serial) - free(t->serial); - - memset(t,0xee,sizeof(atransport)); - free(t); - - update_transports(); - return; - } - - /* don't create transport threads for inaccessible devices */ - if (t->connection_state != CS_NOPERM) { - /* initial references are the two threads */ - t->ref_count = 2; - - if(adb_socketpair(s)) { - fatal_errno("cannot open transport socketpair"); - } - - D("transport: %s (%d,%d) starting\n", t->serial, s[0], s[1]); - - t->transport_socket = s[0]; - t->fd = s[1]; - - fdevent_install(&(t->transport_fde), - t->transport_socket, - transport_socket_events, - t); - - fdevent_set(&(t->transport_fde), FDE_READ); - - if(adb_thread_create(&input_thread_ptr, input_thread, t)){ - fatal_errno("cannot create input thread"); - } - - if(adb_thread_create(&output_thread_ptr, output_thread, t)){ - fatal_errno("cannot create output thread"); - } - } - - /* put us on the master device list */ - adb_mutex_lock(&transport_lock); - t->next = &transport_list; - t->prev = transport_list.prev; - t->next->prev = t; - t->prev->next = t; - adb_mutex_unlock(&transport_lock); - - t->disconnects.next = t->disconnects.prev = &t->disconnects; - - update_transports(); -} - -void init_transport_registration(void) -{ - int s[2]; - - if(adb_socketpair(s)){ - fatal_errno("cannot open transport registration socketpair"); - } - - transport_registration_send = s[0]; - transport_registration_recv = s[1]; - - fdevent_install(&transport_registration_fde, - transport_registration_recv, - transport_registration_func, - 0); - - fdevent_set(&transport_registration_fde, FDE_READ); -} - -/* the fdevent select pump is single threaded */ -static void register_transport(atransport *transport) -{ - tmsg m; - m.transport = transport; - m.action = 1; - D("transport: %s registered\n", transport->serial); - if(transport_write_action(transport_registration_send, &m)) { - fatal_errno("cannot write transport registration socket\n"); - } -} - -static void remove_transport(atransport *transport) -{ - tmsg m; - m.transport = transport; - m.action = 0; - D("transport: %s removed\n", transport->serial); - if(transport_write_action(transport_registration_send, &m)) { - fatal_errno("cannot write transport registration socket\n"); - } -} - - -static void transport_unref_locked(atransport *t) -{ - t->ref_count--; - if (t->ref_count == 0) { - D("transport: %s unref (kicking and closing)\n", t->serial); - if (!t->kicked) { - t->kicked = 1; - t->kick(t); - } - t->close(t); - remove_transport(t); - } else { - D("transport: %s unref (count=%d)\n", t->serial, t->ref_count); - } -} - -static void transport_unref(atransport *t) -{ - if (t) { - adb_mutex_lock(&transport_lock); - transport_unref_locked(t); - adb_mutex_unlock(&transport_lock); - } -} - -void add_transport_disconnect(atransport* t, adisconnect* dis) -{ - adb_mutex_lock(&transport_lock); - dis->next = &t->disconnects; - dis->prev = dis->next->prev; - dis->prev->next = dis; - dis->next->prev = dis; - adb_mutex_unlock(&transport_lock); -} - -void remove_transport_disconnect(atransport* t, adisconnect* dis) -{ - dis->prev->next = dis->next; - dis->next->prev = dis->prev; - dis->next = dis->prev = dis; -} - - -atransport *acquire_one_transport(int state, transport_type ttype, const char* serial, char** error_out) -{ - atransport *t; - atransport *result = NULL; - int ambiguous = 0; - -retry: - if (error_out) - *error_out = "device not found"; - - adb_mutex_lock(&transport_lock); - for (t = transport_list.next; t != &transport_list; t = t->next) { - if (t->connection_state == CS_NOPERM) { - if (error_out) - *error_out = "insufficient permissions for device"; - continue; - } - - /* check for matching serial number */ - if (serial) { - if (t->serial && !strcmp(serial, t->serial)) { - result = t; - break; - } - } else { - if (ttype == kTransportUsb && t->type == kTransportUsb) { - if (result) { - if (error_out) - *error_out = "more than one device"; - ambiguous = 1; - result = NULL; - break; - } - result = t; - } else if (ttype == kTransportLocal && t->type == kTransportLocal) { - if (result) { - if (error_out) - *error_out = "more than one emulator"; - ambiguous = 1; - result = NULL; - break; - } - result = t; - } else if (ttype == kTransportAny) { - if (result) { - if (error_out) - *error_out = "more than one device and emulator"; - ambiguous = 1; - result = NULL; - break; - } - result = t; - } - } - } - adb_mutex_unlock(&transport_lock); - - if (result) { - /* offline devices are ignored -- they are either being born or dying */ - if (result && result->connection_state == CS_OFFLINE) { - if (error_out) - *error_out = "device offline"; - result = NULL; - } - /* check for required connection state */ - if (result && state != CS_ANY && result->connection_state != state) { - if (error_out) - *error_out = "invalid device state"; - result = NULL; - } - } - - if (result) { - /* found one that we can take */ - if (error_out) - *error_out = NULL; - } else if (state != CS_ANY && (serial || !ambiguous)) { - adb_sleep_ms(1000); - goto retry; - } - - return result; -} - -void register_usb_transport(usb_handle *usb, const char *serial, unsigned writeable) -{ - atransport *t = calloc(1, sizeof(atransport)); - D("transport: %p init'ing for usb_handle %p (sn='%s')\n", t, usb, - serial ? serial : ""); - init_usb_transport(t, usb, (writeable ? CS_OFFLINE : CS_NOPERM)); - if(serial) { - t->serial = strdup(serial); - } - register_transport(t); -} - -/* this should only be used for transports with connection_state == CS_NOPERM */ -void unregister_usb_transport(usb_handle *usb) -{ - atransport *t; - adb_mutex_lock(&transport_lock); - for(t = transport_list.next; t != &transport_list; t = t->next) { - if (t->usb == usb && t->connection_state == CS_NOPERM) { - t->next->prev = t->prev; - t->prev->next = t->next; - break; - } - } - adb_mutex_unlock(&transport_lock); -} - -#undef TRACE_TAG -#define TRACE_TAG TRACE_RWX - -int readx(int fd, void *ptr, size_t len) -{ - char *p = ptr; - int r; -#if ADB_TRACE - size_t len0 = len; -#endif - D("readx: fd=%d wanted=%d\n", fd, (int)len); - while(len > 0) { - r = adb_read(fd, p, len); - if(r > 0) { - len -= r; - p += r; - } else { - if (r < 0) { - D("readx: fd=%d error %d: %s\n", fd, errno, strerror(errno)); - if (errno == EINTR) - continue; - } else { - D("readx: fd=%d disconnected\n", fd); - } - return -1; - } - } - -#if ADB_TRACE - D("readx: fd=%d wanted=%zu got=%zu\n", fd, len0, len0 - len); - dump_hex( ptr, len0 ); -#endif - return 0; -} - -int writex(int fd, const void *ptr, size_t len) -{ - char *p = (char*) ptr; - int r; - -#if ADB_TRACE - D("writex: fd=%d len=%d: ", fd, (int)len); - dump_hex( ptr, len ); -#endif - while(len > 0) { - r = adb_write(fd, p, len); - if(r > 0) { - len -= r; - p += r; - } else { - if (r < 0) { - D("writex: fd=%d error %d: %s\n", fd, errno, strerror(errno)); - if (errno == EINTR) - continue; - } else { - D("writex: fd=%d disconnected\n", fd); - } - return -1; - } - } - return 0; -} - -int check_header(apacket *p) -{ - if(p->msg.magic != (p->msg.command ^ 0xffffffff)) { - D("check_header(): invalid magic\n"); - return -1; - } - - if(p->msg.data_length > MAX_PAYLOAD) { - D("check_header(): %d > MAX_PAYLOAD\n", p->msg.data_length); - return -1; - } - - return 0; -} - -int check_data(apacket *p) -{ - unsigned count, sum; - unsigned char *x; - - count = p->msg.data_length; - x = p->data; - sum = 0; - while(count-- > 0) { - sum += *x++; - } - - if(sum != p->msg.data_check) { - return -1; - } else { - return 0; - } -} diff --git a/minadbd/transport_usb.c b/minadbd/transport_usb.c deleted file mode 100644 index 91cbf6151..000000000 --- a/minadbd/transport_usb.c +++ /dev/null @@ -1,121 +0,0 @@ -/* - * Copyright (C) 2007 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include <stdio.h> -#include <stdlib.h> -#include <string.h> - -#include <sysdeps.h> - -#define TRACE_TAG TRACE_TRANSPORT -#include "adb.h" - -#ifdef HAVE_BIG_ENDIAN -#define H4(x) (((x) & 0xFF000000) >> 24) | (((x) & 0x00FF0000) >> 8) | (((x) & 0x0000FF00) << 8) | (((x) & 0x000000FF) << 24) -static inline void fix_endians(apacket *p) -{ - p->msg.command = H4(p->msg.command); - p->msg.arg0 = H4(p->msg.arg0); - p->msg.arg1 = H4(p->msg.arg1); - p->msg.data_length = H4(p->msg.data_length); - p->msg.data_check = H4(p->msg.data_check); - p->msg.magic = H4(p->msg.magic); -} -unsigned host_to_le32(unsigned n) -{ - return H4(n); -} -#else -#define fix_endians(p) do {} while (0) -unsigned host_to_le32(unsigned n) -{ - return n; -} -#endif - -static int remote_read(apacket *p, atransport *t) -{ - if(usb_read(t->usb, &p->msg, sizeof(amessage))){ - D("remote usb: read terminated (message)\n"); - return -1; - } - - fix_endians(p); - - if(check_header(p)) { - D("remote usb: check_header failed\n"); - return -1; - } - - if(p->msg.data_length) { - if(usb_read(t->usb, p->data, p->msg.data_length)){ - D("remote usb: terminated (data)\n"); - return -1; - } - } - - if(check_data(p)) { - D("remote usb: check_data failed\n"); - return -1; - } - - return 0; -} - -static int remote_write(apacket *p, atransport *t) -{ - unsigned size = p->msg.data_length; - - fix_endians(p); - - if(usb_write(t->usb, &p->msg, sizeof(amessage))) { - D("remote usb: 1 - write terminated\n"); - return -1; - } - if(p->msg.data_length == 0) return 0; - if(usb_write(t->usb, &p->data, size)) { - D("remote usb: 2 - write terminated\n"); - return -1; - } - - return 0; -} - -static void remote_close(atransport *t) -{ - usb_close(t->usb); - t->usb = 0; -} - -static void remote_kick(atransport *t) -{ - usb_kick(t->usb); -} - -void init_usb_transport(atransport *t, usb_handle *h, int state) -{ - D("transport: usb\n"); - t->close = remote_close; - t->kick = remote_kick; - t->read_from_remote = remote_read; - t->write_to_remote = remote_write; - t->sync_token = 1; - t->connection_state = state; - t->type = kTransportUsb; - t->usb = h; - - HOST = 0; -} diff --git a/minadbd/usb_linux_client.c b/minadbd/usb_linux_client.c deleted file mode 100644 index 29bab1558..000000000 --- a/minadbd/usb_linux_client.c +++ /dev/null @@ -1,493 +0,0 @@ -/* - * Copyright (C) 2007 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include <stdio.h> -#include <stdlib.h> -#include <unistd.h> -#include <string.h> - -#include <linux/usb/ch9.h> -#include <linux/usb/functionfs.h> -#include <sys/ioctl.h> -#include <sys/types.h> -#include <dirent.h> -#include <errno.h> - -#include "sysdeps.h" - -#define TRACE_TAG TRACE_USB -#include "adb.h" - -#define MAX_PACKET_SIZE_FS 64 -#define MAX_PACKET_SIZE_HS 512 - -#define cpu_to_le16(x) htole16(x) -#define cpu_to_le32(x) htole32(x) - -struct usb_handle -{ - int fd; - adb_cond_t notify; - adb_mutex_t lock; - - int (*write)(usb_handle *h, const void *data, int len); - int (*read)(usb_handle *h, void *data, int len); - void (*kick)(usb_handle *h); - - int control; - int bulk_out; /* "out" from the host's perspective => source for adbd */ - int bulk_in; /* "in" from the host's perspective => sink for adbd */ -}; - -static const struct { - struct usb_functionfs_descs_head header; - struct { - struct usb_interface_descriptor intf; - struct usb_endpoint_descriptor_no_audio source; - struct usb_endpoint_descriptor_no_audio sink; - } __attribute__((packed)) fs_descs, hs_descs; -} __attribute__((packed)) descriptors = { - .header = { - .magic = cpu_to_le32(FUNCTIONFS_DESCRIPTORS_MAGIC), - .length = cpu_to_le32(sizeof(descriptors)), - .fs_count = 3, - .hs_count = 3, - }, - .fs_descs = { - .intf = { - .bLength = sizeof(descriptors.fs_descs.intf), - .bDescriptorType = USB_DT_INTERFACE, - .bInterfaceNumber = 0, - .bNumEndpoints = 2, - .bInterfaceClass = ADB_CLASS, - .bInterfaceSubClass = ADB_SUBCLASS, - .bInterfaceProtocol = ADB_PROTOCOL, - .iInterface = 1, /* first string from the provided table */ - }, - .source = { - .bLength = sizeof(descriptors.fs_descs.source), - .bDescriptorType = USB_DT_ENDPOINT, - .bEndpointAddress = 1 | USB_DIR_OUT, - .bmAttributes = USB_ENDPOINT_XFER_BULK, - .wMaxPacketSize = MAX_PACKET_SIZE_FS, - }, - .sink = { - .bLength = sizeof(descriptors.fs_descs.sink), - .bDescriptorType = USB_DT_ENDPOINT, - .bEndpointAddress = 2 | USB_DIR_IN, - .bmAttributes = USB_ENDPOINT_XFER_BULK, - .wMaxPacketSize = MAX_PACKET_SIZE_FS, - }, - }, - .hs_descs = { - .intf = { - .bLength = sizeof(descriptors.hs_descs.intf), - .bDescriptorType = USB_DT_INTERFACE, - .bInterfaceNumber = 0, - .bNumEndpoints = 2, - .bInterfaceClass = ADB_CLASS, - .bInterfaceSubClass = ADB_SUBCLASS, - .bInterfaceProtocol = ADB_PROTOCOL, - .iInterface = 1, /* first string from the provided table */ - }, - .source = { - .bLength = sizeof(descriptors.hs_descs.source), - .bDescriptorType = USB_DT_ENDPOINT, - .bEndpointAddress = 1 | USB_DIR_OUT, - .bmAttributes = USB_ENDPOINT_XFER_BULK, - .wMaxPacketSize = MAX_PACKET_SIZE_HS, - }, - .sink = { - .bLength = sizeof(descriptors.hs_descs.sink), - .bDescriptorType = USB_DT_ENDPOINT, - .bEndpointAddress = 2 | USB_DIR_IN, - .bmAttributes = USB_ENDPOINT_XFER_BULK, - .wMaxPacketSize = MAX_PACKET_SIZE_HS, - }, - }, -}; - -#define STR_INTERFACE_ "ADB Interface" - -static const struct { - struct usb_functionfs_strings_head header; - struct { - __le16 code; - const char str1[sizeof(STR_INTERFACE_)]; - } __attribute__((packed)) lang0; -} __attribute__((packed)) strings = { - .header = { - .magic = cpu_to_le32(FUNCTIONFS_STRINGS_MAGIC), - .length = cpu_to_le32(sizeof(strings)), - .str_count = cpu_to_le32(1), - .lang_count = cpu_to_le32(1), - }, - .lang0 = { - cpu_to_le16(0x0409), /* en-us */ - STR_INTERFACE_, - }, -}; - -void usb_cleanup() -{ - // nothing to do here -} - -static void *usb_adb_open_thread(void *x) -{ - struct usb_handle *usb = (struct usb_handle *)x; - int fd; - - while (1) { - // wait until the USB device needs opening - adb_mutex_lock(&usb->lock); - while (usb->fd != -1) - adb_cond_wait(&usb->notify, &usb->lock); - adb_mutex_unlock(&usb->lock); - - D("[ usb_thread - opening device ]\n"); - do { - /* XXX use inotify? */ - fd = unix_open("/dev/android_adb", O_RDWR); - if (fd < 0) { - // to support older kernels - fd = unix_open("/dev/android", O_RDWR); - fprintf(stderr, "usb_adb_open_thread: %d\n", fd ); - } - if (fd < 0) { - adb_sleep_ms(1000); - } - } while (fd < 0); - D("[ opening device succeeded ]\n"); - - close_on_exec(fd); - usb->fd = fd; - - D("[ usb_thread - registering device ]\n"); - register_usb_transport(usb, 0, 1); - } - - // never gets here - return 0; -} - -static int usb_adb_write(usb_handle *h, const void *data, int len) -{ - int n; - - D("about to write (fd=%d, len=%d)\n", h->fd, len); - n = adb_write(h->fd, data, len); - if(n != len) { - D("ERROR: fd = %d, n = %d, errno = %d (%s)\n", - h->fd, n, errno, strerror(errno)); - return -1; - } - D("[ done fd=%d ]\n", h->fd); - return 0; -} - -static int usb_adb_read(usb_handle *h, void *data, int len) -{ - int n; - - D("about to read (fd=%d, len=%d)\n", h->fd, len); - n = adb_read(h->fd, data, len); - if(n != len) { - D("ERROR: fd = %d, n = %d, errno = %d (%s)\n", - h->fd, n, errno, strerror(errno)); - return -1; - } - D("[ done fd=%d ]\n", h->fd); - return 0; -} - -static void usb_adb_kick(usb_handle *h) -{ - D("usb_kick\n"); - adb_mutex_lock(&h->lock); - adb_close(h->fd); - h->fd = -1; - - // notify usb_adb_open_thread that we are disconnected - adb_cond_signal(&h->notify); - adb_mutex_unlock(&h->lock); -} - -static void usb_adb_init() -{ - usb_handle *h; - adb_thread_t tid; - int fd; - - h = calloc(1, sizeof(usb_handle)); - - h->write = usb_adb_write; - h->read = usb_adb_read; - h->kick = usb_adb_kick; - h->fd = -1; - - adb_cond_init(&h->notify, 0); - adb_mutex_init(&h->lock, 0); - - fprintf(stderr, "Starting to open usb_init()\n"); - // Open the file /dev/android_adb_enable to trigger - // the enabling of the adb USB function in the kernel. - // We never touch this file again - just leave it open - // indefinitely so the kernel will know when we are running - // and when we are not. - fd = unix_open("/dev/android_adb_enable", O_RDWR); - fprintf(stderr, "unix_open to open usb_init(): %d\n", fd); - if (fd < 0) { - D("failed to open /dev/android_adb_enable\n"); - } else { - close_on_exec(fd); - } - - D("[ usb_init - starting thread ]\n"); - if(adb_thread_create(&tid, usb_adb_open_thread, h)){ - fatal_errno("cannot create usb thread"); - fprintf(stderr, "cannot create the usb thread()\n"); - } -} - - -static void init_functionfs(struct usb_handle *h) -{ - ssize_t ret; - - D("OPENING %s\n", USB_FFS_ADB_EP0); - h->control = adb_open(USB_FFS_ADB_EP0, O_RDWR); - if (h->control < 0) { - D("[ %s: cannot open control endpoint: errno=%d]\n", USB_FFS_ADB_EP0, errno); - goto err; - } - - ret = adb_write(h->control, &descriptors, sizeof(descriptors)); - if (ret < 0) { - D("[ %s: write descriptors failed: errno=%d ]\n", USB_FFS_ADB_EP0, errno); - goto err; - } - - ret = adb_write(h->control, &strings, sizeof(strings)); - if (ret < 0) { - D("[ %s: writing strings failed: errno=%d]\n", USB_FFS_ADB_EP0, errno); - goto err; - } - - h->bulk_out = adb_open(USB_FFS_ADB_OUT, O_RDWR); - if (h->bulk_out < 0) { - D("[ %s: cannot open bulk-out ep: errno=%d ]\n", USB_FFS_ADB_OUT, errno); - goto err; - } - - h->bulk_in = adb_open(USB_FFS_ADB_IN, O_RDWR); - if (h->bulk_in < 0) { - D("[ %s: cannot open bulk-in ep: errno=%d ]\n", USB_FFS_ADB_IN, errno); - goto err; - } - - return; - -err: - if (h->bulk_in > 0) { - adb_close(h->bulk_in); - h->bulk_in = -1; - } - if (h->bulk_out > 0) { - adb_close(h->bulk_out); - h->bulk_out = -1; - } - if (h->control > 0) { - adb_close(h->control); - h->control = -1; - } - return; -} - -static void *usb_ffs_open_thread(void *x) -{ - struct usb_handle *usb = (struct usb_handle *)x; - - while (1) { - // wait until the USB device needs opening - adb_mutex_lock(&usb->lock); - while (usb->control != -1) - adb_cond_wait(&usb->notify, &usb->lock); - adb_mutex_unlock(&usb->lock); - - while (1) { - init_functionfs(usb); - - if (usb->control >= 0) - break; - - adb_sleep_ms(1000); - } - - D("[ usb_thread - registering device ]\n"); - register_usb_transport(usb, 0, 1); - } - - // never gets here - return 0; -} - -static int bulk_write(int bulk_in, const char *buf, size_t length) -{ - size_t count = 0; - int ret; - - do { - ret = adb_write(bulk_in, buf + count, length - count); - if (ret < 0) { - if (errno != EINTR) - return ret; - } else { - count += ret; - } - } while (count < length); - - D("[ bulk_write done fd=%d ]\n", bulk_in); - return count; -} - -static int usb_ffs_write(usb_handle *h, const void *data, int len) -{ - int n; - - D("about to write (fd=%d, len=%d)\n", h->bulk_in, len); - n = bulk_write(h->bulk_in, data, len); - if (n != len) { - D("ERROR: fd = %d, n = %d, errno = %d (%s)\n", - h->bulk_in, n, errno, strerror(errno)); - return -1; - } - D("[ done fd=%d ]\n", h->bulk_in); - return 0; -} - -static int bulk_read(int bulk_out, char *buf, size_t length) -{ - size_t count = 0; - int ret; - - do { - ret = adb_read(bulk_out, buf + count, length - count); - if (ret < 0) { - if (errno != EINTR) { - D("[ bulk_read failed fd=%d length=%zu count=%zu ]\n", - bulk_out, length, count); - return ret; - } - } else { - count += ret; - } - } while (count < length); - - return count; -} - -static int usb_ffs_read(usb_handle *h, void *data, int len) -{ - int n; - - D("about to read (fd=%d, len=%d)\n", h->bulk_out, len); - n = bulk_read(h->bulk_out, data, len); - if (n != len) { - D("ERROR: fd = %d, n = %d, errno = %d (%s)\n", - h->bulk_out, n, errno, strerror(errno)); - return -1; - } - D("[ done fd=%d ]\n", h->bulk_out); - return 0; -} - -static void usb_ffs_kick(usb_handle *h) -{ - int err; - - err = ioctl(h->bulk_in, FUNCTIONFS_CLEAR_HALT); - if (err < 0) - D("[ kick: source (fd=%d) clear halt failed (%d) ]", h->bulk_in, errno); - - err = ioctl(h->bulk_out, FUNCTIONFS_CLEAR_HALT); - if (err < 0) - D("[ kick: sink (fd=%d) clear halt failed (%d) ]", h->bulk_out, errno); - - adb_mutex_lock(&h->lock); - adb_close(h->control); - adb_close(h->bulk_out); - adb_close(h->bulk_in); - h->control = h->bulk_out = h->bulk_in = -1; - - // notify usb_ffs_open_thread that we are disconnected - adb_cond_signal(&h->notify); - adb_mutex_unlock(&h->lock); -} - -static void usb_ffs_init() -{ - usb_handle *h; - adb_thread_t tid; - - D("[ usb_init - using FunctionFS ]\n"); - - h = calloc(1, sizeof(usb_handle)); - - h->write = usb_ffs_write; - h->read = usb_ffs_read; - h->kick = usb_ffs_kick; - - h->control = -1; - h->bulk_out = -1; - h->bulk_out = -1; - - adb_cond_init(&h->notify, 0); - adb_mutex_init(&h->lock, 0); - - D("[ usb_init - starting thread ]\n"); - if (adb_thread_create(&tid, usb_ffs_open_thread, h)){ - fatal_errno("[ cannot create usb thread ]\n"); - } -} - -void usb_init() -{ - if (access(USB_FFS_ADB_EP0, F_OK) == 0) - usb_ffs_init(); - else - usb_adb_init(); -} - -int usb_write(usb_handle *h, const void *data, int len) -{ - return h->write(h, data, len); -} - -int usb_read(usb_handle *h, void *data, int len) -{ - return h->read(h, data, len); -} -int usb_close(usb_handle *h) -{ - // nothing to do here - return 0; -} - -void usb_kick(usb_handle *h) -{ - h->kick(h); -} diff --git a/minadbd/utils.c b/minadbd/utils.c deleted file mode 100644 index 91518bab6..000000000 --- a/minadbd/utils.c +++ /dev/null @@ -1,106 +0,0 @@ -/* - * Copyright (C) 2008 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -#include "utils.h" -#include <stdarg.h> -#include <stdio.h> -#include <string.h> - -char* -buff_addc (char* buff, char* buffEnd, int c) -{ - int avail = buffEnd - buff; - - if (avail <= 0) /* already in overflow mode */ - return buff; - - if (avail == 1) { /* overflowing, the last byte is reserved for zero */ - buff[0] = 0; - return buff + 1; - } - - buff[0] = (char) c; /* add char and terminating zero */ - buff[1] = 0; - return buff + 1; -} - -char* -buff_adds (char* buff, char* buffEnd, const char* s) -{ - int slen = strlen(s); - - return buff_addb(buff, buffEnd, s, slen); -} - -char* -buff_addb (char* buff, char* buffEnd, const void* data, int len) -{ - int avail = (buffEnd - buff); - - if (avail <= 0 || len <= 0) /* already overflowing */ - return buff; - - if (len > avail) - len = avail; - - memcpy(buff, data, len); - - buff += len; - - /* ensure there is a terminating zero */ - if (buff >= buffEnd) { /* overflow */ - buff[-1] = 0; - } else - buff[0] = 0; - - return buff; -} - -char* -buff_add (char* buff, char* buffEnd, const char* format, ... ) -{ - int avail; - - avail = (buffEnd - buff); - - if (avail > 0) { - va_list args; - int nn; - - va_start(args, format); - nn = vsnprintf( buff, avail, format, args); - va_end(args); - - if (nn < 0) { - /* some C libraries return -1 in case of overflow, - * but they will also do that if the format spec is - * invalid. We assume ADB is not buggy enough to - * trigger that last case. */ - nn = avail; - } - else if (nn > avail) { - nn = avail; - } - - buff += nn; - - /* ensure that there is a terminating zero */ - if (buff >= buffEnd) - buff[-1] = 0; - else - buff[0] = 0; - } - return buff; -} diff --git a/minadbd/utils.h b/minadbd/utils.h deleted file mode 100644 index f70ecd24d..000000000 --- a/minadbd/utils.h +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Copyright (C) 2008 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -#ifndef _ADB_UTILS_H -#define _ADB_UTILS_H - -/* bounded buffer functions */ - -/* all these functions are used to append data to a bounded buffer. - * - * after each operation, the buffer is guaranteed to be zero-terminated, - * even in the case of an overflow. they all return the new buffer position - * which allows one to use them in succession, only checking for overflows - * at the end. For example: - * - * BUFF_DECL(temp,p,end,1024); - * char* p; - * - * p = buff_addc(temp, end, '"'); - * p = buff_adds(temp, end, string); - * p = buff_addc(temp, end, '"'); - * - * if (p >= end) { - * overflow detected. note that 'temp' is - * zero-terminated for safety. - * } - * return strdup(temp); - */ - -/* tries to add a character to the buffer, in case of overflow - * this will only write a terminating zero and return buffEnd. - */ -char* buff_addc (char* buff, char* buffEnd, int c); - -/* tries to add a string to the buffer */ -char* buff_adds (char* buff, char* buffEnd, const char* s); - -/* tries to add a bytes to the buffer. the input can contain zero bytes, - * but a terminating zero will always be appended at the end anyway - */ -char* buff_addb (char* buff, char* buffEnd, const void* data, int len); - -/* tries to add a formatted string to a bounded buffer */ -char* buff_add (char* buff, char* buffEnd, const char* format, ... ); - -/* convenience macro used to define a bounded buffer, as well as - * a 'cursor' and 'end' variables all in one go. - * - * note: this doesn't place an initial terminating zero in the buffer, - * you need to use one of the buff_ functions for this. or simply - * do _cursor[0] = 0 manually. - */ -#define BUFF_DECL(_buff,_cursor,_end,_size) \ - char _buff[_size], *_cursor=_buff, *_end = _cursor + (_size) - -#endif /* _ADB_UTILS_H */ |