diff options
| author | The Android Open Source Project <initial-contribution@android.com> | 2009-03-03 18:29:04 -0800 |
|---|---|---|
| committer | The Android Open Source Project <initial-contribution@android.com> | 2009-03-03 18:29:04 -0800 |
| commit | e54eebbf1a908d65ee8cf80bab62821c05666d70 (patch) | |
| tree | 4b825dc642cb6eb9a060e54bf8d69288fbee4904 /adb | |
| parent | a1e1c1b106423de09bc918502e7a51d4ffe5a4ae (diff) | |
| download | system_core-e54eebbf1a908d65ee8cf80bab62821c05666d70.tar.gz system_core-e54eebbf1a908d65ee8cf80bab62821c05666d70.tar.bz2 system_core-e54eebbf1a908d65ee8cf80bab62821c05666d70.zip | |
auto import from //depot/cupcake/@135843
Diffstat (limited to 'adb')
40 files changed, 0 insertions, 13929 deletions
diff --git a/adb/Android.mk b/adb/Android.mk deleted file mode 100644 index 2296610a..00000000 --- a/adb/Android.mk +++ /dev/null @@ -1,140 +0,0 @@ -# Copyright 2005 The Android Open Source Project -# -# Android.mk for adb -# - -LOCAL_PATH:= $(call my-dir) - -# adb host tool -# ========================================================= -ifneq ($(TARGET_SIMULATOR),true) # not 64 bit clean (also unused with the sim) -include $(CLEAR_VARS) - -# Default to a virtual (sockets) usb interface -USB_SRCS := -EXTRA_SRCS := - -ifeq ($(HOST_OS),linux) - USB_SRCS := usb_linux.c - EXTRA_SRCS := get_my_path_linux.c - LOCAL_LDLIBS += -lrt -lncurses -lpthread -endif - -ifeq ($(HOST_OS),darwin) - USB_SRCS := usb_osx.c - EXTRA_SRCS := get_my_path_darwin.c - LOCAL_LDLIBS += -lpthread -framework CoreFoundation -framework IOKit -framework Carbon -endif - -ifeq ($(HOST_OS),windows) - USB_SRCS := usb_windows.c - EXTRA_SRCS := get_my_path_windows.c - EXTRA_STATIC_LIBS := AdbWinApi - LOCAL_C_INCLUDES += /usr/include/w32api/ddk development/host/windows/usb/api/ - ifneq ($(strip $(USE_CYGWIN)),) - LOCAL_LDLIBS += -lpthread - else - LOCAL_LDLIBS += -lws2_32 - USE_SYSDEPS_WIN32 := 1 - endif -endif - -LOCAL_SRC_FILES := \ - adb.c \ - console.c \ - transport.c \ - transport_local.c \ - transport_usb.c \ - commandline.c \ - adb_client.c \ - sockets.c \ - services.c \ - file_sync_client.c \ - $(EXTRA_SRCS) \ - $(USB_SRCS) \ - shlist.c \ - utils.c \ - - -ifneq ($(USE_SYSDEPS_WIN32),) - LOCAL_SRC_FILES += sysdeps_win32.c -endif - -LOCAL_CFLAGS += -O2 -g -DADB_HOST=1 -Wall -Wno-unused-parameter -LOCAL_CFLAGS += -D_XOPEN_SOURCE -D_GNU_SOURCE -DSH_HISTORY -LOCAL_MODULE := adb - -LOCAL_STATIC_LIBRARIES := libzipfile libunz $(EXTRA_STATIC_LIBS) -ifeq ($(USE_SYSDEPS_WIN32),) - LOCAL_STATIC_LIBRARIES += libcutils -endif - -include $(BUILD_HOST_EXECUTABLE) - -$(call dist-for-goals,droid,$(LOCAL_BUILT_MODULE)) - -ifeq ($(HOST_OS),windows) -$(LOCAL_INSTALLED_MODULE): $(HOST_OUT_EXECUTABLES)/AdbWinApi.dll -endif - -endif - -# adbd device daemon -# ========================================================= - -# build adbd in all non-simulator builds -BUILD_ADBD := false -ifneq ($(TARGET_SIMULATOR),true) - BUILD_ADBD := true -endif - -# build adbd for the Linux simulator build -# so we can use it to test the adb USB gadget driver on x86 -ifeq ($(HOST_OS),linux) - BUILD_ADBD := true -endif - - -ifeq ($(BUILD_ADBD),true) -include $(CLEAR_VARS) - -LOCAL_SRC_FILES := \ - adb.c \ - transport.c \ - transport_local.c \ - transport_usb.c \ - sockets.c \ - services.c \ - file_sync_service.c \ - jdwp_service.c \ - framebuffer_service.c \ - remount_service.c \ - usb_linux_client.c \ - log_service.c \ - utils.c \ - -LOCAL_CFLAGS := -O2 -g -DADB_HOST=0 -Wall -Wno-unused-parameter -LOCAL_CFLAGS += -D_XOPEN_SOURCE -D_GNU_SOURCE - -# TODO: This should probably be board specific, whether or not the kernel has -# the gadget driver; rather than relying on the architecture type. -ifeq ($(TARGET_ARCH),arm) -LOCAL_CFLAGS += -DANDROID_GADGET=1 -endif - -LOCAL_MODULE := adbd - -LOCAL_FORCE_STATIC_EXECUTABLE := true -LOCAL_MODULE_PATH := $(TARGET_ROOT_OUT_SBIN) -LOCAL_UNSTRIPPED_PATH := $(TARGET_ROOT_OUT_SBIN_UNSTRIPPED) - -ifeq ($(TARGET_SIMULATOR),true) - LOCAL_STATIC_LIBRARIES := libcutils - LOCAL_LDLIBS += -lpthread - include $(BUILD_HOST_EXECUTABLE) -else - LOCAL_STATIC_LIBRARIES := libcutils libc - include $(BUILD_EXECUTABLE) -endif - -endif diff --git a/adb/OVERVIEW.TXT b/adb/OVERVIEW.TXT deleted file mode 100644 index 6a5191ae..00000000 --- a/adb/OVERVIEW.TXT +++ /dev/null @@ -1,139 +0,0 @@ -Implementation notes regarding ADB. - -I. General Overview: - -The Android Debug Bridge (ADB) is used to: - -- keep track of all Android devices and emulators instances - connected to or running on a given host developer machine - -- implement various control commands (e.g. "adb shell", "adb pull", etc..) - for the benefit of clients (command-line users, or helper programs like - DDMS). These commands are what is called a 'service' in ADB. - -As a whole, everything works through the following components: - - 1. The ADB server - - This is a background process that runs on the host machine. Its purpose - if to sense the USB ports to know when devices are attached/removed, - as well as when emulator instances start/stop. - - It thus maintains a list of "connected devices" and assigns a 'state' - to each one of them: OFFLINE, BOOTLOADER, RECOVERY or ONLINE (more on - this below). - - The ADB server is really one giant multiplexing loop whose purpose is - to orchestrate the exchange of data (packets, really) between clients, - services and devices. - - - 2. The ADB daemon (adbd) - - The 'adbd' program runs as a background process within an Android device - or emulated system. Its purpose is to connect to the ADB server - (through USB for devices, through TCP for emulators) and provide a - few services for clients that run on the host. - - The ADB server considers that a device is ONLINE when it has succesfully - connected to the adbd program within it. Otherwise, the device is OFFLINE, - meaning that the ADB server detected a new device/emulator, but could not - connect to the adbd daemon. - - the BOOTLOADER and RECOVERY states correspond to alternate states of - devices when they are in the bootloader or recovery mode. - - 3. The ADB command-line client - - The 'adb' command-line program is used to run adb commands from a shell - or a script. It first tries to locate the ADB server on the host machine, - and will start one automatically if none is found. - - then, the client sends its service requests to the ADB server. It doesn't - need to know. - - Currently, a single 'adb' binary is used for both the server and client. - this makes distribution and starting the server easier. - - - 4. Services - - There are essentially two kinds of services that a client can talk to. - - Host Services: - these services run within the ADB Server and thus do not need to - communicate with a device at all. A typical example is "adb devices" - which is used to return the list of currently known devices and their - state. They are a few couple other services though. - - Local Services: - these services either run within the adbd daemon, or are started by - it on the device. The ADB server is used to multiplex streams - between the client and the service running in adbd. In this case - its role is to initiate the connection, then of being a pass-through - for the data. - - -II. Protocol details: - - 1. Client <-> Server protocol: - - This details the protocol used between ADB clients and the ADB - server itself. The ADB server listens on TCP:localhost:5037. - - A client sends a request using the following format: - - 1. A 4-byte hexadecimal string giving the length of the payload - 2. Followed by the payload itself. - - For example, to query the ADB server for its internal version number, - the client will do the following: - - 1. Connect to tcp:localhost:5037 - 2. Send the string "000Chost:version" to the corresponding socket - - The 'host:' prefix is used to indicate that the request is addressed - to the server itself (we will talk about other kinds of requests later). - The content length is encoded in ASCII for easier debugging. - - The server should answer a request with one of the following: - - 1. For success, the 4-byte "OKAY" string - - 2. For failure, the 4-byte "FAIL" string, followed by a - 4-byte hex length, followed by a string giving the reason - for failure. - - 3. As a special exception, for 'host:version', a 4-byte - hex string corresponding to the server's internal version number - - Note that the connection is still alive after an OKAY, which allows the - client to make other requests. But in certain cases, an OKAY will even - change the state of the connection. - - For example, the case of the 'host:transport:<serialnumber>' request, - where '<serialnumber>' is used to identify a given device/emulator; after - the "OKAY" answer, all further requests made by the client will go - directly to the corresponding adbd daemon. - - The file SERVICES.TXT lists all services currently implemented by ADB. - - - 2. Transports: - - An ADB transport models a connection between the ADB server and one device - or emulator. There are currently two kinds of transports: - - - USB transports, for physical devices through USB - - - Local transports, for emulators running on the host, connected to - the server through TCP - - In theory, it should be possible to write a local transport that proxies - a connection between an ADB server and a device/emulator connected to/ - running on another machine. This hasn't been done yet though. - - Each transport can carry one or more multiplexed streams between clients - and the device/emulator they point to. The ADB server must handle - unexpected transport disconnections (e.g. when a device is physically - unplugged) properly. diff --git a/adb/SERVICES.TXT b/adb/SERVICES.TXT deleted file mode 100644 index b0124a4d..00000000 --- a/adb/SERVICES.TXT +++ /dev/null @@ -1,236 +0,0 @@ -This file tries to document all requests a client can make -to the ADB server of an adbd daemon. See the OVERVIEW.TXT document -to understand what's going on here. - -HOST SERVICES: - -host:version - Ask the ADB server for its internal version number. - - As a special exception, the server will respond with a 4-byte - hex string corresponding to its internal version number, without - any OKAY or FAIL. - -host:kill - Ask the ADB server to quit immediately. This is used when the - ADB client detects that an obsolete server is running after an - upgrade. - -host:devices - Ask to return the list of available Android devices and their - state. After the OKAY, this is followed by a 4-byte hex len, - and a string that will be dumped as-is by the client, then - the connection is closed - -host:track-devices - This is a variant of host:devices which doesn't close the - connection. Instead, a new device list description is sent - each time a device is added/removed or the state of a given - device changes (hex4 + content). This allows tools like DDMS - to track the state of connected devices in real-time without - polling the server repeatedly. - -host:emulator:<port> - This is a special query that is sent to the ADB server when a - new emulator starts up. <port> is a decimal number corresponding - to the emulator's ADB control port, i.e. the TCP port that the - emulator will forward automatically to the adbd daemon running - in the emulator system. - - This mechanism allows the ADB server to know when new emulator - instances start. - -host:transport:<serial-number> - Ask to switch the connection to the device/emulator identified by - <serial-number>. After the OKAY response, every client request will - be sent directly to the adbd daemon running on the device. - (Used to implement the -s option) - -host:transport-usb - Ask to switch the connection to one device connected through USB - to the host machine. This will fail if there are more than one such - devices. (Used to implement the -d convenience option) - -host:transport-local - Ask to switch the connection to one emulator connected through TCP. - This will fail if there is more than one such emulator instance - running. (Used to implement the -e convenience option) - -host:transport-any - Another host:transport variant. Ask to switch the connection to - either the device or emulator connect to/running on the host. - Will fail if there is more than one such device/emulator available. - (Used when neither -s, -d or -e are provided) - -host-serial:<serial-number>:<request> - This is a special form of query, where the 'host-serial:<serial-number>:' - prefix can be used to indicate that the client is asking the ADB server - for information related to a specific device. <request> can be in one - of the format described below. - -host-usb:<request> - A variant of host-serial used to target the single USB device connected - to the host. This will fail if there is none or more than one. - -host-local:<request> - A variant of host-serial used to target the single emulator instance - running on the host. This will fail if therre is none or more than one. - -host:<request> - When asking for information related to a device, 'host:' can also be - interpreted as 'any single device or emulator connected to/running on - the host'. - -<host-prefix>:get-product - XXX - -<host-prefix>:get-serialno - Returns the serial number of the corresponding device/emulator. - Note that emulator serial numbers are of the form "emulator-5554" - -<host-prefix>:get-state - Returns the state of a given device as a string. - -<host-prefix>:forward:<local>;<remote> - Asks the ADB server to forward local connections from <local> - to the <remote> address on a given device. - - There, <host-prefix> can be one of the - host-serial/host-usb/host-local/host prefixes as described previously - and indicates which device/emulator to target. - - the format of <local> is one of: - - tcp:<port> -> TCP connection on localhost:<port> - local:<path> -> Unix local domain socket on <path> - - the format of <remote> is one of: - - tcp:<port> -> TCP localhost:<port> on device - local:<path> -> Unix local domain socket on device - jdwp:<pid> -> JDWP thread on VM process <pid> - - or even any one of the local services described below. - - - -LOCAL SERVICES: - -All the queries below assumed that you already switched the transport -to a real device, or that you have used a query prefix as described -above. - -shell:command arg1 arg2 ... - Run 'command arg1 arg2 ...' in a shell on the device, and return - its output and error streams. Note that arguments must be separated - by spaces. If an argument contains a space, it must be quoted with - double-quotes. Arguments cannot contain double quotes or things - will go very wrong. - - Note that this is the non-interactive version of "adb shell" - -shell: - Start an interactive shell session on the device. Redirect - stdin/stdout/stderr as appropriate. Note that the ADB server uses - this to implement "adb shell", but will also cook the input before - sending it to the device (see interactive_shell() in commandline.c) - -remount: - Ask adbd to remount the device's filesystem in read-write mode, - instead of read-only. This is usually necessary before performing - an "adb sync" or "adb push" request. - - This request may not succeed on certain builds which do not allow - that. - -dev:<path> - Opens a device file and connects the client directly to it for - read/write purposes. Useful for debugging, but may require special - priviledges and thus may not run on all devices. <path> is a full - path from the root of the filesystem. - -tcp:<port> - Tries to connect to tcp port <port> on localhost. - -tcp:<port>:<server-name> - Tries to connect to tcp port <port> on machine <server-name> from - the device. This can be useful to debug some networking/proxy - issues that can only be revealed on the device itself. - -local:<path> - Tries to connect to a Unix domain socket <path> on the device - -localreserved:<path> -localabstract:<path> -localfilesystem:<path> - Variants of local:<path> that are used to access other Android - socket namespaces. - -log:<name> - Opens one of the system logs (/dev/log/<name>) and allows the client - to read them directly. Used to implement 'adb logcat'. The stream - will be read-only for the client. - -framebuffer: - This service is used to send snapshots of the framebuffer to a client. - It requires sufficient priviledges but works as follow: - - After the OKAY, the service sends 16-byte binary structure - containing the following fields (little-endian format): - - depth: uint32_t: framebuffer depth - size: uint32_t: framebuffer size in bytes - width: uint32_t: framebuffer width in pixels - height: uint32_t: framebuffer height in pixels - - With the current implementation, depth is always 16, and - size is always width*height*2 - - Then, each time the client wants a snapshot, it should send - one byte through the channel, which will trigger the service - to send it 'size' bytes of framebuffer data. - - If the adbd daemon doesn't have sufficient priviledges to open - the framebuffer device, the connection is simply closed immediately. - -dns:<server-name> - This service is an exception because it only runs within the ADB server. - It is used to implement USB networking, i.e. to provide a network connection - to the device through the host machine (note: this is the exact opposite of - network thetering). - - It is used to perform a gethostbyname(<address>) on the host and return - the corresponding IP address as a 4-byte string. - -recover:<size> - This service is used to upload a recovery image to the device. <size> - must be a number corresponding to the size of the file. The service works - by: - - - creating a file named /tmp/update - - reading 'size' bytes from the client and writing them to /tmp/update - - when everything is read succesfully, create a file named /tmp/update.start - - This service can only work when the device is in recovery mode. Otherwise, - the /tmp directory doesn't exist and the connection will be closed immediately. - -jdwp:<pid> - Connects to the JDWP thread running in the VM of process <pid>. - -track-jdwp - This is used to send the list of JDWP pids periodically to the client. - The format of the returned data is the following: - - <hex4>: the length of all content as a 4-char hexadecimal string - <content>: a series of ASCII lines of the following format: - <pid> "\n" - - This service is used by DDMS to know which debuggable processes are running - on the device/emulator. - - Note that there is no single-shot service to retrieve the list only once. - -sync: - This starts the file synchronisation service, used to implement "adb push" - and "adb pull". Since this service is pretty complex, it will be detailed - in a companion document named SYNC.TXT diff --git a/adb/adb.c b/adb/adb.c deleted file mode 100644 index fa5269f5..00000000 --- a/adb/adb.c +++ /dev/null @@ -1,1083 +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 "sysdeps.h" -#include "adb.h" - -#if !ADB_HOST -#include <private/android_filesystem_config.h> -#endif - - -int HOST = 0; - -static const char *adb_device_banner = "device"; - -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 }, - { 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"); -#if !ADB_HOST - property_set("adb.connected","1"); -#endif -} - -void handle_offline(atransport *t) -{ - D("adb: offline\n"); - //Close the associated usb - run_transport_disconnects(t); -#if !ADB_HOST - property_set("adb.connected",""); -#endif -} - -#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); -#if ADB_HOST - /* XXX why sleep here? */ - // allow the device some time to respond to the connect message - adb_sleep_ms(1000); -#endif -} - -static char *connection_state_name(atransport *t) -{ - if (t == NULL) { - return "unknown"; - } - - switch(t->connection_state) { - case CS_BOOTLOADER: - return "bootloader"; - case CS_DEVICE: - return "device"; - case CS_OFFLINE: - return "offline"; - default: - return "unknown"; - } -} - -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; - } - - t->connection_state = CS_HOST; -} - -void handle_packet(apacket *p, atransport *t) -{ - asocket *s; - - D("handle_packet() %d\n", p->msg.command); - - 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); -} - -alistener listener_list = { - .next = &listener_list, - .prev = &listener_list, -}; - -static void ss_listener_event_func(int _fd, unsigned ev, void *_l) -{ - asocket *s; - - if(ev & FDE_READ) { - struct sockaddr addr; - socklen_t alen; - int fd; - - alen = sizeof(addr); - fd = adb_socket_accept(_fd, &addr, &alen); - if(fd < 0) return; - - adb_socket_setbufsize(fd, CHUNK_SIZE); - - s = create_local_socket(fd); - if(s) { - connect_to_smartsocket(s); - return; - } - - adb_close(fd); - } -} - -static void listener_event_func(int _fd, unsigned ev, void *_l) -{ - alistener *l = _l; - asocket *s; - - if(ev & FDE_READ) { - struct sockaddr addr; - socklen_t alen; - int fd; - - alen = sizeof(addr); - fd = adb_socket_accept(_fd, &addr, &alen); - if(fd < 0) return; - - s = create_local_socket(fd); - if(s) { - s->transport = l->transport; - connect_to_remote(s, l->connect_to); - return; - } - - adb_close(fd); - } -} - -static void free_listener(alistener* l) -{ - if (l->next) { - l->next->prev = l->prev; - l->prev->next = l->next; - l->next = l->prev = l; - } - - // closes the corresponding fd - fdevent_remove(&l->fde); - - if (l->local_name) - free((char*)l->local_name); - - if (l->connect_to) - free((char*)l->connect_to); - - if (l->transport) { - remove_transport_disconnect(l->transport, &l->disconnect); - } - free(l); -} - -static void listener_disconnect(void* _l, atransport* t) -{ - alistener* l = _l; - - free_listener(l); -} - -int local_name_to_fd(const char *name) -{ - int port; - - if(!strncmp("tcp:", name, 4)){ - int ret; - port = atoi(name + 4); - ret = socket_loopback_server(port, SOCK_STREAM); - return ret; - } -#ifndef HAVE_WIN32_IPC /* no Unix-domain sockets on Win32 */ - // It's non-sensical to support the "reserved" space on the adb host side - if(!strncmp(name, "local:", 6)) { - return socket_local_server(name + 6, - ANDROID_SOCKET_NAMESPACE_ABSTRACT, SOCK_STREAM); - } else if(!strncmp(name, "localabstract:", 14)) { - return socket_local_server(name + 14, - ANDROID_SOCKET_NAMESPACE_ABSTRACT, SOCK_STREAM); - } else if(!strncmp(name, "localfilesystem:", 16)) { - return socket_local_server(name + 16, - ANDROID_SOCKET_NAMESPACE_FILESYSTEM, SOCK_STREAM); - } - -#endif - printf("unknown local portname '%s'\n", name); - return -1; -} - -static int remove_listener(const char *local_name, const char *connect_to, atransport* transport) -{ - alistener *l; - - for (l = listener_list.next; l != &listener_list; l = l->next) { - if (!strcmp(local_name, l->local_name) && - !strcmp(connect_to, l->connect_to) && - l->transport && l->transport == transport) { - - listener_disconnect(l, transport); - return 0; - } - } - - return -1; -} - -static int install_listener(const char *local_name, const char *connect_to, atransport* transport) -{ - alistener *l; - - //printf("install_listener('%s','%s')\n", local_name, connect_to); - - for(l = listener_list.next; l != &listener_list; l = l->next){ - if(strcmp(local_name, l->local_name) == 0) { - char *cto; - - /* can't repurpose a smartsocket */ - if(l->connect_to[0] == '*') { - return -1; - } - - cto = strdup(connect_to); - if(cto == 0) { - return -1; - } - - //printf("rebinding '%s' to '%s'\n", local_name, connect_to); - free((void*) l->connect_to); - l->connect_to = cto; - if (l->transport != transport) { - remove_transport_disconnect(l->transport, &l->disconnect); - l->transport = transport; - add_transport_disconnect(l->transport, &l->disconnect); - } - return 0; - } - } - - if((l = calloc(1, sizeof(alistener))) == 0) goto nomem; - if((l->local_name = strdup(local_name)) == 0) goto nomem; - if((l->connect_to = strdup(connect_to)) == 0) goto nomem; - - - l->fd = local_name_to_fd(local_name); - if(l->fd < 0) { - free((void*) l->local_name); - free((void*) l->connect_to); - free(l); - printf("cannot bind '%s'\n", local_name); - return -2; - } - - close_on_exec(l->fd); - if(!strcmp(l->connect_to, "*smartsocket*")) { - fdevent_install(&l->fde, l->fd, ss_listener_event_func, l); - } else { - fdevent_install(&l->fde, l->fd, listener_event_func, l); - } - fdevent_set(&l->fde, FDE_READ); - - l->next = &listener_list; - l->prev = listener_list.prev; - l->next->prev = l; - l->prev->next = l; - l->transport = transport; - - if (transport) { - l->disconnect.opaque = l; - l->disconnect.func = listener_disconnect; - add_transport_disconnect(transport, &l->disconnect); - } - return 0; - -nomem: - fatal("cannot allocate listener"); - return 0; -} - -#ifdef HAVE_FORKEXEC -static void sigchld_handler(int n) -{ - int status; - while(waitpid(-1, &status, WNOHANG) > 0) ; -} -#endif - -#ifdef HAVE_WIN32_PROC -static BOOL WINAPI ctrlc_handler(DWORD type) -{ - exit(STATUS_CONTROL_C_EXIT); - return TRUE; -} -#endif - -static void adb_cleanup(void) -{ - usb_cleanup(); -} - -void start_logging(void) -{ -#ifdef HAVE_WIN32_PROC - char temp[ MAX_PATH ]; - FILE* fnul; - FILE* flog; - - GetTempPath( sizeof(temp) - 8, temp ); - strcat( temp, "adb.log" ); - - /* Win32 specific redirections */ - fnul = fopen( "NUL", "rt" ); - if (fnul != NULL) - stdin[0] = fnul[0]; - - flog = fopen( temp, "at" ); - if (flog == NULL) - flog = fnul; - - setvbuf( flog, NULL, _IONBF, 0 ); - - stdout[0] = flog[0]; - stderr[0] = flog[0]; - fprintf(stderr,"--- adb starting (pid %d) ---\n", getpid()); -#else - int fd; - - fd = unix_open("/dev/null", O_RDONLY); - dup2(fd, 0); - - fd = unix_open("/tmp/adb.log", O_WRONLY | O_CREAT | O_APPEND, 0640); - if(fd < 0) { - fd = unix_open("/dev/null", O_WRONLY); - } - dup2(fd, 1); - dup2(fd, 2); - fprintf(stderr,"--- adb starting (pid %d) ---\n", getpid()); -#endif -} - -#if !ADB_HOST -void start_device_log(void) -{ - int fd; - char path[100]; - - snprintf(path, sizeof path, "/data/adb_%ld.txt", (long)time(NULL)); - fd = unix_open(path, O_WRONLY | O_CREAT | O_APPEND, 0640); - if (fd < 0) - return; - - // redirect stdout and stderr to the log file - dup2(fd, 1); - dup2(fd, 2); - fprintf(stderr,"--- adb starting (pid %d) ---\n", getpid()); - - fd = unix_open("/dev/null", O_RDONLY); - dup2(fd, 0); - - // log everything - adb_trace_mask = ~0; - // except TRACE_RWX is a bit too verbose - adb_trace_mask &= ~TRACE_RWX; -} -#endif - -#if ADB_HOST -int launch_server() -{ -#ifdef HAVE_WIN32_PROC - /* we need to start the server in the background */ - /* we create a PIPE that will be used to wait for the server's "OK" */ - /* message since the pipe handles must be inheritable, we use a */ - /* security attribute */ - HANDLE pipe_read, pipe_write; - SECURITY_ATTRIBUTES sa; - STARTUPINFO startup; - PROCESS_INFORMATION pinfo; - char program_path[ MAX_PATH ]; - int ret; - - sa.nLength = sizeof(sa); - sa.lpSecurityDescriptor = NULL; - sa.bInheritHandle = TRUE; - - /* create pipe, and ensure its read handle isn't inheritable */ - ret = CreatePipe( &pipe_read, &pipe_write, &sa, 0 ); - if (!ret) { - fprintf(stderr, "CreatePipe() failure, error %ld\n", GetLastError() ); - return -1; - } - - SetHandleInformation( pipe_read, HANDLE_FLAG_INHERIT, 0 ); - - ZeroMemory( &startup, sizeof(startup) ); - startup.cb = sizeof(startup); - startup.hStdInput = GetStdHandle( STD_INPUT_HANDLE ); - startup.hStdOutput = pipe_write; - startup.hStdError = GetStdHandle( STD_ERROR_HANDLE ); - startup.dwFlags = STARTF_USESTDHANDLES; - - ZeroMemory( &pinfo, sizeof(pinfo) ); - - /* get path of current program */ - GetModuleFileName( NULL, program_path, sizeof(program_path) ); - - ret = CreateProcess( - program_path, /* program path */ - "adb fork-server server", - /* the fork-server argument will set the - debug = 2 in the child */ - NULL, /* process handle is not inheritable */ - NULL, /* thread handle is not inheritable */ - TRUE, /* yes, inherit some handles */ - DETACHED_PROCESS, /* the new process doesn't have a console */ - NULL, /* use parent's environment block */ - NULL, /* use parent's starting directory */ - &startup, /* startup info, i.e. std handles */ - &pinfo ); - - CloseHandle( pipe_write ); - - if (!ret) { - fprintf(stderr, "CreateProcess failure, error %ld\n", GetLastError() ); - CloseHandle( pipe_read ); - return -1; - } - - CloseHandle( pinfo.hProcess ); - CloseHandle( pinfo.hThread ); - - /* wait for the "OK\n" message */ - { - char temp[3]; - DWORD count; - - ret = ReadFile( pipe_read, temp, 3, &count, NULL ); - CloseHandle( pipe_read ); - if ( !ret ) { - fprintf(stderr, "could not read ok from ADB Server, error = %ld\n", GetLastError() ); - return -1; - } - if (count != 3 || temp[0] != 'O' || temp[1] != 'K' || temp[2] != '\n') { - fprintf(stderr, "ADB server didn't ACK\n" ); - return -1; - } - } -#elif defined(HAVE_FORKEXEC) - char path[PATH_MAX]; - int fd[2]; - - // set up a pipe so the child can tell us when it is ready. - // fd[0] will be parent's end, and fd[1] will get mapped to stderr in the child. - if (pipe(fd)) { - fprintf(stderr, "pipe failed in launch_server, errno: %d\n", errno); - return -1; - } - get_my_path(path); - pid_t pid = fork(); - if(pid < 0) return -1; - - if (pid == 0) { - // child side of the fork - - // redirect stderr to the pipe - // we use stderr instead of stdout due to stdout's buffering behavior. - adb_close(fd[0]); - dup2(fd[1], STDERR_FILENO); - adb_close(fd[1]); - - // child process - int result = execl(path, "adb", "fork-server", "server", NULL); - // this should not return - fprintf(stderr, "OOPS! execl returned %d, errno: %d\n", result, errno); - } else { - // parent side of the fork - - char temp[3]; - - temp[0] = 'A'; temp[1] = 'B'; temp[2] = 'C'; - // wait for the "OK\n" message - adb_close(fd[1]); - int ret = adb_read(fd[0], temp, 3); - adb_close(fd[0]); - if (ret < 0) { - fprintf(stderr, "could not read ok from ADB Server, errno = %d\n", errno); - return -1; - } - if (ret != 3 || temp[0] != 'O' || temp[1] != 'K' || temp[2] != '\n') { - fprintf(stderr, "ADB server didn't ACK\n" ); - return -1; - } - - setsid(); - } -#else -#error "cannot implement background server start on this platform" -#endif - return 0; -} -#endif - -int adb_main(int is_daemon) -{ -#if !ADB_HOST - int secure = 0; - char value[PROPERTY_VALUE_MAX]; - - // prevent the OOM killer from killing us - char text[64]; - snprintf(text, sizeof text, "/proc/%d/oom_adj", (int)getpid()); - int fd = adb_open(text, O_WRONLY); - if (fd >= 0) { - // -17 should make us immune to OOM - snprintf(text, sizeof text, "%d", -17); - adb_write(fd, text, strlen(text)); - adb_close(fd); - } else { - D("adb: unable to open %s\n", text); - } -#endif - - atexit(adb_cleanup); -#ifdef HAVE_WIN32_PROC - SetConsoleCtrlHandler( ctrlc_handler, TRUE ); -#elif defined(HAVE_FORKEXEC) - signal(SIGCHLD, sigchld_handler); - signal(SIGPIPE, SIG_IGN); -#endif - - init_transport_registration(); - - -#if ADB_HOST - HOST = 1; - usb_init(); - local_init(); - - if(install_listener("tcp:5037", "*smartsocket*", NULL)) { - exit(1); - } -#else - /* run adbd in secure mode if ro.secure is set and - ** we are not in the emulator - */ - property_get("ro.kernel.qemu", value, ""); - if (strcmp(value, "1") != 0) { - property_get("ro.secure", value, ""); - if (strcmp(value, "1") == 0) - secure = 1; - } - - /* don't listen on port 5037 if we are running in secure mode */ - /* don't run as root if we are running in secure mode */ - if (secure) { - /* add extra groups: - ** AID_ADB to access the USB driver - ** AID_LOG to read system logs (adb logcat) - ** AID_INPUT to diagnose input issues (getevent) - ** AID_INET to diagnose network issues (netcfg, ping) - ** AID_GRAPHICS to access the frame buffer - */ - gid_t groups[] = { AID_ADB, AID_LOG, AID_INPUT, AID_INET, AID_GRAPHICS }; - setgroups(sizeof(groups)/sizeof(groups[0]), groups); - - /* then switch user and group to "shell" */ - setgid(AID_SHELL); - setuid(AID_SHELL); - - D("Local port 5037 disabled\n"); - } else { - if(install_listener("tcp:5037", "*smartsocket*", NULL)) { - exit(1); - } - } - - /* for the device, start the usb transport if the - ** android usb device exists, otherwise start the - ** network transport. - */ - if(access("/dev/android_adb", F_OK) == 0 || - access("/dev/android", F_OK) == 0) { - usb_init(); - } else { - local_init(); - } - init_jdwp(); -#endif - - if (is_daemon) - { - // inform our parent that we are up and running. -#ifdef HAVE_WIN32_PROC - DWORD count; - WriteFile( GetStdHandle( STD_OUTPUT_HANDLE ), "OK\n", 3, &count, NULL ); -#elif defined(HAVE_FORKEXEC) - fprintf(stderr, "OK\n"); -#endif - start_logging(); - } - - fdevent_loop(); - - usb_cleanup(); - - return 0; -} - -int handle_host_request(char *service, transport_type ttype, char* serial, int reply_fd, asocket *s) -{ - atransport *transport = NULL; - char buf[4096]; - - if(!strcmp(service, "kill")) { - fprintf(stderr,"adb server killed by remote request\n"); - fflush(stdout); - adb_write(reply_fd, "OKAY", 4); - usb_cleanup(); - exit(0); - } - -#if ADB_HOST - // "transport:" is used for switching transport with a specified serial number - // "transport-usb:" is used for switching transport to the only USB transport - // "transport-local:" is used for switching transport to the only local transport - // "transport-any:" is used for switching transport to the only transport - if (!strncmp(service, "transport", strlen("transport"))) { - char* error_string = "unknown failure"; - transport_type type = kTransportAny; - - if (!strncmp(service, "transport-usb", strlen("transport-usb"))) { - type = kTransportUsb; - } else if (!strncmp(service, "transport-local", strlen("transport-local"))) { - type = kTransportLocal; - } else if (!strncmp(service, "transport-any", strlen("transport-any"))) { - type = kTransportAny; - } else if (!strncmp(service, "transport:", strlen("transport:"))) { - service += strlen("transport:"); - serial = strdup(service); - } - - transport = acquire_one_transport(CS_ANY, type, serial, &error_string); - - if (transport) { - s->transport = transport; - adb_write(reply_fd, "OKAY", 4); - } else { - sendfailmsg(reply_fd, error_string); - } - return 1; - } - - // return a list of all connected devices - if (!strcmp(service, "devices")) { - char buffer[4096]; - memset(buf, 0, sizeof(buf)); - memset(buffer, 0, sizeof(buffer)); - D("Getting device list \n"); - list_transports(buffer, sizeof(buffer)); - snprintf(buf, sizeof(buf), "OKAY%04x%s",(unsigned)strlen(buffer),buffer); - D("Wrote device list \n"); - writex(reply_fd, buf, strlen(buf)); - return 0; - } - - // returns our value for ADB_SERVER_VERSION - if (!strcmp(service, "version")) { - char version[12]; - snprintf(version, sizeof version, "%04x", ADB_SERVER_VERSION); - snprintf(buf, sizeof buf, "OKAY%04x%s", (unsigned)strlen(version), version); - writex(reply_fd, buf, strlen(buf)); - return 0; - } - - if(!strncmp(service,"get-serialno",strlen("get-serialno"))) { - char *out = "unknown"; - transport = acquire_one_transport(CS_ANY, ttype, serial, NULL); - if (transport && transport->serial) { - out = transport->serial; - } - snprintf(buf, sizeof buf, "OKAY%04x%s",(unsigned)strlen(out),out); - writex(reply_fd, buf, strlen(buf)); - return 0; - } - // indicates a new emulator instance has started - if (!strncmp(service,"emulator:",9)) { - int port = atoi(service+9); - local_connect(port); - /* we don't even need to send a reply */ - return 0; - } -#endif // ADB_HOST - - if(!strncmp(service,"forward:",8) || !strncmp(service,"killforward:",12)) { - char *local, *remote, *err; - int r; - atransport *transport; - - int createForward = strncmp(service,"kill",4); - - local = service + (createForward ? 8 : 12); - remote = strchr(local,';'); - if(remote == 0) { - sendfailmsg(reply_fd, "malformed forward spec"); - return 0; - } - - *remote++ = 0; - if((local[0] == 0) || (remote[0] == 0) || (remote[0] == '*')){ - sendfailmsg(reply_fd, "malformed forward spec"); - return 0; - } - - transport = acquire_one_transport(CS_ANY, ttype, serial, &err); - if (!transport) { - sendfailmsg(reply_fd, err); - return 0; - } - - if (createForward) { - r = install_listener(local, remote, transport); - } else { - r = remove_listener(local, remote, transport); - } - if(r == 0) { - /* 1st OKAY is connect, 2nd OKAY is status */ - writex(reply_fd, "OKAYOKAY", 8); - return 0; - } - - if (createForward) { - sendfailmsg(reply_fd, (r == -1) ? "cannot rebind smartsocket" : "cannot bind socket"); - } else { - sendfailmsg(reply_fd, "cannot remove listener"); - } - return 0; - } - - if(!strncmp(service,"get-state",strlen("get-state"))) { - transport = acquire_one_transport(CS_ANY, ttype, serial, NULL); - char *state = connection_state_name(transport); - snprintf(buf, sizeof buf, "OKAY%04x%s",(unsigned)strlen(state),state); - writex(reply_fd, buf, strlen(buf)); - return 0; - } - return -1; -} - -#if !ADB_HOST -int recovery_mode = 0; -#endif - -int main(int argc, char **argv) -{ - adb_trace_init(); -#if ADB_HOST - adb_sysdeps_init(); - return adb_commandline(argc - 1, argv + 1); -#else - if((argc > 1) && (!strcmp(argv[1],"recovery"))) { - adb_device_banner = "recovery"; - recovery_mode = 1; - } -#if ADB_DEVICE_LOG - start_device_log(); -#endif - return adb_main(0); -#endif -} - diff --git a/adb/adb.h b/adb/adb.h deleted file mode 100644 index a17c8ddc..00000000 --- a/adb/adb.h +++ /dev/null @@ -1,407 +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> - -#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 20 // 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 alistener alistener; -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, listeners, 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; - - /* a list of adisconnect callbacks called when the transport is kicked */ - int kicked; - adisconnect disconnects; -}; - - -/* A listener is an entity which binds to a local port -** and, upon receiving a connection on that port, creates -** an asocket to connect the new local connection to a -** specific remote service. -** -** TODO: some listeners read from the new connection to -** determine what exact service to connect to on the far -** side. -*/ -struct alistener -{ - alistener *next; - alistener *prev; - - fdevent fde; - int fd; - - const char *local_name; - const char *connect_to; - atransport *transport; - adisconnect disconnect; -}; - - -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[PATH_MAX]); -int launch_server(); -int adb_main(int is_daemon); - - -/* 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 */ -int init_socket_transport(atransport *t, int s, int port); -void init_usb_transport(atransport *t, usb_handle *usb); - -/* for MacOS X cleanup */ -void close_usb_devices(); - -/* cause new transports to be init'd and added to the list */ -void register_socket_transport(int s, const char *serial, int port); -void register_usb_transport(usb_handle *h, const char *serial); - -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 -int init_jdwp(void); -asocket* create_jdwp_service_socket(); -asocket* create_jdwp_tracker_service_socket(); -int create_jdwp_connection_fd(int jdwp_pid); -#endif - -#if !ADB_HOST -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); - -/* 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); - -/* 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, - TRACE_SOCKETS, - TRACE_PACKETS, - TRACE_TRANSPORT, - TRACE_RWX, - TRACE_USB, - TRACE_SYNC, - TRACE_SYSDEPS, - TRACE_JDWP, -} AdbTrace; - -#if ADB_TRACE - - int adb_trace_mask; - - 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) \ - fprintf(stderr, __VA_ARGS__ ); \ - } while (0) -#else -# define D(...) ((void)0) -# define ADB_TRACING 0 -#endif - - -/* set this to log to /data/adb/adb_<time>.txt on the device. - * has no effect if the /data/adb/ directory does not exist. - */ -#define ADB_DEVICE_LOG 0 - -#if !TRACE_PACKETS -#define print_packet(tag,p) do {} while (0) -#endif - -#define ADB_PORT 5037 -#define ADB_LOCAL_TRANSPORT_PORT 5555 - -// Google's USB Vendor ID -#define VENDOR_ID_GOOGLE 0x18d1 -// HTC's USB Vendor ID -#define VENDOR_ID_HTC 0x0bb4 - -// products for VENDOR_ID_GOOGLE -#define PRODUCT_ID_SOONER 0xd00d // Sooner bootloader -#define PRODUCT_ID_SOONER_COMP 0xdeed // Sooner composite device - -// products for VENDOR_ID_HTC -#define PRODUCT_ID_DREAM 0x0c01 // Dream bootloader -#define PRODUCT_ID_DREAM_COMP 0x0c02 // Dream composite device - -void local_init(); -int local_connect(int 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 */ -int is_adb_interface(int vid, int pid, int usb_class, int usb_subclass, int usb_protocol); - -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_ERROR 5 - -extern int HOST; - -#define CHUNK_SIZE (64*1024) - -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/adb/adb_client.c b/adb/adb_client.c deleted file mode 100644 index 58687448..00000000 --- a/adb/adb_client.c +++ /dev/null @@ -1,318 +0,0 @@ -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <errno.h> -#include <limits.h> -#include <stdarg.h> -#include <zipfile/zipfile.h> -#include <sys/types.h> -#include <sys/stat.h> - -#include "sysdeps.h" - -#define TRACE_TAG TRACE_ADB -#include "adb_client.h" - -static transport_type __adb_transport = kTransportAny; -static const char* __adb_serial = NULL; - -void adb_set_transport(transport_type type, const char* serial) -{ - __adb_transport = type; - __adb_serial = serial; -} - -int adb_get_emulator_console_port(void) -{ - const char* serial = __adb_serial; - int port; - - if (serial == NULL) { - /* if no specific device was specified, we need to look at */ - /* the list of connected devices, and extract an emulator */ - /* name from it. two emulators is an error */ - char* tmp = adb_query("host:devices"); - char* p = tmp; - if(!tmp) { - printf("no emulator connected\n"); - return -1; - } - while (*p) { - char* q = strchr(p, '\n'); - if (q != NULL) - *q++ = 0; - else - q = p + strlen(p); - - if (!memcmp(p, LOCAL_CLIENT_PREFIX, sizeof(LOCAL_CLIENT_PREFIX)-1)) { - if (serial != NULL) { /* more than one emulator listed */ - free(tmp); - return -2; - } - serial = p; - } - - p = q; - } - free(tmp); - - if (serial == NULL) - return -1; /* no emulator found */ - } - else { - if (memcmp(serial, LOCAL_CLIENT_PREFIX, sizeof(LOCAL_CLIENT_PREFIX)-1) != 0) - return -1; /* not an emulator */ - } - - serial += sizeof(LOCAL_CLIENT_PREFIX)-1; - port = strtol(serial, NULL, 10); - return port; -} - -static char __adb_error[256] = { 0 }; - -const char *adb_error(void) -{ - return __adb_error; -} - -static int switch_socket_transport(int fd) -{ - char service[64]; - char tmp[5]; - int len; - - if (__adb_serial) - snprintf(service, sizeof service, "host:transport:%s", __adb_serial); - else { - char* transport_type = "???"; - - switch (__adb_transport) { - case kTransportUsb: - transport_type = "transport-usb"; - break; - case kTransportLocal: - transport_type = "transport-local"; - break; - case kTransportAny: - transport_type = "transport-any"; - break; - case kTransportHost: - // no switch necessary - return 0; - break; - } - - snprintf(service, sizeof service, "host:%s", transport_type); - } - len = strlen(service); - snprintf(tmp, sizeof tmp, "%04x", len); - - if(writex(fd, tmp, 4) || writex(fd, service, len)) { - strcpy(__adb_error, "write failure during connection"); - adb_close(fd); - return -1; - } - D("Switch transport in progress\n"); - - if(adb_status(fd)) { - adb_close(fd); - D("Switch transport failed\n"); - return -1; - } - D("Switch transport success\n"); - return 0; -} - -int adb_status(int fd) -{ - unsigned char buf[5]; - unsigned len; - - if(readx(fd, buf, 4)) { - strcpy(__adb_error, "protocol fault (no status)"); - return -1; - } - - if(!memcmp(buf, "OKAY", 4)) { - return 0; - } - - if(memcmp(buf, "FAIL", 4)) { - sprintf(__adb_error, - "protocol fault (status %02x %02x %02x %02x?!)", - buf[0], buf[1], buf[2], buf[3]); - return -1; - } - - if(readx(fd, buf, 4)) { - strcpy(__adb_error, "protocol fault (status len)"); - return -1; - } - buf[4] = 0; - len = strtoul((char*)buf, 0, 16); - if(len > 255) len = 255; - if(readx(fd, __adb_error, len)) { - strcpy(__adb_error, "protocol fault (status read)"); - return -1; - } - __adb_error[len] = 0; - return -1; -} - -int _adb_connect(const char *service) -{ - char tmp[5]; - int len; - int fd; - - D("_adb_connect: %s\n", service); - len = strlen(service); - if((len < 1) || (len > 1024)) { - strcpy(__adb_error, "service name too long"); - return -1; - } - snprintf(tmp, sizeof tmp, "%04x", len); - - fd = socket_loopback_client(ADB_PORT, SOCK_STREAM); - if(fd < 0) { - strcpy(__adb_error, "cannot connect to daemon"); - return -2; - } - - if (memcmp(service,"host",4) != 0 && switch_socket_transport(fd)) { - return -1; - } - - if(writex(fd, tmp, 4) || writex(fd, service, len)) { - strcpy(__adb_error, "write failure during connection"); - adb_close(fd); - return -1; - } - - if(adb_status(fd)) { - adb_close(fd); - return -1; - } - - return fd; -} - -int adb_connect(const char *service) -{ - // first query the adb server's version - int fd = _adb_connect("host:version"); - - if(fd == -2) { - fprintf(stdout,"* daemon not running. starting it now *\n"); - start_server: - if(launch_server(0)) { - fprintf(stderr,"* failed to start daemon *\n"); - return -1; - } else { - fprintf(stdout,"* daemon started successfully *\n"); - } - /* give the server some time to start properly and detect devices */ - adb_sleep_ms(2000); - // fall through to _adb_connect - } else { - // if server was running, check its version to make sure it is not out of date - char buf[100]; - int n; - int version = ADB_SERVER_VERSION - 1; - - // if we have a file descriptor, then parse version result - if(fd >= 0) { - if(readx(fd, buf, 4)) goto error; - - buf[4] = 0; - n = strtoul(buf, 0, 16); - if(n > (int)sizeof(buf)) goto error; - if(readx(fd, buf, n)) goto error; - adb_close(fd); - - if (sscanf(buf, "%04x", &version) != 1) goto error; - } else { - // if fd is -1, then check for "unknown host service", - // which would indicate a version of adb that does not support the version command - if (strcmp(__adb_error, "unknown host service") != 0) - return fd; - } - - if(version != ADB_SERVER_VERSION) { - printf("adb server is out of date. killing...\n"); - fd = _adb_connect("host:kill"); - adb_close(fd); - - /* XXX can we better detect its death? */ - adb_sleep_ms(2000); - goto start_server; - } - } - - // if the command is start-server, we are done. - if (!strcmp(service, "host:start-server")) - return 0; - - fd = _adb_connect(service); - if(fd == -2) { - fprintf(stderr,"** daemon still not running"); - } - - return fd; -error: - adb_close(fd); - return -1; -} - - -int adb_command(const char *service) -{ - int fd = adb_connect(service); - if(fd < 0) { - return -1; - } - - if(adb_status(fd)) { - adb_close(fd); - return -1; - } - - return 0; -} - -char *adb_query(const char *service) -{ - char buf[5]; - unsigned n; - char *tmp; - - D("adb_query: %s\n", service); - int fd = adb_connect(service); - if(fd < 0) { - fprintf(stderr,"error: %s\n", __adb_error); - return 0; - } - - if(readx(fd, buf, 4)) goto oops; - - buf[4] = 0; - n = strtoul(buf, 0, 16); - if(n > 1024) goto oops; - - tmp = malloc(n + 1); - if(tmp == 0) goto oops; - - if(readx(fd, tmp, n) == 0) { - tmp[n] = 0; - adb_close(fd); - return tmp; - } - free(tmp); - -oops: - adb_close(fd); - return 0; -} - - diff --git a/adb/adb_client.h b/adb/adb_client.h deleted file mode 100644 index 80615790..00000000 --- a/adb/adb_client.h +++ /dev/null @@ -1,49 +0,0 @@ -#ifndef _ADB_CLIENT_H_ -#define _ADB_CLIENT_H_ - -#include "adb.h" - -/* connect to adb, connect to the named service, and return -** a valid fd for interacting with that service upon success -** or a negative number on failure -*/ -int adb_connect(const char *service); -int _adb_connect(const char *service); - -/* connect to adb, connect to the named service, return 0 if -** the connection succeeded AND the service returned OKAY -*/ -int adb_command(const char *service); - -/* connect to adb, connect to the named service, return -** a malloc'd string of its response upon success or NULL -** on failure. -*/ -char *adb_query(const char *service); - -/* Set the preferred transport to connect to. -*/ -void adb_set_transport(transport_type type, const char* serial); - -/* Return the console port of the currently connected emulator (if any) - * of -1 if there is no emulator, and -2 if there is more than one. - * assumes adb_set_transport() was alled previously... - */ -int adb_get_emulator_console_port(void); - -/* send commands to the current emulator instance. will fail if there - * is zero, or more than one emulator connected (or if you use -s <serial> - * with a <serial> that does not designate an emulator) - */ -int adb_send_emulator_command(int argc, char** argv); - -/* return verbose error string from last operation */ -const char *adb_error(void); - -/* read a standard adb status response (OKAY|FAIL) and -** return 0 in the event of OKAY, -1 in the event of FAIL -** or protocol error -*/ -int adb_status(int fd); - -#endif diff --git a/adb/commandline.c b/adb/commandline.c deleted file mode 100644 index be596ce5..00000000 --- a/adb/commandline.c +++ /dev/null @@ -1,1249 +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 <errno.h> -#include <unistd.h> -#include <limits.h> -#include <stdarg.h> -#include <sys/types.h> -#include <sys/stat.h> -#include <ctype.h> -#include <assert.h> - -#include "sysdeps.h" - -#ifdef HAVE_TERMIO_H -#include <termios.h> -#endif - -#define TRACE_TAG TRACE_ADB -#include "adb.h" -#include "adb_client.h" -#include "file_sync_service.h" - -#ifdef SH_HISTORY -#include "shlist.h" -#include "history.h" -#endif - -enum { - IGNORE_DATA, - WIPE_DATA, - FLASH_DATA -}; - -static int do_cmd(transport_type ttype, char* serial, char *cmd, ...); - -void get_my_path(char s[PATH_MAX]); -int find_sync_dirs(const char *srcarg, - char **android_srcdir_out, char **data_srcdir_out); -int install_app(transport_type transport, char* serial, int argc, char** argv); -int uninstall_app(transport_type transport, char* serial, int argc, char** argv); - -static const char *gProductOutPath = NULL; - -static char *product_file(const char *extra) -{ - int n; - char *x; - - if (gProductOutPath == NULL) { - fprintf(stderr, "adb: Product directory not specified; " - "use -p or define ANDROID_PRODUCT_OUT\n"); - exit(1); - } - - n = strlen(gProductOutPath) + strlen(extra) + 2; - x = malloc(n); - if (x == 0) { - fprintf(stderr, "adb: Out of memory (product_file())\n"); - exit(1); - } - - snprintf(x, (size_t)n, "%s" OS_PATH_SEPARATOR_STR "%s", gProductOutPath, extra); - return x; -} - -void version(FILE * out) { - fprintf(out, "Android Debug Bridge version %d.%d.%d\n", - ADB_VERSION_MAJOR, ADB_VERSION_MINOR, ADB_SERVER_VERSION); -} - -void help() -{ - version(stderr); - - fprintf(stderr, - "\n" - " -d - directs command to the only connected USB device\n" - " returns an error if more than one USB device is present.\n" - " -e - directs command to the only running emulator.\n" - " returns an error if more than one emulator is running.\n" - " -s <serial number> - directs command to the USB device or emulator with\n" - " the given serial number\n" - " -p <product name or path> - simple product name like 'sooner', or\n" - " a relative/absolute path to a product\n" - " out directory like 'out/target/product/sooner'.\n" - " If -p is not specified, the ANDROID_PRODUCT_OUT\n" - " environment variable is used, which must\n" - " be an absolute path.\n" - " devices - list all connected devices\n" - "\n" - "device commands:\n" - " adb push <local> <remote> - copy file/dir to device\n" - " adb pull <remote> <local> - copy file/dir from device\n" - " adb sync [ <directory> ] - copy host->device only if changed\n" - " (see 'adb help all')\n" - " adb shell - run remote shell interactively\n" - " adb shell <command> - run remote shell command\n" - " adb emu <command> - run emulator console command\n" - " adb logcat [ <filter-spec> ] - View device log\n" - " adb forward <local> <remote> - forward socket connections\n" - " forward specs are one of: \n" - " tcp:<port>\n" - " localabstract:<unix domain socket name>\n" - " localreserved:<unix domain socket name>\n" - " localfilesystem:<unix domain socket name>\n" - " dev:<character device name>\n" - " jdwp:<process pid> (remote only)\n" - " adb jdwp - list PIDs of processes hosting a JDWP transport\n" - " adb install [-l] [-r] <file> - push this package file to the device and install it\n" - " ('-l' means forward-lock the app)\n" - " ('-r' means reinstall the app, keeping its data)\n" - " adb uninstall [-k] <package> - remove this app package from the device\n" - " ('-k' means keep the data and cache directories)\n" - " adb bugreport - return all information from the device\n" - " that should be included in a bug report.\n" - "\n" - " adb help - show this help message\n" - " adb version - show version num\n" - "\n" - "DATAOPTS:\n" - " (no option) - don't touch the data partition\n" - " -w - wipe the data partition\n" - " -d - flash the data partition\n" - "\n" - "scripting:\n" - " adb wait-for-device - block until device is online\n" - " adb start-server - ensure that there is a server running\n" - " adb kill-server - kill the server if it is running\n" - " adb get-state - prints: offline | bootloader | device\n" - " adb get-serialno - prints: <serial-number>\n" - " adb status-window - continuously print device status for a specified device\n" - " adb remount - remounts the /system partition on the device read-write\n" - "\n" - "networking:\n" - " adb ppp <tty> [parameters] - Run PPP over USB.\n" - " Note: you should not automatically start a PDP connection.\n" - " <tty> refers to the tty for PPP stream. Eg. dev:/dev/omap_csmi_tty1\n" - " [parameters] - Eg. defaultroute debug dump local notty usepeerdns\n" - "\n" - "adb sync notes: adb sync [ <directory> ]\n" - " <localdir> can be interpreted in several ways:\n" - "\n" - " - If <directory> is not specified, both /system and /data partitions will be updated.\n" - "\n" - " - If it is \"system\" or \"data\", only the corresponding partition\n" - " is updated.\n" - ); -} - -int usage() -{ - help(); - return 1; -} - -#ifdef HAVE_TERMIO_H -static struct termios tio_save; - -static void stdin_raw_init(int fd) -{ - struct termios tio; - - if(tcgetattr(fd, &tio)) return; - if(tcgetattr(fd, &tio_save)) return; - - tio.c_lflag = 0; /* disable CANON, ECHO*, etc */ - - /* no timeout but request at least one character per read */ - tio.c_cc[VTIME] = 0; - tio.c_cc[VMIN] = 1; - - tcsetattr(fd, TCSANOW, &tio); - tcflush(fd, TCIFLUSH); -} - -static void stdin_raw_restore(int fd) -{ - tcsetattr(fd, TCSANOW, &tio_save); - tcflush(fd, TCIFLUSH); -} -#endif - -static void read_and_dump(int fd) -{ - char buf[4096]; - int len; - - while(fd >= 0) { - len = adb_read(fd, buf, 4096); - if(len == 0) { - break; - } - - if(len < 0) { - if(errno == EINTR) continue; - break; - } - /* we want to output to stdout, so no adb_write here !! */ - unix_write(1, buf, len); - } -} - -#ifdef SH_HISTORY -int shItemCmp( void *val, void *idata ) -{ - return( (strcmp( val, idata ) == 0) ); -} -#endif - -static void *stdin_read_thread(void *x) -{ - int fd, fdi; - unsigned char buf[1024]; -#ifdef SH_HISTORY - unsigned char realbuf[1024], *buf_ptr; - SHLIST history; - SHLIST *item = &history; - int cmdlen = 0, ins_flag = 0; -#endif - int r, n; - int state = 0; - - int *fds = (int*) x; - fd = fds[0]; - fdi = fds[1]; - free(fds); - -#ifdef SH_HISTORY - shListInitList( &history ); -#endif - for(;;) { - /* fdi is really the client's stdin, so use read, not adb_read here */ - r = unix_read(fdi, buf, 1024); - if(r == 0) break; - if(r < 0) { - if(errno == EINTR) continue; - break; - } -#ifdef SH_HISTORY - if( (r == 3) && /* Arrow processing */ - (memcmp( (void *)buf, SH_ARROW_ANY, 2 ) == 0) ) { - switch( buf[2] ) { - case SH_ARROW_UP: - item = shListGetNextItem( &history, item ); - break; - case SH_ARROW_DOWN: - item = shListGetPrevItem( &history, item ); - break; - default: - item = NULL; - break; - } - memset( buf, SH_DEL_CHAR, cmdlen ); - if( item != NULL ) { - n = snprintf( (char *)(&buf[cmdlen]), sizeof buf - cmdlen, "%s", (char *)(item->data) ); - memcpy( realbuf, item->data, n ); - } - else { /* Clean buffer */ - item = &history; - n = 0; - } - r = n + cmdlen; - cmdlen = n; - ins_flag = 0; - if( r == 0 ) - continue; - } - else { -#endif - for(n = 0; n < r; n++){ - switch(buf[n]) { - case '\n': -#ifdef SH_HISTORY - if( ins_flag && (SH_BLANK_CHAR <= realbuf[0]) ) { - buf_ptr = malloc(cmdlen + 1); - if( buf_ptr != NULL ) { - memcpy( buf_ptr, realbuf, cmdlen ); - buf_ptr[cmdlen] = '\0'; - if( (item = shListFindItem( &history, (void *)buf_ptr, shItemCmp )) == NULL ) { - shListInsFirstItem( &history, (void *)buf_ptr ); - item = &history; - } - } - } - cmdlen = 0; - ins_flag = 0; -#endif - state = 1; - break; - case '\r': - state = 1; - break; - case '~': - if(state == 1) state++; - break; - case '.': - if(state == 2) { - fprintf(stderr,"\n* disconnect *\n"); - #ifdef HAVE_TERMIO_H - stdin_raw_restore(fdi); - #endif - exit(0); - } - default: -#ifdef SH_HISTORY - if( buf[n] == SH_DEL_CHAR ) { - if( cmdlen > 0 ) - cmdlen--; - } - else { - realbuf[cmdlen] = buf[n]; - cmdlen++; - } - ins_flag = 1; -#endif - state = 0; - } - } -#ifdef SH_HISTORY - } -#endif - r = adb_write(fd, buf, r); - if(r <= 0) { - break; - } - } -#ifdef SH_HISTORY - shListDelAllItems( &history, (shListFree)free ); -#endif - return 0; -} - -int interactive_shell(void) -{ - adb_thread_t thr; - int fdi, fd; - int *fds; - - fd = adb_connect("shell:"); - if(fd < 0) { - fprintf(stderr,"error: %s\n", adb_error()); - return 1; - } - fdi = 0; //dup(0); - - fds = malloc(sizeof(int) * 2); - fds[0] = fd; - fds[1] = fdi; - -#ifdef HAVE_TERMIO_H - stdin_raw_init(fdi); -#endif - adb_thread_create(&thr, stdin_read_thread, fds); - read_and_dump(fd); -#ifdef HAVE_TERMIO_H - stdin_raw_restore(fdi); -#endif - return 0; -} - - -static void format_host_command(char* buffer, size_t buflen, const char* command, transport_type ttype, const char* serial) -{ - if (serial) { - snprintf(buffer, buflen, "host-serial:%s:%s", serial, command); - } else { - const char* prefix = "host"; - if (ttype == kTransportUsb) - prefix = "host-usb"; - else if (ttype == kTransportLocal) - prefix = "host-local"; - - snprintf(buffer, buflen, "%s:%s", prefix, command); - } -} - -static void status_window(transport_type ttype, const char* serial) -{ - char command[4096]; - char *state = 0; - char *laststate = 0; - - /* silence stderr */ -#ifdef _WIN32 - /* XXX: TODO */ -#else - int fd; - fd = unix_open("/dev/null", O_WRONLY); - dup2(fd, 2); - adb_close(fd); -#endif - - format_host_command(command, sizeof command, "get-state", ttype, serial); - - for(;;) { - adb_sleep_ms(250); - - if(state) { - free(state); - state = 0; - } - - state = adb_query(command); - - if(state) { - if(laststate && !strcmp(state,laststate)){ - continue; - } else { - if(laststate) free(laststate); - laststate = strdup(state); - } - } - - printf("%c[2J%c[2H", 27, 27); - printf("Android Debug Bridge\n"); - printf("State: %s\n", state ? state : "offline"); - fflush(stdout); - } -} - -/** duplicate string and quote all \ " ( ) chars + space character. */ -static char * -dupAndQuote(const char *s) -{ - const char *ts; - size_t alloc_len; - char *ret; - char *dest; - - ts = s; - - alloc_len = 0; - - for( ;*ts != '\0'; ts++) { - alloc_len++; - if (*ts == ' ' || *ts == '"' || *ts == '\\' || *ts == '(' || *ts == ')') { - alloc_len++; - } - } - - ret = (char *)malloc(alloc_len + 1); - - ts = s; - dest = ret; - - for ( ;*ts != '\0'; ts++) { - if (*ts == ' ' || *ts == '"' || *ts == '\\' || *ts == '(' || *ts == ')') { - *dest++ = '\\'; - } - - *dest++ = *ts; - } - - *dest++ = '\0'; - - return ret; -} - -/** - * Run ppp in "notty" mode against a resource listed as the first parameter - * eg: - * - * ppp dev:/dev/omap_csmi_tty0 <ppp options> - * - */ -int ppp(int argc, char **argv) -{ -#ifdef HAVE_WIN32_PROC - fprintf(stderr, "error: adb %s not implemented on Win32\n", argv[0]); - return -1; -#else - char *adb_service_name; - pid_t pid; - int fd; - - if (argc < 2) { - fprintf(stderr, "usage: adb %s <adb service name> [ppp opts]\n", - argv[0]); - - return 1; - } - - adb_service_name = argv[1]; - - fd = adb_connect(adb_service_name); - - if(fd < 0) { - fprintf(stderr,"Error: Could not open adb service: %s. Error: %s\n", - adb_service_name, adb_error()); - return 1; - } - - pid = fork(); - - if (pid < 0) { - perror("from fork()"); - return 1; - } else if (pid == 0) { - int err; - int i; - const char **ppp_args; - - // copy args - ppp_args = (const char **) alloca(sizeof(char *) * argc + 1); - ppp_args[0] = "pppd"; - for (i = 2 ; i < argc ; i++) { - //argv[2] and beyond become ppp_args[1] and beyond - ppp_args[i - 1] = argv[i]; - } - ppp_args[i-1] = NULL; - - // child side - - dup2(fd, STDIN_FILENO); - dup2(fd, STDOUT_FILENO); - adb_close(STDERR_FILENO); - adb_close(fd); - - err = execvp("pppd", (char * const *)ppp_args); - - if (err < 0) { - perror("execing pppd"); - } - exit(-1); - } else { - // parent side - - adb_close(fd); - return 0; - } -#endif /* !HAVE_WIN32_PROC */ -} - -static int send_shellcommand(transport_type transport, char* serial, char* buf) -{ - int fd, ret; - - for(;;) { - fd = adb_connect(buf); - if(fd >= 0) - break; - fprintf(stderr,"- waiting for device -\n"); - adb_sleep_ms(1000); - do_cmd(transport, serial, "wait-for-device", 0); - } - - read_and_dump(fd); - ret = adb_close(fd); - if (ret) - perror("close"); - - return ret; -} - -static int logcat(transport_type transport, char* serial, int argc, char **argv) -{ - char buf[4096]; - - char *log_tags; - char *quoted_log_tags; - - log_tags = getenv("ANDROID_LOG_TAGS"); - quoted_log_tags = dupAndQuote(log_tags == NULL ? "" : log_tags); - - snprintf(buf, sizeof(buf), - "shell:export ANDROID_LOG_TAGS=\"\%s\" ; exec logcat", - quoted_log_tags); - - free(quoted_log_tags); - - argc -= 1; - argv += 1; - while(argc-- > 0) { - char *quoted; - - quoted = dupAndQuote (*argv++); - - strncat(buf, " ", sizeof(buf)-1); - strncat(buf, quoted, sizeof(buf)-1); - free(quoted); - } - - send_shellcommand(transport, serial, buf); - return 0; -} - -#define SENTINEL_FILE "config" OS_PATH_SEPARATOR_STR "envsetup.make" -static int top_works(const char *top) -{ - if (top != NULL && adb_is_absolute_host_path(top)) { - char path_buf[PATH_MAX]; - snprintf(path_buf, sizeof(path_buf), - "%s" OS_PATH_SEPARATOR_STR SENTINEL_FILE, top); - return access(path_buf, F_OK) == 0; - } - return 0; -} - -static char *find_top_from(const char *indir, char path_buf[PATH_MAX]) -{ - strcpy(path_buf, indir); - while (1) { - if (top_works(path_buf)) { - return path_buf; - } - char *s = adb_dirstop(path_buf); - if (s != NULL) { - *s = '\0'; - } else { - path_buf[0] = '\0'; - return NULL; - } - } -} - -static char *find_top(char path_buf[PATH_MAX]) -{ - char *top = getenv("ANDROID_BUILD_TOP"); - if (top != NULL && top[0] != '\0') { - if (!top_works(top)) { - fprintf(stderr, "adb: bad ANDROID_BUILD_TOP value \"%s\"\n", top); - return NULL; - } - } else { - top = getenv("TOP"); - if (top != NULL && top[0] != '\0') { - if (!top_works(top)) { - fprintf(stderr, "adb: bad TOP value \"%s\"\n", top); - return NULL; - } - } else { - top = NULL; - } - } - - if (top != NULL) { - /* The environment pointed to a top directory that works. - */ - strcpy(path_buf, top); - return path_buf; - } - - /* The environment didn't help. Walk up the tree from the CWD - * to see if we can find the top. - */ - char dir[PATH_MAX]; - top = find_top_from(getcwd(dir, sizeof(dir)), path_buf); - if (top == NULL) { - /* If the CWD isn't under a good-looking top, see if the - * executable is. - */ - get_my_path(dir); - top = find_top_from(dir, path_buf); - } - return top; -} - -/* <hint> may be: - * - A simple product name - * e.g., "sooner" -TODO: debug? sooner-debug, sooner:debug? - * - A relative path from the CWD to the ANDROID_PRODUCT_OUT dir - * e.g., "out/target/product/sooner" - * - An absolute path to the PRODUCT_OUT dir - * e.g., "/src/device/out/target/product/sooner" - * - * Given <hint>, try to construct an absolute path to the - * ANDROID_PRODUCT_OUT dir. - */ -static const char *find_product_out_path(const char *hint) -{ - static char path_buf[PATH_MAX]; - - if (hint == NULL || hint[0] == '\0') { - return NULL; - } - - /* If it's already absolute, don't bother doing any work. - */ - if (adb_is_absolute_host_path(hint)) { - strcpy(path_buf, hint); - return path_buf; - } - - /* If there are any slashes in it, assume it's a relative path; - * make it absolute. - */ - if (adb_dirstart(hint) != NULL) { - if (getcwd(path_buf, sizeof(path_buf)) == NULL) { - fprintf(stderr, "adb: Couldn't get CWD: %s\n", strerror(errno)); - return NULL; - } - if (strlen(path_buf) + 1 + strlen(hint) >= sizeof(path_buf)) { - fprintf(stderr, "adb: Couldn't assemble path\n"); - return NULL; - } - strcat(path_buf, OS_PATH_SEPARATOR_STR); - strcat(path_buf, hint); - return path_buf; - } - - /* It's a string without any slashes. Try to do something with it. - * - * Try to find the root of the build tree, and build a PRODUCT_OUT - * path from there. - */ - char top_buf[PATH_MAX]; - const char *top = find_top(top_buf); - if (top == NULL) { - fprintf(stderr, "adb: Couldn't find top of build tree\n"); - return NULL; - } -//TODO: if we have a way to indicate debug, look in out/debug/target/... - snprintf(path_buf, sizeof(path_buf), - "%s" OS_PATH_SEPARATOR_STR - "out" OS_PATH_SEPARATOR_STR - "target" OS_PATH_SEPARATOR_STR - "product" OS_PATH_SEPARATOR_STR - "%s", top_buf, hint); - if (access(path_buf, F_OK) < 0) { - fprintf(stderr, "adb: Couldn't find a product dir " - "based on \"-p %s\"; \"%s\" doesn't exist\n", hint, path_buf); - return NULL; - } - return path_buf; -} - -int adb_commandline(int argc, char **argv) -{ - char buf[4096]; - int no_daemon = 0; - int is_daemon = 0; - int persist = 0; - int r; - int quote; - transport_type ttype = kTransportAny; - char* serial = NULL; - - /* If defined, this should be an absolute path to - * the directory containing all of the various system images - * for a particular product. If not defined, and the adb - * command requires this information, then the user must - * specify the path using "-p". - */ - gProductOutPath = getenv("ANDROID_PRODUCT_OUT"); - if (gProductOutPath == NULL || gProductOutPath[0] == '\0') { - gProductOutPath = NULL; - } - // TODO: also try TARGET_PRODUCT/TARGET_DEVICE as a hint - - /* modifiers and flags */ - while(argc > 0) { - if(!strcmp(argv[0],"nodaemon")) { - no_daemon = 1; - } else if (!strcmp(argv[0], "fork-server")) { - /* this is a special flag used only when the ADB client launches the ADB Server */ - is_daemon = 1; - } else if(!strcmp(argv[0],"persist")) { - persist = 1; - } else if(!strncmp(argv[0], "-p", 2)) { - const char *product = NULL; - if (argv[0][2] == '\0') { - if (argc < 2) return usage(); - product = argv[1]; - argc--; - argv++; - } else { - product = argv[1] + 2; - } - gProductOutPath = find_product_out_path(product); - if (gProductOutPath == NULL) { - fprintf(stderr, "adb: could not resolve \"-p %s\"\n", - product); - return usage(); - } - } else if (argv[0][0]=='-' && argv[0][1]=='s') { - if (isdigit(argv[0][2])) { - serial = argv[0] + 2; - } else { - if(argc < 2) return usage(); - serial = argv[1]; - argc--; - argv++; - } - } else if (!strcmp(argv[0],"-d")) { - ttype = kTransportUsb; - } else if (!strcmp(argv[0],"-e")) { - ttype = kTransportLocal; - } else { - /* out of recognized modifiers and flags */ - break; - } - argc--; - argv++; - } - - adb_set_transport(ttype, serial); - - if ((argc > 0) && (!strcmp(argv[0],"server"))) { - if (no_daemon || is_daemon) { - r = adb_main(is_daemon); - } else { - r = launch_server(); - } - if(r) { - fprintf(stderr,"* could not start server *\n"); - } - return r; - } - -top: - if(argc == 0) { - return usage(); - } - - /* adb_connect() commands */ - - if(!strcmp(argv[0], "devices")) { - char *tmp; - snprintf(buf, sizeof buf, "host:%s", argv[0]); - tmp = adb_query(buf); - if(tmp) { - printf("List of devices attached \n"); - printf("%s\n", tmp); - return 0; - } else { - return 1; - } - } - - if (!strcmp(argv[0], "emu")) { - return adb_send_emulator_command(argc, argv); - } - - if(!strcmp(argv[0], "shell")) { - int r; - int fd; - - if(argc < 2) { - return interactive_shell(); - } - - snprintf(buf, sizeof buf, "shell:%s", argv[1]); - argc -= 2; - argv += 2; - while(argc-- > 0) { - strcat(buf, " "); - - /* quote empty strings and strings with spaces */ - quote = (**argv == 0 || strchr(*argv, ' ')); - if (quote) - strcat(buf, "\""); - strcat(buf, *argv++); - if (quote) - strcat(buf, "\""); - } - - for(;;) { - fd = adb_connect(buf); - if(fd >= 0) { - read_and_dump(fd); - adb_close(fd); - r = 0; - } else { - fprintf(stderr,"error: %s\n", adb_error()); - r = -1; - } - - if(persist) { - fprintf(stderr,"\n- waiting for device -\n"); - adb_sleep_ms(1000); - do_cmd(ttype, serial, "wait-for-device", 0); - } else { - return r; - } - } - } - - if(!strcmp(argv[0], "kill-server")) { - int fd; - fd = _adb_connect("host:kill"); - if(fd == -1) { - fprintf(stderr,"* server not running *\n"); - return 1; - } - return 0; - } - - if(!strcmp(argv[0], "remount")) { - int fd = adb_connect("remount:"); - if(fd >= 0) { - read_and_dump(fd); - adb_close(fd); - return 0; - } - fprintf(stderr,"error: %s\n", adb_error()); - return 1; - } - - if(!strcmp(argv[0], "bugreport")) { - if (argc != 1) { - return 1; - } - do_cmd(ttype, serial, "shell", "dumpstate", "-", 0); - return 0; - } - - /* adb_command() wrapper commands */ - - if(!strncmp(argv[0], "wait-for-", strlen("wait-for-"))) { - char* service = argv[0]; - if (!strncmp(service, "wait-for-device", strlen("wait-for-device"))) { - if (ttype == kTransportUsb) { - service = "wait-for-usb"; - } else if (ttype == kTransportLocal) { - service = "wait-for-local"; - } else { - service = "wait-for-any"; - } - } - - format_host_command(buf, sizeof buf, service, ttype, serial); - - if (adb_command(buf)) { - D("failure: %s *\n",adb_error()); - fprintf(stderr,"error: %s\n", adb_error()); - return 1; - } - - /* Allow a command to be run after wait-for-device, - * e.g. 'adb wait-for-device shell'. - */ - if(argc > 1) { - argc--; - argv++; - goto top; - } - return 0; - } - - if(!strcmp(argv[0], "forward")) { - if(argc != 3) return usage(); - if (serial) { - snprintf(buf, sizeof buf, "host-serial:%s:forward:%s;%s",serial,argv[1],argv[2]); - } else { - snprintf(buf, sizeof buf, "host:forward:%s;%s",argv[1],argv[2]); - } - if(adb_command(buf)) { - fprintf(stderr,"error: %s\n", adb_error()); - return 1; - } - return 0; - } - - /* do_sync_*() commands */ - - if(!strcmp(argv[0], "ls")) { - if(argc != 2) return usage(); - return do_sync_ls(argv[1]); - } - - if(!strcmp(argv[0], "push")) { - if(argc != 3) return usage(); - return do_sync_push(argv[1], argv[2], 0 /* no verify APK */); - } - - if(!strcmp(argv[0], "pull")) { - if(argc != 3) return usage(); - return do_sync_pull(argv[1], argv[2]); - } - - if(!strcmp(argv[0], "install")) { - if (argc < 2) return usage(); - return install_app(ttype, serial, argc, argv); - } - - if(!strcmp(argv[0], "uninstall")) { - if (argc < 2) return usage(); - return uninstall_app(ttype, serial, argc, argv); - } - - if(!strcmp(argv[0], "sync")) { - char *srcarg, *android_srcpath, *data_srcpath; - int ret; - if(argc < 2) { - /* No local path was specified. */ - srcarg = NULL; - } else if(argc == 2) { - /* A local path or "android"/"data" arg was specified. */ - srcarg = argv[1]; - } else { - return usage(); - } - ret = find_sync_dirs(srcarg, &android_srcpath, &data_srcpath); - if(ret != 0) return usage(); - - if(android_srcpath != NULL) - ret = do_sync_sync(android_srcpath, "/system"); - if(ret == 0 && data_srcpath != NULL) - ret = do_sync_sync(data_srcpath, "/data"); - - free(android_srcpath); - free(data_srcpath); - return ret; - } - - /* passthrough commands */ - - if(!strcmp(argv[0],"get-state") || - !strcmp(argv[0],"get-serialno")) - { - char *tmp; - - format_host_command(buf, sizeof buf, argv[0], ttype, serial); - tmp = adb_query(buf); - if(tmp) { - printf("%s\n", tmp); - return 0; - } else { - return 1; - } - } - - /* other commands */ - - if(!strcmp(argv[0],"status-window")) { - status_window(ttype, serial); - return 0; - } - - if(!strcmp(argv[0],"logcat") || !strcmp(argv[0],"lolcat")) { - return logcat(ttype, serial, argc, argv); - } - - if(!strcmp(argv[0],"ppp")) { - return ppp(argc, argv); - } - - if (!strcmp(argv[0], "start-server")) { - return adb_connect("host:start-server"); - } - - if (!strcmp(argv[0], "jdwp")) { - int fd = adb_connect("jdwp"); - if (fd >= 0) { - read_and_dump(fd); - adb_close(fd); - return 0; - } else { - fprintf(stderr, "error: %s\n", adb_error()); - return -1; - } - } - - /* "adb /?" is a common idiom under Windows */ - if(!strcmp(argv[0], "help") || !strcmp(argv[0], "/?")) { - help(); - return 0; - } - - if(!strcmp(argv[0], "version")) { - version(stdout); - return 0; - } - - usage(); - return 1; -} - -static int do_cmd(transport_type ttype, char* serial, char *cmd, ...) -{ - char *argv[16]; - int argc; - va_list ap; - - va_start(ap, cmd); - argc = 0; - - if (serial) { - argv[argc++] = "-s"; - argv[argc++] = serial; - } else if (ttype == kTransportUsb) { - argv[argc++] = "-d"; - } else if (ttype == kTransportLocal) { - argv[argc++] = "-e"; - } - - argv[argc++] = cmd; - while((argv[argc] = va_arg(ap, char*)) != 0) argc++; - va_end(ap); - -#if 0 - int n; - fprintf(stderr,"argc = %d\n",argc); - for(n = 0; n < argc; n++) { - fprintf(stderr,"argv[%d] = \"%s\"\n", n, argv[n]); - } -#endif - - return adb_commandline(argc, argv); -} - -int find_sync_dirs(const char *srcarg, - char **android_srcdir_out, char **data_srcdir_out) -{ - char *android_srcdir, *data_srcdir; - - if(srcarg == NULL) { - android_srcdir = product_file("system"); - data_srcdir = product_file("data"); - } else { - /* srcarg may be "data", "system" or NULL. - * if srcarg is NULL, then both data and system are synced - */ - if(strcmp(srcarg, "system") == 0) { - android_srcdir = product_file("system"); - data_srcdir = NULL; - } else if(strcmp(srcarg, "data") == 0) { - android_srcdir = NULL; - data_srcdir = product_file("data"); - } else { - /* It's not "system" or "data". - */ - return 1; - } - } - - if(android_srcdir_out != NULL) - *android_srcdir_out = android_srcdir; - else - free(android_srcdir); - - if(data_srcdir_out != NULL) - *data_srcdir_out = data_srcdir; - else - free(data_srcdir); - - return 0; -} - -static int pm_command(transport_type transport, char* serial, - int argc, char** argv) -{ - char buf[4096]; - - snprintf(buf, sizeof(buf), "shell:pm"); - - while(argc-- > 0) { - char *quoted; - - quoted = dupAndQuote(*argv++); - - strncat(buf, " ", sizeof(buf)-1); - strncat(buf, quoted, sizeof(buf)-1); - free(quoted); - } - - send_shellcommand(transport, serial, buf); - return 0; -} - -int uninstall_app(transport_type transport, char* serial, int argc, char** argv) -{ - /* if the user choose the -k option, we refuse to do it until devices are - out with the option to uninstall the remaining data somehow (adb/ui) */ - if (argc == 3 && strcmp(argv[1], "-k") == 0) - { - printf( - "The -k option uninstalls the application while retaining the data/cache.\n" - "At the moment, there is no way to remove the remaining data.\n" - "You will have to reinstall the application with the same signature, and fully uninstall it.\n" - "If you truly wish to continue, execute 'adb shell pm uninstall -k %s'\n", argv[2]); - return -1; - } - - /* 'adb uninstall' takes the same arguments as 'pm uninstall' on device */ - return pm_command(transport, serial, argc, argv); -} - -static int delete_file(transport_type transport, char* serial, char* filename) -{ - char buf[4096]; - char* quoted; - - snprintf(buf, sizeof(buf), "shell:rm "); - quoted = dupAndQuote(filename); - strncat(buf, quoted, sizeof(buf)-1); - free(quoted); - - send_shellcommand(transport, serial, buf); - return 0; -} - -int install_app(transport_type transport, char* serial, int argc, char** argv) -{ - struct stat st; - int err; - const char *const WHERE = "/data/local/tmp/%s"; - char to[PATH_MAX]; - char* filename = argv[argc - 1]; - const char* p; - - p = adb_dirstop(filename); - if (p) { - p++; - snprintf(to, sizeof to, WHERE, p); - } else { - snprintf(to, sizeof to, WHERE, filename); - } - if (p[0] == '\0') { - } - - err = stat(filename, &st); - if (err != 0) { - fprintf(stderr, "can't find '%s' to install\n", filename); - return 1; - } - if (!S_ISREG(st.st_mode)) { - fprintf(stderr, "can't install '%s' because it's not a file\n", - filename); - return 1; - } - - if (!(err = do_sync_push(filename, to, 1 /* verify APK */))) { - /* file in place; tell the Package Manager to install it */ - argv[argc - 1] = to; /* destination name, not source location */ - pm_command(transport, serial, argc, argv); - delete_file(transport, serial, to); - } - - return err; -} diff --git a/adb/console.c b/adb/console.c deleted file mode 100644 index b813d337..00000000 --- a/adb/console.c +++ /dev/null @@ -1,45 +0,0 @@ -#include "sysdeps.h" -#include "adb.h" -#include "adb_client.h" -#include <stdio.h> - -static int connect_to_console(void) -{ - int fd, port; - - port = adb_get_emulator_console_port(); - if (port < 0) { - if (port == -2) - fprintf(stderr, "error: more than one emulator detected. use -s option\n"); - else - fprintf(stderr, "error: no emulator detected\n"); - return -1; - } - fd = socket_loopback_client( port, SOCK_STREAM ); - if (fd < 0) { - fprintf(stderr, "error: could not connect to TCP port %d\n", port); - return -1; - } - return fd; -} - - -int adb_send_emulator_command(int argc, char** argv) -{ - int fd, nn; - - fd = connect_to_console(); - if (fd < 0) - return 1; - -#define QUIT "quit\n" - - for (nn = 1; nn < argc; nn++) { - adb_write( fd, argv[nn], strlen(argv[nn]) ); - adb_write( fd, (nn == argc-1) ? "\n" : " ", 1 ); - } - adb_write( fd, QUIT, sizeof(QUIT)-1 ); - adb_close(fd); - - return 0; -} diff --git a/adb/file_sync_client.c b/adb/file_sync_client.c deleted file mode 100644 index 4e6d3859..00000000 --- a/adb/file_sync_client.c +++ /dev/null @@ -1,1022 +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 <errno.h> -#include <sys/stat.h> -#include <sys/time.h> -#include <time.h> -#include <dirent.h> -#include <limits.h> -#include <sys/types.h> -#include <zipfile/zipfile.h> - -#include "sysdeps.h" -#include "adb.h" -#include "adb_client.h" -#include "file_sync_service.h" - - -static unsigned total_bytes; -static long long start_time; - -static long long NOW() -{ - struct timeval tv; - gettimeofday(&tv, 0); - return ((long long) tv.tv_usec) + - 1000000LL * ((long long) tv.tv_sec); -} - -static void BEGIN() -{ - total_bytes = 0; - start_time = NOW(); -} - -static void END() -{ - long long t = NOW() - start_time; - if(total_bytes == 0) return; - - if (t == 0) /* prevent division by 0 :-) */ - t = 1000000; - - fprintf(stderr,"%lld KB/s (%d bytes in %lld.%03llds)\n", - ((((long long) total_bytes) * 1000000LL) / t) / 1024LL, - total_bytes, (t / 1000000LL), (t % 1000000LL) / 1000LL); -} - -void sync_quit(int fd) -{ - syncmsg msg; - - msg.req.id = ID_QUIT; - msg.req.namelen = 0; - - writex(fd, &msg.req, sizeof(msg.req)); -} - -typedef void (*sync_ls_cb)(unsigned mode, unsigned size, unsigned time, const char *name, void *cookie); - -int sync_ls(int fd, const char *path, sync_ls_cb func, void *cookie) -{ - syncmsg msg; - char buf[257]; - int len; - - len = strlen(path); - if(len > 1024) goto fail; - - msg.req.id = ID_LIST; - msg.req.namelen = htoll(len); - - if(writex(fd, &msg.req, sizeof(msg.req)) || - writex(fd, path, len)) { - goto fail; - } - - for(;;) { - if(readx(fd, &msg.dent, sizeof(msg.dent))) break; - if(msg.dent.id == ID_DONE) return 0; - if(msg.dent.id != ID_DENT) break; - - len = ltohl(msg.dent.namelen); - if(len > 256) break; - - if(readx(fd, buf, len)) break; - buf[len] = 0; - - func(ltohl(msg.dent.mode), - ltohl(msg.dent.size), - ltohl(msg.dent.time), - buf, cookie); - } - -fail: - adb_close(fd); - return -1; -} - -typedef struct syncsendbuf syncsendbuf; - -struct syncsendbuf { - unsigned id; - unsigned size; - char data[SYNC_DATA_MAX]; -}; - -static syncsendbuf send_buffer; - -int sync_readtime(int fd, const char *path, unsigned *timestamp) -{ - syncmsg msg; - int len = strlen(path); - - msg.req.id = ID_STAT; - msg.req.namelen = htoll(len); - - if(writex(fd, &msg.req, sizeof(msg.req)) || - writex(fd, path, len)) { - return -1; - } - - if(readx(fd, &msg.stat, sizeof(msg.stat))) { - return -1; - } - - if(msg.stat.id != ID_STAT) { - return -1; - } - - *timestamp = ltohl(msg.stat.time); - return 0; -} - -static int sync_start_readtime(int fd, const char *path) -{ - syncmsg msg; - int len = strlen(path); - - msg.req.id = ID_STAT; - msg.req.namelen = htoll(len); - - if(writex(fd, &msg.req, sizeof(msg.req)) || - writex(fd, path, len)) { - return -1; - } - - return 0; -} - -static int sync_finish_readtime(int fd, unsigned int *timestamp, - unsigned int *mode, unsigned int *size) -{ - syncmsg msg; - - if(readx(fd, &msg.stat, sizeof(msg.stat))) - return -1; - - if(msg.stat.id != ID_STAT) - return -1; - - *timestamp = ltohl(msg.stat.time); - *mode = ltohl(msg.stat.mode); - *size = ltohl(msg.stat.size); - - return 0; -} - -int sync_readmode(int fd, const char *path, unsigned *mode) -{ - syncmsg msg; - int len = strlen(path); - - msg.req.id = ID_STAT; - msg.req.namelen = htoll(len); - - if(writex(fd, &msg.req, sizeof(msg.req)) || - writex(fd, path, len)) { - return -1; - } - - if(readx(fd, &msg.stat, sizeof(msg.stat))) { - return -1; - } - - if(msg.stat.id != ID_STAT) { - return -1; - } - - *mode = ltohl(msg.stat.mode); - return 0; -} - -static int write_data_file(int fd, const char *path, syncsendbuf *sbuf) -{ - int lfd, err = 0; - - lfd = adb_open(path, O_RDONLY); - if(lfd < 0) { - fprintf(stderr,"cannot open '%s': %s\n", path, strerror(errno)); - return -1; - } - - sbuf->id = ID_DATA; - for(;;) { - int ret; - - ret = adb_read(lfd, sbuf->data, SYNC_DATA_MAX); - if(!ret) - break; - - if(ret < 0) { - if(errno == EINTR) - continue; - fprintf(stderr,"cannot read '%s': %s\n", path, strerror(errno)); - break; - } - - sbuf->size = htoll(ret); - if(writex(fd, sbuf, sizeof(unsigned) * 2 + ret)){ - err = -1; - break; - } - total_bytes += ret; - } - - adb_close(lfd); - return err; -} - -static int write_data_buffer(int fd, char* file_buffer, int size, syncsendbuf *sbuf) -{ - int err = 0; - int total = 0; - - sbuf->id = ID_DATA; - while (total < size) { - int count = size - total; - if (count > SYNC_DATA_MAX) { - count = SYNC_DATA_MAX; - } - - memcpy(sbuf->data, &file_buffer[total], count); - sbuf->size = htoll(count); - if(writex(fd, sbuf, sizeof(unsigned) * 2 + count)){ - err = -1; - break; - } - total += count; - total_bytes += count; - } - - return err; -} - -#ifdef HAVE_SYMLINKS -static int write_data_link(int fd, const char *path, syncsendbuf *sbuf) -{ - int len, ret; - - len = readlink(path, sbuf->data, SYNC_DATA_MAX-1); - if(len < 0) { - fprintf(stderr, "error reading link '%s': %s\n", path, strerror(errno)); - return -1; - } - sbuf->data[len] = '\0'; - - sbuf->size = htoll(len + 1); - sbuf->id = ID_DATA; - - ret = writex(fd, sbuf, sizeof(unsigned) * 2 + len + 1); - if(ret) - return -1; - - total_bytes += len + 1; - - return 0; -} -#endif - -static int sync_send(int fd, const char *lpath, const char *rpath, - unsigned mtime, mode_t mode, int verifyApk) -{ - syncmsg msg; - int len, r; - syncsendbuf *sbuf = &send_buffer; - char* file_buffer = NULL; - int size = 0; - char tmp[64]; - - len = strlen(rpath); - if(len > 1024) goto fail; - - snprintf(tmp, sizeof(tmp), ",%d", mode); - r = strlen(tmp); - - if (verifyApk) { - int lfd; - zipfile_t zip; - zipentry_t entry; - int amt; - - // if we are transferring an APK file, then sanity check to make sure - // we have a real zip file that contains an AndroidManifest.xml - // this requires that we read the entire file into memory. - lfd = adb_open(lpath, O_RDONLY); - if(lfd < 0) { - fprintf(stderr,"cannot open '%s': %s\n", lpath, strerror(errno)); - return -1; - } - - size = adb_lseek(lfd, 0, SEEK_END); - if (size == -1 || -1 == adb_lseek(lfd, 0, SEEK_SET)) { - fprintf(stderr, "error seeking in file '%s'\n", lpath); - adb_close(lfd); - return 1; - } - - file_buffer = (char *)malloc(size); - if (file_buffer == NULL) { - fprintf(stderr, "could not allocate buffer for '%s'\n", - lpath); - adb_close(lfd); - return 1; - } - amt = adb_read(lfd, file_buffer, size); - if (amt != size) { - fprintf(stderr, "error reading from file: '%s'\n", lpath); - adb_close(lfd); - free(file_buffer); - return 1; - } - - adb_close(lfd); - - zip = init_zipfile(file_buffer, size); - if (zip == NULL) { - fprintf(stderr, "file '%s' is not a valid zip file\n", - lpath); - free(file_buffer); - return 1; - } - - entry = lookup_zipentry(zip, "AndroidManifest.xml"); - release_zipfile(zip); - if (entry == NULL) { - fprintf(stderr, "file '%s' does not contain AndroidManifest.xml\n", - lpath); - free(file_buffer); - return 1; - } - } - - msg.req.id = ID_SEND; - msg.req.namelen = htoll(len + r); - - if(writex(fd, &msg.req, sizeof(msg.req)) || - writex(fd, rpath, len) || writex(fd, tmp, r)) { - free(file_buffer); - goto fail; - } - - if (file_buffer) { - write_data_buffer(fd, file_buffer, size, sbuf); - free(file_buffer); - } else if (S_ISREG(mode)) - write_data_file(fd, lpath, sbuf); -#ifdef HAVE_SYMLINKS - else if (S_ISLNK(mode)) - write_data_link(fd, lpath, sbuf); -#endif - else - goto fail; - - msg.data.id = ID_DONE; - msg.data.size = htoll(mtime); - if(writex(fd, &msg.data, sizeof(msg.data))) - goto fail; - - if(readx(fd, &msg.status, sizeof(msg.status))) - return -1; - - if(msg.status.id != ID_OKAY) { - if(msg.status.id == ID_FAIL) { - len = ltohl(msg.status.msglen); - if(len > 256) len = 256; - if(readx(fd, sbuf->data, len)) { - return -1; - } - sbuf->data[len] = 0; - } else - strcpy(sbuf->data, "unknown reason"); - - fprintf(stderr,"failed to copy '%s' to '%s': %s\n", lpath, rpath, sbuf->data); - return -1; - } - - return 0; - -fail: - fprintf(stderr,"protocol failure\n"); - adb_close(fd); - return -1; -} - -static int mkdirs(char *name) -{ - int ret; - char *x = name + 1; - - for(;;) { - x = adb_dirstart(x); - if(x == 0) return 0; - *x = 0; - ret = adb_mkdir(name, 0775); - *x = OS_PATH_SEPARATOR; - if((ret < 0) && (errno != EEXIST)) { - return ret; - } - x++; - } - return 0; -} - -int sync_recv(int fd, const char *rpath, const char *lpath) -{ - syncmsg msg; - int len; - int lfd = -1; - char *buffer = send_buffer.data; - unsigned id; - - len = strlen(rpath); - if(len > 1024) return -1; - - msg.req.id = ID_RECV; - msg.req.namelen = htoll(len); - if(writex(fd, &msg.req, sizeof(msg.req)) || - writex(fd, rpath, len)) { - return -1; - } - - if(readx(fd, &msg.data, sizeof(msg.data))) { - return -1; - } - id = msg.data.id; - - if((id == ID_DATA) || (id == ID_DONE)) { - adb_unlink(lpath); - mkdirs((char *)lpath); - lfd = adb_creat(lpath, 0644); - if(lfd < 0) { - fprintf(stderr,"cannot create '%s': %s\n", lpath, strerror(errno)); - return -1; - } - goto handle_data; - } else { - goto remote_error; - } - - for(;;) { - if(readx(fd, &msg.data, sizeof(msg.data))) { - return -1; - } - id = msg.data.id; - - handle_data: - len = ltohl(msg.data.size); - if(id == ID_DONE) break; - if(id != ID_DATA) goto remote_error; - if(len > SYNC_DATA_MAX) { - fprintf(stderr,"data overrun\n"); - adb_close(lfd); - return -1; - } - - if(readx(fd, buffer, len)) { - adb_close(lfd); - return -1; - } - - if(writex(lfd, buffer, len)) { - fprintf(stderr,"cannot write '%s': %s\n", rpath, strerror(errno)); - adb_close(lfd); - return -1; - } - - total_bytes += len; - } - - adb_close(lfd); - return 0; - -remote_error: - adb_close(lfd); - adb_unlink(lpath); - - if(id == ID_FAIL) { - len = ltohl(msg.data.size); - if(len > 256) len = 256; - if(readx(fd, buffer, len)) { - return -1; - } - buffer[len] = 0; - } else { - memcpy(buffer, &id, 4); - buffer[4] = 0; -// strcpy(buffer,"unknown reason"); - } - fprintf(stderr,"failed to copy '%s' to '%s': %s\n", rpath, lpath, buffer); - return 0; -} - - - -/* --- */ - - -static void do_sync_ls_cb(unsigned mode, unsigned size, unsigned time, - const char *name, void *cookie) -{ - printf("%08x %08x %08x %s\n", mode, size, time, name); -} - -int do_sync_ls(const char *path) -{ - int fd = adb_connect("sync:"); - if(fd < 0) { - fprintf(stderr,"error: %s\n", adb_error()); - return 1; - } - - if(sync_ls(fd, path, do_sync_ls_cb, 0)) { - return 1; - } else { - sync_quit(fd); - return 0; - } -} - -typedef struct copyinfo copyinfo; - -struct copyinfo -{ - copyinfo *next; - const char *src; - const char *dst; - unsigned int time; - unsigned int mode; - unsigned int size; - int flag; - //char data[0]; -}; - -copyinfo *mkcopyinfo(const char *spath, const char *dpath, - const char *name, int isdir) -{ - int slen = strlen(spath); - int dlen = strlen(dpath); - int nlen = strlen(name); - int ssize = slen + nlen + 2; - int dsize = dlen + nlen + 2; - - copyinfo *ci = malloc(sizeof(copyinfo) + ssize + dsize); - if(ci == 0) { - fprintf(stderr,"out of memory\n"); - abort(); - } - - ci->next = 0; - ci->time = 0; - ci->mode = 0; - ci->size = 0; - ci->flag = 0; - ci->src = (const char*)(ci + 1); - ci->dst = ci->src + ssize; - snprintf((char*) ci->src, ssize, isdir ? "%s%s/" : "%s%s", spath, name); - snprintf((char*) ci->dst, dsize, isdir ? "%s%s/" : "%s%s", dpath, name); - -// fprintf(stderr,"mkcopyinfo('%s','%s')\n", ci->src, ci->dst); - return ci; -} - - -static int local_build_list(copyinfo **filelist, - const char *lpath, const char *rpath) -{ - DIR *d; - struct dirent *de; - struct stat st; - copyinfo *dirlist = 0; - copyinfo *ci, *next; - -// fprintf(stderr,"local_build_list('%s','%s')\n", lpath, rpath); - - d = opendir(lpath); - if(d == 0) { - fprintf(stderr,"cannot open '%s': %s\n", lpath, strerror(errno)); - return -1; - } - - while((de = readdir(d))) { - char stat_path[PATH_MAX]; - char *name = de->d_name; - - if(name[0] == '.') { - if(name[1] == 0) continue; - if((name[1] == '.') && (name[2] == 0)) continue; - } - - /* - * We could use d_type if HAVE_DIRENT_D_TYPE is defined, but reiserfs - * always returns DT_UNKNOWN, so we just use stat() for all cases. - */ - if (strlen(lpath) + strlen(de->d_name) + 1 > sizeof(stat_path)) - continue; - strcpy(stat_path, lpath); - strcat(stat_path, de->d_name); - stat(stat_path, &st); - - if (S_ISDIR(st.st_mode)) { - ci = mkcopyinfo(lpath, rpath, name, 1); - ci->next = dirlist; - dirlist = ci; - } else { - ci = mkcopyinfo(lpath, rpath, name, 0); - if(lstat(ci->src, &st)) { - closedir(d); - fprintf(stderr,"cannot stat '%s': %s\n", ci->src, strerror(errno)); - return -1; - } - if(!S_ISREG(st.st_mode) && !S_ISLNK(st.st_mode)) { - fprintf(stderr, "skipping special file '%s'\n", ci->src); - free(ci); - } else { - ci->time = st.st_mtime; - ci->mode = st.st_mode; - ci->size = st.st_size; - ci->next = *filelist; - *filelist = ci; - } - } - } - - closedir(d); - - for(ci = dirlist; ci != 0; ci = next) { - next = ci->next; - local_build_list(filelist, ci->src, ci->dst); - free(ci); - } - - return 0; -} - - -static int copy_local_dir_remote(int fd, const char *lpath, const char *rpath, int checktimestamps) -{ - copyinfo *filelist = 0; - copyinfo *ci, *next; - int pushed = 0; - int skipped = 0; - - if((lpath[0] == 0) || (rpath[0] == 0)) return -1; - if(lpath[strlen(lpath) - 1] != '/') { - int tmplen = strlen(lpath)+2; - char *tmp = malloc(tmplen); - if(tmp == 0) return -1; - snprintf(tmp, tmplen, "%s/",lpath); - lpath = tmp; - } - if(rpath[strlen(rpath) - 1] != '/') { - int tmplen = strlen(rpath)+2; - char *tmp = malloc(tmplen); - if(tmp == 0) return -1; - snprintf(tmp, tmplen, "%s/",rpath); - rpath = tmp; - } - - if(local_build_list(&filelist, lpath, rpath)) { - return -1; - } - - if(checktimestamps){ - for(ci = filelist; ci != 0; ci = ci->next) { - if(sync_start_readtime(fd, ci->dst)) { - return 1; - } - } - for(ci = filelist; ci != 0; ci = ci->next) { - unsigned int timestamp, mode, size; - if(sync_finish_readtime(fd, ×tamp, &mode, &size)) - return 1; - if(size == ci->size) { - /* for links, we cannot update the atime/mtime */ - if((S_ISREG(ci->mode & mode) && timestamp == ci->time) || - (S_ISLNK(ci->mode & mode) && timestamp >= ci->time)) - ci->flag = 1; - } - } - } - for(ci = filelist; ci != 0; ci = next) { - next = ci->next; - if(ci->flag == 0) { - fprintf(stderr,"push: %s -> %s\n", ci->src, ci->dst); - if(sync_send(fd, ci->src, ci->dst, ci->time, ci->mode, 0 /* no verify APK */)){ - return 1; - } - pushed++; - } else { - skipped++; - } - free(ci); - } - - fprintf(stderr,"%d file%s pushed. %d file%s skipped.\n", - pushed, (pushed == 1) ? "" : "s", - skipped, (skipped == 1) ? "" : "s"); - - return 0; -} - - -int do_sync_push(const char *lpath, const char *rpath, int verifyApk) -{ - struct stat st; - unsigned mode; - int fd; - - fd = adb_connect("sync:"); - if(fd < 0) { - fprintf(stderr,"error: %s\n", adb_error()); - return 1; - } - - if(stat(lpath, &st)) { - fprintf(stderr,"cannot stat '%s': %s\n", lpath, strerror(errno)); - sync_quit(fd); - return 1; - } - - if(S_ISDIR(st.st_mode)) { - BEGIN(); - if(copy_local_dir_remote(fd, lpath, rpath, 0)) { - return 1; - } else { - END(); - sync_quit(fd); - } - } else { - if(sync_readmode(fd, rpath, &mode)) { - return 1; - } - if((mode != 0) && S_ISDIR(mode)) { - /* if we're copying a local file to a remote directory, - ** we *really* want to copy to remotedir + "/" + localfilename - */ - const char *name = adb_dirstop(lpath); - if(name == 0) { - name = lpath; - } else { - name++; - } - int tmplen = strlen(name) + strlen(rpath) + 2; - char *tmp = malloc(strlen(name) + strlen(rpath) + 2); - if(tmp == 0) return 1; - snprintf(tmp, tmplen, "%s/%s", rpath, name); - rpath = tmp; - } - BEGIN(); - if(sync_send(fd, lpath, rpath, st.st_mtime, st.st_mode, verifyApk)) { - return 1; - } else { - END(); - sync_quit(fd); - return 0; - } - } - - return 0; -} - - -typedef struct { - copyinfo **filelist; - copyinfo **dirlist; - const char *rpath; - const char *lpath; -} sync_ls_build_list_cb_args; - -void -sync_ls_build_list_cb(unsigned mode, unsigned size, unsigned time, - const char *name, void *cookie) -{ - sync_ls_build_list_cb_args *args = (sync_ls_build_list_cb_args *)cookie; - copyinfo *ci; - - if (S_ISDIR(mode)) { - copyinfo **dirlist = args->dirlist; - - /* Don't try recursing down "." or ".." */ - if (name[0] == '.') { - if (name[1] == '\0') return; - if ((name[1] == '.') && (name[2] == '\0')) return; - } - - ci = mkcopyinfo(args->rpath, args->lpath, name, 1); - ci->next = *dirlist; - *dirlist = ci; - } else if (S_ISREG(mode) || S_ISLNK(mode)) { - copyinfo **filelist = args->filelist; - - ci = mkcopyinfo(args->rpath, args->lpath, name, 0); - ci->time = time; - ci->mode = mode; - ci->size = size; - ci->next = *filelist; - *filelist = ci; - } else { - fprintf(stderr, "skipping special file '%s'\n", name); - } -} - -static int remote_build_list(int syncfd, copyinfo **filelist, - const char *rpath, const char *lpath) -{ - copyinfo *dirlist = NULL; - sync_ls_build_list_cb_args args; - - args.filelist = filelist; - args.dirlist = &dirlist; - args.rpath = rpath; - args.lpath = lpath; - - /* Put the files/dirs in rpath on the lists. */ - if (sync_ls(syncfd, rpath, sync_ls_build_list_cb, (void *)&args)) { - return 1; - } - - /* Recurse into each directory we found. */ - while (dirlist != NULL) { - copyinfo *next = dirlist->next; - if (remote_build_list(syncfd, filelist, dirlist->src, dirlist->dst)) { - return 1; - } - free(dirlist); - dirlist = next; - } - - return 0; -} - -static int copy_remote_dir_local(int fd, const char *rpath, const char *lpath, - int checktimestamps) -{ - copyinfo *filelist = 0; - copyinfo *ci, *next; - int pulled = 0; - int skipped = 0; - - /* Make sure that both directory paths end in a slash. */ - if (rpath[0] == 0 || lpath[0] == 0) return -1; - if (rpath[strlen(rpath) - 1] != '/') { - int tmplen = strlen(rpath) + 2; - char *tmp = malloc(tmplen); - if (tmp == 0) return -1; - snprintf(tmp, tmplen, "%s/", rpath); - rpath = tmp; - } - if (lpath[strlen(lpath) - 1] != '/') { - int tmplen = strlen(lpath) + 2; - char *tmp = malloc(tmplen); - if (tmp == 0) return -1; - snprintf(tmp, tmplen, "%s/", lpath); - lpath = tmp; - } - - fprintf(stderr, "pull: building file list...\n"); - /* Recursively build the list of files to copy. */ - if (remote_build_list(fd, &filelist, rpath, lpath)) { - return -1; - } - -#if 0 - if (checktimestamps) { - for (ci = filelist; ci != 0; ci = ci->next) { - if (sync_start_readtime(fd, ci->dst)) { - return 1; - } - } - for (ci = filelist; ci != 0; ci = ci->next) { - unsigned int timestamp, mode, size; - if (sync_finish_readtime(fd, ×tamp, &mode, &size)) - return 1; - if (size == ci->size) { - /* for links, we cannot update the atime/mtime */ - if ((S_ISREG(ci->mode & mode) && timestamp == ci->time) || - (S_ISLNK(ci->mode & mode) && timestamp >= ci->time)) - ci->flag = 1; - } - } - } -#endif - for (ci = filelist; ci != 0; ci = next) { - next = ci->next; - if (ci->flag == 0) { - fprintf(stderr, "pull: %s -> %s\n", ci->src, ci->dst); - if (sync_recv(fd, ci->src, ci->dst)) { - return 1; - } - pulled++; - } else { - skipped++; - } - free(ci); - } - - fprintf(stderr, "%d file%s pulled. %d file%s skipped.\n", - pulled, (pulled == 1) ? "" : "s", - skipped, (skipped == 1) ? "" : "s"); - - return 0; -} - -int do_sync_pull(const char *rpath, const char *lpath) -{ - unsigned mode; - struct stat st; - - int fd; - - fd = adb_connect("sync:"); - if(fd < 0) { - fprintf(stderr,"error: %s\n", adb_error()); - return 1; - } - - if(sync_readmode(fd, rpath, &mode)) { - return 1; - } - if(mode == 0) { - fprintf(stderr,"remote object '%s' does not exist\n", rpath); - return 1; - } - - if(S_ISREG(mode) || S_ISCHR(mode) || S_ISBLK(mode)) { - if(stat(lpath, &st) == 0) { - if(S_ISDIR(st.st_mode)) { - /* if we're copying a remote file to a local directory, - ** we *really* want to copy to localdir + "/" + remotefilename - */ - const char *name = adb_dirstop(rpath); - if(name == 0) { - name = rpath; - } else { - name++; - } - int tmplen = strlen(name) + strlen(lpath) + 2; - char *tmp = malloc(tmplen); - if(tmp == 0) return 1; - snprintf(tmp, tmplen, "%s/%s", lpath, name); - lpath = tmp; - } - } - BEGIN(); - if(sync_recv(fd, rpath, lpath)) { - return 1; - } else { - END(); - sync_quit(fd); - return 0; - } - } else if(S_ISDIR(mode)) { - BEGIN(); - if (copy_remote_dir_local(fd, rpath, lpath, 0)) { - return 1; - } else { - END(); - sync_quit(fd); - return 0; - } - } else { - fprintf(stderr,"remote object '%s' not a file or directory\n", rpath); - return 1; - } -} - -int do_sync_sync(const char *lpath, const char *rpath) -{ - fprintf(stderr,"syncing %s...\n",rpath); - - int fd = adb_connect("sync:"); - if(fd < 0) { - fprintf(stderr,"error: %s\n", adb_error()); - return 1; - } - - BEGIN(); - if(copy_local_dir_remote(fd, lpath, rpath, 1)){ - return 1; - } else { - END(); - sync_quit(fd); - return 0; - } -} diff --git a/adb/file_sync_service.c b/adb/file_sync_service.c deleted file mode 100644 index a231e93d..00000000 --- a/adb/file_sync_service.c +++ /dev/null @@ -1,412 +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 <stdlib.h> -#include <stdio.h> -#include <string.h> - -#include <sys/stat.h> -#include <sys/types.h> -#include <dirent.h> -#include <utime.h> - -#include <errno.h> - -#include "sysdeps.h" - -#define TRACE_TAG TRACE_SYNC -#include "adb.h" -#include "file_sync_service.h" - -static int mkdirs(char *name) -{ - int ret; - char *x = name + 1; - - if(name[0] != '/') return -1; - - for(;;) { - x = adb_dirstart(x); - if(x == 0) return 0; - *x = 0; - ret = adb_mkdir(name, 0775); - if((ret < 0) && (errno != EEXIST)) { - D("mkdir(\"%s\") -> %s\n", name, strerror(errno)); - *x = '/'; - return ret; - } - *x++ = '/'; - } - return 0; -} - -static int do_stat(int s, const char *path) -{ - syncmsg msg; - struct stat st; - - msg.stat.id = ID_STAT; - - if(lstat(path, &st)) { - msg.stat.mode = 0; - msg.stat.size = 0; - msg.stat.time = 0; - } else { - msg.stat.mode = htoll(st.st_mode); - msg.stat.size = htoll(st.st_size); - msg.stat.time = htoll(st.st_mtime); - } - - return writex(s, &msg.stat, sizeof(msg.stat)); -} - -static int do_list(int s, const char *path) -{ - DIR *d; - struct dirent *de; - struct stat st; - syncmsg msg; - int len; - - char tmp[1024 + 256 + 1]; - char *fname; - - len = strlen(path); - memcpy(tmp, path, len); - tmp[len] = '/'; - fname = tmp + len + 1; - - msg.dent.id = ID_DENT; - - d = opendir(path); - if(d == 0) goto done; - - while((de = readdir(d))) { - int len = strlen(de->d_name); - - /* not supposed to be possible, but - if it does happen, let's not buffer overrun */ - if(len > 256) continue; - - strcpy(fname, de->d_name); - if(lstat(tmp, &st) == 0) { - msg.dent.mode = htoll(st.st_mode); - msg.dent.size = htoll(st.st_size); - msg.dent.time = htoll(st.st_mtime); - msg.dent.namelen = htoll(len); - - if(writex(s, &msg.dent, sizeof(msg.dent)) || - writex(s, de->d_name, len)) { - return -1; - } - } - } - - closedir(d); - -done: - msg.dent.id = ID_DONE; - msg.dent.mode = 0; - msg.dent.size = 0; - msg.dent.time = 0; - msg.dent.namelen = 0; - return writex(s, &msg.dent, sizeof(msg.dent)); -} - -static int fail_message(int s, const char *reason) -{ - syncmsg msg; - int len = strlen(reason); - - D("sync: failure: %s\n", reason); - - msg.data.id = ID_FAIL; - msg.data.size = htoll(len); - if(writex(s, &msg.data, sizeof(msg.data)) || - writex(s, reason, len)) { - return -1; - } else { - return 0; - } -} - -static int fail_errno(int s) -{ - return fail_message(s, strerror(errno)); -} - -static int handle_send_file(int s, char *path, mode_t mode, char *buffer) -{ - syncmsg msg; - unsigned int timestamp = 0; - int fd; - - fd = adb_open_mode(path, O_WRONLY | O_CREAT | O_EXCL, mode); - if(fd < 0 && errno == ENOENT) { - mkdirs(path); - fd = adb_open_mode(path, O_WRONLY | O_CREAT | O_EXCL, mode); - } - if(fd < 0 && errno == EEXIST) { - fd = adb_open_mode(path, O_WRONLY, mode); - } - if(fd < 0) { - if(fail_errno(s)) - return -1; - fd = -1; - } - - for(;;) { - unsigned int len; - - if(readx(s, &msg.data, sizeof(msg.data))) - goto fail; - - if(msg.data.id != ID_DATA) { - if(msg.data.id == ID_DONE) { - timestamp = ltohl(msg.data.size); - break; - } - fail_message(s, "invalid data message"); - goto fail; - } - len = ltohl(msg.data.size); - if(len > SYNC_DATA_MAX) { - fail_message(s, "oversize data message"); - goto fail; - } - if(readx(s, buffer, len)) - goto fail; - - if(fd < 0) - continue; - if(writex(fd, buffer, len)) { - adb_close(fd); - adb_unlink(path); - fd = -1; - if(fail_errno(s)) return -1; - } - } - - if(fd >= 0) { - struct utimbuf u; - adb_close(fd); - u.actime = timestamp; - u.modtime = timestamp; - utime(path, &u); - - msg.status.id = ID_OKAY; - msg.status.msglen = 0; - if(writex(s, &msg.status, sizeof(msg.status))) - return -1; - } - return 0; - -fail: - if(fd >= 0) - adb_close(fd); - adb_unlink(path); - return -1; -} - -#ifdef HAVE_SYMLINKS -static int handle_send_link(int s, char *path, char *buffer) -{ - syncmsg msg; - unsigned int len; - int ret; - - if(readx(s, &msg.data, sizeof(msg.data))) - return -1; - - if(msg.data.id != ID_DATA) { - fail_message(s, "invalid data message: expected ID_DATA"); - return -1; - } - - len = ltohl(msg.data.size); - if(len > SYNC_DATA_MAX) { - fail_message(s, "oversize data message"); - return -1; - } - if(readx(s, buffer, len)) - return -1; - - ret = symlink(buffer, path); - if(ret && errno == ENOENT) { - mkdirs(path); - ret = symlink(buffer, path); - } - if(ret) { - fail_errno(s); - return -1; - } - - if(readx(s, &msg.data, sizeof(msg.data))) - return -1; - - if(msg.data.id == ID_DONE) { - msg.status.id = ID_OKAY; - msg.status.msglen = 0; - if(writex(s, &msg.status, sizeof(msg.status))) - return -1; - } else { - fail_message(s, "invalid data message: expected ID_DONE"); - return -1; - } - - return 0; -} -#endif /* HAVE_SYMLINKS */ - -static int do_send(int s, char *path, char *buffer) -{ - char *tmp; - mode_t mode; - int is_link, ret; - - tmp = strrchr(path,','); - if(tmp) { - *tmp = 0; - errno = 0; - mode = strtoul(tmp + 1, NULL, 0); -#ifndef HAVE_SYMLINKS - is_link = 0; -#else - is_link = S_ISLNK(mode); -#endif - mode &= 0777; - } - if(!tmp || errno) { - mode = 0644; - is_link = 0; - } - - adb_unlink(path); - - -#ifdef HAVE_SYMLINKS - if(is_link) - ret = handle_send_link(s, path, buffer); - else { -#else - { -#endif - /* copy user permission bits to "group" and "other" permissions */ - mode |= ((mode >> 3) & 0070); - mode |= ((mode >> 3) & 0007); - - ret = handle_send_file(s, path, mode, buffer); - } - - return ret; -} - -static int do_recv(int s, const char *path, char *buffer) -{ - syncmsg msg; - int fd, r; - - fd = adb_open(path, O_RDONLY); - if(fd < 0) { - if(fail_errno(s)) return -1; - return 0; - } - - msg.data.id = ID_DATA; - for(;;) { - r = adb_read(fd, buffer, SYNC_DATA_MAX); - if(r <= 0) { - if(r == 0) break; - if(errno == EINTR) continue; - r = fail_errno(s); - adb_close(fd); - return r; - } - msg.data.size = htoll(r); - if(writex(s, &msg.data, sizeof(msg.data)) || - writex(s, buffer, r)) { - adb_close(fd); - return -1; - } - } - - adb_close(fd); - - msg.data.id = ID_DONE; - msg.data.size = 0; - if(writex(s, &msg.data, sizeof(msg.data))) { - return -1; - } - - return 0; -} - -void file_sync_service(int fd, void *cookie) -{ - syncmsg msg; - char name[1025]; - unsigned namelen; - - char *buffer = malloc(SYNC_DATA_MAX); - if(buffer == 0) goto fail; - - for(;;) { - D("sync: waiting for command\n"); - - if(readx(fd, &msg.req, sizeof(msg.req))) { - fail_message(fd, "command read failure"); - break; - } - namelen = ltohl(msg.req.namelen); - if(namelen > 1024) { - fail_message(fd, "invalid namelen"); - break; - } - if(readx(fd, name, namelen)) { - fail_message(fd, "filename read failure"); - break; - } - name[namelen] = 0; - - msg.req.namelen = 0; - D("sync: '%s' '%s'\n", (char*) &msg.req, name); - - switch(msg.req.id) { - case ID_STAT: - if(do_stat(fd, name)) goto fail; - break; - case ID_LIST: - if(do_list(fd, name)) goto fail; - break; - case ID_SEND: - if(do_send(fd, name, buffer)) goto fail; - break; - case ID_RECV: - if(do_recv(fd, name, buffer)) goto fail; - break; - case ID_QUIT: - goto fail; - default: - fail_message(fd, "unknown command"); - goto fail; - } - } - -fail: - if(buffer != 0) free(buffer); - D("sync: done\n"); - adb_close(fd); -} diff --git a/adb/file_sync_service.h b/adb/file_sync_service.h deleted file mode 100644 index 4ee40ba2..00000000 --- a/adb/file_sync_service.h +++ /dev/null @@ -1,87 +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 _FILE_SYNC_SERVICE_H_ -#define _FILE_SYNC_SERVICE_H_ - -#ifdef __ppc__ -static inline unsigned __swap_uint32(unsigned x) -{ - return (((x) & 0xFF000000) >> 24) - | (((x) & 0x00FF0000) >> 8) - | (((x) & 0x0000FF00) << 8) - | (((x) & 0x000000FF) << 24); -} -#define htoll(x) __swap_uint32(x) -#define ltohl(x) __swap_uint32(x) -#define MKID(a,b,c,d) ((d) | ((c) << 8) | ((b) << 16) | ((a) << 24)) -#else -#define htoll(x) (x) -#define ltohl(x) (x) -#define MKID(a,b,c,d) ((a) | ((b) << 8) | ((c) << 16) | ((d) << 24)) -#endif - -#define ID_STAT MKID('S','T','A','T') -#define ID_LIST MKID('L','I','S','T') -#define ID_ULNK MKID('U','L','N','K') -#define ID_SEND MKID('S','E','N','D') -#define ID_RECV MKID('R','E','C','V') -#define ID_DENT MKID('D','E','N','T') -#define ID_DONE MKID('D','O','N','E') -#define ID_DATA MKID('D','A','T','A') -#define ID_OKAY MKID('O','K','A','Y') -#define ID_FAIL MKID('F','A','I','L') -#define ID_QUIT MKID('Q','U','I','T') - -typedef union { - unsigned id; - struct { - unsigned id; - unsigned namelen; - } req; - struct { - unsigned id; - unsigned mode; - unsigned size; - unsigned time; - } stat; - struct { - unsigned id; - unsigned mode; - unsigned size; - unsigned time; - unsigned namelen; - } dent; - struct { - unsigned id; - unsigned size; - } data; - struct { - unsigned id; - unsigned msglen; - } status; -} syncmsg; - - -void file_sync_service(int fd, void *cookie); -int do_sync_ls(const char *path); -int do_sync_push(const char *lpath, const char *rpath, int verifyApk); -int do_sync_sync(const char *lpath, const char *rpath); -int do_sync_pull(const char *rpath, const char *lpath); - -#define SYNC_DATA_MAX (64*1024) - -#endif diff --git a/adb/framebuffer_service.c b/adb/framebuffer_service.c deleted file mode 100644 index 0de0dd5e..00000000 --- a/adb/framebuffer_service.c +++ /dev/null @@ -1,70 +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 <stdlib.h> -#include <stdio.h> -#include <unistd.h> -#include <string.h> -#include <fcntl.h> - -#include <cutils/fdevent.h> -#include "adb.h" - -#include <linux/fb.h> -#include <sys/ioctl.h> -#include <sys/mman.h> - -/* TODO: -** - grab the current buffer, not the first buffer -** - sync with vsync to avoid tearing -*/ - -void framebuffer_service(int fd, void *cookie) -{ - struct fb_var_screeninfo vinfo; - int fb; - void *ptr = MAP_FAILED; - char x; - - unsigned fbinfo[4]; - - fb = open("/dev/graphics/fb0", O_RDONLY); - if(fb < 0) goto done; - - if(ioctl(fb, FBIOGET_VSCREENINFO, &vinfo) < 0) goto done; - fcntl(fb, F_SETFD, FD_CLOEXEC); - - fbinfo[0] = 16; - fbinfo[1] = vinfo.xres * vinfo.yres * 2; - fbinfo[2] = vinfo.xres; - fbinfo[3] = vinfo.yres; - - ptr = mmap(0, fbinfo[1], PROT_READ, MAP_SHARED, fb, 0); - if(ptr == MAP_FAILED) goto done; - - if(writex(fd, fbinfo, sizeof(unsigned) * 4)) goto done; - - for(;;) { - if(readx(fd, &x, 1)) goto done; - if(writex(fd, ptr, fbinfo[1])) goto done; - } - -done: - if(ptr != MAP_FAILED) munmap(ptr, fbinfo[1]); - if(fb >= 0) close(fb); - close(fd); -} - diff --git a/adb/get_my_path_darwin.c b/adb/get_my_path_darwin.c deleted file mode 100644 index 00dfee43..00000000 --- a/adb/get_my_path_darwin.c +++ /dev/null @@ -1,31 +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 <utils/executablepath.h> -#import <Carbon/Carbon.h> -#include <unistd.h> - -void get_my_path(char s[PATH_MAX]) -{ - ProcessSerialNumber psn; - GetCurrentProcess(&psn); - CFDictionaryRef dict; - dict = ProcessInformationCopyDictionary(&psn, 0xffffffff); - CFStringRef value = (CFStringRef)CFDictionaryGetValue(dict, - CFSTR("CFBundleExecutable")); - CFStringGetCString(value, s, PATH_MAX - 1, kCFStringEncodingUTF8); -} - diff --git a/adb/get_my_path_linux.c b/adb/get_my_path_linux.c deleted file mode 100644 index f516e591..00000000 --- a/adb/get_my_path_linux.c +++ /dev/null @@ -1,33 +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 <sys/types.h> -#include <unistd.h> -#include <limits.h> -#include <stdio.h> - -void get_my_path(char exe[PATH_MAX]) -{ - char proc[64]; - snprintf(proc, sizeof proc, "/proc/%d/exe", getpid()); - int err = readlink(proc, exe, PATH_MAX - 1); - if(err > 0) { - exe[err] = 0; - } else { - exe[0] = 0; - } -} - diff --git a/adb/get_my_path_windows.c b/adb/get_my_path_windows.c deleted file mode 100644 index fc7143c1..00000000 --- a/adb/get_my_path_windows.c +++ /dev/null @@ -1,31 +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 <limits.h> -#include <assert.h> -#include <windows.h> - -void get_my_path(char exe[PATH_MAX]) -{ - char* r; - - GetModuleFileName( NULL, exe, PATH_MAX-1 ); - exe[PATH_MAX-1] = 0; - r = strrchr( exe, '\\' ); - if (r) - *r = 0; -} - diff --git a/adb/history.h b/adb/history.h deleted file mode 100755 index ef86ad9b..00000000 --- a/adb/history.h +++ /dev/null @@ -1,13 +0,0 @@ -#ifndef _HISTORY_H_
-#define _HISTORY_H_
-
-#define SH_ARROW_ANY "\x1b\x5b"
-#define SH_ARROW_UP '\x41'
-#define SH_ARROW_DOWN '\x42'
-#define SH_ARROW_RIGHT '\x43'
-#define SH_ARROW_LEFT '\x44'
-#define SH_DEL_CHAR '\x7F'
-#define SH_BLANK_CHAR '\x20'
-
-#endif
-
diff --git a/adb/jdwp_service.c b/adb/jdwp_service.c deleted file mode 100644 index ae7f12df..00000000 --- a/adb/jdwp_service.c +++ /dev/null @@ -1,709 +0,0 @@ -/* implement the "debug-ports" and "track-debug-ports" device services */ -#include "sysdeps.h" -#define TRACE_TAG TRACE_JDWP -#include "adb.h" -#include <errno.h> -#include <stdio.h> -#include <string.h> - -/* here's how these things work. - - when adbd starts, it creates a unix server socket - named @vm-debug-control (@ is a shortcut for "first byte is zero" - to use the private namespace instead of the file system) - - when a new JDWP daemon thread starts in a new VM process, it creates - a connection to @vm-debug-control to announce its availability. - - - JDWP thread @vm-debug-control - | | - |-------------------------------> | - | hello I'm in process <pid> | - | | - | | - - the connection is kept alive. it will be closed automatically if - the JDWP process terminates (this allows adbd to detect dead - processes). - - adbd thus maintains a list of "active" JDWP processes. it can send - its content to clients through the "device:debug-ports" service, - or even updates through the "device:track-debug-ports" service. - - when a debugger wants to connect, it simply runs the command - equivalent to "adb forward tcp:<hostport> jdwp:<pid>" - - "jdwp:<pid>" is a new forward destination format used to target - a given JDWP process on the device. when sutch a request arrives, - adbd does the following: - - - first, it calls socketpair() to create a pair of equivalent - sockets. - - - it attaches the first socket in the pair to a local socket - which is itself attached to the transport's remote socket: - - - - it sends the file descriptor of the second socket directly - to the JDWP process with the help of sendmsg() - - - JDWP thread @vm-debug-control - | | - | <----------------------| - | OK, try this file descriptor | - | | - | | - - then, the JDWP thread uses this new socket descriptor as its - pass-through connection to the debugger (and receives the - JDWP-Handshake message, answers to it, etc...) - - this gives the following graphics: - ____________________________________ - | | - | ADB Server (host) | - | | - Debugger <---> LocalSocket <----> RemoteSocket | - | ^^ | - |___________________________||_______| - || - Transport || - (TCP for emulator - USB for device) || - || - ___________________________||_______ - | || | - | ADBD (device) || | - | VV | - JDWP <======> LocalSocket <----> RemoteSocket | - | | - |____________________________________| - - due to the way adb works, this doesn't need a special socket - type or fancy handling of socket termination if either the debugger - or the JDWP process closes the connection. - - THIS IS THE SIMPLEST IMPLEMENTATION I COULD FIND, IF YOU HAPPEN - TO HAVE A BETTER IDEA, LET ME KNOW - Digit - -**********************************************************************/ - -/** JDWP PID List Support Code - ** for each JDWP process, we record its pid and its connected socket - **/ - -#define MAX_OUT_FDS 4 - -#if !ADB_HOST - -#include <sys/socket.h> -#include <sys/un.h> - -typedef struct JdwpProcess JdwpProcess; -struct JdwpProcess { - JdwpProcess* next; - JdwpProcess* prev; - int pid; - int socket; - fdevent* fde; - - char in_buff[4]; /* input character to read PID */ - int in_len; /* number from JDWP process */ - - int out_fds[MAX_OUT_FDS]; /* output array of file descriptors */ - int out_count; /* to send to the JDWP process */ -}; - -static JdwpProcess _jdwp_list; - -static int -jdwp_process_list( char* buffer, int bufferlen ) -{ - char* end = buffer + bufferlen; - char* p = buffer; - JdwpProcess* proc = _jdwp_list.next; - - for ( ; proc != &_jdwp_list; proc = proc->next ) { - int len; - - /* skip transient connections */ - if (proc->pid < 0) - continue; - - len = snprintf(p, end-p, "%d\n", proc->pid); - if (p + len >= end) - break; - p += len; - } - p[0] = 0; - return (p - buffer); -} - - -static int -jdwp_process_list_msg( char* buffer, int bufferlen ) -{ - char head[5]; - int len = jdwp_process_list( buffer+4, bufferlen-4 ); - snprintf(head, sizeof head, "%04x", len); - memcpy(buffer, head, 4); - return len + 4; -} - - -static void jdwp_process_list_updated(void); - -static void -jdwp_process_free( JdwpProcess* proc ) -{ - if (proc) { - int n; - - proc->prev->next = proc->next; - proc->next->prev = proc->prev; - - if (proc->socket >= 0) { - shutdown(proc->socket, SHUT_RDWR); - adb_close(proc->socket); - proc->socket = -1; - } - - if (proc->fde != NULL) { - fdevent_destroy(proc->fde); - proc->fde = NULL; - } - proc->pid = -1; - - for (n = 0; n < proc->out_count; n++) { - adb_close(proc->out_fds[n]); - } - proc->out_count = 0; - - free(proc); - - jdwp_process_list_updated(); - } -} - - -static void jdwp_process_event(int, unsigned, void*); /* forward */ - - -static JdwpProcess* -jdwp_process_alloc( int socket ) -{ - JdwpProcess* proc = calloc(1,sizeof(*proc)); - - if (proc == NULL) { - D("not enough memory to create new JDWP process\n"); - return NULL; - } - - proc->socket = socket; - proc->pid = -1; - proc->next = proc; - proc->prev = proc; - - proc->fde = fdevent_create( socket, jdwp_process_event, proc ); - if (proc->fde == NULL) { - D("could not create fdevent for new JDWP process\n" ); - free(proc); - return NULL; - } - - proc->fde->state |= FDE_DONT_CLOSE; - proc->in_len = 0; - proc->out_count = 0; - - /* append to list */ - proc->next = &_jdwp_list; - proc->prev = proc->next->prev; - - proc->prev->next = proc; - proc->next->prev = proc; - - /* start by waiting for the PID */ - fdevent_add(proc->fde, FDE_READ); - - return proc; -} - - -static void -jdwp_process_event( int socket, unsigned events, void* _proc ) -{ - JdwpProcess* proc = _proc; - - if (events & FDE_READ) { - if (proc->pid < 0) { - /* read the PID as a 4-hexchar string */ - char* p = proc->in_buff + proc->in_len; - int size = 4 - proc->in_len; - char temp[5]; - while (size > 0) { - int len = recv( socket, p, size, 0 ); - if (len < 0) { - if (errno == EINTR) - continue; - if (errno == EAGAIN) - return; - /* this can fail here if the JDWP process crashes very fast */ - D("weird unknown JDWP process failure: %s\n", - strerror(errno)); - - goto CloseProcess; - } - if (len == 0) { /* end of stream ? */ - D("weird end-of-stream from unknown JDWP process\n"); - goto CloseProcess; - } - p += len; - proc->in_len += len; - size -= len; - } - /* we have read 4 characters, now decode the pid */ - memcpy(temp, proc->in_buff, 4); - temp[4] = 0; - - if (sscanf( temp, "%04x", &proc->pid ) != 1) { - D("could not decode JDWP %p PID number: '%s'\n", proc, temp); - goto CloseProcess; - } - - /* all is well, keep reading to detect connection closure */ - D("Adding pid %d to jdwp process list\n", proc->pid); - jdwp_process_list_updated(); - } - else - { - /* the pid was read, if we get there it's probably because the connection - * was closed (e.g. the JDWP process exited or crashed) */ - char buf[32]; - - for (;;) { - int len = recv(socket, buf, sizeof(buf), 0); - - if (len <= 0) { - if (len < 0 && errno == EINTR) - continue; - if (len < 0 && errno == EAGAIN) - return; - else { - D("terminating JDWP %d connection: %s\n", proc->pid, - strerror(errno)); - break; - } - } - else { - D( "ignoring unexpected JDWP %d control socket activity (%d bytes)\n", - proc->pid, len ); - } - } - - CloseProcess: - if (proc->pid >= 0) - D( "remove pid %d to jdwp process list\n", proc->pid ); - jdwp_process_free(proc); - return; - } - } - - if (events & FDE_WRITE) { - D("trying to write to JDWP pid controli (count=%d first=%d) %d\n", - proc->pid, proc->out_count, proc->out_fds[0]); - if (proc->out_count > 0) { - int fd = proc->out_fds[0]; - int n, ret; - struct cmsghdr* cmsg; - struct msghdr msg; - struct iovec iov; - char dummy = '!'; - char buffer[sizeof(struct cmsghdr) + sizeof(int)]; - - iov.iov_base = &dummy; - iov.iov_len = 1; - msg.msg_name = NULL; - msg.msg_namelen = 0; - msg.msg_iov = &iov; - msg.msg_iovlen = 1; - msg.msg_flags = 0; - msg.msg_control = buffer; - msg.msg_controllen = sizeof(buffer); - - cmsg = CMSG_FIRSTHDR(&msg); - cmsg->cmsg_len = msg.msg_controllen; - cmsg->cmsg_level = SOL_SOCKET; - cmsg->cmsg_type = SCM_RIGHTS; - ((int*)CMSG_DATA(cmsg))[0] = fd; - - for (;;) { - ret = sendmsg(proc->socket, &msg, 0); - if (ret >= 0) - break; - if (errno == EINTR) - continue; - D("sending new file descriptor to JDWP %d failed: %s\n", - proc->pid, strerror(errno)); - goto CloseProcess; - } - - D("sent file descriptor %d to JDWP process %d\n", - fd, proc->pid); - - for (n = 1; n < proc->out_count; n++) - proc->out_fds[n-1] = proc->out_fds[n]; - - if (--proc->out_count == 0) - fdevent_del( proc->fde, FDE_WRITE ); - } - } -} - - -int -create_jdwp_connection_fd(int pid) -{ - JdwpProcess* proc = _jdwp_list.next; - - D("looking for pid %d in JDWP process list\n", pid); - for ( ; proc != &_jdwp_list; proc = proc->next ) { - if (proc->pid == pid) { - goto FoundIt; - } - } - D("search failed !!\n"); - return -1; - -FoundIt: - { - int fds[2]; - - if (proc->out_count >= MAX_OUT_FDS) { - D("%s: too many pending JDWP connection for pid %d\n", - __FUNCTION__, pid); - return -1; - } - - if (adb_socketpair(fds) < 0) { - D("%s: socket pair creation failed: %s\n", - __FUNCTION__, strerror(errno)); - return -1; - } - - proc->out_fds[ proc->out_count ] = fds[1]; - if (++proc->out_count == 1) - fdevent_add( proc->fde, FDE_WRITE ); - - return fds[0]; - } -} - -/** VM DEBUG CONTROL SOCKET - ** - ** we do implement a custom asocket to receive the data - **/ - -/* name of the debug control Unix socket */ -#define JDWP_CONTROL_NAME "\0jdwp-control" -#define JDWP_CONTROL_NAME_LEN (sizeof(JDWP_CONTROL_NAME)-1) - -typedef struct { - int listen_socket; - fdevent* fde; - -} JdwpControl; - - -static void -jdwp_control_event(int s, unsigned events, void* user); - - -static int -jdwp_control_init( JdwpControl* control, - const char* sockname, - int socknamelen ) -{ - struct sockaddr_un addr; - socklen_t addrlen; - int s; - int maxpath = sizeof(addr.sun_path); - int pathlen = socknamelen; - - if (pathlen >= maxpath) { - D( "vm debug control socket name too long (%d extra chars)\n", - pathlen+1-maxpath ); - return -1; - } - - memset(&addr, 0, sizeof(addr)); - addr.sun_family = AF_UNIX; - memcpy(addr.sun_path, sockname, socknamelen); - - s = socket( AF_UNIX, SOCK_STREAM, 0 ); - if (s < 0) { - D( "could not create vm debug control socket. %d: %s\n", - errno, strerror(errno)); - return -1; - } - - addrlen = (pathlen + sizeof(addr.sun_family)); - - if (bind(s, (struct sockaddr*)&addr, addrlen) < 0) { - D( "could not bind vm debug control socket: %d: %s\n", - errno, strerror(errno) ); - adb_close(s); - return -1; - } - - if ( listen(s, 4) < 0 ) { - D("listen failed in jdwp control socket: %d: %s\n", - errno, strerror(errno)); - adb_close(s); - return -1; - } - - control->listen_socket = s; - - control->fde = fdevent_create(s, jdwp_control_event, control); - if (control->fde == NULL) { - D( "could not create fdevent for jdwp control socket\n" ); - adb_close(s); - return -1; - } - - /* only wait for incoming connections */ - fdevent_add(control->fde, FDE_READ); - - D("jdwp control socket started (%d)\n", control->listen_socket); - return 0; -} - - -static void -jdwp_control_event( int s, unsigned events, void* _control ) -{ - JdwpControl* control = (JdwpControl*) _control; - - if (events & FDE_READ) { - struct sockaddr addr; - socklen_t addrlen = sizeof(addr); - int s = -1; - JdwpProcess* proc; - - do { - s = adb_socket_accept( control->listen_socket, &addr, &addrlen ); - if (s < 0) { - if (errno == EINTR) - continue; - if (errno == ECONNABORTED) { - /* oops, the JDWP process died really quick */ - D("oops, the JDWP process died really quick\n"); - return; - } - /* the socket is probably closed ? */ - D( "weird accept() failed on jdwp control socket: %s\n", - strerror(errno) ); - return; - } - } - while (s < 0); - - proc = jdwp_process_alloc( s ); - if (proc == NULL) - return; - } -} - - -static JdwpControl _jdwp_control; - -/** "jdwp" local service implementation - ** this simply returns the list of known JDWP process pids - **/ - -typedef struct { - asocket socket; - int pass; -} JdwpSocket; - -static void -jdwp_socket_close( asocket* s ) -{ - asocket* peer = s->peer; - - remove_socket(s); - - if (peer) { - peer->peer = NULL; - peer->close(peer); - } - free(s); -} - -static int -jdwp_socket_enqueue( asocket* s, apacket* p ) -{ - /* you can't write to this asocket */ - put_apacket(p); - s->peer->close(s->peer); - return -1; -} - - -static void -jdwp_socket_ready( asocket* s ) -{ - JdwpSocket* jdwp = (JdwpSocket*)s; - asocket* peer = jdwp->socket.peer; - - /* on the first call, send the list of pids, - * on the second one, close the connection - */ - if (jdwp->pass == 0) { - apacket* p = get_apacket(); - p->len = jdwp_process_list((char*)p->data, MAX_PAYLOAD); - peer->enqueue(peer, p); - jdwp->pass = 1; - } - else { - peer->close(peer); - } -} - -asocket* -create_jdwp_service_socket( void ) -{ - JdwpSocket* s = calloc(sizeof(*s),1); - - if (s == NULL) - return NULL; - - install_local_socket(&s->socket); - - s->socket.ready = jdwp_socket_ready; - s->socket.enqueue = jdwp_socket_enqueue; - s->socket.close = jdwp_socket_close; - s->pass = 0; - - return &s->socket; -} - -/** "track-jdwp" local service implementation - ** this periodically sends the list of known JDWP process pids - ** to the client... - **/ - -typedef struct JdwpTracker JdwpTracker; - -struct JdwpTracker { - asocket socket; - JdwpTracker* next; - JdwpTracker* prev; - int need_update; -}; - -static JdwpTracker _jdwp_trackers_list; - - -static void -jdwp_process_list_updated(void) -{ - char buffer[1024]; - int len; - JdwpTracker* t = _jdwp_trackers_list.next; - - len = jdwp_process_list_msg(buffer, sizeof(buffer)); - - for ( ; t != &_jdwp_trackers_list; t = t->next ) { - apacket* p = get_apacket(); - asocket* peer = t->socket.peer; - memcpy(p->data, buffer, len); - p->len = len; - peer->enqueue( peer, p ); - } -} - -static void -jdwp_tracker_close( asocket* s ) -{ - JdwpTracker* tracker = (JdwpTracker*) s; - asocket* peer = s->peer; - - if (peer) { - peer->peer = NULL; - peer->close(peer); - } - - remove_socket(s); - - tracker->prev->next = tracker->next; - tracker->next->prev = tracker->prev; - - free(s); -} - -static void -jdwp_tracker_ready( asocket* s ) -{ - JdwpTracker* t = (JdwpTracker*) s; - - if (t->need_update) { - apacket* p = get_apacket(); - t->need_update = 0; - p->len = jdwp_process_list_msg((char*)p->data, sizeof(p->data)); - s->peer->enqueue(s->peer, p); - } -} - -static int -jdwp_tracker_enqueue( asocket* s, apacket* p ) -{ - /* you can't write to this socket */ - put_apacket(p); - s->peer->close(s->peer); - return -1; -} - - -asocket* -create_jdwp_tracker_service_socket( void ) -{ - JdwpTracker* t = calloc(sizeof(*t),1); - - if (t == NULL) - return NULL; - - t->next = &_jdwp_trackers_list; - t->prev = t->next->prev; - - t->next->prev = t; - t->prev->next = t; - - install_local_socket(&t->socket); - - t->socket.ready = jdwp_tracker_ready; - t->socket.enqueue = jdwp_tracker_enqueue; - t->socket.close = jdwp_tracker_close; - t->need_update = 1; - - return &t->socket; -} - - -int -init_jdwp(void) -{ - _jdwp_list.next = &_jdwp_list; - _jdwp_list.prev = &_jdwp_list; - - _jdwp_trackers_list.next = &_jdwp_trackers_list; - _jdwp_trackers_list.prev = &_jdwp_trackers_list; - - return jdwp_control_init( &_jdwp_control, - JDWP_CONTROL_NAME, - JDWP_CONTROL_NAME_LEN ); -} - -#endif /* !ADB_HOST */ - diff --git a/adb/log_service.c b/adb/log_service.c deleted file mode 100644 index 6e9bdeee..00000000 --- a/adb/log_service.c +++ /dev/null @@ -1,92 +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 <stdlib.h> -#include <stdio.h> -#include <unistd.h> -#include <string.h> -#include <fcntl.h> -#include <errno.h> -#include <sys/socket.h> -#include <cutils/logger.h> -#include "sysdeps.h" -#include "adb.h" - -#define LOG_FILE_DIR "/dev/log/" - -void write_log_entry(int fd, struct logger_entry *buf); - -void log_service(int fd, void *cookie) -{ - /* get the name of the log filepath to read */ - char * log_filepath = cookie; - - /* open the log file. */ - int logfd = unix_open(log_filepath, O_RDONLY); - if (logfd < 0) { - goto done; - } - - // temp buffer to read the entries - unsigned char buf[LOGGER_ENTRY_MAX_LEN + 1] __attribute__((aligned(4))); - struct logger_entry *entry = (struct logger_entry *) buf; - - while (1) { - int ret; - - ret = unix_read(logfd, entry, LOGGER_ENTRY_MAX_LEN); - if (ret < 0) { - if (errno == EINTR || errno == EAGAIN) - continue; - // perror("logcat read"); - goto done; - } - else if (!ret) { - // fprintf(stderr, "read: Unexpected EOF!\n"); - goto done; - } - - /* NOTE: driver guarantees we read exactly one full entry */ - - entry->msg[entry->len] = '\0'; - - write_log_entry(fd, entry); - } - -done: - unix_close(fd); - free(log_filepath); -} - -/* returns the full path to the log file in a newly allocated string */ -char * get_log_file_path(const char * log_name) { - char *log_device = malloc(strlen(LOG_FILE_DIR) + strlen(log_name) + 1); - - strcpy(log_device, LOG_FILE_DIR); - strcat(log_device, log_name); - - return log_device; -} - - -/* prints one log entry into the file descriptor fd */ -void write_log_entry(int fd, struct logger_entry *buf) -{ - size_t size = sizeof(struct logger_entry) + buf->len; - - writex(fd, buf, size); -} diff --git a/adb/mutex_list.h b/adb/mutex_list.h deleted file mode 100644 index eebe0dfc..00000000 --- a/adb/mutex_list.h +++ /dev/null @@ -1,14 +0,0 @@ -/* the list of mutexes used by addb */ -#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) - -#undef ADB_MUTEX diff --git a/adb/protocol.txt b/adb/protocol.txt deleted file mode 100644 index d0f307cf..00000000 --- a/adb/protocol.txt +++ /dev/null @@ -1,252 +0,0 @@ - ---- a replacement for aproto ------------------------------------------- - -When it comes down to it, aproto's primary purpose is to forward -various streams between the host computer and client device (in either -direction). - -This replacement further simplifies the concept, reducing the protocol -to an extremely straightforward model optimized to accomplish the -forwarding of these streams and removing additional state or -complexity. - -The host side becomes a simple comms bridge with no "UI", which will -be used by either commandline or interactive tools to communicate with -a device or emulator that is connected to the bridge. - -The protocol is designed to be straightforward and well-defined enough -that if it needs to be reimplemented in another environment (Java -perhaps), there should not problems ensuring perfect interoperability. - -The protocol discards the layering aproto has and should allow the -implementation to be much more robust. - - ---- protocol overview and basics --------------------------------------- - -The transport layer deals in "messages", which consist of a 24 byte -header followed (optionally) by a payload. The header consists of 6 -32 bit words which are sent across the wire in little endian format. - -struct message { - unsigned command; /* command identifier constant */ - unsigned arg0; /* first argument */ - unsigned arg1; /* second argument */ - unsigned data_length; /* length of payload (0 is allowed) */ - unsigned data_crc32; /* crc32 of data payload */ - unsigned magic; /* command ^ 0xffffffff */ -}; - -Receipt of an invalid message header, corrupt message payload, or an -unrecognized command MUST result in the closing of the remote -connection. The protocol depends on shared state and any break in the -message stream will result in state getting out of sync. - -The following sections describe the six defined message types in -detail. Their format is COMMAND(arg0, arg1, payload) where the payload -is represented by a quoted string or an empty string if none should be -sent. - -The identifiers "local-id" and "remote-id" are always relative to the -*sender* of the message, so for a receiver, the meanings are effectively -reversed. - - - ---- CONNECT(version, maxdata, "system-identity-string") ---------------- - -The CONNECT message establishes the presence of a remote system. -The version is used to ensure protocol compatibility and maxdata -declares the maximum message body size that the remote system -is willing to accept. - -Currently, version=0x01000000 and maxdata=4096 - -Both sides send a CONNECT message when the connection between them is -established. Until a CONNECT message is received no other messages may -be sent. Any messages received before a CONNECT message MUST be ignored. - -If a CONNECT message is received with an unknown version or insufficiently -large maxdata value, the connection with the other side must be closed. - -The system identity string should be "<systemtype>:<serialno>:<banner>" -where systemtype is "bootloader", "device", or "host", serialno is some -kind of unique ID (or empty), and banner is a human-readable version -or identifier string (informational only). - - ---- OPEN(local-id, 0, "destination") ----------------------------------- - -The OPEN message informs the recipient that the sender has a stream -identified by local-id that it wishes to connect to the named -destination in the message payload. The local-id may not be zero. - -The OPEN message MUST result in either a READY message indicating that -the connection has been established (and identifying the other end) or -a CLOSE message, indicating failure. An OPEN message also implies -a READY message sent at the same time. - -Common destination naming conventions include: - -* "tcp:<host>:<port>" - host may be omitted to indicate localhost -* "udp:<host>:<port>" - host may be omitted to indicate localhost -* "local-dgram:<identifier>" -* "local-stream:<identifier>" -* "shell" - local shell service -* "upload" - service for pushing files across (like aproto's /sync) -* "fs-bridge" - FUSE protocol filesystem bridge - - ---- READY(local-id, remote-id, "") ------------------------------------- - -The READY message informs the recipient that the sender's stream -identified by local-id is ready for write messages and that it is -connected to the recipient's stream identified by remote-id. - -Neither the local-id nor the remote-id may be zero. - -A READY message containing a remote-id which does not map to an open -stream on the recipient's side is ignored. The stream may have been -closed while this message was in-flight. - -The local-id is ignored on all but the first READY message (where it -is used to establish the connection). Nonetheless, the local-id MUST -not change on later READY messages sent to the same stream. - - - ---- WRITE(0, remote-id, "data") ---------------------------------------- - -The WRITE message sends data to the recipient's stream identified by -remote-id. The payload MUST be <= maxdata in length. - -A WRITE message containing a remote-id which does not map to an open -stream on the recipient's side is ignored. The stream may have been -closed while this message was in-flight. - -A WRITE message may not be sent until a READY message is received. -Once a WRITE message is sent, an additional WRITE message may not be -sent until another READY message has been received. Recipients of -a WRITE message that is in violation of this requirement will CLOSE -the connection. - - ---- CLOSE(local-id, remote-id, "") ------------------------------------- - -The CLOSE message informs recipient that the connection between the -sender's stream (local-id) and the recipient's stream (remote-id) is -broken. The remote-id MUST not be zero, but the local-id MAY be zero -if this CLOSE indicates a failed OPEN. - -A CLOSE message containing a remote-id which does not map to an open -stream on the recipient's side is ignored. The stream may have -already been closed by the recipient while this message was in-flight. - -The recipient should not respond to a CLOSE message in any way. The -recipient should cancel pending WRITEs or CLOSEs, but this is not a -requirement, since they will be ignored. - - ---- SYNC(online, sequence, "") ----------------------------------------- - -The SYNC message is used by the io pump to make sure that stale -outbound messages are discarded when the connection to the remote side -is broken. It is only used internally to the bridge and never valid -to send across the wire. - -* when the connection to the remote side goes offline, the io pump - sends a SYNC(0, 0) and starts discarding all messages -* when the connection to the remote side is established, the io pump - sends a SYNC(1, token) and continues to discard messages -* when the io pump receives a matching SYNC(1, token), it once again - starts accepting messages to forward to the remote side - - ---- message command constants ------------------------------------------ - -#define A_SYNC 0x434e5953 -#define A_CNXN 0x4e584e43 -#define A_OPEN 0x4e45504f -#define A_OKAY 0x59414b4f -#define A_CLSE 0x45534c43 -#define A_WRTE 0x45545257 - - - ---- implementation details --------------------------------------------- - -The core of the bridge program will use three threads. One thread -will be a select/epoll loop to handle io between various inbound and -outbound connections and the connection to the remote side. - -The remote side connection will be implemented as two threads (one for -reading, one for writing) and a datagram socketpair to provide the -channel between the main select/epoll thread and the remote connection -threadpair. The reason for this is that for usb connections, the -kernel interface on linux and osx does not allow you to do meaningful -nonblocking IO. - -The endian swapping for the message headers will happen (as needed) in -the remote connection threadpair and that the rest of the program will -always treat message header values as native-endian. - -The bridge program will be able to have a number of mini-servers -compiled in. They will be published under known names (examples -"shell", "fs-bridge", etc) and upon receiving an OPEN() to such a -service, the bridge program will create a stream socketpair and spawn -a thread or subprocess to handle the io. - - ---- simplified / embedded implementation ------------------------------- - -For limited environments, like the bootloader, it is allowable to -support a smaller, fixed number of channels using pre-assigned channel -ID numbers such that only one stream may be connected to a bootloader -endpoint at any given time. The protocol remains unchanged, but the -"embedded" version of it is less dynamic. - -The bootloader will support two streams. A "bootloader:debug" stream, -which may be opened to get debug messages from the bootloader and a -"bootloader:control", stream which will support the set of basic -bootloader commands. - -Example command stream dialogues: - "flash_kernel,2515049,........\n" "okay\n" - "flash_ramdisk,5038,........\n" "fail,flash write error\n" - "bogus_command......" <CLOSE> - - ---- future expansion --------------------------------------------------- - -I plan on providing either a message or a special control stream so that -the client device could ask the host computer to setup inbound socket -translations on the fly on behalf of the client device. - - -The initial design does handshaking to provide flow control, with a -message flow that looks like: - - >OPEN <READY >WRITE <READY >WRITE <READY >WRITE <CLOSE - -The far side may choose to issue the READY message as soon as it receives -a WRITE or it may defer the READY until the write to the local stream -succeeds. A future version may want to do some level of windowing where -multiple WRITEs may be sent without requiring individual READY acks. - ------------------------------------------------------------------------- - ---- smartsockets ------------------------------------------------------- - -Port 5037 is used for smart sockets which allow a client on the host -side to request access to a service in the host adb daemon or in the -remote (device) daemon. The service is requested by ascii name, -preceeded by a 4 digit hex length. Upon successful connection an -"OKAY" response is sent, otherwise a "FAIL" message is returned. Once -connected the client is talking to that (remote or local) service. - -client: <hex4> <service-name> -server: "OKAY" - -client: <hex4> <service-name> -server: "FAIL" <hex4> <reason> - diff --git a/adb/remount_service.c b/adb/remount_service.c deleted file mode 100644 index 26bc841c..00000000 --- a/adb/remount_service.c +++ /dev/null @@ -1,103 +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 <stdlib.h> -#include <stdio.h> -#include <unistd.h> -#include <string.h> -#include <fcntl.h> -#include <sys/mount.h> -#include <errno.h> - -#include "sysdeps.h" - -#define TRACE_TAG TRACE_ADB -#include "adb.h" - - -static int system_ro = 1; - -/* Returns the mount number of the requested partition from /proc/mtd */ -static int find_mount(const char *findme) -{ - int fd; - int res; - int size; - char *token = NULL; - const char delims[] = "\n"; - char buf[1024]; - - fd = unix_open("/proc/mtd", O_RDONLY); - if (fd < 0) - return -errno; - - buf[sizeof(buf) - 1] = '\0'; - size = adb_read(fd, buf, sizeof(buf) - 1); - adb_close(fd); - - token = strtok(buf, delims); - - while (token) { - char mtdname[16]; - int mtdnum, mtdsize, mtderasesize; - - res = sscanf(token, "mtd%d: %x %x %15s", - &mtdnum, &mtdsize, &mtderasesize, mtdname); - - if (res == 4 && !strcmp(mtdname, findme)) - return mtdnum; - - token = strtok(NULL, delims); - } - return -1; -} - -/* Init mounts /system as read only, remount to enable writes. */ -static int remount_system() -{ - int num; - char source[64]; - if (system_ro == 0) { - return 0; - } - if ((num = find_mount("\"system\"")) < 0) - return -1; - - snprintf(source, sizeof source, "/dev/block/mtdblock%d", num); - system_ro = mount(source, "/system", "yaffs2", MS_REMOUNT, NULL); - return system_ro; -} - -static void write_string(int fd, const char* str) -{ - writex(fd, str, strlen(str)); -} - -void remount_service(int fd, void *cookie) -{ - int ret = remount_system(); - - if (!ret) - write_string(fd, "remount succeeded\n"); - else { - char buffer[200]; - snprintf(buffer, sizeof(buffer), "remount failed: %s\n", strerror(errno)); - write_string(fd, buffer); - } - - adb_close(fd); -} - diff --git a/adb/services.c b/adb/services.c deleted file mode 100644 index e686949c..00000000 --- a/adb/services.c +++ /dev/null @@ -1,367 +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 <stdlib.h> -#include <stdio.h> -#include <unistd.h> -#include <string.h> -#include <errno.h> - -#include "sysdeps.h" - -#define TRACE_TAG TRACE_ADB -#include "adb.h" -#include "file_sync_service.h" - -#if ADB_HOST -# ifndef HAVE_WINSOCK -# include <netinet/in.h> -# include <netdb.h> -# endif -#endif - -typedef struct stinfo stinfo; - -struct stinfo { - void (*func)(int fd, void *cookie); - int fd; - void *cookie; -}; - - -void *service_bootstrap_func(void *x) -{ - stinfo *sti = x; - sti->func(sti->fd, sti->cookie); - free(sti); - return 0; -} - -#if ADB_HOST -ADB_MUTEX_DEFINE( dns_lock ); - -static void dns_service(int fd, void *cookie) -{ - char *hostname = cookie; - struct hostent *hp; - unsigned zero = 0; - - adb_mutex_lock(&dns_lock); - hp = gethostbyname(hostname); - if(hp == 0) { - writex(fd, &zero, 4); - } else { - writex(fd, hp->h_addr, 4); - } - adb_mutex_unlock(&dns_lock); - adb_close(fd); -} -#else -extern int recovery_mode; - -static void recover_service(int s, void *cookie) -{ - unsigned char buf[4096]; - unsigned count = (unsigned) cookie; - int fd; - - fd = adb_creat("/tmp/update", 0644); - if(fd < 0) { - adb_close(s); - return; - } - - while(count > 0) { - unsigned xfer = (count > 4096) ? 4096 : count; - if(readx(s, buf, xfer)) break; - if(writex(fd, buf, xfer)) break; - count -= xfer; - } - - if(count == 0) { - writex(s, "OKAY", 4); - } else { - writex(s, "FAIL", 4); - } - adb_close(fd); - adb_close(s); - - fd = adb_creat("/tmp/update.begin", 0644); - adb_close(fd); -} - -#endif - -#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)); - 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)){ - free(sti); - adb_close(s[0]); - adb_close(s[1]); - printf("cannot create service thread\n"); - return -1; - } - - D("service thread started, %d:%d\n",s[0], s[1]); - return s[0]; -} - -static int create_subprocess(const char *cmd, const char *arg0, const char *arg1) -{ -#ifdef HAVE_WIN32_PROC - fprintf(stderr, "error: create_subprocess not implemented on Win32 (%s %s %s)\n", cmd, arg0, arg1); - return -1; -#else /* !HAVE_WIN32_PROC */ - char *devname; - int ptm; - pid_t pid; - - ptm = unix_open("/dev/ptmx", O_RDWR); // | O_NOCTTY); - if(ptm < 0){ - printf("[ cannot open /dev/ptmx - %s ]\n",strerror(errno)); - return -1; - } - fcntl(ptm, F_SETFD, FD_CLOEXEC); - - if(grantpt(ptm) || unlockpt(ptm) || - ((devname = (char*) ptsname(ptm)) == 0)){ - printf("[ trouble with /dev/ptmx - %s ]\n", strerror(errno)); - return -1; - } - - pid = fork(); - if(pid < 0) { - printf("- fork failed: %s -\n", strerror(errno)); - return -1; - } - - if(pid == 0){ - int pts; - - setsid(); - - pts = unix_open(devname, O_RDWR); - if(pts < 0) exit(-1); - - dup2(pts, 0); - dup2(pts, 1); - dup2(pts, 2); - - adb_close(ptm); - - execl(cmd, cmd, arg0, arg1, NULL); - fprintf(stderr, "- exec '%s' failed: %s (%d) -\n", - cmd, strerror(errno), errno); - exit(-1); - } else { - return ptm; - } -#endif /* !HAVE_WIN32_PROC */ -} - -#if ADB_HOST -#define SHELL_COMMAND "/bin/sh" -#else -#define SHELL_COMMAND "/system/bin/sh" -#endif - -int service_to_fd(const char *name) -{ - int ret = -1; - - if(!strncmp(name, "tcp:", 4)) { - int port = atoi(name + 4); - name = strchr(name + 4, ':'); - if(name == 0) { - ret = socket_loopback_client(port, SOCK_STREAM); - if (ret >= 0) - disable_tcp_nagle(ret); - } else { -#if ADB_HOST - adb_mutex_lock(&dns_lock); - ret = socket_network_client(name + 1, port, SOCK_STREAM); - adb_mutex_unlock(&dns_lock); -#else - return -1; -#endif - } -#ifndef HAVE_WINSOCK /* winsock doesn't implement unix domain sockets */ - } else if(!strncmp(name, "local:", 6)) { - ret = socket_local_client(name + 6, - ANDROID_SOCKET_NAMESPACE_RESERVED, SOCK_STREAM); - } else if(!strncmp(name, "localreserved:", 14)) { - ret = socket_local_client(name + 14, - ANDROID_SOCKET_NAMESPACE_RESERVED, SOCK_STREAM); - } else if(!strncmp(name, "localabstract:", 14)) { - ret = socket_local_client(name + 14, - ANDROID_SOCKET_NAMESPACE_ABSTRACT, SOCK_STREAM); - } else if(!strncmp(name, "localfilesystem:", 16)) { - ret = socket_local_client(name + 16, - ANDROID_SOCKET_NAMESPACE_FILESYSTEM, SOCK_STREAM); -#endif -#if ADB_HOST - } else if(!strncmp("dns:", name, 4)){ - char *n = strdup(name + 4); - if(n == 0) return -1; - ret = create_service_thread(dns_service, n); -#else /* !ADB_HOST */ - } else if(!strncmp("dev:", name, 4)) { - ret = unix_open(name + 4, O_RDWR); - } else if(!strncmp(name, "framebuffer:", 12)) { - ret = create_service_thread(framebuffer_service, 0); - } else if(recovery_mode && !strncmp(name, "recover:", 8)) { - ret = create_service_thread(recover_service, (void*) atoi(name + 8)); - } else if (!strncmp(name, "jdwp:", 5)) { - ret = create_jdwp_connection_fd(atoi(name+5)); - } else if (!strncmp(name, "log:", 4)) { - ret = create_service_thread(log_service, get_log_file_path(name + 4)); -#endif - } else if(!HOST && !strncmp(name, "shell:", 6)) { - if(name[6]) { - ret = create_subprocess(SHELL_COMMAND, "-c", name + 6); - } else { - ret = create_subprocess(SHELL_COMMAND, "-", 0); - } -#if !ADB_HOST - } else if(!strncmp(name, "sync:", 5)) { - ret = create_service_thread(file_sync_service, NULL); - } else if(!strncmp(name, "remount:", 8)) { - ret = create_service_thread(remount_service, NULL); -#endif -#if 0 - } else if(!strncmp(name, "echo:", 5)){ - ret = create_service_thread(echo_service, 0); -#endif - } - if (ret >= 0) { - close_on_exec(ret); - } - return ret; -} - -#if ADB_HOST -struct state_info { - transport_type transport; - char* serial; - int state; -}; - -static void wait_for_state(int fd, void* cookie) -{ - struct state_info* sinfo = cookie; - char* err = "unknown error"; - - D("wait_for_state %d\n", sinfo->state); - - atransport *t = acquire_one_transport(sinfo->state, sinfo->transport, sinfo->serial, &err); - if(t != 0) { - writex(fd, "OKAY", 4); - } else { - sendfailmsg(fd, err); - } - - if (sinfo->serial) - free(sinfo->serial); - free(sinfo); - adb_close(fd); - D("wait_for_state is done\n"); -} -#endif - -#if ADB_HOST -asocket* host_service_to_socket(const char* name, const char *serial) -{ - if (!strcmp(name,"track-devices")) { - return create_device_tracker(); - } else if (!strncmp(name, "wait-for-", strlen("wait-for-"))) { - struct state_info* sinfo = malloc(sizeof(struct state_info)); - - if (serial) - sinfo->serial = strdup(serial); - else - sinfo->serial = NULL; - - name += strlen("wait-for-"); - - if (!strncmp(name, "local", strlen("local"))) { - sinfo->transport = kTransportLocal; - sinfo->state = CS_DEVICE; - } else if (!strncmp(name, "usb", strlen("usb"))) { - sinfo->transport = kTransportUsb; - sinfo->state = CS_DEVICE; - } else if (!strncmp(name, "any", strlen("any"))) { - sinfo->transport = kTransportAny; - sinfo->state = CS_DEVICE; - } else { - free(sinfo); - return NULL; - } - - int fd = create_service_thread(wait_for_state, sinfo); - return create_local_socket(fd); - } - return NULL; -} -#endif /* ADB_HOST */ diff --git a/adb/shlist.c b/adb/shlist.c deleted file mode 100755 index 44919ef0..00000000 --- a/adb/shlist.c +++ /dev/null @@ -1,185 +0,0 @@ -/*-------------------------------------------------------------------*/ -/* List Functionality */ -/*-------------------------------------------------------------------*/ -/* #define SH_LIST_DEBUG */ -/*-------------------------------------------------------------------*/ -#include <stdio.h> -#include <stdlib.h> -#include "shlist.h" -/*-------------------------------------------------------------------*/ -void shListInitList( SHLIST *listPtr ) -{ - listPtr->data = (void *)0L; - listPtr->next = listPtr; - listPtr->prev = listPtr; -} - -SHLIST *shListFindItem( SHLIST *head, void *val, shListEqual func ) -{ - SHLIST *item; - - for(item=head->next;( item != head );item=item->next) - if( func ) { - if( func( val, item->data ) ) { - return( item ); - } - } - else { - if( item->data == val ) { - return( item ); - } - } - return( NULL ); -} - -SHLIST *shListGetLastItem( SHLIST *head ) -{ - if( head->prev != head ) - return( head->prev ); - return( NULL ); -} - -SHLIST *shListGetFirstItem( SHLIST *head ) -{ - if( head->next != head ) - return( head->next ); - return( NULL ); -} - -SHLIST *shListGetNItem( SHLIST *head, unsigned long num ) -{ - SHLIST *item; - unsigned long i; - - for(i=0,item=head->next;( (i < num) && (item != head) );i++,item=item->next); - if( item != head ) - return( item ); - return( NULL ); -} - -SHLIST *shListGetNextItem( SHLIST *head, SHLIST *item ) -{ - if( item == NULL ) - return( NULL ); - if( item->next != head ) - return( item->next ); - return( NULL ); -} - -SHLIST *shListGetPrevItem( SHLIST *head, SHLIST *item ) -{ - if( item == NULL ) - return( NULL ); - if( item->prev != head ) - return( item->prev ); - return( NULL ); -} - -void shListDelItem( SHLIST *head, SHLIST *item, shListFree func ) -{ - if( item == NULL ) - return; -#ifdef SH_LIST_DEBUG - fprintf(stderr, "Del %lx\n", (unsigned long)(item->data)); -#endif - (item->prev)->next = item->next; - (item->next)->prev = item->prev; - if( func && item->data ) { - func( (void *)(item->data) ); - } - free( item ); - head->data = (void *)((unsigned long)(head->data) - 1); -} - -void shListInsFirstItem( SHLIST *head, void *val ) -{ /* Insert to the beginning of the list */ - SHLIST *item; - - item = (SHLIST *)malloc( sizeof(SHLIST) ); - if( item == NULL ) - return; - item->data = val; - item->next = head->next; - item->prev = head; - (head->next)->prev = item; - head->next = item; -#ifdef SH_LIST_DEBUG - fprintf(stderr, "Ins First %lx\n", (unsigned long)(item->data)); -#endif - head->data = (void *)((unsigned long)(head->data) + 1); -} - -void shListInsLastItem( SHLIST *head, void *val ) -{ /* Insert to the end of the list */ - SHLIST *item; - - item = (SHLIST *)malloc( sizeof(SHLIST) ); - if( item == NULL ) - return; - item->data = val; - item->next = head; - item->prev = head->prev; - (head->prev)->next = item; - head->prev = item; -#ifdef SH_LIST_DEBUG - fprintf(stderr, "Ins Last %lx\n", (unsigned long)(item->data)); -#endif - head->data = (void *)((unsigned long)(head->data) + 1); -} - -void shListInsBeforeItem( SHLIST *head, void *val, void *etal, - shListCmp func ) -{ - SHLIST *item, *iptr; - - if( func == NULL ) - shListInsFirstItem( head, val ); - else { - item = (SHLIST *)malloc( sizeof(SHLIST) ); - if( item == NULL ) - return; - item->data = val; - for(iptr=head->next;( iptr != head );iptr=iptr->next) - if( func( val, iptr->data, etal ) ) - break; - item->next = iptr; - item->prev = iptr->prev; - (iptr->prev)->next = item; - iptr->prev = item; -#ifdef SH_LIST_DEBUG - fprintf(stderr, "Ins Before %lx\n", (unsigned long)(item->data)); -#endif - head->data = (void *)((unsigned long)(head->data) + 1); - } -} - -void shListDelAllItems( SHLIST *head, shListFree func ) -{ - SHLIST *item; - - for(item=head->next;( item != head );) { - shListDelItem( head, item, func ); - item = head->next; - } - head->data = (void *)0L; -} - -void shListPrintAllItems( SHLIST *head, shListPrint func ) -{ -#ifdef SH_LIST_DEBUG - SHLIST *item; - - for(item=head->next;( item != head );item=item->next) - if( func ) { - func(item->data); - } - else { - fprintf(stderr, "Item: %lx\n",(unsigned long)(item->data)); - } -#endif -} - -unsigned long shListGetCount( SHLIST *head ) -{ - return( (unsigned long)(head->data) ); -} diff --git a/adb/shlist.h b/adb/shlist.h deleted file mode 100755 index 0a9b07b2..00000000 --- a/adb/shlist.h +++ /dev/null @@ -1,34 +0,0 @@ -/*-------------------------------------------------------------------*/ -/* List Functionality */ -/*-------------------------------------------------------------------*/ -#ifndef _SHLIST_H_ -#define _SHLIST_H_ - -typedef struct SHLIST_STRUC { - void *data; - struct SHLIST_STRUC *next; - struct SHLIST_STRUC *prev; -} SHLIST; - -typedef int (*shListCmp)( void *valo, void *valn, void *etalon ); -typedef int (*shListPrint)( void *val ); -typedef void (*shListFree)( void *val ); -typedef int (*shListEqual)( void *val, void *idata ); - -void shListInitList( SHLIST *listPtr ); -SHLIST *shListFindItem( SHLIST *head, void *val, shListEqual func ); -SHLIST *shListGetFirstItem( SHLIST *head ); -SHLIST *shListGetNItem( SHLIST *head, unsigned long num ); -SHLIST *shListGetLastItem( SHLIST *head ); -SHLIST *shListGetNextItem( SHLIST *head, SHLIST *item ); -SHLIST *shListGetPrevItem( SHLIST *head, SHLIST *item ); -void shListDelItem( SHLIST *head, SHLIST *item, shListFree func ); -void shListInsFirstItem( SHLIST *head, void *val ); -void shListInsBeforeItem( SHLIST *head, void *val, void *etalon, - shListCmp func ); -void shListInsLastItem( SHLIST *head, void *val ); -void shListDelAllItems( SHLIST *head, shListFree func ); -void shListPrintAllItems( SHLIST *head, shListPrint func ); -unsigned long shListGetCount( SHLIST *head ); - -#endif diff --git a/adb/sockets.c b/adb/sockets.c deleted file mode 100644 index 9f1b5987..00000000 --- a/adb/sockets.c +++ /dev/null @@ -1,787 +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 && !result; s = s->next) { - if(s->id == id) result = s; - } - 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; - - /* 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) -{ - if(s->peer) { - 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); - } - - /* 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); - insert_local_socket(s, &local_socket_closing_list); -} - -static void local_socket_event_func(int fd, unsigned ev, void *_s) -{ - asocket *s = _s; - - /* 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; - } - 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) { - 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); - 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; - } - - if((avail == MAX_PAYLOAD) || (s->peer == 0)) { - put_apacket(p); - } else { - p->len = MAX_PAYLOAD - avail; - - r = s->peer->enqueue(s->peer, p); - - 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); - } - } - - if(is_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); - return; - } -} - -asocket *create_local_socket(int fd) -{ - asocket *s = calloc(1, sizeof(asocket)); - if(s == 0) fatal("cannot allocate socket"); - install_local_socket(s); - s->fd = fd; - s->enqueue = local_socket_enqueue; - s->ready = local_socket_ready; - s->close = local_socket_close; - - 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; - -#if !ADB_HOST - if (!strcmp(name,"jdwp")) { - return create_jdwp_service_socket(); - } - if (!strcmp(name,"track-jdwp")) { - return create_jdwp_tracker_service_socket(); - } -#endif - fd = service_to_fd(name); - if(fd < 0) return 0; - - s = create_local_socket(fd); - D("LS(%d): bound to '%s'\n", s->id, name); - return s; -} - -#if ADB_HOST -static asocket *create_host_service_socket(const char *name, const char* serial) -{ - asocket *s; - - s = host_service_to_socket(name, serial); - - if (s != NULL) { - D("LS(%d) bound to '%s'\n", s->id, name); - return s; - } - - return s; -} -#endif /* ADB_HOST */ - -/* 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("Calling remote_socket_enqueue\n"); - 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("Calling remote_socket_ready\n"); - 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("Calling remote_socket_close\n"); - apacket *p = get_apacket(); - p->msg.command = A_CLSE; - if(s->peer) { - p->msg.arg0 = s->peer->id; - s->peer->peer = 0; - 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 == 0) 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 \n"); - 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; -} - -static int smart_socket_enqueue(asocket *s, apacket *p) -{ - unsigned len; -#if ADB_HOST - char *service = NULL; - char* serial = NULL; - transport_type ttype = kTransportAny; -#endif - - 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 ADB_HOST - service = (char *)p->data + 4; - if(!strncmp(service, "host-serial:", strlen("host-serial:"))) { - char* serial_end; - service += strlen("host-serial:"); - - // serial number should follow "host:" - serial_end = strchr(service, ':'); - if (serial_end) { - *serial_end = 0; // terminate string - serial = service; - service = serial_end + 1; - } - } else if (!strncmp(service, "host-usb:", strlen("host-usb:"))) { - ttype = kTransportUsb; - service += strlen("host-usb:"); - } else if (!strncmp(service, "host-local:", strlen("host-local:"))) { - ttype = kTransportLocal; - service += strlen("host-local:"); - } else if (!strncmp(service, "host:", strlen("host:"))) { - ttype = kTransportAny; - service += strlen("host:"); - } else { - service = NULL; - } - - if (service) { - asocket *s2; - - /* some requests are handled immediately -- in that - ** case the handle_host_request() routine has sent - ** the OKAY or FAIL message and all we have to do - ** is clean up. - */ - if(handle_host_request(service, ttype, serial, s->peer->fd, s) == 0) { - /* XXX fail message? */ - D( "SS(%d): handled host service '%s'\n", s->id, service ); - goto fail; - } - if (!strncmp(service, "transport", strlen("transport"))) { - D( "SS(%d): okay transport\n", s->id ); - p->len = 0; - return 0; - } - - /* try to find a local service with this name. - ** if no such service exists, we'll fail out - ** and tear down here. - */ - s2 = create_host_service_socket(service, serial); - if(s2 == 0) { - D( "SS(%d): couldn't create host service '%s'\n", s->id, service ); - sendfailmsg(s->peer->fd, "unknown host service"); - goto fail; - } - - /* we've connected to a local host service, - ** so we make our peer back into a regular - ** local socket and bind it to the new local - ** service socket, acknowledge the successful - ** connection, and close this smart socket now - ** that its work is done. - */ - adb_write(s->peer->fd, "OKAY", 4); - - s->peer->ready = local_socket_ready; - s->peer->close = local_socket_close; - s->peer->peer = s2; - s2->peer = s->peer; - s->peer = 0; - D( "SS(%d): okay\n", s->id ); - s->close(s); - - /* initial state is "ready" */ - s2->ready(s2); - return 0; - } -#else /* !ADB_HOST */ - 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; - } - } -#endif - - 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); - } - 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 == 0) fatal("cannot allocate socket"); - s->id = 0; - 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/adb/sockets.dia b/adb/sockets.dia Binary files differdeleted file mode 100644 index c626f20f..00000000 --- a/adb/sockets.dia +++ /dev/null diff --git a/adb/sysdeps.h b/adb/sysdeps.h deleted file mode 100644 index e5d17a85..00000000 --- a/adb/sysdeps.h +++ /dev/null @@ -1,473 +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 */ -#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_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 <cutils/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; - 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 <cutils/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) static 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 - -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_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_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_creat(const char* path, int mode) -{ - int fd = creat(path, mode); - - if ( fd < 0 ) - return -1; - - close_on_exec(fd); - return fd; -} -#undef creat -#define creat ___xxx_creat - -static __inline__ int adb_socket_accept(int serverfd, struct sockaddr* addr, socklen_t *addrlen) -{ - return accept( serverfd, addr, addrlen ); -} - -#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/adb/sysdeps_win32.c b/adb/sysdeps_win32.c deleted file mode 100644 index c2a9a985..00000000 --- a/adb/sysdeps_win32.c +++ /dev/null @@ -1,1953 +0,0 @@ -#include "sysdeps.h" -#include <windows.h> -#include <winsock2.h> -#include <stdio.h> -#include <errno.h> -#define TRACE_TAG TRACE_SYSDEPS -#include "adb.h" - -extern void fatal(const char *fmt, ...); - -#define assert(cond) do { if (!(cond)) fatal( "assertion failed '%s' on %s:%ld\n", #cond, __FILE__, __LINE__ ); } while (0) - -/**************************************************************************/ -/**************************************************************************/ -/***** *****/ -/***** replaces libs/cutils/load_file.c *****/ -/***** *****/ -/**************************************************************************/ -/**************************************************************************/ - -void *load_file(const char *fn, unsigned *_sz) -{ - HANDLE file; - char *data; - DWORD file_size; - - file = CreateFile( fn, - GENERIC_READ, - FILE_SHARE_READ, - NULL, - OPEN_EXISTING, - 0, - NULL ); - - if (file == INVALID_HANDLE_VALUE) - return NULL; - - file_size = GetFileSize( file, NULL ); - data = NULL; - - if (file_size > 0) { - data = (char*) malloc( file_size + 1 ); - if (data == NULL) { - D("load_file: could not allocate %ld bytes\n", file_size ); - file_size = 0; - } else { - DWORD out_bytes; - - if ( !ReadFile( file, data, file_size, &out_bytes, NULL ) || - out_bytes != file_size ) - { - D("load_file: could not read %ld bytes from '%s'\n", file_size, fn); - free(data); - data = NULL; - file_size = 0; - } - } - } - CloseHandle( file ); - - *_sz = (unsigned) file_size; - return data; -} - -/**************************************************************************/ -/**************************************************************************/ -/***** *****/ -/***** common file descriptor handling *****/ -/***** *****/ -/**************************************************************************/ -/**************************************************************************/ - -typedef const struct FHClassRec_* FHClass; - -typedef struct FHRec_* FH; - -typedef struct EventHookRec_* EventHook; - -typedef struct FHClassRec_ -{ - void (*_fh_init) ( FH f ); - int (*_fh_close)( FH f ); - int (*_fh_lseek)( FH f, int pos, int origin ); - int (*_fh_read) ( FH f, void* buf, int len ); - int (*_fh_write)( FH f, const void* buf, int len ); - void (*_fh_hook) ( FH f, int events, EventHook hook ); - -} FHClassRec; - -/* used to emulate unix-domain socket pairs */ -typedef struct SocketPairRec_* SocketPair; - -typedef struct FHRec_ -{ - FHClass clazz; - int used; - int eof; - union { - HANDLE handle; - SOCKET socket; - SocketPair pair; - } u; - - HANDLE event; - int mask; - - char name[32]; - -} FHRec; - -#define fh_handle u.handle -#define fh_socket u.socket -#define fh_pair u.pair - -#define WIN32_FH_BASE 100 - -#define WIN32_MAX_FHS 128 - -static adb_mutex_t _win32_lock; -static FHRec _win32_fhs[ WIN32_MAX_FHS ]; -static int _win32_fh_count; - -static FH -_fh_from_int( int fd ) -{ - FH f; - - fd -= WIN32_FH_BASE; - - if (fd < 0 || fd >= _win32_fh_count) { - D( "_fh_from_int: invalid fd %d\n", fd + WIN32_FH_BASE ); - errno = EBADF; - return NULL; - } - - f = &_win32_fhs[fd]; - - if (f->used == 0) { - D( "_fh_from_int: invalid fd %d\n", fd + WIN32_FH_BASE ); - errno = EBADF; - return NULL; - } - - return f; -} - - -static int -_fh_to_int( FH f ) -{ - if (f && f->used && f >= _win32_fhs && f < _win32_fhs + WIN32_MAX_FHS) - return (int)(f - _win32_fhs) + WIN32_FH_BASE; - - return -1; -} - -static FH -_fh_alloc( FHClass clazz ) -{ - int nn; - FH f = NULL; - - adb_mutex_lock( &_win32_lock ); - - if (_win32_fh_count < WIN32_MAX_FHS) { - f = &_win32_fhs[ _win32_fh_count++ ]; - goto Exit; - } - - for (nn = 0; nn < WIN32_MAX_FHS; nn++) { - if ( _win32_fhs[nn].clazz == NULL) { - f = &_win32_fhs[nn]; - goto Exit; - } - } - D( "_fh_alloc: no more free file descriptors\n" ); -Exit: - if (f) { - f->clazz = clazz; - f->used = 1; - f->eof = 0; - clazz->_fh_init(f); - } - adb_mutex_unlock( &_win32_lock ); - return f; -} - - -static int -_fh_close( FH f ) -{ - if ( f->used ) { - f->clazz->_fh_close( f ); - f->used = 0; - f->eof = 0; - f->clazz = NULL; - } - return 0; -} - -/* forward definitions */ -static const FHClassRec _fh_file_class; -static const FHClassRec _fh_socket_class; - -/**************************************************************************/ -/**************************************************************************/ -/***** *****/ -/***** file-based descriptor handling *****/ -/***** *****/ -/**************************************************************************/ -/**************************************************************************/ - -static void -_fh_file_init( FH f ) -{ - f->fh_handle = INVALID_HANDLE_VALUE; -} - -static int -_fh_file_close( FH f ) -{ - CloseHandle( f->fh_handle ); - f->fh_handle = INVALID_HANDLE_VALUE; - return 0; -} - -static int -_fh_file_read( FH f, void* buf, int len ) -{ - DWORD read_bytes; - - if ( !ReadFile( f->fh_handle, buf, (DWORD)len, &read_bytes, NULL ) ) { - D( "adb_read: could not read %d bytes from %s\n", len, f->name ); - errno = EIO; - return -1; - } else if (read_bytes < (DWORD)len) { - f->eof = 1; - } - return (int)read_bytes; -} - -static int -_fh_file_write( FH f, const void* buf, int len ) -{ - DWORD wrote_bytes; - - if ( !WriteFile( f->fh_handle, buf, (DWORD)len, &wrote_bytes, NULL ) ) { - D( "adb_file_write: could not write %d bytes from %s\n", len, f->name ); - errno = EIO; - return -1; - } else if (wrote_bytes < (DWORD)len) { - f->eof = 1; - } - return (int)wrote_bytes; -} - -static int -_fh_file_lseek( FH f, int pos, int origin ) -{ - DWORD method; - DWORD result; - - switch (origin) - { - case SEEK_SET: method = FILE_BEGIN; break; - case SEEK_CUR: method = FILE_CURRENT; break; - case SEEK_END: method = FILE_END; break; - default: - errno = EINVAL; - return -1; - } - - result = SetFilePointer( f->fh_handle, pos, NULL, method ); - if (result == INVALID_SET_FILE_POINTER) { - errno = EIO; - return -1; - } else { - f->eof = 0; - } - return (int)result; -} - -static void _fh_file_hook( FH f, int event, EventHook eventhook ); /* forward */ - -static const FHClassRec _fh_file_class = -{ - _fh_file_init, - _fh_file_close, - _fh_file_lseek, - _fh_file_read, - _fh_file_write, - _fh_file_hook -}; - -/**************************************************************************/ -/**************************************************************************/ -/***** *****/ -/***** file-based descriptor handling *****/ -/***** *****/ -/**************************************************************************/ -/**************************************************************************/ - -int adb_open(const char* path, int options) -{ - FH f; - - DWORD desiredAccess = 0; - DWORD shareMode = FILE_SHARE_READ | FILE_SHARE_WRITE; - - switch (options) { - case O_RDONLY: - desiredAccess = GENERIC_READ; - break; - case O_WRONLY: - desiredAccess = GENERIC_WRITE; - break; - case O_RDWR: - desiredAccess = GENERIC_READ | GENERIC_WRITE; - break; - default: - D("adb_open: invalid options (0x%0x)\n", options); - errno = EINVAL; - return -1; - } - - f = _fh_alloc( &_fh_file_class ); - if ( !f ) { - errno = ENOMEM; - return -1; - } - - f->fh_handle = CreateFile( path, desiredAccess, shareMode, NULL, OPEN_EXISTING, - 0, NULL ); - - if ( f->fh_handle == INVALID_HANDLE_VALUE ) { - _fh_close(f); - D( "adb_open: could not open '%s':", path ); - switch (GetLastError()) { - case ERROR_FILE_NOT_FOUND: - D( "file not found\n" ); - errno = ENOENT; - return -1; - - case ERROR_PATH_NOT_FOUND: - D( "path not found\n" ); - errno = ENOTDIR; - return -1; - - default: - D( "unknown error\n" ); - errno = ENOENT; - return -1; - } - } - - snprintf( f->name, sizeof(f->name), "%d(%s)", _fh_to_int(f), path ); - D( "adb_open: '%s' => fd %d\n", path, _fh_to_int(f) ); - return _fh_to_int(f); -} - -/* ignore mode on Win32 */ -int adb_creat(const char* path, int mode) -{ - FH f; - - f = _fh_alloc( &_fh_file_class ); - if ( !f ) { - errno = ENOMEM; - return -1; - } - - f->fh_handle = CreateFile( path, GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, - NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, - NULL ); - - if ( f->fh_handle == INVALID_HANDLE_VALUE ) { - _fh_close(f); - D( "adb_creat: could not open '%s':", path ); - switch (GetLastError()) { - case ERROR_FILE_NOT_FOUND: - D( "file not found\n" ); - errno = ENOENT; - return -1; - - case ERROR_PATH_NOT_FOUND: - D( "path not found\n" ); - errno = ENOTDIR; - return -1; - - default: - D( "unknown error\n" ); - errno = ENOENT; - return -1; - } - } - snprintf( f->name, sizeof(f->name), "%d(%s)", _fh_to_int(f), path ); - D( "adb_creat: '%s' => fd %d\n", path, _fh_to_int(f) ); - return _fh_to_int(f); -} - - -int adb_read(int fd, void* buf, int len) -{ - FH f = _fh_from_int(fd); - - if (f == NULL) { - return -1; - } - - return f->clazz->_fh_read( f, buf, len ); -} - - -int adb_write(int fd, const void* buf, int len) -{ - FH f = _fh_from_int(fd); - - if (f == NULL) { - return -1; - } - - return f->clazz->_fh_write(f, buf, len); -} - - -int adb_lseek(int fd, int pos, int where) -{ - FH f = _fh_from_int(fd); - - if (!f) { - return -1; - } - - return f->clazz->_fh_lseek(f, pos, where); -} - - -int adb_close(int fd) -{ - FH f = _fh_from_int(fd); - - if (!f) { - return -1; - } - - D( "adb_close: %s\n", f->name); - _fh_close(f); - return 0; -} - -/**************************************************************************/ -/**************************************************************************/ -/***** *****/ -/***** socket-based file descriptors *****/ -/***** *****/ -/**************************************************************************/ -/**************************************************************************/ - -static void -_socket_set_errno( void ) -{ - switch (WSAGetLastError()) { - case 0: errno = 0; break; - case WSAEWOULDBLOCK: errno = EAGAIN; break; - case WSAEINTR: errno = EINTR; break; - default: - D( "_socket_set_errno: unhandled value %d\n", WSAGetLastError() ); - errno = EINVAL; - } -} - -static void -_fh_socket_init( FH f ) -{ - f->fh_socket = INVALID_SOCKET; - f->event = WSACreateEvent(); - f->mask = 0; -} - -static int -_fh_socket_close( FH f ) -{ - /* gently tell any peer that we're closing the socket */ - shutdown( f->fh_socket, SD_BOTH ); - closesocket( f->fh_socket ); - f->fh_socket = INVALID_SOCKET; - CloseHandle( f->event ); - f->mask = 0; - return 0; -} - -static int -_fh_socket_lseek( FH f, int pos, int origin ) -{ - errno = EPIPE; - return -1; -} - -static int -_fh_socket_read( FH f, void* buf, int len ) -{ - int result = recv( f->fh_socket, buf, len, 0 ); - if (result == SOCKET_ERROR) { - _socket_set_errno(); - result = -1; - } - return result; -} - -static int -_fh_socket_write( FH f, const void* buf, int len ) -{ - int result = send( f->fh_socket, buf, len, 0 ); - if (result == SOCKET_ERROR) { - _socket_set_errno(); - result = -1; - } - return result; -} - -static void _fh_socket_hook( FH f, int event, EventHook hook ); /* forward */ - -static const FHClassRec _fh_socket_class = -{ - _fh_socket_init, - _fh_socket_close, - _fh_socket_lseek, - _fh_socket_read, - _fh_socket_write, - _fh_socket_hook -}; - -/**************************************************************************/ -/**************************************************************************/ -/***** *****/ -/***** replacement for libs/cutils/socket_xxxx.c *****/ -/***** *****/ -/**************************************************************************/ -/**************************************************************************/ - -#include <winsock2.h> - -static int _winsock_init; - -static void -_cleanup_winsock( void ) -{ - WSACleanup(); -} - -static void -_init_winsock( void ) -{ - if (!_winsock_init) { - WSADATA wsaData; - int rc = WSAStartup( MAKEWORD(2,2), &wsaData); - if (rc != 0) { - fatal( "adb: could not initialize Winsock\n" ); - } - atexit( _cleanup_winsock ); - _winsock_init = 1; - } -} - -int socket_loopback_client(int port, int type) -{ - FH f = _fh_alloc( &_fh_socket_class ); - struct sockaddr_in addr; - SOCKET s; - - if (!f) - return -1; - - if (!_winsock_init) - _init_winsock(); - - memset(&addr, 0, sizeof(addr)); - addr.sin_family = AF_INET; - addr.sin_port = htons(port); - addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); - - s = socket(AF_INET, type, 0); - if(s == INVALID_SOCKET) { - D("socket_loopback_client: could not create socket\n" ); - _fh_close(f); - return -1; - } - - f->fh_socket = s; - if(connect(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) { - D("socket_loopback_client: could not connect to %s:%d\n", type != SOCK_STREAM ? "udp" : "tcp", port ); - _fh_close(f); - return -1; - } - snprintf( f->name, sizeof(f->name), "%d(lo-client:%s%d)", _fh_to_int(f), type != SOCK_STREAM ? "udp:" : "", port ); - D( "socket_loopback_client: port %d type %s => fd %d\n", port, type != SOCK_STREAM ? "udp" : "tcp", _fh_to_int(f) ); - return _fh_to_int(f); -} - -#define LISTEN_BACKLOG 4 - -int socket_loopback_server(int port, int type) -{ - FH f = _fh_alloc( &_fh_socket_class ); - struct sockaddr_in addr; - SOCKET s; - int n; - - if (!f) { - return -1; - } - - if (!_winsock_init) - _init_winsock(); - - memset(&addr, 0, sizeof(addr)); - addr.sin_family = AF_INET; - addr.sin_port = htons(port); - addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); - - s = socket(AF_INET, type, 0); - if(s == INVALID_SOCKET) return -1; - - f->fh_socket = s; - - n = 1; - setsockopt(s, SOL_SOCKET, SO_EXCLUSIVEADDRUSE, (const char*)&n, sizeof(n)); - - if(bind(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) { - _fh_close(f); - return -1; - } - if (type == SOCK_STREAM) { - int ret; - - ret = listen(s, LISTEN_BACKLOG); - if (ret < 0) { - _fh_close(f); - return -1; - } - } - snprintf( f->name, sizeof(f->name), "%d(lo-server:%s%d)", _fh_to_int(f), type != SOCK_STREAM ? "udp:" : "", port ); - D( "socket_loopback_server: port %d type %s => fd %d\n", port, type != SOCK_STREAM ? "udp" : "tcp", _fh_to_int(f) ); - return _fh_to_int(f); -} - - -int socket_network_client(const char *host, int port, int type) -{ - FH f = _fh_alloc( &_fh_socket_class ); - struct hostent *hp; - struct sockaddr_in addr; - SOCKET s; - - if (!f) - return -1; - - if (!_winsock_init) - _init_winsock(); - - hp = gethostbyname(host); - if(hp == 0) { - _fh_close(f); - return -1; - } - - memset(&addr, 0, sizeof(addr)); - addr.sin_family = hp->h_addrtype; - addr.sin_port = htons(port); - memcpy(&addr.sin_addr, hp->h_addr, hp->h_length); - - s = socket(hp->h_addrtype, type, 0); - if(s == INVALID_SOCKET) { - _fh_close(f); - return -1; - } - f->fh_socket = s; - - if(connect(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) { - _fh_close(f); - return -1; - } - - snprintf( f->name, sizeof(f->name), "%d(net-client:%s%d)", _fh_to_int(f), type != SOCK_STREAM ? "udp:" : "", port ); - D( "socket_network_client: host '%s' port %d type %s => fd %d\n", host, port, type != SOCK_STREAM ? "udp" : "tcp", _fh_to_int(f) ); - return _fh_to_int(f); -} - - -int socket_inaddr_any_server(int port, int type) -{ - FH f = _fh_alloc( &_fh_socket_class ); - struct sockaddr_in addr; - SOCKET s; - int n; - - if (!f) - return -1; - - if (!_winsock_init) - _init_winsock(); - - memset(&addr, 0, sizeof(addr)); - addr.sin_family = AF_INET; - addr.sin_port = htons(port); - addr.sin_addr.s_addr = htonl(INADDR_ANY); - - s = socket(AF_INET, type, 0); - if(s == INVALID_SOCKET) { - _fh_close(f); - return -1; - } - - f->fh_socket = s; - n = 1; - setsockopt(s, SOL_SOCKET, SO_EXCLUSIVEADDRUSE, (const char*)&n, sizeof(n)); - - if(bind(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) { - _fh_close(f); - return -1; - } - - if (type == SOCK_STREAM) { - int ret; - - ret = listen(s, LISTEN_BACKLOG); - if (ret < 0) { - _fh_close(f); - return -1; - } - } - snprintf( f->name, sizeof(f->name), "%d(any-server:%s%d)", _fh_to_int(f), type != SOCK_STREAM ? "udp:" : "", port ); - D( "socket_inaddr_server: port %d type %s => fd %d\n", port, type != SOCK_STREAM ? "udp" : "tcp", _fh_to_int(f) ); - return _fh_to_int(f); -} - -#undef accept -int adb_socket_accept(int serverfd, struct sockaddr* addr, socklen_t *addrlen) -{ - FH serverfh = _fh_from_int(serverfd); - FH fh; - - if ( !serverfh || serverfh->clazz != &_fh_socket_class ) { - D( "adb_socket_accept: invalid fd %d\n", serverfd ); - return -1; - } - - fh = _fh_alloc( &_fh_socket_class ); - if (!fh) { - D( "adb_socket_accept: not enough memory to allocate accepted socket descriptor\n" ); - return -1; - } - - fh->fh_socket = accept( serverfh->fh_socket, addr, addrlen ); - if (fh->fh_socket == INVALID_SOCKET) { - _fh_close( fh ); - D( "adb_socket_accept: accept on fd %d return error %ld\n", serverfd, GetLastError() ); - return -1; - } - - snprintf( fh->name, sizeof(fh->name), "%d(accept:%s)", _fh_to_int(fh), serverfh->name ); - D( "adb_socket_accept on fd %d returns fd %d\n", serverfd, _fh_to_int(fh) ); - return _fh_to_int(fh); -} - - -void disable_tcp_nagle(int fd) -{ - FH fh = _fh_from_int(fd); - int on; - - if ( !fh || fh->clazz != &_fh_socket_class ) - return; - - setsockopt( fh->fh_socket, IPPROTO_TCP, TCP_NODELAY, (const char*)&on, sizeof(on) ); -} - -/**************************************************************************/ -/**************************************************************************/ -/***** *****/ -/***** emulated socketpairs *****/ -/***** *****/ -/**************************************************************************/ -/**************************************************************************/ - -/* we implement socketpairs directly in use space for the following reasons: - * - it avoids copying data from/to the Nt kernel - * - it allows us to implement fdevent hooks easily and cheaply, something - * that is not possible with standard Win32 pipes !! - * - * basically, we use two circular buffers, each one corresponding to a given - * direction. - * - * each buffer is implemented as two regions: - * - * region A which is (a_start,a_end) - * region B which is (0, b_end) with b_end <= a_start - * - * an empty buffer has: a_start = a_end = b_end = 0 - * - * a_start is the pointer where we start reading data - * a_end is the pointer where we start writing data, unless it is BUFFER_SIZE, - * then you start writing at b_end - * - * the buffer is full when b_end == a_start && a_end == BUFFER_SIZE - * - * there is room when b_end < a_start || a_end < BUFER_SIZE - * - * when reading, a_start is incremented, it a_start meets a_end, then - * we do: a_start = 0, a_end = b_end, b_end = 0, and keep going on.. - */ - -#define BIP_BUFFER_SIZE 4096 - -#if 0 -#include <stdio.h> -# define BIPD(x) D x -# define BIPDUMP bip_dump_hex - -static void bip_dump_hex( const unsigned char* ptr, size_t len ) -{ - int nn, len2 = len; - - if (len2 > 8) len2 = 8; - - for (nn = 0; nn < len2; nn++) - printf("%02x", ptr[nn]); - printf(" "); - - for (nn = 0; nn < len2; nn++) { - int c = ptr[nn]; - if (c < 32 || c > 127) - c = '.'; - printf("%c", c); - } - printf("\n"); - fflush(stdout); -} - -#else -# define BIPD(x) do {} while (0) -# define BIPDUMP(p,l) BIPD(p) -#endif - -typedef struct BipBufferRec_ -{ - int a_start; - int a_end; - int b_end; - int fdin; - int fdout; - int closed; - int can_write; /* boolean */ - HANDLE evt_write; /* event signaled when one can write to a buffer */ - int can_read; /* boolean */ - HANDLE evt_read; /* event signaled when one can read from a buffer */ - CRITICAL_SECTION lock; - unsigned char buff[ BIP_BUFFER_SIZE ]; - -} BipBufferRec, *BipBuffer; - -static void -bip_buffer_init( BipBuffer buffer ) -{ - D( "bit_buffer_init %p\n", buffer ); - buffer->a_start = 0; - buffer->a_end = 0; - buffer->b_end = 0; - buffer->can_write = 1; - buffer->can_read = 0; - buffer->fdin = 0; - buffer->fdout = 0; - buffer->closed = 0; - buffer->evt_write = CreateEvent( NULL, TRUE, TRUE, NULL ); - buffer->evt_read = CreateEvent( NULL, TRUE, FALSE, NULL ); - InitializeCriticalSection( &buffer->lock ); -} - -static void -bip_buffer_close( BipBuffer bip ) -{ - bip->closed = 1; - - if (!bip->can_read) { - SetEvent( bip->evt_read ); - } - if (!bip->can_write) { - SetEvent( bip->evt_write ); - } -} - -static void -bip_buffer_done( BipBuffer bip ) -{ - BIPD(( "bip_buffer_done: %d->%d\n", bip->fdin, bip->fdout )); - CloseHandle( bip->evt_read ); - CloseHandle( bip->evt_write ); - DeleteCriticalSection( &bip->lock ); -} - -static int -bip_buffer_write( BipBuffer bip, const void* src, int len ) -{ - int avail, count = 0; - - if (len <= 0) - return 0; - - BIPD(( "bip_buffer_write: enter %d->%d len %d\n", bip->fdin, bip->fdout, len )); - BIPDUMP( src, len ); - - EnterCriticalSection( &bip->lock ); - - while (!bip->can_write) { - int ret; - LeaveCriticalSection( &bip->lock ); - - if (bip->closed) { - errno = EPIPE; - return -1; - } - /* spinlocking here is probably unfair, but let's live with it */ - ret = WaitForSingleObject( bip->evt_write, INFINITE ); - if (ret != WAIT_OBJECT_0) { /* buffer probably closed */ - D( "bip_buffer_write: error %d->%d WaitForSingleObject returned %d, error %ld\n", bip->fdin, bip->fdout, ret, GetLastError() ); - return 0; - } - if (bip->closed) { - errno = EPIPE; - return -1; - } - EnterCriticalSection( &bip->lock ); - } - - BIPD(( "bip_buffer_write: exec %d->%d len %d\n", bip->fdin, bip->fdout, len )); - - avail = BIP_BUFFER_SIZE - bip->a_end; - if (avail > 0) - { - /* we can append to region A */ - if (avail > len) - avail = len; - - memcpy( bip->buff + bip->a_end, src, avail ); - src += avail; - count += avail; - len -= avail; - - bip->a_end += avail; - if (bip->a_end == BIP_BUFFER_SIZE && bip->a_start == 0) { - bip->can_write = 0; - ResetEvent( bip->evt_write ); - goto Exit; - } - } - - if (len == 0) - goto Exit; - - avail = bip->a_start - bip->b_end; - assert( avail > 0 ); /* since can_write is TRUE */ - - if (avail > len) - avail = len; - - memcpy( bip->buff + bip->b_end, src, avail ); - count += avail; - bip->b_end += avail; - - if (bip->b_end == bip->a_start) { - bip->can_write = 0; - ResetEvent( bip->evt_write ); - } - -Exit: - assert( count > 0 ); - - if ( !bip->can_read ) { - bip->can_read = 1; - SetEvent( bip->evt_read ); - } - - BIPD(( "bip_buffer_write: exit %d->%d count %d (as=%d ae=%d be=%d cw=%d cr=%d\n", - bip->fdin, bip->fdout, count, bip->a_start, bip->a_end, bip->b_end, bip->can_write, bip->can_read )); - LeaveCriticalSection( &bip->lock ); - - return count; - } - -static int -bip_buffer_read( BipBuffer bip, void* dst, int len ) -{ - int avail, count = 0; - - if (len <= 0) - return 0; - - BIPD(( "bip_buffer_read: enter %d->%d len %d\n", bip->fdin, bip->fdout, len )); - - EnterCriticalSection( &bip->lock ); - while ( !bip->can_read ) - { -#if 0 - LeaveCriticalSection( &bip->lock ); - errno = EAGAIN; - return -1; -#else - int ret; - LeaveCriticalSection( &bip->lock ); - - if (bip->closed) { - errno = EPIPE; - return -1; - } - - ret = WaitForSingleObject( bip->evt_read, INFINITE ); - if (ret != WAIT_OBJECT_0) { /* probably closed buffer */ - D( "bip_buffer_read: error %d->%d WaitForSingleObject returned %d, error %ld\n", bip->fdin, bip->fdout, ret, GetLastError()); - return 0; - } - if (bip->closed) { - errno = EPIPE; - return -1; - } - EnterCriticalSection( &bip->lock ); -#endif - } - - BIPD(( "bip_buffer_read: exec %d->%d len %d\n", bip->fdin, bip->fdout, len )); - - avail = bip->a_end - bip->a_start; - assert( avail > 0 ); /* since can_read is TRUE */ - - if (avail > len) - avail = len; - - memcpy( dst, bip->buff + bip->a_start, avail ); - dst += avail; - count += avail; - len -= avail; - - bip->a_start += avail; - if (bip->a_start < bip->a_end) - goto Exit; - - bip->a_start = 0; - bip->a_end = bip->b_end; - bip->b_end = 0; - - avail = bip->a_end; - if (avail > 0) { - if (avail > len) - avail = len; - memcpy( dst, bip->buff, avail ); - count += avail; - bip->a_start += avail; - - if ( bip->a_start < bip->a_end ) - goto Exit; - - bip->a_start = bip->a_end = 0; - } - - bip->can_read = 0; - ResetEvent( bip->evt_read ); - -Exit: - assert( count > 0 ); - - if (!bip->can_write ) { - bip->can_write = 1; - SetEvent( bip->evt_write ); - } - - BIPDUMP( (const unsigned char*)dst - count, count ); - BIPD(( "bip_buffer_read: exit %d->%d count %d (as=%d ae=%d be=%d cw=%d cr=%d\n", - bip->fdin, bip->fdout, count, bip->a_start, bip->a_end, bip->b_end, bip->can_write, bip->can_read )); - LeaveCriticalSection( &bip->lock ); - - return count; -} - -typedef struct SocketPairRec_ -{ - BipBufferRec a2b_bip; - BipBufferRec b2a_bip; - FH a_fd; - int used; - -} SocketPairRec; - -void _fh_socketpair_init( FH f ) -{ - f->fh_pair = NULL; -} - -static int -_fh_socketpair_close( FH f ) -{ - if ( f->fh_pair ) { - SocketPair pair = f->fh_pair; - - if ( f == pair->a_fd ) { - pair->a_fd = NULL; - } - - bip_buffer_close( &pair->b2a_bip ); - bip_buffer_close( &pair->a2b_bip ); - - if ( --pair->used == 0 ) { - bip_buffer_done( &pair->b2a_bip ); - bip_buffer_done( &pair->a2b_bip ); - free( pair ); - } - f->fh_pair = NULL; - } - return 0; -} - -static int -_fh_socketpair_lseek( FH f, int pos, int origin ) -{ - errno = ESPIPE; - return -1; -} - -static int -_fh_socketpair_read( FH f, void* buf, int len ) -{ - SocketPair pair = f->fh_pair; - BipBuffer bip; - - if (!pair) - return -1; - - if ( f == pair->a_fd ) - bip = &pair->b2a_bip; - else - bip = &pair->a2b_bip; - - return bip_buffer_read( bip, buf, len ); -} - -static int -_fh_socketpair_write( FH f, const void* buf, int len ) -{ - SocketPair pair = f->fh_pair; - BipBuffer bip; - - if (!pair) - return -1; - - if ( f == pair->a_fd ) - bip = &pair->a2b_bip; - else - bip = &pair->b2a_bip; - - return bip_buffer_write( bip, buf, len ); -} - - -static void _fh_socketpair_hook( FH f, int event, EventHook hook ); /* forward */ - -static const FHClassRec _fh_socketpair_class = -{ - _fh_socketpair_init, - _fh_socketpair_close, - _fh_socketpair_lseek, - _fh_socketpair_read, - _fh_socketpair_write, - _fh_socketpair_hook -}; - - -int adb_socketpair( int sv[2] ) -{ - FH fa, fb; - SocketPair pair; - - fa = _fh_alloc( &_fh_socketpair_class ); - fb = _fh_alloc( &_fh_socketpair_class ); - - if (!fa || !fb) - goto Fail; - - pair = malloc( sizeof(*pair) ); - if (pair == NULL) { - D("adb_socketpair: not enough memory to allocate pipes\n" ); - goto Fail; - } - - bip_buffer_init( &pair->a2b_bip ); - bip_buffer_init( &pair->b2a_bip ); - - fa->fh_pair = pair; - fb->fh_pair = pair; - pair->used = 2; - pair->a_fd = fa; - - sv[0] = _fh_to_int(fa); - sv[1] = _fh_to_int(fb); - - pair->a2b_bip.fdin = sv[0]; - pair->a2b_bip.fdout = sv[1]; - pair->b2a_bip.fdin = sv[1]; - pair->b2a_bip.fdout = sv[0]; - - snprintf( fa->name, sizeof(fa->name), "%d(pair:%d)", sv[0], sv[1] ); - snprintf( fb->name, sizeof(fb->name), "%d(pair:%d)", sv[1], sv[0] ); - D( "adb_socketpair: returns (%d, %d)\n", sv[0], sv[1] ); - return 0; - -Fail: - _fh_close(fb); - _fh_close(fa); - return -1; -} - -/**************************************************************************/ -/**************************************************************************/ -/***** *****/ -/***** fdevents emulation *****/ -/***** *****/ -/***** this is a very simple implementation, we rely on the fact *****/ -/***** that ADB doesn't use FDE_ERROR. *****/ -/***** *****/ -/**************************************************************************/ -/**************************************************************************/ - -#define FATAL(x...) fatal(__FUNCTION__, x) - -#if DEBUG -static void dump_fde(fdevent *fde, const char *info) -{ - 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); -} -#else -#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 fdevent list_pending = { - .next = &list_pending, - .prev = &list_pending, -}; - -static fdevent **fd_table = 0; -static int fd_table_max = 0; - -typedef struct EventLooperRec_* EventLooper; - -typedef struct EventHookRec_ -{ - EventHook next; - FH fh; - HANDLE h; - int wanted; /* wanted event flags */ - int ready; /* ready event flags */ - void* aux; - void (*prepare)( EventHook hook ); - int (*start) ( EventHook hook ); - void (*stop) ( EventHook hook ); - int (*check) ( EventHook hook ); - int (*peek) ( EventHook hook ); -} EventHookRec; - -static EventHook _free_hooks; - -static EventHook -event_hook_alloc( FH fh ) -{ - EventHook hook = _free_hooks; - if (hook != NULL) - _free_hooks = hook->next; - else { - hook = malloc( sizeof(*hook) ); - if (hook == NULL) - fatal( "could not allocate event hook\n" ); - } - hook->next = NULL; - hook->fh = fh; - hook->wanted = 0; - hook->ready = 0; - hook->h = INVALID_HANDLE_VALUE; - hook->aux = NULL; - - hook->prepare = NULL; - hook->start = NULL; - hook->stop = NULL; - hook->check = NULL; - hook->peek = NULL; - - return hook; -} - -static void -event_hook_free( EventHook hook ) -{ - hook->fh = NULL; - hook->wanted = 0; - hook->ready = 0; - hook->next = _free_hooks; - _free_hooks = hook; -} - - -static void -event_hook_signal( EventHook hook ) -{ - FH f = hook->fh; - int fd = _fh_to_int(f); - fdevent* fde = fd_table[ fd - WIN32_FH_BASE ]; - - if (fde != NULL && fde->fd == fd) { - if ((fde->state & FDE_PENDING) == 0) { - fde->state |= FDE_PENDING; - fdevent_plist_enqueue( fde ); - } - fde->events |= hook->wanted; - } -} - - -#define MAX_LOOPER_HANDLES WIN32_MAX_FHS - -typedef struct EventLooperRec_ -{ - EventHook hooks; - HANDLE htab[ MAX_LOOPER_HANDLES ]; - int htab_count; - -} EventLooperRec; - -static EventHook* -event_looper_find_p( EventLooper looper, FH fh ) -{ - EventHook *pnode = &looper->hooks; - EventHook node = *pnode; - for (;;) { - if ( node == NULL || node->fh == fh ) - break; - pnode = &node->next; - node = *pnode; - } - return pnode; -} - -static void -event_looper_hook( EventLooper looper, int fd, int events ) -{ - FH f = _fh_from_int(fd); - EventHook *pnode; - EventHook node; - - if (f == NULL) /* invalid arg */ { - D("event_looper_hook: invalid fd=%d\n", fd); - return; - } - - pnode = event_looper_find_p( looper, f ); - node = *pnode; - if ( node == NULL ) { - node = event_hook_alloc( f ); - node->next = *pnode; - *pnode = node; - } - - if ( (node->wanted & events) != events ) { - /* this should update start/stop/check/peek */ - D("event_looper_hook: call hook for %d (new=%x, old=%x)\n", - fd, node->wanted, events); - f->clazz->_fh_hook( f, events & ~node->wanted, node ); - node->wanted |= events; - } else { - D("event_looper_hook: ignoring events %x for %d wanted=%x)\n", - events, fd, node->wanted); - } -} - -static void -event_looper_unhook( EventLooper looper, int fd, int events ) -{ - FH fh = _fh_from_int(fd); - EventHook *pnode = event_looper_find_p( looper, fh ); - EventHook node = *pnode; - - if (node != NULL) { - int events2 = events & node->wanted; - if ( events2 == 0 ) { - D( "event_looper_unhook: events %x not registered for fd %d\n", events, fd ); - return; - } - node->wanted &= ~events2; - if (!node->wanted) { - *pnode = node->next; - event_hook_free( node ); - } - } -} - -static EventLooperRec win32_looper; - -static void fdevent_init(void) -{ - win32_looper.htab_count = 0; - win32_looper.hooks = NULL; -} - -static void fdevent_connect(fdevent *fde) -{ - EventLooper looper = &win32_looper; - int events = fde->state & FDE_EVENTMASK; - - if (events != 0) - event_looper_hook( looper, fde->fd, events ); -} - -static void fdevent_disconnect(fdevent *fde) -{ - EventLooper looper = &win32_looper; - int events = fde->state & FDE_EVENTMASK; - - if (events != 0) - event_looper_unhook( looper, fde->fd, events ); -} - -static void fdevent_update(fdevent *fde, unsigned events) -{ - EventLooper looper = &win32_looper; - unsigned events0 = fde->state & FDE_EVENTMASK; - - if (events != events0) { - int removes = events0 & ~events; - int adds = events & ~events0; - if (removes) { - D("fdevent_update: remove %x from %d\n", removes, fde->fd); - event_looper_unhook( looper, fde->fd, removes ); - } - if (adds) { - D("fdevent_update: add %x to %d\n", adds, fde->fd); - event_looper_hook ( looper, fde->fd, adds ); - } - } -} - -static void fdevent_process() -{ - EventLooper looper = &win32_looper; - EventHook hook; - int gotone = 0; - - /* if we have at least one ready hook, execute it/them */ - for (hook = looper->hooks; hook; hook = hook->next) { - hook->ready = 0; - if (hook->prepare) { - hook->prepare(hook); - if (hook->ready != 0) { - event_hook_signal( hook ); - gotone = 1; - } - } - } - - /* nothing's ready yet, so wait for something to happen */ - if (!gotone) - { - looper->htab_count = 0; - - for (hook = looper->hooks; hook; hook = hook->next) - { - if (hook->start && !hook->start(hook)) { - D( "fdevent_process: error when starting a hook\n" ); - return; - } - if (hook->h != INVALID_HANDLE_VALUE) { - int nn; - - for (nn = 0; nn < looper->htab_count; nn++) - { - if ( looper->htab[nn] == hook->h ) - goto DontAdd; - } - looper->htab[ looper->htab_count++ ] = hook->h; - DontAdd: - ; - } - } - - if (looper->htab_count == 0) { - D( "fdevent_process: nothing to wait for !!\n" ); - return; - } - - do - { - int wait_ret; - - D( "adb_win32: waiting for %d events\n", looper->htab_count ); - if (looper->htab_count > MAXIMUM_WAIT_OBJECTS) { - D("handle count %d exceeds MAXIMUM_WAIT_OBJECTS, aborting!\n", looper->htab_count); - abort(); - } - wait_ret = WaitForMultipleObjects( looper->htab_count, looper->htab, FALSE, INFINITE ); - if (wait_ret == (int)WAIT_FAILED) { - D( "adb_win32: wait failed, error %ld\n", GetLastError() ); - } else { - D( "adb_win32: got one (index %d)\n", wait_ret ); - - /* according to Cygwin, some objects like consoles wake up on "inappropriate" events - * like mouse movements. we need to filter these with the "check" function - */ - if ((unsigned)wait_ret < (unsigned)looper->htab_count) - { - for (hook = looper->hooks; hook; hook = hook->next) - { - if ( looper->htab[wait_ret] == hook->h && - (!hook->check || hook->check(hook)) ) - { - D( "adb_win32: signaling %s for %x\n", hook->fh->name, hook->ready ); - event_hook_signal( hook ); - gotone = 1; - break; - } - } - } - } - } - while (!gotone); - - for (hook = looper->hooks; hook; hook = hook->next) { - if (hook->stop) - hook->stop( hook ); - } - } - - for (hook = looper->hooks; hook; hook = hook->next) { - if (hook->peek && hook->peek(hook)) - event_hook_signal( hook ); - } -} - - -static void fdevent_register(fdevent *fde) -{ - int fd = fde->fd - WIN32_FH_BASE; - - if(fd < 0) { - FATAL("bogus negative fd (%d)\n", fde->fd); - } - - if(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 <= 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[fd] = fde; -} - -static void fdevent_unregister(fdevent *fde) -{ - int fd = fde->fd - WIN32_FH_BASE; - - if((fd < 0) || (fd >= fd_table_max)) { - FATAL("fd out of range (%d)\n", fde->fd); - } - - if(fd_table[fd] != fde) { - FATAL("fd_table out of sync"); - } - - fd_table[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; -} - -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->func = func; - fde->arg = arg; - - 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) == (int)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_loop() -{ - fdevent *fde; - - for(;;) { -#if DEBUG - fprintf(stderr,"--- ---- waiting for events\n"); -#endif - fdevent_process(); - - while((fde = fdevent_plist_dequeue())) { - unsigned events = fde->events; - fde->events = 0; - fde->state &= (~FDE_PENDING); - dump_fde(fde, "callback"); - fde->func(fde->fd, events, fde->arg); - } - } -} - -/** FILE EVENT HOOKS - **/ - -static void _event_file_prepare( EventHook hook ) -{ - if (hook->wanted & (FDE_READ|FDE_WRITE)) { - /* we can always read/write */ - hook->ready |= hook->wanted & (FDE_READ|FDE_WRITE); - } -} - -static int _event_file_peek( EventHook hook ) -{ - return (hook->wanted & (FDE_READ|FDE_WRITE)); -} - -static void _fh_file_hook( FH f, int events, EventHook hook ) -{ - hook->h = f->fh_handle; - hook->prepare = _event_file_prepare; - hook->peek = _event_file_peek; -} - -/** SOCKET EVENT HOOKS - **/ - -static void _event_socket_verify( EventHook hook, WSANETWORKEVENTS* evts ) -{ - if ( evts->lNetworkEvents & (FD_READ|FD_ACCEPT|FD_CLOSE) ) { - if (hook->wanted & FDE_READ) - hook->ready |= FDE_READ; - if ((evts->iErrorCode[FD_READ] != 0) && hook->wanted & FDE_ERROR) - hook->ready |= FDE_ERROR; - } - if ( evts->lNetworkEvents & (FD_WRITE|FD_CONNECT|FD_CLOSE) ) { - if (hook->wanted & FDE_WRITE) - hook->ready |= FDE_WRITE; - if ((evts->iErrorCode[FD_WRITE] != 0) && hook->wanted & FDE_ERROR) - hook->ready |= FDE_ERROR; - } - if ( evts->lNetworkEvents & FD_OOB ) { - if (hook->wanted & FDE_ERROR) - hook->ready |= FDE_ERROR; - } -} - -static void _event_socket_prepare( EventHook hook ) -{ - WSANETWORKEVENTS evts; - - /* look if some of the events we want already happened ? */ - if (!WSAEnumNetworkEvents( hook->fh->fh_socket, NULL, &evts )) - _event_socket_verify( hook, &evts ); -} - -static int _socket_wanted_to_flags( int wanted ) -{ - int flags = 0; - if (wanted & FDE_READ) - flags |= FD_READ | FD_ACCEPT | FD_CLOSE; - - if (wanted & FDE_WRITE) - flags |= FD_WRITE | FD_CONNECT | FD_CLOSE; - - if (wanted & FDE_ERROR) - flags |= FD_OOB; - - return flags; -} - -static int _event_socket_start( EventHook hook ) -{ - /* create an event which we're going to wait for */ - FH fh = hook->fh; - long flags = _socket_wanted_to_flags( hook->wanted ); - - hook->h = fh->event; - if (hook->h == INVALID_HANDLE_VALUE) { - D( "_event_socket_start: no event for %s\n", fh->name ); - return 0; - } - - if ( flags != fh->mask ) { - D( "_event_socket_start: hooking %s for %x (flags %ld)\n", hook->fh->name, hook->wanted, flags ); - if ( WSAEventSelect( fh->fh_socket, hook->h, flags ) ) { - D( "_event_socket_start: WSAEventSelect() for %s failed, error %d\n", hook->fh->name, WSAGetLastError() ); - CloseHandle( hook->h ); - hook->h = INVALID_HANDLE_VALUE; - exit(1); - return 0; - } - fh->mask = flags; - } - return 1; -} - -static void _event_socket_stop( EventHook hook ) -{ - hook->h = INVALID_HANDLE_VALUE; -} - -static int _event_socket_check( EventHook hook ) -{ - int result = 0; - FH fh = hook->fh; - WSANETWORKEVENTS evts; - - if (!WSAEnumNetworkEvents( fh->fh_socket, hook->h, &evts ) ) { - _event_socket_verify( hook, &evts ); - result = (hook->ready != 0); - if (result) { - ResetEvent( hook->h ); - } - } - D( "_event_socket_check %s returns %d\n", fh->name, result ); - return result; -} - -static int _event_socket_peek( EventHook hook ) -{ - WSANETWORKEVENTS evts; - FH fh = hook->fh; - - /* look if some of the events we want already happened ? */ - if (!WSAEnumNetworkEvents( fh->fh_socket, NULL, &evts )) { - _event_socket_verify( hook, &evts ); - if (hook->ready) - ResetEvent( hook->h ); - } - - return hook->ready != 0; -} - - - -static void _fh_socket_hook( FH f, int events, EventHook hook ) -{ - hook->prepare = _event_socket_prepare; - hook->start = _event_socket_start; - hook->stop = _event_socket_stop; - hook->check = _event_socket_check; - hook->peek = _event_socket_peek; - - _event_socket_start( hook ); -} - -/** SOCKETPAIR EVENT HOOKS - **/ - -static void _event_socketpair_prepare( EventHook hook ) -{ - FH fh = hook->fh; - SocketPair pair = fh->fh_pair; - BipBuffer rbip = (pair->a_fd == fh) ? &pair->b2a_bip : &pair->a2b_bip; - BipBuffer wbip = (pair->a_fd == fh) ? &pair->a2b_bip : &pair->b2a_bip; - - if (hook->wanted & FDE_READ && rbip->can_read) - hook->ready |= FDE_READ; - - if (hook->wanted & FDE_WRITE && wbip->can_write) - hook->ready |= FDE_WRITE; - } - - static int _event_socketpair_start( EventHook hook ) - { - FH fh = hook->fh; - SocketPair pair = fh->fh_pair; - BipBuffer rbip = (pair->a_fd == fh) ? &pair->b2a_bip : &pair->a2b_bip; - BipBuffer wbip = (pair->a_fd == fh) ? &pair->a2b_bip : &pair->b2a_bip; - - if (hook->wanted == FDE_READ) - hook->h = rbip->evt_read; - - else if (hook->wanted == FDE_WRITE) - hook->h = wbip->evt_write; - - else { - D("_event_socketpair_start: can't handle FDE_READ+FDE_WRITE\n" ); - return 0; - } - D( "_event_socketpair_start: hook %s for %x wanted=%x\n", - hook->fh->name, _fh_to_int(fh), hook->wanted); - return 1; -} - -static int _event_socketpair_peek( EventHook hook ) -{ - _event_socketpair_prepare( hook ); - return hook->ready != 0; -} - -static void _fh_socketpair_hook( FH fh, int events, EventHook hook ) -{ - hook->prepare = _event_socketpair_prepare; - hook->start = _event_socketpair_start; - hook->peek = _event_socketpair_peek; -} - - -void -adb_sysdeps_init( void ) -{ -#define ADB_MUTEX(x) InitializeCriticalSection( & x ); -#include "mutex_list.h" - InitializeCriticalSection( &_win32_lock ); -} - diff --git a/adb/test_track_devices.c b/adb/test_track_devices.c deleted file mode 100644 index 77b3ad99..00000000 --- a/adb/test_track_devices.c +++ /dev/null @@ -1,97 +0,0 @@ -/* a simple test program, connects to ADB server, and opens a track-devices session */ -#include <netdb.h> -#include <sys/socket.h> -#include <stdio.h> -#include <stdlib.h> -#include <errno.h> -#include <memory.h> - -static void -panic( const char* msg ) -{ - fprintf(stderr, "PANIC: %s: %s\n", msg, strerror(errno)); - exit(1); -} - -static int -unix_write( int fd, const char* buf, int len ) -{ - int result = 0; - while (len > 0) { - int len2 = write(fd, buf, len); - if (len2 < 0) { - if (errno == EINTR || errno == EAGAIN) - continue; - return -1; - } - result += len2; - len -= len2; - buf += len2; - } - return result; -} - -static int -unix_read( int fd, char* buf, int len ) -{ - int result = 0; - while (len > 0) { - int len2 = read(fd, buf, len); - if (len2 < 0) { - if (errno == EINTR || errno == EAGAIN) - continue; - return -1; - } - result += len2; - len -= len2; - buf += len2; - } - return result; -} - - -int main( void ) -{ - int ret, s; - struct sockaddr_in server; - char buffer[1024]; - const char* request = "host:track-devices"; - int len; - - memset( &server, 0, sizeof(server) ); - server.sin_family = AF_INET; - server.sin_port = htons(5037); - server.sin_addr.s_addr = htonl(INADDR_LOOPBACK); - - s = socket( PF_INET, SOCK_STREAM, 0 ); - ret = connect( s, (struct sockaddr*) &server, sizeof(server) ); - if (ret < 0) panic( "could not connect to server" ); - - /* send the request */ - len = snprintf( buffer, sizeof buffer, "%04x%s", strlen(request), request ); - if (unix_write(s, buffer, len) < 0) - panic( "could not send request" ); - - /* read the OKAY answer */ - if (unix_read(s, buffer, 4) != 4) - panic( "could not read request" ); - - printf( "server answer: %.*s\n", 4, buffer ); - - /* now loop */ - for (;;) { - char head[5] = "0000"; - - if (unix_read(s, head, 4) < 0) - panic("could not read length"); - - if ( sscanf( head, "%04x", &len ) != 1 ) - panic("could not decode length"); - - if (unix_read(s, buffer, len) != len) - panic("could not read data"); - - printf( "received header %.*s (%d bytes):\n%.*s", 4, head, len, len, buffer ); - } - close(s); -} diff --git a/adb/test_track_jdwp.c b/adb/test_track_jdwp.c deleted file mode 100644 index 8ecc6b87..00000000 --- a/adb/test_track_jdwp.c +++ /dev/null @@ -1,97 +0,0 @@ -/* a simple test program, connects to ADB server, and opens a track-devices session */ -#include <netdb.h> -#include <sys/socket.h> -#include <stdio.h> -#include <stdlib.h> -#include <errno.h> -#include <memory.h> - -static void -panic( const char* msg ) -{ - fprintf(stderr, "PANIC: %s: %s\n", msg, strerror(errno)); - exit(1); -} - -static int -unix_write( int fd, const char* buf, int len ) -{ - int result = 0; - while (len > 0) { - int len2 = write(fd, buf, len); - if (len2 < 0) { - if (errno == EINTR || errno == EAGAIN) - continue; - return -1; - } - result += len2; - len -= len2; - buf += len2; - } - return result; -} - -static int -unix_read( int fd, char* buf, int len ) -{ - int result = 0; - while (len > 0) { - int len2 = read(fd, buf, len); - if (len2 < 0) { - if (errno == EINTR || errno == EAGAIN) - continue; - return -1; - } - result += len2; - len -= len2; - buf += len2; - } - return result; -} - - -int main( void ) -{ - int ret, s; - struct sockaddr_in server; - char buffer[1024]; - const char* request = "track-jdwp"; - int len; - - memset( &server, 0, sizeof(server) ); - server.sin_family = AF_INET; - server.sin_port = htons(5037); - server.sin_addr.s_addr = htonl(INADDR_LOOPBACK); - - s = socket( PF_INET, SOCK_STREAM, 0 ); - ret = connect( s, (struct sockaddr*) &server, sizeof(server) ); - if (ret < 0) panic( "could not connect to server" ); - - /* send the request */ - len = snprintf( buffer, sizeof buffer, "%04x%s", strlen(request), request ); - if (unix_write(s, buffer, len) < 0) - panic( "could not send request" ); - - /* read the OKAY answer */ - if (unix_read(s, buffer, 4) != 4) - panic( "could not read request" ); - - printf( "server answer: %.*s\n", 4, buffer ); - - /* now loop */ - for (;;) { - char head[5] = "0000"; - - if (unix_read(s, head, 4) < 0) - panic("could not read length"); - - if ( sscanf( head, "%04x", &len ) != 1 ) - panic("could not decode length"); - - if (unix_read(s, buffer, len) != len) - panic("could not read data"); - - printf( "received header %.*s (%d bytes):\n%.*s", 4, head, len, len, buffer ); - } - close(s); -} diff --git a/adb/transport.c b/adb/transport.c deleted file mode 100644 index c76f1a5f..00000000 --- a/adb/transport.c +++ /dev/null @@ -1,958 +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 -static void dump_hex( const unsigned char* ptr, size_t len ) -{ - int nn, len2 = len; - - if (len2 > 16) len2 = 16; - - for (nn = 0; nn < len2; nn++) - D("%02x", ptr[nn]); - D(" "); - - for (nn = 0; nn < len2; nn++) { - int c = ptr[nn]; - if (c < 32 || c > 127) - c = '.'; - D("%c", c); - } - D("\n"); - fflush(stdout); -} -#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("run_transport_disconnects: %p (%s)\n", t, t->serial ? t->serial : "unknown" ); - while (dis != &t->disconnects) { - adisconnect* next = dis->next; - dis->func( dis->opaque, t ); - dis = next; - } -} - -static int -read_packet(int fd, apacket** ppacket) -{ - char *p = (char*)ppacket; /* really read a packet address */ - int r; - int len = sizeof(*ppacket); - while(len > 0) { - r = adb_read(fd, p, len); - if(r > 0) { - len -= r; - p += r; - } else { - D("read_packet: %d error %d %d\n", fd, r, errno); - if((r < 0) && (errno == EINTR)) continue; - return -1; - } - } - -#if ADB_TRACE - if (ADB_TRACING) - { - unsigned command = (*ppacket)->msg.command; - int len = (*ppacket)->msg.data_length; - char cmd[5]; - int n; - - for (n = 0; n < 4; n++) { - int b = (command >> (n*8)) & 255; - if (b >= 32 && b < 127) - cmd[n] = (char)b; - else - cmd[n] = '.'; - } - cmd[4] = 0; - - D("read_packet: %d ok: [%08x %s] %08x %08x (%d) ", - fd, command, cmd, (*ppacket)->msg.arg0, (*ppacket)->msg.arg1, len); - dump_hex((*ppacket)->data, len); - } -#endif - return 0; -} - -static int -write_packet(int fd, apacket** ppacket) -{ - char *p = (char*) ppacket; /* we really write the packet address */ - int r, len = sizeof(ppacket); - -#if ADB_TRACE - if (ADB_TRACING) - { - unsigned command = (*ppacket)->msg.command; - int len = (*ppacket)->msg.data_length; - char cmd[5]; - int n; - - for (n = 0; n < 4; n++) { - int b = (command >> (n*8)) & 255; - if (b >= 32 && b < 127) - cmd[n] = (char)b; - else - cmd[n] = '.'; - } - cmd[4] = 0; - - D("write_packet: %d [%08x %s] %08x %08x (%d) ", - fd, command, cmd, (*ppacket)->msg.arg0, (*ppacket)->msg.arg1, len); - dump_hex((*ppacket)->data, len); - } -#endif - len = sizeof(ppacket); - while(len > 0) { - r = adb_write(fd, p, len); - if(r > 0) { - len -= r; - p += r; - } else { - D("write_packet: %d error %d %d\n", fd, r, errno); - if((r < 0) && (errno == EINTR)) continue; - return -1; - } - } - return 0; -} - -static void transport_socket_events(int fd, unsigned events, void *_t) -{ - if(events & FDE_READ){ - apacket *p = 0; - if(read_packet(fd, &p)){ - D("failed to read packet from transport socket on fd %d\n", 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) { - fatal_errno("Transport is null"); - D("Transport is null \n"); - } - - if(write_packet(t->transport_socket, &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("from_remote: starting thread for transport %p, on fd %d\n", t, t->fd ); - - D("from_remote: transport %p SYNC online (%d)\n", t, 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, &p)) { - put_apacket(p); - D("from_remote: failed to write SYNC apacket to transport %p", t); - goto oops; - } - - D("from_remote: data pump for transport %p\n", t); - for(;;) { - p = get_apacket(); - - if(t->read_from_remote(p, t) == 0){ - D("from_remote: received remote packet, sending to transport %p\n", - t); - if(write_packet(t->fd, &p)){ - put_apacket(p); - D("from_remote: failed to write apacket to transport %p", t); - goto oops; - } - } else { - D("from_remote: remote read failed for transport %p\n", p); - put_apacket(p); - break; - } - } - - D("from_remote: SYNC offline for transport %p\n", t); - 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, &p)) { - put_apacket(p); - D("from_remote: failed to write SYNC apacket to transport %p", t); - } - -oops: - D("from_remote: thread is exiting for transport %p\n", t); - kick_transport(t); - transport_unref(t); - return 0; -} - -static void *input_thread(void *_t) -{ - atransport *t = _t; - apacket *p; - int active = 0; - - D("to_remote: starting input_thread for %p, reading from fd %d\n", - t, t->fd); - - for(;;){ - if(read_packet(t->fd, &p)) { - D("to_remote: failed to read apacket from transport %p on fd %d\n", - t, t->fd ); - break; - } - if(p->msg.command == A_SYNC){ - if(p->msg.arg0 == 0) { - D("to_remote: transport %p SYNC offline\n", t); - put_apacket(p); - break; - } else { - if(p->msg.arg1 == t->sync_token) { - D("to_remote: transport %p SYNC online\n", t); - active = 1; - } else { - D("to_remote: trandport %p ignoring SYNC %d != %d\n", - t, p->msg.arg1, t->sync_token); - } - } - } else { - if(active) { - D("to_remote: transport %p got packet, sending to remote\n", t); - t->write_to_remote(p, t); - } else { - D("to_remote: transport %p ignoring packet while offline\n", t); - } - } - - 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("to_remote: thread is exiting for transport %p, fd %d\n", t, 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; - - -#if ADB_HOST -static int list_transports_msg(char* buffer, size_t bufferlen) -{ - char head[5]; - int len; - - len = list_transports(buffer+4, bufferlen-4); - snprintf(head, sizeof(head), "%04x", len); - memcpy(buffer, head, 4); - len += 4; - return len; -} - -/* this adds support required by the 'track-devices' service. - * this is used to send the content of "list_transport" to any - * number of client connections that want it through a single - * live TCP connection - */ -typedef struct device_tracker device_tracker; -struct device_tracker { - asocket socket; - int update_needed; - device_tracker* next; -}; - -/* linked list of all device trackers */ -static device_tracker* device_tracker_list; - -static void -device_tracker_remove( device_tracker* tracker ) -{ - device_tracker** pnode = &device_tracker_list; - device_tracker* node = *pnode; - - adb_mutex_lock( &transport_lock ); - while (node) { - if (node == tracker) { - *pnode = node->next; - break; - } - pnode = &node->next; - node = *pnode; - } - adb_mutex_unlock( &transport_lock ); -} - -static void -device_tracker_close( asocket* socket ) -{ - device_tracker* tracker = (device_tracker*) socket; - asocket* peer = socket->peer; - - D( "device tracker %p removed\n", tracker); - if (peer) { - peer->peer = NULL; - peer->close(peer); - } - device_tracker_remove(tracker); - free(tracker); -} - -static int -device_tracker_enqueue( asocket* socket, apacket* p ) -{ - /* you can't read from a device tracker, close immediately */ - put_apacket(p); - device_tracker_close(socket); - return -1; -} - -static int -device_tracker_send( device_tracker* tracker, - const char* buffer, - int len ) -{ - apacket* p = get_apacket(); - asocket* peer = tracker->socket.peer; - - memcpy(p->data, buffer, len); - p->len = len; - return peer->enqueue( peer, p ); -} - - -static void -device_tracker_ready( asocket* socket ) -{ - device_tracker* tracker = (device_tracker*) socket; - - /* we want to send the device list when the tracker connects - * for the first time, even if no update occured */ - if (tracker->update_needed > 0) { - char buffer[1024]; - int len; - - tracker->update_needed = 0; - - len = list_transports_msg(buffer, sizeof(buffer)); - device_tracker_send(tracker, buffer, len); - } -} - - -asocket* -create_device_tracker(void) -{ - device_tracker* tracker = calloc(1,sizeof(*tracker)); - - if(tracker == 0) fatal("cannot allocate device tracker"); - - D( "device tracker %p created\n", tracker); - - tracker->socket.enqueue = device_tracker_enqueue; - tracker->socket.ready = device_tracker_ready; - tracker->socket.close = device_tracker_close; - tracker->update_needed = 1; - - tracker->next = device_tracker_list; - device_tracker_list = tracker; - - return &tracker->socket; -} - - -/* call this function each time the transport list has changed */ -void update_transports(void) -{ - char buffer[1024]; - int len; - device_tracker* tracker; - - len = list_transports_msg(buffer, sizeof(buffer)); - - tracker = device_tracker_list; - while (tracker != NULL) { - device_tracker* next = tracker->next; - /* note: this may destroy the tracker if the connection is closed */ - device_tracker_send(tracker, buffer, len); - tracker = next; - } -} -#else -void update_transports(void) -{ - // nothing to do on the device side -} -#endif // ADB_HOST - -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: %p removing and free'ing %d\n", t, 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; - } - - /* initial references are the two threads */ - t->ref_count = 2; - - if(adb_socketpair(s)) { - fatal_errno("cannot open transport socketpair"); - } - - D("transport: %p (%d,%d) starting\n", t, s[0], s[1]); - - t->transport_socket = s[0]; - t->fd = s[1]; - - /* 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); - - D("transport: %p install %d\n", t, t->transport_socket ); - 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"); - } - - 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: %p registered\n", transport); - 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: %p removed\n", transport); - if(transport_write_action(transport_registration_send, &m)) { - fatal_errno("cannot write transport registration socket\n"); - } -} - - -static void transport_unref(atransport *t) -{ - if (t) { - adb_mutex_lock(&transport_lock); - t->ref_count--; - D("transport: %p R- (ref=%d)\n", t, t->ref_count); - if (t->ref_count == 0) { - D("transport: %p kicking and closing\n", t); - if (!t->kicked) { - t->kicked = 1; - t->kick(t); - } - t->close(t); - remove_transport(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) { - /* 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; -} - -#if ADB_HOST -static const char *statename(atransport *t) -{ - switch(t->connection_state){ - case CS_OFFLINE: return "offline"; - case CS_BOOTLOADER: return "bootloader"; - case CS_DEVICE: return "device"; - case CS_HOST: return "host"; - case CS_RECOVERY: return "recovery"; - default: return "unknown"; - } -} - -int list_transports(char *buf, size_t bufsize) -{ - char* p = buf; - char* end = buf + bufsize; - int len; - atransport *t; - - /* XXX OVERRUN PROBLEMS XXX */ - adb_mutex_lock(&transport_lock); - for(t = transport_list.next; t != &transport_list; t = t->next) { - len = snprintf(p, end - p, "%s\t%s\n", - t->serial ? t->serial : "", - statename(t)); - - if (p + len >= end) { - /* discard last line if buffer is too short */ - break; - } - p += len; - } - p[0] = 0; - adb_mutex_unlock(&transport_lock); - return p - buf; -} - - -/* hack for osx */ -void close_usb_devices() -{ - atransport *t; - - adb_mutex_lock(&transport_lock); - for(t = transport_list.next; t != &transport_list; t = t->next) { - if ( !t->kicked ) { - t->kicked = 1; - t->kick(t); - } - } - adb_mutex_unlock(&transport_lock); -} -#endif // ADB_HOST - -void register_socket_transport(int s, const char *serial, int port) -{ - atransport *t = calloc(1, sizeof(atransport)); - D("transport: %p init'ing for socket %d, on port %d\n", t, s, port); - if ( init_socket_transport(t, s, port) < 0 ) { - adb_close(s); - free(t); - return; - } - if(serial) { - t->serial = strdup(serial); - } - register_transport(t); -} - -void register_usb_transport(usb_handle *usb, const char *serial) -{ - 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); - if(serial) { - t->serial = strdup(serial); - } - register_transport(t); -} - - -#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 - int len0 = len; -#endif - D("readx: %d %p %d\n", fd, ptr, (int)len); - while(len > 0) { - r = adb_read(fd, p, len); - if(r > 0) { - len -= r; - p += r; - } else { - D("readx: %d %d %s\n", fd, r, strerror(errno)); - if((r < 0) && (errno == EINTR)) continue; - return -1; - } - } - -#if ADB_TRACE - D("readx: %d ok: ", fd); - 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: %d %p %d: ", fd, ptr, (int)len); - dump_hex( ptr, len ); -#endif - while(len > 0) { - r = adb_write(fd, p, len); - if(r > 0) { - len -= r; - p += r; - } else { - D("writex: %d %d %s\n", fd, r, strerror(errno)); - if((r < 0) && (errno == EINTR)) continue; - return -1; - } - } - - D("writex: %d ok\n", fd); - 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/adb/transport_local.c b/adb/transport_local.c deleted file mode 100644 index be01f290..00000000 --- a/adb/transport_local.c +++ /dev/null @@ -1,263 +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 <errno.h> - -#include "sysdeps.h" -#include <sys/types.h> - -#define TRACE_TAG TRACE_TRANSPORT -#include "adb.h" - -#ifdef __ppc__ -#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); -} -#else -#define fix_endians(p) do {} while (0) -#endif - -#if ADB_HOST -/* we keep a list of opened transports, transport 0 is bound to 5555, - * transport 1 to 5557, .. transport n to 5555 + n*2. the list is used - * to detect when we're trying to connect twice to a given local transport - */ -#define ADB_LOCAL_TRANSPORT_MAX 16 - -ADB_MUTEX_DEFINE( local_transports_lock ); - -static atransport* local_transports[ ADB_LOCAL_TRANSPORT_MAX ]; -#endif /* ADB_HOST */ - -static int remote_read(apacket *p, atransport *t) -{ - if(readx(t->sfd, &p->msg, sizeof(amessage))){ - D("remote local: read terminated (message)\n"); - return -1; - } - - fix_endians(p); - -#if 0 && defined __ppc__ - D("read remote packet: %04x arg0=%0x arg1=%0x data_length=%0x data_check=%0x magic=%0x\n", - p->msg.command, p->msg.arg0, p->msg.arg1, p->msg.data_length, p->msg.data_check, p->msg.magic); -#endif - if(check_header(p)) { - D("bad header: terminated (data)\n"); - return -1; - } - - if(readx(t->sfd, p->data, p->msg.data_length)){ - D("remote local: terminated (data)\n"); - return -1; - } - - if(check_data(p)) { - D("bad data: terminated (data)\n"); - return -1; - } - - return 0; -} - -static int remote_write(apacket *p, atransport *t) -{ - int length = p->msg.data_length; - - fix_endians(p); - -#if 0 && defined __ppc__ - D("write remote packet: %04x arg0=%0x arg1=%0x data_length=%0x data_check=%0x magic=%0x\n", - p->msg.command, p->msg.arg0, p->msg.arg1, p->msg.data_length, p->msg.data_check, p->msg.magic); -#endif - if(writex(t->sfd, &p->msg, sizeof(amessage) + length)) { - D("remote local: write terminated\n"); - return -1; - } - - return 0; -} - - -int local_connect(int port) -{ - char buf[64]; - int fd = -1; - -#if ADB_HOST - const char *host = getenv("ADBHOST"); - if (host) { - fd = socket_network_client(host, port, SOCK_STREAM); - } -#endif - if (fd < 0) { - fd = socket_loopback_client(port, SOCK_STREAM); - } - - if (fd >= 0) { - D("client: connected on remote on fd %d\n", fd); - close_on_exec(fd); - disable_tcp_nagle(fd); - snprintf(buf, sizeof buf, "%s%d", LOCAL_CLIENT_PREFIX, port - 1); - register_socket_transport(fd, buf, port); - return 0; - } - return -1; -} - - -static void *client_socket_thread(void *x) -{ -#if ADB_HOST - int port = ADB_LOCAL_TRANSPORT_PORT; - int count = ADB_LOCAL_TRANSPORT_MAX; - - D("transport: client_socket_thread() starting\n"); - - /* try to connect to any number of running emulator instances */ - /* this is only done when ADB starts up. later, each new emulator */ - /* will send a message to ADB to indicate that is is starting up */ - for ( ; count > 0; count--, port += 2 ) { - (void) local_connect(port); - } -#endif - return 0; -} - -static void *server_socket_thread(void *x) -{ - int serverfd, fd; - struct sockaddr addr; - socklen_t alen; - - D("transport: server_socket_thread() starting\n"); - serverfd = -1; - for(;;) { - if(serverfd == -1) { - serverfd = socket_inaddr_any_server(ADB_LOCAL_TRANSPORT_PORT, SOCK_STREAM); - if(serverfd < 0) { - D("server: cannot bind socket yet\n"); - adb_sleep_ms(1000); - continue; - } - close_on_exec(serverfd); - } - - alen = sizeof(addr); - D("server: trying to get new connection from %d\n", ADB_LOCAL_TRANSPORT_PORT); - fd = adb_socket_accept(serverfd, &addr, &alen); - if(fd >= 0) { - D("server: new connection on fd %d\n", fd); - close_on_exec(fd); - disable_tcp_nagle(fd); - register_socket_transport(fd,"host",ADB_LOCAL_TRANSPORT_PORT); - } - } - D("transport: server_socket_thread() exiting\n"); - return 0; -} - -void local_init(void) -{ - adb_thread_t thr; - void* (*func)(void *); - - if(HOST) { - func = client_socket_thread; - } else { - func = server_socket_thread; - } - - D("transport: local %s init\n", HOST ? "client" : "server"); - - if(adb_thread_create(&thr, func, 0)) { - fatal_errno("cannot create local socket %s thread", - HOST ? "client" : "server"); - } -} - -static void remote_kick(atransport *t) -{ - int fd = t->sfd; - t->sfd = -1; - adb_close(fd); - -#if ADB_HOST - if(HOST) { - int nn; - adb_mutex_lock( &local_transports_lock ); - for (nn = 0; nn < ADB_LOCAL_TRANSPORT_MAX; nn++) { - if (local_transports[nn] == t) { - local_transports[nn] = NULL; - break; - } - } - adb_mutex_unlock( &local_transports_lock ); - } -#endif -} - -static void remote_close(atransport *t) -{ - adb_close(t->fd); -} - -int init_socket_transport(atransport *t, int s, int port) -{ - int fail = 0; - - t->kick = remote_kick; - t->close = remote_close; - t->read_from_remote = remote_read; - t->write_to_remote = remote_write; - t->sfd = s; - t->sync_token = 1; - t->connection_state = CS_OFFLINE; - t->type = kTransportLocal; - -#if ADB_HOST - if (HOST) { - adb_mutex_lock( &local_transports_lock ); - { - int index = (port - ADB_LOCAL_TRANSPORT_PORT)/2; - - if (!(port & 1) || index < 0 || index >= ADB_LOCAL_TRANSPORT_MAX) { - D("bad local transport port number: %d\n", port); - fail = -1; - } - else if (local_transports[index] != NULL) { - D("local transport for port %d already registered (%p)?\n", - port, local_transports[index]); - fail = -1; - } - else - local_transports[index] = t; - } - adb_mutex_unlock( &local_transports_lock ); - } -#endif - return fail; -} diff --git a/adb/transport_usb.c b/adb/transport_usb.c deleted file mode 100644 index 01c4a7ed..00000000 --- a/adb/transport_usb.c +++ /dev/null @@ -1,147 +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" - -/* XXX better define? */ -#ifdef __ppc__ -#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) -{ - 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 = CS_OFFLINE; - t->type = kTransportUsb; - t->usb = h; - -#if ADB_HOST - HOST = 1; -#else - HOST = 0; -#endif -} - -int is_adb_interface(int vid, int pid, int usb_class, int usb_subclass, int usb_protocol) -{ - if (vid == VENDOR_ID_GOOGLE) { - /* might support adb */ - } else if (vid == VENDOR_ID_HTC) { - /* might support adb */ - } else { - /* not supported */ - return 0; - } - - /* class:vendor (0xff) subclass:android (0x42) proto:adb (0x01) */ - if(usb_class == 0xff) { - if((usb_subclass == 0x42) && (usb_protocol == 0x01)) { - return 1; - } - } - - return 0; -} diff --git a/adb/usb_linux.c b/adb/usb_linux.c deleted file mode 100644 index 32ce0a9e..00000000 --- a/adb/usb_linux.c +++ /dev/null @@ -1,654 +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 <sys/ioctl.h> -#include <sys/types.h> -#include <dirent.h> -#include <fcntl.h> -#include <errno.h> -#include <ctype.h> - -#include <linux/usbdevice_fs.h> -#include <linux/version.h> -#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 20) -#include <linux/usb/ch9.h> -#else -#include <linux/usb_ch9.h> -#endif -#include <asm/byteorder.h> - -#include "sysdeps.h" - -#define TRACE_TAG TRACE_USB -#include "adb.h" - - -/* usb scan debugging is waaaay too verbose */ -#define DBGX(x...) - -static adb_mutex_t usb_lock = ADB_MUTEX_INITIALIZER; - -struct usb_handle -{ - usb_handle *prev; - usb_handle *next; - - char fname[64]; - int desc; - unsigned char ep_in; - unsigned char ep_out; - - unsigned zero_mask; - - struct usbdevfs_urb urb_in; - struct usbdevfs_urb urb_out; - - int urb_in_busy; - int urb_out_busy; - int dead; - - adb_cond_t notify; - adb_mutex_t lock; - - // for garbage collecting disconnected devices - int mark; - - // ID of thread currently in REAPURB - pthread_t reaper_thread; -}; - -static usb_handle handle_list = { - .prev = &handle_list, - .next = &handle_list, -}; - -static int known_device(const char *dev_name) -{ - usb_handle *usb; - - adb_mutex_lock(&usb_lock); - for(usb = handle_list.next; usb != &handle_list; usb = usb->next){ - if(!strcmp(usb->fname, dev_name)) { - // set mark flag to indicate this device is still alive - usb->mark = 1; - adb_mutex_unlock(&usb_lock); - return 1; - } - } - adb_mutex_unlock(&usb_lock); - return 0; -} - -static void kick_disconnected_devices() -{ - usb_handle *usb; - - adb_mutex_lock(&usb_lock); - // kick any devices in the device list that were not found in the device scan - for(usb = handle_list.next; usb != &handle_list; usb = usb->next){ - if (usb->mark == 0) { - usb_kick(usb); - } else { - usb->mark = 0; - } - } - adb_mutex_unlock(&usb_lock); - -} - -static void register_device(const char *dev_name, unsigned char ep_in, unsigned char ep_out, - int ifc, const char *serial, unsigned zero_mask); - -static inline int badname(const char *name) -{ - while(*name) { - if(!isdigit(*name++)) return 1; - } - return 0; -} - -static int find_usb_device(const char *base, - void (*register_device_callback) (const char *, unsigned char, unsigned char, int, const char *, unsigned)) -{ - char busname[32], devname[32]; - unsigned char local_ep_in, local_ep_out; - DIR *busdir , *devdir ; - struct dirent *de; - int fd ; - int found_device = 0; - char serial[256]; - - busdir = opendir(base); - if(busdir == 0) return 0; - - while((de = readdir(busdir)) != 0) { - if(badname(de->d_name)) continue; - - snprintf(busname, sizeof busname, "%s/%s", base, de->d_name); - devdir = opendir(busname); - if(devdir == 0) continue; - -// DBGX("[ scanning %s ]\n", busname); - while((de = readdir(devdir))) { - unsigned char devdesc[256]; - unsigned char* bufptr = devdesc; - struct usb_device_descriptor* device; - struct usb_config_descriptor* config; - struct usb_interface_descriptor* interface; - struct usb_endpoint_descriptor *ep1, *ep2; - unsigned zero_mask = 0; - unsigned vid, pid; - int i, interfaces; - size_t desclength; - - if(badname(de->d_name)) continue; - snprintf(devname, sizeof devname, "%s/%s", busname, de->d_name); - - if(known_device(devname)) { - DBGX("skipping %s\n", devname); - continue; - } - -// DBGX("[ scanning %s ]\n", devname); - if((fd = unix_open(devname, O_RDWR)) < 0) { - continue; - } - - desclength = adb_read(fd, devdesc, sizeof(devdesc)); - - // should have device and configuration descriptors, and atleast two endpoints - if (desclength < USB_DT_DEVICE_SIZE + USB_DT_CONFIG_SIZE) { - D("desclength %d is too small\n", desclength); - adb_close(fd); - continue; - } - - device = (struct usb_device_descriptor*)bufptr; - bufptr += USB_DT_DEVICE_SIZE; - - if((device->bLength != USB_DT_DEVICE_SIZE) || (device->bDescriptorType != USB_DT_DEVICE)) { - adb_close(fd); - continue; - } - - vid = __le16_to_cpu(device->idVendor); - pid = __le16_to_cpu(device->idProduct); - pid = devdesc[10] | (devdesc[11] << 8); - DBGX("[ %s is V:%04x P:%04x ]\n", devname, vid, pid); - - // should have config descriptor next - config = (struct usb_config_descriptor *)bufptr; - bufptr += USB_DT_CONFIG_SIZE; - if (config->bLength != USB_DT_CONFIG_SIZE || config->bDescriptorType != USB_DT_CONFIG) { - D("usb_config_descriptor not found\n"); - adb_close(fd); - continue; - } - - // loop through all the interfaces and look for the ADB interface - interfaces = config->bNumInterfaces; - for (i = 0; i < interfaces; i++) { - if (bufptr + USB_DT_ENDPOINT_SIZE > devdesc + desclength) - break; - - interface = (struct usb_interface_descriptor *)bufptr; - bufptr += USB_DT_INTERFACE_SIZE; - if (interface->bLength != USB_DT_INTERFACE_SIZE || - interface->bDescriptorType != USB_DT_INTERFACE) { - D("usb_interface_descriptor not found\n"); - break; - } - - DBGX("bInterfaceClass: %d, bInterfaceSubClass: %d," - "bInterfaceProtocol: %d, bNumEndpoints: %d\n", - interface->bInterfaceClass, interface->bInterfaceSubClass, - interface->bInterfaceProtocol, interface->bNumEndpoints); - - if (interface->bNumEndpoints == 2 && - is_adb_interface(vid, pid, interface->bInterfaceClass, - interface->bInterfaceSubClass, interface->bInterfaceProtocol)) { - - DBGX("looking for bulk endpoints\n"); - // looks like ADB... - ep1 = (struct usb_endpoint_descriptor *)bufptr; - bufptr += USB_DT_ENDPOINT_SIZE; - ep2 = (struct usb_endpoint_descriptor *)bufptr; - bufptr += USB_DT_ENDPOINT_SIZE; - - if (bufptr > devdesc + desclength || - ep1->bLength != USB_DT_ENDPOINT_SIZE || - ep1->bDescriptorType != USB_DT_ENDPOINT || - ep2->bLength != USB_DT_ENDPOINT_SIZE || - ep2->bDescriptorType != USB_DT_ENDPOINT) { - D("endpoints not found\n"); - break; - } - - // both endpoints should be bulk - if (ep1->bmAttributes != USB_ENDPOINT_XFER_BULK || - ep2->bmAttributes != USB_ENDPOINT_XFER_BULK) { - D("bulk endpoints not found\n"); - continue; - } - - /* aproto 01 needs 0 termination */ - if(interface->bInterfaceProtocol == 0x01) { - zero_mask = ep1->wMaxPacketSize - 1; - } - - // we have a match. now we just need to figure out which is in and which is out. - if (ep1->bEndpointAddress & USB_ENDPOINT_DIR_MASK) { - local_ep_in = ep1->bEndpointAddress; - local_ep_out = ep2->bEndpointAddress; - } else { - local_ep_in = ep2->bEndpointAddress; - local_ep_out = ep1->bEndpointAddress; - } - - // read the device's serial number - serial[0] = 0; - memset(serial, 0, sizeof(serial)); - if (device->iSerialNumber) { - struct usbdevfs_ctrltransfer ctrl; - __u16 buffer[128]; - int result; - - memset(buffer, 0, sizeof(buffer)); - memset(&ctrl, 0, sizeof(ctrl)); - - ctrl.bRequestType = USB_DIR_IN|USB_TYPE_STANDARD|USB_RECIP_DEVICE; - ctrl.bRequest = USB_REQ_GET_DESCRIPTOR; - ctrl.wValue = (USB_DT_STRING << 8) | device->iSerialNumber; - ctrl.wIndex = 0; - ctrl.wLength = sizeof(buffer); - ctrl.data = buffer; - - result = ioctl(fd, USBDEVFS_CONTROL, &ctrl); - if (result > 0) { - int i; - // skip first word, and copy the rest to the serial string, changing shorts to bytes. - result /= 2; - for (i = 1; i < result; i++) - serial[i - 1] = buffer[i]; - serial[i - 1] = 0; - } - } - - register_device_callback(devname, local_ep_in, local_ep_out, - interface->bInterfaceNumber, serial, zero_mask); - - found_device = 1; - break; - } else { - // skip to next interface - bufptr += (interface->bNumEndpoints * USB_DT_ENDPOINT_SIZE); - } - } // end of for - - adb_close(fd); - } // end of devdir while - closedir(devdir); - } //end of busdir while - closedir(busdir); - - return found_device; -} - -void usb_cleanup() -{ -} - -static int usb_bulk_write(usb_handle *h, const void *data, int len) -{ - struct usbdevfs_urb *urb = &h->urb_out; - int res; - - memset(urb, 0, sizeof(*urb)); - urb->type = USBDEVFS_URB_TYPE_BULK; - urb->endpoint = h->ep_out; - urb->status = -1; - urb->buffer = (void*) data; - urb->buffer_length = len; - - D("++ write ++\n"); - - adb_mutex_lock(&h->lock); - if(h->dead) { - res = -1; - goto fail; - } - do { - res = ioctl(h->desc, USBDEVFS_SUBMITURB, urb); - } while((res < 0) && (errno == EINTR)); - - if(res < 0) { - goto fail; - } - - res = -1; - h->urb_out_busy = 1; - for(;;) { - adb_cond_wait(&h->notify, &h->lock); - if(h->dead) { - break; - } - if(h->urb_out_busy == 0) { - if(urb->status == 0) { - res = urb->actual_length; - } - break; - } - } -fail: - adb_mutex_unlock(&h->lock); - D("-- write --\n"); - return res; -} - -static int usb_bulk_read(usb_handle *h, void *data, int len) -{ - struct usbdevfs_urb *urb = &h->urb_in; - struct usbdevfs_urb *out = NULL; - int res; - - memset(urb, 0, sizeof(*urb)); - urb->type = USBDEVFS_URB_TYPE_BULK; - urb->endpoint = h->ep_in; - urb->status = -1; - urb->buffer = data; - urb->buffer_length = len; - - - adb_mutex_lock(&h->lock); - if(h->dead) { - res = -1; - goto fail; - } - do { - res = ioctl(h->desc, USBDEVFS_SUBMITURB, urb); - } while((res < 0) && (errno == EINTR)); - - if(res < 0) { - goto fail; - } - - h->urb_in_busy = 1; - for(;;) { - D("[ reap urb - wait ]\n"); - h->reaper_thread = pthread_self(); - adb_mutex_unlock(&h->lock); - res = ioctl(h->desc, USBDEVFS_REAPURB, &out); - adb_mutex_lock(&h->lock); - h->reaper_thread = 0; - if(h->dead) { - res = -1; - break; - } - if(res < 0) { - if(errno == EINTR) { - continue; - } - D("[ reap urb - error ]\n"); - break; - } - D("[ urb @%p status = %d, actual = %d ]\n", - out, out->status, out->actual_length); - - if(out == &h->urb_in) { - D("[ reap urb - IN complete ]\n"); - h->urb_in_busy = 0; - if(urb->status == 0) { - res = urb->actual_length; - } else { - res = -1; - } - break; - } - if(out == &h->urb_out) { - D("[ reap urb - OUT compelete ]\n"); - h->urb_out_busy = 0; - adb_cond_broadcast(&h->notify); - } - } -fail: - adb_mutex_unlock(&h->lock); - return res; -} - - -int usb_write(usb_handle *h, const void *_data, int len) -{ - unsigned char *data = (unsigned char*) _data; - int n; - int need_zero = 0; - - if(h->zero_mask) { - /* if we need 0-markers and our transfer - ** is an even multiple of the packet size, - ** we make note of it - */ - if(!(len & h->zero_mask)) { - need_zero = 1; - } - } - - while(len > 0) { - int xfer = (len > 4096) ? 4096 : len; - - n = usb_bulk_write(h, data, xfer); - if(n != xfer) { - D("ERROR: n = %d, errno = %d (%s)\n", - n, errno, strerror(errno)); - return -1; - } - - len -= xfer; - data += xfer; - } - - if(need_zero){ - n = usb_bulk_write(h, _data, 0); - return n; - } - - return 0; -} - -int usb_read(usb_handle *h, void *_data, int len) -{ - unsigned char *data = (unsigned char*) _data; - int n; - - D("++ usb_read ++\n"); - while(len > 0) { - int xfer = (len > 4096) ? 4096 : len; - - D("[ usb read %d fd = %d], fname=%s\n", xfer, h->desc, h->fname); - n = usb_bulk_read(h, data, xfer); - D("[ usb read %d ] = %d, fname=%s\n", xfer, n, h->fname); - if(n != xfer) { - if((errno == ETIMEDOUT) && (h->desc != -1)) { - D("[ timeout ]\n"); - if(n > 0){ - data += n; - len -= n; - } - continue; - } - D("ERROR: n = %d, errno = %d (%s)\n", - n, errno, strerror(errno)); - return -1; - } - - len -= xfer; - data += xfer; - } - - D("-- usb_read --\n"); - return 0; -} - -void usb_kick(usb_handle *h) -{ - D("[ kicking %p (fd = %d) ]\n", h, h->desc); - adb_mutex_lock(&h->lock); - if(h->dead == 0) { - h->dead = 1; - - /* HACK ALERT! - ** Sometimes we get stuck in ioctl(USBDEVFS_REAPURB). - ** This is a workaround for that problem. - */ - if (h->reaper_thread) { - pthread_kill(h->reaper_thread, SIGALRM); - } - - /* cancel any pending transactions - ** these will quietly fail if the txns are not active, - ** but this ensures that a reader blocked on REAPURB - ** will get unblocked - */ - ioctl(h->desc, USBDEVFS_DISCARDURB, &h->urb_in); - ioctl(h->desc, USBDEVFS_DISCARDURB, &h->urb_out); - h->urb_in.status = -ENODEV; - h->urb_out.status = -ENODEV; - h->urb_in_busy = 0; - h->urb_out_busy = 0; - adb_cond_broadcast(&h->notify); - } - adb_mutex_unlock(&h->lock); -} - -int usb_close(usb_handle *h) -{ - D("[ usb close ... ]\n"); - adb_mutex_lock(&usb_lock); - h->next->prev = h->prev; - h->prev->next = h->next; - h->prev = 0; - h->next = 0; - - adb_close(h->desc); - D("[ usb closed %p (fd = %d) ]\n", h, h->desc); - adb_mutex_unlock(&usb_lock); - - free(h); - return 0; -} - -static void register_device(const char *dev_name, - unsigned char ep_in, unsigned char ep_out, - int interface, - const char *serial, unsigned zero_mask) -{ - usb_handle* usb = 0; - int n = 0; - - /* Since Linux will not reassign the device ID (and dev_name) - ** as long as the device is open, we can add to the list here - ** once we open it and remove from the list when we're finally - ** closed and everything will work out fine. - ** - ** If we have a usb_handle on the list 'o handles with a matching - ** name, we have no further work to do. - */ - adb_mutex_lock(&usb_lock); - for(usb = handle_list.next; usb != &handle_list; usb = usb->next){ - if(!strcmp(usb->fname, dev_name)) { - adb_mutex_unlock(&usb_lock); - return; - } - } - adb_mutex_unlock(&usb_lock); - - D("[ usb located new device %s (%d/%d/%d) ]\n", - dev_name, ep_in, ep_out, interface); - usb = calloc(1, sizeof(usb_handle)); - strcpy(usb->fname, dev_name); - usb->ep_in = ep_in; - usb->ep_out = ep_out; - usb->zero_mask = zero_mask; - - adb_cond_init(&usb->notify, 0); - adb_mutex_init(&usb->lock, 0); - /* initialize mark to 1 so we don't get garbage collected after the device scan */ - usb->mark = 1; - usb->reaper_thread = 0; - - usb->desc = unix_open(usb->fname, O_RDWR); - if(usb->desc < 0) goto fail; - D("[ usb open %s fd = %d]\n", usb->fname, usb->desc); - n = ioctl(usb->desc, USBDEVFS_CLAIMINTERFACE, &interface); - if(n != 0) goto fail; - - /* add to the end of the active handles */ - adb_mutex_lock(&usb_lock); - usb->next = &handle_list; - usb->prev = handle_list.prev; - usb->prev->next = usb; - usb->next->prev = usb; - adb_mutex_unlock(&usb_lock); - - register_usb_transport(usb, serial); - return; - -fail: - D("[ usb open %s error=%d, err_str = %s]\n", - usb->fname, errno, strerror(errno)); - if(usb->desc >= 0) { - adb_close(usb->desc); - } - free(usb); -} - -void* device_poll_thread(void* unused) -{ - D("Created device thread\n"); - for(;;) { - /* XXX use inotify */ - find_usb_device("/dev/bus/usb", register_device); - kick_disconnected_devices(); - sleep(1); - } - return NULL; -} - -static void sigalrm_handler(int signo) -{ - // don't need to do anything here -} - -void usb_init() -{ - adb_thread_t tid; - struct sigaction actions; - - memset(&actions, 0, sizeof(actions)); - sigemptyset(&actions.sa_mask); - actions.sa_flags = 0; - actions.sa_handler = sigalrm_handler; - sigaction(SIGALRM,& actions, NULL); - - if(adb_thread_create(&tid, device_poll_thread, NULL)){ - fatal_errno("cannot create input thread"); - } -} - diff --git a/adb/usb_linux_client.c b/adb/usb_linux_client.c deleted file mode 100644 index 530bd04d..00000000 --- a/adb/usb_linux_client.c +++ /dev/null @@ -1,156 +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 <sys/ioctl.h> -#include <sys/types.h> -#include <dirent.h> -#include <errno.h> - -#include "sysdeps.h" - -#define TRACE_TAG TRACE_USB -#include "adb.h" - - -struct usb_handle -{ - int fd; - adb_cond_t notify; - adb_mutex_t lock; -}; - -void usb_cleanup() -{ - // nothing to do here -} - -static void *usb_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); - } - 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); - } - - // never gets here - return 0; -} - -int usb_write(usb_handle *h, const void *data, int len) -{ - int n; - - D("[ write %d ]\n", len); - n = adb_write(h->fd, data, len); - if(n != len) { - D("ERROR: n = %d, errno = %d (%s)\n", - n, errno, strerror(errno)); - return -1; - } - D("[ done ]\n"); - return 0; -} - -int usb_read(usb_handle *h, void *data, int len) -{ - int n; - - D("[ read %d ]\n", len); - n = adb_read(h->fd, data, len); - if(n != len) { - D("ERROR: n = %d, errno = %d (%s)\n", - n, errno, strerror(errno)); - return -1; - } - return 0; -} - -void usb_init() -{ - usb_handle *h; - adb_thread_t tid; - int fd; - - h = calloc(1, sizeof(usb_handle)); - h->fd = -1; - adb_cond_init(&h->notify, 0); - adb_mutex_init(&h->lock, 0); - - // 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); - 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_open_thread, h)){ - fatal_errno("cannot create usb thread"); - } -} - -void usb_kick(usb_handle *h) -{ - D("usb_kick\n"); - adb_mutex_lock(&h->lock); - adb_close(h->fd); - h->fd = -1; - - // notify usb_open_thread that we are disconnected - adb_cond_signal(&h->notify); - adb_mutex_unlock(&h->lock); -} - -int usb_close(usb_handle *h) -{ - // nothing to do here - return 0; -} diff --git a/adb/usb_osx.c b/adb/usb_osx.c deleted file mode 100644 index 49e1eef5..00000000 --- a/adb/usb_osx.c +++ /dev/null @@ -1,536 +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 <CoreFoundation/CoreFoundation.h> - -#include <IOKit/IOKitLib.h> -#include <IOKit/IOCFPlugIn.h> -#include <IOKit/usb/IOUSBLib.h> -#include <IOKit/IOMessage.h> -#include <mach/mach_port.h> - -#include "sysdeps.h" - -#include <stdio.h> - -#define TRACE_TAG TRACE_USB -#include "adb.h" - -#define DBG D - -typedef struct { - int vid; - int pid; -} VendorProduct; - -#define kSupportedDeviceCount 4 -VendorProduct kSupportedDevices[kSupportedDeviceCount] = { - { VENDOR_ID_GOOGLE, PRODUCT_ID_SOONER }, - { VENDOR_ID_GOOGLE, PRODUCT_ID_SOONER_COMP }, - { VENDOR_ID_HTC, PRODUCT_ID_DREAM }, - { VENDOR_ID_HTC, PRODUCT_ID_DREAM_COMP }, -}; - -static IONotificationPortRef notificationPort = 0; -static io_iterator_t notificationIterators[kSupportedDeviceCount]; - -struct usb_handle -{ - UInt8 bulkIn; - UInt8 bulkOut; - IOUSBInterfaceInterface **interface; - io_object_t usbNotification; - unsigned int zero_mask; -}; - -static CFRunLoopRef currentRunLoop = 0; -static pthread_mutex_t start_lock; -static pthread_cond_t start_cond; - - -static void AndroidDeviceAdded(void *refCon, io_iterator_t iterator); -static void AndroidDeviceNotify(void *refCon, io_iterator_t iterator, natural_t messageType, void *messageArgument); -static usb_handle* FindDeviceInterface(IOUSBDeviceInterface **dev, UInt16 vendor, UInt16 product); - -static int -InitUSB() -{ - CFMutableDictionaryRef matchingDict; - CFRunLoopSourceRef runLoopSource; - SInt32 vendor, product; - int i; - - //* To set up asynchronous notifications, create a notification port and - //* add its run loop event source to the program's run loop - notificationPort = IONotificationPortCreate(kIOMasterPortDefault); - runLoopSource = IONotificationPortGetRunLoopSource(notificationPort); - CFRunLoopAddSource(CFRunLoopGetCurrent(), runLoopSource, kCFRunLoopDefaultMode); - - memset(notificationIterators, 0, sizeof(notificationIterators)); - - //* loop through all supported vendor/product pairs - for (i = 0; i < kSupportedDeviceCount; i++) { - //* Create our matching dictionary to find the Android device - //* IOServiceAddMatchingNotification consumes the reference, so we do not need to release this - matchingDict = IOServiceMatching(kIOUSBDeviceClassName); - - if (!matchingDict) { - DBG("ERR: Couldn't create USB matching dictionary.\n"); - return -1; - } - - //* Set up two matching dictionaries, one for each product ID we support. - //* This will cause the kernel to notify us only if the vendor and product IDs match. - vendor = kSupportedDevices[i].vid; - product = kSupportedDevices[i].pid; - CFDictionarySetValue(matchingDict, CFSTR(kUSBVendorID), CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &vendor)); - CFDictionarySetValue(matchingDict, CFSTR(kUSBProductID), CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &product)); - - //* Now set up two notifications: one to be called when a raw device - //* is first matched by the I/O Kit and another to be called when the - //* device is terminated. - //* we need to do this with each matching dictionary. - IOServiceAddMatchingNotification( - notificationPort, - kIOFirstMatchNotification, - matchingDict, - AndroidDeviceAdded, - NULL, - ¬ificationIterators[i]); - - //* Iterate over set of matching devices to access already-present devices - //* and to arm the notification - AndroidDeviceAdded(NULL, notificationIterators[i]); - } - - return 0; -} - -static void -AndroidDeviceAdded(void *refCon, io_iterator_t iterator) -{ - kern_return_t kr; - io_service_t usbDevice; - IOCFPlugInInterface **plugInInterface = NULL; - IOUSBDeviceInterface182 **dev = NULL; - HRESULT result; - SInt32 score; - UInt16 vendor; - UInt16 product; - UInt8 serialIndex; - char serial[256]; - - while ((usbDevice = IOIteratorNext(iterator))) { - //* Create an intermediate plugin - kr = IOCreatePlugInInterfaceForService(usbDevice, - kIOUSBDeviceUserClientTypeID, - kIOCFPlugInInterfaceID, - &plugInInterface, &score); - - if ((kIOReturnSuccess != kr) || (!plugInInterface)) { - DBG("ERR: Unable to create a plug-in (%08x)\n", kr); - goto continue1; - } - - //* Now create the device interface - result = (*plugInInterface)->QueryInterface(plugInInterface, - CFUUIDGetUUIDBytes(kIOUSBDeviceInterfaceID), (LPVOID) &dev); - - if (result || !dev) { - DBG("ERR: Couldn't create a device interface (%08x)\n", (int) result); - goto continue2; - } - - //* Check the device to see if it's ours - kr = (*dev)->GetDeviceVendor(dev, &vendor); - kr = (*dev)->GetDeviceProduct(dev, &product); - kr = (*dev)->USBGetSerialNumberStringIndex(dev, &serialIndex); - - if (serialIndex > 0) { - IOUSBDevRequest req; - UInt16 buffer[256]; - - req.bmRequestType = USBmakebmRequestType(kUSBIn, kUSBStandard, kUSBDevice); - req.bRequest = kUSBRqGetDescriptor; - req.wValue = (kUSBStringDesc << 8) | serialIndex; - req.wIndex = 0; - req.pData = buffer; - req.wLength = sizeof(buffer); - kr = (*dev)->DeviceRequest(dev, &req); - - if (kr == kIOReturnSuccess && req.wLenDone > 0) { - int i, count; - - // skip first word, and copy the rest to the serial string, changing shorts to bytes. - count = (req.wLenDone - 1) / 2; - for (i = 0; i < count; i++) - serial[i] = buffer[i + 1]; - serial[i] = 0; - } - } - - usb_handle* handle = NULL; - - //* Open the device - kr = (*dev)->USBDeviceOpen(dev); - - if (kr != kIOReturnSuccess) { - DBG("ERR: Could not open device: %08x\n", kr); - goto continue3; - } else { - //* Find an interface for the device - handle = FindDeviceInterface((IOUSBDeviceInterface**)dev, vendor, product); - } - - if (handle == NULL) { - DBG("ERR: Could not find device interface: %08x\n", kr); - (*dev)->USBDeviceClose(dev); - goto continue3; - } - - DBG("AndroidDeviceAdded calling register_usb_transport\n"); - register_usb_transport(handle, (serial[0] ? serial : NULL)); - - // Register for an interest notification of this device being removed. Pass the reference to our - // private data as the refCon for the notification. - kr = IOServiceAddInterestNotification(notificationPort, - usbDevice, - kIOGeneralInterest, - AndroidDeviceNotify, - handle, - &handle->usbNotification); - if (kIOReturnSuccess != kr) { - DBG("ERR: Unable to create interest notification (%08x)\n", kr); - } - -continue3: - (void)(*dev)->Release(dev); -continue2: - IODestroyPlugInInterface(plugInInterface); -continue1: - IOObjectRelease(usbDevice); - } -} - -static void -AndroidDeviceNotify(void *refCon, io_service_t service, natural_t messageType, void *messageArgument) -{ - usb_handle *handle = (usb_handle *)refCon; - - if (messageType == kIOMessageServiceIsTerminated) { - DBG("AndroidDeviceNotify\n"); - IOObjectRelease(handle->usbNotification); - usb_kick(handle); - } -} - -static usb_handle* -FindDeviceInterface(IOUSBDeviceInterface **dev, UInt16 vendor, UInt16 product) -{ - usb_handle* handle = NULL; - IOReturn kr; - IOUSBFindInterfaceRequest request; - io_iterator_t iterator; - io_service_t usbInterface; - IOCFPlugInInterface **plugInInterface; - IOUSBInterfaceInterface **interface = NULL; - HRESULT result; - SInt32 score; - UInt8 interfaceNumEndpoints, interfaceClass, interfaceSubClass, interfaceProtocol; - UInt8 endpoint, configuration; - - //* Placing the constant KIOUSBFindInterfaceDontCare into the following - //* fields of the IOUSBFindInterfaceRequest structure will allow us to - //* find all of the interfaces - request.bInterfaceClass = kIOUSBFindInterfaceDontCare; - request.bInterfaceSubClass = kIOUSBFindInterfaceDontCare; - request.bInterfaceProtocol = kIOUSBFindInterfaceDontCare; - request.bAlternateSetting = kIOUSBFindInterfaceDontCare; - - //* SetConfiguration will kill an existing UMS connection, so let's not do this if not necessary. - configuration = 0; - (*dev)->GetConfiguration(dev, &configuration); - if (configuration != 1) - (*dev)->SetConfiguration(dev, 1); - - //* Get an iterator for the interfaces on the device - kr = (*dev)->CreateInterfaceIterator(dev, &request, &iterator); - - if (kr != kIOReturnSuccess) { - DBG("ERR: Couldn't create a device interface iterator: (%08x)\n", kr); - return NULL; - } - - while ((usbInterface = IOIteratorNext(iterator))) { - //* Create an intermediate plugin - kr = IOCreatePlugInInterfaceForService( - usbInterface, - kIOUSBInterfaceUserClientTypeID, - kIOCFPlugInInterfaceID, - &plugInInterface, - &score); - - //* No longer need the usbInterface object now that we have the plugin - (void) IOObjectRelease(usbInterface); - - if ((kr != kIOReturnSuccess) || (!plugInInterface)) { - DBG("ERR: Unable to create plugin (%08x)\n", kr); - break; - } - - //* Now create the interface interface for the interface - result = (*plugInInterface)->QueryInterface( - plugInInterface, - CFUUIDGetUUIDBytes(kIOUSBInterfaceInterfaceID), - (LPVOID) &interface); - - //* No longer need the intermediate plugin - (*plugInInterface)->Release(plugInInterface); - - if (result || !interface) { - DBG("ERR: Couldn't create interface interface: (%08x)\n", - (unsigned int) result); - break; - } - - //* Now open the interface. This will cause the pipes associated with - //* the endpoints in the interface descriptor to be instantiated - kr = (*interface)->USBInterfaceOpen(interface); - - if (kr != kIOReturnSuccess) - { - DBG("ERR: Could not open interface: (%08x)\n", kr); - (void) (*interface)->Release(interface); - //* continue so we can try the next interface - continue; - } - - //* Get the number of endpoints associated with this interface - kr = (*interface)->GetNumEndpoints(interface, &interfaceNumEndpoints); - - if (kr != kIOReturnSuccess) { - DBG("ERR: Unable to get number of endpoints: (%08x)\n", kr); - goto next_interface; - } - - //* Get interface class, subclass and protocol - if ((*interface)->GetInterfaceClass(interface, &interfaceClass) != kIOReturnSuccess || - (*interface)->GetInterfaceSubClass(interface, &interfaceSubClass) != kIOReturnSuccess || - (*interface)->GetInterfaceProtocol(interface, &interfaceProtocol) != kIOReturnSuccess) - { - DBG("ERR: Unable to get interface class, subclass and protocol\n"); - goto next_interface; - } - - //* check to make sure interface class, subclass and protocol match ADB - //* avoid opening mass storage endpoints - if (is_adb_interface(vendor, product, interfaceClass, interfaceSubClass, interfaceProtocol)) { - handle = calloc(1, sizeof(usb_handle)); - - //* Iterate over the endpoints for this interface and find the first - //* bulk in/out pipes available. These will be our read/write pipes. - for (endpoint = 0; endpoint <= interfaceNumEndpoints; endpoint++) { - UInt8 transferType; - UInt16 maxPacketSize; - UInt8 interval; - UInt8 number; - UInt8 direction; - - kr = (*interface)->GetPipeProperties(interface, endpoint, &direction, - &number, &transferType, &maxPacketSize, &interval); - - if (kIOReturnSuccess == kr) { - if (kUSBBulk != transferType) - continue; - - if (kUSBIn == direction) - handle->bulkIn = endpoint; - - if (kUSBOut == direction) - handle->bulkOut = endpoint; - - if (interfaceProtocol == 0x01) { - handle->zero_mask = maxPacketSize - 1; - } - - } else { - DBG("ERR: FindDeviceInterface - could not get pipe properties\n"); - } - } - - handle->interface = interface; - break; - } - -next_interface: - (*interface)->USBInterfaceClose(interface); - (*interface)->Release(interface); - } - - return handle; -} - - -void* RunLoopThread(void* unused) -{ - int i; - - InitUSB(); - - currentRunLoop = CFRunLoopGetCurrent(); - - // Signal the parent that we are running - adb_mutex_lock(&start_lock); - adb_cond_signal(&start_cond); - adb_mutex_unlock(&start_lock); - - CFRunLoopRun(); - currentRunLoop = 0; - - for (i = 0; i < kSupportedDeviceCount; i++) { - IOObjectRelease(notificationIterators[i]); - } - IONotificationPortDestroy(notificationPort); - - DBG("RunLoopThread done\n"); - return NULL; -} - - -static int initialized = 0; -void usb_init() -{ - if (!initialized) - { - adb_thread_t tid; - - adb_mutex_init(&start_lock, NULL); - adb_cond_init(&start_cond, NULL); - - if(adb_thread_create(&tid, RunLoopThread, NULL)) - fatal_errno("cannot create input thread"); - - // Wait for initialization to finish - adb_mutex_lock(&start_lock); - adb_cond_wait(&start_cond, &start_lock); - adb_mutex_unlock(&start_lock); - - adb_mutex_destroy(&start_lock); - adb_cond_destroy(&start_cond); - - initialized = 1; - } -} - -void usb_cleanup() -{ - DBG("usb_cleanup\n"); - close_usb_devices(); - if (currentRunLoop) - CFRunLoopStop(currentRunLoop); -} - -int usb_write(usb_handle *handle, const void *buf, int len) -{ - IOReturn result; - - if (!len) - return 0; - - if (!handle) - return -1; - - if (NULL == handle->interface) { - DBG("ERR: usb_write interface was null\n"); - return -1; - } - - if (0 == handle->bulkOut) { - DBG("ERR: bulkOut endpoint not assigned\n"); - return -1; - } - - result = - (*handle->interface)->WritePipe( - handle->interface, handle->bulkOut, (void *)buf, len); - - if ((result == 0) && (handle->zero_mask)) { - /* we need 0-markers and our transfer */ - if(!(len & handle->zero_mask)) { - result = - (*handle->interface)->WritePipe( - handle->interface, handle->bulkOut, (void *)buf, 0); - } - } - - if (0 == result) - return 0; - - DBG("ERR: usb_write failed with status %d\n", result); - return -1; -} - -int usb_read(usb_handle *handle, void *buf, int len) -{ - IOReturn result; - UInt32 numBytes = len; - - if (!len) { - return 0; - } - - if (!handle) { - return -1; - } - - if (NULL == handle->interface) { - DBG("ERR: usb_read interface was null\n"); - return -1; - } - - if (0 == handle->bulkIn) { - DBG("ERR: bulkIn endpoint not assigned\n"); - return -1; - } - - result = - (*handle->interface)->ReadPipe(handle->interface, - handle->bulkIn, buf, &numBytes); - - if (0 == result) - return 0; - else { - DBG("ERR: usb_read failed with status %d\n", result); - } - - return -1; -} - -int usb_close(usb_handle *handle) -{ - return 0; -} - -void usb_kick(usb_handle *handle) -{ - /* release the interface */ - if (handle->interface) - { - (*handle->interface)->USBInterfaceClose(handle->interface); - (*handle->interface)->Release(handle->interface); - handle->interface = 0; - } -} diff --git a/adb/usb_windows.c b/adb/usb_windows.c deleted file mode 100644 index 7ddaa0c1..00000000 --- a/adb/usb_windows.c +++ /dev/null @@ -1,513 +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 <windows.h> -#include <winerror.h> -#include <errno.h> -#include <usb100.h> -#include <adb_api.h> -#include <stdio.h> - -#include "sysdeps.h" - -#define TRACE_TAG TRACE_USB -#include "adb.h" - -/** Structure usb_handle describes our connection to the usb device via - AdbWinApi.dll. This structure is returned from usb_open() routine and - is expected in each subsequent call that is accessing the device. -*/ -struct usb_handle { - /// Previous entry in the list of opened usb handles - usb_handle *prev; - - /// Next entry in the list of opened usb handles - usb_handle *next; - - /// Handle to USB interface - ADBAPIHANDLE adb_interface; - - /// Handle to USB read pipe (endpoint) - ADBAPIHANDLE adb_read_pipe; - - /// Handle to USB write pipe (endpoint) - ADBAPIHANDLE adb_write_pipe; - - /// Interface name - char* interface_name; - - /// Mask for determining when to use zero length packets - unsigned zero_mask; -}; - -/// Class ID assigned to the device by androidusb.sys -static const GUID usb_class_id = ANDROID_USB_CLASS_ID; - -/// List of opened usb handles -static usb_handle handle_list = { - .prev = &handle_list, - .next = &handle_list, -}; - -/// Locker for the list of opened usb handles -ADB_MUTEX_DEFINE( usb_lock ); - -/// Checks if there is opened usb handle in handle_list for this device. -int known_device(const char* dev_name); - -/// Checks if there is opened usb handle in handle_list for this device. -/// usb_lock mutex must be held before calling this routine. -int known_device_locked(const char* dev_name); - -/// Registers opened usb handle (adds it to handle_list). -int register_new_device(usb_handle* handle); - -/// Checks if interface (device) matches certain criteria -int recognized_device(usb_handle* handle); - -/// Enumerates present and available interfaces (devices), opens new ones and -/// registers usb transport for them. -void find_devices(); - -/// Entry point for thread that polls (every second) for new usb interfaces. -/// This routine calls find_devices in infinite loop. -void* device_poll_thread(void* unused); - -/// Initializes this module -void usb_init(); - -/// Cleans up this module -void usb_cleanup(); - -/// Opens usb interface (device) by interface (device) name. -usb_handle* do_usb_open(const wchar_t* interface_name); - -/// Writes data to the opened usb handle -int usb_write(usb_handle* handle, const void* data, int len); - -/// Reads data using the opened usb handle -int usb_read(usb_handle *handle, void* data, int len); - -/// Cleans up opened usb handle -void usb_cleanup_handle(usb_handle* handle); - -/// Cleans up (but don't close) opened usb handle -void usb_kick(usb_handle* handle); - -/// Closes opened usb handle -int usb_close(usb_handle* handle); - -/// Gets interface (device) name for an opened usb handle -const char *usb_name(usb_handle* handle); - -int known_device_locked(const char* dev_name) { - usb_handle* usb; - - if (NULL != dev_name) { - // Iterate through the list looking for the name match. - for(usb = handle_list.next; usb != &handle_list; usb = usb->next) { - // In Windows names are not case sensetive! - if((NULL != usb->interface_name) && - (0 == stricmp(usb->interface_name, dev_name))) { - return 1; - } - } - } - - return 0; -} - -int known_device(const char* dev_name) { - int ret = 0; - - if (NULL != dev_name) { - adb_mutex_lock(&usb_lock); - ret = known_device_locked(dev_name); - adb_mutex_unlock(&usb_lock); - } - - return ret; -} - -int register_new_device(usb_handle* handle) { - if (NULL == handle) - return 0; - - adb_mutex_lock(&usb_lock); - - // Check if device is already in the list - if (known_device_locked(handle->interface_name)) { - adb_mutex_unlock(&usb_lock); - return 0; - } - - // Not in the list. Add this handle to the list. - handle->next = &handle_list; - handle->prev = handle_list.prev; - handle->prev->next = handle; - handle->next->prev = handle; - - adb_mutex_unlock(&usb_lock); - - return 1; -} - -void* device_poll_thread(void* unused) { - D("Created device thread\n"); - - while(1) { - find_devices(); - adb_sleep_ms(1000); - } - - return NULL; -} - -void usb_init() { - adb_thread_t tid; - - if(adb_thread_create(&tid, device_poll_thread, NULL)) { - fatal_errno("cannot create input thread"); - } -} - -void usb_cleanup() { -} - -usb_handle* do_usb_open(const wchar_t* interface_name) { - // Allocate our handle - usb_handle* ret = (usb_handle*)malloc(sizeof(usb_handle)); - if (NULL == ret) - return NULL; - - // Set linkers back to the handle - ret->next = ret; - ret->prev = ret; - - // Create interface. - ret->adb_interface = AdbCreateInterfaceByName(interface_name); - - if (NULL == ret->adb_interface) { - free(ret); - errno = GetLastError(); - return NULL; - } - - // Open read pipe (endpoint) - ret->adb_read_pipe = - AdbOpenDefaultBulkReadEndpoint(ret->adb_interface, - AdbOpenAccessTypeReadWrite, - AdbOpenSharingModeReadWrite); - if (NULL != ret->adb_read_pipe) { - // Open write pipe (endpoint) - ret->adb_write_pipe = - AdbOpenDefaultBulkWriteEndpoint(ret->adb_interface, - AdbOpenAccessTypeReadWrite, - AdbOpenSharingModeReadWrite); - if (NULL != ret->adb_write_pipe) { - // Save interface name - unsigned long name_len = 0; - - // First get expected name length - AdbGetInterfaceName(ret->adb_interface, - NULL, - &name_len, - true); - if (0 != name_len) { - ret->interface_name = (char*)malloc(name_len); - - if (NULL != ret->interface_name) { - // Now save the name - if (AdbGetInterfaceName(ret->adb_interface, - ret->interface_name, - &name_len, - true)) { - // We're done at this point - return ret; - } - } else { - SetLastError(ERROR_OUTOFMEMORY); - } - } - } - } - - // Something went wrong. - errno = GetLastError(); - usb_cleanup_handle(ret); - free(ret); - SetLastError(errno); - - return NULL; -} - -int usb_write(usb_handle* handle, const void* data, int len) { - unsigned long time_out = 500 + len * 8; - unsigned long written = 0; - int ret; - - D("usb_write %d\n", len); - if (NULL != handle) { - // Perform write - ret = AdbWriteEndpointSync(handle->adb_write_pipe, - (void*)data, - (unsigned long)len, - &written, - time_out); - errno = GetLastError(); - - if (ret) { - // Make sure that we've written what we were asked to write - D("usb_write got: %ld, expected: %d\n", written, len); - if (written == (unsigned long)len) { - if(handle->zero_mask && (len & handle->zero_mask) == 0) { - // Send a zero length packet - AdbWriteEndpointSync(handle->adb_write_pipe, - (void*)data, - 0, - &written, - time_out); - } - return 0; - } - } else { - // assume ERROR_INVALID_HANDLE indicates we are disconnected - if (errno == ERROR_INVALID_HANDLE) - usb_kick(handle); - } - } else { - D("usb_write NULL handle\n"); - SetLastError(ERROR_INVALID_HANDLE); - } - - D("usb_write failed: %d\n", errno); - - return -1; -} - -int usb_read(usb_handle *handle, void* data, int len) { - unsigned long time_out = 500 + len * 8; - unsigned long read = 0; - int ret; - - D("usb_read %d\n", len); - if (NULL != handle) { - while (len > 0) { - int xfer = (len > 4096) ? 4096 : len; - - ret = AdbReadEndpointSync(handle->adb_read_pipe, - (void*)data, - (unsigned long)xfer, - &read, - time_out); - errno = GetLastError(); - D("usb_write got: %ld, expected: %d, errno: %d\n", read, xfer, errno); - if (ret) { - data += read; - len -= read; - - if (len == 0) - return 0; - } else if (errno != ERROR_SEM_TIMEOUT) { - // assume ERROR_INVALID_HANDLE indicates we are disconnected - if (errno == ERROR_INVALID_HANDLE) - usb_kick(handle); - break; - } - } - } else { - D("usb_read NULL handle\n"); - SetLastError(ERROR_INVALID_HANDLE); - } - - D("usb_read failed: %d\n", errno); - - return -1; -} - -void usb_cleanup_handle(usb_handle* handle) { - if (NULL != handle) { - if (NULL != handle->interface_name) - free(handle->interface_name); - if (NULL != handle->adb_write_pipe) - AdbCloseHandle(handle->adb_write_pipe); - if (NULL != handle->adb_read_pipe) - AdbCloseHandle(handle->adb_read_pipe); - if (NULL != handle->adb_interface) - AdbCloseHandle(handle->adb_interface); - - handle->interface_name = NULL; - handle->adb_write_pipe = NULL; - handle->adb_read_pipe = NULL; - handle->adb_interface = NULL; - } -} - -void usb_kick(usb_handle* handle) { - if (NULL != handle) { - adb_mutex_lock(&usb_lock); - - usb_cleanup_handle(handle); - - adb_mutex_unlock(&usb_lock); - } else { - SetLastError(ERROR_INVALID_HANDLE); - errno = ERROR_INVALID_HANDLE; - } -} - -int usb_close(usb_handle* handle) { - D("usb_close\n"); - - if (NULL != handle) { - // Remove handle from the list - adb_mutex_lock(&usb_lock); - - if ((handle->next != handle) && (handle->prev != handle)) { - handle->next->prev = handle->prev; - handle->prev->next = handle->next; - handle->prev = handle; - handle->next = handle; - } - - adb_mutex_unlock(&usb_lock); - - // Cleanup handle - usb_cleanup_handle(handle); - free(handle); - } - - return 0; -} - -const char *usb_name(usb_handle* handle) { - if (NULL == handle) { - SetLastError(ERROR_INVALID_HANDLE); - errno = ERROR_INVALID_HANDLE; - return NULL; - } - - return (const char*)handle->interface_name; -} - -int recognized_device(usb_handle* handle) { - if (NULL == handle) - return 0; - - // Check vendor and product id first - USB_DEVICE_DESCRIPTOR device_desc; - - if (!AdbGetUsbDeviceDescriptor(handle->adb_interface, - &device_desc)) { - return 0; - } - - // Then check interface properties - USB_INTERFACE_DESCRIPTOR interf_desc; - - if (!AdbGetUsbInterfaceDescriptor(handle->adb_interface, - &interf_desc)) { - return 0; - } - - // Must have two endpoints - if (2 != interf_desc.bNumEndpoints) { - return 0; - } - - if (is_adb_interface(device_desc.idVendor, device_desc.idProduct, - interf_desc.bInterfaceClass, interf_desc.bInterfaceSubClass, interf_desc.bInterfaceProtocol)) { - - if(interf_desc.bInterfaceProtocol == 0x01) { - AdbEndpointInformation endpoint_info; - // assuming zero is a valid bulk endpoint ID - if (AdbGetEndpointInformation(handle->adb_interface, 0, &endpoint_info)) { - handle->zero_mask = endpoint_info.max_packet_size - 1; - } - } - - return 1; - } - - return 0; -} - -void find_devices() { - usb_handle* handle = NULL; - char entry_buffer[2048]; - char interf_name[2048]; - AdbInterfaceInfo* next_interface = (AdbInterfaceInfo*)(&entry_buffer[0]); - unsigned long entry_buffer_size = sizeof(entry_buffer); - char* copy_name; - - // Enumerate all present and active interfaces. - ADBAPIHANDLE enum_handle = - AdbEnumInterfaces(usb_class_id, true, true, true); - - if (NULL == enum_handle) - return; - - while (AdbNextInterface(enum_handle, next_interface, &entry_buffer_size)) { - // TODO: FIXME - temp hack converting wchar_t into char. - // It would be better to change AdbNextInterface so it will return - // interface name as single char string. - const wchar_t* wchar_name = next_interface->device_name; - for(copy_name = interf_name; - L'\0' != *wchar_name; - wchar_name++, copy_name++) { - *copy_name = (char)(*wchar_name); - } - *copy_name = '\0'; - - // Lets see if we already have this device in the list - if (!known_device(interf_name)) { - // This seems to be a new device. Open it! - handle = do_usb_open(next_interface->device_name); - if (NULL != handle) { - // Lets see if this interface (device) belongs to us - if (recognized_device(handle)) { - D("adding a new device %s\n", interf_name); - char serial_number[512]; - unsigned long serial_number_len = sizeof(serial_number); - if (AdbGetSerialNumber(handle->adb_interface, - serial_number, - &serial_number_len, - true)) { - // Lets make sure that we don't duplicate this device - if (register_new_device(handle)) { - register_usb_transport(handle, serial_number); - } else { - D("register_new_device failed for %s\n", interf_name); - usb_cleanup_handle(handle); - free(handle); - } - } else { - D("cannot get serial number\n"); - usb_cleanup_handle(handle); - free(handle); - } - } else { - usb_cleanup_handle(handle); - free(handle); - } - } - } - - entry_buffer_size = sizeof(entry_buffer); - } - - AdbCloseHandle(enum_handle); -} diff --git a/adb/utils.c b/adb/utils.c deleted file mode 100644 index 91518bab..00000000 --- a/adb/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/adb/utils.h b/adb/utils.h deleted file mode 100644 index f70ecd24..00000000 --- a/adb/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 */ |
