diff -Nru android-tools-4.2.2+git20130218/core/adb/adb.c android-tools-4.2.2+git20130529/core/adb/adb.c --- android-tools-4.2.2+git20130218/core/adb/adb.c 2013-02-18 14:49:03.000000000 +0000 +++ android-tools-4.2.2+git20130529/core/adb/adb.c 2013-05-29 20:16:54.000000000 +0000 @@ -35,7 +35,7 @@ #if !ADB_HOST #include -#include +#include #include #include #else @@ -401,6 +401,10 @@ return "bootloader"; case CS_DEVICE: return "device"; + case CS_RECOVERY: + return "recovery"; + case CS_SIDELOAD: + return "sideload"; case CS_OFFLINE: return "offline"; default: diff -Nru android-tools-4.2.2+git20130218/core/adb/commandline.c android-tools-4.2.2+git20130529/core/adb/commandline.c --- android-tools-4.2.2+git20130218/core/adb/commandline.c 2013-02-18 14:49:03.000000000 +0000 +++ android-tools-4.2.2+git20130529/core/adb/commandline.c 2013-05-29 20:16:54.000000000 +0000 @@ -383,7 +383,7 @@ } } -int adb_download_buffer(const char *service, const void* data, int sz, +int adb_download_buffer(const char *service, const char *fn, const void* data, int sz, unsigned progress) { char buf[4096]; @@ -419,7 +419,7 @@ sz -= xfer; ptr += xfer; if(progress) { - printf("sending: '%s' %4d%% \r", service, (int)(100LL - ((100LL * sz) / (total)))); + printf("sending: '%s' %4d%% \r", fn, (int)(100LL - ((100LL * sz) / (total)))); fflush(stdout); } } @@ -451,11 +451,11 @@ data = load_file(fn, &sz); if(data == 0) { - fprintf(stderr,"* cannot read '%s' *\n", service); + fprintf(stderr,"* cannot read '%s' *\n", fn); return -1; } - int status = adb_download_buffer(service, data, sz, progress); + int status = adb_download_buffer(service, fn, data, sz, progress); free(data); return status; } diff -Nru android-tools-4.2.2+git20130218/core/adb/usb_vendors.c android-tools-4.2.2+git20130529/core/adb/usb_vendors.c --- android-tools-4.2.2+git20130218/core/adb/usb_vendors.c 2013-02-18 14:49:03.000000000 +0000 +++ android-tools-4.2.2+git20130529/core/adb/usb_vendors.c 2013-05-29 20:16:54.000000000 +0000 @@ -131,6 +131,18 @@ #define VENDOR_ID_KOBO 0x2237 // Teleepoch's USB Vendor ID #define VENDOR_ID_TELEEPOCH 0x2340 +// AnyDATA's USB Vendor ID +#define VENDOR_ID_ANYDATA 0x16D5 +// Harris's USB Vendor ID +#define VENDOR_ID_HARRIS 0x19A5 +// OPPO's USB Vendor ID +#define VENDOR_ID_OPPO 0x22D9 +// Xiaomi's USB Vendor ID +#define VENDOR_ID_XIAOMI 0x2717 +// BYD's USB Vendor ID +#define VENDOR_ID_BYD 0x19D1 +// OUYA's USB Vendor ID +#define VENDOR_ID_OUYA 0x2836 /** built-in vendor list */ @@ -183,6 +195,12 @@ VENDOR_ID_YULONG_COOLPAD, VENDOR_ID_KOBO, VENDOR_ID_TELEEPOCH, + VENDOR_ID_ANYDATA, + VENDOR_ID_HARRIS, + VENDOR_ID_OPPO, + VENDOR_ID_XIAOMI, + VENDOR_ID_BYD, + VENDOR_ID_OUYA, }; #define BUILT_IN_VENDOR_COUNT (sizeof(builtInVendorIds)/sizeof(builtInVendorIds[0])) @@ -235,6 +253,7 @@ break; } } + fclose(f); } } } diff -Nru android-tools-4.2.2+git20130218/core/include/cutils/debugger.h android-tools-4.2.2+git20130529/core/include/cutils/debugger.h --- android-tools-4.2.2+git20130218/core/include/cutils/debugger.h 2013-02-18 14:49:03.000000000 +0000 +++ android-tools-4.2.2+git20130529/core/include/cutils/debugger.h 2013-05-29 20:16:54.000000000 +0000 @@ -34,10 +34,10 @@ DEBUGGER_ACTION_DUMP_BACKTRACE, } debugger_action_t; -/* message sent over the socket */ typedef struct { debugger_action_t action; pid_t tid; + uintptr_t abort_msg_address; } debugger_msg_t; /* Dumps a process backtrace, registers, and stack to a tombstone file (requires root). diff -Nru android-tools-4.2.2+git20130218/core/include/private/android_filesystem_capability.h android-tools-4.2.2+git20130529/core/include/private/android_filesystem_capability.h --- android-tools-4.2.2+git20130218/core/include/private/android_filesystem_capability.h 1970-01-01 00:00:00.000000000 +0000 +++ android-tools-4.2.2+git20130529/core/include/private/android_filesystem_capability.h 2013-05-29 20:16:54.000000000 +0000 @@ -0,0 +1,117 @@ +/* + * Copyright (C) 2013 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. + */ + +/* + * Taken from linux/capability.h, with minor modifications + */ + +#ifndef _SYSTEM_CORE_INCLUDE_PRIVATE_ANDROID_FILESYSTEM_CAPABILITY_H +#define _SYSTEM_CORE_INCLUDE_PRIVATE_ANDROID_FILESYSTEM_CAPABILITY_H + +#include + +#define __user +#define __u32 uint32_t +#define __le32 uint32_t + +#define _LINUX_CAPABILITY_VERSION_1 0x19980330 +#define _LINUX_CAPABILITY_U32S_1 1 +#define _LINUX_CAPABILITY_VERSION_2 0x20071026 +#define _LINUX_CAPABILITY_U32S_2 2 +#define _LINUX_CAPABILITY_VERSION_3 0x20080522 +#define _LINUX_CAPABILITY_U32S_3 2 + +typedef struct __user_cap_header_struct { + __u32 version; + int pid; +} __user *cap_user_header_t; + +typedef struct __user_cap_data_struct { + __u32 effective; + __u32 permitted; + __u32 inheritable; +} __user *cap_user_data_t; + +#define VFS_CAP_REVISION_MASK 0xFF000000 +#define VFS_CAP_REVISION_SHIFT 24 +#define VFS_CAP_FLAGS_MASK ~VFS_CAP_REVISION_MASK +#define VFS_CAP_FLAGS_EFFECTIVE 0x000001 +#define VFS_CAP_REVISION_1 0x01000000 +#define VFS_CAP_U32_1 1 +#define XATTR_CAPS_SZ_1 (sizeof(__le32)*(1 + 2*VFS_CAP_U32_1)) +#define VFS_CAP_REVISION_2 0x02000000 +#define VFS_CAP_U32_2 2 +#define XATTR_CAPS_SZ_2 (sizeof(__le32)*(1 + 2*VFS_CAP_U32_2)) +#define XATTR_CAPS_SZ XATTR_CAPS_SZ_2 +#define VFS_CAP_U32 VFS_CAP_U32_2 +#define VFS_CAP_REVISION VFS_CAP_REVISION_2 + +struct vfs_cap_data { + __le32 magic_etc; + struct { + __le32 permitted; + __le32 inheritable; + } data[VFS_CAP_U32]; +}; + +#define _LINUX_CAPABILITY_VERSION _LINUX_CAPABILITY_VERSION_1 +#define _LINUX_CAPABILITY_U32S _LINUX_CAPABILITY_U32S_1 +#define CAP_CHOWN 0 +#define CAP_DAC_OVERRIDE 1 +#define CAP_DAC_READ_SEARCH 2 +#define CAP_FOWNER 3 +#define CAP_FSETID 4 +#define CAP_KILL 5 +#define CAP_SETGID 6 +#define CAP_SETUID 7 +#define CAP_SETPCAP 8 +#define CAP_LINUX_IMMUTABLE 9 +#define CAP_NET_BIND_SERVICE 10 +#define CAP_NET_BROADCAST 11 +#define CAP_NET_ADMIN 12 +#define CAP_NET_RAW 13 +#define CAP_IPC_LOCK 14 +#define CAP_IPC_OWNER 15 +#define CAP_SYS_MODULE 16 +#define CAP_SYS_RAWIO 17 +#define CAP_SYS_CHROOT 18 +#define CAP_SYS_PTRACE 19 +#define CAP_SYS_PACCT 20 +#define CAP_SYS_ADMIN 21 +#define CAP_SYS_BOOT 22 +#define CAP_SYS_NICE 23 +#define CAP_SYS_RESOURCE 24 +#define CAP_SYS_TIME 25 +#define CAP_SYS_TTY_CONFIG 26 +#define CAP_MKNOD 27 +#define CAP_LEASE 28 +#define CAP_AUDIT_WRITE 29 +#define CAP_AUDIT_CONTROL 30 +#define CAP_SETFCAP 31 +#define CAP_MAC_OVERRIDE 32 +#define CAP_MAC_ADMIN 33 +#define CAP_SYSLOG 34 +#define CAP_WAKE_ALARM 35 +#define CAP_LAST_CAP CAP_WAKE_ALARM +#define cap_valid(x) ((x) >= 0 && (x) <= CAP_LAST_CAP) +#define CAP_TO_INDEX(x) ((x) >> 5) +#define CAP_TO_MASK(x) (1 << ((x) & 31)) + +#undef __user +#undef __u32 +#undef __le32 + +#endif diff -Nru android-tools-4.2.2+git20130218/core/include/private/android_filesystem_config.h android-tools-4.2.2+git20130529/core/include/private/android_filesystem_config.h --- android-tools-4.2.2+git20130218/core/include/private/android_filesystem_config.h 1970-01-01 00:00:00.000000000 +0000 +++ android-tools-4.2.2+git20130529/core/include/private/android_filesystem_config.h 2013-05-29 20:16:54.000000000 +0000 @@ -0,0 +1,283 @@ +/* + * 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 is used to define the properties of the filesystem +** images generated by build tools (mkbootfs and mkyaffs2image) and +** by the device side of adb. +*/ + +#ifndef _ANDROID_FILESYSTEM_CONFIG_H_ +#define _ANDROID_FILESYSTEM_CONFIG_H_ + +#include +#include +#include +#include + +#ifdef HAVE_ANDROID_OS +#include +#else +#include "android_filesystem_capability.h" +#endif + +/* This is the master Users and Groups config for the platform. +** DO NOT EVER RENUMBER. +*/ + +#define AID_ROOT 0 /* traditional unix root user */ + +#define AID_SYSTEM 1000 /* system server */ + +#define AID_RADIO 1001 /* telephony subsystem, RIL */ +#define AID_BLUETOOTH 1002 /* bluetooth subsystem */ +#define AID_GRAPHICS 1003 /* graphics devices */ +#define AID_INPUT 1004 /* input devices */ +#define AID_AUDIO 1005 /* audio devices */ +#define AID_CAMERA 1006 /* camera devices */ +#define AID_LOG 1007 /* log devices */ +#define AID_COMPASS 1008 /* compass device */ +#define AID_MOUNT 1009 /* mountd socket */ +#define AID_WIFI 1010 /* wifi subsystem */ +#define AID_ADB 1011 /* android debug bridge (adbd) */ +#define AID_INSTALL 1012 /* group for installing packages */ +#define AID_MEDIA 1013 /* mediaserver process */ +#define AID_DHCP 1014 /* dhcp client */ +#define AID_SDCARD_RW 1015 /* external storage write access */ +#define AID_VPN 1016 /* vpn system */ +#define AID_KEYSTORE 1017 /* keystore subsystem */ +#define AID_USB 1018 /* USB devices */ +#define AID_DRM 1019 /* DRM server */ +#define AID_MDNSR 1020 /* MulticastDNSResponder (service discovery) */ +#define AID_GPS 1021 /* GPS daemon */ +#define AID_UNUSED1 1022 /* deprecated, DO NOT USE */ +#define AID_MEDIA_RW 1023 /* internal media storage write access */ +#define AID_MTP 1024 /* MTP USB driver access */ +#define AID_UNUSED2 1025 /* deprecated, DO NOT USE */ +#define AID_DRMRPC 1026 /* group for drm rpc */ +#define AID_NFC 1027 /* nfc subsystem */ +#define AID_SDCARD_R 1028 /* external storage read access */ +#define AID_CLAT 1029 /* clat part of nat464 */ +#define AID_LOOP_RADIO 1030 /* loop radio devices */ + +#define AID_SHELL 2000 /* adb and debug shell user */ +#define AID_CACHE 2001 /* cache access */ +#define AID_DIAG 2002 /* access to diagnostic resources */ + +/* The 3000 series are intended for use as supplemental group id's only. + * They indicate special Android capabilities that the kernel is aware of. */ +#define AID_NET_BT_ADMIN 3001 /* bluetooth: create any socket */ +#define AID_NET_BT 3002 /* bluetooth: create sco, rfcomm or l2cap sockets */ +#define AID_INET 3003 /* can create AF_INET and AF_INET6 sockets */ +#define AID_NET_RAW 3004 /* can create raw INET sockets */ +#define AID_NET_ADMIN 3005 /* can configure interfaces and routing tables. */ +#define AID_NET_BW_STATS 3006 /* read bandwidth statistics */ +#define AID_NET_BW_ACCT 3007 /* change bandwidth statistics accounting */ +#define AID_NET_BT_STACK 3008 /* bluetooth: access config files */ + +#define AID_MISC 9998 /* access to misc storage */ +#define AID_NOBODY 9999 + +#define AID_APP 10000 /* first app user */ + +#define AID_ISOLATED_START 99000 /* start of uids for fully isolated sandboxed processes */ +#define AID_ISOLATED_END 99999 /* end of uids for fully isolated sandboxed processes */ + +#define AID_USER 100000 /* offset for uid ranges for each user */ + +#define AID_SHARED_GID_START 50000 /* start of gids for apps in each user to share */ +#define AID_SHARED_GID_END 59999 /* start of gids for apps in each user to share */ + +#if !defined(EXCLUDE_FS_CONFIG_STRUCTURES) +struct android_id_info { + const char *name; + unsigned aid; +}; + +static const struct android_id_info android_ids[] = { + { "root", AID_ROOT, }, + { "system", AID_SYSTEM, }, + { "radio", AID_RADIO, }, + { "bluetooth", AID_BLUETOOTH, }, + { "graphics", AID_GRAPHICS, }, + { "input", AID_INPUT, }, + { "audio", AID_AUDIO, }, + { "camera", AID_CAMERA, }, + { "log", AID_LOG, }, + { "compass", AID_COMPASS, }, + { "mount", AID_MOUNT, }, + { "wifi", AID_WIFI, }, + { "dhcp", AID_DHCP, }, + { "adb", AID_ADB, }, + { "install", AID_INSTALL, }, + { "media", AID_MEDIA, }, + { "drm", AID_DRM, }, + { "mdnsr", AID_MDNSR, }, + { "nfc", AID_NFC, }, + { "drmrpc", AID_DRMRPC, }, + { "shell", AID_SHELL, }, + { "cache", AID_CACHE, }, + { "diag", AID_DIAG, }, + { "net_bt_admin", AID_NET_BT_ADMIN, }, + { "net_bt", AID_NET_BT, }, + { "net_bt_stack", AID_NET_BT_STACK, }, + { "sdcard_r", AID_SDCARD_R, }, + { "sdcard_rw", AID_SDCARD_RW, }, + { "media_rw", AID_MEDIA_RW, }, + { "vpn", AID_VPN, }, + { "keystore", AID_KEYSTORE, }, + { "usb", AID_USB, }, + { "mtp", AID_MTP, }, + { "gps", AID_GPS, }, + { "inet", AID_INET, }, + { "net_raw", AID_NET_RAW, }, + { "net_admin", AID_NET_ADMIN, }, + { "net_bw_stats", AID_NET_BW_STATS, }, + { "net_bw_acct", AID_NET_BW_ACCT, }, + { "loop_radio", AID_LOOP_RADIO, }, + { "misc", AID_MISC, }, + { "nobody", AID_NOBODY, }, + { "clat", AID_CLAT, }, +}; + +#define android_id_count \ + (sizeof(android_ids) / sizeof(android_ids[0])) + +struct fs_path_config { + unsigned mode; + unsigned uid; + unsigned gid; + uint64_t capabilities; + const char *prefix; +}; + +/* Rules for directories. +** These rules are applied based on "first match", so they +** should start with the most specific path and work their +** way up to the root. +*/ + +static const struct fs_path_config android_dirs[] = { + { 00770, AID_SYSTEM, AID_CACHE, 0, "cache" }, + { 00771, AID_SYSTEM, AID_SYSTEM, 0, "data/app" }, + { 00771, AID_SYSTEM, AID_SYSTEM, 0, "data/app-private" }, + { 00771, AID_SYSTEM, AID_SYSTEM, 0, "data/dalvik-cache" }, + { 00771, AID_SYSTEM, AID_SYSTEM, 0, "data/data" }, + { 00771, AID_SHELL, AID_SHELL, 0, "data/local/tmp" }, + { 00771, AID_SHELL, AID_SHELL, 0, "data/local" }, + { 01771, AID_SYSTEM, AID_MISC, 0, "data/misc" }, + { 00770, AID_DHCP, AID_DHCP, 0, "data/misc/dhcp" }, + { 00775, AID_MEDIA_RW, AID_MEDIA_RW, 0, "data/media" }, + { 00775, AID_MEDIA_RW, AID_MEDIA_RW, 0, "data/media/Music" }, + { 00771, AID_SYSTEM, AID_SYSTEM, 0, "data" }, + { 00750, AID_ROOT, AID_SHELL, 0, "sbin" }, + { 00755, AID_ROOT, AID_SHELL, 0, "system/bin" }, + { 00755, AID_ROOT, AID_SHELL, 0, "system/vendor" }, + { 00755, AID_ROOT, AID_SHELL, 0, "system/xbin" }, + { 00755, AID_ROOT, AID_ROOT, 0, "system/etc/ppp" }, + { 00777, AID_ROOT, AID_ROOT, 0, "sdcard" }, + { 00755, AID_ROOT, AID_ROOT, 0, 0 }, +}; + +/* Rules for files. +** These rules are applied based on "first match", so they +** should start with the most specific path and work their +** way up to the root. Prefixes ending in * denotes wildcard +** and will allow partial matches. +*/ +static const struct fs_path_config android_files[] = { + { 00440, AID_ROOT, AID_SHELL, 0, "system/etc/init.goldfish.rc" }, + { 00550, AID_ROOT, AID_SHELL, 0, "system/etc/init.goldfish.sh" }, + { 00440, AID_ROOT, AID_SHELL, 0, "system/etc/init.trout.rc" }, + { 00550, AID_ROOT, AID_SHELL, 0, "system/etc/init.ril" }, + { 00550, AID_ROOT, AID_SHELL, 0, "system/etc/init.testmenu" }, + { 00550, AID_DHCP, AID_SHELL, 0, "system/etc/dhcpcd/dhcpcd-run-hooks" }, + { 00440, AID_BLUETOOTH, AID_BLUETOOTH, 0, "system/etc/dbus.conf" }, + { 00444, AID_RADIO, AID_AUDIO, 0, "system/etc/AudioPara4.csv" }, + { 00555, AID_ROOT, AID_ROOT, 0, "system/etc/ppp/*" }, + { 00555, AID_ROOT, AID_ROOT, 0, "system/etc/rc.*" }, + { 00644, AID_SYSTEM, AID_SYSTEM, 0, "data/app/*" }, + { 00644, AID_MEDIA_RW, AID_MEDIA_RW, 0, "data/media/*" }, + { 00644, AID_SYSTEM, AID_SYSTEM, 0, "data/app-private/*" }, + { 00644, AID_APP, AID_APP, 0, "data/data/*" }, + { 00755, AID_ROOT, AID_ROOT, 0, "system/bin/ping" }, + + /* the following file is INTENTIONALLY set-gid and not set-uid. + * Do not change. */ + { 02750, AID_ROOT, AID_INET, 0, "system/bin/netcfg" }, + + /* the following five files are INTENTIONALLY set-uid, but they + * are NOT included on user builds. */ + { 06755, AID_ROOT, AID_ROOT, 0, "system/xbin/su" }, + { 06755, AID_ROOT, AID_ROOT, 0, "system/xbin/librank" }, + { 06755, AID_ROOT, AID_ROOT, 0, "system/xbin/procrank" }, + { 06755, AID_ROOT, AID_ROOT, 0, "system/xbin/procmem" }, + { 06755, AID_ROOT, AID_ROOT, 0, "system/xbin/tcpdump" }, + { 04770, AID_ROOT, AID_RADIO, 0, "system/bin/pppd-ril" }, + + /* the following file has enhanced capabilities and IS included in user builds. */ + { 00750, AID_ROOT, AID_SHELL, (1 << CAP_SETUID) | (1 << CAP_SETGID), "system/bin/run-as" }, + + { 00755, AID_ROOT, AID_SHELL, 0, "system/bin/*" }, + { 00755, AID_ROOT, AID_ROOT, 0, "system/lib/valgrind/*" }, + { 00755, AID_ROOT, AID_SHELL, 0, "system/xbin/*" }, + { 00755, AID_ROOT, AID_SHELL, 0, "system/vendor/bin/*" }, + { 00750, AID_ROOT, AID_SHELL, 0, "sbin/*" }, + { 00755, AID_ROOT, AID_ROOT, 0, "bin/*" }, + { 00750, AID_ROOT, AID_SHELL, 0, "init*" }, + { 00750, AID_ROOT, AID_SHELL, 0, "charger*" }, + { 00750, AID_ROOT, AID_SHELL, 0, "sbin/fs_mgr" }, + { 00640, AID_ROOT, AID_SHELL, 0, "fstab.*" }, + { 00644, AID_ROOT, AID_ROOT, 0, 0 }, +}; + +static inline void fs_config(const char *path, int dir, + unsigned *uid, unsigned *gid, unsigned *mode, uint64_t *capabilities) +{ + const struct fs_path_config *pc; + int plen; + + if (path[0] == '/') { + path++; + } + + pc = dir ? android_dirs : android_files; + plen = strlen(path); + for(; pc->prefix; pc++){ + int len = strlen(pc->prefix); + if (dir) { + if(plen < len) continue; + if(!strncmp(pc->prefix, path, len)) break; + continue; + } + /* If name ends in * then allow partial matches. */ + if (pc->prefix[len -1] == '*') { + if(!strncmp(pc->prefix, path, len - 1)) break; + } else if (plen == len){ + if(!strncmp(pc->prefix, path, len)) break; + } + } + *uid = pc->uid; + *gid = pc->gid; + *mode = (*mode & (~07777)) | pc->mode; + *capabilities = pc->capabilities; + +#if 0 + fprintf(stderr,"< '%s' '%s' %d %d %o >\n", + path, pc->prefix ? pc->prefix : "", *uid, *gid, *mode); +#endif +} +#endif +#endif diff -Nru android-tools-4.2.2+git20130218/core/libsparse/output_file.c android-tools-4.2.2+git20130529/core/libsparse/output_file.c --- android-tools-4.2.2+git20130218/core/libsparse/output_file.c 2013-02-18 14:49:03.000000000 +0000 +++ android-tools-4.2.2+git20130529/core/libsparse/output_file.c 2013-05-29 20:16:54.000000000 +0000 @@ -675,6 +675,9 @@ } else { out = output_file_new_normal(); } + if (!out) { + return NULL; + } out->ops->open(out, fd); diff -Nru android-tools-4.2.2+git20130218/core/mkbootimg/mkbootimg.c android-tools-4.2.2+git20130529/core/mkbootimg/mkbootimg.c --- android-tools-4.2.2+git20130218/core/mkbootimg/mkbootimg.c 2013-02-18 14:49:03.000000000 +0000 +++ android-tools-4.2.2+git20130529/core/mkbootimg/mkbootimg.c 2013-05-29 20:16:54.000000000 +0000 @@ -72,7 +72,7 @@ -static unsigned char padding[4096] = { 0, }; +static unsigned char padding[16384] = { 0, }; int write_padding(int fd, unsigned pagesize, unsigned itemsize) { @@ -152,7 +152,8 @@ board = val; } else if(!strcmp(arg,"--pagesize")) { pagesize = strtoul(val, 0, 10); - if ((pagesize != 2048) && (pagesize != 4096)) { + if ((pagesize != 2048) && (pagesize != 4096) + && (pagesize != 8192) && (pagesize != 16384)) { fprintf(stderr,"error: unsupported page size %d\n", pagesize); return -1; } diff -Nru android-tools-4.2.2+git20130218/debian/adb-completion android-tools-4.2.2+git20130529/debian/adb-completion --- android-tools-4.2.2+git20130218/debian/adb-completion 2014-03-14 04:06:05.000000000 +0000 +++ android-tools-4.2.2+git20130529/debian/adb-completion 1970-01-01 00:00:00.000000000 +0000 @@ -1,33 +0,0 @@ -_adb() -{ - local cur prev opts - COMPREPLY=() - cur="${COMP_WORDS[COMP_CWORD]}" - prev="${COMP_WORDS[COMP_CWORD-1]}" - opts="shell push pull reboot reboot-bootloader forward logcat devices kill-server root remount" - - case "$prev" in - shell | pull | reboot-bootloader | logcat | devices | kill-server | root | remount) - COMPREPLY=() - return 0 - ;; - reboot) - COMPREPLY=( $(compgen -W "bootloader recovery" -- $cur) ) - return 0 - ;; - push) - COMPREPLY=( $(compgen -o default -o plusdirs -f -- $cur) ) - return 0 - ;; - *) - local prev2="${COMP_WORDS[COMP_CWORD-2]}" - if [ "$prev2" == "push" ] || [ "$prev2" == "reboot" ];then - return 0 - fi - ;; - esac - - COMPREPLY=( $(compgen -W "$opts" -- $cur) ) - return 0 -} -complete -F _adb adb diff -Nru android-tools-4.2.2+git20130218/debian/android-tools-adb.bash-completion android-tools-4.2.2+git20130529/debian/android-tools-adb.bash-completion --- android-tools-4.2.2+git20130218/debian/android-tools-adb.bash-completion 2014-03-14 04:06:05.000000000 +0000 +++ android-tools-4.2.2+git20130529/debian/android-tools-adb.bash-completion 2014-11-24 20:27:47.000000000 +0000 @@ -1 +1 @@ -debian/adb-completion adb +debian/bash_completion.d/adb adb diff -Nru android-tools-4.2.2+git20130218/debian/android-tools-adbd.install android-tools-4.2.2+git20130529/debian/android-tools-adbd.install --- android-tools-4.2.2+git20130218/debian/android-tools-adbd.install 2014-03-14 04:05:30.000000000 +0000 +++ android-tools-4.2.2+git20130529/debian/android-tools-adbd.install 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -core/adbd/adbd usr/bin/ diff -Nru android-tools-4.2.2+git20130218/debian/android-tools-adbd.upstart android-tools-4.2.2+git20130529/debian/android-tools-adbd.upstart --- android-tools-4.2.2+git20130218/debian/android-tools-adbd.upstart 2014-03-31 17:56:50.000000000 +0000 +++ android-tools-4.2.2+git20130529/debian/android-tools-adbd.upstart 1970-01-01 00:00:00.000000000 +0000 @@ -1,28 +0,0 @@ -# adbd - run adb debugging shell -# -# This task enables the adb shell - -description "adbd" - -start on android-container persist.sys.usb.config=*adb -stop on runlevel [06] - -respawn - -pre-start script - if [ -d /sys/class/android_usb ] - then - - if [ -d /sys/class/android_usb/android0/f_ffs ] - then - # some devices use the functionfs (i.e. manta) - # we need to mount it to keep adb working - mkdir -p /dev/usb-ffs/adb - mount -t functionfs adb /dev/usb-ffs/adb - fi - else - grep -q qemu /proc/cmdline || { stop; exit 0; } - fi -end script - -exec su - -c adbd diff -Nru android-tools-4.2.2+git20130218/debian/android-tools-adb.install android-tools-4.2.2+git20130529/debian/android-tools-adb.install --- android-tools-4.2.2+git20130218/debian/android-tools-adb.install 2014-03-14 04:05:30.000000000 +0000 +++ android-tools-4.2.2+git20130529/debian/android-tools-adb.install 2014-11-24 20:27:47.000000000 +0000 @@ -1 +1 @@ -core/adb/adb usr/bin/ +builddir/adb/adb usr/bin/ diff -Nru android-tools-4.2.2+git20130218/debian/android-tools-adb.postinst android-tools-4.2.2+git20130529/debian/android-tools-adb.postinst --- android-tools-4.2.2+git20130218/debian/android-tools-adb.postinst 2014-03-14 04:05:30.000000000 +0000 +++ android-tools-4.2.2+git20130529/debian/android-tools-adb.postinst 2014-11-24 20:27:47.000000000 +0000 @@ -1,16 +1,42 @@ #!/bin/sh +# postinst script for android-tools-adb +# +# see: dh_installdeb(1) set -e -# Old udev rules were marking all /dev entries as "uaccess" meaning -# that the current active user could write to any entry. -# A reboot is required to make sure all the permissions are set to -# a sane value again. -if dpkg --compare-versions "$2" lt 4.2.2+git20130218-3ubuntu15 && \ - [ -x /usr/share/update-notifier/notify-reboot-required ] -then - /usr/share/update-notifier/notify-reboot-required || : -fi +# summary of how this script can be called: +# * `configure' +# * `abort-upgrade' +# * `abort-remove' `in-favour' +# +# * `abort-remove' +# * `abort-deconfigure' `in-favour' +# `removing' +# +# for details, see http://www.debian.org/doc/debian-policy/ or +# the debian-policy package + + +case "$1" in + configure) + # create adb group if not already present + if ! getent group adb > /dev/null; then + addgroup --quiet --system adb + fi + ;; + + abort-upgrade|abort-remove|abort-deconfigure) + ;; + + *) + echo "postinst called with unknown argument \`$1'" >&2 + exit 1 + ;; +esac + +# dh_installdeb will replace this with shell code automatically +# generated by other debhelper scripts. #DEBHELPER# diff -Nru android-tools-4.2.2+git20130218/debian/android-tools-adb.udev android-tools-4.2.2+git20130529/debian/android-tools-adb.udev --- android-tools-4.2.2+git20130218/debian/android-tools-adb.udev 2014-03-14 04:05:30.000000000 +0000 +++ android-tools-4.2.2+git20130529/debian/android-tools-adb.udev 2014-11-24 20:27:47.000000000 +0000 @@ -1,49 +1,416 @@ -# Udev rules for letting the console user access adb. -# Vendor ids -# Important product ids -# d001 adb recovery -# d002 adb system - -# Applies to 18d1 -# 2d00 accessory -# 2d01 accessory,adb -# 2d02 audio_source (part of libgphoto2-2) -# 2d03 audio_source,adb -# 2d04 accessory,audio_source -# 2d05 accessory,audio_source,adb -# 4ee1 mtp (part of libmtp-common) -# 4ee2 mtp,adb (part of libmtp-common) -# 4ee3 rndis -# 4ee4 adb,rdnis -# 4ee5 ptp -# 4ee6 ptp,adb -# 4e41 mtp -# 4e42 mtp,adb -# 4e43 ptp -# 4e44 ptp,adb -# 4e23 rndis -# 4e24 rndis,adb - -ACTION=="add|change", SUBSYSTEM=="usb", \ - ATTRS{idVendor}=="18d1", \ - ATTRS{idProduct}=="2d01|2d03|2d05|4ee2|4ee4|4ee6|4e42|4e44|4e24|d001|d002", \ - TAG+="uaccess" - -# Applies to 04e8 -# 685b mass_storage -# 685e mass_storage,adb -# 685c mtp (libgphoto2-2 libmtp-common) -# 6860 mtp,adb (part of libgphoto2-2 libmtp-common) -# 6862 rndis,dm -# 6863 rndis -# 6864 rndis,adb & rndis,acm,dm -# 6865 ptp -# 6866 ptp,adb -# 6864 rndis,dm -# 6865 ptp -# 6866 ptp,adb - -ACTION=="add|change", SUBSYSTEM=="usb", \ - ATTRS{idVendor}=="04e8", \ - ATTRS{idProduct}=="685e|6860|6864|6866|6866", \ - TAG+="uaccess" +# Skip this section below if this device is not connected by USB +SUBSYSTEM!="usb", GOTO="android_usb_rules_end" + +LABEL="android_usb_rules_begin" +# Devices listed here in android_usb_rules_{begin...end} are connected by USB +# Acer +ATTR{idVendor}!="0502", GOTO="not_Acer" +ENV{adb_user}="yes" +# Iconia Tab A1-830 +ATTR{idProduct}=="3604", SYMLINK+="android_adb", SYMLINK+="android_fastboot" +# Iconia Tab A500 +ATTR{idProduct}=="3325", SYMLINK+="android_adb", SYMLINK+="android_fastboot" +# Liquid +ATTR{idProduct}=="3202" +ATTR{idProduct}=="3203", SYMLINK+="android_adb" +GOTO="android_usb_rule_match" +LABEL="not_Acer" + +# ADVANCE +ATTR{idVendor}=="0a5c", ENV{adb_user}="yes" +# S5 +ATTR{idVendor}=="0a5c", ATTR{idProduct}=="e681", SYMLINK+="android_adb" + +# Archos +ATTR{idVendor}!="0e79", GOTO="not_Archos" +ENV{adb_user}="yes" +# 43 +ATTR{idProduct}=="1417", SYMLINK+="android_adb", SYMLINK+="android_fastboot" +# 101 +ATTR{idProduct}=="1411", SYMLINK+="android_adb", SYMLINK+="android_fastboot" +# 101 xs +ATTR{idProduct}=="1549", SYMLINK+="android_adb", SYMLINK+="android_fastboot" +GOTO="android_usb_rule_match" +LABEL="not_Archos" + +# Asus +ATTR{idVendor}=="0b05", ENV{adb_user}="yes" +# Zenphone 5 +ATTR{idProduct}=="4daf", SYMLINK+="android_adb", SYMLINK+="android_fastboot" + +# Azpen Onda +ATTR{idVendor}=="1f3a", ENV{adb_user}="yes" + +# Dell +ATTR{idVendor}=="413c", ENV{adb_user}="yes" + +# Foxconn +ATTR{idVendor}=="0489", ENV{adb_user}="yes" +# Commtiva Z71, Geeksphone One +ATTR{idVendor}=="0489", ATTR{idProduct}=="c001", SYMLINK+="android_adb" + +# Fujitsu/Fujitsu Toshiba +ATTR{idVendor}=="04c5", ENV{adb_user}="yes" + +# Fuzhou Rockchip Electronics +ATTR{idVendor}=="2207", ENV{adb_user}="yes" +# Mediacom Smartpad 715i +ATTR{idVendor}=="2207", ATTR{idProduct}=="0000", SYMLINK+="android_adb" +# Ubislate 7Ci +ATTR{idVendor}=="2207", ATTR{idProduct}=="0010", SYMLINK+="android_adb" + +# Garmin-Asus +ATTR{idVendor}=="091e", ENV{adb_user}="yes" + +# Google +ATTR{idVendor}!="18d1", GOTO="not_Google" +ENV{adb_user}="yes" +# Nexus 4, Nexus 7 2013 +ATTR{idProduct}=="4ee2", SYMLINK+="android_adb" +ATTR{idProduct}=="4ee0", SYMLINK+="android_fastboot" +# Nexus 7 +ATTR{idProduct}=="4e42", SYMLINK+="android_adb" +ATTR{idProduct}=="4e40", SYMLINK+="android_fastboot" +# Nexus 5, Nexus 10 +ATTR{idProduct}=="4ee1", SYMLINK+="android_adb", SYMLINK+="android_fastboot" +# Nexus S +ATTR{idProduct}=="4e21" +ATTR{idProduct}=="4e22", SYMLINK+="android_adb" +ATTR{idProduct}=="4e20", SYMLINK+="android_fastboot" +# Galaxy Nexus +ATTR{idProduct}=="4e30", SYMLINK+="android_adb", SYMLINK+="android_fastboot" +# Nexus One +ATTR{idProduct}=="4e11" +ATTR{idProduct}=="4e12", SYMLINK+="android_adb" +ATTR{idProduct}=="0fff", SYMLINK+="android_fastboot" +# Generic and unspecified debug interface +ATTR{idProduct}=="d00d", SYMLINK+="android_fastboot" +# Include: Samsung Galaxy Nexus (GSM) +ATTR{idProduct}=="4e30", SYMLINK+="android_fastboot" +# Recovery adb entry for Nexus Family +ATTR{idProduct}=="d001", SYMLINK+="android_adb" +GOTO="android_usb_rule_match" +LABEL="not_Google" + +# Haier +ATTR{idVendor}=="201e", ENV{adb_user}="yes" + +# Hisense +ATTR{idVendor}=="109b", ENV{adb_user}="yes" + +# HTC +ATTR{idVendor}!="0bb4", GOTO="not_HTC" +ENV{adb_user}="yes" +# ChaCha +ATTR{idProduct}=="0cb2", SYMLINK+="android_adb", SYMLINK+="android_fastboot" +# Desire (Bravo) +ATTR{idProduct}=="0ff9" +ATTR{idProduct}=="0c87", SYMLINK+="android_adb" +ATTR{idProduct}=="0fff", SYMLINK+="android_fastboot" +# Desire HD +ATTR{idProduct}=="0ca2", SYMLINK+="android_adb" +ATTR{idProduct}=="0fff", SYMLINK+="android_fastboot" +# Desire S (Saga) +ATTR{idProduct}=="0cab", SYMLINK+="android_adb" +# Desire Z +ATTR{idProduct}=="0c91", SYMLINK+="android_adb", SYMLINK+="android_fastboot" +# Evo Shift +ATTR{idProduct}=="0ff9" +ATTR{idProduct}=="0ca5", SYMLINK+="android_adb" +ATTR{idProduct}=="0fff", SYMLINK+="android_fastboot" +# G1 +ATTR{idProduct}=="0c01", SYMLINK+="android_adb", SYMLINK+="android_fastboot" +# HD2 +ATTR{idProduct}=="0c02", SYMLINK+="android_adb", SYMLINK+="android_fastboot" +# Hero H2000 +ATTR{idProduct}=="0001", SYMLINK+="android_adb", SYMLINK+="android_fastboot" +# Hero (GSM), Desire +ATTR{idProduct}=="0ff9" +ATTR{idProduct}=="0c99", SYMLINK+="android_adb" +ATTR{idProduct}=="0fff", SYMLINK+="android_fastboot" +# Hero (CDMA) +ATTR{idProduct}=="0ff9" +ATTR{idProduct}=="0c9a", SYMLINK+="android_adb" +ATTR{idProduct}=="0fff", SYMLINK+="android_fastboot" +# Incredible +ATTR{idProduct}=="0ff9" +ATTR{idProduct}=="0c9e", SYMLINK+="android_adb" +ATTR{idProduct}=="0fff", SYMLINK+="android_fastboot" +# Incredible rev 0002 +ATTR{idProduct}=="0ff9" +ATTR{idProduct}=="0c8d", SYMLINK+="android_adb" +ATTR{idProduct}=="0fff", SYMLINK+="android_fastboot" +# MyTouch 4G +ATTR{idProduct}=="0ff9" +ATTR{idProduct}=="0c96", SYMLINK+="android_adb" +ATTR{idProduct}=="0fff", SYMLINK+="android_fastboot" +# One (m7) +ATTR{idProduct}=="0c93" +ATTR{idProduct}=="0f87", SYMLINK+="android_adb" +ATTR{idProduct}=="0ff0", SYMLINK+="android_fastboot" +# Slide +ATTR{idProduct}=="0ff9" +ATTR{idProduct}=="0e03", SYMLINK+="android_adb" +ATTR{idProduct}=="0fff", SYMLINK+="android_fastboot" +# Tatoo, Dream, ADP1, G1, Magic +ATTR{idProduct}=="0c01" +ATTR{idProduct}=="0c02", SYMLINK+="android_adb", SYMLINK+="android_fastboot" +# Vision +ATTR{idProduct}=="0ff9" +ATTR{idProduct}=="0c91", SYMLINK+="android_adb" +ATTR{idProduct}=="0fff", SYMLINK+="android_fastboot" +# Wildfire +ATTR{idProduct}=="0c8b", SYMLINK+="android_adb", SYMLINK+="android_fastboot" +# Wildfire S +ATTR{idProduct}=="0c86", SYMLINK+="android_adb", SYMLINK+="android_fastboot" +# Zopo ZP900, Fairphone +ATTR{idProduct}=="0c03", SYMLINK+="android_adb", SYMLINK+="android_fastboot" +# Zopo C2 +ATTR{idProduct}=="2008", SYMLINK+="libmtp-%k", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1" +GOTO="android_usb_rule_match" +LABEL="not_HTC" + +# Huawei +ATTR{idVendor}=="12d1", ENV{adb_user}="yes" +ATTR{idVendor}=="12d1", ATTR{idProduct}=="1038", SYMLINK+="android_adb" +ATTR{idVendor}=="12d1", ATTR{idProduct}=="1038", SYMLINK+="android_fastboot" +# U8850 Vision +ATTR{idVendor}=="12d1", ATTR{idProduct}=="1021", SYMLINK+="android_adb" +ATTR{idVendor}=="12d1", ATTR{idProduct}=="1021", SYMLINK+="android_fastboot" + +# Intel +ATTR{idVendor}=="8087", ENV{adb_user}="yes" +# Geeksphone Revolution +ATTR{idVendor}=="8087", ATTR{idProduct}=="0a16", SYMLINK+="android_adb" + +# K-Touch +ATTR{idVendor}=="24e3", ENV{adb_user}="yes" + +# KT Tech +ATTR{idVendor}=="2116", ENV{adb_user}="yes" + +# Kyocera +ATTR{idVendor}=="0482", ENV{adb_user}="yes" + +# Lab126 +ATTR{idVendor}=="1949", ENV{adb_user}="yes" +# Amazon Kindle Fire +ATTR{idVendor}=="1949", ATTR{idProduct}=="0006", SYMLINK+="android_adb" +ATTR{idVendor}=="1949", ATTR{idProduct}=="0006", SYMLINK+="android_fastboot" + +# Lenovo +ATTR{idVendor}=="17ef", ENV{adb_user}="yes" + +# LG +ATTR{idVendor}!="1004", GOTO="not_LG" +ENV{adb_user}="yes" +# Ally, Vortex, P500 +ATTR{idProduct}=="618f" +ATTR{idProduct}=="618e", SYMLINK+="android_adb" +# G2 D803 +ATTR{idProduct}=="631f", SYMLINK+="android_adb" +# Optimus LTE +ATTR{idProduct}=="6315", SYMLINK+="android_adb" +ATTR{idProduct}=="61f9", SYMLINK+="libmtp-%k", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1" +# Optimus One +ATTR{idProduct}=="61c5", SYMLINK+="android_adb" +# Swift GT540 +ATTR{idProduct}=="61b4", SYMLINK+="android_adb" +# P500 CM10 +ATTR{idProduct}=="61a6", SYMLINK+="android_adb" +# 4X HD P880 +ATTR{idProduct}=="61f9", SYMLINK+="android_adb" +GOTO="android_usb_rule_match" +LABEL="not_LG" + +# Motorola +ATTR{idVendor}!="22b8", GOTO="not_Motorola" +ENV{adb_user}="yes" +# CLIQ XT/Quench +ATTR{idProduct}=="2d66" +# Defy/MB525 +ATTR{idProduct}=="428c" +# Droid +ATTR{idProduct}=="41db" +# Xoom ID 1 +ATTR{idProduct}=="70a8", SYMLINK+="android_adb", SYMLINK+="android_fastboot" +# Xoom ID 2 +ATTR{idProduct}=="70a9", SYMLINK+="android_adb", SYMLINK+="android_fastboot" +# Razr XT912 +ATTR{idProduct}=="4362", SYMLINK+="android_adb", SYMLINK+="android_fastboot" +# Moto G +ATTR{idProduct}=="2e76", SYMLINK+="android_adb", SYMLINK+="android_fastboot" +# Moto G (Dual SIM) +ATTR{idProduct}=="2e80", SYMLINK+="android_adb", SYMLINK+="android_fastboot" +# Moto G (Global GSM) +ATTR{idProduct}=="2e82", SYMLINK+="android_adb", SYMLINK+="android_fastboot" +GOTO="android_usb_rule_match" +LABEL="not_Motorola" + +# MTK +ATTR{idVendor}=="0e8d", ENV{adb_user}="yes" + +# NEC +ATTR{idVendor}=="0409", ENV{adb_user}="yes" + +# Nook +ATTR{idVendor}=="2080", ENV{adb_user}="yes" + +# Nvidia +ATTR{idVendor}=="0955", ENV{adb_user}="yes" + +# Oppo +ATTR{idVendor}=="22d9", ENV{adb_user}="yes" +# Find 5 +ATTR{idVendor}=="22d9", ATTR{idProduct}=="2767", SYMLINK+="android_adb" +ATTR{idVendor}=="22d9", ATTR{idProduct}=="2764", SYMLINK+="libmtp-%k", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1" + +# OTGV +ATTR{idVendor}=="2257", ENV{adb_user}="yes" + +# Pantech +ATTR{idVendor}=="10a9", ENV{adb_user}="yes" + +# Pegatron +ATTR{idVendor}=="1d4d", ENV{adb_user}="yes" + +# Philips +ATTR{idVendor}=="0471", ENV{adb_user}="yes" + +# PMC-Sierra +ATTR{idVendor}=="04da", ENV{adb_user}="yes" + +# Qualcomm +ATTR{idVendor}=="05c6", ENV{adb_user}="yes" +# Geeksphone Zero +ATTR{idVendor}=="05c6", ATTR{idProduct}=="9025", SYMLINK+="android_adb" +# OnePlus One +ATTR{idVendor}=="05c6", ATTR{idProduct}=="6769", SYMLINK+="android_adb" + +# SK Telesys +ATTR{idVendor}=="1f53", ENV{adb_user}="yes" + +# Samsung +ATTR{idVendor}!="04e8", GOTO="not_Samsung" +ENV{adb_user}="yes" +# Galaxy i5700 +ATTR{idProduct}=="681c", SYMLINK+="android_adb", SYMLINK+="android_fastboot" +# Galaxy i5800 +ATTR{idProduct}=="681c", SYMLINK+="android_adb" +ATTR{idProduct}=="6601", SYMLINK+="android_fastboot" +ATTR{idProduct}=="68a9", SYMLINK+="libmtp-%k", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1" +# Galaxy i7500 +ATTR{idProduct}=="6640", SYMLINK+="android_adb", SYMLINK+="android_fastboot" +# Galaxy i9000 S, i9300 S3 +ATTR{idProduct}=="6601", SYMLINK+="android_adb" +ATTR{idProduct}=="685d", MODE="0660" +ATTR{idProduct}=="68c3", MODE="0660" +# Galaxy Ace (S5830) "Cooper" +ATTR{idProduct}=="689e", SYMLINK+="android_adb", SYMLINK+="android_fastboot" +# Galaxy Tab +ATTR{idProduct}=="6877", SYMLINK+="android_adb", SYMLINK+="android_fastboot" +# Galaxy Nexus (GSM) +ATTR{idProduct}=="685c" +ATTR{idProduct}=="6860", SYMLINK+="android_adb" +# Galaxy Tab 10.1, i9100 S2, i9300 S3, N5100 Note (8.0) +ATTR{idProduct}=="6860" +ATTR{idProduct}=="685e", SYMLINK+="android_adb", SYMLINK+="android_fastboot" +ATTR{idProduct}=="6860", SYMLINK+="libmtp-%k", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1" +# Galaxy i9300 S3 +ATTR{idProduct}=="6866", SYMLINK+="libmtp-%k", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1" +# Galaxy S4 GT-I9500 +ATTR{idProduct}=="685d", SYMLINK+="android_adb" +# False positive printer +ATTR{idProduct}=="3252", OPTIONS=="ignore_device" +GOTO="android_usb_rule_match" +LABEL="not_Samsung" + +# Sharp +ATTR{idVendor}=="04dd", ENV{adb_user}="yes" + +# Sony +ATTR{idVendor}=="054c", ENV{adb_user}="yes" + +# Sony Ericsson +ATTR{idVendor}!="0fce", GOTO="not_Sony_Ericsson" +ENV{adb_user}="yes" +# Xperia X10 mini +ATTR{idProduct}=="3137" +ATTR{idProduct}=="2137", SYMLINK+="android_adb" +# Xperia X10 mini pro +ATTR{idProduct}=="3138" +ATTR{idProduct}=="2138", SYMLINK+="android_adb" +# Xperia X8 +ATTR{idProduct}=="3149" +ATTR{idProduct}=="2149", SYMLINK+="android_adb" +# Xperia X12 +ATTR{idProduct}=="e14f" +ATTR{idProduct}=="614f", SYMLINK+="android_adb" +# Xperia Arc S +ATTR{idProduct}=="414f", SYMLINK+="android_adb", SYMLINK+="android_fastboot" +# Xperia Neo V +ATTR{idProduct}=="6156", SYMLINK+="android_adb" +ATTR{idProduct}=="0dde", SYMLINK+="android_fastboot" +# Xperia S +ATTR{idProduct}=="5169", SYMLINK+="android_adb", SYMLINK+="android_fastboot" +# Xperia SP +ATTR{idProduct}=="6195", SYMLINK+="android_adb", SYMLINK+="android_fastboot" +# Xperia L +ATTR{idProduct}=="5192", SYMLINK+="android_adb", SYMLINK+="android_fastboot" +# Xperia Mini Pro +ATTR{idProduct}=="0166", SYMLINK+="android_adb", SYMLINK+="android_fastboot" +# Xperia V +ATTR{idProduct}=="0186", SYMLINK+="android_adb", SYMLINK+="android_fastboot" +# Xperia Acro S +ATTR{idProduct}=="5176", SYMLINK+="android_adb", SYMLINK+="android_fastboot" +# Xperia Z1 Compact +ATTR{idProduct}=="51a7", SYMLINK+="android_adb", SYMLINK+="android_fastboot" +GOTO="android_usb_rule_match" +LABEL="not_Sony_Ericsson" + +# Spreadtrum +ATTR{idVendor}=="1782", ENV{adb_user}="yes" + +# T & A Mobile Phones +ATTR{idVendor}=="1bbb", ENV{adb_user}="yes" +# Alcatel OT991D +ATTR{idVendor}=="1bbb", ATTR{idProduct}=="00f2", SYMLINK+="android_adb" + +# Teleepoch +ATTR{idVendor}=="2340", ENV{adb_user}="yes" + +# Texas Instruments UsbBoot +ATTR{idVendor}=="0451", ATTR{idProduct}=="d00f" +ATTR{idVendor}=="0451", ATTR{idProduct}=="d010" + +# Toshiba +ATTR{idVendor}=="0930", ENV{adb_user}="yes" + +# WEARNERS +ATTR{idVendor}=="05c6", ENV{adb_user}="yes" + +# ZTE +ATTR{idVendor}=="19d2", ENV{adb_user}="yes" +# Blade +ATTR{idVendor}=="19d2", ATTR{idProduct}=="1353" +ATTR{idVendor}=="19d2", ATTR{idProduct}=="1351", SYMLINK+="android_adb" +# Blade S (Crescent, Orange San Francisco 2) +ATTR{idVendor}=="19d2", ATTR{idProduct}=="1355" +ATTR{idVendor}=="19d2", ATTR{idProduct}=="1354", SYMLINK+="android_adb" + +# XiaoMi +ATTR{idVendor}=="2717", ENV{adb_user}="yes" +# Mi2A +ATTR{idVendor}=="2717", ATTR{idProduct}=="904e", SYMLINK+="android_adb" +ATTR{idVendor}=="2717", ATTR{idProduct}=="9039", SYMLINK+="android_adb" +# Mi3 +ATTR{idVendor}=="2717", ATTR{idProduct}=="0368", SYMLINK+="android_adb" + +# Skip other vendor tests +LABEL="android_usb_rule_match" + +# Enable device as a user device if found +ENV{adb_user}=="yes", MODE="0660", GROUP="adb", TAG+="uaccess", TAG+="udev-acl" + +# Devices listed here {begin...end} are connected by USB +LABEL="android_usb_rules_end" diff -Nru android-tools-4.2.2+git20130218/debian/android-tools-fastboot.bash-completion android-tools-4.2.2+git20130529/debian/android-tools-fastboot.bash-completion --- android-tools-4.2.2+git20130218/debian/android-tools-fastboot.bash-completion 2014-03-14 04:06:05.000000000 +0000 +++ android-tools-4.2.2+git20130529/debian/android-tools-fastboot.bash-completion 2014-11-24 20:27:47.000000000 +0000 @@ -1 +1 @@ -debian/fastboot-completion fastboot +debian/bash_completion.d/fastboot fastboot diff -Nru android-tools-4.2.2+git20130218/debian/android-tools-fastboot.install android-tools-4.2.2+git20130529/debian/android-tools-fastboot.install --- android-tools-4.2.2+git20130218/debian/android-tools-fastboot.install 2014-03-14 04:05:30.000000000 +0000 +++ android-tools-4.2.2+git20130529/debian/android-tools-fastboot.install 2014-11-24 20:27:47.000000000 +0000 @@ -1 +1 @@ -core/fastboot/fastboot usr/bin/ +builddir/fastboot/fastboot usr/bin/ diff -Nru android-tools-4.2.2+git20130218/debian/android-tools-fastboot.manpages android-tools-4.2.2+git20130529/debian/android-tools-fastboot.manpages --- android-tools-4.2.2+git20130218/debian/android-tools-fastboot.manpages 1970-01-01 00:00:00.000000000 +0000 +++ android-tools-4.2.2+git20130529/debian/android-tools-fastboot.manpages 2014-11-24 20:27:47.000000000 +0000 @@ -0,0 +1 @@ +debian/fastboot.1 diff -Nru android-tools-4.2.2+git20130218/debian/android-tools-fastboot.udev android-tools-4.2.2+git20130529/debian/android-tools-fastboot.udev --- android-tools-4.2.2+git20130218/debian/android-tools-fastboot.udev 2014-03-14 04:05:30.000000000 +0000 +++ android-tools-4.2.2+git20130529/debian/android-tools-fastboot.udev 2014-11-24 20:27:47.000000000 +0000 @@ -1,8 +1,416 @@ -# Udev rules for letting the console user access fastboot -# 4e40 grouper -# 4ee0 mako/manta -# 4e30 maguro/toro - -ACTION=="add|change", SUBSYSTEM=="usb", \ - ATTRS{idVendor}=="18d1", ATTRS{idProduct}=="4e30|4e40|4ee0", \ - TAG+="uaccess" +# Skip this section below if this device is not connected by USB +SUBSYSTEM!="usb", GOTO="android_usb_rules_end" + +LABEL="android_usb_rules_begin" +# Devices listed here in android_usb_rules_{begin...end} are connected by USB +# Acer +ATTR{idVendor}!="0502", GOTO="not_Acer" +ENV{adb_user}="yes" +# Iconia Tab A1-830 +ATTR{idProduct}=="3604", SYMLINK+="android_adb", SYMLINK+="android_fastboot" +# Iconia Tab A500 +ATTR{idProduct}=="3325", SYMLINK+="android_adb", SYMLINK+="android_fastboot" +# Liquid +ATTR{idProduct}=="3202" +ATTR{idProduct}=="3203", SYMLINK+="android_adb" +GOTO="android_usb_rule_match" +LABEL="not_Acer" + +# ADVANCE +ATTR{idVendor}=="0a5c", ENV{adb_user}="yes" +# S5 +ATTR{idVendor}=="0a5c", ATTR{idProduct}=="e681", SYMLINK+="android_adb" + +# Archos +ATTR{idVendor}!="0e79", GOTO="not_Archos" +ENV{adb_user}="yes" +# 43 +ATTR{idProduct}=="1417", SYMLINK+="android_adb", SYMLINK+="android_fastboot" +# 101 +ATTR{idProduct}=="1411", SYMLINK+="android_adb", SYMLINK+="android_fastboot" +# 101 xs +ATTR{idProduct}=="1549", SYMLINK+="android_adb", SYMLINK+="android_fastboot" +GOTO="android_usb_rule_match" +LABEL="not_Archos" + +# Asus +ATTR{idVendor}=="0b05", ENV{adb_user}="yes" +# Zenphone 5 +ATTR{idProduct}=="4daf", SYMLINK+="android_adb", SYMLINK+="android_fastboot" + +# Azpen Onda +ATTR{idVendor}=="1f3a", ENV{adb_user}="yes" + +# Dell +ATTR{idVendor}=="413c", ENV{adb_user}="yes" + +# Foxconn +ATTR{idVendor}=="0489", ENV{adb_user}="yes" +# Commtiva Z71, Geeksphone One +ATTR{idVendor}=="0489", ATTR{idProduct}=="c001", SYMLINK+="android_adb" + +# Fujitsu/Fujitsu Toshiba +ATTR{idVendor}=="04c5", ENV{adb_user}="yes" + +# Fuzhou Rockchip Electronics +ATTR{idVendor}=="2207", ENV{adb_user}="yes" +# Mediacom Smartpad 715i +ATTR{idVendor}=="2207", ATTR{idProduct}=="0000", SYMLINK+="android_adb" +# Ubislate 7Ci +ATTR{idVendor}=="2207", ATTR{idProduct}=="0010", SYMLINK+="android_adb" + +# Garmin-Asus +ATTR{idVendor}=="091e", ENV{adb_user}="yes" + +# Google +ATTR{idVendor}!="18d1", GOTO="not_Google" +ENV{adb_user}="yes" +# Nexus 4, Nexus 7 2013 +ATTR{idProduct}=="4ee2", SYMLINK+="android_adb" +ATTR{idProduct}=="4ee0", SYMLINK+="android_fastboot" +# Nexus 7 +ATTR{idProduct}=="4e42", SYMLINK+="android_adb" +ATTR{idProduct}=="4e40", SYMLINK+="android_fastboot" +# Nexus 5, Nexus 10 +ATTR{idProduct}=="4ee1", SYMLINK+="android_adb", SYMLINK+="android_fastboot" +# Nexus S +ATTR{idProduct}=="4e21" +ATTR{idProduct}=="4e22", SYMLINK+="android_adb" +ATTR{idProduct}=="4e20", SYMLINK+="android_fastboot" +# Galaxy Nexus +ATTR{idProduct}=="4e30", SYMLINK+="android_adb", SYMLINK+="android_fastboot" +# Nexus One +ATTR{idProduct}=="4e11" +ATTR{idProduct}=="4e12", SYMLINK+="android_adb" +ATTR{idProduct}=="0fff", SYMLINK+="android_fastboot" +# Generic and unspecified debug interface +ATTR{idProduct}=="d00d", SYMLINK+="android_fastboot" +# Include: Samsung Galaxy Nexus (GSM) +ATTR{idProduct}=="4e30", SYMLINK+="android_fastboot" +# Recovery adb entry for Nexus Family +ATTR{idProduct}=="d001", SYMLINK+="android_adb" +GOTO="android_usb_rule_match" +LABEL="not_Google" + +# Haier +ATTR{idVendor}=="201e", ENV{adb_user}="yes" + +# Hisense +ATTR{idVendor}=="109b", ENV{adb_user}="yes" + +# HTC +ATTR{idVendor}!="0bb4", GOTO="not_HTC" +ENV{adb_user}="yes" +# ChaCha +ATTR{idProduct}=="0cb2", SYMLINK+="android_adb", SYMLINK+="android_fastboot" +# Desire (Bravo) +ATTR{idProduct}=="0ff9" +ATTR{idProduct}=="0c87", SYMLINK+="android_adb" +ATTR{idProduct}=="0fff", SYMLINK+="android_fastboot" +# Desire HD +ATTR{idProduct}=="0ca2", SYMLINK+="android_adb" +ATTR{idProduct}=="0fff", SYMLINK+="android_fastboot" +# Desire S (Saga) +ATTR{idProduct}=="0cab", SYMLINK+="android_adb" +# Desire Z +ATTR{idProduct}=="0c91", SYMLINK+="android_adb", SYMLINK+="android_fastboot" +# Evo Shift +ATTR{idProduct}=="0ff9" +ATTR{idProduct}=="0ca5", SYMLINK+="android_adb" +ATTR{idProduct}=="0fff", SYMLINK+="android_fastboot" +# G1 +ATTR{idProduct}=="0c01", SYMLINK+="android_adb", SYMLINK+="android_fastboot" +# HD2 +ATTR{idProduct}=="0c02", SYMLINK+="android_adb", SYMLINK+="android_fastboot" +# Hero H2000 +ATTR{idProduct}=="0001", SYMLINK+="android_adb", SYMLINK+="android_fastboot" +# Hero (GSM), Desire +ATTR{idProduct}=="0ff9" +ATTR{idProduct}=="0c99", SYMLINK+="android_adb" +ATTR{idProduct}=="0fff", SYMLINK+="android_fastboot" +# Hero (CDMA) +ATTR{idProduct}=="0ff9" +ATTR{idProduct}=="0c9a", SYMLINK+="android_adb" +ATTR{idProduct}=="0fff", SYMLINK+="android_fastboot" +# Incredible +ATTR{idProduct}=="0ff9" +ATTR{idProduct}=="0c9e", SYMLINK+="android_adb" +ATTR{idProduct}=="0fff", SYMLINK+="android_fastboot" +# Incredible rev 0002 +ATTR{idProduct}=="0ff9" +ATTR{idProduct}=="0c8d", SYMLINK+="android_adb" +ATTR{idProduct}=="0fff", SYMLINK+="android_fastboot" +# MyTouch 4G +ATTR{idProduct}=="0ff9" +ATTR{idProduct}=="0c96", SYMLINK+="android_adb" +ATTR{idProduct}=="0fff", SYMLINK+="android_fastboot" +# One (m7) +ATTR{idProduct}=="0c93" +ATTR{idProduct}=="0f87", SYMLINK+="android_adb" +ATTR{idProduct}=="0ff0", SYMLINK+="android_fastboot" +# Slide +ATTR{idProduct}=="0ff9" +ATTR{idProduct}=="0e03", SYMLINK+="android_adb" +ATTR{idProduct}=="0fff", SYMLINK+="android_fastboot" +# Tatoo, Dream, ADP1, G1, Magic +ATTR{idProduct}=="0c01" +ATTR{idProduct}=="0c02", SYMLINK+="android_adb", SYMLINK+="android_fastboot" +# Vision +ATTR{idProduct}=="0ff9" +ATTR{idProduct}=="0c91", SYMLINK+="android_adb" +ATTR{idProduct}=="0fff", SYMLINK+="android_fastboot" +# Wildfire +ATTR{idProduct}=="0c8b", SYMLINK+="android_adb", SYMLINK+="android_fastboot" +# Wildfire S +ATTR{idProduct}=="0c86", SYMLINK+="android_adb", SYMLINK+="android_fastboot" +# Zopo ZP900, Fairphone +ATTR{idProduct}=="0c03", SYMLINK+="android_adb", SYMLINK+="android_fastboot" +# Zopo C2 +ATTR{idProduct}=="2008", SYMLINK+="libmtp-%k", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1" +GOTO="android_usb_rule_match" +LABEL="not_HTC" + +# Huawei +ATTR{idVendor}=="12d1", ENV{adb_user}="yes" +ATTR{idVendor}=="12d1", ATTR{idProduct}=="1038", SYMLINK+="android_adb" +ATTR{idVendor}=="12d1", ATTR{idProduct}=="1038", SYMLINK+="android_fastboot" +# U8850 Vision +ATTR{idVendor}=="12d1", ATTR{idProduct}=="1021", SYMLINK+="android_adb" +ATTR{idVendor}=="12d1", ATTR{idProduct}=="1021", SYMLINK+="android_fastboot" + +# Intel +ATTR{idVendor}=="8087", ENV{adb_user}="yes" +# Geeksphone Revolution +ATTR{idVendor}=="8087", ATTR{idProduct}=="0a16", SYMLINK+="android_adb" + +# K-Touch +ATTR{idVendor}=="24e3", ENV{adb_user}="yes" + +# KT Tech +ATTR{idVendor}=="2116", ENV{adb_user}="yes" + +# Kyocera +ATTR{idVendor}=="0482", ENV{adb_user}="yes" + +# Lab126 +ATTR{idVendor}=="1949", ENV{adb_user}="yes" +# Amazon Kindle Fire +ATTR{idVendor}=="1949", ATTR{idProduct}=="0006", SYMLINK+="android_adb" +ATTR{idVendor}=="1949", ATTR{idProduct}=="0006", SYMLINK+="android_fastboot" + +# Lenovo +ATTR{idVendor}=="17ef", ENV{adb_user}="yes" + +# LG +ATTR{idVendor}!="1004", GOTO="not_LG" +ENV{adb_user}="yes" +# Ally, Vortex, P500 +ATTR{idProduct}=="618f" +ATTR{idProduct}=="618e", SYMLINK+="android_adb" +# G2 D803 +ATTR{idProduct}=="631f", SYMLINK+="android_adb" +# Optimus LTE +ATTR{idProduct}=="6315", SYMLINK+="android_adb" +ATTR{idProduct}=="61f9", SYMLINK+="libmtp-%k", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1" +# Optimus One +ATTR{idProduct}=="61c5", SYMLINK+="android_adb" +# Swift GT540 +ATTR{idProduct}=="61b4", SYMLINK+="android_adb" +# P500 CM10 +ATTR{idProduct}=="61a6", SYMLINK+="android_adb" +# 4X HD P880 +ATTR{idProduct}=="61f9", SYMLINK+="android_adb" +GOTO="android_usb_rule_match" +LABEL="not_LG" + +# Motorola +ATTR{idVendor}!="22b8", GOTO="not_Motorola" +ENV{adb_user}="yes" +# CLIQ XT/Quench +ATTR{idProduct}=="2d66" +# Defy/MB525 +ATTR{idProduct}=="428c" +# Droid +ATTR{idProduct}=="41db" +# Xoom ID 1 +ATTR{idProduct}=="70a8", SYMLINK+="android_adb", SYMLINK+="android_fastboot" +# Xoom ID 2 +ATTR{idProduct}=="70a9", SYMLINK+="android_adb", SYMLINK+="android_fastboot" +# Razr XT912 +ATTR{idProduct}=="4362", SYMLINK+="android_adb", SYMLINK+="android_fastboot" +# Moto G +ATTR{idProduct}=="2e76", SYMLINK+="android_adb", SYMLINK+="android_fastboot" +# Moto G (Dual SIM) +ATTR{idProduct}=="2e80", SYMLINK+="android_adb", SYMLINK+="android_fastboot" +# Moto G (Global GSM) +ATTR{idProduct}=="2e82", SYMLINK+="android_adb", SYMLINK+="android_fastboot" +GOTO="android_usb_rule_match" +LABEL="not_Motorola" + +# MTK +ATTR{idVendor}=="0e8d", ENV{adb_user}="yes" + +# NEC +ATTR{idVendor}=="0409", ENV{adb_user}="yes" + +# Nook +ATTR{idVendor}=="2080", ENV{adb_user}="yes" + +# Nvidia +ATTR{idVendor}=="0955", ENV{adb_user}="yes" + +# Oppo +ATTR{idVendor}=="22d9", ENV{adb_user}="yes" +# Find 5 +ATTR{idVendor}=="22d9", ATTR{idProduct}=="2767", SYMLINK+="android_adb" +ATTR{idVendor}=="22d9", ATTR{idProduct}=="2764", SYMLINK+="libmtp-%k", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1" + +# OTGV +ATTR{idVendor}=="2257", ENV{adb_user}="yes" + +# Pantech +ATTR{idVendor}=="10a9", ENV{adb_user}="yes" + +# Pegatron +ATTR{idVendor}=="1d4d", ENV{adb_user}="yes" + +# Philips +ATTR{idVendor}=="0471", ENV{adb_user}="yes" + +# PMC-Sierra +ATTR{idVendor}=="04da", ENV{adb_user}="yes" + +# Qualcomm +ATTR{idVendor}=="05c6", ENV{adb_user}="yes" +# Geeksphone Zero +ATTR{idVendor}=="05c6", ATTR{idProduct}=="9025", SYMLINK+="android_adb" +# OnePlus One +ATTR{idVendor}=="05c6", ATTR{idProduct}=="6769", SYMLINK+="android_adb" + +# SK Telesys +ATTR{idVendor}=="1f53", ENV{adb_user}="yes" + +# Samsung +ATTR{idVendor}!="04e8", GOTO="not_Samsung" +ENV{adb_user}="yes" +# Galaxy i5700 +ATTR{idProduct}=="681c", SYMLINK+="android_adb", SYMLINK+="android_fastboot" +# Galaxy i5800 +ATTR{idProduct}=="681c", SYMLINK+="android_adb" +ATTR{idProduct}=="6601", SYMLINK+="android_fastboot" +ATTR{idProduct}=="68a9", SYMLINK+="libmtp-%k", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1" +# Galaxy i7500 +ATTR{idProduct}=="6640", SYMLINK+="android_adb", SYMLINK+="android_fastboot" +# Galaxy i9000 S, i9300 S3 +ATTR{idProduct}=="6601", SYMLINK+="android_adb" +ATTR{idProduct}=="685d", MODE="0660" +ATTR{idProduct}=="68c3", MODE="0660" +# Galaxy Ace (S5830) "Cooper" +ATTR{idProduct}=="689e", SYMLINK+="android_adb", SYMLINK+="android_fastboot" +# Galaxy Tab +ATTR{idProduct}=="6877", SYMLINK+="android_adb", SYMLINK+="android_fastboot" +# Galaxy Nexus (GSM) +ATTR{idProduct}=="685c" +ATTR{idProduct}=="6860", SYMLINK+="android_adb" +# Galaxy Tab 10.1, i9100 S2, i9300 S3, N5100 Note (8.0) +ATTR{idProduct}=="6860" +ATTR{idProduct}=="685e", SYMLINK+="android_adb", SYMLINK+="android_fastboot" +ATTR{idProduct}=="6860", SYMLINK+="libmtp-%k", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1" +# Galaxy i9300 S3 +ATTR{idProduct}=="6866", SYMLINK+="libmtp-%k", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1" +# Galaxy S4 GT-I9500 +ATTR{idProduct}=="685d", SYMLINK+="android_adb" +# False positive printer +ATTR{idProduct}=="3252", OPTIONS=="ignore_device" +GOTO="android_usb_rule_match" +LABEL="not_Samsung" + +# Sharp +ATTR{idVendor}=="04dd", ENV{adb_user}="yes" + +# Sony +ATTR{idVendor}=="054c", ENV{adb_user}="yes" + +# Sony Ericsson +ATTR{idVendor}!="0fce", GOTO="not_Sony_Ericsson" +ENV{adb_user}="yes" +# Xperia X10 mini +ATTR{idProduct}=="3137" +ATTR{idProduct}=="2137", SYMLINK+="android_adb" +# Xperia X10 mini pro +ATTR{idProduct}=="3138" +ATTR{idProduct}=="2138", SYMLINK+="android_adb" +# Xperia X8 +ATTR{idProduct}=="3149" +ATTR{idProduct}=="2149", SYMLINK+="android_adb" +# Xperia X12 +ATTR{idProduct}=="e14f" +ATTR{idProduct}=="614f", SYMLINK+="android_adb" +# Xperia Arc S +ATTR{idProduct}=="414f", SYMLINK+="android_adb", SYMLINK+="android_fastboot" +# Xperia Neo V +ATTR{idProduct}=="6156", SYMLINK+="android_adb" +ATTR{idProduct}=="0dde", SYMLINK+="android_fastboot" +# Xperia S +ATTR{idProduct}=="5169", SYMLINK+="android_adb", SYMLINK+="android_fastboot" +# Xperia SP +ATTR{idProduct}=="6195", SYMLINK+="android_adb", SYMLINK+="android_fastboot" +# Xperia L +ATTR{idProduct}=="5192", SYMLINK+="android_adb", SYMLINK+="android_fastboot" +# Xperia Mini Pro +ATTR{idProduct}=="0166", SYMLINK+="android_adb", SYMLINK+="android_fastboot" +# Xperia V +ATTR{idProduct}=="0186", SYMLINK+="android_adb", SYMLINK+="android_fastboot" +# Xperia Acro S +ATTR{idProduct}=="5176", SYMLINK+="android_adb", SYMLINK+="android_fastboot" +# Xperia Z1 Compact +ATTR{idProduct}=="51a7", SYMLINK+="android_adb", SYMLINK+="android_fastboot" +GOTO="android_usb_rule_match" +LABEL="not_Sony_Ericsson" + +# Spreadtrum +ATTR{idVendor}=="1782", ENV{adb_user}="yes" + +# T & A Mobile Phones +ATTR{idVendor}=="1bbb", ENV{adb_user}="yes" +# Alcatel OT991D +ATTR{idVendor}=="1bbb", ATTR{idProduct}=="00f2", SYMLINK+="android_adb" + +# Teleepoch +ATTR{idVendor}=="2340", ENV{adb_user}="yes" + +# Texas Instruments UsbBoot +ATTR{idVendor}=="0451", ATTR{idProduct}=="d00f" +ATTR{idVendor}=="0451", ATTR{idProduct}=="d010" + +# Toshiba +ATTR{idVendor}=="0930", ENV{adb_user}="yes" + +# WEARNERS +ATTR{idVendor}=="05c6", ENV{adb_user}="yes" + +# ZTE +ATTR{idVendor}=="19d2", ENV{adb_user}="yes" +# Blade +ATTR{idVendor}=="19d2", ATTR{idProduct}=="1353" +ATTR{idVendor}=="19d2", ATTR{idProduct}=="1351", SYMLINK+="android_adb" +# Blade S (Crescent, Orange San Francisco 2) +ATTR{idVendor}=="19d2", ATTR{idProduct}=="1355" +ATTR{idVendor}=="19d2", ATTR{idProduct}=="1354", SYMLINK+="android_adb" + +# XiaoMi +ATTR{idVendor}=="2717", ENV{adb_user}="yes" +# Mi2A +ATTR{idVendor}=="2717", ATTR{idProduct}=="904e", SYMLINK+="android_adb" +ATTR{idVendor}=="2717", ATTR{idProduct}=="9039", SYMLINK+="android_adb" +# Mi3 +ATTR{idVendor}=="2717", ATTR{idProduct}=="0368", SYMLINK+="android_adb" + +# Skip other vendor tests +LABEL="android_usb_rule_match" + +# Enable device as a user device if found +ENV{adb_user}=="yes", MODE="0660", GROUP="adb", TAG+="uaccess", TAG+="udev-acl" + +# Devices listed here {begin...end} are connected by USB +LABEL="android_usb_rules_end" diff -Nru android-tools-4.2.2+git20130218/debian/android-tools-fsutils.install android-tools-4.2.2+git20130529/debian/android-tools-fsutils.install --- android-tools-4.2.2+git20130218/debian/android-tools-fsutils.install 2014-03-14 04:05:30.000000000 +0000 +++ android-tools-4.2.2+git20130529/debian/android-tools-fsutils.install 2014-11-24 20:27:47.000000000 +0000 @@ -1,7 +1,7 @@ -extras/ext4_utils/ext2simg usr/bin -extras/ext4_utils/ext4fixup usr/bin -extras/ext4_utils/img2simg usr/bin -extras/ext4_utils/make_ext4fs usr/bin -extras/ext4_utils/simg2img usr/bin -extras/ext4_utils/simg2simg usr/bin +builddir/ext4_utils/ext2simg usr/bin +builddir/ext4_utils/ext4fixup usr/bin +builddir/ext4_utils/img2simg usr/bin +builddir/ext4_utils/make_ext4fs usr/bin +builddir/ext4_utils/simg2img usr/bin +builddir/ext4_utils/simg2simg usr/bin extras/ext4_utils/test_ext4fixup usr/bin diff -Nru android-tools-4.2.2+git20130218/debian/bash_completion.d/adb android-tools-4.2.2+git20130529/debian/bash_completion.d/adb --- android-tools-4.2.2+git20130218/debian/bash_completion.d/adb 1970-01-01 00:00:00.000000000 +0000 +++ android-tools-4.2.2+git20130529/debian/bash_completion.d/adb 2014-11-24 20:27:47.000000000 +0000 @@ -0,0 +1,157 @@ +## Bash completion for the Android SDK tools. +## +## Copyright (c) 2009 Matt Brubeck +## +## Permission is hereby granted, free of charge, to any person obtaining a copy +## of this software and associated documentation files (the "Software"), to deal +## in the Software without restriction, including without limitation the rights +## to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +## copies of the Software, and to permit persons to whom the Software is +## furnished to do so, subject to the following conditions: +## +## The above copyright notice and this permission notice shall be included in +## all copies or substantial portions of the Software. +## +## THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +## IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +## FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +## AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +## LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +## OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +## THE SOFTWARE. + +function _adb() +{ + local cur prev opts cmds c subcommand device_selected + COMPREPLY=() + cur="${COMP_WORDS[COMP_CWORD]}" + prev="${COMP_WORDS[COMP_CWORD-1]}" + opts="-d -e -s -p" + cmds="devices push pull sync shell emu logcat forward jdwp install \ + uninstall bugreport help version wait-for-device start-server \ + reboot reboot-bootloader sideload \ + kill-server get-state get-serialno status-window remount root ppp" + cmds_not_need_device="devices help version start-server kill-server" + subcommand="" + device_selected="" + + # Look for the subcommand. + c=1 + while [ $c -lt $COMP_CWORD ]; do + word="${COMP_WORDS[c]}" + if [ "$word" = "-d" -o "$word" = "-e" -o "$word" = "-s" ]; then + device_selected=true + opts="-p" + fi + for cmd in $cmds; do + if [ "$cmd" = "$word" ]; then + subcommand="$word" + fi + done + c=$((++c)) + done + + case "${subcommand}" in + '') + case "${prev}" in + -p) + return 0; + ;; + -s) + # Use 'adb devices' to list serial numbers. + COMPREPLY=( $(compgen -W "$(adb devices|grep 'device$'|cut -f1)" -- ${cur} ) ) + return 0 + ;; + esac + case "${cur}" in + -*) + COMPREPLY=( $(compgen -W "$opts" -- ${cur}) ) + return 0 + ;; + esac + if [ -z "$device_selected" ]; then + local num_devices=$(( $(adb devices 2>/dev/null|wc -l) - 2 )) + if [ "$num_devices" -gt "1" ]; then + # With multiple devices, you must choose a device first. + COMPREPLY=( $(compgen -W "${opts} ${cmds_not_need_device}" -- ${cur}) ) + return 0 + fi + fi + COMPREPLY=( $(compgen -W "${cmds}" -- ${cur}) ) + return 0 + ;; + install) + case "${cur}" in + -*) + COMPREPLY=( $(compgen -W "-l -r -s" -- ${cur}) ) + return 0 + ;; + esac + ;; + forward) + # Filename or installation option. + COMPREPLY=( $(compgen -W "tcp: localabstract: localreserved: localfilesystem: dev: jdwp:" -- ${cur}) ) + return 0 + ;; + uninstall) + local apks=$(adb shell ls /data/data 2>/dev/null | tr '\n' ' ' | tr -d '\r') + if [[ $prev != "-k" && $cur == "-" ]]; then + COMPREPLY=( $(compgen -W "-k $apks" -- ${cur}) ) + else + COMPREPLY=( $(compgen -W "$apks" -- ${cur}) ) + fi + return 0 + ;; + logcat) + case "${cur}" in + -*) + COMPREPLY=( $(compgen -W "-v -b -c -d -f -g -n -r -s" -- ${cur}) ) + return 0 + ;; + esac + case "${prev}" in + -v) + COMPREPLY=( $(compgen -W "brief process tag thread raw time long" -- ${cur}) ) + return 0 + ;; + -b) + COMPREPLY=( $(compgen -W "radio events main" -- ${cur}) ) + return 0 + ;; + esac + ;; + pull) + if [ ${prev} == "pull" ]; then + if [ -z ${cur} ]; then + local files=$(adb shell "ls -a -d /*" 2>/dev/null | tr '\n' ' ' | tr -d '\r') + COMPREPLY=( $(compgen -W "$files" -o filenames -- ${cur}) ) + else + local files=$(adb shell "ls -a -d ${cur}*" 2>/dev/null | tr '\n' ' ' | tr -d '\r') + COMPREPLY=( $(compgen -W "$files" -o filenames -- ${cur}) ) + fi + return 0 + fi + ;; + push) + if [ "${COMP_WORDS[COMP_CWORD-2]}" == "push" ]; then + if [ -z "${cur}" ]; then + local files=$(adb shell "ls -a -d /*" 2>/dev/null | tr '\n' ' ' | tr -d '\r') + COMPREPLY=( $(compgen -W "$files" -o filenames -- ${cur}) ) + else + local files=$(adb shell "ls -a -d ${cur}*" 2>/dev/null | tr '\n' ' ' | tr -d '\r') + COMPREPLY=( $(compgen -W "$files" -o filenames -- ${cur}) ) + fi + return 0 + fi + ;; + esac +} +complete -o default -F _adb adb + +# Local variables: +# mode: shell-script +# sh-basic-offset: 4 +# sh-indent-comment: t +# indent-tabs-mode: nil +# End: +# ex: ts=4 sw=4 et filetype=sh diff -Nru android-tools-4.2.2+git20130218/debian/bash_completion.d/fastboot android-tools-4.2.2+git20130529/debian/bash_completion.d/fastboot --- android-tools-4.2.2+git20130218/debian/bash_completion.d/fastboot 1970-01-01 00:00:00.000000000 +0000 +++ android-tools-4.2.2+git20130529/debian/bash_completion.d/fastboot 2014-11-24 20:27:47.000000000 +0000 @@ -0,0 +1,97 @@ +## Bash completion for the Android SDK tools. +## +## Copyright (c) 2009 Matt Brubeck +## +## Permission is hereby granted, free of charge, to any person obtaining a copy +## of this software and associated documentation files (the "Software"), to deal +## in the Software without restriction, including without limitation the rights +## to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +## copies of the Software, and to permit persons to whom the Software is +## furnished to do so, subject to the following conditions: +## +## The above copyright notice and this permission notice shall be included in +## all copies or substantial portions of the Software. +## +## THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +## IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +## FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +## AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +## LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +## OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +## THE SOFTWARE. + +function _fastboot() +{ + local cur prev opts cmds c subcommand device_selected + COMPREPLY=() + cur="${COMP_WORDS[COMP_CWORD]}" + prev="${COMP_WORDS[COMP_CWORD-1]}" + opts="-w -s -p -c -i -b -n" + cmds="update flashall flash erase getvar boot devices \ + reboot reboot-bootloader oem" + subcommand="" + partition_list="boot recovery system userdata" + device_selected="" + + # Look for the subcommand. + c=1 + while [ $c -lt $COMP_CWORD ]; do + word="${COMP_WORDS[c]}" + if [ "$word" = "-s" ]; then + device_selected=true + fi + for cmd in $cmds; do + if [ "$cmd" = "$word" ]; then + subcommand="$word" + fi + done + c=$((++c)) + done + + case "${subcommand}" in + '') + case "${prev}" in + -s) + # Use 'fastboot devices' to list serial numbers. + COMPREPLY=( $(compgen -W "$(fastboot devices|cut -f1)" -- ${cur} ) ) + return 0 + ;; + esac + case "${cur}" in + -*) + COMPREPLY=( $(compgen -W "$opts" -- ${cur}) ) + return 0 + ;; + esac + if [ -z "$device_selected" ]; then + local num_devices=$(( $(fastboot devices 2>/dev/null|wc -l) )) + if [ "$num_devices" -gt "1" ]; then + # With multiple devices, you must choose a device first. + COMPREPLY=( $(compgen -W "-s" -- ${cur}) ) + return 0 + fi + fi + COMPREPLY=( $(compgen -W "${cmds}" -- ${cur}) ) + return 0 + ;; + flash) + # partition name + COMPREPLY=( $(compgen -W "${partition_list}" -- ${cur}) ) + return 0 + ;; + erase) + # partition name + COMPREPLY=( $(compgen -W "${partition_list}" -- ${cur}) ) + return 0 + ;; + esac +} +complete -o default -F _fastboot fastboot + +# Local variables: +# mode: shell-script +# sh-basic-offset: 4 +# sh-indent-comment: t +# indent-tabs-mode: nil +# End: +# ex: ts=4 sw=4 et filetype=sh diff -Nru android-tools-4.2.2+git20130218/debian/changelog android-tools-4.2.2+git20130529/debian/changelog --- android-tools-4.2.2+git20130218/debian/changelog 2014-03-31 18:03:26.000000000 +0000 +++ android-tools-4.2.2+git20130529/debian/changelog 2015-08-11 09:21:16.000000000 +0000 @@ -1,169 +1,101 @@ -android-tools (4.2.2+git20130218-3ubuntu23) trusty; urgency=medium +android-tools (4.2.2+git20130529-5.1~ppa14.04+1) trusty; urgency=medium - * Start adbd under a PAM session, such that it has the default system - locale and environmental variables set. (LP: #1267117) + * Merge from Debian Unstable. - -- Dimitri John Ledkov Mon, 31 Mar 2014 18:57:22 +0100 + -- Nicolas Derive Tue, 11 Aug 2015 11:20:15 +0200 -android-tools (4.2.2+git20130218-3ubuntu22) trusty; urgency=medium +android-tools (4.2.2+git20130529-5.1) unstable; urgency=medium - * Add bash completion for adb and fastboot + * Non-maintainer upload. + * add patch for CVE-2014-1909 (Closes: #770513) - -- Chris Wayne Thu, 13 Mar 2014 18:10:45 -0400 + -- Hilko Bengen Mon, 24 Nov 2014 21:35:22 +0100 -android-tools (4.2.2+git20130218-3ubuntu21) trusty; urgency=low +android-tools (4.2.2+git20130529-5) unstable; urgency=low - * rework adbd upstart job to react to changes of the persist.sys.usb.config - property, on devices where functionfs is used (manta) we now mount the - functionfs layer to make the usb gadget usable by adb. + * use system group 'adb' for udev rules (Closes: #766399) - -- Oliver Grawert Thu, 06 Mar 2014 17:29:43 +0100 + -- Hans-Christoph Steiner Wed, 22 Oct 2014 19:43:35 -0400 -android-tools (4.2.2+git20130218-3ubuntu20) trusty; urgency=medium +android-tools (4.2.2+git20130529-4) unstable; urgency=low - * do not reset android_usb device on startup to not cause unwanted - disconnects + [ Hans-Christoph Steiner ] + * set "Android Tools" as Maintainer, add myself as Uploader, remove Marcin + * update udev rules (Closes: #690453, #754566) + * fix odd language in Description (Closes: #710785) + * fix missing word in adb Description (Closes: #745358) + * include AndroidConfig.h in builds (Closes: #700461) + * include bash completion rules for adb and fastboot + * fix build failure on ppc64el - -- Oliver Grawert Wed, 05 Mar 2014 14:50:10 +0100 + [ Ramakrishnan Muthukrishnan ] + * include man page for fastboot (Closes: #741967) -android-tools (4.2.2+git20130218-3ubuntu19) trusty; urgency=medium + -- Hans-Christoph Steiner Tue, 21 Oct 2014 22:39:19 -0400 - * debian/patches/ppc64el-ftbfs.patch: Fix build failure on ppc64el. +android-tools (4.2.2+git20130529-3) unstable; urgency=low - -- Steve Langasek Fri, 21 Feb 2014 16:42:58 -0800 + * Update my email address. -android-tools (4.2.2+git20130218-3ubuntu18) trusty; urgency=low + [ Hilko Bengen ] + * Fix previous local socket patch for adb + (Closes: #715238, #716996, #717525) - * Fix adbd upstart pre-start logic. + -- Laszlo Boszormenyi (GCS) Tue, 23 Jul 2013 23:51:22 +0200 - -- Dmitrijs Ledkovs Tue, 29 Oct 2013 12:19:42 +0000 +android-tools (4.2.2+git20130529-2.1) unstable; urgency=low -android-tools (4.2.2+git20130218-3ubuntu17) trusty; urgency=low + * Non-maintainer upload. + * adb: Use local socket by default (Closes: #694176) - * Patch adbd to provide commented out qemu_pipe launch path. - * Update android-tool-adbd.upstart job to launch adbd under qemu - emulator. + -- Hilko Bengen Thu, 04 Jul 2013 23:28:34 +0200 - -- Dmitrijs Ledkovs Mon, 28 Oct 2013 13:17:07 +0000 +android-tools (4.2.2+git20130529-2) unstable; urgency=low -android-tools (4.2.2+git20130218-3ubuntu16) saucy; urgency=low + * Misc fixes to adbd upstart job. + * Misc fixes to adbd env props support patch. + * Bump up Standards-Version to 3.9.4. + * Use canonical Vcs-Git format. - * android-tools-adbd.upstart: stop on runlevel [!2345] to avoid a respawn - loop when shutting down the device + -- Loïc Minier Wed, 19 Jun 2013 17:16:18 +0200 - -- Ricardo Salveti de Araujo Thu, 03 Oct 2013 16:19:32 -0300 +android-tools (4.2.2+git20130529-1) unstable; urgency=low -android-tools (4.2.2+git20130218-3ubuntu15) saucy; urgency=low + * Drop Architecture: linux-any field in the Source control stanza as that + breaks Launchpad and creates an useless delta with Ubuntu; drop it; + inspired from changes by Logan Rosen in 4.2.2+git20130218-3ubuntu1. + * Use uaccess in udev rules instead of deprecated udev-acl; thanks + Martin Pitt. + * Update udev rules to support more devices: 18d1:4e30 (fastboot on + maguro/toro), 18d1:4ee0 (fastboot on mako/manta) and 18d1:d002 (adb + recovery) and split rules in corresponding packages; from + 4.2.2+git20130218-3ubuntu3; thanks Sergio Schvezov. + * Add Vcs-Git + * Drop bogus external/zlib include in makefiles. + * Rework the makefiles and build rules to use a builddir per component + we're building. This paves the way to building adbd and adb out of the + same source, keeps the source tree clean and for some reason also fixes + ccache. + * Various changes and patches to help with adbd build: + - adb.mk: Define _XOPEN_SOURCE _GNU_SOURCE as in Android.mk. + - Add patch to use glibc syscall() for reboot. + - Add patch to use linux/capability.h on linux systems. + - Add patch to fake Android init properties via env vars. + - Update create-snapshot script to pull more sources needed for adbd; pull + libhardware includes from libhardware repo and private filesystem and + capability includes from core repo. + - Add local makefile to build adbd + * On Ubuntu and derivatives, build adbd binary and corresponding package + with upstart job taken from Ubuntu package 4.2.2+git20130218-3ubuntu9; + this is disabled on Debian and derivatives because it's essentially a + security hole in the form of an unauthenticated remote root shell. + * New upstream snapshot 4.2.2+git20130529; this is mainly to pick up new + source files but also picks up a number of minor upstream fixes. + - Add build-dep on libcap-dev for sys/capability.h. + * Add patch adbd-use-user-shell from Ubuntu by Stéphane Graber to use the + running user's shell by default. - * Fix the udev rules, adding the missing comma and backslash that were - causing every single device under /dev to be writable to the active - user. - - -- Stéphane Graber Thu, 03 Oct 2013 14:06:33 -0400 - -android-tools (4.2.2+git20130218-3ubuntu14) saucy; urgency=low - - * debian/android-tools-adb.udev: Adding rules for all usb configs that - enable adb. - - -- Sergio Schvezov Tue, 30 Jul 2013 15:08:43 -0300 - -android-tools (4.2.2+git20130218-3ubuntu13) saucy; urgency=low - - * debian/control: android-tools-adbd should depend on libhybris-utils to use - the android get/setprop utilities - * android-tools-adbd.upstart: also write the product, model and - serial number, otherwise there's no easy way to retrieve information from - the target device - - -- Ricardo Salveti de Araujo Thu, 04 Jul 2013 18:49:18 -0300 - -android-tools (4.2.2+git20130218-3ubuntu12) saucy; urgency=low - - * drop teh "stop on" stanza from adbd upstart job, we want it to run as long - as we can to be able to debug shutdown probalms, sendsigs should be enough - to kill the adbd process at the end of teh shutdown/reboot - - -- Oliver Grawert Fri, 28 Jun 2013 20:30:01 +0200 - -android-tools (4.2.2+git20130218-3ubuntu11) saucy; urgency=low - - * add a respawn to the android-tools-adbd upstart job - - -- Oliver Grawert Mon, 24 Jun 2013 14:58:21 +0200 - -android-tools (4.2.2+git20130218-3ubuntu10) saucy; urgency=low - - * debian/patches/adbd.patch: removing commented android_reboot call - * debian/patches/reboot-syscall.patch: use glibc syscall() for reboot - * debian/makefiles/adbd.mk: adding android_reboot.c to srcs - - -- Ricardo Salveti de Araujo Wed, 19 Jun 2013 02:43:35 -0300 - -android-tools (4.2.2+git20130218-3ubuntu9) saucy; urgency=low - - * adbd.upstart: if /sys/class/android_usb does exist, do not start adbd - daemon. - - -- Dmitrijs Ledkovs Fri, 14 Jun 2013 12:00:53 +0100 - -android-tools (4.2.2+git20130218-3ubuntu8) saucy; urgency=low - - * adbd: Use the running user's shell by default. - - -- Stéphane Graber Tue, 04 Jun 2013 18:18:12 -0400 - -android-tools (4.2.2+git20130218-3ubuntu7) saucy; urgency=low - - * fix path in android-tools-adbd upstart job - - -- Oliver Grawert Sun, 02 Jun 2013 15:19:30 +0200 - -android-tools (4.2.2+git20130218-3ubuntu6) saucy; urgency=low - - * actually exclude the build of adbd on powerpc as well in debian/rules - - -- Oliver Grawert Tue, 28 May 2013 20:48:22 +0200 - -android-tools (4.2.2+git20130218-3ubuntu5) saucy; urgency=low - - * only build android-tools-adbd on armhf, i386 and amd64 until powerpc - tablets and phones show up on teh market. - - -- Oliver Grawert Tue, 28 May 2013 18:50:39 +0200 - -android-tools (4.2.2+git20130218-3ubuntu4) saucy; urgency=low - - * debian/patches/add_adbd.patch (could need some cleanup since it is mostly - a copy of core/adb) - * add adbd.mk to debian/makefiles - * add build and clean targets for adbd to debian/rules - * add android-tools-adbd binary package (debian/control and .install file) - * add upstart job that starts adbd - - -- Oliver Grawert Tue, 28 May 2013 13:27:09 +0200 - -android-tools (4.2.2+git20130218-3ubuntu3) saucy; urgency=low - - * Add udev rules to access adb from the user console (LP: #1177850). - * Add udev rules to access fastboot from the user console for grouper, - manta, mako and maguro (LP: #1177874). - - -- Sergio Schvezov Wed, 08 May 2013 13:03:06 -0300 - -android-tools (4.2.2+git20130218-3ubuntu2) saucy; urgency=low - - * debian/android-tools-fastboot.udev: Use uaccess instead of udev-acl (which - is gone now). - - -- Martin Pitt Tue, 30 Apr 2013 16:23:18 -0700 - -android-tools (4.2.2+git20130218-3ubuntu1) raring; urgency=low - - * debian/control: Move Architecture field (and associated comments) to the - android-tools-adb binary to fix the FTBFS. - - -- Logan Rosen Tue, 26 Mar 2013 14:27:49 -0400 + -- Loïc Minier Wed, 19 Jun 2013 00:17:40 +0200 android-tools (4.2.2+git20130218-3) unstable; urgency=low diff -Nru android-tools-4.2.2+git20130218/debian/control android-tools-4.2.2+git20130529/debian/control --- android-tools-4.2.2+git20130218/debian/control 2014-03-14 04:06:05.000000000 +0000 +++ android-tools-4.2.2+git20130529/debian/control 2014-11-24 20:27:47.000000000 +0000 @@ -1,18 +1,22 @@ Source: android-tools Section: devel Priority: extra -Maintainer: Ubuntu Developers -XSBC-Original-Maintainer: Laszlo Boszormenyi (GCS) -Uploaders: Loïc Minier , - Marcin Juszkiewicz +Maintainer: Android tools Maintainer +Uploaders: Laszlo Boszormenyi (GCS) , + Hans-Christoph Steiner , + Loïc Minier Build-Depends: debhelper (>= 9), + android-system-dev, + libcap-dev, libselinux-dev, libssl-dev, python, zlib1g-dev, bash-completion -Standards-Version: 3.9.3 +Standards-Version: 3.9.6 Homepage: http://developer.android.com/guide/developing/tools/adb.html +Vcs-Git: https://anonscm.debian.org/git/android-tools/android-tools.git +Vcs-Browser: http://anonscm.debian.org/cgit/android-tools/android-tools.git Package: android-tools-adb # requires porting of selinux calls in extras/ext4_utils and @@ -20,9 +24,9 @@ Architecture: linux-any Depends: ${misc:Depends}, ${shlibs:Depends} Description: Android Debug Bridge CLI tool - Android Debug Bridge (adb) is a versatile tool lets you manage the - state of an emulator instance or Android-powered device. It is a - client-server program that includes three components: + Android Debug Bridge (adb) is a versatile tool that lets you manage the state + of an emulator instance or Android-powered device. It is a client-server + program that includes three components: . A client, which runs on your development machine. You can invoke a client from a shell by issuing an adb command. Other Android tools such @@ -49,18 +53,7 @@ Depends: ${misc:Depends}, ${python:Depends}, ${shlibs:Depends} Description: Android ext4 utilities with sparse support Android images (.img) are typically ext4 filesystems in a special - sparse file format come in a special format. + sparse file format. These are tools to help make that format. . This package provides the utilities to deal with Android sparse ext4 images. - -Package: android-tools-adbd -Architecture: armhf i386 amd64 -Depends: libhybris-utils, ${misc:Depends}, ${python:Depends}, ${shlibs:Depends} -Description: Android Debug Bridge Phone Daemon - Android Debug Bridge (adb) is a versatile tool lets you manage the - state of an emulator instance or Android-powered device. It is a - client-server program that includes three components. - . - This package provides the daemon, which runs as a background process - on a device you want to connect to from a PC. diff -Nru android-tools-4.2.2+git20130218/debian/copyright android-tools-4.2.2+git20130529/debian/copyright --- android-tools-4.2.2+git20130218/debian/copyright 2014-03-14 04:05:30.000000000 +0000 +++ android-tools-4.2.2+git20130529/debian/copyright 2014-11-24 20:27:47.000000000 +0000 @@ -5,7 +5,7 @@ Files: * Copyright: 2006-2012, The Android Open Source Project 2006, Brian Swetland -License: Apache 2.0 +License: Apache-2.0 Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. . @@ -21,7 +21,7 @@ Files: debian/* Copyright: 2012, Linaro Ltd. 2012, Laszlo Boszormenyi (GCS) -License: GPL v2 +License: GPL-2 This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either @@ -43,6 +43,45 @@ License version 2 can be found in the file `/usr/share/common-licenses/GPL-2'. +Files: debian/*.udev +Copyright: 2012-2014 M0Rf30 + 2012-2014 Gianluca Boiano +License: GPL-3 + This program is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public + License as published by the Free Software Foundation; either + version 3 of the License, or (at your option) any later + version. + . + This program is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied + warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the GNU General Public License for more + details. + . + You should have received a copy of the GNU General Public + License along with this package; if not, write to the Free + Software Foundation, Inc., 51 Franklin St, Fifth Floor, + Boston, MA 02110-1301 USA + . + On Debian systems, the full text of the GNU General Public + License version 3 can be found in the file + `/usr/share/common-licenses/GPL-3'. + +Files: debian/bash_completion.d/* +Copyright: 2011-2014, Hans-Christoph Steiner + 2009 Matt Brubeck +License: MIT + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + . + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + Files: core/fastboot/* Copyright: 2008, The Android Open Source Project 2007, Google Inc. @@ -98,43 +137,17 @@ OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -Files: core/libcutils/private.h - core/libcutils/tzfile.h - core/libcutils/tztime.c -Copyright: none -License: public domain - This file is in the public domain, so clarified as of │ - 1996-06-05 by Arthur David Olson. - -Files: core/libcutils/tzstrftime.c -Copyright: 1989 The Regents of the University of California. -License: Prior BSD License - Copyright (c) 1989 The Regents of the University of California. - All rights reserved. - . - Redistribution and use in source and binary forms are permitted - provided that the above copyright notice and this paragraph are - duplicated in all such forms and that any documentation, - advertising materials, and other materials related to such - distribution and use acknowledge that the software was developed - by the University of California, Berkeley. The name of the - University may not be used to endorse or promote products derived - from this software without specific prior written permission. - THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR - IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED - WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. - Files: extras/ext4_utils/sha1.c extras/ext4_utils/sha1.h Copyright: none -License: public domain +License: public-domain SHA-1 in C By Steve Reid 100% Public Domain Files: core/libsparse/sparse_crc32.c Copyright: none -License: public domain +License: public-domain COPYRIGHT (C) 1986 Gary S. Brown. You may use this program, or code or tables extracted from it, as desired without restriction. @@ -143,7 +156,7 @@ extras/ext4_utils/ext4_jbd2.h extras/ext4_utils/jbd2.h Copyright: none -License: public domain +License: public-domain This header was automatically generated from a Linux kernel header of the same name, to make information necessary for userspace to call into the kernel available to libc. It contains only constants, @@ -153,7 +166,7 @@ Files: core/include/cutils/ashmem.h core/include/cutils/logger.h Copyright: 2006-2012, The Android Open Source Project -License: Apache 2.0 or GPL v2 +License: Apache-2.0 or GPL-2 Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. . diff -Nru android-tools-4.2.2+git20130218/debian/create-snapshot android-tools-4.2.2+git20130529/debian/create-snapshot --- android-tools-4.2.2+git20130218/debian/create-snapshot 2014-03-14 04:05:30.000000000 +0000 +++ android-tools-4.2.2+git20130529/debian/create-snapshot 2014-11-24 20:27:47.000000000 +0000 @@ -26,6 +26,7 @@ ANDROID_MIRROR="https://android.googlesource.com/" CORE_REPO="$ANDROID_MIRROR/platform/system/core" EXTRAS_REPO="$ANDROID_MIRROR/platform/system/extras" +LIBHARDWARE_REPO="$ANDROID_MIRROR/platform/hardware/libhardware" GITIGNORE=" * !*.[ch] @@ -35,6 +36,7 @@ !/core/include/ !/core/include/cutils/ !/core/include/mincrypt/ +!/core/include/private/ !/core/include/zipfile/ !/core/libcutils/ !/core/libzipfile/ @@ -47,6 +49,9 @@ !/extras/ext4_utils/ !/extras/ext4_utils/mkuserimg.sh !/extras/ext4_utils/test_ext4fixup +!/libhardware/ +!/libhardware/include/ +!/libhardware/include/hardware/ " self="$(basename "$0")" @@ -85,8 +90,10 @@ git clone "$CORE_REPO" log_i "Cloning extras..." git clone "$EXTRAS_REPO" + log_i "Cloning libhardware..." + git clone "$LIBHARDWARE_REPO" - for d in core extras; do + for d in core extras libhardware; do (cd "$d" && log_i "$d: abbrev=`git_abbrev` tag=`git_latest_tag`") rm -rf "$d/.git" done diff -Nru android-tools-4.2.2+git20130218/debian/fastboot.1 android-tools-4.2.2+git20130529/debian/fastboot.1 --- android-tools-4.2.2+git20130218/debian/fastboot.1 1970-01-01 00:00:00.000000000 +0000 +++ android-tools-4.2.2+git20130529/debian/fastboot.1 2014-11-24 20:27:47.000000000 +0000 @@ -0,0 +1,193 @@ +.TH fastboot +.SH NAME +fastboot \- manipulate the non-volatile flash partitions +.SH SYNOPSIS +.B fastboot +[\fIoptions\fR] +[\fIcommands\fR] +.SH DESCRIPTION +.B fastboot +is a program used to manipulate (list, install, erase) the non-volatile +memory such as flash filesystem partitions on devices that adhere to the +fastboot protocol, via a USB connection from a host computer. It requires +that the device be started in a boot loader mode with the fastboot +protocol enabled. Once connected to the device, the program accepts a +specific set of commands sent to it via the USB using the fastboot +program on the host. +.PP +fastboot is primarily used for installing the operating system binary +`images' into the non-volatile flash memory of the devices. +.PP +The partition should adhere to a specific layout. Fastboot was designed +for use with phones and tablets running the Android operating system. +.PP +To allow non-root user access to the devices, one might needed to add +udev rules file for the specific device and add the user to the +appopriate group (typically the group is named \fIplugdev\fR). +.PP +If the device is not connected, certain fastboot commands display the +output: +.PP + < waiting for the device > +.br +.PP +and waits till it detects and establish a fastboot connection with +the connected device. Otherwise, it prints a helpful list of commands +and switches and exits. +.SH OPTIONS +.TP +.BR \-w +Erase userdata and cache and format, if supported by the partition type. +.TP +.BR \-u +Do not first erase partition before formatting. +.TP +.BR \-s " " \fIdevice\fR +Specify device serial number or path to device port. +.IP +The device serial number can also be set by setting the environment +variable ANDROID_SERIAL. +.TP +.BR \-l +Lists device paths. Works only with the command \fIdevices\fR. +.TP +.BR \-p " " \fIproduct\fR +Specify the device product name. +.IP +Normally `fastboot' binary is built when building Android from the source +using the `Android Open Source Project' (AOSP) repositories. Assuming +\fI$aosp\fR is the root of the AOSP source code, the output binaries and +images are stored in the $AOSP/out directory. `fastboot' binary lives in +`$AOSP/out/host/linux-x86/bin' directory. If run from this directory, the +images are looked for in `../../../target/product/$product' directory +where $product is specified with the `\-p' switch. +.IP +If this switch is not set, the environment variable ANDROID_PRODUCT_OUT +should be set to the directory containing the binary images. +.IP +This switch is generally specified with the \fIflash\fR and \fIflashall\fR +commands. +.TP +.BR \-c " " \fIcommandline\fR +Override linux kernel command line. This switch is typically used along +with the command \fIboot\fR. See the EXAMPLES section for a typical usage. +.TP +.BR \-i " " \fIVendorID\fR +Specify a custom USB Vendor ID for the device. +.TP +.BR \-b " " \fIbase_addr\fR +Specify a custom linux kernel base address. +.TP +.BR \-n " " \fIpagesize\fR +Specify page size for the flash device. Default value is 2048. +.TP +.BR \-S " " \fIsize[K|M|G]\fR +Automatically sparse files greater than the specified \fIsize\fR. Specify +the \fIsize\fR as 0 to disable sparse files. +.SH COMMANDS +.TP +.BR update " " \fIfilename\fR +Reflash the device from the give update file. The filename must be a zip +file. +.TP +.BR flashall +Reflash boot partition, recovery partition and the system partition. +.TP +.BR flash " " \fIpartition\fR " " [\fIfilename\fR] +Write the given file to the specified partition. +.TP +.BR erase " " \fIpartition\fR +Erase a flash partition. +.TP +.BR format " " \fIpartition\fR +Format a flash partition. +.TP +.BR getvar " " \fIvariable\fR +Display a bootloader variable. +.TP +.BR boot " " \fIkernel\fR " " [\fIramdisk\fR] +Download and boot kernel. +.TP +.BR flash:raw " " boot " " \fIkernel\fR " " [\fIramdisk\fR] +Create boot image and flash it. +.TP +.BR devices +List all connected devices. +.TP +.BR continue +Continue with autoboot. +.TP +.BR reboot\-bootloader +Reboot device into bootloader. +.TP +.BR reboot +.RS +Reboot the device normally.. +.RE +.TP +.BR help +.RS +Show a help message. +.RE +.SH ENVIRONMENT +.B ANDROID_PRODUCT_OUT +.IP +This variable should be set to the root of the directory where the +images for the specific product is stored. +.PP +.B ANDROID_SERIAL +.IP +Thie variable can be used to specify the device serial number. +.SH EXAMPLES +.nf +1. Flashing the recovery image: + fastboot flash recovery recovery.img + +2. Flash the kernel and bootloader: + fastboot flash boot boot.img + +3. Erase a partition: + fastboot erase cache + +4. Reboot the phone: + fastboot reboot + +5. Boot with a custom built kernel and root filesystem (but not write them into the flash memory): + fastboot boot linux-2.6/arch/arm/boot/zImage root-image/recovery.img-ramdisk.cpio.gz + +6. Format partitions: + fastboot format cache + fastboot format userdata + +7. Flash all partitions at once: + fastboot \-w flashall + +8. Restoring from backed up images in the user's computer:: + fastboot erase system + fastboot erase data + fastboot erase cache + and then flash the images (starting with system): + fastboot flash system system.img + fastboot flash data data.img + fastboot flash cache cache.img + +9. Boot the phone with a specific linux kernel commandline argument: + fastboot \-c "console=ttyHSL0,115200,n8" boot boot.img + +.fi +.SH DIAGNOSTICS +Make sure that the device is connected and is visible via \fIlsusb\fR. +If the device is detected by `\fIlsusb\fR' and `\fIadb devices\fR' output +shows `\fI???????????? device\fR', then try reloading udev rules or +try disconnecting and connecting the cables. +.SH BUGS +The command name should have been chosen more carefully to reflect its +purpose. +.SH AUTHOR +.B fastboot +was written by engineers at Google for the Android project. +.PP +Ramakrishnan Muthukrishnan wrote this manual page, originally for the +Debian Project, with a lot of suggestions from Raul Miller. +.SH SEE ALSO +\fBadb\fP(1), \fBudev\fP(7), \fBlsusb\fP(8) diff -Nru android-tools-4.2.2+git20130218/debian/fastboot-completion android-tools-4.2.2+git20130529/debian/fastboot-completion --- android-tools-4.2.2+git20130218/debian/fastboot-completion 2014-03-14 04:06:05.000000000 +0000 +++ android-tools-4.2.2+git20130529/debian/fastboot-completion 1970-01-01 00:00:00.000000000 +0000 @@ -1,41 +0,0 @@ -_fastboot() -{ - local cur prev opts - COMPREPLY=() - cur="${COMP_WORDS[COMP_CWORD]}" - prev="${COMP_WORDS[COMP_CWORD-1]}" - opts="reboot boot flash devices -w reboot-bootloader" - - case "$prev" in - reboot | devices | -w | reboot-bootloader) - COMPREPLY=() - return 0 - ;; - flash) - COMPREPLY=( $(compgen -W "boot system recovery radio" -- $cur )) - return 0 - ;; - boot) - COMPREPLY=( $(compgen -o filenames -G "${cur}*.img")) - return 0 - ;; - *) - local prev2="${COMP_WORDS[COMP_CWORD-2]}" - local prev3="${COMP_WORDS[COMP_CWORD-3]}" - if [ "$prev2" == "flash" ];then - COMPREPLY=( $(compgen -o filenames -G "${cur}*.img")) - return 0 - elif [ "$prev2" == "boot" ];then - COMPREPLY=() - return 0 - elif [ "$prev3" == "flash" ];then - COMPREPLY=() - return 0 - fi - ;; - esac - - COMPREPLY=( $(compgen -W "$opts" -- $cur) ) - return 0 -} -complete -F _fastboot fastboot diff -Nru android-tools-4.2.2+git20130218/debian/makefiles/adbd.mk android-tools-4.2.2+git20130529/debian/makefiles/adbd.mk --- android-tools-4.2.2+git20130218/debian/makefiles/adbd.mk 2014-03-14 04:05:30.000000000 +0000 +++ android-tools-4.2.2+git20130529/debian/makefiles/adbd.mk 1970-01-01 00:00:00.000000000 +0000 @@ -1,60 +0,0 @@ -# Makefile for adbd - -VPATH+= ../libcutils -SRCS+= abort_socket.c -SRCS+= socket_inaddr_any_server.c -SRCS+= socket_local_client.c -SRCS+= socket_local_server.c -SRCS+= socket_loopback_client.c -SRCS+= socket_loopback_server.c -SRCS+= socket_network_client.c -SRCS+= list.c -SRCS+= load_file.c -SRCS+= android_reboot.c - -#VPATH+= ../adb -SRCS+= adb.c -SRCS+= backup_service.c -SRCS+= fdevent.c -SRCS+= transport.c -SRCS+= transport_local.c -SRCS+= transport_usb.c -SRCS+= adb_auth_client.c -SRCS+= sockets.c -SRCS+= services.c -SRCS+= file_sync_service.c -SRCS+= jdwp_service.c -SRCS+= framebuffer_service.c -SRCS+= remount_service.c -SRCS+= usb_linux_client.c -SRCS+= log_service.c -SRCS+= utils.c -SRCS+= base64.c - -VPATH+= ../libzipfile -SRCS+= centraldir.c -SRCS+= zipfile.c - - -CPPFLAGS+= -O2 -g -Wall -Wno-unused-parameter -CPPFLAGS+= -DADB_HOST=0 -DHAVE_FORKEXEC=1 -D_XOPEN_SOURCE -D_GNU_SOURCE -DALLOW_ADBD_ROOT=1 -CPPFLAGS+= -DHAVE_SYMLINKS -DBOARD_ALWAYS_INSECURE -CPPFLAGS+= -DHAVE_TERMIO_H -CPPFLAGS+= -I. -CPPFLAGS+= -I../include -CPPFLAGS+= -I../../../external/zlib - -LIBS+= -lc -lpthread -lz -lcrypto - -OBJS= $(patsubst %, %.o, $(basename $(SRCS))) - -all: adbd - -adbd: $(OBJS) - $(CC) -o $@ $(LDFLAGS) $(OBJS) $(LIBS) - -#%.o: -# echo $(OBJS) -# $(CC) -o $@ $(CPPFLAGS) $(CFLAGS) -c $(wildcard $(addprefix $(CURDIR)/../*/,$(patsubst %.o, %.c, $@))) -clean: - rm -rf $(OBJS) adbd diff -Nru android-tools-4.2.2+git20130218/debian/makefiles/adb.mk android-tools-4.2.2+git20130529/debian/makefiles/adb.mk --- android-tools-4.2.2+git20130218/debian/makefiles/adb.mk 2014-03-14 04:05:30.000000000 +0000 +++ android-tools-4.2.2+git20130529/debian/makefiles/adb.mk 2014-11-24 20:27:47.000000000 +0000 @@ -1,5 +1,8 @@ # Makefile for adb; from https://heiher.info/2227.html +SRCDIR ?= $(CURDIR) + +VPATH+= $(SRCDIR)/core/adb SRCS+= adb.c SRCS+= adb_client.c SRCS+= adb_auth_host.c @@ -17,7 +20,7 @@ SRCS+= usb_vendors.c SRCS+= utils.c -VPATH+= ../libcutils +VPATH+= $(SRCDIR)/core/libcutils SRCS+= abort_socket.c SRCS+= socket_inaddr_any_server.c SRCS+= socket_local_client.c @@ -28,18 +31,16 @@ SRCS+= list.c SRCS+= load_file.c -VPATH+= ../libzipfile +VPATH+= $(SRCDIR)/core/libzipfile SRCS+= centraldir.c SRCS+= zipfile.c +CPPFLAGS+= -D_XOPEN_SOURCE -D_GNU_SOURCE CPPFLAGS+= -DADB_HOST=1 -CPPFLAGS+= -DHAVE_FORKEXEC=1 -CPPFLAGS+= -DHAVE_SYMLINKS -CPPFLAGS+= -DHAVE_TERMIO_H -CPPFLAGS+= -I. -CPPFLAGS+= -I../include -CPPFLAGS+= -I../../../external/zlib +CPPFLAGS+= -I$(SRCDIR)/core/adb +CPPFLAGS+= -I$(SRCDIR)/core/include +CPPFLAGS+= -include /usr/include/android/arch/linux-x86/AndroidConfig.h LIBS+= -lc -lpthread -lz -lcrypto diff -Nru android-tools-4.2.2+git20130218/debian/makefiles/ext4_utils.mk android-tools-4.2.2+git20130529/debian/makefiles/ext4_utils.mk --- android-tools-4.2.2+git20130218/debian/makefiles/ext4_utils.mk 2014-03-14 04:05:30.000000000 +0000 +++ android-tools-4.2.2+git20130529/debian/makefiles/ext4_utils.mk 2014-11-24 20:27:47.000000000 +0000 @@ -1,6 +1,9 @@ # Makefile for ext4_utils; based on https://heiher.info/2227.html # Author: Dmitrijs Ledkovs +SRCDIR ?= $(CURDIR) + +VPATH+= $(SRCDIR)/extras/ext4_utils SRCS+=make_ext4fs.c SRCS+=ext4fixup.c SRCS+=ext4_utils.c @@ -13,7 +16,7 @@ SRCS+=wipe.c SRCS+=crc16.c -VPATH+=../../core/libsparse +VPATH+= $(SRCDIR)/core/libsparse SRCS+= backed_block.c SRCS+= sparse_crc32.c SRCS+= sparse.c @@ -31,10 +34,11 @@ SRCS+=simg2img.c SRCS+=simg2simg.c -CPPFLAGS+= -I. +CPPFLAGS+= -I$(SRCDIR)/extras/ext4_utils CPPFLAGS+= -I/usr/include -CPPFLAGS+= -I../../core/include -CPPFLAGS+= -I../../core/libsparse/include/ +CPPFLAGS+= -I$(SRCDIR)/core/include +CPPFLAGS+= -I$(SRCDIR)/core/libsparse/include +CPPFLAGS+= -include /usr/include/android/arch/linux-x86/AndroidConfig.h LIBS+= -lz -lselinux diff -Nru android-tools-4.2.2+git20130218/debian/makefiles/fastboot.mk android-tools-4.2.2+git20130529/debian/makefiles/fastboot.mk --- android-tools-4.2.2+git20130218/debian/makefiles/fastboot.mk 2014-03-14 04:05:30.000000000 +0000 +++ android-tools-4.2.2+git20130529/debian/makefiles/fastboot.mk 2014-11-24 20:27:47.000000000 +0000 @@ -1,5 +1,8 @@ # Makefile for fastboot; from https://heiher.info/2227.html +SRCDIR ?= $(CURDIR) + +VPATH+= $(SRCDIR)/core/fastboot SRCS+= bootimg.c SRCS+= engine.c SRCS+= fastboot.c @@ -7,11 +10,11 @@ SRCS+= usb_linux.c SRCS+= util_linux.c -VPATH+= ../libzipfile +VPATH+= $(SRCDIR)/core/libzipfile SRCS+= centraldir.c SRCS+= zipfile.c -VPATH+= ../libsparse +VPATH+= $(SRCDIR)/core/libsparse SRCS+= backed_block.c SRCS+= sparse_crc32.c SRCS+= sparse.c @@ -19,7 +22,7 @@ SRCS+= sparse_err.c SRCS+= output_file.c -VPATH+= ../../extras/ext4_utils/ +VPATH+= $(SRCDIR)/extras/ext4_utils SRCS+= make_ext4fs.c SRCS+= crc16.c SRCS+= ext4_utils.c @@ -31,11 +34,12 @@ SRCS+= wipe.c SRCS+= sha1.c -CPPFLAGS+= -I. -CPPFLAGS+= -I../include -CPPFLAGS+= -I../mkbootimg -CPPFLAGS+= -I../../extras/ext4_utils/ -CPPFLAGS+= -I../libsparse/include/ +CPPFLAGS+= -I$(SRCDIR)/core/fastboot +CPPFLAGS+= -I$(SRCDIR)/core/include +CPPFLAGS+= -I$(SRCDIR)/core/mkbootimg +CPPFLAGS+= -I$(SRCDIR)/extras/ext4_utils +CPPFLAGS+= -I$(SRCDIR)/core/libsparse/include +CPPFLAGS+= -include /usr/include/android/arch/linux-x86/AndroidConfig.h LIBS+= -lz -lselinux diff -Nru android-tools-4.2.2+git20130218/debian/patches/add_adbd.patch android-tools-4.2.2+git20130529/debian/patches/add_adbd.patch --- android-tools-4.2.2+git20130218/debian/patches/add_adbd.patch 2014-03-14 04:05:30.000000000 +0000 +++ android-tools-4.2.2+git20130529/debian/patches/add_adbd.patch 1970-01-01 00:00:00.000000000 +0000 @@ -1,20218 +0,0 @@ -## Description: add some description -## Origin/Author: add some origin or author -## Bug: bug URL -Index: android-tools-4.2.2+git20130218/core/adbd/adb.c -=================================================================== ---- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ android-tools-4.2.2+git20130218/core/adbd/adb.c 2013-06-18 17:12:17.000000000 -0300 -@@ -0,0 +1,1719 @@ -+/* -+ * 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 -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include "sysdeps.h" -+#include "adb.h" -+#include "adb_auth.h" -+ -+#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0])) -+ -+#if !ADB_HOST -+#include "android_filesystem_config.h" -+#include -+#include -+#include -+#else -+#include "usb_vendors.h" -+#endif -+ -+#if ADB_TRACE -+ADB_MUTEX_DEFINE( D_lock ); -+#endif -+ -+int HOST = 0; -+int gListenAll = 0; -+ -+static int auth_enabled = 0; -+ -+#if !ADB_HOST -+static const char *adb_device_banner = "device"; -+#endif -+ -+void fatal(const char *fmt, ...) -+{ -+ va_list ap; -+ va_start(ap, fmt); -+ fprintf(stderr, "error: "); -+ vfprintf(stderr, fmt, ap); -+ fprintf(stderr, "\n"); -+ va_end(ap); -+ exit(-1); -+} -+ -+void fatal_errno(const char *fmt, ...) -+{ -+ va_list ap; -+ va_start(ap, fmt); -+ fprintf(stderr, "error: %s: ", strerror(errno)); -+ vfprintf(stderr, fmt, ap); -+ fprintf(stderr, "\n"); -+ va_end(ap); -+ exit(-1); -+} -+ -+int adb_trace_mask; -+ -+/* read a comma/space/colum/semi-column separated list of tags -+ * from the ADB_TRACE environment variable and build the trace -+ * mask from it. note that '1' and 'all' are special cases to -+ * enable all tracing -+ */ -+void adb_trace_init(void) -+{ -+ const char* p = getenv("ADB_TRACE"); -+ const char* q; -+ -+ static const struct { -+ const char* tag; -+ int flag; -+ } tags[] = { -+ { "1", 0 }, -+ { "all", 0 }, -+ { "adb", TRACE_ADB }, -+ { "sockets", TRACE_SOCKETS }, -+ { "packets", TRACE_PACKETS }, -+ { "rwx", TRACE_RWX }, -+ { "usb", TRACE_USB }, -+ { "sync", TRACE_SYNC }, -+ { "sysdeps", TRACE_SYSDEPS }, -+ { "transport", TRACE_TRANSPORT }, -+ { "jdwp", TRACE_JDWP }, -+ { "services", TRACE_SERVICES }, -+ { "auth", TRACE_AUTH }, -+ { 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++; -+ } -+} -+ -+#if !ADB_HOST -+/* -+ * Implements ADB tracing inside the emulator. -+ */ -+ -+#include -+ -+/* -+ * Redefine open and write for qemu_pipe.h that contains inlined references -+ * to those routines. We will redifine them back after qemu_pipe.h inclusion. -+ */ -+ -+#undef open -+#undef write -+#define open adb_open -+#define write adb_write -+#include "qemu_pipe.h" -+#undef open -+#undef write -+#define open ___xxx_open -+#define write ___xxx_write -+ -+/* A handle to adb-debug qemud service in the emulator. */ -+int adb_debug_qemu = -1; -+ -+/* Initializes connection with the adb-debug qemud service in the emulator. */ -+static int adb_qemu_trace_init(void) -+{ -+ char con_name[32]; -+ -+ if (adb_debug_qemu >= 0) { -+ return 0; -+ } -+ -+ /* adb debugging QEMUD service connection request. */ -+ snprintf(con_name, sizeof(con_name), "qemud:adb-debug"); -+ adb_debug_qemu = qemu_pipe_open(con_name); -+ return (adb_debug_qemu >= 0) ? 0 : -1; -+} -+ -+void adb_qemu_trace(const char* fmt, ...) -+{ -+ va_list args; -+ va_start(args, fmt); -+ char msg[1024]; -+ -+ if (adb_debug_qemu >= 0) { -+ vsnprintf(msg, sizeof(msg), fmt, args); -+ adb_write(adb_debug_qemu, msg, strlen(msg)); -+ } -+} -+#endif /* !ADB_HOST */ -+ -+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(atransport *t) -+{ -+ D("adb: online\n"); -+ t->online = 1; -+} -+ -+void handle_offline(atransport *t) -+{ -+ D("adb: offline\n"); -+ //Close the associated usb -+ t->online = 0; -+ run_transport_disconnects(t); -+} -+ -+#if DEBUG_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; -+ case A_AUTH: tag = "AUTH"; 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++; -+ } -+ fputs(tag, stderr); -+} -+#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 size_t fill_connect_data(char *buf, size_t bufsize) -+{ -+#if ADB_HOST -+ return snprintf(buf, bufsize, "host::") + 1; -+#else -+ static const char *cnxn_props[] = { -+ "ro.product.name", -+ "ro.product.model", -+ "ro.product.device", -+ }; -+ static const int num_cnxn_props = ARRAY_SIZE(cnxn_props); -+ static const char *values[] = { -+ "occam", -+ "Nexus 4", -+ "mako", -+ }; -+ int i; -+ size_t remaining = bufsize; -+ size_t len; -+ -+ len = snprintf(buf, remaining, "%s::", adb_device_banner); -+ remaining -= len; -+ buf += len; -+ for (i = 0; i < num_cnxn_props; i++) { -+ char value[PROPERTY_VALUE_MAX]; -+ //property_get(cnxn_props[i], value, ""); -+ len = snprintf(buf, remaining, "%s=%s;", cnxn_props[i], values[i]); -+ remaining -= len; -+ buf += len; -+ } -+ -+ return bufsize - remaining + 1; -+#endif -+} -+ -+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; -+ cp->msg.data_length = fill_connect_data((char *)cp->data, -+ sizeof(cp->data)); -+ send_packet(cp, t); -+} -+ -+static void send_auth_request(atransport *t) -+{ -+ D("Calling send_auth_request\n"); -+ apacket *p; -+ int ret; -+ -+ ret = adb_auth_generate_token(t->token, sizeof(t->token)); -+ if (ret != sizeof(t->token)) { -+ D("Error generating token ret=%d\n", ret); -+ return; -+ } -+ -+ p = get_apacket(); -+ memcpy(p->data, t->token, ret); -+ p->msg.command = A_AUTH; -+ p->msg.arg0 = ADB_AUTH_TOKEN; -+ p->msg.data_length = ret; -+ send_packet(p, t); -+} -+ -+static void send_auth_response(uint8_t *token, size_t token_size, atransport *t) -+{ -+ D("Calling send_auth_response\n"); -+ apacket *p = get_apacket(); -+ int ret; -+ -+ ret = adb_auth_sign(t->key, token, token_size, p->data); -+ if (!ret) { -+ D("Error signing the token\n"); -+ put_apacket(p); -+ return; -+ } -+ -+ p->msg.command = A_AUTH; -+ p->msg.arg0 = ADB_AUTH_SIGNATURE; -+ p->msg.data_length = ret; -+ send_packet(p, t); -+} -+ -+static void send_auth_publickey(atransport *t) -+{ -+ D("Calling send_auth_publickey\n"); -+ apacket *p = get_apacket(); -+ int ret; -+ -+ ret = adb_auth_get_userkey(p->data, sizeof(p->data)); -+ if (!ret) { -+ D("Failed to get user public key\n"); -+ put_apacket(p); -+ return; -+ } -+ -+ p->msg.command = A_AUTH; -+ p->msg.arg0 = ADB_AUTH_RSAPUBLICKEY; -+ p->msg.data_length = ret; -+ send_packet(p, t); -+} -+ -+void adb_auth_verified(atransport *t) -+{ -+ handle_online(t); -+ send_connect(t); -+} -+ -+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"; -+ } -+} -+ -+/* qual_overwrite is used to overwrite a qualifier string. dst is a -+ * pointer to a char pointer. It is assumed that if *dst is non-NULL, it -+ * was malloc'ed and needs to freed. *dst will be set to a dup of src. -+ */ -+static void qual_overwrite(char **dst, const char *src) -+{ -+ if (!dst) -+ return; -+ -+ free(*dst); -+ *dst = NULL; -+ -+ if (!src || !*src) -+ return; -+ -+ *dst = strdup(src); -+} -+ -+void parse_banner(char *banner, atransport *t) -+{ -+ static const char *prop_seps = ";"; -+ static const char key_val_sep = '='; -+ char *cp; -+ char *type; -+ -+ D("parse_banner: %s\n", banner); -+ type = banner; -+ cp = strchr(type, ':'); -+ if (cp) { -+ *cp++ = 0; -+ /* Nothing is done with second field. */ -+ cp = strchr(cp, ':'); -+ if (cp) { -+ char *save; -+ char *key; -+ key = adb_strtok_r(cp + 1, prop_seps, &save); -+ while (key) { -+ cp = strchr(key, key_val_sep); -+ if (cp) { -+ *cp++ = '\0'; -+ if (!strcmp(key, "ro.product.name")) -+ qual_overwrite(&t->product, cp); -+ else if (!strcmp(key, "ro.product.model")) -+ qual_overwrite(&t->model, cp); -+ else if (!strcmp(key, "ro.product.device")) -+ qual_overwrite(&t->device, cp); -+ } -+ key = adb_strtok_r(NULL, prop_seps, &save); -+ } -+ } -+ } -+ -+ if(!strcmp(type, "bootloader")){ -+ D("setting connection_state to CS_BOOTLOADER\n"); -+ t->connection_state = CS_BOOTLOADER; -+ update_transports(); -+ return; -+ } -+ -+ if(!strcmp(type, "device")) { -+ D("setting connection_state to CS_DEVICE\n"); -+ t->connection_state = CS_DEVICE; -+ update_transports(); -+ return; -+ } -+ -+ if(!strcmp(type, "recovery")) { -+ D("setting connection_state to CS_RECOVERY\n"); -+ t->connection_state = CS_RECOVERY; -+ update_transports(); -+ return; -+ } -+ -+ if(!strcmp(type, "sideload")) { -+ D("setting connection_state to CS_SIDELOAD\n"); -+ t->connection_state = CS_SIDELOAD; -+ update_transports(); -+ return; -+ } -+ -+ t->connection_state = CS_HOST; -+} -+ -+void handle_packet(apacket *p, atransport *t) -+{ -+ asocket *s; -+ -+ D("handle_packet() %c%c%c%c\n", ((char*) (&(p->msg.command)))[0], -+ ((char*) (&(p->msg.command)))[1], -+ ((char*) (&(p->msg.command)))[2], -+ ((char*) (&(p->msg.command)))[3]); -+ print_packet("recv", p); -+ -+ switch(p->msg.command){ -+ case A_SYNC: -+ if(p->msg.arg0){ -+ send_packet(p, t); -+ if(HOST) send_connect(t); -+ } else { -+ t->connection_state = CS_OFFLINE; -+ handle_offline(t); -+ send_packet(p, t); -+ } -+ return; -+ -+ case A_CNXN: /* CONNECT(version, maxdata, "system-id-string") */ -+ /* XXX verify version, etc */ -+ if(t->connection_state != CS_OFFLINE) { -+ t->connection_state = CS_OFFLINE; -+ handle_offline(t); -+ } -+ -+ parse_banner((char*) p->data, t); -+ -+ if (HOST || !auth_enabled) { -+ handle_online(t); -+ if(!HOST) send_connect(t); -+ } else { -+ send_auth_request(t); -+ } -+ break; -+ -+ case A_AUTH: -+ if (p->msg.arg0 == ADB_AUTH_TOKEN) { -+ t->key = adb_auth_nextkey(t->key); -+ if (t->key) { -+ send_auth_response(p->data, p->msg.data_length, t); -+ } else { -+ /* No more private keys to try, send the public key */ -+ send_auth_publickey(t); -+ } -+ } else if (p->msg.arg0 == ADB_AUTH_SIGNATURE) { -+ if (adb_auth_verify(t->token, p->data, p->msg.data_length)) { -+ adb_auth_verified(t); -+ t->failed_auth_attempts = 0; -+ } else { -+ if (t->failed_auth_attempts++ > 10) -+ adb_sleep_ms(1000); -+ send_auth_request(t); -+ } -+ } else if (p->msg.arg0 == ADB_AUTH_RSAPUBLICKEY) { -+ adb_auth_confirm_key(p->data, p->msg.data_length, t); -+ } -+ break; -+ -+ case A_OPEN: /* OPEN(local-id, 0, "destination") */ -+ if (t->online) { -+ 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->online) { -+ 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->online) { -+ if((s = find_local_socket(p->msg.arg1))) { -+ s->close(s); -+ } -+ } -+ break; -+ -+ case A_WRTE: -+ if (t->online) { -+ 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); -+ -+ if (gListenAll > 0) { -+ ret = socket_inaddr_any_server(port, SOCK_STREAM); -+ } else { -+ 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; -+} -+ -+// Write a single line describing a listener to a user-provided buffer. -+// Appends a trailing zero, even in case of truncation, but the function -+// returns the full line length. -+// If |buffer| is NULL, does not write but returns required size. -+static int format_listener(alistener* l, char* buffer, size_t buffer_len) { -+ // Format is simply: -+ // -+ // " " " " "\n" -+ // -+ int local_len = strlen(l->local_name); -+ int connect_len = strlen(l->connect_to); -+ int serial_len = strlen(l->transport->serial); -+ -+ if (buffer != NULL) { -+ snprintf(buffer, buffer_len, "%s %s %s\n", -+ l->transport->serial, l->local_name, l->connect_to); -+ } -+ // NOTE: snprintf() on Windows returns -1 in case of truncation, so -+ // return the computed line length instead. -+ return local_len + connect_len + serial_len + 3; -+} -+ -+// Write the list of current listeners (network redirections) into a -+// user-provided buffer. Appends a trailing zero, even in case of -+// trunctaion, but return the full size in bytes. -+// If |buffer| is NULL, does not write but returns required size. -+static int format_listeners(char* buf, size_t buflen) -+{ -+ alistener* l; -+ int result = 0; -+ for (l = listener_list.next; l != &listener_list; l = l->next) { -+ // Ignore special listeners like those for *smartsocket* -+ if (l->connect_to[0] == '*') -+ continue; -+ int len = format_listener(l, buf, buflen); -+ // Ensure there is space for the trailing zero. -+ result += len; -+ if (buf != NULL) { -+ buf += len; -+ buflen -= len; -+ if (buflen <= 0) -+ break; -+ } -+ } -+ return result; -+} -+ -+static int remove_listener(const char *local_name, atransport* transport) -+{ -+ alistener *l; -+ -+ for (l = listener_list.next; l != &listener_list; l = l->next) { -+ if (!strcmp(local_name, l->local_name)) { -+ listener_disconnect(l, l->transport); -+ return 0; -+ } -+ } -+ return -1; -+} -+ -+static void remove_all_listeners(void) -+{ -+ alistener *l, *l_next; -+ for (l = listener_list.next; l != &listener_list; l = l_next) { -+ l_next = l->next; -+ // Never remove smart sockets. -+ if (l->connect_to[0] == '*') -+ continue; -+ listener_disconnect(l, l->transport); -+ } -+} -+ -+// error/status codes for install_listener. -+typedef enum { -+ INSTALL_STATUS_OK = 0, -+ INSTALL_STATUS_INTERNAL_ERROR = -1, -+ INSTALL_STATUS_CANNOT_BIND = -2, -+ INSTALL_STATUS_CANNOT_REBIND = -3, -+} install_status_t; -+ -+static install_status_t install_listener(const char *local_name, -+ const char *connect_to, -+ atransport* transport, -+ int no_rebind) -+{ -+ 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 INSTALL_STATUS_INTERNAL_ERROR; -+ } -+ -+ /* can't repurpose a listener if 'no_rebind' is true */ -+ if (no_rebind) { -+ return INSTALL_STATUS_CANNOT_REBIND; -+ } -+ -+ cto = strdup(connect_to); -+ if(cto == 0) { -+ return INSTALL_STATUS_INTERNAL_ERROR; -+ } -+ -+ //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 INSTALL_STATUS_OK; -+ } -+ } -+ -+ 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 INSTALL_STATUS_OK; -+ -+nomem: -+ fatal("cannot allocate listener"); -+ return INSTALL_STATUS_INTERNAL_ERROR; -+} -+ -+#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); -+ adb_close(fd); -+ -+ 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); -+ adb_close(fd); -+ fprintf(stderr,"--- adb starting (pid %d) ---\n", getpid()); -+#endif -+} -+ -+#if !ADB_HOST -+void start_device_log(void) -+{ -+ int fd; -+ char path[PATH_MAX]; -+ struct tm now; -+ time_t t; -+ char value[PROPERTY_VALUE_MAX]; -+ -+ // read the trace mask from persistent property persist.adb.trace_mask -+ // give up if the property is not set or cannot be parsed -+ //property_get("persist.adb.trace_mask", value, ""); -+ //if (sscanf(value, "%x", &adb_trace_mask) != 1) -+ return; -+ -+ adb_mkdir("/data/adb", 0775); -+ tzset(); -+ time(&t); -+ localtime_r(&t, &now); -+ strftime(path, sizeof(path), -+ "/data/adb/adb-%Y-%m-%d-%H-%M-%S.txt", -+ &now); -+ fd = unix_open(path, O_WRONLY | O_CREAT | O_TRUNC, 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()); -+ adb_close(fd); -+ -+ fd = unix_open("/dev/null", O_RDONLY); -+ dup2(fd, 0); -+ adb_close(fd); -+} -+#endif -+ -+#if ADB_HOST -+int launch_server(int server_port) -+{ -+#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; -+ HANDLE stdout_handle, stderr_handle; -+ 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 ); -+ -+ /* Some programs want to launch an adb command and collect its output by -+ * calling CreateProcess with inheritable stdout/stderr handles, then -+ * using read() to get its output. When this happens, the stdout/stderr -+ * handles passed to the adb client process will also be inheritable. -+ * When starting the adb server here, care must be taken to reset them -+ * to non-inheritable. -+ * Otherwise, something bad happens: even if the adb command completes, -+ * the calling process is stuck while read()-ing from the stdout/stderr -+ * descriptors, because they're connected to corresponding handles in the -+ * adb server process (even if the latter never uses/writes to them). -+ */ -+ stdout_handle = GetStdHandle( STD_OUTPUT_HANDLE ); -+ stderr_handle = GetStdHandle( STD_ERROR_HANDLE ); -+ if (stdout_handle != INVALID_HANDLE_VALUE) { -+ SetHandleInformation( stdout_handle, HANDLE_FLAG_INHERIT, 0 ); -+ } -+ if (stderr_handle != INVALID_HANDLE_VALUE) { -+ SetHandleInformation( stderr_handle, 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, PATH_MAX); -+ 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]); -+ -+ char str_port[30]; -+ snprintf(str_port, sizeof(str_port), "%d", server_port); -+ // child process -+ int result = execl(path, "adb", "-P", str_port, "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); -+ int saved_errno = errno; -+ adb_close(fd[0]); -+ if (ret < 0) { -+ fprintf(stderr, "could not read ok from ADB Server, errno = %d\n", saved_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 -+ -+/* Constructs a local name of form tcp:port. -+ * target_str points to the target string, it's content will be overwritten. -+ * target_size is the capacity of the target string. -+ * server_port is the port number to use for the local name. -+ */ -+void build_local_name(char* target_str, size_t target_size, int server_port) -+{ -+ snprintf(target_str, target_size, "tcp:%d", server_port); -+} -+ -+#if !ADB_HOST -+static int should_drop_privileges() { -+#ifndef ALLOW_ADBD_ROOT -+ return 1; -+#else /* ALLOW_ADBD_ROOT */ -+ int secure = 0; -+ char value[PROPERTY_VALUE_MAX]; -+ -+ return 0; -+ /* 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, "1"); -+ if (strcmp(value, "1") == 0) { -+ // don't run as root if ro.secure is set... -+ secure = 1; -+ -+ // ... except we allow running as root in userdebug builds if the -+ // service.adb.root property has been set by the "adb root" command -+// property_get("ro.debuggable", value, ""); -+ if (strcmp(value, "1") == 0) { -+// property_get("service.adb.root", value, ""); -+ if (strcmp(value, "1") == 0) { -+ secure = 0; -+ } -+ } -+ } -+ } -+ return secure; -+#endif /* ALLOW_ADBD_ROOT */ -+} -+#endif /* !ADB_HOST */ -+ -+int adb_main(int is_daemon, int server_port) -+{ -+#if !ADB_HOST -+ int port; -+ char value[PROPERTY_VALUE_MAX]; -+ -+ umask(000); -+#endif -+ -+ atexit(adb_cleanup); -+#ifdef HAVE_WIN32_PROC -+ SetConsoleCtrlHandler( ctrlc_handler, TRUE ); -+#elif defined(HAVE_FORKEXEC) -+ // No SIGCHLD. Let the service subproc handle its children. -+ signal(SIGPIPE, SIG_IGN); -+#endif -+ -+ init_transport_registration(); -+ -+#if ADB_HOST -+ HOST = 1; -+ usb_vendors_init(); -+ usb_init(); -+ local_init(DEFAULT_ADB_LOCAL_TRANSPORT_PORT); -+ adb_auth_init(); -+ -+ char local_name[30]; -+ build_local_name(local_name, sizeof(local_name), server_port); -+ if(install_listener(local_name, "*smartsocket*", NULL, 0)) { -+ exit(1); -+ } -+#else -+ //property_get("ro.adb.secure", value, "0"); -+ auth_enabled = 0;//!strcmp(value, "1"); -+ if (auth_enabled) -+ adb_auth_init(); -+ -+ // Our external storage path may be different than apps, since -+ // we aren't able to bind mount after dropping root. -+ const char* adb_external_storage = getenv("ADB_EXTERNAL_STORAGE"); -+ if (NULL != adb_external_storage) { -+ setenv("EXTERNAL_STORAGE", adb_external_storage, 1); -+ } else { -+ D("Warning: ADB_EXTERNAL_STORAGE is not set. Leaving EXTERNAL_STORAGE" -+ " unchanged.\n"); -+ } -+ -+ /* don't listen on a port (default 5037) if running in secure mode */ -+ /* don't run as root if we are running in secure mode */ -+ if (should_drop_privileges()) { -+ struct __user_cap_header_struct header; -+ struct __user_cap_data_struct cap[2]; -+ -+ if (prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0) != 0) { -+ exit(1); -+ } -+ -+ /* 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 -+ ** AID_NET_BT and AID_NET_BT_ADMIN to diagnose bluetooth (hcidump) -+ ** AID_SDCARD_R to allow reading from the SD card -+ ** AID_SDCARD_RW to allow writing to the SD card -+ ** AID_MOUNT to allow unmounting the SD card before rebooting -+ ** AID_NET_BW_STATS to read out qtaguid statistics -+ */ -+ gid_t groups[] = { AID_ADB, AID_LOG, AID_INPUT, AID_INET, AID_GRAPHICS, -+ AID_NET_BT, AID_NET_BT_ADMIN, AID_SDCARD_R, AID_SDCARD_RW, -+ AID_MOUNT, AID_NET_BW_STATS }; -+ if (setgroups(sizeof(groups)/sizeof(groups[0]), groups) != 0) { -+ exit(1); -+ } -+ -+ /* then switch user and group to "shell" */ -+ if (setgid(AID_SHELL) != 0) { -+ exit(1); -+ } -+ if (setuid(AID_SHELL) != 0) { -+ exit(1); -+ } -+ -+ memset(&header, 0, sizeof(header)); -+ memset(cap, 0, sizeof(cap)); -+ -+ /* set CAP_SYS_BOOT capability, so "adb reboot" will succeed */ -+ header.version = _LINUX_CAPABILITY_VERSION_3; -+ header.pid = 0; -+ cap[CAP_TO_INDEX(CAP_SYS_BOOT)].effective |= CAP_TO_MASK(CAP_SYS_BOOT); -+ cap[CAP_TO_INDEX(CAP_SYS_BOOT)].permitted |= CAP_TO_MASK(CAP_SYS_BOOT); -+ capset(&header, cap); -+ -+ D("Local port disabled\n"); -+ } else { -+ char local_name[30]; -+ build_local_name(local_name, sizeof(local_name), server_port); -+ if(install_listener(local_name, "*smartsocket*", NULL, 0)) { -+ exit(1); -+ } -+ } -+ -+ int usb = 0; -+ if (access(USB_ADB_PATH, F_OK) == 0 || access(USB_FFS_ADB_EP0, F_OK) == 0) { -+ // listen on USB -+ usb_init(); -+ usb = 1; -+ } -+ -+ // If one of these properties is set, also listen on that port -+ // If one of the properties isn't set and we couldn't listen on usb, -+ // listen on the default port. -+ //property_get("service.adb.tcp.port", value, ""); -+ //if (!value[0]) { -+ //property_get("persist.adb.tcp.port", value, ""); -+ //} -+ //if (sscanf(value, "%d", &port) == 1 && port > 0) { -+ // printf("using port=%d\n", port); -+ // listen on TCP port specified by service.adb.tcp.port property -+ // local_init(port); -+ //} else -+ if (!usb) { -+ printf("Using USB\n"); -+ // listen on default port -+ local_init(DEFAULT_ADB_LOCAL_TRANSPORT_PORT); -+ } -+ -+ D("adb_main(): pre init_jdwp()\n"); -+ init_jdwp(); -+ D("adb_main(): post init_jdwp()\n"); -+#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(); -+ } -+ D("Event loop starting\n"); -+ -+ fdevent_loop(); -+ -+ usb_cleanup(); -+ -+ return 0; -+} -+ -+#if ADB_HOST -+void connect_device(char* host, char* buffer, int buffer_size) -+{ -+ int port, fd; -+ char* portstr = strchr(host, ':'); -+ char hostbuf[100]; -+ char serial[100]; -+ -+ strncpy(hostbuf, host, sizeof(hostbuf) - 1); -+ if (portstr) { -+ if (portstr - host >= (ptrdiff_t)sizeof(hostbuf)) { -+ snprintf(buffer, buffer_size, "bad host name %s", host); -+ return; -+ } -+ // zero terminate the host at the point we found the colon -+ hostbuf[portstr - host] = 0; -+ if (sscanf(portstr + 1, "%d", &port) == 0) { -+ snprintf(buffer, buffer_size, "bad port number %s", portstr); -+ return; -+ } -+ } else { -+ port = DEFAULT_ADB_LOCAL_TRANSPORT_PORT; -+ } -+ -+ snprintf(serial, sizeof(serial), "%s:%d", hostbuf, port); -+ if (find_transport(serial)) { -+ snprintf(buffer, buffer_size, "already connected to %s", serial); -+ return; -+ } -+ -+ fd = socket_network_client(hostbuf, port, SOCK_STREAM); -+ if (fd < 0) { -+ snprintf(buffer, buffer_size, "unable to connect to %s:%d", host, port); -+ return; -+ } -+ -+ D("client: connected on remote on fd %d\n", fd); -+ close_on_exec(fd); -+ disable_tcp_nagle(fd); -+ register_socket_transport(fd, serial, port, 0); -+ snprintf(buffer, buffer_size, "connected to %s", serial); -+} -+ -+void connect_emulator(char* port_spec, char* buffer, int buffer_size) -+{ -+ char* port_separator = strchr(port_spec, ','); -+ if (!port_separator) { -+ snprintf(buffer, buffer_size, -+ "unable to parse '%s' as ,", -+ port_spec); -+ return; -+ } -+ -+ // Zero-terminate console port and make port_separator point to 2nd port. -+ *port_separator++ = 0; -+ int console_port = strtol(port_spec, NULL, 0); -+ int adb_port = strtol(port_separator, NULL, 0); -+ if (!(console_port > 0 && adb_port > 0)) { -+ *(port_separator - 1) = ','; -+ snprintf(buffer, buffer_size, -+ "Invalid port numbers: Expected positive numbers, got '%s'", -+ port_spec); -+ return; -+ } -+ -+ /* Check if the emulator is already known. -+ * Note: There's a small but harmless race condition here: An emulator not -+ * present just yet could be registered by another invocation right -+ * after doing this check here. However, local_connect protects -+ * against double-registration too. From here, a better error message -+ * can be produced. In the case of the race condition, the very specific -+ * error message won't be shown, but the data doesn't get corrupted. */ -+ atransport* known_emulator = find_emulator_transport_by_adb_port(adb_port); -+ if (known_emulator != NULL) { -+ snprintf(buffer, buffer_size, -+ "Emulator on port %d already registered.", adb_port); -+ return; -+ } -+ -+ /* Check if more emulators can be registered. Similar unproblematic -+ * race condition as above. */ -+ int candidate_slot = get_available_local_transport_index(); -+ if (candidate_slot < 0) { -+ snprintf(buffer, buffer_size, "Cannot accept more emulators."); -+ return; -+ } -+ -+ /* Preconditions met, try to connect to the emulator. */ -+ if (!local_connect_arbitrary_ports(console_port, adb_port)) { -+ snprintf(buffer, buffer_size, -+ "Connected to emulator on ports %d,%d", console_port, adb_port); -+ } else { -+ snprintf(buffer, buffer_size, -+ "Could not connect to emulator on ports %d,%d", -+ console_port, adb_port); -+ } -+} -+#endif -+ -+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 = 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 (!strncmp(service, "devices", 7)) { -+ char buffer[4096]; -+ int use_long = !strcmp(service+7, "-l"); -+ if (use_long || service[7] == 0) { -+ memset(buf, 0, sizeof(buf)); -+ memset(buffer, 0, sizeof(buffer)); -+ D("Getting device list \n"); -+ list_transports(buffer, sizeof(buffer), use_long); -+ snprintf(buf, sizeof(buf), "OKAY%04x%s",(unsigned)strlen(buffer),buffer); -+ D("Wrote device list \n"); -+ writex(reply_fd, buf, strlen(buf)); -+ return 0; -+ } -+ } -+ -+ // add a new TCP transport, device or emulator -+ if (!strncmp(service, "connect:", 8)) { -+ char buffer[4096]; -+ char* host = service + 8; -+ if (!strncmp(host, "emu:", 4)) { -+ connect_emulator(host + 4, buffer, sizeof(buffer)); -+ } else { -+ connect_device(host, buffer, sizeof(buffer)); -+ } -+ // Send response for emulator and device -+ snprintf(buf, sizeof(buf), "OKAY%04x%s",(unsigned)strlen(buffer), buffer); -+ writex(reply_fd, buf, strlen(buf)); -+ return 0; -+ } -+ -+ // remove TCP transport -+ if (!strncmp(service, "disconnect:", 11)) { -+ char buffer[4096]; -+ memset(buffer, 0, sizeof(buffer)); -+ char* serial = service + 11; -+ if (serial[0] == 0) { -+ // disconnect from all TCP devices -+ unregister_all_tcp_transports(); -+ } else { -+ char hostbuf[100]; -+ // assume port 5555 if no port is specified -+ if (!strchr(serial, ':')) { -+ snprintf(hostbuf, sizeof(hostbuf) - 1, "%s:5555", serial); -+ serial = hostbuf; -+ } -+ atransport *t = find_transport(serial); -+ -+ if (t) { -+ unregister_transport(t); -+ } else { -+ snprintf(buffer, sizeof(buffer), "No such device %s", serial); -+ } -+ } -+ -+ snprintf(buf, sizeof(buf), "OKAY%04x%s",(unsigned)strlen(buffer), buffer); -+ 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; -+ } -+ if(!strncmp(service,"get-devpath",strlen("get-devpath"))) { -+ char *out = "unknown"; -+ transport = acquire_one_transport(CS_ANY, ttype, serial, NULL); -+ if (transport && transport->devpath) { -+ out = transport->devpath; -+ } -+ 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(!strcmp(service,"list-forward")) { -+ // Create the list of forward redirections. -+ char header[9]; -+ int buffer_size = format_listeners(NULL, 0); -+ // Add one byte for the trailing zero. -+ char* buffer = malloc(buffer_size+1); -+ (void) format_listeners(buffer, buffer_size+1); -+ snprintf(header, sizeof header, "OKAY%04x", buffer_size); -+ writex(reply_fd, header, 8); -+ writex(reply_fd, buffer, buffer_size); -+ free(buffer); -+ return 0; -+ } -+ -+ if (!strcmp(service,"killforward-all")) { -+ remove_all_listeners(); -+ adb_write(reply_fd, "OKAYOKAY", 8); -+ return 0; -+ } -+ -+ if(!strncmp(service,"forward:",8) || -+ !strncmp(service,"killforward:",12)) { -+ char *local, *remote, *err; -+ int r; -+ atransport *transport; -+ -+ int createForward = strncmp(service,"kill",4); -+ int no_rebind = 0; -+ -+ local = strchr(service, ':') + 1; -+ -+ // Handle forward:norebind:... here -+ if (createForward && !strncmp(local, "norebind:", 9)) { -+ no_rebind = 1; -+ local = strchr(local, ':') + 1; -+ } -+ -+ remote = strchr(local,';'); -+ -+ if (createForward) { -+ // Check forward: parameter format: ';' -+ 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; -+ } -+ } else { -+ // Check killforward: parameter format: '' -+ if (local[0] == 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, no_rebind); -+ } else { -+ r = remove_listener(local, transport); -+ } -+ if(r == 0) { -+ /* 1st OKAY is connect, 2nd OKAY is status */ -+ writex(reply_fd, "OKAYOKAY", 8); -+ return 0; -+ } -+ -+ if (createForward) { -+ const char* message; -+ switch (r) { -+ case INSTALL_STATUS_CANNOT_BIND: -+ message = "cannot bind to socket"; -+ break; -+ case INSTALL_STATUS_CANNOT_REBIND: -+ message = "cannot rebind existing socket"; -+ break; -+ default: -+ message = "internal error"; -+ } -+ sendfailmsg(reply_fd, message); -+ } 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) -+{ -+#if ADB_HOST -+ adb_sysdeps_init(); -+ adb_trace_init(); -+ D("Handling commandline()\n"); -+ return adb_commandline(argc - 1, argv + 1); -+#else -+ /* If adbd runs inside the emulator this will enable adb tracing via -+ * adb-debug qemud service in the emulator. */ -+ adb_qemu_trace_init(); -+ if((argc > 1) && (!strcmp(argv[1],"recovery"))) { -+ adb_device_banner = "recovery"; -+ recovery_mode = 1; -+ } -+ -+ start_device_log(); -+ D("Handling main()\n"); -+ return adb_main(0, DEFAULT_ADB_PORT); -+#endif -+} -Index: android-tools-4.2.2+git20130218/core/adbd/adb.h -=================================================================== ---- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ android-tools-4.2.2+git20130218/core/adbd/adb.h 2013-06-18 17:12:17.000000000 -0300 -@@ -0,0 +1,491 @@ -+/* -+ * 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 -+ -+#include "transport.h" /* readx(), writex() */ -+ -+#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_AUTH 0x48545541 -+ -+#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 31 // 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; -+ -+ /* flag: quit adbd when both ends close the -+ ** local service socket -+ */ -+ int exit_on_close; -+ -+ /* 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; -+ -+#define TOKEN_SIZE 20 -+ -+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; -+ int online; -+ 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; -+ char *model; -+ char *device; -+ char *devpath; -+ int adb_port; // Use for emulators (local transport) -+ -+ /* a list of adisconnect callbacks called when the transport is kicked */ -+ int kicked; -+ adisconnect disconnects; -+ -+ void *key; -+ unsigned char token[TOKEN_SIZE]; -+ fdevent auth_fde; -+ unsigned failed_auth_attempts; -+}; -+ -+ -+/* 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, size_t maxLen); -+int launch_server(int server_port); -+int adb_main(int is_daemon, int server_port); -+ -+ -+/* 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, int long_listing); -+void update_transports(void); -+ -+asocket* create_device_tracker(void); -+ -+/* Obtain a transport from the available transports. -+** If state is != CS_ANY, only transports in that state are considered. -+** If serial is non-NULL then only the device with that serial will be chosen. -+** If no suitable transport is found, error is set. -+*/ -+atransport *acquire_one_transport(int state, transport_type ttype, const char* serial, char **error_out); -+void add_transport_disconnect( atransport* t, adisconnect* dis ); -+void remove_transport_disconnect( atransport* t, adisconnect* dis ); -+void run_transport_disconnects( atransport* t ); -+void kick_transport( atransport* t ); -+ -+/* initialize a transport object's func pointers and state */ -+#if ADB_HOST -+int get_available_local_transport_index(); -+#endif -+int init_socket_transport(atransport *t, int s, int port, int local); -+void init_usb_transport(atransport *t, usb_handle *usb, int state); -+ -+/* 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, int local); -+ -+/* these should only be used for the "adb disconnect" command */ -+void unregister_transport(atransport *t); -+void unregister_all_tcp_transports(); -+ -+void register_usb_transport(usb_handle *h, const char *serial, const char *devpath, unsigned writeable); -+ -+/* this should only be used for transports with connection_state == CS_NOPERM */ -+void unregister_usb_transport(usb_handle *usb); -+ -+atransport *find_transport(const char *serial); -+#if ADB_HOST -+atransport* find_emulator_transport_by_adb_port(int adb_port); -+#endif -+ -+int service_to_fd(const char *name); -+#if ADB_HOST -+asocket *host_service_to_socket(const char* name, const char *serial); -+#endif -+ -+#if !ADB_HOST -+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 -+typedef enum { -+ BACKUP, -+ RESTORE -+} BackupOperation; -+int backup_service(BackupOperation operation, char* args); -+void framebuffer_service(int fd, void *cookie); -+void log_service(int fd, void *cookie); -+void remount_service(int fd, void *cookie); -+char * get_log_file_path(const char * log_name); -+#endif -+ -+/* packet allocator */ -+apacket *get_apacket(void); -+void put_apacket(apacket *p); -+ -+int check_header(apacket *p); -+int check_data(apacket *p); -+ -+/* define ADB_TRACE to 1 to enable tracing support, or 0 to disable it */ -+ -+#define ADB_TRACE 1 -+ -+/* IMPORTANT: if you change the following list, don't -+ * forget to update the corresponding 'tags' table in -+ * the adb_trace_init() function implemented in adb.c -+ */ -+typedef enum { -+ TRACE_ADB = 0, /* 0x001 */ -+ TRACE_SOCKETS, -+ TRACE_PACKETS, -+ TRACE_TRANSPORT, -+ TRACE_RWX, /* 0x010 */ -+ TRACE_USB, -+ TRACE_SYNC, -+ TRACE_SYSDEPS, -+ TRACE_JDWP, /* 0x100 */ -+ TRACE_SERVICES, -+ TRACE_AUTH, -+} AdbTrace; -+ -+#if ADB_TRACE -+ -+#if !ADB_HOST -+/* -+ * When running inside the emulator, guest's adbd can connect to 'adb-debug' -+ * qemud service that can display adb trace messages (on condition that emulator -+ * has been started with '-debug adb' option). -+ */ -+ -+/* Delivers a trace message to the emulator via QEMU pipe. */ -+void adb_qemu_trace(const char* fmt, ...); -+/* Macro to use to send ADB trace messages to the emulator. */ -+#define DQ(...) adb_qemu_trace(__VA_ARGS__) -+#else -+#define DQ(...) ((void)0) -+#endif /* !ADB_HOST */ -+ -+ extern int adb_trace_mask; -+ extern unsigned char adb_trace_output_count; -+ void adb_trace_init(void); -+ -+# define ADB_TRACING ((adb_trace_mask & (1 << TRACE_TAG)) != 0) -+ -+ /* you must define TRACE_TAG before using this macro */ -+# define D(...) \ -+ do { \ -+ if (ADB_TRACING) { \ -+ int save_errno = errno; \ -+ adb_mutex_lock(&D_lock); \ -+ fprintf(stderr, "%s::%s():", \ -+ __FILE__, __FUNCTION__); \ -+ errno = save_errno; \ -+ fprintf(stderr, __VA_ARGS__ ); \ -+ fflush(stderr); \ -+ adb_mutex_unlock(&D_lock); \ -+ errno = save_errno; \ -+ } \ -+ } while (0) -+# define DR(...) \ -+ do { \ -+ if (ADB_TRACING) { \ -+ int save_errno = errno; \ -+ adb_mutex_lock(&D_lock); \ -+ errno = save_errno; \ -+ fprintf(stderr, __VA_ARGS__ ); \ -+ fflush(stderr); \ -+ adb_mutex_unlock(&D_lock); \ -+ errno = save_errno; \ -+ } \ -+ } while (0) -+#else -+# define D(...) ((void)0) -+# define DR(...) ((void)0) -+# define ADB_TRACING 0 -+#endif -+ -+ -+#if !DEBUG_PACKETS -+#define print_packet(tag,p) do {} while (0) -+#endif -+ -+#if ADB_HOST_ON_TARGET -+/* adb and adbd are coexisting on the target, so use 5038 for adb -+ * to avoid conflicting with adbd's usage of 5037 -+ */ -+# define DEFAULT_ADB_PORT 5038 -+#else -+# define DEFAULT_ADB_PORT 5037 -+#endif -+ -+#define DEFAULT_ADB_LOCAL_TRANSPORT_PORT 5555 -+ -+#define ADB_CLASS 0xff -+#define ADB_SUBCLASS 0x42 -+#define ADB_PROTOCOL 0x1 -+ -+ -+void local_init(int port); -+int local_connect(int port); -+int local_connect_arbitrary_ports(int console_port, int adb_port); -+ -+/* usb host/client interface */ -+void usb_init(); -+void usb_cleanup(); -+int usb_write(usb_handle *h, const void *data, int len); -+int usb_read(usb_handle *h, void *data, int len); -+int usb_close(usb_handle *h); -+void usb_kick(usb_handle *h); -+ -+/* used for USB device detection */ -+#if ADB_HOST -+int is_adb_interface(int vid, int pid, int usb_class, int usb_subclass, int usb_protocol); -+#endif -+ -+unsigned host_to_le32(unsigned n); -+int adb_commandline(int argc, char **argv); -+ -+int connection_state(atransport *t); -+ -+#define CS_ANY -1 -+#define CS_OFFLINE 0 -+#define CS_BOOTLOADER 1 -+#define CS_DEVICE 2 -+#define CS_HOST 3 -+#define CS_RECOVERY 4 -+#define CS_NOPERM 5 /* Insufficient permissions to communicate with the device */ -+#define CS_SIDELOAD 6 -+ -+extern int HOST; -+extern int SHELL_EXIT_NOTIFY_FD; -+ -+#define CHUNK_SIZE (64*1024) -+ -+#if !ADB_HOST -+#define USB_ADB_PATH "/dev/android_adb" -+ -+#define USB_FFS_ADB_PATH "/dev/usb-ffs/adb/" -+#define USB_FFS_ADB_EP(x) USB_FFS_ADB_PATH#x -+ -+#define USB_FFS_ADB_EP0 USB_FFS_ADB_EP(ep0) -+#define USB_FFS_ADB_OUT USB_FFS_ADB_EP(ep1) -+#define USB_FFS_ADB_IN USB_FFS_ADB_EP(ep2) -+#endif -+ -+int sendfailmsg(int fd, const char *reason); -+int handle_host_request(char *service, transport_type ttype, char* serial, int reply_fd, asocket *s); -+ -+#endif -Index: android-tools-4.2.2+git20130218/core/adbd/adb_auth.h -=================================================================== ---- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ android-tools-4.2.2+git20130218/core/adbd/adb_auth.h 2013-06-18 17:12:17.000000000 -0300 -@@ -0,0 +1,54 @@ -+/* -+ * Copyright (C) 2012 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_AUTH_H -+#define __ADB_AUTH_H -+ -+void adb_auth_init(void); -+void adb_auth_verified(atransport *t); -+ -+/* AUTH packets first argument */ -+/* Request */ -+#define ADB_AUTH_TOKEN 1 -+/* Response */ -+#define ADB_AUTH_SIGNATURE 2 -+#define ADB_AUTH_RSAPUBLICKEY 3 -+ -+#if ADB_HOST -+ -+int adb_auth_sign(void *key, void *token, size_t token_size, void *sig); -+void *adb_auth_nextkey(void *current); -+int adb_auth_get_userkey(unsigned char *data, size_t len); -+ -+static inline int adb_auth_generate_token(void *token, size_t token_size) { return 0; } -+static inline int adb_auth_verify(void *token, void *sig, int siglen) { return 0; } -+static inline void adb_auth_confirm_key(unsigned char *data, size_t len, atransport *t) { } -+static inline void adb_auth_reload_keys(void) { } -+ -+#else // !ADB_HOST -+ -+static inline int adb_auth_sign(void* key, void *token, size_t token_size, void *sig) { return 0; } -+static inline void *adb_auth_nextkey(void *current) { return NULL; } -+static inline int adb_auth_get_userkey(unsigned char *data, size_t len) { return 0; } -+ -+int adb_auth_generate_token(void *token, size_t token_size); -+int adb_auth_verify(void *token, void *sig, int siglen); -+void adb_auth_confirm_key(unsigned char *data, size_t len, atransport *t); -+void adb_auth_reload_keys(void); -+ -+#endif // ADB_HOST -+ -+#endif // __ADB_AUTH_H -Index: android-tools-4.2.2+git20130218/core/adbd/adb_auth_client.c -=================================================================== ---- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ android-tools-4.2.2+git20130218/core/adbd/adb_auth_client.c 2013-06-18 17:12:17.000000000 -0300 -@@ -0,0 +1,245 @@ -+/* -+ * Copyright (C) 2012 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 -+#include -+#include -+#include -+#include -+ -+#include "sysdeps.h" -+#include "adb.h" -+#include "adb_auth.h" -+#include "fdevent.h" -+#include "mincrypt/rsa.h" -+ -+#define TRACE_TAG TRACE_AUTH -+ -+ -+struct adb_public_key { -+ struct listnode node; -+ RSAPublicKey key; -+}; -+ -+static struct listnode key_list; -+ -+static char *key_paths[] = { -+ "/adb_keys", -+ "/data/misc/adb/adb_keys", -+ NULL -+}; -+ -+static fdevent listener_fde; -+static int framework_fd = -1; -+ -+ -+static void read_keys(const char *file, struct listnode *list) -+{ -+ struct adb_public_key *key; -+ FILE *f; -+ char buf[MAX_PAYLOAD]; -+ char *sep; -+ int ret; -+ -+ f = fopen(file, "r"); -+ if (!f) { -+ D("Can't open '%s'\n", file); -+ return; -+ } -+ -+ while (fgets(buf, sizeof(buf), f)) { -+ /* Allocate 4 extra bytes to decode the base64 data in-place */ -+ key = calloc(1, sizeof(*key) + 4); -+ if (!key) { -+ D("Can't malloc key\n"); -+ break; -+ } -+ -+ sep = strpbrk(buf, " \t"); -+ if (sep) -+ *sep = '\0'; -+ -+ ret = __b64_pton(buf, (u_char *)&key->key, sizeof(key->key) + 4); -+ if (ret != sizeof(key->key)) { -+ D("%s: Invalid base64 data ret=%d\n", file, ret); -+ free(key); -+ continue; -+ } -+ -+ if (key->key.len != RSANUMWORDS) { -+ D("%s: Invalid key len %d\n", file, key->key.len); -+ free(key); -+ continue; -+ } -+ -+ list_add_tail(list, &key->node); -+ } -+ -+ fclose(f); -+} -+ -+static void free_keys(struct listnode *list) -+{ -+ struct listnode *item; -+ -+ while (!list_empty(list)) { -+ item = list_head(list); -+ list_remove(item); -+ free(node_to_item(item, struct adb_public_key, node)); -+ } -+} -+ -+void adb_auth_reload_keys(void) -+{ -+ char *path; -+ char **paths = key_paths; -+ struct stat buf; -+ -+ free_keys(&key_list); -+ -+ while ((path = *paths++)) { -+ if (!stat(path, &buf)) { -+ D("Loading keys from '%s'\n", path); -+ read_keys(path, &key_list); -+ } -+ } -+} -+ -+int adb_auth_generate_token(void *token, size_t token_size) -+{ -+ FILE *f; -+ int ret; -+ -+ f = fopen("/dev/urandom", "r"); -+ if (!f) -+ return 0; -+ -+ ret = fread(token, token_size, 1, f); -+ -+ fclose(f); -+ return ret * token_size; -+} -+ -+int adb_auth_verify(void *token, void *sig, int siglen) -+{ -+ struct listnode *item; -+ struct adb_public_key *key; -+ int ret; -+ -+ if (siglen != RSANUMBYTES) -+ return 0; -+ -+ list_for_each(item, &key_list) { -+ key = node_to_item(item, struct adb_public_key, node); -+ ret = RSA_verify(&key->key, sig, siglen, token); -+ if (ret) -+ return 1; -+ } -+ -+ return 0; -+} -+ -+static void adb_auth_event(int fd, unsigned events, void *data) -+{ -+ atransport *t = data; -+ char response[2]; -+ int ret; -+ -+ if (events & FDE_READ) { -+ ret = unix_read(fd, response, sizeof(response)); -+ if (ret < 0) { -+ D("Disconnect"); -+ fdevent_remove(&t->auth_fde); -+ framework_fd = -1; -+ } -+ else if (ret == 2 && response[0] == 'O' && response[1] == 'K') { -+ adb_auth_reload_keys(); -+ adb_auth_verified(t); -+ } -+ } -+} -+ -+void adb_auth_confirm_key(unsigned char *key, size_t len, atransport *t) -+{ -+ char msg[MAX_PAYLOAD]; -+ int ret; -+ -+ if (framework_fd < 0) { -+ D("Client not connected\n"); -+ return; -+ } -+ -+ if (key[len - 1] != '\0') { -+ D("Key must be a null-terminated string\n"); -+ return; -+ } -+ -+ ret = snprintf(msg, sizeof(msg), "PK%s", key); -+ if (ret >= (signed)sizeof(msg)) { -+ D("Key too long. ret=%d", ret); -+ return; -+ } -+ D("Sending '%s'\n", msg); -+ -+ ret = unix_write(framework_fd, msg, ret); -+ if (ret < 0) { -+ D("Failed to write PK, errno=%d\n", errno); -+ return; -+ } -+ -+ fdevent_install(&t->auth_fde, framework_fd, adb_auth_event, t); -+ fdevent_add(&t->auth_fde, FDE_READ); -+} -+ -+static void adb_auth_listener(int fd, unsigned events, void *data) -+{ -+ struct sockaddr addr; -+ socklen_t alen; -+ int s; -+ -+ alen = sizeof(addr); -+ -+ s = adb_socket_accept(fd, &addr, &alen); -+ if (s < 0) { -+ D("Failed to accept: errno=%d\n", errno); -+ return; -+ } -+ -+ framework_fd = s; -+} -+ -+void adb_auth_init(void) -+{ -+ int fd, ret; -+ -+ list_init(&key_list); -+ adb_auth_reload_keys(); -+ -+ fd = android_get_control_socket("adbd"); -+ if (fd < 0) { -+ D("Failed to get adbd socket\n"); -+ return; -+ } -+ -+ ret = listen(fd, 4); -+ if (ret < 0) { -+ D("Failed to listen on '%d'\n", fd); -+ return; -+ } -+ -+ fdevent_install(&listener_fde, fd, adb_auth_listener, NULL); -+ fdevent_add(&listener_fde, FDE_READ); -+} -Index: android-tools-4.2.2+git20130218/core/adbd/adb_auth_host.c -=================================================================== ---- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ android-tools-4.2.2+git20130218/core/adbd/adb_auth_host.c 2013-06-18 17:12:17.000000000 -0300 -@@ -0,0 +1,426 @@ -+/* -+ * Copyright (C) 2012 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 -+ -+#ifdef _WIN32 -+# define WIN32_LEAN_AND_MEAN -+# include "windows.h" -+# include "shlobj.h" -+#else -+# include -+# include -+# include -+#endif -+#include -+ -+#include "sysdeps.h" -+#include "adb.h" -+#include "adb_auth.h" -+ -+/* HACK: we need the RSAPublicKey struct -+ * but RSA_verify conflits with openssl */ -+#define RSA_verify RSA_verify_mincrypt -+#include "mincrypt/rsa.h" -+#undef RSA_verify -+ -+#include -+ -+#include -+#include -+#include -+#include -+#include -+ -+#define TRACE_TAG TRACE_AUTH -+ -+#define ANDROID_PATH ".android" -+#define ADB_KEY_FILE "adbkey" -+ -+ -+struct adb_private_key { -+ struct listnode node; -+ RSA *rsa; -+}; -+ -+static struct listnode key_list; -+ -+ -+/* Convert OpenSSL RSA private key to android pre-computed RSAPublicKey format */ -+static int RSA_to_RSAPublicKey(RSA *rsa, RSAPublicKey *pkey) -+{ -+ int ret = 1; -+ unsigned int i; -+ -+ BN_CTX* ctx = BN_CTX_new(); -+ BIGNUM* r32 = BN_new(); -+ BIGNUM* rr = BN_new(); -+ BIGNUM* r = BN_new(); -+ BIGNUM* rem = BN_new(); -+ BIGNUM* n = BN_new(); -+ BIGNUM* n0inv = BN_new(); -+ -+ if (RSA_size(rsa) != RSANUMBYTES) { -+ ret = 0; -+ goto out; -+ } -+ -+ BN_set_bit(r32, 32); -+ BN_copy(n, rsa->n); -+ BN_set_bit(r, RSANUMWORDS * 32); -+ BN_mod_sqr(rr, r, n, ctx); -+ BN_div(NULL, rem, n, r32, ctx); -+ BN_mod_inverse(n0inv, rem, r32, ctx); -+ -+ pkey->len = RSANUMWORDS; -+ pkey->n0inv = 0 - BN_get_word(n0inv); -+ for (i = 0; i < RSANUMWORDS; i++) { -+ BN_div(rr, rem, rr, r32, ctx); -+ pkey->rr[i] = BN_get_word(rem); -+ BN_div(n, rem, n, r32, ctx); -+ pkey->n[i] = BN_get_word(rem); -+ } -+ pkey->exponent = BN_get_word(rsa->e); -+ -+out: -+ BN_free(n0inv); -+ BN_free(n); -+ BN_free(rem); -+ BN_free(r); -+ BN_free(rr); -+ BN_free(r32); -+ BN_CTX_free(ctx); -+ -+ return ret; -+} -+ -+static void get_user_info(char *buf, size_t len) -+{ -+ char hostname[1024], username[1024]; -+ int ret; -+ -+#ifndef _WIN32 -+ ret = gethostname(hostname, sizeof(hostname)); -+ if (ret < 0) -+#endif -+ strcpy(hostname, "unknown"); -+ -+#if !defined _WIN32 && !defined ADB_HOST_ON_TARGET -+ ret = getlogin_r(username, sizeof(username)); -+ if (ret < 0) -+#endif -+ strcpy(username, "unknown"); -+ -+ ret = snprintf(buf, len, " %s@%s", username, hostname); -+ if (ret >= (signed)len) -+ buf[len - 1] = '\0'; -+} -+ -+static int write_public_keyfile(RSA *private_key, const char *private_key_path) -+{ -+ RSAPublicKey pkey; -+ BIO *bio, *b64, *bfile; -+ char path[PATH_MAX], info[MAX_PAYLOAD]; -+ int ret; -+ -+ ret = snprintf(path, sizeof(path), "%s.pub", private_key_path); -+ if (ret >= (signed)sizeof(path)) -+ return 0; -+ -+ ret = RSA_to_RSAPublicKey(private_key, &pkey); -+ if (!ret) { -+ D("Failed to convert to publickey\n"); -+ return 0; -+ } -+ -+ bfile = BIO_new_file(path, "w"); -+ if (!bfile) { -+ D("Failed to open '%s'\n", path); -+ return 0; -+ } -+ -+ D("Writing public key to '%s'\n", path); -+ -+ b64 = BIO_new(BIO_f_base64()); -+ BIO_set_flags(b64, BIO_FLAGS_BASE64_NO_NL); -+ -+ bio = BIO_push(b64, bfile); -+ BIO_write(bio, &pkey, sizeof(pkey)); -+ BIO_flush(bio); -+ BIO_pop(b64); -+ BIO_free(b64); -+ -+ get_user_info(info, sizeof(info)); -+ BIO_write(bfile, info, strlen(info)); -+ BIO_flush(bfile); -+ BIO_free_all(bfile); -+ -+ return 1; -+} -+ -+static int generate_key(const char *file) -+{ -+ EVP_PKEY* pkey = EVP_PKEY_new(); -+ BIGNUM* exponent = BN_new(); -+ RSA* rsa = RSA_new(); -+ mode_t old_mask; -+ FILE *f = NULL; -+ int ret = 0; -+ -+ D("generate_key '%s'\n", file); -+ -+ if (!pkey || !exponent || !rsa) { -+ D("Failed to allocate key\n"); -+ goto out; -+ } -+ -+ BN_set_word(exponent, RSA_F4); -+ RSA_generate_key_ex(rsa, 2048, exponent, NULL); -+ EVP_PKEY_set1_RSA(pkey, rsa); -+ -+ old_mask = umask(077); -+ -+ f = fopen(file, "w"); -+ if (!f) { -+ D("Failed to open '%s'\n", file); -+ umask(old_mask); -+ goto out; -+ } -+ -+ umask(old_mask); -+ -+ if (!PEM_write_PrivateKey(f, pkey, NULL, NULL, 0, NULL, NULL)) { -+ D("Failed to write key\n"); -+ goto out; -+ } -+ -+ if (!write_public_keyfile(rsa, file)) { -+ D("Failed to write public key\n"); -+ goto out; -+ } -+ -+ ret = 1; -+ -+out: -+ if (f) -+ fclose(f); -+ EVP_PKEY_free(pkey); -+ RSA_free(rsa); -+ BN_free(exponent); -+ return ret; -+} -+ -+static int read_key(const char *file, struct listnode *list) -+{ -+ struct adb_private_key *key; -+ FILE *f; -+ -+ D("read_key '%s'\n", file); -+ -+ f = fopen(file, "r"); -+ if (!f) { -+ D("Failed to open '%s'\n", file); -+ return 0; -+ } -+ -+ key = malloc(sizeof(*key)); -+ if (!key) { -+ D("Failed to alloc key\n"); -+ fclose(f); -+ return 0; -+ } -+ key->rsa = RSA_new(); -+ -+ if (!PEM_read_RSAPrivateKey(f, &key->rsa, NULL, NULL)) { -+ D("Failed to read key\n"); -+ fclose(f); -+ RSA_free(key->rsa); -+ free(key); -+ return 0; -+ } -+ -+ fclose(f); -+ list_add_tail(list, &key->node); -+ return 1; -+} -+ -+static int get_user_keyfilepath(char *filename, size_t len) -+{ -+ const char *format, *home; -+ char android_dir[PATH_MAX]; -+ struct stat buf; -+#ifdef _WIN32 -+ char path[PATH_MAX]; -+ home = getenv("ANDROID_SDK_HOME"); -+ if (!home) { -+ SHGetFolderPath(NULL, CSIDL_PROFILE, NULL, 0, path); -+ home = path; -+ } -+ format = "%s\\%s"; -+#else -+ home = getenv("HOME"); -+ if (!home) -+ return -1; -+ format = "%s/%s"; -+#endif -+ -+ D("home '%s'\n", home); -+ -+ if (snprintf(android_dir, sizeof(android_dir), format, home, -+ ANDROID_PATH) >= (int)sizeof(android_dir)) -+ return -1; -+ -+ if (stat(android_dir, &buf)) { -+ if (adb_mkdir(android_dir, 0750) < 0) { -+ D("Cannot mkdir '%s'", android_dir); -+ return -1; -+ } -+ } -+ -+ return snprintf(filename, len, format, android_dir, ADB_KEY_FILE); -+} -+ -+static int get_user_key(struct listnode *list) -+{ -+ struct stat buf; -+ char path[PATH_MAX]; -+ int ret; -+ -+ ret = get_user_keyfilepath(path, sizeof(path)); -+ if (ret < 0 || ret >= (signed)sizeof(path)) { -+ D("Error getting user key filename"); -+ return 0; -+ } -+ -+ D("user key '%s'\n", path); -+ -+ if (stat(path, &buf) == -1) { -+ if (!generate_key(path)) { -+ D("Failed to generate new key\n"); -+ return 0; -+ } -+ } -+ -+ return read_key(path, list); -+} -+ -+static void get_vendor_keys(struct listnode *list) -+{ -+ const char *adb_keys_path; -+ char keys_path[MAX_PAYLOAD]; -+ char *path; -+ char *save; -+ struct stat buf; -+ -+ adb_keys_path = getenv("ADB_VENDOR_KEYS"); -+ if (!adb_keys_path) -+ return; -+ strncpy(keys_path, adb_keys_path, sizeof(keys_path)); -+ -+ path = adb_strtok_r(keys_path, ENV_PATH_SEPARATOR_STR, &save); -+ while (path) { -+ D("Reading: '%s'\n", path); -+ -+ if (stat(path, &buf)) -+ D("Can't read '%s'\n", path); -+ else if (!read_key(path, list)) -+ D("Failed to read '%s'\n", path); -+ -+ path = adb_strtok_r(NULL, ENV_PATH_SEPARATOR_STR, &save); -+ } -+} -+ -+int adb_auth_sign(void *node, void *token, size_t token_size, void *sig) -+{ -+ unsigned int len; -+ struct adb_private_key *key = node_to_item(node, struct adb_private_key, node); -+ -+ if (!RSA_sign(NID_sha1, token, token_size, sig, &len, key->rsa)) { -+ return 0; -+ } -+ -+ D("adb_auth_sign len=%d\n", len); -+ return (int)len; -+} -+ -+void *adb_auth_nextkey(void *current) -+{ -+ struct listnode *item; -+ -+ if (list_empty(&key_list)) -+ return NULL; -+ -+ if (!current) -+ return list_head(&key_list); -+ -+ list_for_each(item, &key_list) { -+ if (item == current) { -+ /* current is the last item, we tried all the keys */ -+ if (item->next == &key_list) -+ return NULL; -+ return item->next; -+ } -+ } -+ -+ return NULL; -+} -+ -+int adb_auth_get_userkey(unsigned char *data, size_t len) -+{ -+ char path[PATH_MAX]; -+ char *file; -+ int ret; -+ -+ ret = get_user_keyfilepath(path, sizeof(path) - 4); -+ if (ret < 0 || ret >= (signed)(sizeof(path) - 4)) { -+ D("Error getting user key filename"); -+ return 0; -+ } -+ strcat(path, ".pub"); -+ -+ file = load_file(path, (unsigned*)&ret); -+ if (!file) { -+ D("Can't load '%s'\n", path); -+ return 0; -+ } -+ -+ if (len < (size_t)(ret + 1)) { -+ D("%s: Content too large ret=%d\n", path, ret); -+ return 0; -+ } -+ -+ memcpy(data, file, ret); -+ data[ret] = '\0'; -+ -+ return ret + 1; -+} -+ -+void adb_auth_init(void) -+{ -+ int ret; -+ -+ D("adb_auth_init\n"); -+ -+ list_init(&key_list); -+ -+ ret = get_user_key(&key_list); -+ if (!ret) { -+ D("Failed to get user key\n"); -+ return; -+ } -+ -+ get_vendor_keys(&key_list); -+} -Index: android-tools-4.2.2+git20130218/core/adbd/adb_client.c -=================================================================== ---- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ android-tools-4.2.2+git20130218/core/adbd/adb_client.c 2013-06-18 17:12:17.000000000 -0300 -@@ -0,0 +1,340 @@ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include "sysdeps.h" -+ -+#define TRACE_TAG TRACE_ADB -+#include "adb_client.h" -+ -+static transport_type __adb_transport = kTransportAny; -+static const char* __adb_serial = NULL; -+ -+static int __adb_server_port = DEFAULT_ADB_PORT; -+static const char* __adb_server_name = NULL; -+ -+void adb_set_transport(transport_type type, const char* serial) -+{ -+ __adb_transport = type; -+ __adb_serial = serial; -+} -+ -+void adb_set_tcp_specifics(int server_port) -+{ -+ __adb_server_port = server_port; -+} -+ -+void adb_set_tcp_name(const char* hostname) -+{ -+ __adb_server_name = hostname; -+} -+ -+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); -+ -+ if (__adb_server_name) -+ fd = socket_network_client(__adb_server_name, __adb_server_port, SOCK_STREAM); -+ else -+ fd = socket_loopback_client(__adb_server_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; -+ } -+ -+ D("_adb_connect: return fd %d\n", fd); -+ return fd; -+} -+ -+int adb_connect(const char *service) -+{ -+ // first query the adb server's version -+ int fd = _adb_connect("host:version"); -+ -+ D("adb_connect: service %s\n", service); -+ if(fd == -2 && __adb_server_name) { -+ fprintf(stderr,"** Cannot start server on remote host\n"); -+ return fd; -+ } else if(fd == -2) { -+ fprintf(stdout,"* daemon not running. starting it now on port %d *\n", -+ __adb_server_port); -+ start_server: -+ if(launch_server(__adb_server_port)) { -+ 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(3000); -+ // 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\n"); -+ } -+ D("adb_connect: return fd %d\n", fd); -+ -+ 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; -+} -Index: android-tools-4.2.2+git20130218/core/adbd/adb_client.h -=================================================================== ---- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ android-tools-4.2.2+git20130218/core/adbd/adb_client.h 2013-06-18 17:12:17.000000000 -0300 -@@ -0,0 +1,57 @@ -+#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); -+ -+/* Set TCP specifics of the transport to use -+*/ -+void adb_set_tcp_specifics(int server_port); -+ -+/* Set TCP Hostname of the transport to use -+*/ -+void adb_set_tcp_name(const char* hostname); -+ -+/* 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 -+ * with a 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 -Index: android-tools-4.2.2+git20130218/core/adbd/android_filesystem_config.h -=================================================================== ---- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ android-tools-4.2.2+git20130218/core/adbd/android_filesystem_config.h 2013-06-18 17:12:17.000000000 -0300 -@@ -0,0 +1,302 @@ -+/* -+ * 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 is used to define the properties of the filesystem -+** images generated by build tools (mkbootfs and mkyaffs2image) and -+** by the device side of adb. -+*/ -+ -+#ifndef _ANDROID_FILESYSTEM_CONFIG_H_ -+#define _ANDROID_FILESYSTEM_CONFIG_H_ -+ -+#include -+#include -+#include -+ -+/* This is the master Users and Groups config for the platform. -+** DO NOT EVER RENUMBER. -+*/ -+ -+#define AID_ROOT 0 /* traditional unix root user */ -+ -+#define AID_SYSTEM 1000 /* system server */ -+ -+#define AID_RADIO 1001 /* telephony subsystem, RIL */ -+#define AID_BLUETOOTH 1002 /* bluetooth subsystem */ -+#define AID_GRAPHICS 1003 /* graphics devices */ -+#define AID_INPUT 1004 /* input devices */ -+#define AID_AUDIO 1005 /* audio devices */ -+#define AID_CAMERA 1006 /* camera devices */ -+#define AID_LOG 1007 /* log devices */ -+#define AID_COMPASS 1008 /* compass device */ -+#define AID_MOUNT 1009 /* mountd socket */ -+#define AID_WIFI 1010 /* wifi subsystem */ -+#define AID_ADB 1011 /* android debug bridge (adbd) */ -+#define AID_INSTALL 1012 /* group for installing packages */ -+#define AID_MEDIA 1013 /* mediaserver process */ -+#define AID_DHCP 1014 /* dhcp client */ -+#define AID_SDCARD_RW 1015 /* external storage write access */ -+#define AID_VPN 1016 /* vpn system */ -+#define AID_KEYSTORE 1017 /* keystore subsystem */ -+#define AID_USB 1018 /* USB devices */ -+#define AID_DRM 1019 /* DRM server */ -+#define AID_MDNSR 1020 /* MulticastDNSResponder (service discovery) */ -+#define AID_GPS 1021 /* GPS daemon */ -+#define AID_UNUSED1 1022 /* deprecated, DO NOT USE */ -+#define AID_MEDIA_RW 1023 /* internal media storage write access */ -+#define AID_MTP 1024 /* MTP USB driver access */ -+#define AID_UNUSED2 1025 /* deprecated, DO NOT USE */ -+#define AID_DRMRPC 1026 /* group for drm rpc */ -+#define AID_NFC 1027 /* nfc subsystem */ -+#define AID_SDCARD_R 1028 /* external storage read access */ -+ -+#define AID_SHELL 2000 /* adb and debug shell user */ -+#define AID_CACHE 2001 /* cache access */ -+#define AID_DIAG 2002 /* access to diagnostic resources */ -+ -+/* The 3000 series are intended for use as supplemental group id's only. -+ * They indicate special Android capabilities that the kernel is aware of. */ -+#define AID_NET_BT_ADMIN 3001 /* bluetooth: create any socket */ -+#define AID_NET_BT 3002 /* bluetooth: create sco, rfcomm or l2cap sockets */ -+#define AID_INET 3003 /* can create AF_INET and AF_INET6 sockets */ -+#define AID_NET_RAW 3004 /* can create raw INET sockets */ -+#define AID_NET_ADMIN 3005 /* can configure interfaces and routing tables. */ -+#define AID_NET_BW_STATS 3006 /* read bandwidth statistics */ -+#define AID_NET_BW_ACCT 3007 /* change bandwidth statistics accounting */ -+#define AID_NET_BT_STACK 3008 /* bluetooth: access config files */ -+#define AID_QCOM_ONCRPC 3009 /* can read/write /dev/oncrpc files */ -+#define AID_QCOM_DIAG 3010 /* can read/write /dev/diag */ -+ -+#if defined(MOTOROLA_UIDS) -+#define AID_MOT_OSH 5000 /* OSH */ -+#define AID_MOT_ACCY 9000 /* access to accessory */ -+#define AID_MOT_PWRIC 9001 /* power IC */ -+#define AID_MOT_USB 9002 /* mot usb */ -+#define AID_MOT_DRM 9003 /* can access DRM resource. */ -+#define AID_MOT_TCMD 9004 /* mot_tcmd */ -+#define AID_MOT_SEC_RTC 9005 /* mot cpcap rtc */ -+#define AID_MOT_TOMBSTONE 9006 -+#define AID_MOT_TPAPI 9007 /* mot_tpapi */ -+#define AID_MOT_SECCLKD 9008 /* mot_secclkd */ -+#define AID_MOT_WHISPER 9009 /* Whisper Protocol access */ -+#define AID_MOT_CAIF 9010 /* can create CAIF sockets */ -+#define AID_MOT_DLNA 9011 /* DLNA native */ -+#endif // MOTOROLA_UIDS -+ -+#define AID_MISC 9998 /* access to misc storage */ -+#define AID_NOBODY 9999 -+ -+#define AID_APP 10000 /* first app user */ -+ -+#define AID_ISOLATED_START 99000 /* start of uids for fully isolated sandboxed processes */ -+#define AID_ISOLATED_END 99999 /* end of uids for fully isolated sandboxed processes */ -+ -+#define AID_USER 100000 /* offset for uid ranges for each user */ -+ -+#define AID_SHARED_GID_START 50000 /* start of gids for apps in each user to share */ -+#define AID_SHARED_GID_END 59999 /* start of gids for apps in each user to share */ -+ -+#if !defined(EXCLUDE_FS_CONFIG_STRUCTURES) -+struct android_id_info { -+ const char *name; -+ unsigned aid; -+}; -+ -+static const struct android_id_info android_ids[] = { -+ { "root", AID_ROOT, }, -+ { "system", AID_SYSTEM, }, -+ { "radio", AID_RADIO, }, -+ { "bluetooth", AID_BLUETOOTH, }, -+ { "graphics", AID_GRAPHICS, }, -+ { "input", AID_INPUT, }, -+ { "audio", AID_AUDIO, }, -+ { "camera", AID_CAMERA, }, -+ { "log", AID_LOG, }, -+ { "compass", AID_COMPASS, }, -+ { "mount", AID_MOUNT, }, -+ { "wifi", AID_WIFI, }, -+ { "dhcp", AID_DHCP, }, -+ { "adb", AID_ADB, }, -+ { "install", AID_INSTALL, }, -+ { "media", AID_MEDIA, }, -+ { "drm", AID_DRM, }, -+ { "mdnsr", AID_MDNSR, }, -+ { "nfc", AID_NFC, }, -+ { "drmrpc", AID_DRMRPC, }, -+ { "shell", AID_SHELL, }, -+ { "cache", AID_CACHE, }, -+ { "diag", AID_DIAG, }, -+ { "net_bt_admin", AID_NET_BT_ADMIN, }, -+ { "net_bt", AID_NET_BT, }, -+ { "net_bt_stack", AID_NET_BT_STACK, }, -+ { "sdcard_r", AID_SDCARD_R, }, -+ { "sdcard_rw", AID_SDCARD_RW, }, -+ { "media_rw", AID_MEDIA_RW, }, -+ { "vpn", AID_VPN, }, -+ { "keystore", AID_KEYSTORE, }, -+ { "usb", AID_USB, }, -+ { "mtp", AID_MTP, }, -+ { "gps", AID_GPS, }, -+ { "inet", AID_INET, }, -+ { "net_raw", AID_NET_RAW, }, -+ { "net_admin", AID_NET_ADMIN, }, -+ { "net_bw_stats", AID_NET_BW_STATS, }, -+ { "net_bw_acct", AID_NET_BW_ACCT, }, -+ { "qcom_oncrpc", AID_QCOM_ONCRPC, }, -+ { "qcom_diag", AID_QCOM_DIAG, }, -+#if defined(MOTOROLA_UIDS) -+ { "mot_osh", AID_MOT_OSH, }, -+ { "mot_accy", AID_MOT_ACCY, }, -+ { "mot_pwric", AID_MOT_PWRIC, }, -+ { "mot_usb", AID_MOT_USB, }, -+ { "mot_drm", AID_MOT_DRM, }, -+ { "mot_tcmd", AID_MOT_TCMD, }, -+ { "mot_sec_rtc", AID_MOT_SEC_RTC, }, -+ { "mot_tombstone", AID_MOT_TOMBSTONE, }, -+ { "mot_tpapi", AID_MOT_TPAPI, }, -+ { "mot_secclkd", AID_MOT_SECCLKD, }, -+ { "mot_whisper", AID_MOT_WHISPER, }, -+ { "mot_caif", AID_MOT_CAIF, }, -+ { "mot_dlna", AID_MOT_DLNA, }, -+#endif -+ { "misc", AID_MISC, }, -+ { "nobody", AID_NOBODY, }, -+}; -+ -+#define android_id_count \ -+ (sizeof(android_ids) / sizeof(android_ids[0])) -+ -+struct fs_path_config { -+ unsigned mode; -+ unsigned uid; -+ unsigned gid; -+ const char *prefix; -+}; -+ -+/* Rules for directories. -+** These rules are applied based on "first match", so they -+** should start with the most specific path and work their -+** way up to the root. -+*/ -+ -+static struct fs_path_config android_dirs[] = { -+ { 00770, AID_SYSTEM, AID_CACHE, "cache" }, -+ { 00771, AID_SYSTEM, AID_SYSTEM, "data/app" }, -+ { 00771, AID_SYSTEM, AID_SYSTEM, "data/app-private" }, -+ { 00771, AID_SYSTEM, AID_SYSTEM, "data/dalvik-cache" }, -+ { 00771, AID_SYSTEM, AID_SYSTEM, "data/data" }, -+ { 00771, AID_SHELL, AID_SHELL, "data/local/tmp" }, -+ { 00771, AID_SHELL, AID_SHELL, "data/local" }, -+ { 01771, AID_SYSTEM, AID_MISC, "data/misc" }, -+ { 00770, AID_DHCP, AID_DHCP, "data/misc/dhcp" }, -+ { 00775, AID_MEDIA_RW, AID_MEDIA_RW, "data/media" }, -+ { 00775, AID_MEDIA_RW, AID_MEDIA_RW, "data/media/Music" }, -+ { 00771, AID_SYSTEM, AID_SYSTEM, "data" }, -+ { 00750, AID_ROOT, AID_SHELL, "sbin" }, -+ { 00755, AID_ROOT, AID_ROOT, "system/addon.d" }, -+ { 00755, AID_ROOT, AID_SHELL, "system/bin" }, -+ { 00755, AID_ROOT, AID_SHELL, "system/vendor" }, -+ { 00755, AID_ROOT, AID_SHELL, "system/xbin" }, -+ { 00755, AID_ROOT, AID_ROOT, "system/etc/ppp" }, -+ { 00777, AID_ROOT, AID_ROOT, "sdcard" }, -+ { 00755, AID_ROOT, AID_ROOT, 0 }, -+}; -+ -+/* Rules for files. -+** These rules are applied based on "first match", so they -+** should start with the most specific path and work their -+** way up to the root. Prefixes ending in * denotes wildcard -+** and will allow partial matches. -+*/ -+static struct fs_path_config android_files[] = { -+ { 00440, AID_ROOT, AID_SHELL, "system/etc/init.goldfish.rc" }, -+ { 00550, AID_ROOT, AID_SHELL, "system/etc/init.goldfish.sh" }, -+ { 00440, AID_ROOT, AID_SHELL, "system/etc/init.trout.rc" }, -+ { 00550, AID_ROOT, AID_SHELL, "system/etc/init.ril" }, -+ { 00550, AID_ROOT, AID_SHELL, "system/etc/init.testmenu" }, -+ { 00550, AID_DHCP, AID_SHELL, "system/etc/dhcpcd/dhcpcd-run-hooks" }, -+ { 00440, AID_BLUETOOTH, AID_BLUETOOTH, "system/etc/dbus.conf" }, -+ { 00444, AID_RADIO, AID_AUDIO, "system/etc/AudioPara4.csv" }, -+ { 00555, AID_ROOT, AID_ROOT, "system/etc/ppp/*" }, -+ { 00555, AID_ROOT, AID_ROOT, "system/etc/rc.*" }, -+ { 00755, AID_ROOT, AID_ROOT, "system/addon.d/*" }, -+ { 00644, AID_SYSTEM, AID_SYSTEM, "data/app/*" }, -+ { 00644, AID_MEDIA_RW, AID_MEDIA_RW, "data/media/*" }, -+ { 00644, AID_SYSTEM, AID_SYSTEM, "data/app-private/*" }, -+ { 00644, AID_APP, AID_APP, "data/data/*" }, -+ /* the following two files are INTENTIONALLY set-gid and not set-uid. -+ * Do not change. */ -+ { 02755, AID_ROOT, AID_NET_RAW, "system/bin/ping" }, -+ { 02750, AID_ROOT, AID_INET, "system/bin/netcfg" }, -+ /* the following five files are INTENTIONALLY set-uid, but they -+ * are NOT included on user builds. */ -+ { 06755, AID_ROOT, AID_ROOT, "system/xbin/su" }, -+ { 06755, AID_ROOT, AID_ROOT, "system/xbin/librank" }, -+ { 06755, AID_ROOT, AID_ROOT, "system/xbin/procrank" }, -+ { 06755, AID_ROOT, AID_ROOT, "system/xbin/procmem" }, -+ { 06755, AID_ROOT, AID_ROOT, "system/xbin/tcpdump" }, -+ { 04770, AID_ROOT, AID_RADIO, "system/bin/pppd-ril" }, -+ /* the following file is INTENTIONALLY set-uid, and IS included -+ * in user builds. */ -+ { 06750, AID_ROOT, AID_SHELL, "system/bin/run-as" }, -+ { 06750, AID_ROOT, AID_SYSTEM, "system/bin/rebootcmd" }, -+ { 00755, AID_ROOT, AID_SHELL, "system/bin/*" }, -+ { 00755, AID_ROOT, AID_ROOT, "system/lib/valgrind/*" }, -+ { 00755, AID_ROOT, AID_SHELL, "system/xbin/*" }, -+ { 00755, AID_ROOT, AID_SHELL, "system/vendor/bin/*" }, -+ { 00750, AID_ROOT, AID_SHELL, "sbin/*" }, -+ { 00755, AID_ROOT, AID_ROOT, "bin/*" }, -+ { 00750, AID_ROOT, AID_SHELL, "init*" }, -+ { 00750, AID_ROOT, AID_SHELL, "charger*" }, -+ { 00750, AID_ROOT, AID_SHELL, "sbin/fs_mgr" }, -+ { 00640, AID_ROOT, AID_SHELL, "fstab.*" }, -+ { 00755, AID_ROOT, AID_SHELL, "system/etc/init.d/*" }, -+ { 00644, AID_ROOT, AID_ROOT, 0 }, -+}; -+ -+static inline void fs_config(const char *path, int dir, -+ unsigned *uid, unsigned *gid, unsigned *mode) -+{ -+ struct fs_path_config *pc; -+ int plen; -+ -+ pc = dir ? android_dirs : android_files; -+ plen = strlen(path); -+ for(; pc->prefix; pc++){ -+ int len = strlen(pc->prefix); -+ if (dir) { -+ if(plen < len) continue; -+ if(!strncmp(pc->prefix, path, len)) break; -+ continue; -+ } -+ /* If name ends in * then allow partial matches. */ -+ if (pc->prefix[len -1] == '*') { -+ if(!strncmp(pc->prefix, path, len - 1)) break; -+ } else if (plen == len){ -+ if(!strncmp(pc->prefix, path, len)) break; -+ } -+ } -+ *uid = pc->uid; -+ *gid = pc->gid; -+ *mode = (*mode & (~07777)) | pc->mode; -+ -+#if 0 -+ fprintf(stderr,"< '%s' '%s' %d %d %o >\n", -+ path, pc->prefix ? pc->prefix : "", *uid, *gid, *mode); -+#endif -+} -+#endif -+#endif -Index: android-tools-4.2.2+git20130218/core/adbd/arpa_nameser.h -=================================================================== ---- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ android-tools-4.2.2+git20130218/core/adbd/arpa_nameser.h 2013-06-18 17:12:17.000000000 -0300 -@@ -0,0 +1,577 @@ -+/* $NetBSD: nameser.h,v 1.19 2005/12/26 19:01:47 perry Exp $ */ -+ -+/* -+ * Copyright (c) 1983, 1989, 1993 -+ * The Regents of the University of California. All rights reserved. -+ * -+ * Redistribution and use in source and binary forms, with or without -+ * modification, are permitted provided that the following conditions -+ * are met: -+ * 1. Redistributions of source code must retain the above copyright -+ * notice, this list of conditions and the following disclaimer. -+ * 2. Redistributions in binary form must reproduce the above copyright -+ * notice, this list of conditions and the following disclaimer in the -+ * documentation and/or other materials provided with the distribution. -+ * 3. Neither the name of the University nor the names of its contributors -+ * may be used to endorse or promote products derived from this software -+ * without specific prior written permission. -+ * -+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND -+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE -+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -+ * SUCH DAMAGE. -+ */ -+ -+/* -+ * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") -+ * Copyright (c) 1996-1999 by Internet Software Consortium. -+ * -+ * Permission to use, copy, modify, and distribute this software for any -+ * purpose with or without fee is hereby granted, provided that the above -+ * copyright notice and this permission notice appear in all copies. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES -+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR -+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT -+ * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -+ */ -+ -+/* -+ * Id: nameser.h,v 1.2.2.4.4.1 2004/03/09 08:33:30 marka Exp -+ */ -+ -+#ifndef _ARPA_NAMESER_H_ -+#define _ARPA_NAMESER_H_ -+ -+#define BIND_4_COMPAT -+ -+#include -+#include -+ -+/* -+ * Revision information. This is the release date in YYYYMMDD format. -+ * It can change every day so the right thing to do with it is use it -+ * in preprocessor commands such as "#if (__NAMESER > 19931104)". Do not -+ * compare for equality; rather, use it to determine whether your libbind.a -+ * contains a new enough lib/nameser/ to support the feature you need. -+ */ -+ -+#define __NAMESER 19991006 /* New interface version stamp. */ -+ -+/* -+ * Define constants based on RFC 883, RFC 1034, RFC 1035 -+ */ -+#define NS_PACKETSZ 512 /* default UDP packet size */ -+#define NS_MAXDNAME 1025 /* maximum domain name */ -+#define NS_MAXMSG 65535 /* maximum message size */ -+#define NS_MAXCDNAME 255 /* maximum compressed domain name */ -+#define NS_MAXLABEL 63 /* maximum length of domain label */ -+#define NS_HFIXEDSZ 12 /* #/bytes of fixed data in header */ -+#define NS_QFIXEDSZ 4 /* #/bytes of fixed data in query */ -+#define NS_RRFIXEDSZ 10 /* #/bytes of fixed data in r record */ -+#define NS_INT32SZ 4 /* #/bytes of data in a uint32_t */ -+#define NS_INT16SZ 2 /* #/bytes of data in a uint16_t */ -+#define NS_INT8SZ 1 /* #/bytes of data in a uint8_t */ -+#define NS_INADDRSZ 4 /* IPv4 T_A */ -+#define NS_IN6ADDRSZ 16 /* IPv6 T_AAAA */ -+#define NS_CMPRSFLGS 0xc0 /* Flag bits indicating name compression. */ -+#define NS_DEFAULTPORT 53 /* For both TCP and UDP. */ -+ -+/* -+ * These can be expanded with synonyms, just keep ns_parse.c:ns_parserecord() -+ * in synch with it. -+ */ -+typedef enum __ns_sect { -+ ns_s_qd = 0, /* Query: Question. */ -+ ns_s_zn = 0, /* Update: Zone. */ -+ ns_s_an = 1, /* Query: Answer. */ -+ ns_s_pr = 1, /* Update: Prerequisites. */ -+ ns_s_ns = 2, /* Query: Name servers. */ -+ ns_s_ud = 2, /* Update: Update. */ -+ ns_s_ar = 3, /* Query|Update: Additional records. */ -+ ns_s_max = 4 -+} ns_sect; -+ -+/* -+ * This is a message handle. It is caller allocated and has no dynamic data. -+ * This structure is intended to be opaque to all but ns_parse.c, thus the -+ * leading _'s on the member names. Use the accessor functions, not the _'s. -+ */ -+typedef struct __ns_msg { -+ const u_char *_msg, *_eom; -+ uint16_t _id, _flags, _counts[ns_s_max]; -+ const u_char *_sections[ns_s_max]; -+ ns_sect _sect; -+ int _rrnum; -+ const u_char *_msg_ptr; -+} ns_msg; -+ -+/* Private data structure - do not use from outside library. */ -+struct _ns_flagdata { int mask, shift; }; -+extern const struct _ns_flagdata _ns_flagdata[]; -+ -+/* Accessor macros - this is part of the public interface. */ -+ -+#define ns_msg_id(handle) ((handle)._id + 0) -+#define ns_msg_base(handle) ((handle)._msg + 0) -+#define ns_msg_end(handle) ((handle)._eom + 0) -+#define ns_msg_size(handle) ((size_t)((handle)._eom - (handle)._msg)) -+#define ns_msg_count(handle, section) ((handle)._counts[section] + 0) -+ -+/* -+ * This is a parsed record. It is caller allocated and has no dynamic data. -+ */ -+typedef struct __ns_rr { -+ char name[NS_MAXDNAME]; -+ uint16_t type; -+ uint16_t rr_class; -+ uint32_t ttl; -+ uint16_t rdlength; -+ const u_char * rdata; -+} ns_rr; -+ -+/* Accessor macros - this is part of the public interface. */ -+#define ns_rr_name(rr) (((rr).name[0] != '\0') ? (rr).name : ".") -+#define ns_rr_type(rr) ((ns_type)((rr).type + 0)) -+#define ns_rr_class(rr) ((ns_class)((rr).rr_class + 0)) -+#define ns_rr_ttl(rr) ((u_long)(rr).ttl + 0) -+#define ns_rr_rdlen(rr) ((size_t)(rr).rdlength + 0) -+#define ns_rr_rdata(rr) ((rr).rdata + 0) -+ -+/* -+ * These don't have to be in the same order as in the packet flags word, -+ * and they can even overlap in some cases, but they will need to be kept -+ * in synch with ns_parse.c:ns_flagdata[]. -+ */ -+typedef enum __ns_flag { -+ ns_f_qr, /* Question/Response. */ -+ ns_f_opcode, /* Operation code. */ -+ ns_f_aa, /* Authoritative Answer. */ -+ ns_f_tc, /* Truncation occurred. */ -+ ns_f_rd, /* Recursion Desired. */ -+ ns_f_ra, /* Recursion Available. */ -+ ns_f_z, /* MBZ. */ -+ ns_f_ad, /* Authentic Data (DNSSEC). */ -+ ns_f_cd, /* Checking Disabled (DNSSEC). */ -+ ns_f_rcode, /* Response code. */ -+ ns_f_max -+} ns_flag; -+ -+/* -+ * Currently defined opcodes. -+ */ -+typedef enum __ns_opcode { -+ ns_o_query = 0, /* Standard query. */ -+ ns_o_iquery = 1, /* Inverse query (deprecated/unsupported). */ -+ ns_o_status = 2, /* Name server status query (unsupported). */ -+ /* Opcode 3 is undefined/reserved. */ -+ ns_o_notify = 4, /* Zone change notification. */ -+ ns_o_update = 5, /* Zone update message. */ -+ ns_o_max = 6 -+} ns_opcode; -+ -+/* -+ * Currently defined response codes. -+ */ -+typedef enum __ns_rcode { -+ ns_r_noerror = 0, /* No error occurred. */ -+ ns_r_formerr = 1, /* Format error. */ -+ ns_r_servfail = 2, /* Server failure. */ -+ ns_r_nxdomain = 3, /* Name error. */ -+ ns_r_notimpl = 4, /* Unimplemented. */ -+ ns_r_refused = 5, /* Operation refused. */ -+ /* these are for BIND_UPDATE */ -+ ns_r_yxdomain = 6, /* Name exists */ -+ ns_r_yxrrset = 7, /* RRset exists */ -+ ns_r_nxrrset = 8, /* RRset does not exist */ -+ ns_r_notauth = 9, /* Not authoritative for zone */ -+ ns_r_notzone = 10, /* Zone of record different from zone section */ -+ ns_r_max = 11, -+ /* The following are EDNS extended rcodes */ -+ ns_r_badvers = 16, -+ /* The following are TSIG errors */ -+ ns_r_badsig = 16, -+ ns_r_badkey = 17, -+ ns_r_badtime = 18 -+} ns_rcode; -+ -+/* BIND_UPDATE */ -+typedef enum __ns_update_operation { -+ ns_uop_delete = 0, -+ ns_uop_add = 1, -+ ns_uop_max = 2 -+} ns_update_operation; -+ -+/* -+ * This structure is used for TSIG authenticated messages -+ */ -+struct ns_tsig_key { -+ char name[NS_MAXDNAME], alg[NS_MAXDNAME]; -+ unsigned char *data; -+ int len; -+}; -+typedef struct ns_tsig_key ns_tsig_key; -+ -+/* -+ * This structure is used for TSIG authenticated TCP messages -+ */ -+struct ns_tcp_tsig_state { -+ int counter; -+ struct dst_key *key; -+ void *ctx; -+ unsigned char sig[NS_PACKETSZ]; -+ int siglen; -+}; -+typedef struct ns_tcp_tsig_state ns_tcp_tsig_state; -+ -+#define NS_TSIG_FUDGE 300 -+#define NS_TSIG_TCP_COUNT 100 -+#define NS_TSIG_ALG_HMAC_MD5 "HMAC-MD5.SIG-ALG.REG.INT" -+ -+#define NS_TSIG_ERROR_NO_TSIG -10 -+#define NS_TSIG_ERROR_NO_SPACE -11 -+#define NS_TSIG_ERROR_FORMERR -12 -+ -+/* -+ * Currently defined type values for resources and queries. -+ */ -+typedef enum __ns_type { -+ ns_t_invalid = 0, /* Cookie. */ -+ ns_t_a = 1, /* Host address. */ -+ ns_t_ns = 2, /* Authoritative server. */ -+ ns_t_md = 3, /* Mail destination. */ -+ ns_t_mf = 4, /* Mail forwarder. */ -+ ns_t_cname = 5, /* Canonical name. */ -+ ns_t_soa = 6, /* Start of authority zone. */ -+ ns_t_mb = 7, /* Mailbox domain name. */ -+ ns_t_mg = 8, /* Mail group member. */ -+ ns_t_mr = 9, /* Mail rename name. */ -+ ns_t_null = 10, /* Null resource record. */ -+ ns_t_wks = 11, /* Well known service. */ -+ ns_t_ptr = 12, /* Domain name pointer. */ -+ ns_t_hinfo = 13, /* Host information. */ -+ ns_t_minfo = 14, /* Mailbox information. */ -+ ns_t_mx = 15, /* Mail routing information. */ -+ ns_t_txt = 16, /* Text strings. */ -+ ns_t_rp = 17, /* Responsible person. */ -+ ns_t_afsdb = 18, /* AFS cell database. */ -+ ns_t_x25 = 19, /* X_25 calling address. */ -+ ns_t_isdn = 20, /* ISDN calling address. */ -+ ns_t_rt = 21, /* Router. */ -+ ns_t_nsap = 22, /* NSAP address. */ -+ ns_t_nsap_ptr = 23, /* Reverse NSAP lookup (deprecated). */ -+ ns_t_sig = 24, /* Security signature. */ -+ ns_t_key = 25, /* Security key. */ -+ ns_t_px = 26, /* X.400 mail mapping. */ -+ ns_t_gpos = 27, /* Geographical position (withdrawn). */ -+ ns_t_aaaa = 28, /* Ip6 Address. */ -+ ns_t_loc = 29, /* Location Information. */ -+ ns_t_nxt = 30, /* Next domain (security). */ -+ ns_t_eid = 31, /* Endpoint identifier. */ -+ ns_t_nimloc = 32, /* Nimrod Locator. */ -+ ns_t_srv = 33, /* Server Selection. */ -+ ns_t_atma = 34, /* ATM Address */ -+ ns_t_naptr = 35, /* Naming Authority PoinTeR */ -+ ns_t_kx = 36, /* Key Exchange */ -+ ns_t_cert = 37, /* Certification record */ -+ ns_t_a6 = 38, /* IPv6 address (deprecates AAAA) */ -+ ns_t_dname = 39, /* Non-terminal DNAME (for IPv6) */ -+ ns_t_sink = 40, /* Kitchen sink (experimentatl) */ -+ ns_t_opt = 41, /* EDNS0 option (meta-RR) */ -+ ns_t_apl = 42, /* Address prefix list (RFC 3123) */ -+ ns_t_tkey = 249, /* Transaction key */ -+ ns_t_tsig = 250, /* Transaction signature. */ -+ ns_t_ixfr = 251, /* Incremental zone transfer. */ -+ ns_t_axfr = 252, /* Transfer zone of authority. */ -+ ns_t_mailb = 253, /* Transfer mailbox records. */ -+ ns_t_maila = 254, /* Transfer mail agent records. */ -+ ns_t_any = 255, /* Wildcard match. */ -+ ns_t_zxfr = 256, /* BIND-specific, nonstandard. */ -+ ns_t_max = 65536 -+} ns_type; -+ -+/* Exclusively a QTYPE? (not also an RTYPE) */ -+#define ns_t_qt_p(t) (ns_t_xfr_p(t) || (t) == ns_t_any || \ -+ (t) == ns_t_mailb || (t) == ns_t_maila) -+/* Some kind of meta-RR? (not a QTYPE, but also not an RTYPE) */ -+#define ns_t_mrr_p(t) ((t) == ns_t_tsig || (t) == ns_t_opt) -+/* Exclusively an RTYPE? (not also a QTYPE or a meta-RR) */ -+#define ns_t_rr_p(t) (!ns_t_qt_p(t) && !ns_t_mrr_p(t)) -+#define ns_t_udp_p(t) ((t) != ns_t_axfr && (t) != ns_t_zxfr) -+#define ns_t_xfr_p(t) ((t) == ns_t_axfr || (t) == ns_t_ixfr || \ -+ (t) == ns_t_zxfr) -+ -+/* -+ * Values for class field -+ */ -+typedef enum __ns_class { -+ ns_c_invalid = 0, /* Cookie. */ -+ ns_c_in = 1, /* Internet. */ -+ ns_c_2 = 2, /* unallocated/unsupported. */ -+ ns_c_chaos = 3, /* MIT Chaos-net. */ -+ ns_c_hs = 4, /* MIT Hesiod. */ -+ /* Query class values which do not appear in resource records */ -+ ns_c_none = 254, /* for prereq. sections in update requests */ -+ ns_c_any = 255, /* Wildcard match. */ -+ ns_c_max = 65536 -+} ns_class; -+ -+/* DNSSEC constants. */ -+ -+typedef enum __ns_key_types { -+ ns_kt_rsa = 1, /* key type RSA/MD5 */ -+ ns_kt_dh = 2, /* Diffie Hellman */ -+ ns_kt_dsa = 3, /* Digital Signature Standard (MANDATORY) */ -+ ns_kt_private = 254 /* Private key type starts with OID */ -+} ns_key_types; -+ -+typedef enum __ns_cert_types { -+ cert_t_pkix = 1, /* PKIX (X.509v3) */ -+ cert_t_spki = 2, /* SPKI */ -+ cert_t_pgp = 3, /* PGP */ -+ cert_t_url = 253, /* URL private type */ -+ cert_t_oid = 254 /* OID private type */ -+} ns_cert_types; -+ -+/* Flags field of the KEY RR rdata. */ -+#define NS_KEY_TYPEMASK 0xC000 /* Mask for "type" bits */ -+#define NS_KEY_TYPE_AUTH_CONF 0x0000 /* Key usable for both */ -+#define NS_KEY_TYPE_CONF_ONLY 0x8000 /* Key usable for confidentiality */ -+#define NS_KEY_TYPE_AUTH_ONLY 0x4000 /* Key usable for authentication */ -+#define NS_KEY_TYPE_NO_KEY 0xC000 /* No key usable for either; no key */ -+/* The type bits can also be interpreted independently, as single bits: */ -+#define NS_KEY_NO_AUTH 0x8000 /* Key unusable for authentication */ -+#define NS_KEY_NO_CONF 0x4000 /* Key unusable for confidentiality */ -+#define NS_KEY_RESERVED2 0x2000 /* Security is *mandatory* if bit=0 */ -+#define NS_KEY_EXTENDED_FLAGS 0x1000 /* reserved - must be zero */ -+#define NS_KEY_RESERVED4 0x0800 /* reserved - must be zero */ -+#define NS_KEY_RESERVED5 0x0400 /* reserved - must be zero */ -+#define NS_KEY_NAME_TYPE 0x0300 /* these bits determine the type */ -+#define NS_KEY_NAME_USER 0x0000 /* key is assoc. with user */ -+#define NS_KEY_NAME_ENTITY 0x0200 /* key is assoc. with entity eg host */ -+#define NS_KEY_NAME_ZONE 0x0100 /* key is zone key */ -+#define NS_KEY_NAME_RESERVED 0x0300 /* reserved meaning */ -+#define NS_KEY_RESERVED8 0x0080 /* reserved - must be zero */ -+#define NS_KEY_RESERVED9 0x0040 /* reserved - must be zero */ -+#define NS_KEY_RESERVED10 0x0020 /* reserved - must be zero */ -+#define NS_KEY_RESERVED11 0x0010 /* reserved - must be zero */ -+#define NS_KEY_SIGNATORYMASK 0x000F /* key can sign RR's of same name */ -+#define NS_KEY_RESERVED_BITMASK ( NS_KEY_RESERVED2 | \ -+ NS_KEY_RESERVED4 | \ -+ NS_KEY_RESERVED5 | \ -+ NS_KEY_RESERVED8 | \ -+ NS_KEY_RESERVED9 | \ -+ NS_KEY_RESERVED10 | \ -+ NS_KEY_RESERVED11 ) -+#define NS_KEY_RESERVED_BITMASK2 0xFFFF /* no bits defined here */ -+ -+/* The Algorithm field of the KEY and SIG RR's is an integer, {1..254} */ -+#define NS_ALG_MD5RSA 1 /* MD5 with RSA */ -+#define NS_ALG_DH 2 /* Diffie Hellman KEY */ -+#define NS_ALG_DSA 3 /* DSA KEY */ -+#define NS_ALG_DSS NS_ALG_DSA -+#define NS_ALG_EXPIRE_ONLY 253 /* No alg, no security */ -+#define NS_ALG_PRIVATE_OID 254 /* Key begins with OID giving alg */ -+ -+/* Protocol values */ -+/* value 0 is reserved */ -+#define NS_KEY_PROT_TLS 1 -+#define NS_KEY_PROT_EMAIL 2 -+#define NS_KEY_PROT_DNSSEC 3 -+#define NS_KEY_PROT_IPSEC 4 -+#define NS_KEY_PROT_ANY 255 -+ -+/* Signatures */ -+#define NS_MD5RSA_MIN_BITS 512 /* Size of a mod or exp in bits */ -+#define NS_MD5RSA_MAX_BITS 4096 -+ /* Total of binary mod and exp */ -+#define NS_MD5RSA_MAX_BYTES ((NS_MD5RSA_MAX_BITS+7/8)*2+3) -+ /* Max length of text sig block */ -+#define NS_MD5RSA_MAX_BASE64 (((NS_MD5RSA_MAX_BYTES+2)/3)*4) -+#define NS_MD5RSA_MIN_SIZE ((NS_MD5RSA_MIN_BITS+7)/8) -+#define NS_MD5RSA_MAX_SIZE ((NS_MD5RSA_MAX_BITS+7)/8) -+ -+#define NS_DSA_SIG_SIZE 41 -+#define NS_DSA_MIN_SIZE 213 -+#define NS_DSA_MAX_BYTES 405 -+ -+/* Offsets into SIG record rdata to find various values */ -+#define NS_SIG_TYPE 0 /* Type flags */ -+#define NS_SIG_ALG 2 /* Algorithm */ -+#define NS_SIG_LABELS 3 /* How many labels in name */ -+#define NS_SIG_OTTL 4 /* Original TTL */ -+#define NS_SIG_EXPIR 8 /* Expiration time */ -+#define NS_SIG_SIGNED 12 /* Signature time */ -+#define NS_SIG_FOOT 16 /* Key footprint */ -+#define NS_SIG_SIGNER 18 /* Domain name of who signed it */ -+ -+/* How RR types are represented as bit-flags in NXT records */ -+#define NS_NXT_BITS 8 -+#define NS_NXT_BIT_SET( n,p) (p[(n)/NS_NXT_BITS] |= (0x80>>((n)%NS_NXT_BITS))) -+#define NS_NXT_BIT_CLEAR(n,p) (p[(n)/NS_NXT_BITS] &= ~(0x80>>((n)%NS_NXT_BITS))) -+#define NS_NXT_BIT_ISSET(n,p) (p[(n)/NS_NXT_BITS] & (0x80>>((n)%NS_NXT_BITS))) -+#define NS_NXT_MAX 127 -+ -+/* -+ * EDNS0 extended flags, host order. -+ */ -+#define NS_OPT_DNSSEC_OK 0x8000U -+ -+/* -+ * Inline versions of get/put short/long. Pointer is advanced. -+ */ -+#define NS_GET16(s, cp) do { \ -+ const u_char *t_cp = (const u_char *)(cp); \ -+ (s) = ((uint16_t)t_cp[0] << 8) \ -+ | ((uint16_t)t_cp[1]) \ -+ ; \ -+ (cp) += NS_INT16SZ; \ -+} while (/*CONSTCOND*/0) -+ -+#define NS_GET32(l, cp) do { \ -+ const u_char *t_cp = (const u_char *)(cp); \ -+ (l) = ((uint32_t)t_cp[0] << 24) \ -+ | ((uint32_t)t_cp[1] << 16) \ -+ | ((uint32_t)t_cp[2] << 8) \ -+ | ((uint32_t)t_cp[3]) \ -+ ; \ -+ (cp) += NS_INT32SZ; \ -+} while (/*CONSTCOND*/0) -+ -+#define NS_PUT16(s, cp) do { \ -+ uint32_t t_s = (uint32_t)(s); \ -+ u_char *t_cp = (u_char *)(cp); \ -+ *t_cp++ = t_s >> 8; \ -+ *t_cp = t_s; \ -+ (cp) += NS_INT16SZ; \ -+} while (/*CONSTCOND*/0) -+ -+#define NS_PUT32(l, cp) do { \ -+ uint32_t t_l = (uint32_t)(l); \ -+ u_char *t_cp = (u_char *)(cp); \ -+ *t_cp++ = t_l >> 24; \ -+ *t_cp++ = t_l >> 16; \ -+ *t_cp++ = t_l >> 8; \ -+ *t_cp = t_l; \ -+ (cp) += NS_INT32SZ; \ -+} while (/*CONSTCOND*/0) -+ -+/* -+ * ANSI C identifier hiding for bind's lib/nameser. -+ */ -+#define ns_msg_getflag __ns_msg_getflag -+#define ns_get16 __ns_get16 -+#define ns_get32 __ns_get32 -+#define ns_put16 __ns_put16 -+#define ns_put32 __ns_put32 -+#define ns_initparse __ns_initparse -+#define ns_skiprr __ns_skiprr -+#define ns_parserr __ns_parserr -+#define ns_sprintrr __ns_sprintrr -+#define ns_sprintrrf __ns_sprintrrf -+#define ns_format_ttl __ns_format_ttl -+#define ns_parse_ttl __ns_parse_ttl -+#define ns_datetosecs __ns_datetosecs -+#define ns_name_ntol __ns_name_ntol -+#define ns_name_ntop __ns_name_ntop -+#define ns_name_pton __ns_name_pton -+#define ns_name_unpack __ns_name_unpack -+#define ns_name_pack __ns_name_pack -+#define ns_name_compress __ns_name_compress -+#define ns_name_uncompress __ns_name_uncompress -+#define ns_name_skip __ns_name_skip -+#define ns_name_rollback __ns_name_rollback -+#define ns_sign __ns_sign -+#define ns_sign2 __ns_sign2 -+#define ns_sign_tcp __ns_sign_tcp -+#define ns_sign_tcp2 __ns_sign_tcp2 -+#define ns_sign_tcp_init __ns_sign_tcp_init -+#define ns_find_tsig __ns_find_tsig -+#define ns_verify __ns_verify -+#define ns_verify_tcp __ns_verify_tcp -+#define ns_verify_tcp_init __ns_verify_tcp_init -+#define ns_samedomain __ns_samedomain -+#define ns_subdomain __ns_subdomain -+#define ns_makecanon __ns_makecanon -+#define ns_samename __ns_samename -+ -+__BEGIN_DECLS -+int ns_msg_getflag(ns_msg, int); -+uint16_t ns_get16(const u_char *); -+uint32_t ns_get32(const u_char *); -+void ns_put16(uint16_t, u_char *); -+void ns_put32(uint32_t, u_char *); -+int ns_initparse(const u_char *, int, ns_msg *); -+int ns_skiprr(const u_char *, const u_char *, ns_sect, int); -+int ns_parserr(ns_msg *, ns_sect, int, ns_rr *); -+int ns_sprintrr(const ns_msg *, const ns_rr *, -+ const char *, const char *, char *, size_t); -+int ns_sprintrrf(const u_char *, size_t, const char *, -+ ns_class, ns_type, u_long, const u_char *, -+ size_t, const char *, const char *, -+ char *, size_t); -+int ns_format_ttl(u_long, char *, size_t); -+int ns_parse_ttl(const char *, u_long *); -+uint32_t ns_datetosecs(const char *cp, int *errp); -+int ns_name_ntol(const u_char *, u_char *, size_t); -+int ns_name_ntop(const u_char *, char *, size_t); -+int ns_name_pton(const char *, u_char *, size_t); -+int ns_name_unpack(const u_char *, const u_char *, -+ const u_char *, u_char *, size_t); -+int ns_name_pack(const u_char *, u_char *, int, -+ const u_char **, const u_char **); -+int ns_name_uncompress(const u_char *, const u_char *, -+ const u_char *, char *, size_t); -+int ns_name_compress(const char *, u_char *, size_t, -+ const u_char **, const u_char **); -+int ns_name_skip(const u_char **, const u_char *); -+void ns_name_rollback(const u_char *, const u_char **, -+ const u_char **); -+int ns_sign(u_char *, int *, int, int, void *, -+ const u_char *, int, u_char *, int *, time_t); -+int ns_sign2(u_char *, int *, int, int, void *, -+ const u_char *, int, u_char *, int *, time_t, -+ u_char **, u_char **); -+int ns_sign_tcp(u_char *, int *, int, int, -+ ns_tcp_tsig_state *, int); -+int ns_sign_tcp2(u_char *, int *, int, int, -+ ns_tcp_tsig_state *, int, -+ u_char **, u_char **); -+int ns_sign_tcp_init(void *, const u_char *, int, -+ ns_tcp_tsig_state *); -+u_char *ns_find_tsig(u_char *, u_char *); -+int ns_verify(u_char *, int *, void *, -+ const u_char *, int, u_char *, int *, -+ time_t *, int); -+int ns_verify_tcp(u_char *, int *, ns_tcp_tsig_state *, int); -+int ns_verify_tcp_init(void *, const u_char *, int, -+ ns_tcp_tsig_state *); -+int ns_samedomain(const char *, const char *); -+int ns_subdomain(const char *, const char *); -+int ns_makecanon(const char *, char *, size_t); -+int ns_samename(const char *, const char *); -+__END_DECLS -+ -+#ifdef BIND_4_COMPAT -+#include "arpa_nameser_compat.h" -+#endif -+ -+#if 0 -+# include -+# define XLOG(...) \ -+ __libc_android_log_print(ANDROID_LOG_DEBUG,"libc",__VA_ARGS__) -+#else -+#define XLOG(...) do {} while (0) -+#endif -+ -+#endif /* !_ARPA_NAMESER_H_ */ -Index: android-tools-4.2.2+git20130218/core/adbd/arpa_nameser_compat.h -=================================================================== ---- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ android-tools-4.2.2+git20130218/core/adbd/arpa_nameser_compat.h 2013-06-18 17:12:17.000000000 -0300 -@@ -0,0 +1,236 @@ -+/* $NetBSD: nameser_compat.h,v 1.1.1.2 2004/11/07 01:28:27 christos Exp $ */ -+ -+/* Copyright (c) 1983, 1989 -+ * The Regents of the University of California. All rights reserved. -+ * -+ * Redistribution and use in source and binary forms, with or without -+ * modification, are permitted provided that the following conditions -+ * are met: -+ * 1. Redistributions of source code must retain the above copyright -+ * notice, this list of conditions and the following disclaimer. -+ * 2. Redistributions in binary form must reproduce the above copyright -+ * notice, this list of conditions and the following disclaimer in the -+ * documentation and/or other materials provided with the distribution. -+ * 3. All advertising materials mentioning features or use of this software -+ * must display the following acknowledgement: -+ * This product includes software developed by the University of -+ * California, Berkeley and its contributors. -+ * 4. Neither the name of the University nor the names of its contributors -+ * may be used to endorse or promote products derived from this software -+ * without specific prior written permission. -+ * -+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND -+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE -+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -+ * SUCH DAMAGE. -+ */ -+ -+/* -+ * from nameser.h 8.1 (Berkeley) 6/2/93 -+ * Id: nameser_compat.h,v 1.1.2.3.4.2 2004/07/01 04:43:41 marka Exp -+ */ -+ -+#ifndef _ARPA_NAMESER_COMPAT_ -+#define _ARPA_NAMESER_COMPAT_ -+ -+#define __BIND 19950621 /* (DEAD) interface version stamp. */ -+ -+#include -+ -+#ifndef BYTE_ORDER -+#if (BSD >= 199103) -+# include -+#else -+#ifdef __linux -+# include -+#else -+#define LITTLE_ENDIAN 1234 /* least-significant byte first (vax, pc) */ -+#define BIG_ENDIAN 4321 /* most-significant byte first (IBM, net) */ -+#define PDP_ENDIAN 3412 /* LSB first in word, MSW first in long (pdp)*/ -+ -+#if defined(vax) || defined(ns32000) || defined(sun386) || defined(i386) || \ -+ defined(MIPSEL) || defined(_MIPSEL) || defined(BIT_ZERO_ON_RIGHT) || \ -+ defined(__alpha__) || defined(__alpha) || \ -+ (defined(__Lynx__) && defined(__x86__)) -+#define BYTE_ORDER LITTLE_ENDIAN -+#endif -+ -+#if defined(sel) || defined(pyr) || defined(mc68000) || defined(sparc) || \ -+ defined(is68k) || defined(tahoe) || defined(ibm032) || defined(ibm370) || \ -+ defined(MIPSEB) || defined(_MIPSEB) || defined(_IBMR2) || defined(DGUX) ||\ -+ defined(apollo) || defined(__convex__) || defined(_CRAY) || \ -+ defined(__hppa) || defined(__hp9000) || \ -+ defined(__hp9000s300) || defined(__hp9000s700) || \ -+ defined(__hp3000s900) || defined(__hpux) || defined(MPE) || \ -+ defined (BIT_ZERO_ON_LEFT) || defined(m68k) || defined(__sparc) || \ -+ (defined(__Lynx__) && \ -+ (defined(__68k__) || defined(__sparc__) || defined(__powerpc__))) -+#define BYTE_ORDER BIG_ENDIAN -+#endif -+#endif /* __linux */ -+#endif /* BSD */ -+#endif /* BYTE_ORDER */ -+ -+#if !defined(BYTE_ORDER) || \ -+ (BYTE_ORDER != BIG_ENDIAN && BYTE_ORDER != LITTLE_ENDIAN && \ -+ BYTE_ORDER != PDP_ENDIAN) -+ /* you must determine what the correct bit order is for -+ * your compiler - the next line is an intentional error -+ * which will force your compiles to bomb until you fix -+ * the above macros. -+ */ -+ #error "Undefined or invalid BYTE_ORDER"; -+#endif -+ -+/* -+ * Structure for query header. The order of the fields is machine- and -+ * compiler-dependent, depending on the byte/bit order and the layout -+ * of bit fields. We use bit fields only in int variables, as this -+ * is all ANSI requires. This requires a somewhat confusing rearrangement. -+ */ -+ -+typedef struct { -+ unsigned id :16; /* query identification number */ -+#if BYTE_ORDER == BIG_ENDIAN -+ /* fields in third byte */ -+ unsigned qr: 1; /* response flag */ -+ unsigned opcode: 4; /* purpose of message */ -+ unsigned aa: 1; /* authoritive answer */ -+ unsigned tc: 1; /* truncated message */ -+ unsigned rd: 1; /* recursion desired */ -+ /* fields in fourth byte */ -+ unsigned ra: 1; /* recursion available */ -+ unsigned unused :1; /* unused bits (MBZ as of 4.9.3a3) */ -+ unsigned ad: 1; /* authentic data from named */ -+ unsigned cd: 1; /* checking disabled by resolver */ -+ unsigned rcode :4; /* response code */ -+#endif -+#if BYTE_ORDER == LITTLE_ENDIAN || BYTE_ORDER == PDP_ENDIAN -+ /* fields in third byte */ -+ unsigned rd :1; /* recursion desired */ -+ unsigned tc :1; /* truncated message */ -+ unsigned aa :1; /* authoritive answer */ -+ unsigned opcode :4; /* purpose of message */ -+ unsigned qr :1; /* response flag */ -+ /* fields in fourth byte */ -+ unsigned rcode :4; /* response code */ -+ unsigned cd: 1; /* checking disabled by resolver */ -+ unsigned ad: 1; /* authentic data from named */ -+ unsigned unused :1; /* unused bits (MBZ as of 4.9.3a3) */ -+ unsigned ra :1; /* recursion available */ -+#endif -+ /* remaining bytes */ -+ unsigned qdcount :16; /* number of question entries */ -+ unsigned ancount :16; /* number of answer entries */ -+ unsigned nscount :16; /* number of authority entries */ -+ unsigned arcount :16; /* number of resource entries */ -+} HEADER; -+ -+#define PACKETSZ NS_PACKETSZ -+#define MAXDNAME NS_MAXDNAME -+#define MAXCDNAME NS_MAXCDNAME -+#define MAXLABEL NS_MAXLABEL -+#define HFIXEDSZ NS_HFIXEDSZ -+#define QFIXEDSZ NS_QFIXEDSZ -+#define RRFIXEDSZ NS_RRFIXEDSZ -+#define INT32SZ NS_INT32SZ -+#define INT16SZ NS_INT16SZ -+#define INT8SZ NS_INT8SZ -+#define INADDRSZ NS_INADDRSZ -+#define IN6ADDRSZ NS_IN6ADDRSZ -+#define INDIR_MASK NS_CMPRSFLGS -+#define NAMESERVER_PORT NS_DEFAULTPORT -+ -+#define S_ZONE ns_s_zn -+#define S_PREREQ ns_s_pr -+#define S_UPDATE ns_s_ud -+#define S_ADDT ns_s_ar -+ -+#define QUERY ns_o_query -+#define IQUERY ns_o_iquery -+#define STATUS ns_o_status -+#define NS_NOTIFY_OP ns_o_notify -+#define NS_UPDATE_OP ns_o_update -+ -+#define NOERROR ns_r_noerror -+#define FORMERR ns_r_formerr -+#define SERVFAIL ns_r_servfail -+#define NXDOMAIN ns_r_nxdomain -+#define NOTIMP ns_r_notimpl -+#define REFUSED ns_r_refused -+#define YXDOMAIN ns_r_yxdomain -+#define YXRRSET ns_r_yxrrset -+#define NXRRSET ns_r_nxrrset -+#define NOTAUTH ns_r_notauth -+#define NOTZONE ns_r_notzone -+/*#define BADSIG ns_r_badsig*/ -+/*#define BADKEY ns_r_badkey*/ -+/*#define BADTIME ns_r_badtime*/ -+ -+ -+#define DELETE ns_uop_delete -+#define ADD ns_uop_add -+ -+#define T_A ns_t_a -+#define T_NS ns_t_ns -+#define T_MD ns_t_md -+#define T_MF ns_t_mf -+#define T_CNAME ns_t_cname -+#define T_SOA ns_t_soa -+#define T_MB ns_t_mb -+#define T_MG ns_t_mg -+#define T_MR ns_t_mr -+#define T_NULL ns_t_null -+#define T_WKS ns_t_wks -+#define T_PTR ns_t_ptr -+#define T_HINFO ns_t_hinfo -+#define T_MINFO ns_t_minfo -+#define T_MX ns_t_mx -+#define T_TXT ns_t_txt -+#define T_RP ns_t_rp -+#define T_AFSDB ns_t_afsdb -+#define T_X25 ns_t_x25 -+#define T_ISDN ns_t_isdn -+#define T_RT ns_t_rt -+#define T_NSAP ns_t_nsap -+#define T_NSAP_PTR ns_t_nsap_ptr -+#define T_SIG ns_t_sig -+#define T_KEY ns_t_key -+#define T_PX ns_t_px -+#define T_GPOS ns_t_gpos -+#define T_AAAA ns_t_aaaa -+#define T_LOC ns_t_loc -+#define T_NXT ns_t_nxt -+#define T_EID ns_t_eid -+#define T_NIMLOC ns_t_nimloc -+#define T_SRV ns_t_srv -+#define T_ATMA ns_t_atma -+#define T_NAPTR ns_t_naptr -+#define T_A6 ns_t_a6 -+#define T_TSIG ns_t_tsig -+#define T_IXFR ns_t_ixfr -+#define T_AXFR ns_t_axfr -+#define T_MAILB ns_t_mailb -+#define T_MAILA ns_t_maila -+#define T_ANY ns_t_any -+ -+#define C_IN ns_c_in -+#define C_CHAOS ns_c_chaos -+#define C_HS ns_c_hs -+/* BIND_UPDATE */ -+#define C_NONE ns_c_none -+#define C_ANY ns_c_any -+ -+#define GETSHORT NS_GET16 -+#define GETLONG NS_GET32 -+#define PUTSHORT NS_PUT16 -+#define PUTLONG NS_PUT32 -+ -+#endif /* _ARPA_NAMESER_COMPAT_ */ -Index: android-tools-4.2.2+git20130218/core/adbd/backup_service.c -=================================================================== ---- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ android-tools-4.2.2+git20130218/core/adbd/backup_service.c 2013-06-18 17:12:17.000000000 -0300 -@@ -0,0 +1,155 @@ -+/* -+ * Copyright (C) 2011 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 -+#include -+ -+#include "sysdeps.h" -+ -+#define TRACE_TAG TRACE_ADB -+#include "adb.h" -+ -+typedef struct { -+ pid_t pid; -+ int fd; -+} backup_harvest_params; -+ -+// socketpair but do *not* mark as close_on_exec -+static int backup_socketpair(int sv[2]) { -+ int rc = unix_socketpair( AF_UNIX, SOCK_STREAM, 0, sv ); -+ if (rc < 0) -+ return -1; -+ -+ return 0; -+} -+ -+// harvest the child process then close the read end of the socketpair -+static void* backup_child_waiter(void* args) { -+ int status; -+ backup_harvest_params* params = (backup_harvest_params*) args; -+ -+ waitpid(params->pid, &status, 0); -+ adb_close(params->fd); -+ free(params); -+ return NULL; -+} -+ -+/* returns the data socket passing the backup data here for forwarding */ -+int backup_service(BackupOperation op, char* args) { -+ pid_t pid; -+ int s[2]; -+ char* operation; -+ int socketnum; -+ -+ // Command string and choice of stdin/stdout for the pipe depend on our invocation -+ if (op == BACKUP) { -+ operation = "backup"; -+ socketnum = STDOUT_FILENO; -+ } else { -+ operation = "restore"; -+ socketnum = STDIN_FILENO; -+ } -+ -+ D("backup_service(%s, %s)\n", operation, args); -+ -+ // set up the pipe from the subprocess to here -+ // parent will read s[0]; child will write s[1] -+ if (backup_socketpair(s)) { -+ D("can't create backup/restore socketpair\n"); -+ fprintf(stderr, "unable to create backup/restore socketpair\n"); -+ return -1; -+ } -+ -+ D("Backup/restore socket pair: (send=%d, receive=%d)\n", s[1], s[0]); -+ close_on_exec(s[0]); // only the side we hold on to -+ -+ // spin off the child process to run the backup command -+ pid = fork(); -+ if (pid < 0) { -+ // failure -+ D("can't fork for %s\n", operation); -+ fprintf(stderr, "unable to fork for %s\n", operation); -+ adb_close(s[0]); -+ adb_close(s[1]); -+ return -1; -+ } -+ -+ // Great, we're off and running. -+ if (pid == 0) { -+ // child -- actually run the backup here -+ char* p; -+ int argc; -+ char portnum[16]; -+ char** bu_args; -+ -+ // fixed args: [0] is 'bu', [1] is the port number, [2] is the 'operation' string -+ argc = 3; -+ for (p = (char*)args; p && *p; ) { -+ argc++; -+ while (*p && *p != ':') p++; -+ if (*p == ':') p++; -+ } -+ -+ bu_args = (char**) alloca(argc*sizeof(char*) + 1); -+ -+ // run through again to build the argv array -+ argc = 0; -+ bu_args[argc++] = "bu"; -+ snprintf(portnum, sizeof(portnum), "%d", s[1]); -+ bu_args[argc++] = portnum; -+ bu_args[argc++] = operation; -+ for (p = (char*)args; p && *p; ) { -+ bu_args[argc++] = p; -+ while (*p && *p != ':') p++; -+ if (*p == ':') { -+ *p = 0; -+ p++; -+ } -+ } -+ bu_args[argc] = NULL; -+ -+ // Close the half of the socket that we don't care about, route 'bu's console -+ // to the output socket, and off we go -+ adb_close(s[0]); -+ -+ // off we go -+ execvp("/system/bin/bu", (char * const *)bu_args); -+ // oops error - close up shop and go home -+ fprintf(stderr, "Unable to exec 'bu', bailing\n"); -+ exit(-1); -+ } else { -+ adb_thread_t t; -+ backup_harvest_params* params; -+ -+ // parent, i.e. adbd -- close the sending half of the socket -+ D("fork() returned pid %d\n", pid); -+ adb_close(s[1]); -+ -+ // spin a thread to harvest the child process -+ params = (backup_harvest_params*) malloc(sizeof(backup_harvest_params)); -+ params->pid = pid; -+ params->fd = s[0]; -+ if (adb_thread_create(&t, backup_child_waiter, params)) { -+ adb_close(s[0]); -+ free(params); -+ D("Unable to create child harvester\n"); -+ return -1; -+ } -+ } -+ -+ // we'll be reading from s[0] as the data is sent by the child process -+ return s[0]; -+} -Index: android-tools-4.2.2+git20130218/core/adbd/base64.c -=================================================================== ---- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ android-tools-4.2.2+git20130218/core/adbd/base64.c 2013-06-18 17:12:17.000000000 -0300 -@@ -0,0 +1,340 @@ -+/* $NetBSD: base64.c,v 1.8 2002/11/11 01:15:17 thorpej Exp $ */ -+ -+/* -+ * Copyright (c) 1996 by Internet Software Consortium. -+ * -+ * Permission to use, copy, modify, and distribute this software for any -+ * purpose with or without fee is hereby granted, provided that the above -+ * copyright notice and this permission notice appear in all copies. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS -+ * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES -+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE -+ * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL -+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR -+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS -+ * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS -+ * SOFTWARE. -+ */ -+ -+/* -+ * Portions Copyright (c) 1995 by International Business Machines, Inc. -+ * -+ * International Business Machines, Inc. (hereinafter called IBM) grants -+ * permission under its copyrights to use, copy, modify, and distribute this -+ * Software with or without fee, provided that the above copyright notice and -+ * all paragraphs of this notice appear in all copies, and that the name of IBM -+ * not be used in connection with the marketing of any product incorporating -+ * the Software or modifications thereof, without specific, written prior -+ * permission. -+ * -+ * To the extent it has a right to do so, IBM grants an immunity from suit -+ * under its patents, if any, for the use, sale or manufacture of products to -+ * the extent that such products are used for performing Domain Name System -+ * dynamic updates in TCP/IP networks by means of the Software. No immunity is -+ * granted for any product per se or for any other function of any product. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", AND IBM DISCLAIMS ALL WARRANTIES, -+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A -+ * PARTICULAR PURPOSE. IN NO EVENT SHALL IBM BE LIABLE FOR ANY SPECIAL, -+ * DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER ARISING -+ * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE, EVEN -+ * IF IBM IS APPRISED OF THE POSSIBILITY OF SUCH DAMAGES. -+ */ -+ -+#include -+#if defined(LIBC_SCCS) && !defined(lint) -+__RCSID("$NetBSD: base64.c,v 1.8 2002/11/11 01:15:17 thorpej Exp $"); -+#endif /* LIBC_SCCS and not lint */ -+ -+#include -+#include -+#include -+#include -+#include -+#include "arpa_nameser.h" -+ -+#include -+#include -+#ifdef ANDROID_CHANGES -+#include "resolv_private.h" -+#else -+#include -+#endif -+#include -+ -+#include -+#include -+ -+static const char Base64[] = -+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; -+static const char Pad64 = '='; -+ -+/* (From RFC1521 and draft-ietf-dnssec-secext-03.txt) -+ The following encoding technique is taken from RFC 1521 by Borenstein -+ and Freed. It is reproduced here in a slightly edited form for -+ convenience. -+ -+ A 65-character subset of US-ASCII is used, enabling 6 bits to be -+ represented per printable character. (The extra 65th character, "=", -+ is used to signify a special processing function.) -+ -+ The encoding process represents 24-bit groups of input bits as output -+ strings of 4 encoded characters. Proceeding from left to right, a -+ 24-bit input group is formed by concatenating 3 8-bit input groups. -+ These 24 bits are then treated as 4 concatenated 6-bit groups, each -+ of which is translated into a single digit in the base64 alphabet. -+ -+ Each 6-bit group is used as an index into an array of 64 printable -+ characters. The character referenced by the index is placed in the -+ output string. -+ -+ Table 1: The Base64 Alphabet -+ -+ Value Encoding Value Encoding Value Encoding Value Encoding -+ 0 A 17 R 34 i 51 z -+ 1 B 18 S 35 j 52 0 -+ 2 C 19 T 36 k 53 1 -+ 3 D 20 U 37 l 54 2 -+ 4 E 21 V 38 m 55 3 -+ 5 F 22 W 39 n 56 4 -+ 6 G 23 X 40 o 57 5 -+ 7 H 24 Y 41 p 58 6 -+ 8 I 25 Z 42 q 59 7 -+ 9 J 26 a 43 r 60 8 -+ 10 K 27 b 44 s 61 9 -+ 11 L 28 c 45 t 62 + -+ 12 M 29 d 46 u 63 / -+ 13 N 30 e 47 v -+ 14 O 31 f 48 w (pad) = -+ 15 P 32 g 49 x -+ 16 Q 33 h 50 y -+ -+ Special processing is performed if fewer than 24 bits are available -+ at the end of the data being encoded. A full encoding quantum is -+ always completed at the end of a quantity. When fewer than 24 input -+ bits are available in an input group, zero bits are added (on the -+ right) to form an integral number of 6-bit groups. Padding at the -+ end of the data is performed using the '=' character. -+ -+ Since all base64 input is an integral number of octets, only the -+ ------------------------------------------------- -+ following cases can arise: -+ -+ (1) the final quantum of encoding input is an integral -+ multiple of 24 bits; here, the final unit of encoded -+ output will be an integral multiple of 4 characters -+ with no "=" padding, -+ (2) the final quantum of encoding input is exactly 8 bits; -+ here, the final unit of encoded output will be two -+ characters followed by two "=" padding characters, or -+ (3) the final quantum of encoding input is exactly 16 bits; -+ here, the final unit of encoded output will be three -+ characters followed by one "=" padding character. -+ */ -+ -+int -+b64_ntop(src, srclength, target, targsize) -+ u_char const *src; -+ size_t srclength; -+ char *target; -+ size_t targsize; -+{ -+ size_t datalength = 0; -+ u_char input[3] = { 0, 0, 0 }; /* make compiler happy */ -+ u_char output[4]; -+ size_t i; -+ -+ assert(src != NULL); -+ assert(target != NULL); -+ -+ while (2 < srclength) { -+ input[0] = *src++; -+ input[1] = *src++; -+ input[2] = *src++; -+ srclength -= 3; -+ -+ output[0] = (u_int32_t)input[0] >> 2; -+ output[1] = ((u_int32_t)(input[0] & 0x03) << 4) + -+ ((u_int32_t)input[1] >> 4); -+ output[2] = ((u_int32_t)(input[1] & 0x0f) << 2) + -+ ((u_int32_t)input[2] >> 6); -+ output[3] = input[2] & 0x3f; -+ assert(output[0] < 64); -+ assert(output[1] < 64); -+ assert(output[2] < 64); -+ assert(output[3] < 64); -+ -+ if (datalength + 4 > targsize) -+ return (-1); -+ target[datalength++] = Base64[output[0]]; -+ target[datalength++] = Base64[output[1]]; -+ target[datalength++] = Base64[output[2]]; -+ target[datalength++] = Base64[output[3]]; -+ } -+ -+ /* Now we worry about padding. */ -+ if (0 != srclength) { -+ /* Get what's left. */ -+ input[0] = input[1] = input[2] = '\0'; -+ for (i = 0; i < srclength; i++) -+ input[i] = *src++; -+ -+ output[0] = (u_int32_t)input[0] >> 2; -+ output[1] = ((u_int32_t)(input[0] & 0x03) << 4) + -+ ((u_int32_t)input[1] >> 4); -+ output[2] = ((u_int32_t)(input[1] & 0x0f) << 2) + -+ ((u_int32_t)input[2] >> 6); -+ assert(output[0] < 64); -+ assert(output[1] < 64); -+ assert(output[2] < 64); -+ -+ if (datalength + 4 > targsize) -+ return (-1); -+ target[datalength++] = Base64[output[0]]; -+ target[datalength++] = Base64[output[1]]; -+ if (srclength == 1) -+ target[datalength++] = Pad64; -+ else -+ target[datalength++] = Base64[output[2]]; -+ target[datalength++] = Pad64; -+ } -+ if (datalength >= targsize) -+ return (-1); -+ target[datalength] = '\0'; /* Returned value doesn't count \0. */ -+ return (datalength); -+} -+ -+/* skips all whitespace anywhere. -+ converts characters, four at a time, starting at (or after) -+ src from base - 64 numbers into three 8 bit bytes in the target area. -+ it returns the number of data bytes stored at the target, or -1 on error. -+ */ -+ -+int -+b64_pton(src, target, targsize) -+ char const *src; -+ u_char *target; -+ size_t targsize; -+{ -+ size_t tarindex; -+ int state, ch; -+ char *pos; -+ -+ assert(src != NULL); -+ assert(target != NULL); -+ -+ state = 0; -+ tarindex = 0; -+ -+ while ((ch = (u_char) *src++) != '\0') { -+ if (isspace(ch)) /* Skip whitespace anywhere. */ -+ continue; -+ -+ if (ch == Pad64) -+ break; -+ -+ pos = strchr(Base64, ch); -+ if (pos == 0) /* A non-base64 character. */ -+ return (-1); -+ -+ switch (state) { -+ case 0: -+ if (target) { -+ if (tarindex >= targsize) -+ return (-1); -+ target[tarindex] = (pos - Base64) << 2; -+ } -+ state = 1; -+ break; -+ case 1: -+ if (target) { -+ if (tarindex + 1 >= targsize) -+ return (-1); -+ target[tarindex] |= -+ (u_int32_t)(pos - Base64) >> 4; -+ target[tarindex+1] = ((pos - Base64) & 0x0f) -+ << 4 ; -+ } -+ tarindex++; -+ state = 2; -+ break; -+ case 2: -+ if (target) { -+ if (tarindex + 1 >= targsize) -+ return (-1); -+ target[tarindex] |= -+ (u_int32_t)(pos - Base64) >> 2; -+ target[tarindex+1] = ((pos - Base64) & 0x03) -+ << 6; -+ } -+ tarindex++; -+ state = 3; -+ break; -+ case 3: -+ if (target) { -+ if (tarindex >= targsize) -+ return (-1); -+ target[tarindex] |= (pos - Base64); -+ } -+ tarindex++; -+ state = 0; -+ break; -+ default: -+ abort(); -+ } -+ } -+ -+ /* -+ * We are done decoding Base-64 chars. Let's see if we ended -+ * on a byte boundary, and/or with erroneous trailing characters. -+ */ -+ -+ if (ch == Pad64) { /* We got a pad char. */ -+ ch = *src++; /* Skip it, get next. */ -+ switch (state) { -+ case 0: /* Invalid = in first position */ -+ case 1: /* Invalid = in second position */ -+ return (-1); -+ -+ case 2: /* Valid, means one byte of info */ -+ /* Skip any number of spaces. */ -+ for (; ch != '\0'; ch = (u_char) *src++) -+ if (!isspace(ch)) -+ break; -+ /* Make sure there is another trailing = sign. */ -+ if (ch != Pad64) -+ return (-1); -+ ch = *src++; /* Skip the = */ -+ /* Fall through to "single trailing =" case. */ -+ /* FALLTHROUGH */ -+ -+ case 3: /* Valid, means two bytes of info */ -+ /* -+ * We know this char is an =. Is there anything but -+ * whitespace after it? -+ */ -+ for (; ch != '\0'; ch = (u_char) *src++) -+ if (!isspace(ch)) -+ return (-1); -+ -+ /* -+ * Now make sure for cases 2 and 3 that the "extra" -+ * bits that slopped past the last full byte were -+ * zeros. If we don't check them, they become a -+ * subliminal channel. -+ */ -+ if (target && target[tarindex] != 0) -+ return (-1); -+ } -+ } else { -+ /* -+ * We ended by seeing the end of the string. Make sure we -+ * have no partial bytes lying around. -+ */ -+ if (state != 0) -+ return (-1); -+ } -+ -+ return (tarindex); -+} -Index: android-tools-4.2.2+git20130218/core/adbd/commandline.c -=================================================================== ---- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ android-tools-4.2.2+git20130218/core/adbd/commandline.c 2013-06-18 17:12:17.000000000 -0300 -@@ -0,0 +1,1743 @@ -+/* -+ * 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 -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include "sysdeps.h" -+ -+#ifdef HAVE_TERMIO_H -+#include -+#endif -+ -+#define TRACE_TAG TRACE_ADB -+#include "adb.h" -+#include "adb_client.h" -+#include "file_sync_service.h" -+ -+static int do_cmd(transport_type ttype, char* serial, char *cmd, ...); -+ -+void get_my_path(char *s, size_t maxLen); -+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; -+extern int gListenAll; -+ -+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" -+ " -a - directs adb to listen on all interfaces for a connection\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 - directs command to the device or emulator with the given\n" -+ " serial number or qualifier. Overrides ANDROID_SERIAL\n" -+ " environment variable.\n" -+ " -p - 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" -+ " -H - Name of adb server host (default: localhost)\n" -+ " -P - Port of adb server (default: 5037)\n" -+ " devices [-l] - list all connected devices\n" -+ " ('-l' will also list device qualifiers)\n" -+ " connect [:] - connect to a device via TCP/IP\n" -+ " Port 5555 is used by default if no port number is specified.\n" -+ " disconnect [[:]] - disconnect from a TCP/IP device.\n" -+ " Port 5555 is used by default if no port number is specified.\n" -+ " Using this command with no additional arguments\n" -+ " will disconnect from all connected TCP/IP devices.\n" -+ "\n" -+ "device commands:\n" -+ " adb push - copy file/dir to device\n" -+ " adb pull [] - copy file/dir from device\n" -+ " adb sync [ ] - copy host->device only if changed\n" -+ " (-l means list but don't copy)\n" -+ " (see 'adb help all')\n" -+ " adb shell - run remote shell interactively\n" -+ " adb shell - run remote shell command\n" -+ " adb emu - run emulator console command\n" -+ " adb logcat [ ] - View device log\n" -+ " adb forward --list - list all forward socket connections.\n" -+ " the format is a list of lines with the following format:\n" -+ " \" \" \" \" \"\\n\"\n" -+ " adb forward - forward socket connections\n" -+ " forward specs are one of: \n" -+ " tcp:\n" -+ " localabstract:\n" -+ " localreserved:\n" -+ " localfilesystem:\n" -+ " dev:\n" -+ " jdwp: (remote only)\n" -+ " adb forward --no-rebind \n" -+ " - same as 'adb forward ' but fails\n" -+ " if is already forwarded\n" -+ " adb forward --remove - remove a specific forward socket connection\n" -+ " adb forward --remove-all - remove all forward socket connections\n" -+ " adb jdwp - list PIDs of processes hosting a JDWP transport\n" -+ " adb install [-l] [-r] [-s] [--algo --key --iv ] \n" -+ " - 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" -+ " ('-s' means install on SD card instead of internal storage)\n" -+ " ('--algo', '--key', and '--iv' mean the file is encrypted already)\n" -+ " adb uninstall [-k] - 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 backup [-f ] [-apk|-noapk] [-shared|-noshared] [-all] [-system|-nosystem] []\n" -+ " - write an archive of the device's data to .\n" -+ " If no -f option is supplied then the data is written\n" -+ " to \"backup.ab\" in the current directory.\n" -+ " (-apk|-noapk enable/disable backup of the .apks themselves\n" -+ " in the archive; the default is noapk.)\n" -+ " (-shared|-noshared enable/disable backup of the device's\n" -+ " shared storage / SD card contents; the default is noshared.)\n" -+ " (-all means to back up all installed applications)\n" -+ " (-system|-nosystem toggles whether -all automatically includes\n" -+ " system applications; the default is to include system apps)\n" -+ " ( is the list of applications to be backed up. If\n" -+ " the -all or -shared flags are passed, then the package\n" -+ " list is optional. Applications explicitly given on the\n" -+ " command line will be included even if -nosystem would\n" -+ " ordinarily cause them to be omitted.)\n" -+ "\n" -+ " adb restore - restore device contents from the backup archive\n" -+ "\n" -+ " adb help - show this help message\n" -+ " adb version - show version num\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: \n" -+ " adb get-devpath - prints: \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" -+ " adb reboot [bootloader|recovery] - reboots the device, optionally into the bootloader or recovery program\n" -+ " adb reboot-bootloader - reboots the device into the bootloader\n" -+ " adb root - restarts the adbd daemon with root permissions\n" -+ " adb usb - restarts the adbd daemon listening on USB\n" -+ " adb tcpip - restarts the adbd daemon listening on TCP on the specified port" -+ "\n" -+ "networking:\n" -+ " adb ppp [parameters] - Run PPP over USB.\n" -+ " Note: you should not automatically start a PPP connection.\n" -+ " 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 [ ]\n" -+ " can be interpreted in several ways:\n" -+ "\n" -+ " - If 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" -+ "\n" -+ "environmental variables:\n" -+ " ADB_TRACE - Print debug information. A comma separated list of the following values\n" -+ " 1 or all, adb, sockets, packets, rwx, usb, sync, sysdeps, transport, jdwp\n" -+ " ANDROID_SERIAL - The serial number to connect to. -s takes priority over this if given.\n" -+ " ANDROID_LOG_TAGS - When used with the logcat option, only these debug tags are printed.\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) { -+ D("read_and_dump(): pre adb_read(fd=%d)\n", fd); -+ len = adb_read(fd, buf, 4096); -+ D("read_and_dump(): post adb_read(fd=%d): len=%d\n", fd, len); -+ if(len == 0) { -+ break; -+ } -+ -+ if(len < 0) { -+ if(errno == EINTR) continue; -+ break; -+ } -+ fwrite(buf, 1, len, stdout); -+ fflush(stdout); -+ } -+} -+ -+static void copy_to_file(int inFd, int outFd) { -+ const size_t BUFSIZE = 32 * 1024; -+ char* buf = (char*) malloc(BUFSIZE); -+ int len; -+ long total = 0; -+ -+ D("copy_to_file(%d -> %d)\n", inFd, outFd); -+ for (;;) { -+ len = adb_read(inFd, buf, BUFSIZE); -+ if (len == 0) { -+ D("copy_to_file() : read 0 bytes; exiting\n"); -+ break; -+ } -+ if (len < 0) { -+ if (errno == EINTR) { -+ D("copy_to_file() : EINTR, retrying\n"); -+ continue; -+ } -+ D("copy_to_file() : error %d\n", errno); -+ break; -+ } -+ adb_write(outFd, buf, len); -+ total += len; -+ } -+ D("copy_to_file() finished after %lu bytes\n", total); -+ free(buf); -+} -+ -+static void *stdin_read_thread(void *x) -+{ -+ int fd, fdi; -+ unsigned char buf[1024]; -+ int r, n; -+ int state = 0; -+ -+ int *fds = (int*) x; -+ fd = fds[0]; -+ fdi = fds[1]; -+ free(fds); -+ -+ for(;;) { -+ /* fdi is really the client's stdin, so use read, not adb_read here */ -+ D("stdin_read_thread(): pre unix_read(fdi=%d,...)\n", fdi); -+ r = unix_read(fdi, buf, 1024); -+ D("stdin_read_thread(): post unix_read(fdi=%d,...)\n", fdi); -+ if(r == 0) break; -+ if(r < 0) { -+ if(errno == EINTR) continue; -+ break; -+ } -+ for(n = 0; n < r; n++){ -+ switch(buf[n]) { -+ case '\n': -+ 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: -+ state = 0; -+ } -+ } -+ r = adb_write(fd, buf, r); -+ if(r <= 0) { -+ break; -+ } -+ } -+ 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); -+ } -+} -+ -+int adb_download_buffer(const char *service, const void* data, int sz, -+ unsigned progress) -+{ -+ char buf[4096]; -+ unsigned total; -+ int fd; -+ const unsigned char *ptr; -+ -+ sprintf(buf,"%s:%d", service, sz); -+ fd = adb_connect(buf); -+ if(fd < 0) { -+ fprintf(stderr,"error: %s\n", adb_error()); -+ return -1; -+ } -+ -+ int opt = CHUNK_SIZE; -+ opt = setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &opt, sizeof(opt)); -+ -+ total = sz; -+ ptr = data; -+ -+ if(progress) { -+ char *x = strrchr(service, ':'); -+ if(x) service = x + 1; -+ } -+ -+ while(sz > 0) { -+ unsigned xfer = (sz > CHUNK_SIZE) ? CHUNK_SIZE : sz; -+ if(writex(fd, ptr, xfer)) { -+ adb_status(fd); -+ fprintf(stderr,"* failed to write data '%s' *\n", adb_error()); -+ return -1; -+ } -+ sz -= xfer; -+ ptr += xfer; -+ if(progress) { -+ printf("sending: '%s' %4d%% \r", service, (int)(100LL - ((100LL * sz) / (total)))); -+ fflush(stdout); -+ } -+ } -+ if(progress) { -+ printf("\n"); -+ } -+ -+ if(readx(fd, buf, 4)){ -+ fprintf(stderr,"* error reading response *\n"); -+ adb_close(fd); -+ return -1; -+ } -+ if(memcmp(buf, "OKAY", 4)) { -+ buf[4] = 0; -+ fprintf(stderr,"* error response '%s' *\n", buf); -+ adb_close(fd); -+ return -1; -+ } -+ -+ adb_close(fd); -+ return 0; -+} -+ -+ -+int adb_download(const char *service, const char *fn, unsigned progress) -+{ -+ void *data; -+ unsigned sz; -+ -+ data = load_file(fn, &sz); -+ if(data == 0) { -+ fprintf(stderr,"* cannot read '%s' *\n", service); -+ return -1; -+ } -+ -+ int status = adb_download_buffer(service, data, sz, progress); -+ free(data); -+ return status; -+} -+ -+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 -+ * -+ */ -+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 [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); -+ -+ if (!strcmp(argv[0],"longcat")) { -+ strncat(buf, " -v long", sizeof(buf)-1); -+ } -+ -+ 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; -+} -+ -+static int mkdirs(char *path) -+{ -+ int ret; -+ char *x = path + 1; -+ -+ for(;;) { -+ x = adb_dirstart(x); -+ if(x == 0) return 0; -+ *x = 0; -+ ret = adb_mkdir(path, 0775); -+ *x = OS_PATH_SEPARATOR; -+ if((ret < 0) && (errno != EEXIST)) { -+ return ret; -+ } -+ x++; -+ } -+ return 0; -+} -+ -+static int backup(int argc, char** argv) { -+ char buf[4096]; -+ char default_name[32]; -+ const char* filename = strcpy(default_name, "./backup.ab"); -+ int fd, outFd; -+ int i, j; -+ -+ /* find, extract, and use any -f argument */ -+ for (i = 1; i < argc; i++) { -+ if (!strcmp("-f", argv[i])) { -+ if (i == argc-1) { -+ fprintf(stderr, "adb: -f passed with no filename\n"); -+ return usage(); -+ } -+ filename = argv[i+1]; -+ for (j = i+2; j <= argc; ) { -+ argv[i++] = argv[j++]; -+ } -+ argc -= 2; -+ argv[argc] = NULL; -+ } -+ } -+ -+ /* bare "adb backup" or "adb backup -f filename" are not valid invocations */ -+ if (argc < 2) return usage(); -+ -+ adb_unlink(filename); -+ mkdirs((char *)filename); -+ outFd = adb_creat(filename, 0640); -+ if (outFd < 0) { -+ fprintf(stderr, "adb: unable to open file %s\n", filename); -+ return -1; -+ } -+ -+ snprintf(buf, sizeof(buf), "backup"); -+ for (argc--, argv++; argc; argc--, argv++) { -+ strncat(buf, ":", sizeof(buf) - strlen(buf) - 1); -+ strncat(buf, argv[0], sizeof(buf) - strlen(buf) - 1); -+ } -+ -+ D("backup. filename=%s buf=%s\n", filename, buf); -+ fd = adb_connect(buf); -+ if (fd < 0) { -+ fprintf(stderr, "adb: unable to connect for backup\n"); -+ adb_close(outFd); -+ return -1; -+ } -+ -+ printf("Now unlock your device and confirm the backup operation.\n"); -+ copy_to_file(fd, outFd); -+ -+ adb_close(fd); -+ adb_close(outFd); -+ return 0; -+} -+ -+static int restore(int argc, char** argv) { -+ const char* filename; -+ int fd, tarFd; -+ -+ if (argc != 2) return usage(); -+ -+ filename = argv[1]; -+ tarFd = adb_open(filename, O_RDONLY); -+ if (tarFd < 0) { -+ fprintf(stderr, "adb: unable to open file %s\n", filename); -+ return -1; -+ } -+ -+ fd = adb_connect("restore:"); -+ if (fd < 0) { -+ fprintf(stderr, "adb: unable to connect for backup\n"); -+ adb_close(tarFd); -+ return -1; -+ } -+ -+ printf("Now unlock your device and confirm the restore operation.\n"); -+ copy_to_file(tarFd, fd); -+ -+ adb_close(fd); -+ adb_close(tarFd); -+ 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, PATH_MAX); -+ top = find_top_from(dir, path_buf); -+ } -+ return top; -+} -+ -+/* 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 , 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 is_server = 0; -+ int persist = 0; -+ int r; -+ int quote; -+ transport_type ttype = kTransportAny; -+ char* serial = NULL; -+ char* server_port_str = 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 -+ -+ serial = getenv("ANDROID_SERIAL"); -+ -+ /* Validate and assign the server port */ -+ server_port_str = getenv("ANDROID_ADB_SERVER_PORT"); -+ int server_port = DEFAULT_ADB_PORT; -+ if (server_port_str && strlen(server_port_str) > 0) { -+ server_port = (int) strtol(server_port_str, NULL, 0); -+ if (server_port <= 0 || server_port > 65535) { -+ fprintf(stderr, -+ "adb: Env var ANDROID_ADB_SERVER_PORT must be a positive number less than 65535. Got \"%s\"\n", -+ server_port_str); -+ return usage(); -+ } -+ } -+ -+ /* modifiers and flags */ -+ while(argc > 0) { -+ if(!strcmp(argv[0],"server")) { -+ is_server = 1; -+ } else 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[0] + 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 || argv[0][2] != '\0') return usage(); -+ serial = argv[1]; -+ argc--; -+ argv++; -+ } -+ } else if (!strcmp(argv[0],"-d")) { -+ ttype = kTransportUsb; -+ } else if (!strcmp(argv[0],"-e")) { -+ ttype = kTransportLocal; -+ } else if (!strcmp(argv[0],"-a")) { -+ gListenAll = 1; -+ } else if(!strncmp(argv[0], "-H", 2)) { -+ const char *hostname = NULL; -+ if (argv[0][2] == '\0') { -+ if (argc < 2) return usage(); -+ hostname = argv[1]; -+ argc--; -+ argv++; -+ } else { -+ hostname = argv[0] + 2; -+ } -+ adb_set_tcp_name(hostname); -+ -+ } else if(!strncmp(argv[0], "-P", 2)) { -+ if (argv[0][2] == '\0') { -+ if (argc < 2) return usage(); -+ server_port_str = argv[1]; -+ argc--; -+ argv++; -+ } else { -+ server_port_str = argv[0] + 2; -+ } -+ if (strlen(server_port_str) > 0) { -+ server_port = (int) strtol(server_port_str, NULL, 0); -+ if (server_port <= 0 || server_port > 65535) { -+ fprintf(stderr, -+ "adb: port number must be a positive number less than 65536. Got \"%s\"\n", -+ server_port_str); -+ return usage(); -+ } -+ } else { -+ fprintf(stderr, -+ "adb: port number must be a positive number less than 65536. Got empty string.\n"); -+ return usage(); -+ } -+ } else { -+ /* out of recognized modifiers and flags */ -+ break; -+ } -+ argc--; -+ argv++; -+ } -+ -+ adb_set_transport(ttype, serial); -+ adb_set_tcp_specifics(server_port); -+ -+ if (is_server) { -+ if (no_daemon || is_daemon) { -+ r = adb_main(is_daemon, server_port); -+ } else { -+ r = launch_server(server_port); -+ } -+ 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; -+ char *listopt; -+ if (argc < 2) -+ listopt = ""; -+ else if (argc == 2 && !strcmp(argv[1], "-l")) -+ listopt = argv[1]; -+ else { -+ fprintf(stderr, "Usage: adb devices [-l]\n"); -+ return 1; -+ } -+ snprintf(buf, sizeof buf, "host:%s%s", argv[0], listopt); -+ 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], "connect")) { -+ char *tmp; -+ if (argc != 2) { -+ fprintf(stderr, "Usage: adb connect [:]\n"); -+ return 1; -+ } -+ snprintf(buf, sizeof buf, "host:connect:%s", argv[1]); -+ tmp = adb_query(buf); -+ if(tmp) { -+ printf("%s\n", tmp); -+ return 0; -+ } else { -+ return 1; -+ } -+ } -+ -+ if(!strcmp(argv[0], "disconnect")) { -+ char *tmp; -+ if (argc > 2) { -+ fprintf(stderr, "Usage: adb disconnect [[:]]\n"); -+ return 1; -+ } -+ if (argc == 2) { -+ snprintf(buf, sizeof buf, "host:disconnect:%s", argv[1]); -+ } else { -+ snprintf(buf, sizeof buf, "host:disconnect:"); -+ } -+ tmp = adb_query(buf); -+ if(tmp) { -+ 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") || !strcmp(argv[0], "hell")) { -+ int r; -+ int fd; -+ -+ char h = (argv[0][0] == 'h'); -+ -+ if (h) { -+ printf("\x1b[41;33m"); -+ fflush(stdout); -+ } -+ -+ if(argc < 2) { -+ D("starting interactive shell\n"); -+ r = interactive_shell(); -+ if (h) { -+ printf("\x1b[0m"); -+ fflush(stdout); -+ } -+ return r; -+ } -+ -+ 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(;;) { -+ D("interactive shell loop. buff=%s\n", buf); -+ fd = adb_connect(buf); -+ if(fd >= 0) { -+ D("about to read_and_dump(fd=%d)\n", fd); -+ read_and_dump(fd); -+ D("read_and_dump() done.\n"); -+ 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 { -+ if (h) { -+ printf("\x1b[0m"); -+ fflush(stdout); -+ } -+ D("interactive shell loop. return r=%d\n", r); -+ 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], "sideload")) { -+ if(argc != 2) return usage(); -+ if(adb_download("sideload", argv[1], 1)) { -+ return 1; -+ } else { -+ return 0; -+ } -+ } -+ -+ if(!strcmp(argv[0], "remount") || !strcmp(argv[0], "reboot") -+ || !strcmp(argv[0], "reboot-bootloader") -+ || !strcmp(argv[0], "tcpip") || !strcmp(argv[0], "usb") -+ || !strcmp(argv[0], "root")) { -+ char command[100]; -+ if (!strcmp(argv[0], "reboot-bootloader")) -+ snprintf(command, sizeof(command), "reboot:bootloader"); -+ else if (argc > 1) -+ snprintf(command, sizeof(command), "%s:%s", argv[0], argv[1]); -+ else -+ snprintf(command, sizeof(command), "%s:", argv[0]); -+ int fd = adb_connect(command); -+ 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 usage(); -+ do_cmd(ttype, serial, "shell", "bugreport", 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")) { -+ char host_prefix[64]; -+ char remove = 0; -+ char remove_all = 0; -+ char list = 0; -+ char no_rebind = 0; -+ -+ // Parse options here. -+ while (argc > 1 && argv[1][0] == '-') { -+ if (!strcmp(argv[1], "--list")) -+ list = 1; -+ else if (!strcmp(argv[1], "--remove")) -+ remove = 1; -+ else if (!strcmp(argv[1], "--remove-all")) -+ remove_all = 1; -+ else if (!strcmp(argv[1], "--no-rebind")) -+ no_rebind = 1; -+ else { -+ return usage(); -+ } -+ argc--; -+ argv++; -+ } -+ -+ // Ensure we can only use one option at a time. -+ if (list + remove + remove_all + no_rebind > 1) { -+ return usage(); -+ } -+ -+ // Determine the for this command. -+ if (serial) { -+ snprintf(host_prefix, sizeof host_prefix, "host-serial:%s", -+ serial); -+ } else if (ttype == kTransportUsb) { -+ snprintf(host_prefix, sizeof host_prefix, "host-usb"); -+ } else if (ttype == kTransportLocal) { -+ snprintf(host_prefix, sizeof host_prefix, "host-local"); -+ } else { -+ snprintf(host_prefix, sizeof host_prefix, "host"); -+ } -+ -+ // Implement forward --list -+ if (list) { -+ if (argc != 1) -+ return usage(); -+ snprintf(buf, sizeof buf, "%s:list-forward", host_prefix); -+ char* forwards = adb_query(buf); -+ if (forwards == NULL) { -+ fprintf(stderr, "error: %s\n", adb_error()); -+ return 1; -+ } -+ printf("%s", forwards); -+ free(forwards); -+ return 0; -+ } -+ -+ // Implement forward --remove-all -+ else if (remove_all) { -+ if (argc != 1) -+ return usage(); -+ snprintf(buf, sizeof buf, "%s:killforward-all", host_prefix); -+ } -+ -+ // Implement forward --remove -+ else if (remove) { -+ if (argc != 2) -+ return usage(); -+ snprintf(buf, sizeof buf, "%s:killforward:%s", host_prefix, argv[1]); -+ } -+ // Or implement one of: -+ // forward -+ // forward --no-rebind -+ else -+ { -+ if (argc != 3) -+ return usage(); -+ const char* command = no_rebind ? "forward:norebind:" : "forward"; -+ snprintf(buf, sizeof buf, "%s:%s:%s;%s", host_prefix, command, 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 == 2) { -+ return do_sync_pull(argv[1], "."); -+ } else if (argc == 3) { -+ return do_sync_pull(argv[1], argv[2]); -+ } else { -+ return usage(); -+ } -+ } -+ -+ 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 listonly = 0; -+ -+ int ret; -+ if(argc < 2) { -+ /* No local path was specified. */ -+ srcarg = NULL; -+ } else if (argc >= 2 && strcmp(argv[1], "-l") == 0) { -+ listonly = 1; -+ if (argc == 3) { -+ srcarg = argv[2]; -+ } else { -+ 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", listonly); -+ if(ret == 0 && data_srcpath != NULL) -+ ret = do_sync_sync(data_srcpath, "/data", listonly); -+ -+ free(android_srcpath); -+ free(data_srcpath); -+ return ret; -+ } -+ -+ /* passthrough commands */ -+ -+ if(!strcmp(argv[0],"get-state") || -+ !strcmp(argv[0],"get-serialno") || -+ !strcmp(argv[0],"get-devpath")) -+ { -+ 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") || !strcmp(argv[0],"longcat")) { -+ 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], "backup")) { -+ return backup(argc, argv); -+ } -+ -+ if (!strcmp(argv[0], "restore")) { -+ return restore(argc, argv); -+ } -+ -+ 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; -+} -+ -+static const char* get_basename(const char* filename) -+{ -+ const char* basename = adb_dirstop(filename); -+ if (basename) { -+ basename++; -+ return basename; -+ } else { -+ return filename; -+ } -+} -+ -+static int check_file(const char* filename) -+{ -+ struct stat st; -+ -+ if (filename == NULL) { -+ return 0; -+ } -+ -+ if (stat(filename, &st) != 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; -+ } -+ -+ return 0; -+} -+ -+int install_app(transport_type transport, char* serial, int argc, char** argv) -+{ -+ static const char *const DATA_DEST = "/data/local/tmp/%s"; -+ static const char *const SD_DEST = "/sdcard/tmp/%s"; -+ const char* where = DATA_DEST; -+ char apk_dest[PATH_MAX]; -+ char verification_dest[PATH_MAX]; -+ char* apk_file; -+ char* verification_file = NULL; -+ int file_arg = -1; -+ int err; -+ int i; -+ int verify_apk = 1; -+ -+ for (i = 1; i < argc; i++) { -+ if (*argv[i] != '-') { -+ file_arg = i; -+ break; -+ } else if (!strcmp(argv[i], "-i")) { -+ // Skip the installer package name. -+ i++; -+ } else if (!strcmp(argv[i], "-s")) { -+ where = SD_DEST; -+ } else if (!strcmp(argv[i], "--algo")) { -+ verify_apk = 0; -+ i++; -+ } else if (!strcmp(argv[i], "--iv")) { -+ verify_apk = 0; -+ i++; -+ } else if (!strcmp(argv[i], "--key")) { -+ verify_apk = 0; -+ i++; -+ } -+ } -+ -+ if (file_arg < 0) { -+ fprintf(stderr, "can't find filename in arguments\n"); -+ return 1; -+ } else if (file_arg + 2 < argc) { -+ fprintf(stderr, "too many files specified; only takes APK file and verifier file\n"); -+ return 1; -+ } -+ -+ apk_file = argv[file_arg]; -+ -+ if (file_arg != argc - 1) { -+ verification_file = argv[file_arg + 1]; -+ } -+ -+ if (check_file(apk_file) || check_file(verification_file)) { -+ return 1; -+ } -+ -+ snprintf(apk_dest, sizeof apk_dest, where, get_basename(apk_file)); -+ if (verification_file != NULL) { -+ snprintf(verification_dest, sizeof(verification_dest), where, get_basename(verification_file)); -+ -+ if (!strcmp(apk_dest, verification_dest)) { -+ fprintf(stderr, "APK and verification file can't have the same name\n"); -+ return 1; -+ } -+ } -+ -+ err = do_sync_push(apk_file, apk_dest, verify_apk); -+ if (err) { -+ goto cleanup_apk; -+ } else { -+ argv[file_arg] = apk_dest; /* destination name, not source location */ -+ } -+ -+ if (verification_file != NULL) { -+ err = do_sync_push(verification_file, verification_dest, 0 /* no verify APK */); -+ if (err) { -+ goto cleanup_apk; -+ } else { -+ argv[file_arg + 1] = verification_dest; /* destination name, not source location */ -+ } -+ } -+ -+ pm_command(transport, serial, argc, argv); -+ -+cleanup_apk: -+ if (verification_file != NULL) { -+ delete_file(transport, serial, verification_dest); -+ } -+ -+ delete_file(transport, serial, apk_dest); -+ -+ return err; -+} -Index: android-tools-4.2.2+git20130218/core/adbd/console.c -=================================================================== ---- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ android-tools-4.2.2+git20130218/core/adbd/console.c 2013-06-18 17:12:17.000000000 -0300 -@@ -0,0 +1,45 @@ -+#include "sysdeps.h" -+#include "adb.h" -+#include "adb_client.h" -+#include -+ -+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; -+} -Index: android-tools-4.2.2+git20130218/core/adbd/fdevent.c -=================================================================== ---- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ android-tools-4.2.2+git20130218/core/adbd/fdevent.c 2013-06-18 17:12:17.000000000 -0300 -@@ -0,0 +1,695 @@ -+/* http://frotznet.googlecode.com/svn/trunk/utils/fdevent.c -+** -+** Copyright 2006, Brian Swetland -+** -+** 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 -+ -+#include -+#include -+#include -+#include -+#include -+ -+#include -+ -+#include -+#include -+ -+#include "fdevent.h" -+#include "transport.h" -+#include "sysdeps.h" -+ -+ -+/* !!! Do not enable DEBUG for the adb that will run as the server: -+** both stdout and stderr are used to communicate between the client -+** and server. Any extra output will cause failures. -+*/ -+#define DEBUG 0 /* non-0 will break adb server */ -+ -+// This socket is used when a subproc shell service exists. -+// It wakes up the fdevent_loop() and cause the correct handling -+// of the shell's pseudo-tty master. I.e. force close it. -+int SHELL_EXIT_NOTIFY_FD = -1; -+ -+static void fatal(const char *fn, const char *fmt, ...) -+{ -+ va_list ap; -+ va_start(ap, fmt); -+ fprintf(stderr, "%s:", fn); -+ vfprintf(stderr, fmt, ap); -+ va_end(ap); -+ abort(); -+} -+ -+#define FATAL(x...) fatal(__FUNCTION__, x) -+ -+#if DEBUG -+#define D(...) \ -+ do { \ -+ adb_mutex_lock(&D_lock); \ -+ int save_errno = errno; \ -+ fprintf(stderr, "%s::%s():", __FILE__, __FUNCTION__); \ -+ errno = save_errno; \ -+ fprintf(stderr, __VA_ARGS__); \ -+ adb_mutex_unlock(&D_lock); \ -+ errno = save_errno; \ -+ } while(0) -+static void dump_fde(fdevent *fde, const char *info) -+{ -+ adb_mutex_lock(&D_lock); -+ fprintf(stderr,"FDE #%03d %c%c%c %s\n", fde->fd, -+ fde->state & FDE_READ ? 'R' : ' ', -+ fde->state & FDE_WRITE ? 'W' : ' ', -+ fde->state & FDE_ERROR ? 'E' : ' ', -+ info); -+ adb_mutex_unlock(&D_lock); -+} -+#else -+#define D(...) ((void)0) -+#define dump_fde(fde, info) do { } while(0) -+#endif -+ -+#define FDE_EVENTMASK 0x00ff -+#define FDE_STATEMASK 0xff00 -+ -+#define FDE_ACTIVE 0x0100 -+#define FDE_PENDING 0x0200 -+#define FDE_CREATED 0x0400 -+ -+static void fdevent_plist_enqueue(fdevent *node); -+static void fdevent_plist_remove(fdevent *node); -+static fdevent *fdevent_plist_dequeue(void); -+static void fdevent_subproc_event_func(int fd, unsigned events, void *userdata); -+ -+static fdevent list_pending = { -+ .next = &list_pending, -+ .prev = &list_pending, -+}; -+ -+static fdevent **fd_table = 0; -+static int fd_table_max = 0; -+ -+#ifdef CRAPTASTIC -+//HAVE_EPOLL -+ -+#include -+ -+static int epoll_fd = -1; -+ -+static void fdevent_init() -+{ -+ /* XXX: what's a good size for the passed in hint? */ -+ epoll_fd = epoll_create(256); -+ -+ if(epoll_fd < 0) { -+ perror("epoll_create() failed"); -+ exit(1); -+ } -+ -+ /* mark for close-on-exec */ -+ fcntl(epoll_fd, F_SETFD, FD_CLOEXEC); -+} -+ -+static void fdevent_connect(fdevent *fde) -+{ -+ struct epoll_event ev; -+ -+ memset(&ev, 0, sizeof(ev)); -+ ev.events = 0; -+ ev.data.ptr = fde; -+ -+#if 0 -+ if(epoll_ctl(epoll_fd, EPOLL_CTL_ADD, fde->fd, &ev)) { -+ perror("epoll_ctl() failed\n"); -+ exit(1); -+ } -+#endif -+} -+ -+static void fdevent_disconnect(fdevent *fde) -+{ -+ struct epoll_event ev; -+ -+ memset(&ev, 0, sizeof(ev)); -+ ev.events = 0; -+ ev.data.ptr = fde; -+ -+ /* technically we only need to delete if we -+ ** were actively monitoring events, but let's -+ ** be aggressive and do it anyway, just in case -+ ** something's out of sync -+ */ -+ epoll_ctl(epoll_fd, EPOLL_CTL_DEL, fde->fd, &ev); -+} -+ -+static void fdevent_update(fdevent *fde, unsigned events) -+{ -+ struct epoll_event ev; -+ int active; -+ -+ active = (fde->state & FDE_EVENTMASK) != 0; -+ -+ memset(&ev, 0, sizeof(ev)); -+ ev.events = 0; -+ ev.data.ptr = fde; -+ -+ if(events & FDE_READ) ev.events |= EPOLLIN; -+ if(events & FDE_WRITE) ev.events |= EPOLLOUT; -+ if(events & FDE_ERROR) ev.events |= (EPOLLERR | EPOLLHUP); -+ -+ fde->state = (fde->state & FDE_STATEMASK) | events; -+ -+ if(active) { -+ /* we're already active. if we're changing to *no* -+ ** events being monitored, we need to delete, otherwise -+ ** we need to just modify -+ */ -+ if(ev.events) { -+ if(epoll_ctl(epoll_fd, EPOLL_CTL_MOD, fde->fd, &ev)) { -+ perror("epoll_ctl() failed\n"); -+ exit(1); -+ } -+ } else { -+ if(epoll_ctl(epoll_fd, EPOLL_CTL_DEL, fde->fd, &ev)) { -+ perror("epoll_ctl() failed\n"); -+ exit(1); -+ } -+ } -+ } else { -+ /* we're not active. if we're watching events, we need -+ ** to add, otherwise we can just do nothing -+ */ -+ if(ev.events) { -+ if(epoll_ctl(epoll_fd, EPOLL_CTL_ADD, fde->fd, &ev)) { -+ perror("epoll_ctl() failed\n"); -+ exit(1); -+ } -+ } -+ } -+} -+ -+static void fdevent_process() -+{ -+ struct epoll_event events[256]; -+ fdevent *fde; -+ int i, n; -+ -+ n = epoll_wait(epoll_fd, events, 256, -1); -+ -+ if(n < 0) { -+ if(errno == EINTR) return; -+ perror("epoll_wait"); -+ exit(1); -+ } -+ -+ for(i = 0; i < n; i++) { -+ struct epoll_event *ev = events + i; -+ fde = ev->data.ptr; -+ -+ if(ev->events & EPOLLIN) { -+ fde->events |= FDE_READ; -+ } -+ if(ev->events & EPOLLOUT) { -+ fde->events |= FDE_WRITE; -+ } -+ if(ev->events & (EPOLLERR | EPOLLHUP)) { -+ fde->events |= FDE_ERROR; -+ } -+ if(fde->events) { -+ if(fde->state & FDE_PENDING) continue; -+ fde->state |= FDE_PENDING; -+ fdevent_plist_enqueue(fde); -+ } -+ } -+} -+ -+#else /* USE_SELECT */ -+ -+#ifdef HAVE_WINSOCK -+#include -+#else -+#include -+#endif -+ -+static fd_set read_fds; -+static fd_set write_fds; -+static fd_set error_fds; -+ -+static int select_n = 0; -+ -+static void fdevent_init(void) -+{ -+ FD_ZERO(&read_fds); -+ FD_ZERO(&write_fds); -+ FD_ZERO(&error_fds); -+} -+ -+static void fdevent_connect(fdevent *fde) -+{ -+ if(fde->fd >= select_n) { -+ select_n = fde->fd + 1; -+ } -+} -+ -+static void fdevent_disconnect(fdevent *fde) -+{ -+ int i, n; -+ -+ FD_CLR(fde->fd, &read_fds); -+ FD_CLR(fde->fd, &write_fds); -+ FD_CLR(fde->fd, &error_fds); -+ -+ for(n = 0, i = 0; i < select_n; i++) { -+ if(fd_table[i] != 0) n = i; -+ } -+ select_n = n + 1; -+} -+ -+static void fdevent_update(fdevent *fde, unsigned events) -+{ -+ if(events & FDE_READ) { -+ FD_SET(fde->fd, &read_fds); -+ } else { -+ FD_CLR(fde->fd, &read_fds); -+ } -+ if(events & FDE_WRITE) { -+ FD_SET(fde->fd, &write_fds); -+ } else { -+ FD_CLR(fde->fd, &write_fds); -+ } -+ if(events & FDE_ERROR) { -+ FD_SET(fde->fd, &error_fds); -+ } else { -+ FD_CLR(fde->fd, &error_fds); -+ } -+ -+ fde->state = (fde->state & FDE_STATEMASK) | events; -+} -+ -+/* Looks at fd_table[] for bad FDs and sets bit in fds. -+** Returns the number of bad FDs. -+*/ -+static int fdevent_fd_check(fd_set *fds) -+{ -+ int i, n = 0; -+ fdevent *fde; -+ -+ for(i = 0; i < select_n; i++) { -+ fde = fd_table[i]; -+ if(fde == 0) continue; -+ if(fcntl(i, F_GETFL, NULL) < 0) { -+ FD_SET(i, fds); -+ n++; -+ // fde->state |= FDE_DONT_CLOSE; -+ -+ } -+ } -+ return n; -+} -+ -+#if !DEBUG -+static inline void dump_all_fds(const char *extra_msg) {} -+#else -+static void dump_all_fds(const char *extra_msg) -+{ -+int i; -+ fdevent *fde; -+ // per fd: 4 digits (but really: log10(FD_SETSIZE)), 1 staus, 1 blank -+ char msg_buff[FD_SETSIZE*6 + 1], *pb=msg_buff; -+ size_t max_chars = FD_SETSIZE * 6 + 1; -+ int printed_out; -+#define SAFE_SPRINTF(...) \ -+ do { \ -+ printed_out = snprintf(pb, max_chars, __VA_ARGS__); \ -+ if (printed_out <= 0) { \ -+ D("... snprintf failed.\n"); \ -+ return; \ -+ } \ -+ if (max_chars < (unsigned int)printed_out) { \ -+ D("... snprintf out of space.\n"); \ -+ return; \ -+ } \ -+ pb += printed_out; \ -+ max_chars -= printed_out; \ -+ } while(0) -+ -+ for(i = 0; i < select_n; i++) { -+ fde = fd_table[i]; -+ SAFE_SPRINTF("%d", i); -+ if(fde == 0) { -+ SAFE_SPRINTF("? "); -+ continue; -+ } -+ if(fcntl(i, F_GETFL, NULL) < 0) { -+ SAFE_SPRINTF("b"); -+ } -+ SAFE_SPRINTF(" "); -+ } -+ D("%s fd_table[]->fd = {%s}\n", extra_msg, msg_buff); -+} -+#endif -+ -+static void fdevent_process() -+{ -+ int i, n; -+ fdevent *fde; -+ unsigned events; -+ fd_set rfd, wfd, efd; -+ -+ memcpy(&rfd, &read_fds, sizeof(fd_set)); -+ memcpy(&wfd, &write_fds, sizeof(fd_set)); -+ memcpy(&efd, &error_fds, sizeof(fd_set)); -+ -+ dump_all_fds("pre select()"); -+ -+ n = select(select_n, &rfd, &wfd, &efd, NULL); -+ int saved_errno = errno; -+ D("select() returned n=%d, errno=%d\n", n, n<0?saved_errno:0); -+ -+ dump_all_fds("post select()"); -+ -+ if(n < 0) { -+ switch(saved_errno) { -+ case EINTR: return; -+ case EBADF: -+ // Can't trust the FD sets after an error. -+ FD_ZERO(&wfd); -+ FD_ZERO(&efd); -+ FD_ZERO(&rfd); -+ break; -+ default: -+ D("Unexpected select() error=%d\n", saved_errno); -+ return; -+ } -+ } -+ if(n <= 0) { -+ // We fake a read, as the rest of the code assumes -+ // that errors will be detected at that point. -+ n = fdevent_fd_check(&rfd); -+ } -+ -+ for(i = 0; (i < select_n) && (n > 0); i++) { -+ events = 0; -+ if(FD_ISSET(i, &rfd)) { events |= FDE_READ; n--; } -+ if(FD_ISSET(i, &wfd)) { events |= FDE_WRITE; n--; } -+ if(FD_ISSET(i, &efd)) { events |= FDE_ERROR; n--; } -+ -+ if(events) { -+ fde = fd_table[i]; -+ if(fde == 0) -+ FATAL("missing fde for fd %d\n", i); -+ -+ fde->events |= events; -+ -+ D("got events fde->fd=%d events=%04x, state=%04x\n", -+ fde->fd, fde->events, fde->state); -+ if(fde->state & FDE_PENDING) continue; -+ fde->state |= FDE_PENDING; -+ fdevent_plist_enqueue(fde); -+ } -+ } -+} -+ -+#endif -+ -+static void fdevent_register(fdevent *fde) -+{ -+ if(fde->fd < 0) { -+ FATAL("bogus negative fd (%d)\n", fde->fd); -+ } -+ -+ if(fde->fd >= fd_table_max) { -+ int oldmax = fd_table_max; -+ if(fde->fd > 32000) { -+ FATAL("bogus huuuuge fd (%d)\n", fde->fd); -+ } -+ if(fd_table_max == 0) { -+ fdevent_init(); -+ fd_table_max = 256; -+ } -+ while(fd_table_max <= fde->fd) { -+ fd_table_max *= 2; -+ } -+ fd_table = realloc(fd_table, sizeof(fdevent*) * fd_table_max); -+ if(fd_table == 0) { -+ FATAL("could not expand fd_table to %d entries\n", fd_table_max); -+ } -+ memset(fd_table + oldmax, 0, sizeof(int) * (fd_table_max - oldmax)); -+ } -+ -+ fd_table[fde->fd] = fde; -+} -+ -+static void fdevent_unregister(fdevent *fde) -+{ -+ if((fde->fd < 0) || (fde->fd >= fd_table_max)) { -+ FATAL("fd out of range (%d)\n", fde->fd); -+ } -+ -+ if(fd_table[fde->fd] != fde) { -+ FATAL("fd_table out of sync [%d]\n", fde->fd); -+ } -+ -+ fd_table[fde->fd] = 0; -+ -+ if(!(fde->state & FDE_DONT_CLOSE)) { -+ dump_fde(fde, "close"); -+ adb_close(fde->fd); -+ } -+} -+ -+static void fdevent_plist_enqueue(fdevent *node) -+{ -+ fdevent *list = &list_pending; -+ -+ node->next = list; -+ node->prev = list->prev; -+ node->prev->next = node; -+ list->prev = node; -+} -+ -+static void fdevent_plist_remove(fdevent *node) -+{ -+ node->prev->next = node->next; -+ node->next->prev = node->prev; -+ node->next = 0; -+ node->prev = 0; -+} -+ -+static fdevent *fdevent_plist_dequeue(void) -+{ -+ fdevent *list = &list_pending; -+ fdevent *node = list->next; -+ -+ if(node == list) return 0; -+ -+ list->next = node->next; -+ list->next->prev = list; -+ node->next = 0; -+ node->prev = 0; -+ -+ return node; -+} -+ -+static void fdevent_call_fdfunc(fdevent* fde) -+{ -+ unsigned events = fde->events; -+ fde->events = 0; -+ if(!(fde->state & FDE_PENDING)) return; -+ fde->state &= (~FDE_PENDING); -+ dump_fde(fde, "callback"); -+ fde->func(fde->fd, events, fde->arg); -+} -+ -+static void fdevent_subproc_event_func(int fd, unsigned ev, void *userdata) -+{ -+ -+ D("subproc handling on fd=%d ev=%04x\n", fd, ev); -+ -+ // Hook oneself back into the fde's suitable for select() on read. -+ if((fd < 0) || (fd >= fd_table_max)) { -+ FATAL("fd %d out of range for fd_table \n", fd); -+ } -+ fdevent *fde = fd_table[fd]; -+ fdevent_add(fde, FDE_READ); -+ -+ if(ev & FDE_READ){ -+ int subproc_fd; -+ -+ if(readx(fd, &subproc_fd, sizeof(subproc_fd))) { -+ FATAL("Failed to read the subproc's fd from fd=%d\n", fd); -+ } -+ if((subproc_fd < 0) || (subproc_fd >= fd_table_max)) { -+ D("subproc_fd %d out of range 0, fd_table_max=%d\n", -+ subproc_fd, fd_table_max); -+ return; -+ } -+ fdevent *subproc_fde = fd_table[subproc_fd]; -+ if(!subproc_fde) { -+ D("subproc_fd %d cleared from fd_table\n", subproc_fd); -+ return; -+ } -+ if(subproc_fde->fd != subproc_fd) { -+ // Already reallocated? -+ D("subproc_fd %d != fd_table[].fd %d\n", subproc_fd, subproc_fde->fd); -+ return; -+ } -+ -+ subproc_fde->force_eof = 1; -+ -+ int rcount = 0; -+ ioctl(subproc_fd, FIONREAD, &rcount); -+ D("subproc with fd=%d has rcount=%d err=%d\n", -+ subproc_fd, rcount, errno); -+ -+ if(rcount) { -+ // If there is data left, it will show up in the select(). -+ // This works because there is no other thread reading that -+ // data when in this fd_func(). -+ return; -+ } -+ -+ D("subproc_fde.state=%04x\n", subproc_fde->state); -+ subproc_fde->events |= FDE_READ; -+ if(subproc_fde->state & FDE_PENDING) { -+ return; -+ } -+ subproc_fde->state |= FDE_PENDING; -+ fdevent_call_fdfunc(subproc_fde); -+ } -+} -+ -+fdevent *fdevent_create(int fd, fd_func func, void *arg) -+{ -+ fdevent *fde = (fdevent*) malloc(sizeof(fdevent)); -+ if(fde == 0) return 0; -+ fdevent_install(fde, fd, func, arg); -+ fde->state |= FDE_CREATED; -+ return fde; -+} -+ -+void fdevent_destroy(fdevent *fde) -+{ -+ if(fde == 0) return; -+ if(!(fde->state & FDE_CREATED)) { -+ FATAL("fde %p not created by fdevent_create()\n", fde); -+ } -+ fdevent_remove(fde); -+} -+ -+void fdevent_install(fdevent *fde, int fd, fd_func func, void *arg) -+{ -+ memset(fde, 0, sizeof(fdevent)); -+ fde->state = FDE_ACTIVE; -+ fde->fd = fd; -+ fde->force_eof = 0; -+ fde->func = func; -+ fde->arg = arg; -+ -+#ifndef HAVE_WINSOCK -+ fcntl(fd, F_SETFL, O_NONBLOCK); -+#endif -+ fdevent_register(fde); -+ dump_fde(fde, "connect"); -+ fdevent_connect(fde); -+ fde->state |= FDE_ACTIVE; -+} -+ -+void fdevent_remove(fdevent *fde) -+{ -+ if(fde->state & FDE_PENDING) { -+ fdevent_plist_remove(fde); -+ } -+ -+ if(fde->state & FDE_ACTIVE) { -+ fdevent_disconnect(fde); -+ dump_fde(fde, "disconnect"); -+ fdevent_unregister(fde); -+ } -+ -+ fde->state = 0; -+ fde->events = 0; -+} -+ -+ -+void fdevent_set(fdevent *fde, unsigned events) -+{ -+ events &= FDE_EVENTMASK; -+ -+ if((fde->state & FDE_EVENTMASK) == events) return; -+ -+ if(fde->state & FDE_ACTIVE) { -+ fdevent_update(fde, events); -+ dump_fde(fde, "update"); -+ } -+ -+ fde->state = (fde->state & FDE_STATEMASK) | events; -+ -+ if(fde->state & FDE_PENDING) { -+ /* if we're pending, make sure -+ ** we don't signal an event that -+ ** is no longer wanted. -+ */ -+ fde->events &= (~events); -+ if(fde->events == 0) { -+ fdevent_plist_remove(fde); -+ fde->state &= (~FDE_PENDING); -+ } -+ } -+} -+ -+void fdevent_add(fdevent *fde, unsigned events) -+{ -+ fdevent_set( -+ fde, (fde->state & FDE_EVENTMASK) | (events & FDE_EVENTMASK)); -+} -+ -+void fdevent_del(fdevent *fde, unsigned events) -+{ -+ fdevent_set( -+ fde, (fde->state & FDE_EVENTMASK) & (~(events & FDE_EVENTMASK))); -+} -+ -+void fdevent_subproc_setup() -+{ -+ int s[2]; -+ -+ if(adb_socketpair(s)) { -+ FATAL("cannot create shell-exit socket-pair\n"); -+ } -+ SHELL_EXIT_NOTIFY_FD = s[0]; -+ fdevent *fde; -+ fde = fdevent_create(s[1], fdevent_subproc_event_func, NULL); -+ if(!fde) -+ FATAL("cannot create fdevent for shell-exit handler\n"); -+ fdevent_add(fde, FDE_READ); -+} -+ -+void fdevent_loop() -+{ -+ fdevent *fde; -+ fdevent_subproc_setup(); -+ -+ for(;;) { -+ D("--- ---- waiting for events\n"); -+ -+ fdevent_process(); -+ -+ while((fde = fdevent_plist_dequeue())) { -+ fdevent_call_fdfunc(fde); -+ } -+ } -+} -Index: android-tools-4.2.2+git20130218/core/adbd/fdevent.h -=================================================================== ---- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ android-tools-4.2.2+git20130218/core/adbd/fdevent.h 2013-06-18 17:12:17.000000000 -0300 -@@ -0,0 +1,83 @@ -+/* -+ * Copyright (C) 2006 The Android Open Source Project -+ * -+ * Licensed under the Apache License, Version 2.0 (the "License"); -+ * you may not use this file except in compliance with the License. -+ * You may obtain a copy of the License at -+ * -+ * http://www.apache.org/licenses/LICENSE-2.0 -+ * -+ * Unless required by applicable law or agreed to in writing, software -+ * distributed under the License is distributed on an "AS IS" BASIS, -+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -+ * See the License for the specific language governing permissions and -+ * limitations under the License. -+ */ -+ -+#ifndef __FDEVENT_H -+#define __FDEVENT_H -+ -+#include /* for int64_t */ -+ -+/* events that may be observed */ -+#define FDE_READ 0x0001 -+#define FDE_WRITE 0x0002 -+#define FDE_ERROR 0x0004 -+#define FDE_TIMEOUT 0x0008 -+ -+/* features that may be set (via the events set/add/del interface) */ -+#define FDE_DONT_CLOSE 0x0080 -+ -+typedef struct fdevent fdevent; -+ -+typedef void (*fd_func)(int fd, unsigned events, void *userdata); -+ -+/* Allocate and initialize a new fdevent object -+ * Note: use FD_TIMER as 'fd' to create a fd-less object -+ * (used to implement timers). -+*/ -+fdevent *fdevent_create(int fd, fd_func func, void *arg); -+ -+/* Uninitialize and deallocate an fdevent object that was -+** created by fdevent_create() -+*/ -+void fdevent_destroy(fdevent *fde); -+ -+/* Initialize an fdevent object that was externally allocated -+*/ -+void fdevent_install(fdevent *fde, int fd, fd_func func, void *arg); -+ -+/* Uninitialize an fdevent object that was initialized by -+** fdevent_install() -+*/ -+void fdevent_remove(fdevent *item); -+ -+/* Change which events should cause notifications -+*/ -+void fdevent_set(fdevent *fde, unsigned events); -+void fdevent_add(fdevent *fde, unsigned events); -+void fdevent_del(fdevent *fde, unsigned events); -+ -+void fdevent_set_timeout(fdevent *fde, int64_t timeout_ms); -+ -+/* loop forever, handling events. -+*/ -+void fdevent_loop(); -+ -+struct fdevent -+{ -+ fdevent *next; -+ fdevent *prev; -+ -+ int fd; -+ int force_eof; -+ -+ unsigned short state; -+ unsigned short events; -+ -+ fd_func func; -+ void *arg; -+}; -+ -+ -+#endif -Index: android-tools-4.2.2+git20130218/core/adbd/file_sync_client.c -=================================================================== ---- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ android-tools-4.2.2+git20130218/core/adbd/file_sync_client.c 2013-06-18 17:12:17.000000000 -0300 -@@ -0,0 +1,1024 @@ -+/* -+ * 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 -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#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 (%lld bytes in %lld.%03llds)\n", -+ ((((long long) total_bytes) * 1000000LL) / t) / 1024LL, -+ (long long) 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)) { -+ fprintf(stderr,"cannot stat '%s': %s\n", ci->src, strerror(errno)); -+ closedir(d); -+ -+ 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, int listonly) -+{ -+ 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,"%spush: %s -> %s\n", listonly ? "would " : "", ci->src, ci->dst); -+ if(!listonly && -+ 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, 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_ISLNK(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, int listonly) -+{ -+ 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, listonly)){ -+ return 1; -+ } else { -+ END(); -+ sync_quit(fd); -+ return 0; -+ } -+} -Index: android-tools-4.2.2+git20130218/core/adbd/file_sync_service.c -=================================================================== ---- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ android-tools-4.2.2+git20130218/core/adbd/file_sync_service.c 2013-06-18 17:12:17.000000000 -0300 -@@ -0,0 +1,414 @@ -+/* -+ * 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 -+#include -+#include -+ -+#include -+#include -+#include -+#include -+ -+#include -+ -+#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)) { -+ int saved_errno = errno; -+ adb_close(fd); -+ adb_unlink(path); -+ fd = -1; -+ errno = saved_errno; -+ 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); -+} -Index: android-tools-4.2.2+git20130218/core/adbd/file_sync_service.h -=================================================================== ---- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ android-tools-4.2.2+git20130218/core/adbd/file_sync_service.h 2013-06-18 17:12:17.000000000 -0300 -@@ -0,0 +1,87 @@ -+/* -+ * 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 HAVE_BIG_ENDIAN -+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 listonly); -+int do_sync_pull(const char *rpath, const char *lpath); -+ -+#define SYNC_DATA_MAX (64*1024) -+ -+#endif -Index: android-tools-4.2.2+git20130218/core/adbd/framebuffer_service.c -=================================================================== ---- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ android-tools-4.2.2+git20130218/core/adbd/framebuffer_service.c 2013-06-18 17:12:17.000000000 -0300 -@@ -0,0 +1,180 @@ -+/* -+ * 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 -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include "fdevent.h" -+#include "adb.h" -+ -+#include -+#include -+#include -+ -+/* TODO: -+** - sync with vsync to avoid tearing -+*/ -+/* This version number defines the format of the fbinfo struct. -+ It must match versioning in ddms where this data is consumed. */ -+#define DDMS_RAWIMAGE_VERSION 1 -+struct fbinfo { -+ unsigned int version; -+ unsigned int bpp; -+ unsigned int size; -+ unsigned int width; -+ unsigned int height; -+ unsigned int red_offset; -+ unsigned int red_length; -+ unsigned int blue_offset; -+ unsigned int blue_length; -+ unsigned int green_offset; -+ unsigned int green_length; -+ unsigned int alpha_offset; -+ unsigned int alpha_length; -+} __attribute__((packed)); -+ -+void framebuffer_service(int fd, void *cookie) -+{ -+ struct fbinfo fbinfo; -+ unsigned int i; -+ char buf[640]; -+ int fd_screencap; -+ int w, h, f; -+ int fds[2]; -+ -+ if (pipe(fds) < 0) goto done; -+ -+ pid_t pid = fork(); -+ if (pid < 0) goto done; -+ -+ if (pid == 0) { -+ dup2(fds[1], STDOUT_FILENO); -+ close(fds[0]); -+ close(fds[1]); -+ const char* command = "screencap"; -+ const char *args[2] = {command, NULL}; -+ execvp(command, (char**)args); -+ exit(1); -+ } -+ -+ fd_screencap = fds[0]; -+ -+ /* read w, h & format */ -+ if(readx(fd_screencap, &w, 4)) goto done; -+ if(readx(fd_screencap, &h, 4)) goto done; -+ if(readx(fd_screencap, &f, 4)) goto done; -+ -+ fbinfo.version = DDMS_RAWIMAGE_VERSION; -+ /* see hardware/hardware.h */ -+ switch (f) { -+ case 1: /* RGBA_8888 */ -+ fbinfo.bpp = 32; -+ fbinfo.size = w * h * 4; -+ fbinfo.width = w; -+ fbinfo.height = h; -+ fbinfo.red_offset = 0; -+ fbinfo.red_length = 8; -+ fbinfo.green_offset = 8; -+ fbinfo.green_length = 8; -+ fbinfo.blue_offset = 16; -+ fbinfo.blue_length = 8; -+ fbinfo.alpha_offset = 24; -+ fbinfo.alpha_length = 8; -+ break; -+ case 2: /* RGBX_8888 */ -+ fbinfo.bpp = 32; -+ fbinfo.size = w * h * 4; -+ fbinfo.width = w; -+ fbinfo.height = h; -+ fbinfo.red_offset = 0; -+ fbinfo.red_length = 8; -+ fbinfo.green_offset = 8; -+ fbinfo.green_length = 8; -+ fbinfo.blue_offset = 16; -+ fbinfo.blue_length = 8; -+ fbinfo.alpha_offset = 24; -+ fbinfo.alpha_length = 0; -+ break; -+ case 3: /* RGB_888 */ -+ fbinfo.bpp = 24; -+ fbinfo.size = w * h * 3; -+ fbinfo.width = w; -+ fbinfo.height = h; -+ fbinfo.red_offset = 0; -+ fbinfo.red_length = 8; -+ fbinfo.green_offset = 8; -+ fbinfo.green_length = 8; -+ fbinfo.blue_offset = 16; -+ fbinfo.blue_length = 8; -+ fbinfo.alpha_offset = 24; -+ fbinfo.alpha_length = 0; -+ break; -+ case 4: /* RGB_565 */ -+ fbinfo.bpp = 16; -+ fbinfo.size = w * h * 2; -+ fbinfo.width = w; -+ fbinfo.height = h; -+ fbinfo.red_offset = 11; -+ fbinfo.red_length = 5; -+ fbinfo.green_offset = 5; -+ fbinfo.green_length = 6; -+ fbinfo.blue_offset = 0; -+ fbinfo.blue_length = 5; -+ fbinfo.alpha_offset = 0; -+ fbinfo.alpha_length = 0; -+ break; -+ case 5: /* BGRA_8888 */ -+ fbinfo.bpp = 32; -+ fbinfo.size = w * h * 4; -+ fbinfo.width = w; -+ fbinfo.height = h; -+ fbinfo.red_offset = 16; -+ fbinfo.red_length = 8; -+ fbinfo.green_offset = 8; -+ fbinfo.green_length = 8; -+ fbinfo.blue_offset = 0; -+ fbinfo.blue_length = 8; -+ fbinfo.alpha_offset = 24; -+ fbinfo.alpha_length = 8; -+ break; -+ default: -+ goto done; -+ } -+ -+ /* write header */ -+ if(writex(fd, &fbinfo, sizeof(fbinfo))) goto done; -+ -+ /* write data */ -+ for(i = 0; i < fbinfo.size; i += sizeof(buf)) { -+ if(readx(fd_screencap, buf, sizeof(buf))) goto done; -+ if(writex(fd, buf, sizeof(buf))) goto done; -+ } -+ if(readx(fd_screencap, buf, fbinfo.size % sizeof(buf))) goto done; -+ if(writex(fd, buf, fbinfo.size % sizeof(buf))) goto done; -+ -+done: -+ TEMP_FAILURE_RETRY(waitpid(pid, NULL, 0)); -+ -+ close(fds[0]); -+ close(fds[1]); -+ close(fd); -+} -Index: android-tools-4.2.2+git20130218/core/adbd/get_my_path_darwin.c -=================================================================== ---- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ android-tools-4.2.2+git20130218/core/adbd/get_my_path_darwin.c 2013-06-18 17:12:17.000000000 -0300 -@@ -0,0 +1,30 @@ -+/* -+ * 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. -+ */ -+ -+#import -+#include -+ -+void get_my_path(char *s, size_t maxLen) -+{ -+ ProcessSerialNumber psn; -+ GetCurrentProcess(&psn); -+ CFDictionaryRef dict; -+ dict = ProcessInformationCopyDictionary(&psn, 0xffffffff); -+ CFStringRef value = (CFStringRef)CFDictionaryGetValue(dict, -+ CFSTR("CFBundleExecutable")); -+ CFStringGetCString(value, s, maxLen, kCFStringEncodingUTF8); -+} -+ -Index: android-tools-4.2.2+git20130218/core/adbd/get_my_path_freebsd.c -=================================================================== ---- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ android-tools-4.2.2+git20130218/core/adbd/get_my_path_freebsd.c 2013-06-18 17:12:17.000000000 -0300 -@@ -0,0 +1,36 @@ -+/* -+ * Copyright (C) 2009 bsdroid project -+ * Alexey Tarasov -+ * -+ * 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 -+#include -+#include -+#include -+ -+void -+get_my_path(char *exe, size_t maxLen) -+{ -+ char proc[64]; -+ -+ snprintf(proc, sizeof(proc), "/proc/%d/file", getpid()); -+ -+ int err = readlink(proc, exe, maxLen - 1); -+ -+ exe[err > 0 ? err : 0] = '\0'; -+} -+ -Index: android-tools-4.2.2+git20130218/core/adbd/get_my_path_linux.c -=================================================================== ---- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ android-tools-4.2.2+git20130218/core/adbd/get_my_path_linux.c 2013-06-18 17:12:17.000000000 -0300 -@@ -0,0 +1,33 @@ -+/* -+ * 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 -+#include -+#include -+#include -+ -+void get_my_path(char *exe, size_t maxLen) -+{ -+ char proc[64]; -+ snprintf(proc, sizeof proc, "/proc/%d/exe", getpid()); -+ int err = readlink(proc, exe, maxLen - 1); -+ if(err > 0) { -+ exe[err] = '\0'; -+ } else { -+ exe[0] = '\0'; -+ } -+} -+ -Index: android-tools-4.2.2+git20130218/core/adbd/get_my_path_windows.c -=================================================================== ---- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ android-tools-4.2.2+git20130218/core/adbd/get_my_path_windows.c 2013-06-18 17:12:17.000000000 -0300 -@@ -0,0 +1,34 @@ -+/* -+ * 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 -+#include -+#include -+ -+void get_my_path(char *exe, size_t maxLen) -+{ -+ char *r; -+ -+ /* XXX: should be GetModuleFileNameA */ -+ if (GetModuleFileName(NULL, exe, maxLen) > 0) { -+ r = strrchr(exe, '\\'); -+ if (r != NULL) -+ *r = '\0'; -+ } else { -+ exe[0] = '\0'; -+ } -+} -+ -Index: android-tools-4.2.2+git20130218/core/adbd/jdwp_service.c -=================================================================== ---- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ android-tools-4.2.2+git20130218/core/adbd/jdwp_service.c 2013-06-18 17:12:17.000000000 -0300 -@@ -0,0 +1,735 @@ -+/* implement the "debug-ports" and "track-debug-ports" device services */ -+#include "sysdeps.h" -+#define TRACE_TAG TRACE_JDWP -+#include "adb.h" -+#include -+#include -+#include -+#include -+ -+/* 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 | -+ | | -+ | | -+ -+ 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: jdwp:" -+ -+ "jdwp:" 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 -+#include -+ -+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) { -+ adb_shutdown(proc->socket); -+ 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)]; -+ int flags; -+ -+ 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; -+ -+ flags = fcntl(proc->socket,F_GETFL,0); -+ -+ if (flags == -1) { -+ D("failed to get cntl flags for socket %d: %s\n", -+ proc->pid, strerror(errno)); -+ goto CloseProcess; -+ -+ } -+ -+ if (fcntl(proc->socket, F_SETFL, flags & ~O_NONBLOCK) == -1) { -+ D("failed to remove O_NONBLOCK flag for socket %d: %s\n", -+ proc->pid, strerror(errno)); -+ goto CloseProcess; -+ } -+ -+ for (;;) { -+ ret = sendmsg(proc->socket, &msg, 0); -+ if (ret >= 0) { -+ adb_close(fd); -+ 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 (fcntl(proc->socket, F_SETFL, flags) == -1) { -+ D("failed to set O_NONBLOCK flag for socket %d: %s\n", -+ proc->pid, strerror(errno)); -+ goto CloseProcess; -+ } -+ -+ 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); -+ close_on_exec(s); -+ -+ 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 */ -+ -Index: android-tools-4.2.2+git20130218/core/adbd/log_service.c -=================================================================== ---- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ android-tools-4.2.2+git20130218/core/adbd/log_service.c 2013-06-18 17:12:17.000000000 -0300 -@@ -0,0 +1,92 @@ -+/* -+ * 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 -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#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); -+} -Index: android-tools-4.2.2+git20130218/core/adbd/mutex_list.h -=================================================================== ---- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ android-tools-4.2.2+git20130218/core/adbd/mutex_list.h 2013-06-18 17:12:17.000000000 -0300 -@@ -0,0 +1,26 @@ -+/* the list of mutexes used by adb */ -+/* #ifndef __MUTEX_LIST_H -+ * Do not use an include-guard. This file is included once to declare the locks -+ * and once in win32 to actually do the runtime initialization. -+ */ -+#ifndef ADB_MUTEX -+#error ADB_MUTEX not defined when including this file -+#endif -+ADB_MUTEX(dns_lock) -+ADB_MUTEX(socket_list_lock) -+ADB_MUTEX(transport_lock) -+#if ADB_HOST -+ADB_MUTEX(local_transports_lock) -+#endif -+ADB_MUTEX(usb_lock) -+ -+// Sadly logging to /data/adb/adb-... is not thread safe. -+// After modifying adb.h::D() to count invocations: -+// DEBUG(jpa):0:Handling main() -+// DEBUG(jpa):1:[ usb_init - starting thread ] -+// (Oopsies, no :2:, and matching message is also gone.) -+// DEBUG(jpa):3:[ usb_thread - opening device ] -+// DEBUG(jpa):4:jdwp control socket started (10) -+ADB_MUTEX(D_lock) -+ -+#undef ADB_MUTEX -Index: android-tools-4.2.2+git20130218/core/adbd/qemu_pipe.h -=================================================================== ---- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ android-tools-4.2.2+git20130218/core/adbd/qemu_pipe.h 2013-06-18 17:12:17.000000000 -0300 -@@ -0,0 +1,91 @@ -+/* -+ * Copyright (C) 2011 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 ANDROID_INCLUDE_HARDWARE_QEMU_PIPE_H -+#define ANDROID_INCLUDE_HARDWARE_QEMU_PIPE_H -+ -+#include -+#include -+#include -+#include -+#include /* for pthread_once() */ -+#include -+#include -+#include -+ -+#ifndef D -+# define D(...) do{}while(0) -+#endif -+ -+/* Try to open a new Qemu fast-pipe. This function returns a file descriptor -+ * that can be used to communicate with a named service managed by the -+ * emulator. -+ * -+ * This file descriptor can be used as a standard pipe/socket descriptor. -+ * -+ * 'pipeName' is the name of the emulator service you want to connect to. -+ * E.g. 'opengles' or 'camera'. -+ * -+ * On success, return a valid file descriptor -+ * Returns -1 on error, and errno gives the error code, e.g.: -+ * -+ * EINVAL -> unknown/unsupported pipeName -+ * ENOSYS -> fast pipes not available in this system. -+ * -+ * ENOSYS should never happen, except if you're trying to run within a -+ * misconfigured emulator. -+ * -+ * You should be able to open several pipes to the same pipe service, -+ * except for a few special cases (e.g. GSM modem), where EBUSY will be -+ * returned if more than one client tries to connect to it. -+ */ -+static __inline__ int -+qemu_pipe_open(const char* pipeName) -+{ -+ char buff[256]; -+ int buffLen; -+ int fd, ret; -+ -+ if (pipeName == NULL || pipeName[0] == '\0') { -+ errno = EINVAL; -+ return -1; -+ } -+ -+ snprintf(buff, sizeof buff, "pipe:%s", pipeName); -+ -+ fd = open("/dev/qemu_pipe", O_RDWR); -+ if (fd < 0) { -+ D("%s: Could not open /dev/qemu_pipe: %s", __FUNCTION__, strerror(errno)); -+ //errno = ENOSYS; -+ return -1; -+ } -+ -+ buffLen = strlen(buff); -+ -+ ret = TEMP_FAILURE_RETRY(write(fd, buff, buffLen+1)); -+ if (ret != buffLen+1) { -+ D("%s: Could not connect to %s pipe service: %s", __FUNCTION__, pipeName, strerror(errno)); -+ if (ret == 0) { -+ errno = ECONNRESET; -+ } else if (ret > 0) { -+ errno = EINVAL; -+ } -+ return -1; -+ } -+ -+ return fd; -+} -+ -+#endif /* ANDROID_INCLUDE_HARDWARE_QEMUD_PIPE_H */ -Index: android-tools-4.2.2+git20130218/core/adbd/remount_service.c -=================================================================== ---- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ android-tools-4.2.2+git20130218/core/adbd/remount_service.c 2013-06-18 17:12:17.000000000 -0300 -@@ -0,0 +1,111 @@ -+/* -+ * 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 -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include "sysdeps.h" -+ -+#define TRACE_TAG TRACE_ADB -+#include "adb.h" -+ -+ -+static int system_ro = 1; -+ -+/* Returns the device used to mount a directory in /proc/mounts */ -+static char *find_mount(const char *dir) -+{ -+ int fd; -+ int res; -+ int size; -+ char *token = NULL; -+ const char delims[] = "\n"; -+ char buf[4096]; -+ -+ fd = unix_open("/proc/mounts", O_RDONLY); -+ if (fd < 0) -+ return NULL; -+ -+ buf[sizeof(buf) - 1] = '\0'; -+ size = adb_read(fd, buf, sizeof(buf) - 1); -+ adb_close(fd); -+ -+ token = strtok(buf, delims); -+ -+ while (token) { -+ char mount_dev[256]; -+ char mount_dir[256]; -+ int mount_freq; -+ int mount_passno; -+ -+ res = sscanf(token, "%255s %255s %*s %*s %d %d\n", -+ mount_dev, mount_dir, &mount_freq, &mount_passno); -+ mount_dev[255] = 0; -+ mount_dir[255] = 0; -+ if (res == 4 && (strcmp(dir, mount_dir) == 0)) -+ return strdup(mount_dev); -+ -+ token = strtok(NULL, delims); -+ } -+ return NULL; -+} -+ -+/* Init mounts /system as read only, remount to enable writes. */ -+static int remount_system() -+{ -+ char *dev; -+ -+ if (system_ro == 0) { -+ return 0; -+ } -+ -+ dev = find_mount("/system"); -+ -+ if (!dev) -+ return -1; -+ -+ system_ro = mount(dev, "/system", "none", MS_REMOUNT, NULL); -+ -+ free(dev); -+ -+ 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); -+} -+ -Index: android-tools-4.2.2+git20130218/core/adbd/services.c -=================================================================== ---- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ android-tools-4.2.2+git20130218/core/adbd/services.c 2013-06-19 02:41:32.583408302 -0300 -@@ -0,0 +1,568 @@ -+/* -+ * 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 -+#include -+#include -+#include -+#include -+#include -+ -+#include "sysdeps.h" -+ -+#define TRACE_TAG TRACE_SERVICES -+#include "adb.h" -+#include "file_sync_service.h" -+ -+#if ADB_HOST -+# ifndef HAVE_WINSOCK -+# include -+# include -+# include -+# endif -+#else -+# include -+#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); -+ free(cookie); -+ 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); -+} -+ -+void restart_root_service(int fd, void *cookie) -+{ -+ char buf[100]; -+ char value[PROPERTY_VALUE_MAX]; -+ -+ if (getuid() == 0) { -+ snprintf(buf, sizeof(buf), "adbd is already running as root\n"); -+ writex(fd, buf, strlen(buf)); -+ adb_close(fd); -+ } else { -+ //property_get("ro.debuggable", value, ""); -+ if (strcmp(value, "1") != 0) { -+ snprintf(buf, sizeof(buf), "adbd cannot run as root in production builds\n"); -+ writex(fd, buf, strlen(buf)); -+ adb_close(fd); -+ return; -+ } -+ -+ //property_set("service.adb.root", "1"); -+ snprintf(buf, sizeof(buf), "restarting adbd as root\n"); -+ writex(fd, buf, strlen(buf)); -+ adb_close(fd); -+ } -+} -+ -+void restart_tcp_service(int fd, void *cookie) -+{ -+ char buf[100]; -+ char value[PROPERTY_VALUE_MAX]; -+ int port = (int)cookie; -+ -+ if (port <= 0) { -+ snprintf(buf, sizeof(buf), "invalid port\n"); -+ writex(fd, buf, strlen(buf)); -+ adb_close(fd); -+ return; -+ } -+ -+ snprintf(value, sizeof(value), "%d", port); -+ //property_set("service.adb.tcp.port", value); -+ snprintf(buf, sizeof(buf), "restarting in TCP mode port: %d\n", port); -+ writex(fd, buf, strlen(buf)); -+ adb_close(fd); -+} -+ -+void restart_usb_service(int fd, void *cookie) -+{ -+ char buf[100]; -+ -+ //property_set("service.adb.tcp.port", "0"); -+ snprintf(buf, sizeof(buf), "restarting in USB mode\n"); -+ writex(fd, buf, strlen(buf)); -+ adb_close(fd); -+} -+ -+void reboot_service(int fd, void *arg) -+{ -+ char buf[100]; -+ int pid, ret; -+ -+ sync(); -+ -+ /* Attempt to unmount the SD card first. -+ * No need to bother checking for errors. -+ */ -+ pid = fork(); -+ if (pid == 0) { -+ /* ask vdc to unmount it */ -+ execl("/system/bin/vdc", "/system/bin/vdc", "volume", "unmount", -+ getenv("EXTERNAL_STORAGE"), "force", NULL); -+ } else if (pid > 0) { -+ /* wait until vdc succeeds or fails */ -+ waitpid(pid, &ret, 0); -+ } -+ -+ ret = android_reboot(ANDROID_RB_RESTART2, 0, (char *) arg); -+ if (ret < 0) { -+ snprintf(buf, sizeof(buf), "reboot failed: %s\n", strerror(errno)); -+ writex(fd, buf, strlen(buf)); -+ } -+ free(arg); -+ 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 = adb_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]; -+} -+ -+#if !ADB_HOST -+static int create_subprocess(const char *cmd, const char *arg0, const char *arg1, pid_t *pid) -+{ -+#ifdef HAVE_WIN32_PROC -+ D("create_subprocess(cmd=%s, arg0=%s, arg1=%s)\n", cmd, arg0, arg1); -+ 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; -+ -+ 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)); -+ adb_close(ptm); -+ return -1; -+ } -+ -+ *pid = fork(); -+ if(*pid < 0) { -+ printf("- fork failed: %s -\n", strerror(errno)); -+ adb_close(ptm); -+ return -1; -+ } -+ -+ if(*pid == 0){ -+ int pts; -+ -+ setsid(); -+ -+ pts = unix_open(devname, O_RDWR); -+ if(pts < 0) { -+ fprintf(stderr, "child failed to open pseudo-term slave: %s\n", devname); -+ exit(-1); -+ } -+ -+ dup2(pts, 0); -+ dup2(pts, 1); -+ dup2(pts, 2); -+ -+ adb_close(pts); -+ adb_close(ptm); -+ -+ // set OOM adjustment to zero -+ char text[64]; -+ snprintf(text, sizeof text, "/proc/%d/oom_adj", getpid()); -+ int fd = adb_open(text, O_WRONLY); -+ if (fd >= 0) { -+ adb_write(fd, "0", 1); -+ adb_close(fd); -+ } else { -+ D("adb: unable to open %s\n", text); -+ } -+ execl(cmd, cmd, arg0, arg1, NULL); -+ fprintf(stderr, "- exec '%s' failed: %s (%d) -\n", -+ cmd, strerror(errno), errno); -+ exit(-1); -+ } else { -+ // Don't set child's OOM adjustment to zero. -+ // Let the child do it itself, as sometimes the parent starts -+ // running before the child has a /proc/pid/oom_adj. -+ // """adb: unable to open /proc/644/oom_adj""" seen in some logs. -+ return ptm; -+ } -+#endif /* !HAVE_WIN32_PROC */ -+} -+#endif /* !ABD_HOST */ -+ -+#if ADB_HOST -+#define SHELL_COMMAND "/bin/sh" -+#else -+#define SHELL_COMMAND "/system/bin/sh" -+#endif -+ -+#if !ADB_HOST -+static void subproc_waiter_service(int fd, void *cookie) -+{ -+ pid_t pid = (pid_t)cookie; -+ -+ D("entered. fd=%d of pid=%d\n", fd, pid); -+ for (;;) { -+ int status; -+ pid_t p = waitpid(pid, &status, 0); -+ if (p == pid) { -+ D("fd=%d, post waitpid(pid=%d) status=%04x\n", fd, p, status); -+ if (WIFSIGNALED(status)) { -+ D("*** Killed by signal %d\n", WTERMSIG(status)); -+ break; -+ } else if (!WIFEXITED(status)) { -+ D("*** Didn't exit!!. status %d\n", status); -+ break; -+ } else if (WEXITSTATUS(status) >= 0) { -+ D("*** Exit code %d\n", WEXITSTATUS(status)); -+ break; -+ } -+ } -+ } -+ D("shell exited fd=%d of pid=%d err=%d\n", fd, pid, errno); -+ if (SHELL_EXIT_NOTIFY_FD >=0) { -+ int res; -+ res = writex(SHELL_EXIT_NOTIFY_FD, &fd, sizeof(fd)); -+ D("notified shell exit via fd=%d for pid=%d res=%d errno=%d\n", -+ SHELL_EXIT_NOTIFY_FD, pid, res, errno); -+ } -+} -+ -+static int create_subproc_thread(const char *name) -+{ -+ stinfo *sti; -+ adb_thread_t t; -+ int ret_fd; -+ pid_t pid; -+ -+ struct passwd *user = getpwuid(getuid()); -+ char *shell; -+ -+ if (user && user->pw_shell) -+ shell = user->pw_shell; -+ else -+ shell = SHELL_COMMAND; -+ -+ if(name) { -+ ret_fd = create_subprocess(shell, "-c", name, &pid); -+ } else { -+ ret_fd = create_subprocess(shell, "-", 0, &pid); -+ } -+ D("create_subprocess() ret_fd=%d pid=%d\n", ret_fd, pid); -+ -+ sti = malloc(sizeof(stinfo)); -+ if(sti == 0) fatal("cannot allocate stinfo"); -+ sti->func = subproc_waiter_service; -+ sti->cookie = (void*)pid; -+ sti->fd = ret_fd; -+ -+ if(adb_thread_create( &t, service_bootstrap_func, sti)){ -+ free(sti); -+ adb_close(ret_fd); -+ printf("cannot create service thread\n"); -+ return -1; -+ } -+ -+ D("service thread started, fd=%d pid=%d\n",ret_fd, pid); -+ return ret_fd; -+} -+#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)); -+ } else if(!HOST && !strncmp(name, "shell:", 6)) { -+ if(name[6]) { -+ ret = create_subproc_thread(name + 6); -+ } else { -+ ret = create_subproc_thread(0); -+ } -+ } 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); -+ } else if(!strncmp(name, "reboot:", 7)) { -+ void* arg = strdup(name + 7); -+ if(arg == 0) return -1; -+ ret = create_service_thread(reboot_service, arg); -+ } else if(!strncmp(name, "root:", 5)) { -+ ret = create_service_thread(restart_root_service, NULL); -+ } else if(!strncmp(name, "backup:", 7)) { -+ char* arg = strdup(name+7); -+ if (arg == NULL) return -1; -+ ret = backup_service(BACKUP, arg); -+ } else if(!strncmp(name, "restore:", 8)) { -+ ret = backup_service(RESTORE, NULL); -+ } else if(!strncmp(name, "tcpip:", 6)) { -+ int port; -+ if (sscanf(name + 6, "%d", &port) == 0) { -+ port = 0; -+ } -+ ret = create_service_thread(restart_tcp_service, (void *)port); -+ } else if(!strncmp(name, "usb:", 4)) { -+ ret = create_service_thread(restart_usb_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 */ -Index: android-tools-4.2.2+git20130218/core/adbd/sockets.c -=================================================================== ---- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ android-tools-4.2.2+git20130218/core/adbd/sockets.c 2013-06-18 17:12:17.000000000 -0300 -@@ -0,0 +1,873 @@ -+/* -+ * 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 -+#include -+#include -+#include -+#include -+#include -+ -+#include "sysdeps.h" -+ -+#define TRACE_TAG TRACE_SOCKETS -+#include "adb.h" -+ -+ADB_MUTEX_DEFINE( socket_list_lock ); -+ -+static void local_socket_close_locked(asocket *s); -+ -+int sendfailmsg(int fd, const char *reason) -+{ -+ char buf[9]; -+ int len; -+ len = strlen(reason); -+ if(len > 0xffff) len = 0xffff; -+ snprintf(buf, sizeof buf, "FAIL%04x", len); -+ if(writex(fd, buf, 8)) return -1; -+ return writex(fd, reason, len); -+} -+ -+//extern int online; -+ -+static unsigned local_socket_next_id = 1; -+ -+static asocket local_socket_list = { -+ .next = &local_socket_list, -+ .prev = &local_socket_list, -+}; -+ -+/* the the list of currently closing local sockets. -+** these have no peer anymore, but still packets to -+** write to their fd. -+*/ -+static asocket local_socket_closing_list = { -+ .next = &local_socket_closing_list, -+ .prev = &local_socket_closing_list, -+}; -+ -+asocket *find_local_socket(unsigned id) -+{ -+ asocket *s; -+ asocket *result = NULL; -+ -+ adb_mutex_lock(&socket_list_lock); -+ for (s = local_socket_list.next; s != &local_socket_list; s = s->next) { -+ if (s->id == id) { -+ result = s; -+ break; -+ } -+ } -+ adb_mutex_unlock(&socket_list_lock); -+ -+ return result; -+} -+ -+static void -+insert_local_socket(asocket* s, asocket* list) -+{ -+ s->next = list; -+ s->prev = s->next->prev; -+ s->prev->next = s; -+ s->next->prev = s; -+} -+ -+ -+void install_local_socket(asocket *s) -+{ -+ adb_mutex_lock(&socket_list_lock); -+ -+ s->id = local_socket_next_id++; -+ insert_local_socket(s, &local_socket_list); -+ -+ adb_mutex_unlock(&socket_list_lock); -+} -+ -+void remove_socket(asocket *s) -+{ -+ // socket_list_lock should already be held -+ if (s->prev && s->next) -+ { -+ s->prev->next = s->next; -+ s->next->prev = s->prev; -+ s->next = 0; -+ s->prev = 0; -+ s->id = 0; -+ } -+} -+ -+void close_all_sockets(atransport *t) -+{ -+ asocket *s; -+ -+ /* this is a little gross, but since s->close() *will* modify -+ ** the list out from under you, your options are limited. -+ */ -+ adb_mutex_lock(&socket_list_lock); -+restart: -+ for(s = local_socket_list.next; s != &local_socket_list; s = s->next){ -+ if(s->transport == t || (s->peer && s->peer->transport == t)) { -+ local_socket_close_locked(s); -+ goto restart; -+ } -+ } -+ adb_mutex_unlock(&socket_list_lock); -+} -+ -+static int local_socket_enqueue(asocket *s, apacket *p) -+{ -+ D("LS(%d): enqueue %d\n", s->id, p->len); -+ -+ p->ptr = p->data; -+ -+ /* if there is already data queue'd, we will receive -+ ** events when it's time to write. just add this to -+ ** the tail -+ */ -+ if(s->pkt_first) { -+ goto enqueue; -+ } -+ -+ /* write as much as we can, until we -+ ** would block or there is an error/eof -+ */ -+ while(p->len > 0) { -+ int r = adb_write(s->fd, p->ptr, p->len); -+ if(r > 0) { -+ p->len -= r; -+ p->ptr += r; -+ continue; -+ } -+ if((r == 0) || (errno != EAGAIN)) { -+ D( "LS(%d): not ready, errno=%d: %s\n", s->id, errno, strerror(errno) ); -+ s->close(s); -+ return 1; /* not ready (error) */ -+ } else { -+ break; -+ } -+ } -+ -+ if(p->len == 0) { -+ put_apacket(p); -+ return 0; /* ready for more data */ -+ } -+ -+enqueue: -+ p->next = 0; -+ if(s->pkt_first) { -+ s->pkt_last->next = p; -+ } else { -+ s->pkt_first = p; -+ } -+ s->pkt_last = p; -+ -+ /* make sure we are notified when we can drain the queue */ -+ fdevent_add(&s->fde, FDE_WRITE); -+ -+ return 1; /* not ready (backlog) */ -+} -+ -+static void local_socket_ready(asocket *s) -+{ -+ /* far side is ready for data, pay attention to -+ readable events */ -+ fdevent_add(&s->fde, FDE_READ); -+// D("LS(%d): ready()\n", s->id); -+} -+ -+static void local_socket_close(asocket *s) -+{ -+ adb_mutex_lock(&socket_list_lock); -+ local_socket_close_locked(s); -+ adb_mutex_unlock(&socket_list_lock); -+} -+ -+// be sure to hold the socket list lock when calling this -+static void local_socket_destroy(asocket *s) -+{ -+ apacket *p, *n; -+ int exit_on_close = s->exit_on_close; -+ -+ D("LS(%d): destroying fde.fd=%d\n", s->id, s->fde.fd); -+ -+ /* IMPORTANT: the remove closes the fd -+ ** that belongs to this socket -+ */ -+ fdevent_remove(&s->fde); -+ -+ /* dispose of any unwritten data */ -+ for(p = s->pkt_first; p; p = n) { -+ D("LS(%d): discarding %d bytes\n", s->id, p->len); -+ n = p->next; -+ put_apacket(p); -+ } -+ remove_socket(s); -+ free(s); -+ -+ if (exit_on_close) { -+ D("local_socket_destroy: exiting\n"); -+ exit(1); -+ } -+} -+ -+ -+static void local_socket_close_locked(asocket *s) -+{ -+ D("entered. LS(%d) fd=%d\n", s->id, s->fd); -+ if(s->peer) { -+ D("LS(%d): closing peer. peer->id=%d peer->fd=%d\n", -+ s->id, s->peer->id, s->peer->fd); -+ s->peer->peer = 0; -+ // tweak to avoid deadlock -+ if (s->peer->close == local_socket_close) { -+ local_socket_close_locked(s->peer); -+ } else { -+ s->peer->close(s->peer); -+ } -+ s->peer = 0; -+ } -+ -+ /* If we are already closing, or if there are no -+ ** pending packets, destroy immediately -+ */ -+ if (s->closing || s->pkt_first == NULL) { -+ int id = s->id; -+ local_socket_destroy(s); -+ D("LS(%d): closed\n", id); -+ return; -+ } -+ -+ /* otherwise, put on the closing list -+ */ -+ D("LS(%d): closing\n", s->id); -+ s->closing = 1; -+ fdevent_del(&s->fde, FDE_READ); -+ remove_socket(s); -+ D("LS(%d): put on socket_closing_list fd=%d\n", s->id, s->fd); -+ insert_local_socket(s, &local_socket_closing_list); -+} -+ -+static void local_socket_event_func(int fd, unsigned ev, void *_s) -+{ -+ asocket *s = _s; -+ -+ D("LS(%d): event_func(fd=%d(==%d), ev=%04x)\n", s->id, s->fd, fd, ev); -+ -+ /* put the FDE_WRITE processing before the FDE_READ -+ ** in order to simplify the code. -+ */ -+ if(ev & FDE_WRITE){ -+ apacket *p; -+ -+ while((p = s->pkt_first) != 0) { -+ while(p->len > 0) { -+ int r = adb_write(fd, p->ptr, p->len); -+ if(r > 0) { -+ p->ptr += r; -+ p->len -= r; -+ continue; -+ } -+ if(r < 0) { -+ /* returning here is ok because FDE_READ will -+ ** be processed in the next iteration loop -+ */ -+ if(errno == EAGAIN) return; -+ if(errno == EINTR) continue; -+ } -+ D(" closing after write because r=%d and errno is %d\n", r, errno); -+ s->close(s); -+ return; -+ } -+ -+ if(p->len == 0) { -+ s->pkt_first = p->next; -+ if(s->pkt_first == 0) s->pkt_last = 0; -+ put_apacket(p); -+ } -+ } -+ -+ /* if we sent the last packet of a closing socket, -+ ** we can now destroy it. -+ */ -+ if (s->closing) { -+ D(" closing because 'closing' is set after write\n"); -+ s->close(s); -+ return; -+ } -+ -+ /* no more packets queued, so we can ignore -+ ** writable events again and tell our peer -+ ** to resume writing -+ */ -+ fdevent_del(&s->fde, FDE_WRITE); -+ s->peer->ready(s->peer); -+ } -+ -+ -+ if(ev & FDE_READ){ -+ apacket *p = get_apacket(); -+ unsigned char *x = p->data; -+ size_t avail = MAX_PAYLOAD; -+ int r; -+ int is_eof = 0; -+ -+ while(avail > 0) { -+ r = adb_read(fd, x, avail); -+ D("LS(%d): post adb_read(fd=%d,...) r=%d (errno=%d) avail=%d\n", s->id, s->fd, r, r<0?errno:0, avail); -+ if(r > 0) { -+ avail -= r; -+ x += r; -+ continue; -+ } -+ if(r < 0) { -+ if(errno == EAGAIN) break; -+ if(errno == EINTR) continue; -+ } -+ -+ /* r = 0 or unhandled error */ -+ is_eof = 1; -+ break; -+ } -+ D("LS(%d): fd=%d post avail loop. r=%d is_eof=%d forced_eof=%d\n", -+ s->id, s->fd, r, is_eof, s->fde.force_eof); -+ if((avail == MAX_PAYLOAD) || (s->peer == 0)) { -+ put_apacket(p); -+ } else { -+ p->len = MAX_PAYLOAD - avail; -+ -+ r = s->peer->enqueue(s->peer, p); -+ D("LS(%d): fd=%d post peer->enqueue(). r=%d\n", s->id, s->fd, r); -+ -+ if(r < 0) { -+ /* error return means they closed us as a side-effect -+ ** and we must return immediately. -+ ** -+ ** note that if we still have buffered packets, the -+ ** socket will be placed on the closing socket list. -+ ** this handler function will be called again -+ ** to process FDE_WRITE events. -+ */ -+ return; -+ } -+ -+ if(r > 0) { -+ /* if the remote cannot accept further events, -+ ** we disable notification of READs. They'll -+ ** be enabled again when we get a call to ready() -+ */ -+ fdevent_del(&s->fde, FDE_READ); -+ } -+ } -+ /* Don't allow a forced eof if data is still there */ -+ if((s->fde.force_eof && !r) || is_eof) { -+ D(" closing because is_eof=%d r=%d s->fde.force_eof=%d\n", is_eof, r, s->fde.force_eof); -+ s->close(s); -+ } -+ } -+ -+ if(ev & FDE_ERROR){ -+ /* this should be caught be the next read or write -+ ** catching it here means we may skip the last few -+ ** bytes of readable data. -+ */ -+// s->close(s); -+ D("LS(%d): FDE_ERROR (fd=%d)\n", s->id, s->fd); -+ -+ return; -+ } -+} -+ -+asocket *create_local_socket(int fd) -+{ -+ asocket *s = calloc(1, sizeof(asocket)); -+ if (s == NULL) fatal("cannot allocate socket"); -+ s->fd = fd; -+ s->enqueue = local_socket_enqueue; -+ s->ready = local_socket_ready; -+ s->close = local_socket_close; -+ install_local_socket(s); -+ -+ fdevent_install(&s->fde, fd, local_socket_event_func, s); -+/* fdevent_add(&s->fde, FDE_ERROR); */ -+ //fprintf(stderr, "Created local socket in create_local_socket \n"); -+ D("LS(%d): created (fd=%d)\n", s->id, s->fd); -+ return s; -+} -+ -+asocket *create_local_service_socket(const char *name) -+{ -+ asocket *s; -+ int fd; -+ -+#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' via %d\n", s->id, name, fd); -+ -+#if !ADB_HOST -+ if ((!strncmp(name, "root:", 5) && getuid() != 0) -+ || !strncmp(name, "usb:", 4) -+ || !strncmp(name, "tcpip:", 6)) { -+ D("LS(%d): enabling exit_on_close\n", s->id); -+ s->exit_on_close = 1; -+ } -+#endif -+ -+ 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("entered remote_socket_enqueue RS(%d) WRITE fd=%d peer.fd=%d\n", -+ s->id, s->fd, s->peer->fd); -+ p->msg.command = A_WRTE; -+ p->msg.arg0 = s->peer->id; -+ p->msg.arg1 = s->id; -+ p->msg.data_length = p->len; -+ send_packet(p, s->transport); -+ return 1; -+} -+ -+static void remote_socket_ready(asocket *s) -+{ -+ D("entered remote_socket_ready RS(%d) OKAY fd=%d peer.fd=%d\n", -+ s->id, s->fd, s->peer->fd); -+ apacket *p = get_apacket(); -+ p->msg.command = A_OKAY; -+ p->msg.arg0 = s->peer->id; -+ p->msg.arg1 = s->id; -+ send_packet(p, s->transport); -+} -+ -+static void remote_socket_close(asocket *s) -+{ -+ D("entered remote_socket_close RS(%d) CLOSE fd=%d peer->fd=%d\n", -+ s->id, s->fd, s->peer?s->peer->fd:-1); -+ apacket *p = get_apacket(); -+ p->msg.command = A_CLSE; -+ if(s->peer) { -+ p->msg.arg0 = s->peer->id; -+ s->peer->peer = 0; -+ D("RS(%d) peer->close()ing peer->id=%d peer->fd=%d\n", -+ s->id, s->peer->id, s->peer->fd); -+ s->peer->close(s->peer); -+ } -+ p->msg.arg1 = s->id; -+ send_packet(p, s->transport); -+ D("RS(%d): closed\n", s->id); -+ remove_transport_disconnect( s->transport, &((aremotesocket*)s)->disconnect ); -+ free(s); -+} -+ -+static void remote_socket_disconnect(void* _s, atransport* t) -+{ -+ asocket* s = _s; -+ asocket* peer = s->peer; -+ -+ D("remote_socket_disconnect RS(%d)\n", s->id); -+ if (peer) { -+ peer->peer = NULL; -+ peer->close(peer); -+ } -+ remove_transport_disconnect( s->transport, &((aremotesocket*)s)->disconnect ); -+ free(s); -+} -+ -+asocket *create_remote_socket(unsigned id, atransport *t) -+{ -+ asocket *s = calloc(1, sizeof(aremotesocket)); -+ adisconnect* dis = &((aremotesocket*)s)->disconnect; -+ -+ if (s == NULL) fatal("cannot allocate socket"); -+ s->id = id; -+ s->enqueue = remote_socket_enqueue; -+ s->ready = remote_socket_ready; -+ s->close = remote_socket_close; -+ s->transport = t; -+ -+ dis->func = remote_socket_disconnect; -+ dis->opaque = s; -+ add_transport_disconnect( t, dis ); -+ D("RS(%d): created\n", s->id); -+ return s; -+} -+ -+void connect_to_remote(asocket *s, const char *destination) -+{ -+ D("Connect_to_remote call RS(%d) fd=%d\n", s->id, s->fd); -+ apacket *p = get_apacket(); -+ int len = strlen(destination) + 1; -+ -+ if(len > (MAX_PAYLOAD-1)) { -+ fatal("destination oversized"); -+ } -+ -+ D("LS(%d): connect('%s')\n", s->id, destination); -+ p->msg.command = A_OPEN; -+ p->msg.arg0 = s->id; -+ p->msg.data_length = len; -+ strcpy((char*) p->data, destination); -+ send_packet(p, s->transport); -+} -+ -+ -+/* this is used by magic sockets to rig local sockets to -+ send the go-ahead message when they connect */ -+static void local_socket_ready_notify(asocket *s) -+{ -+ s->ready = local_socket_ready; -+ s->close = local_socket_close; -+ adb_write(s->fd, "OKAY", 4); -+ s->ready(s); -+} -+ -+/* this is used by magic sockets to rig local sockets to -+ send the failure message if they are closed before -+ connected (to avoid closing them without a status message) */ -+static void local_socket_close_notify(asocket *s) -+{ -+ s->ready = local_socket_ready; -+ s->close = local_socket_close; -+ sendfailmsg(s->fd, "closed"); -+ s->close(s); -+} -+ -+unsigned unhex(unsigned char *s, int len) -+{ -+ unsigned n = 0, c; -+ -+ while(len-- > 0) { -+ switch((c = *s++)) { -+ case '0': case '1': case '2': -+ case '3': case '4': case '5': -+ case '6': case '7': case '8': -+ case '9': -+ c -= '0'; -+ break; -+ case 'a': case 'b': case 'c': -+ case 'd': case 'e': case 'f': -+ c = c - 'a' + 10; -+ break; -+ case 'A': case 'B': case 'C': -+ case 'D': case 'E': case 'F': -+ c = c - 'A' + 10; -+ break; -+ default: -+ return 0xffffffff; -+ } -+ -+ n = (n << 4) | c; -+ } -+ -+ return n; -+} -+ -+#define PREFIX(str) { str, sizeof(str) - 1 } -+static const struct prefix_struct { -+ const char *str; -+ const size_t len; -+} prefixes[] = { -+ PREFIX("usb:"), -+ PREFIX("product:"), -+ PREFIX("model:"), -+ PREFIX("device:"), -+}; -+static const int num_prefixes = (sizeof(prefixes) / sizeof(prefixes[0])); -+ -+/* skip_host_serial return the position in a string -+ skipping over the 'serial' parameter in the ADB protocol, -+ where parameter string may be a host:port string containing -+ the protocol delimiter (colon). */ -+char *skip_host_serial(char *service) { -+ char *first_colon, *serial_end; -+ int i; -+ -+ for (i = 0; i < num_prefixes; i++) { -+ if (!strncmp(service, prefixes[i].str, prefixes[i].len)) -+ return strchr(service + prefixes[i].len, ':'); -+ } -+ -+ first_colon = strchr(service, ':'); -+ if (!first_colon) { -+ /* No colon in service string. */ -+ return NULL; -+ } -+ serial_end = first_colon; -+ if (isdigit(serial_end[1])) { -+ serial_end++; -+ while ((*serial_end) && isdigit(*serial_end)) { -+ serial_end++; -+ } -+ if ((*serial_end) != ':') { -+ // Something other than numbers was found, reset the end. -+ serial_end = first_colon; -+ } -+ } -+ return serial_end; -+} -+ -+static int smart_socket_enqueue(asocket *s, apacket *p) -+{ -+ unsigned len; -+#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:" and could be a host:port string. -+ serial_end = skip_host_serial(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); -+ s->peer = 0; -+ } -+ free(s); -+} -+ -+asocket *create_smart_socket(void (*action_cb)(asocket *s, const char *act)) -+{ -+ D("Creating smart socket \n"); -+ asocket *s = calloc(1, sizeof(asocket)); -+ if (s == NULL) fatal("cannot allocate socket"); -+ s->enqueue = smart_socket_enqueue; -+ s->ready = smart_socket_ready; -+ s->close = smart_socket_close; -+ s->extra = action_cb; -+ -+ D("SS(%d): created %p\n", s->id, action_cb); -+ return s; -+} -+ -+void smart_socket_action(asocket *s, const char *act) -+{ -+ -+} -+ -+void connect_to_smartsocket(asocket *s) -+{ -+ D("Connecting to smart socket \n"); -+ asocket *ss = create_smart_socket(smart_socket_action); -+ s->peer = ss; -+ ss->peer = s; -+ s->ready(s); -+} -Index: android-tools-4.2.2+git20130218/core/adbd/sysdeps.h -=================================================================== ---- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ android-tools-4.2.2+git20130218/core/adbd/sysdeps.h 2013-06-18 17:12:17.000000000 -0300 -@@ -0,0 +1,522 @@ -+/* -+ * 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 -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#define OS_PATH_SEPARATOR '\\' -+#define OS_PATH_SEPARATOR_STR "\\" -+#define ENV_PATH_SEPARATOR_STR ";" -+ -+typedef CRITICAL_SECTION adb_mutex_t; -+ -+#define ADB_MUTEX_DEFINE(x) adb_mutex_t x -+ -+/* declare all mutexes */ -+/* For win32, adb_sysdeps_init() will do the mutex runtime initialization. */ -+#define ADB_MUTEX(x) extern adb_mutex_t x; -+#include "mutex_list.h" -+ -+extern void adb_sysdeps_init(void); -+ -+static __inline__ void adb_mutex_lock( adb_mutex_t* lock ) -+{ -+ EnterCriticalSection( lock ); -+} -+ -+static __inline__ void adb_mutex_unlock( adb_mutex_t* lock ) -+{ -+ LeaveCriticalSection( lock ); -+} -+ -+typedef struct { unsigned tid; } adb_thread_t; -+ -+typedef void* (*adb_thread_func_t)(void* arg); -+ -+typedef void (*win_thread_func_t)(void* arg); -+ -+static __inline__ int adb_thread_create( adb_thread_t *thread, adb_thread_func_t func, void* arg) -+{ -+ thread->tid = _beginthread( (win_thread_func_t)func, 0, arg ); -+ if (thread->tid == (unsigned)-1L) { -+ return -1; -+ } -+ return 0; -+} -+ -+static __inline__ void close_on_exec(int fd) -+{ -+ /* nothing really */ -+} -+ -+extern void disable_tcp_nagle(int fd); -+ -+#define lstat stat /* no symlinks on Win32 */ -+ -+#define S_ISLNK(m) 0 /* no symlinks on Win32 */ -+ -+static __inline__ int adb_unlink(const char* path) -+{ -+ int rc = unlink(path); -+ -+ if (rc == -1 && errno == EACCES) { -+ /* unlink returns EACCES when the file is read-only, so we first */ -+ /* try to make it writable, then unlink again... */ -+ rc = chmod(path, _S_IREAD|_S_IWRITE ); -+ if (rc == 0) -+ rc = unlink(path); -+ } -+ return rc; -+} -+#undef unlink -+#define unlink ___xxx_unlink -+ -+static __inline__ int adb_mkdir(const char* path, int mode) -+{ -+ return _mkdir(path); -+} -+#undef mkdir -+#define mkdir ___xxx_mkdir -+ -+extern int adb_open(const char* path, int options); -+extern int adb_creat(const char* path, int mode); -+extern int adb_read(int fd, void* buf, int len); -+extern int adb_write(int fd, const void* buf, int len); -+extern int adb_lseek(int fd, int pos, int where); -+extern int adb_shutdown(int fd); -+extern int adb_close(int fd); -+ -+static __inline__ int unix_close(int fd) -+{ -+ return close(fd); -+} -+#undef close -+#define close ____xxx_close -+ -+static __inline__ int unix_read(int fd, void* buf, size_t len) -+{ -+ return read(fd, buf, len); -+} -+#undef read -+#define read ___xxx_read -+ -+static __inline__ int unix_write(int fd, const void* buf, size_t len) -+{ -+ return write(fd, buf, len); -+} -+#undef write -+#define write ___xxx_write -+ -+static __inline__ int adb_open_mode(const char* path, int options, int mode) -+{ -+ return adb_open(path, options); -+} -+ -+static __inline__ int unix_open(const char* path, int options,...) -+{ -+ if ((options & O_CREAT) == 0) -+ { -+ return open(path, options); -+ } -+ else -+ { -+ int mode; -+ va_list args; -+ va_start( args, options ); -+ mode = va_arg( args, int ); -+ va_end( args ); -+ return open(path, options, mode); -+ } -+} -+#define open ___xxx_unix_open -+ -+ -+/* normally provided by */ -+extern void* load_file(const char* pathname, unsigned* psize); -+ -+/* normally provided by */ -+extern int socket_loopback_client(int port, int type); -+extern int socket_network_client(const char *host, int port, int type); -+extern int socket_loopback_server(int port, int type); -+extern int socket_inaddr_any_server(int port, int type); -+ -+/* normally provided by "fdevent.h" */ -+ -+#define FDE_READ 0x0001 -+#define FDE_WRITE 0x0002 -+#define FDE_ERROR 0x0004 -+#define FDE_DONT_CLOSE 0x0080 -+ -+typedef struct fdevent fdevent; -+ -+typedef void (*fd_func)(int fd, unsigned events, void *userdata); -+ -+fdevent *fdevent_create(int fd, fd_func func, void *arg); -+void fdevent_destroy(fdevent *fde); -+void fdevent_install(fdevent *fde, int fd, fd_func func, void *arg); -+void fdevent_remove(fdevent *item); -+void fdevent_set(fdevent *fde, unsigned events); -+void fdevent_add(fdevent *fde, unsigned events); -+void fdevent_del(fdevent *fde, unsigned events); -+void fdevent_loop(); -+ -+struct fdevent { -+ fdevent *next; -+ fdevent *prev; -+ -+ int fd; -+ int force_eof; -+ -+ unsigned short state; -+ unsigned short events; -+ -+ fd_func func; -+ void *arg; -+}; -+ -+static __inline__ void adb_sleep_ms( int mseconds ) -+{ -+ Sleep( mseconds ); -+} -+ -+extern int adb_socket_accept(int serverfd, struct sockaddr* addr, socklen_t *addrlen); -+ -+#undef accept -+#define accept ___xxx_accept -+ -+static __inline__ int adb_socket_setbufsize( int fd, int bufsize ) -+{ -+ int opt = bufsize; -+ return setsockopt(fd, SOL_SOCKET, SO_RCVBUF, (const char*)&opt, sizeof(opt)); -+} -+ -+extern int adb_socketpair( int sv[2] ); -+ -+static __inline__ char* adb_dirstart( const char* path ) -+{ -+ char* p = strchr(path, '/'); -+ char* p2 = strchr(path, '\\'); -+ -+ if ( !p ) -+ p = p2; -+ else if ( p2 && p2 > p ) -+ p = p2; -+ -+ return p; -+} -+ -+static __inline__ char* adb_dirstop( const char* path ) -+{ -+ char* p = strrchr(path, '/'); -+ char* p2 = strrchr(path, '\\'); -+ -+ if ( !p ) -+ p = p2; -+ else if ( p2 && p2 > p ) -+ p = p2; -+ -+ return p; -+} -+ -+static __inline__ int adb_is_absolute_host_path( const char* path ) -+{ -+ return isalpha(path[0]) && path[1] == ':' && path[2] == '\\'; -+} -+ -+extern char* adb_strtok_r(char *str, const char *delim, char **saveptr); -+ -+#else /* !_WIN32 a.k.a. Unix */ -+ -+#include "fdevent.h" -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+/* -+ * TEMP_FAILURE_RETRY is defined by some, but not all, versions of -+ * . (Alas, it is not as standard as we'd hoped!) So, if it's -+ * not already defined, then define it here. -+ */ -+#ifndef TEMP_FAILURE_RETRY -+/* Used to retry syscalls that can return EINTR. */ -+#define TEMP_FAILURE_RETRY(exp) ({ \ -+ typeof (exp) _rc; \ -+ do { \ -+ _rc = (exp); \ -+ } while (_rc == -1 && errno == EINTR); \ -+ _rc; }) -+#endif -+ -+#define OS_PATH_SEPARATOR '/' -+#define OS_PATH_SEPARATOR_STR "/" -+#define ENV_PATH_SEPARATOR_STR ":" -+ -+typedef pthread_mutex_t adb_mutex_t; -+ -+#define ADB_MUTEX_INITIALIZER PTHREAD_MUTEX_INITIALIZER -+#define adb_mutex_init pthread_mutex_init -+#define adb_mutex_lock pthread_mutex_lock -+#define adb_mutex_unlock pthread_mutex_unlock -+#define adb_mutex_destroy pthread_mutex_destroy -+ -+#define ADB_MUTEX_DEFINE(m) adb_mutex_t m = PTHREAD_MUTEX_INITIALIZER -+ -+#define adb_cond_t pthread_cond_t -+#define adb_cond_init pthread_cond_init -+#define adb_cond_wait pthread_cond_wait -+#define adb_cond_broadcast pthread_cond_broadcast -+#define adb_cond_signal pthread_cond_signal -+#define adb_cond_destroy pthread_cond_destroy -+ -+/* declare all mutexes */ -+#define ADB_MUTEX(x) extern adb_mutex_t x; -+#include "mutex_list.h" -+ -+static __inline__ void close_on_exec(int fd) -+{ -+ fcntl( fd, F_SETFD, FD_CLOEXEC ); -+} -+ -+static __inline__ int unix_open(const char* path, int options,...) -+{ -+ if ((options & O_CREAT) == 0) -+ { -+ return TEMP_FAILURE_RETRY( open(path, options) ); -+ } -+ else -+ { -+ int mode; -+ va_list args; -+ va_start( args, options ); -+ mode = va_arg( args, int ); -+ va_end( args ); -+ return TEMP_FAILURE_RETRY( open( path, options, mode ) ); -+ } -+} -+ -+static __inline__ int adb_open_mode( const char* pathname, int options, int mode ) -+{ -+ return TEMP_FAILURE_RETRY( open( pathname, options, mode ) ); -+} -+ -+ -+static __inline__ int adb_open( const char* pathname, int options ) -+{ -+ int fd = TEMP_FAILURE_RETRY( open( pathname, options ) ); -+ if (fd < 0) -+ return -1; -+ close_on_exec( fd ); -+ return fd; -+} -+#undef open -+#define open ___xxx_open -+ -+static __inline__ int adb_shutdown(int fd) -+{ -+ return shutdown(fd, SHUT_RDWR); -+} -+#undef shutdown -+#define shutdown ____xxx_shutdown -+ -+static __inline__ int adb_close(int fd) -+{ -+ return close(fd); -+} -+#undef close -+#define close ____xxx_close -+ -+ -+static __inline__ int adb_read(int fd, void* buf, size_t len) -+{ -+ return TEMP_FAILURE_RETRY( read( fd, buf, len ) ); -+} -+ -+#undef read -+#define read ___xxx_read -+ -+static __inline__ int adb_write(int fd, const void* buf, size_t len) -+{ -+ return TEMP_FAILURE_RETRY( 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 = TEMP_FAILURE_RETRY( 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) -+{ -+ int fd; -+ -+ fd = TEMP_FAILURE_RETRY( accept( serverfd, addr, addrlen ) ); -+ if (fd >= 0) -+ close_on_exec(fd); -+ -+ return fd; -+} -+ -+#undef accept -+#define accept ___xxx_accept -+ -+#define unix_read adb_read -+#define unix_write adb_write -+#define unix_close adb_close -+ -+typedef pthread_t adb_thread_t; -+ -+typedef void* (*adb_thread_func_t)( void* arg ); -+ -+static __inline__ int adb_thread_create( adb_thread_t *pthread, adb_thread_func_t start, void* arg ) -+{ -+ pthread_attr_t attr; -+ -+ pthread_attr_init (&attr); -+ pthread_attr_setdetachstate (&attr, PTHREAD_CREATE_DETACHED); -+ -+ return pthread_create( pthread, &attr, start, arg ); -+} -+ -+static __inline__ int adb_socket_setbufsize( int fd, int bufsize ) -+{ -+ int opt = bufsize; -+ return setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &opt, sizeof(opt)); -+} -+ -+static __inline__ void disable_tcp_nagle(int fd) -+{ -+ int on = 1; -+ setsockopt( fd, IPPROTO_TCP, TCP_NODELAY, (void*)&on, sizeof(on) ); -+} -+ -+ -+static __inline__ int unix_socketpair( int d, int type, int protocol, int sv[2] ) -+{ -+ return socketpair( d, type, protocol, sv ); -+} -+ -+static __inline__ int adb_socketpair( int sv[2] ) -+{ -+ int rc; -+ -+ rc = unix_socketpair( AF_UNIX, SOCK_STREAM, 0, sv ); -+ if (rc < 0) -+ return -1; -+ -+ close_on_exec( sv[0] ); -+ close_on_exec( sv[1] ); -+ return 0; -+} -+ -+#undef socketpair -+#define socketpair ___xxx_socketpair -+ -+static __inline__ void adb_sleep_ms( int mseconds ) -+{ -+ usleep( mseconds*1000 ); -+} -+ -+static __inline__ int adb_mkdir(const char* path, int mode) -+{ -+ return mkdir(path, mode); -+} -+#undef mkdir -+#define mkdir ___xxx_mkdir -+ -+static __inline__ void adb_sysdeps_init(void) -+{ -+} -+ -+static __inline__ char* adb_dirstart(const char* path) -+{ -+ return strchr(path, '/'); -+} -+ -+static __inline__ char* adb_dirstop(const char* path) -+{ -+ return strrchr(path, '/'); -+} -+ -+static __inline__ int adb_is_absolute_host_path( const char* path ) -+{ -+ return path[0] == '/'; -+} -+ -+static __inline__ char* adb_strtok_r(char *str, const char *delim, char **saveptr) -+{ -+ return strtok_r(str, delim, saveptr); -+} -+#undef strtok_r -+#define strtok_r ___xxx_strtok_r -+ -+#endif /* !_WIN32 */ -+ -+#endif /* _ADB_SYSDEPS_H */ -Index: android-tools-4.2.2+git20130218/core/adbd/sysdeps_win32.c -=================================================================== ---- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ android-tools-4.2.2+git20130218/core/adbd/sysdeps_win32.c 2013-06-18 17:12:17.000000000 -0300 -@@ -0,0 +1,2220 @@ -+#include "sysdeps.h" -+#include -+#include -+#include -+#include -+#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_shutdown(int fd) -+{ -+ FH f = _fh_from_int(fd); -+ -+ if (!f) { -+ return -1; -+ } -+ -+ D( "adb_shutdown: %s\n", f->name); -+ shutdown( f->fh_socket, SD_BOTH ); -+ return 0; -+} -+ -+ -+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 -+ -+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 = 1; -+ -+ 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 -+# 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 ); -+ } -+ } -+} -+ -+/* -+ * A fixer for WaitForMultipleObjects on condition that there are more than 64 -+ * handles to wait on. -+ * -+ * In cetain cases DDMS may establish more than 64 connections with ADB. For -+ * instance, this may happen if there are more than 64 processes running on a -+ * device, or there are multiple devices connected (including the emulator) with -+ * the combined number of running processes greater than 64. In this case using -+ * WaitForMultipleObjects to wait on connection events simply wouldn't cut, -+ * because of the API limitations (64 handles max). So, we need to provide a way -+ * to scale WaitForMultipleObjects to accept an arbitrary number of handles. The -+ * easiest (and "Microsoft recommended") way to do that would be dividing the -+ * handle array into chunks with the chunk size less than 64, and fire up as many -+ * waiting threads as there are chunks. Then each thread would wait on a chunk of -+ * handles, and will report back to the caller which handle has been set. -+ * Here is the implementation of that algorithm. -+ */ -+ -+/* Number of handles to wait on in each wating thread. */ -+#define WAIT_ALL_CHUNK_SIZE 63 -+ -+/* Descriptor for a wating thread */ -+typedef struct WaitForAllParam { -+ /* A handle to an event to signal when waiting is over. This handle is shared -+ * accross all the waiting threads, so each waiting thread knows when any -+ * other thread has exited, so it can exit too. */ -+ HANDLE main_event; -+ /* Upon exit from a waiting thread contains the index of the handle that has -+ * been signaled. The index is an absolute index of the signaled handle in -+ * the original array. This pointer is shared accross all the waiting threads -+ * and it's not guaranteed (due to a race condition) that when all the -+ * waiting threads exit, the value contained here would indicate the first -+ * handle that was signaled. This is fine, because the caller cares only -+ * about any handle being signaled. It doesn't care about the order, nor -+ * about the whole list of handles that were signaled. */ -+ LONG volatile *signaled_index; -+ /* Array of handles to wait on in a waiting thread. */ -+ HANDLE* handles; -+ /* Number of handles in 'handles' array to wait on. */ -+ int handles_count; -+ /* Index inside the main array of the first handle in the 'handles' array. */ -+ int first_handle_index; -+ /* Waiting thread handle. */ -+ HANDLE thread; -+} WaitForAllParam; -+ -+/* Waiting thread routine. */ -+static unsigned __stdcall -+_in_waiter_thread(void* arg) -+{ -+ HANDLE wait_on[WAIT_ALL_CHUNK_SIZE + 1]; -+ int res; -+ WaitForAllParam* const param = (WaitForAllParam*)arg; -+ -+ /* We have to wait on the main_event in order to be notified when any of the -+ * sibling threads is exiting. */ -+ wait_on[0] = param->main_event; -+ /* The rest of the handles go behind the main event handle. */ -+ memcpy(wait_on + 1, param->handles, param->handles_count * sizeof(HANDLE)); -+ -+ res = WaitForMultipleObjects(param->handles_count + 1, wait_on, FALSE, INFINITE); -+ if (res > 0 && res < (param->handles_count + 1)) { -+ /* One of the original handles got signaled. Save its absolute index into -+ * the output variable. */ -+ InterlockedCompareExchange(param->signaled_index, -+ res - 1L + param->first_handle_index, -1L); -+ } -+ -+ /* Notify the caller (and the siblings) that the wait is over. */ -+ SetEvent(param->main_event); -+ -+ _endthreadex(0); -+ return 0; -+} -+ -+/* WaitForMultipeObjects fixer routine. -+ * Param: -+ * handles Array of handles to wait on. -+ * handles_count Number of handles in the array. -+ * Return: -+ * (>= 0 && < handles_count) - Index of the signaled handle in the array, or -+ * WAIT_FAILED on an error. -+ */ -+static int -+_wait_for_all(HANDLE* handles, int handles_count) -+{ -+ WaitForAllParam* threads; -+ HANDLE main_event; -+ int chunks, chunk, remains; -+ -+ /* This variable is going to be accessed by several threads at the same time, -+ * this is bound to fail randomly when the core is run on multi-core machines. -+ * To solve this, we need to do the following (1 _and_ 2): -+ * 1. Use the "volatile" qualifier to ensure the compiler doesn't optimize -+ * out the reads/writes in this function unexpectedly. -+ * 2. Ensure correct memory ordering. The "simple" way to do that is to wrap -+ * all accesses inside a critical section. But we can also use -+ * InterlockedCompareExchange() which always provide a full memory barrier -+ * on Win32. -+ */ -+ volatile LONG sig_index = -1; -+ -+ /* Calculate number of chunks, and allocate thread param array. */ -+ chunks = handles_count / WAIT_ALL_CHUNK_SIZE; -+ remains = handles_count % WAIT_ALL_CHUNK_SIZE; -+ threads = (WaitForAllParam*)malloc((chunks + (remains ? 1 : 0)) * -+ sizeof(WaitForAllParam)); -+ if (threads == NULL) { -+ D("Unable to allocate thread array for %d handles.", handles_count); -+ return (int)WAIT_FAILED; -+ } -+ -+ /* Create main event to wait on for all waiting threads. This is a "manualy -+ * reset" event that will remain set once it was set. */ -+ main_event = CreateEvent(NULL, TRUE, FALSE, NULL); -+ if (main_event == NULL) { -+ D("Unable to create main event. Error: %d", GetLastError()); -+ free(threads); -+ return (int)WAIT_FAILED; -+ } -+ -+ /* -+ * Initialize waiting thread parameters. -+ */ -+ -+ for (chunk = 0; chunk < chunks; chunk++) { -+ threads[chunk].main_event = main_event; -+ threads[chunk].signaled_index = &sig_index; -+ threads[chunk].first_handle_index = WAIT_ALL_CHUNK_SIZE * chunk; -+ threads[chunk].handles = handles + threads[chunk].first_handle_index; -+ threads[chunk].handles_count = WAIT_ALL_CHUNK_SIZE; -+ } -+ if (remains) { -+ threads[chunk].main_event = main_event; -+ threads[chunk].signaled_index = &sig_index; -+ threads[chunk].first_handle_index = WAIT_ALL_CHUNK_SIZE * chunk; -+ threads[chunk].handles = handles + threads[chunk].first_handle_index; -+ threads[chunk].handles_count = remains; -+ chunks++; -+ } -+ -+ /* Start the waiting threads. */ -+ for (chunk = 0; chunk < chunks; chunk++) { -+ /* Note that using adb_thread_create is not appropriate here, since we -+ * need a handle to wait on for thread termination. */ -+ threads[chunk].thread = (HANDLE)_beginthreadex(NULL, 0, _in_waiter_thread, -+ &threads[chunk], 0, NULL); -+ if (threads[chunk].thread == NULL) { -+ /* Unable to create a waiter thread. Collapse. */ -+ D("Unable to create a waiting thread %d of %d. errno=%d", -+ chunk, chunks, errno); -+ chunks = chunk; -+ SetEvent(main_event); -+ break; -+ } -+ } -+ -+ /* Wait on any of the threads to get signaled. */ -+ WaitForSingleObject(main_event, INFINITE); -+ -+ /* Wait on all the waiting threads to exit. */ -+ for (chunk = 0; chunk < chunks; chunk++) { -+ WaitForSingleObject(threads[chunk].thread, INFINITE); -+ CloseHandle(threads[chunk].thread); -+ } -+ -+ CloseHandle(main_event); -+ free(threads); -+ -+ -+ const int ret = (int)InterlockedCompareExchange(&sig_index, -1, -1); -+ return (ret >= 0) ? ret : (int)WAIT_FAILED; -+} -+ -+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.\n", looper->htab_count); -+ wait_ret = _wait_for_all(looper->htab, looper->htab_count); -+ } else { -+ 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 ); -+} -+ -+/* Windows doesn't have strtok_r. Use the one from bionic. */ -+ -+/* -+ * Copyright (c) 1988 Regents of the University of California. -+ * All rights reserved. -+ * -+ * Redistribution and use in source and binary forms, with or without -+ * modification, are permitted provided that the following conditions -+ * are met: -+ * 1. Redistributions of source code must retain the above copyright -+ * notice, this list of conditions and the following disclaimer. -+ * 2. Redistributions in binary form must reproduce the above copyright -+ * notice, this list of conditions and the following disclaimer in the -+ * documentation and/or other materials provided with the distribution. -+ * 3. Neither the name of the University nor the names of its contributors -+ * may be used to endorse or promote products derived from this software -+ * without specific prior written permission. -+ * -+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND -+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE -+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -+ * SUCH DAMAGE. -+ */ -+ -+char * -+adb_strtok_r(char *s, const char *delim, char **last) -+{ -+ char *spanp; -+ int c, sc; -+ char *tok; -+ -+ -+ if (s == NULL && (s = *last) == NULL) -+ return (NULL); -+ -+ /* -+ * Skip (span) leading delimiters (s += strspn(s, delim), sort of). -+ */ -+cont: -+ c = *s++; -+ for (spanp = (char *)delim; (sc = *spanp++) != 0;) { -+ if (c == sc) -+ goto cont; -+ } -+ -+ if (c == 0) { /* no non-delimiter characters */ -+ *last = NULL; -+ return (NULL); -+ } -+ tok = s - 1; -+ -+ /* -+ * Scan token (scan for delimiters: s += strcspn(s, delim), sort of). -+ * Note that delim must have one NUL; we stop if we see that, too. -+ */ -+ for (;;) { -+ c = *s++; -+ spanp = (char *)delim; -+ do { -+ if ((sc = *spanp++) == c) { -+ if (c == 0) -+ s = NULL; -+ else -+ s[-1] = 0; -+ *last = s; -+ return (tok); -+ } -+ } while (sc != 0); -+ } -+ /* NOTREACHED */ -+} -Index: android-tools-4.2.2+git20130218/core/adbd/test_track_devices.c -=================================================================== ---- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ android-tools-4.2.2+git20130218/core/adbd/test_track_devices.c 2013-06-18 17:12:17.000000000 -0300 -@@ -0,0 +1,97 @@ -+/* a simple test program, connects to ADB server, and opens a track-devices session */ -+#include -+#include -+#include -+#include -+#include -+#include -+ -+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); -+} -Index: android-tools-4.2.2+git20130218/core/adbd/test_track_jdwp.c -=================================================================== ---- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ android-tools-4.2.2+git20130218/core/adbd/test_track_jdwp.c 2013-06-18 17:12:17.000000000 -0300 -@@ -0,0 +1,97 @@ -+/* a simple test program, connects to ADB server, and opens a track-devices session */ -+#include -+#include -+#include -+#include -+#include -+#include -+ -+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); -+} -Index: android-tools-4.2.2+git20130218/core/adbd/transport.c -=================================================================== ---- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ android-tools-4.2.2+git20130218/core/adbd/transport.c 2013-06-18 17:12:17.000000000 -0300 -@@ -0,0 +1,1186 @@ -+/* -+ * 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 -+#include -+#include -+#include -+#include -+ -+#include "sysdeps.h" -+ -+#define TRACE_TAG TRACE_TRANSPORT -+#include "adb.h" -+ -+static void transport_unref(atransport *t); -+ -+static atransport transport_list = { -+ .next = &transport_list, -+ .prev = &transport_list, -+}; -+ -+ADB_MUTEX_DEFINE( transport_lock ); -+ -+#if ADB_TRACE -+#define MAX_DUMP_HEX_LEN 16 -+static void dump_hex( const unsigned char* ptr, size_t len ) -+{ -+ int nn, len2 = len; -+ // Build a string instead of logging each character. -+ // MAX chars in 2 digit hex, one space, MAX chars, one '\0'. -+ char buffer[MAX_DUMP_HEX_LEN *2 + 1 + MAX_DUMP_HEX_LEN + 1 ], *pb = buffer; -+ -+ if (len2 > MAX_DUMP_HEX_LEN) len2 = MAX_DUMP_HEX_LEN; -+ -+ for (nn = 0; nn < len2; nn++) { -+ sprintf(pb, "%02x", ptr[nn]); -+ pb += 2; -+ } -+ sprintf(pb++, " "); -+ -+ for (nn = 0; nn < len2; nn++) { -+ int c = ptr[nn]; -+ if (c < 32 || c > 127) -+ c = '.'; -+ *pb++ = c; -+ } -+ *pb++ = '\0'; -+ DR("%s\n", buffer); -+} -+#endif -+ -+void -+kick_transport(atransport* t) -+{ -+ if (t && !t->kicked) -+ { -+ int kicked; -+ -+ adb_mutex_lock(&transport_lock); -+ kicked = t->kicked; -+ if (!kicked) -+ t->kicked = 1; -+ adb_mutex_unlock(&transport_lock); -+ -+ if (!kicked) -+ t->kick(t); -+ } -+} -+ -+void -+run_transport_disconnects(atransport* t) -+{ -+ adisconnect* dis = t->disconnects.next; -+ -+ D("%s: run_transport_disconnects\n", t->serial); -+ while (dis != &t->disconnects) { -+ adisconnect* next = dis->next; -+ dis->func( dis->opaque, t ); -+ dis = next; -+ } -+} -+ -+#if ADB_TRACE -+static void -+dump_packet(const char* name, const char* func, apacket* p) -+{ -+ unsigned command = p->msg.command; -+ int len = p->msg.data_length; -+ char cmd[9]; -+ char arg0[12], arg1[12]; -+ int n; -+ -+ for (n = 0; n < 4; n++) { -+ int b = (command >> (n*8)) & 255; -+ if (b < 32 || b >= 127) -+ break; -+ cmd[n] = (char)b; -+ } -+ if (n == 4) { -+ cmd[4] = 0; -+ } else { -+ /* There is some non-ASCII name in the command, so dump -+ * the hexadecimal value instead */ -+ snprintf(cmd, sizeof cmd, "%08x", command); -+ } -+ -+ if (p->msg.arg0 < 256U) -+ snprintf(arg0, sizeof arg0, "%d", p->msg.arg0); -+ else -+ snprintf(arg0, sizeof arg0, "0x%x", p->msg.arg0); -+ -+ if (p->msg.arg1 < 256U) -+ snprintf(arg1, sizeof arg1, "%d", p->msg.arg1); -+ else -+ snprintf(arg1, sizeof arg1, "0x%x", p->msg.arg1); -+ -+ D("%s: %s: [%s] arg0=%s arg1=%s (len=%d) ", -+ name, func, cmd, arg0, arg1, len); -+ dump_hex(p->data, len); -+} -+#endif /* ADB_TRACE */ -+ -+static int -+read_packet(int fd, const char* name, apacket** ppacket) -+{ -+ char *p = (char*)ppacket; /* really read a packet address */ -+ int r; -+ int len = sizeof(*ppacket); -+ char buff[8]; -+ if (!name) { -+ snprintf(buff, sizeof buff, "fd=%d", fd); -+ name = buff; -+ } -+ while(len > 0) { -+ r = adb_read(fd, p, len); -+ if(r > 0) { -+ len -= r; -+ p += r; -+ } else { -+ D("%s: read_packet (fd=%d), error ret=%d errno=%d: %s\n", name, fd, r, errno, strerror(errno)); -+ if((r < 0) && (errno == EINTR)) continue; -+ return -1; -+ } -+ } -+ -+#if ADB_TRACE -+ if (ADB_TRACING) { -+ dump_packet(name, "from remote", *ppacket); -+ } -+#endif -+ return 0; -+} -+ -+static int -+write_packet(int fd, const char* name, apacket** ppacket) -+{ -+ char *p = (char*) ppacket; /* we really write the packet address */ -+ int r, len = sizeof(ppacket); -+ char buff[8]; -+ if (!name) { -+ snprintf(buff, sizeof buff, "fd=%d", fd); -+ name = buff; -+ } -+ -+#if ADB_TRACE -+ if (ADB_TRACING) { -+ dump_packet(name, "to remote", *ppacket); -+ } -+#endif -+ len = sizeof(ppacket); -+ while(len > 0) { -+ r = adb_write(fd, p, len); -+ if(r > 0) { -+ len -= r; -+ p += r; -+ } else { -+ D("%s: write_packet (fd=%d) error ret=%d errno=%d: %s\n", name, fd, r, errno, strerror(errno)); -+ if((r < 0) && (errno == EINTR)) continue; -+ return -1; -+ } -+ } -+ return 0; -+} -+ -+static void transport_socket_events(int fd, unsigned events, void *_t) -+{ -+ atransport *t = _t; -+ D("transport_socket_events(fd=%d, events=%04x,...)\n", fd, events); -+ if(events & FDE_READ){ -+ apacket *p = 0; -+ if(read_packet(fd, t->serial, &p)){ -+ D("%s: failed to read packet from transport socket on fd %d\n", t->serial, fd); -+ } else { -+ handle_packet(p, (atransport *) _t); -+ } -+ } -+} -+ -+void send_packet(apacket *p, atransport *t) -+{ -+ unsigned char *x; -+ unsigned sum; -+ unsigned count; -+ -+ p->msg.magic = p->msg.command ^ 0xffffffff; -+ -+ count = p->msg.data_length; -+ x = (unsigned char *) p->data; -+ sum = 0; -+ while(count-- > 0){ -+ sum += *x++; -+ } -+ p->msg.data_check = sum; -+ -+ print_packet("send", p); -+ -+ if (t == NULL) { -+ D("Transport is null \n"); -+ // Zap errno because print_packet() and other stuff have errno effect. -+ errno = 0; -+ fatal_errno("Transport is null"); -+ } -+ -+ if(write_packet(t->transport_socket, t->serial, &p)){ -+ fatal_errno("cannot enqueue packet on transport socket"); -+ } -+} -+ -+/* The transport is opened by transport_register_func before -+** the input and output threads are started. -+** -+** The output thread issues a SYNC(1, token) message to let -+** the input thread know to start things up. In the event -+** of transport IO failure, the output thread will post a -+** SYNC(0,0) message to ensure shutdown. -+** -+** The transport will not actually be closed until both -+** threads exit, but the input thread will kick the transport -+** on its way out to disconnect the underlying device. -+*/ -+ -+static void *output_thread(void *_t) -+{ -+ atransport *t = _t; -+ apacket *p; -+ -+ D("%s: starting transport output thread on fd %d, SYNC online (%d)\n", -+ t->serial, t->fd, t->sync_token + 1); -+ p = get_apacket(); -+ p->msg.command = A_SYNC; -+ p->msg.arg0 = 1; -+ p->msg.arg1 = ++(t->sync_token); -+ p->msg.magic = A_SYNC ^ 0xffffffff; -+ if(write_packet(t->fd, t->serial, &p)) { -+ put_apacket(p); -+ D("%s: failed to write SYNC packet\n", t->serial); -+ goto oops; -+ } -+ -+ D("%s: data pump started\n", t->serial); -+ for(;;) { -+ p = get_apacket(); -+ -+ if(t->read_from_remote(p, t) == 0){ -+ D("%s: received remote packet, sending to transport\n", -+ t->serial); -+ if(write_packet(t->fd, t->serial, &p)){ -+ put_apacket(p); -+ D("%s: failed to write apacket to transport\n", t->serial); -+ goto oops; -+ } -+ } else { -+ D("%s: remote read failed for transport\n", t->serial); -+ put_apacket(p); -+ break; -+ } -+ } -+ -+ D("%s: SYNC offline for transport\n", t->serial); -+ p = get_apacket(); -+ p->msg.command = A_SYNC; -+ p->msg.arg0 = 0; -+ p->msg.arg1 = 0; -+ p->msg.magic = A_SYNC ^ 0xffffffff; -+ if(write_packet(t->fd, t->serial, &p)) { -+ put_apacket(p); -+ D("%s: failed to write SYNC apacket to transport", t->serial); -+ } -+ -+oops: -+ D("%s: transport output thread is exiting\n", t->serial); -+ kick_transport(t); -+ transport_unref(t); -+ return 0; -+} -+ -+static void *input_thread(void *_t) -+{ -+ atransport *t = _t; -+ apacket *p; -+ int active = 0; -+ -+ D("%s: starting transport input thread, reading from fd %d\n", -+ t->serial, t->fd); -+ -+ for(;;){ -+ if(read_packet(t->fd, t->serial, &p)) { -+ D("%s: failed to read apacket from transport on fd %d\n", -+ t->serial, t->fd ); -+ break; -+ } -+ if(p->msg.command == A_SYNC){ -+ if(p->msg.arg0 == 0) { -+ D("%s: transport SYNC offline\n", t->serial); -+ put_apacket(p); -+ break; -+ } else { -+ if(p->msg.arg1 == t->sync_token) { -+ D("%s: transport SYNC online\n", t->serial); -+ active = 1; -+ } else { -+ D("%s: transport ignoring SYNC %d != %d\n", -+ t->serial, p->msg.arg1, t->sync_token); -+ } -+ } -+ } else { -+ if(active) { -+ D("%s: transport got packet, sending to remote\n", t->serial); -+ t->write_to_remote(p, t); -+ } else { -+ D("%s: transport ignoring packet while offline\n", t->serial); -+ } -+ } -+ -+ put_apacket(p); -+ } -+ -+ // this is necessary to avoid a race condition that occured when a transport closes -+ // while a client socket is still active. -+ close_all_sockets(t); -+ -+ D("%s: transport input thread is exiting, fd %d\n", t->serial, t->fd); -+ kick_transport(t); -+ transport_unref(t); -+ return 0; -+} -+ -+ -+static int transport_registration_send = -1; -+static int transport_registration_recv = -1; -+static fdevent transport_registration_fde; -+ -+ -+#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, 0); -+ 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: %s removing and free'ing %d\n", t->serial, t->transport_socket); -+ -+ /* IMPORTANT: the remove closes one half of the -+ ** socket pair. The close closes the other half. -+ */ -+ fdevent_remove(&(t->transport_fde)); -+ adb_close(t->fd); -+ -+ adb_mutex_lock(&transport_lock); -+ t->next->prev = t->prev; -+ t->prev->next = t->next; -+ adb_mutex_unlock(&transport_lock); -+ -+ run_transport_disconnects(t); -+ -+ if (t->product) -+ free(t->product); -+ if (t->serial) -+ free(t->serial); -+ if (t->model) -+ free(t->model); -+ if (t->device) -+ free(t->device); -+ if (t->devpath) -+ free(t->devpath); -+ -+ memset(t,0xee,sizeof(atransport)); -+ free(t); -+ -+ update_transports(); -+ return; -+ } -+ -+ /* don't create transport threads for inaccessible devices */ -+ if (t->connection_state != CS_NOPERM) { -+ /* initial references are the two threads */ -+ t->ref_count = 2; -+ -+ if(adb_socketpair(s)) { -+ fatal_errno("cannot open transport socketpair"); -+ } -+ -+ D("transport: %s (%d,%d) starting\n", t->serial, s[0], s[1]); -+ -+ t->transport_socket = s[0]; -+ t->fd = s[1]; -+ -+ fdevent_install(&(t->transport_fde), -+ t->transport_socket, -+ transport_socket_events, -+ t); -+ -+ fdevent_set(&(t->transport_fde), FDE_READ); -+ -+ if(adb_thread_create(&input_thread_ptr, input_thread, t)){ -+ fatal_errno("cannot create input thread"); -+ } -+ -+ if(adb_thread_create(&output_thread_ptr, output_thread, t)){ -+ fatal_errno("cannot create output thread"); -+ } -+ } -+ -+ /* put us on the master device list */ -+ adb_mutex_lock(&transport_lock); -+ t->next = &transport_list; -+ t->prev = transport_list.prev; -+ t->next->prev = t; -+ t->prev->next = t; -+ adb_mutex_unlock(&transport_lock); -+ -+ t->disconnects.next = t->disconnects.prev = &t->disconnects; -+ -+ update_transports(); -+} -+ -+void init_transport_registration(void) -+{ -+ int s[2]; -+ -+ if(adb_socketpair(s)){ -+ fatal_errno("cannot open transport registration socketpair"); -+ } -+ -+ transport_registration_send = s[0]; -+ transport_registration_recv = s[1]; -+ -+ fdevent_install(&transport_registration_fde, -+ transport_registration_recv, -+ transport_registration_func, -+ 0); -+ -+ fdevent_set(&transport_registration_fde, FDE_READ); -+} -+ -+/* the fdevent select pump is single threaded */ -+static void register_transport(atransport *transport) -+{ -+ tmsg m; -+ m.transport = transport; -+ m.action = 1; -+ D("transport: %s registered\n", transport->serial); -+ if(transport_write_action(transport_registration_send, &m)) { -+ fatal_errno("cannot write transport registration socket\n"); -+ } -+} -+ -+static void remove_transport(atransport *transport) -+{ -+ tmsg m; -+ m.transport = transport; -+ m.action = 0; -+ D("transport: %s removed\n", transport->serial); -+ if(transport_write_action(transport_registration_send, &m)) { -+ fatal_errno("cannot write transport registration socket\n"); -+ } -+} -+ -+ -+static void transport_unref_locked(atransport *t) -+{ -+ t->ref_count--; -+ if (t->ref_count == 0) { -+ D("transport: %s unref (kicking and closing)\n", t->serial); -+ if (!t->kicked) { -+ t->kicked = 1; -+ t->kick(t); -+ } -+ t->close(t); -+ remove_transport(t); -+ } else { -+ D("transport: %s unref (count=%d)\n", t->serial, t->ref_count); -+ } -+} -+ -+static void transport_unref(atransport *t) -+{ -+ if (t) { -+ adb_mutex_lock(&transport_lock); -+ transport_unref_locked(t); -+ adb_mutex_unlock(&transport_lock); -+ } -+} -+ -+void add_transport_disconnect(atransport* t, adisconnect* dis) -+{ -+ adb_mutex_lock(&transport_lock); -+ dis->next = &t->disconnects; -+ dis->prev = dis->next->prev; -+ dis->prev->next = dis; -+ dis->next->prev = dis; -+ adb_mutex_unlock(&transport_lock); -+} -+ -+void remove_transport_disconnect(atransport* t, adisconnect* dis) -+{ -+ dis->prev->next = dis->next; -+ dis->next->prev = dis->prev; -+ dis->next = dis->prev = dis; -+} -+ -+static int qual_char_is_invalid(char ch) -+{ -+ if ('A' <= ch && ch <= 'Z') -+ return 0; -+ if ('a' <= ch && ch <= 'z') -+ return 0; -+ if ('0' <= ch && ch <= '9') -+ return 0; -+ return 1; -+} -+ -+static int qual_match(const char *to_test, -+ const char *prefix, const char *qual, int sanitize_qual) -+{ -+ if (!to_test || !*to_test) -+ /* Return true if both the qual and to_test are null strings. */ -+ return !qual || !*qual; -+ -+ if (!qual) -+ return 0; -+ -+ if (prefix) { -+ while (*prefix) { -+ if (*prefix++ != *to_test++) -+ return 0; -+ } -+ } -+ -+ while (*qual) { -+ char ch = *qual++; -+ if (sanitize_qual && qual_char_is_invalid(ch)) -+ ch = '_'; -+ if (ch != *to_test++) -+ return 0; -+ } -+ -+ /* Everything matched so far. Return true if *to_test is a NUL. */ -+ return !*to_test; -+} -+ -+atransport *acquire_one_transport(int state, transport_type ttype, const char* serial, char** error_out) -+{ -+ atransport *t; -+ atransport *result = NULL; -+ int ambiguous = 0; -+ -+retry: -+ if (error_out) -+ *error_out = "device not found"; -+ -+ adb_mutex_lock(&transport_lock); -+ for (t = transport_list.next; t != &transport_list; t = t->next) { -+ if (t->connection_state == CS_NOPERM) { -+ if (error_out) -+ *error_out = "insufficient permissions for device"; -+ continue; -+ } -+ -+ /* check for matching serial number */ -+ if (serial) { -+ if ((t->serial && !strcmp(serial, t->serial)) || -+ (t->devpath && !strcmp(serial, t->devpath)) || -+ qual_match(serial, "product:", t->product, 0) || -+ qual_match(serial, "model:", t->model, 1) || -+ qual_match(serial, "device:", t->device, 0)) { -+ if (result) { -+ if (error_out) -+ *error_out = "more than one device"; -+ ambiguous = 1; -+ result = NULL; -+ break; -+ } -+ result = t; -+ } -+ } 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"; -+ case CS_SIDELOAD: return "sideload"; -+ case CS_NOPERM: return "no permissions"; -+ default: return "unknown"; -+ } -+} -+ -+static void add_qual(char **buf, size_t *buf_size, -+ const char *prefix, const char *qual, int sanitize_qual) -+{ -+ size_t len; -+ int prefix_len; -+ -+ if (!buf || !*buf || !buf_size || !*buf_size || !qual || !*qual) -+ return; -+ -+ len = snprintf(*buf, *buf_size, "%s%n%s", prefix, &prefix_len, qual); -+ -+ if (sanitize_qual) { -+ char *cp; -+ for (cp = *buf + prefix_len; cp < *buf + len; cp++) { -+ if (qual_char_is_invalid(*cp)) -+ *cp = '_'; -+ } -+ } -+ -+ *buf_size -= len; -+ *buf += len; -+} -+ -+static size_t format_transport(atransport *t, char *buf, size_t bufsize, -+ int long_listing) -+{ -+ const char* serial = t->serial; -+ if (!serial || !serial[0]) -+ serial = "????????????"; -+ -+ if (!long_listing) { -+ return snprintf(buf, bufsize, "%s\t%s\n", serial, statename(t)); -+ } else { -+ size_t len, remaining = bufsize; -+ -+ len = snprintf(buf, remaining, "%-22s %s", serial, statename(t)); -+ remaining -= len; -+ buf += len; -+ -+ add_qual(&buf, &remaining, " ", t->devpath, 0); -+ add_qual(&buf, &remaining, " product:", t->product, 0); -+ add_qual(&buf, &remaining, " model:", t->model, 1); -+ add_qual(&buf, &remaining, " device:", t->device, 0); -+ -+ len = snprintf(buf, remaining, "\n"); -+ remaining -= len; -+ -+ return bufsize - remaining; -+ } -+} -+ -+int list_transports(char *buf, size_t bufsize, int long_listing) -+{ -+ 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 = format_transport(t, p, end - p, long_listing); -+ 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, int local) -+{ -+ atransport *t = calloc(1, sizeof(atransport)); -+ char buff[32]; -+ -+ if (!serial) { -+ snprintf(buff, sizeof buff, "T-%p", t); -+ serial = buff; -+ } -+ D("transport: %s init'ing for socket %d, on port %d\n", serial, s, port); -+ if ( init_socket_transport(t, s, port, local) < 0 ) { -+ adb_close(s); -+ free(t); -+ return; -+ } -+ if(serial) { -+ t->serial = strdup(serial); -+ } -+ register_transport(t); -+} -+ -+#if ADB_HOST -+atransport *find_transport(const char *serial) -+{ -+ atransport *t; -+ -+ adb_mutex_lock(&transport_lock); -+ for(t = transport_list.next; t != &transport_list; t = t->next) { -+ if (t->serial && !strcmp(serial, t->serial)) { -+ break; -+ } -+ } -+ adb_mutex_unlock(&transport_lock); -+ -+ if (t != &transport_list) -+ return t; -+ else -+ return 0; -+} -+ -+void unregister_transport(atransport *t) -+{ -+ adb_mutex_lock(&transport_lock); -+ t->next->prev = t->prev; -+ t->prev->next = t->next; -+ adb_mutex_unlock(&transport_lock); -+ -+ kick_transport(t); -+ transport_unref(t); -+} -+ -+// unregisters all non-emulator TCP transports -+void unregister_all_tcp_transports() -+{ -+ atransport *t, *next; -+ adb_mutex_lock(&transport_lock); -+ for (t = transport_list.next; t != &transport_list; t = next) { -+ next = t->next; -+ if (t->type == kTransportLocal && t->adb_port == 0) { -+ t->next->prev = t->prev; -+ t->prev->next = next; -+ // we cannot call kick_transport when holding transport_lock -+ if (!t->kicked) -+ { -+ t->kicked = 1; -+ t->kick(t); -+ } -+ transport_unref_locked(t); -+ } -+ } -+ -+ adb_mutex_unlock(&transport_lock); -+} -+ -+#endif -+ -+void register_usb_transport(usb_handle *usb, const char *serial, const char *devpath, unsigned writeable) -+{ -+ atransport *t = calloc(1, sizeof(atransport)); -+ D("transport: %p init'ing for usb_handle %p (sn='%s')\n", t, usb, -+ serial ? serial : ""); -+ init_usb_transport(t, usb, (writeable ? CS_OFFLINE : CS_NOPERM)); -+ if(serial) { -+ t->serial = strdup(serial); -+ } -+ if(devpath) { -+ t->devpath = strdup(devpath); -+ } -+ register_transport(t); -+} -+ -+/* this should only be used for transports with connection_state == CS_NOPERM */ -+void unregister_usb_transport(usb_handle *usb) -+{ -+ atransport *t; -+ adb_mutex_lock(&transport_lock); -+ for(t = transport_list.next; t != &transport_list; t = t->next) { -+ if (t->usb == usb && t->connection_state == CS_NOPERM) { -+ t->next->prev = t->prev; -+ t->prev->next = t->next; -+ break; -+ } -+ } -+ adb_mutex_unlock(&transport_lock); -+} -+ -+#undef TRACE_TAG -+#define TRACE_TAG TRACE_RWX -+ -+int readx(int fd, void *ptr, size_t len) -+{ -+ char *p = ptr; -+ int r; -+#if ADB_TRACE -+ int len0 = len; -+#endif -+ D("readx: fd=%d wanted=%d\n", fd, (int)len); -+ while(len > 0) { -+ r = adb_read(fd, p, len); -+ if(r > 0) { -+ len -= r; -+ p += r; -+ } else { -+ if (r < 0) { -+ D("readx: fd=%d error %d: %s\n", fd, errno, strerror(errno)); -+ if (errno == EINTR) -+ continue; -+ } else { -+ D("readx: fd=%d disconnected\n", fd); -+ } -+ return -1; -+ } -+ } -+ -+#if ADB_TRACE -+ D("readx: fd=%d wanted=%d got=%d\n", fd, len0, len0 - len); -+ dump_hex( ptr, len0 ); -+#endif -+ return 0; -+} -+ -+int writex(int fd, const void *ptr, size_t len) -+{ -+ char *p = (char*) ptr; -+ int r; -+ -+#if ADB_TRACE -+ D("writex: fd=%d len=%d: ", fd, (int)len); -+ dump_hex( ptr, len ); -+#endif -+ while(len > 0) { -+ r = adb_write(fd, p, len); -+ if(r > 0) { -+ len -= r; -+ p += r; -+ } else { -+ if (r < 0) { -+ D("writex: fd=%d error %d: %s\n", fd, errno, strerror(errno)); -+ if (errno == EINTR) -+ continue; -+ } else { -+ D("writex: fd=%d disconnected\n", fd); -+ } -+ return -1; -+ } -+ } -+ return 0; -+} -+ -+int check_header(apacket *p) -+{ -+ if(p->msg.magic != (p->msg.command ^ 0xffffffff)) { -+ D("check_header(): invalid magic\n"); -+ return -1; -+ } -+ -+ if(p->msg.data_length > MAX_PAYLOAD) { -+ D("check_header(): %d > MAX_PAYLOAD\n", p->msg.data_length); -+ return -1; -+ } -+ -+ return 0; -+} -+ -+int check_data(apacket *p) -+{ -+ unsigned count, sum; -+ unsigned char *x; -+ -+ count = p->msg.data_length; -+ x = p->data; -+ sum = 0; -+ while(count-- > 0) { -+ sum += *x++; -+ } -+ -+ if(sum != p->msg.data_check) { -+ return -1; -+ } else { -+ return 0; -+ } -+} -Index: android-tools-4.2.2+git20130218/core/adbd/transport.h -=================================================================== ---- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ android-tools-4.2.2+git20130218/core/adbd/transport.h 2013-06-18 17:12:17.000000000 -0300 -@@ -0,0 +1,26 @@ -+/* -+ * Copyright (C) 2011 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 __TRANSPORT_H -+#define __TRANSPORT_H -+ -+/* convenience wrappers around read/write that will retry on -+** EINTR and/or short read/write. Returns 0 on success, -1 -+** on error or EOF. -+*/ -+int readx(int fd, void *ptr, size_t len); -+int writex(int fd, const void *ptr, size_t len); -+#endif /* __TRANSPORT_H */ -Index: android-tools-4.2.2+git20130218/core/adbd/transport_local.c -=================================================================== ---- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ android-tools-4.2.2+git20130218/core/adbd/transport_local.c 2013-06-18 17:12:17.000000000 -0300 -@@ -0,0 +1,441 @@ -+/* -+ * 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 -+#include -+#include -+#include -+ -+#include "sysdeps.h" -+#include -+ -+#define TRACE_TAG TRACE_TRANSPORT -+#include "adb.h" -+ -+#ifdef HAVE_BIG_ENDIAN -+#define H4(x) (((x) & 0xFF000000) >> 24) | (((x) & 0x00FF0000) >> 8) | (((x) & 0x0000FF00) << 8) | (((x) & 0x000000FF) << 24) -+static inline void fix_endians(apacket *p) -+{ -+ p->msg.command = H4(p->msg.command); -+ p->msg.arg0 = H4(p->msg.arg0); -+ p->msg.arg1 = H4(p->msg.arg1); -+ p->msg.data_length = H4(p->msg.data_length); -+ p->msg.data_check = H4(p->msg.data_check); -+ p->msg.magic = H4(p->msg.magic); -+} -+#else -+#define fix_endians(p) do {} while (0) -+#endif -+ -+#if ADB_HOST -+/* we keep a list of opened transports. The atransport struct knows to which -+ * local transport it is connected. 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 HAVE_BIG_ENDIAN -+ 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 HAVE_BIG_ENDIAN -+ 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) { -+ return local_connect_arbitrary_ports(port-1, port); -+} -+ -+int local_connect_arbitrary_ports(int console_port, int adb_port) -+{ -+ char buf[64]; -+ int fd = -1; -+ -+#if ADB_HOST -+ const char *host = getenv("ADBHOST"); -+ if (host) { -+ fd = socket_network_client(host, adb_port, SOCK_STREAM); -+ } -+#endif -+ if (fd < 0) { -+ fd = socket_loopback_client(adb_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, console_port); -+ register_socket_transport(fd, buf, adb_port, 1); -+ return 0; -+ } -+ return -1; -+} -+ -+ -+static void *client_socket_thread(void *x) -+{ -+#if ADB_HOST -+ int port = DEFAULT_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 * arg) -+{ -+ int serverfd, fd; -+ struct sockaddr addr; -+ socklen_t alen; -+ int port = (int)arg; -+ -+ D("transport: server_socket_thread() starting\n"); -+ serverfd = -1; -+ for(;;) { -+ if(serverfd == -1) { -+ serverfd = socket_inaddr_any_server(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", 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", port, 1); -+ } -+ } -+ D("transport: server_socket_thread() exiting\n"); -+ return 0; -+} -+ -+/* This is relevant only for ADB daemon running inside the emulator. */ -+#if !ADB_HOST -+/* -+ * Redefine open and write for qemu_pipe.h that contains inlined references -+ * to those routines. We will redifine them back after qemu_pipe.h inclusion. -+ */ -+#undef open -+#undef write -+#define open adb_open -+#define write adb_write -+#include "qemu_pipe.h" -+#undef open -+#undef write -+#define open ___xxx_open -+#define write ___xxx_write -+ -+/* A worker thread that monitors host connections, and registers a transport for -+ * every new host connection. This thread replaces server_socket_thread on -+ * condition that adbd daemon runs inside the emulator, and emulator uses QEMUD -+ * pipe to communicate with adbd daemon inside the guest. This is done in order -+ * to provide more robust communication channel between ADB host and guest. The -+ * main issue with server_socket_thread approach is that it runs on top of TCP, -+ * and thus is sensitive to network disruptions. For instance, the -+ * ConnectionManager may decide to reset all network connections, in which case -+ * the connection between ADB host and guest will be lost. To make ADB traffic -+ * independent from the network, we use here 'adb' QEMUD service to transfer data -+ * between the host, and the guest. See external/qemu/android/adb-*.* that -+ * implements the emulator's side of the protocol. Another advantage of using -+ * QEMUD approach is that ADB will be up much sooner, since it doesn't depend -+ * anymore on network being set up. -+ * The guest side of the protocol contains the following phases: -+ * - Connect with adb QEMUD service. In this phase a handle to 'adb' QEMUD service -+ * is opened, and it becomes clear whether or not emulator supports that -+ * protocol. -+ * - Wait for the ADB host to create connection with the guest. This is done by -+ * sending an 'accept' request to the adb QEMUD service, and waiting on -+ * response. -+ * - When new ADB host connection is accepted, the connection with adb QEMUD -+ * service is registered as the transport, and a 'start' request is sent to the -+ * adb QEMUD service, indicating that the guest is ready to receive messages. -+ * Note that the guest will ignore messages sent down from the emulator before -+ * the transport registration is completed. That's why we need to send the -+ * 'start' request after the transport is registered. -+ */ -+static void *qemu_socket_thread(void * arg) -+{ -+/* 'accept' request to the adb QEMUD service. */ -+static const char _accept_req[] = "accept"; -+/* 'start' request to the adb QEMUD service. */ -+static const char _start_req[] = "start"; -+/* 'ok' reply from the adb QEMUD service. */ -+static const char _ok_resp[] = "ok"; -+ -+ const int port = (int)arg; -+ int res, fd; -+ char tmp[256]; -+ char con_name[32]; -+ -+ D("transport: qemu_socket_thread() starting\n"); -+ -+ /* adb QEMUD service connection request. */ -+ snprintf(con_name, sizeof(con_name), "qemud:adb:%d", port); -+ -+ /* Connect to the adb QEMUD service. */ -+ fd = qemu_pipe_open(con_name); -+ if (fd < 0) { -+ /* This could be an older version of the emulator, that doesn't -+ * implement adb QEMUD service. Fall back to the old TCP way. */ -+ adb_thread_t thr; -+ D("adb service is not available. Falling back to TCP socket.\n"); -+ adb_thread_create(&thr, server_socket_thread, arg); -+ return 0; -+ } -+ -+ for(;;) { -+ /* -+ * Wait till the host creates a new connection. -+ */ -+ -+ /* Send the 'accept' request. */ -+ res = adb_write(fd, _accept_req, strlen(_accept_req)); -+ if ((size_t)res == strlen(_accept_req)) { -+ /* Wait for the response. In the response we expect 'ok' on success, -+ * or 'ko' on failure. */ -+ res = adb_read(fd, tmp, sizeof(tmp)); -+ if (res != 2 || memcmp(tmp, _ok_resp, 2)) { -+ D("Accepting ADB host connection has failed.\n"); -+ adb_close(fd); -+ } else { -+ /* Host is connected. Register the transport, and start the -+ * exchange. */ -+ register_socket_transport(fd, "host", port, 1); -+ adb_write(fd, _start_req, strlen(_start_req)); -+ } -+ -+ /* Prepare for accepting of the next ADB host connection. */ -+ fd = qemu_pipe_open(con_name); -+ if (fd < 0) { -+ D("adb service become unavailable.\n"); -+ return 0; -+ } -+ } else { -+ D("Unable to send the '%s' request to ADB service.\n", _accept_req); -+ return 0; -+ } -+ } -+ D("transport: qemu_socket_thread() exiting\n"); -+ return 0; -+} -+#endif // !ADB_HOST -+ -+void local_init(int port) -+{ -+ adb_thread_t thr; -+ void* (*func)(void *); -+ -+ if(HOST) { -+ func = client_socket_thread; -+ } else { -+#if ADB_HOST -+ func = server_socket_thread; -+#else -+ /* For the adbd daemon in the system image we need to distinguish -+ * between the device, and the emulator. */ -+ char is_qemu[PROPERTY_VALUE_MAX]; -+ //property_get("ro.kernel.qemu", is_qemu, ""); -+ //if (!strcmp(is_qemu, "1")) { -+ /* Running inside the emulator: use QEMUD pipe as the transport. */ -+ // func = qemu_socket_thread; -+ //} else { -+ /* Running inside the device: use TCP socket as the transport. */ -+ func = server_socket_thread; -+ //} -+#endif // !ADB_HOST -+ } -+ -+ D("transport: local %s init\n", HOST ? "client" : "server"); -+ -+ if(adb_thread_create(&thr, func, (void *)port)) { -+ 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_shutdown(fd); -+ 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); -+} -+ -+ -+#if ADB_HOST -+/* Only call this function if you already hold local_transports_lock. */ -+atransport* find_emulator_transport_by_adb_port_locked(int adb_port) -+{ -+ int i; -+ for (i = 0; i < ADB_LOCAL_TRANSPORT_MAX; i++) { -+ if (local_transports[i] && local_transports[i]->adb_port == adb_port) { -+ return local_transports[i]; -+ } -+ } -+ return NULL; -+} -+ -+atransport* find_emulator_transport_by_adb_port(int adb_port) -+{ -+ adb_mutex_lock( &local_transports_lock ); -+ atransport* result = find_emulator_transport_by_adb_port_locked(adb_port); -+ adb_mutex_unlock( &local_transports_lock ); -+ return result; -+} -+ -+/* Only call this function if you already hold local_transports_lock. */ -+int get_available_local_transport_index_locked() -+{ -+ int i; -+ for (i = 0; i < ADB_LOCAL_TRANSPORT_MAX; i++) { -+ if (local_transports[i] == NULL) { -+ return i; -+ } -+ } -+ return -1; -+} -+ -+int get_available_local_transport_index() -+{ -+ adb_mutex_lock( &local_transports_lock ); -+ int result = get_available_local_transport_index_locked(); -+ adb_mutex_unlock( &local_transports_lock ); -+ return result; -+} -+#endif -+ -+int init_socket_transport(atransport *t, int s, int adb_port, int local) -+{ -+ 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; -+ t->adb_port = 0; -+ -+#if ADB_HOST -+ if (HOST && local) { -+ adb_mutex_lock( &local_transports_lock ); -+ { -+ t->adb_port = adb_port; -+ atransport* existing_transport = -+ find_emulator_transport_by_adb_port_locked(adb_port); -+ int index = get_available_local_transport_index_locked(); -+ if (existing_transport != NULL) { -+ D("local transport for port %d already registered (%p)?\n", -+ adb_port, existing_transport); -+ fail = -1; -+ } else if (index < 0) { -+ // Too many emulators. -+ D("cannot register more emulators. Maximum is %d\n", -+ ADB_LOCAL_TRANSPORT_MAX); -+ fail = -1; -+ } else { -+ local_transports[index] = t; -+ } -+ } -+ adb_mutex_unlock( &local_transports_lock ); -+ } -+#endif -+ return fail; -+} -Index: android-tools-4.2.2+git20130218/core/adbd/transport_usb.c -=================================================================== ---- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ android-tools-4.2.2+git20130218/core/adbd/transport_usb.c 2013-06-18 17:12:17.000000000 -0300 -@@ -0,0 +1,148 @@ -+/* -+ * 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 -+#include -+#include -+ -+#include -+ -+#define TRACE_TAG TRACE_TRANSPORT -+#include "adb.h" -+ -+#if ADB_HOST -+#include "usb_vendors.h" -+#endif -+ -+#ifdef HAVE_BIG_ENDIAN -+#define H4(x) (((x) & 0xFF000000) >> 24) | (((x) & 0x00FF0000) >> 8) | (((x) & 0x0000FF00) << 8) | (((x) & 0x000000FF) << 24) -+static inline void fix_endians(apacket *p) -+{ -+ p->msg.command = H4(p->msg.command); -+ p->msg.arg0 = H4(p->msg.arg0); -+ p->msg.arg1 = H4(p->msg.arg1); -+ p->msg.data_length = H4(p->msg.data_length); -+ p->msg.data_check = H4(p->msg.data_check); -+ p->msg.magic = H4(p->msg.magic); -+} -+unsigned host_to_le32(unsigned n) -+{ -+ return H4(n); -+} -+#else -+#define fix_endians(p) do {} while (0) -+unsigned host_to_le32(unsigned n) -+{ -+ return n; -+} -+#endif -+ -+static int remote_read(apacket *p, atransport *t) -+{ -+ if(usb_read(t->usb, &p->msg, sizeof(amessage))){ -+ D("remote usb: read terminated (message)\n"); -+ return -1; -+ } -+ -+ fix_endians(p); -+ -+ if(check_header(p)) { -+ D("remote usb: check_header failed\n"); -+ return -1; -+ } -+ -+ if(p->msg.data_length) { -+ if(usb_read(t->usb, p->data, p->msg.data_length)){ -+ D("remote usb: terminated (data)\n"); -+ return -1; -+ } -+ } -+ -+ if(check_data(p)) { -+ D("remote usb: check_data failed\n"); -+ return -1; -+ } -+ -+ return 0; -+} -+ -+static int remote_write(apacket *p, atransport *t) -+{ -+ unsigned size = p->msg.data_length; -+ -+ fix_endians(p); -+ -+ if(usb_write(t->usb, &p->msg, sizeof(amessage))) { -+ D("remote usb: 1 - write terminated\n"); -+ return -1; -+ } -+ if(p->msg.data_length == 0) return 0; -+ if(usb_write(t->usb, &p->data, size)) { -+ D("remote usb: 2 - write terminated\n"); -+ return -1; -+ } -+ -+ return 0; -+} -+ -+static void remote_close(atransport *t) -+{ -+ usb_close(t->usb); -+ t->usb = 0; -+} -+ -+static void remote_kick(atransport *t) -+{ -+ usb_kick(t->usb); -+} -+ -+void init_usb_transport(atransport *t, usb_handle *h, int state) -+{ -+ D("transport: usb\n"); -+ t->close = remote_close; -+ t->kick = remote_kick; -+ t->read_from_remote = remote_read; -+ t->write_to_remote = remote_write; -+ t->sync_token = 1; -+ t->connection_state = state; -+ t->type = kTransportUsb; -+ t->usb = h; -+ -+#if ADB_HOST -+ HOST = 1; -+#else -+ HOST = 0; -+#endif -+} -+ -+#if ADB_HOST -+int is_adb_interface(int vid, int pid, int usb_class, int usb_subclass, int usb_protocol) -+{ -+ unsigned i; -+ for (i = 0; i < vendorIdCount; i++) { -+ if (vid == vendorIds[i]) { -+ if (usb_class == ADB_CLASS && usb_subclass == ADB_SUBCLASS && -+ usb_protocol == ADB_PROTOCOL) { -+ return 1; -+ } -+ -+ return 0; -+ } -+ } -+ -+ return 0; -+} -+#endif -Index: android-tools-4.2.2+git20130218/core/adbd/usb_libusb.c -=================================================================== ---- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ android-tools-4.2.2+git20130218/core/adbd/usb_libusb.c 2013-06-18 17:12:17.000000000 -0300 -@@ -0,0 +1,657 @@ -+/* -+ * Copyright (C) 2009 bsdroid project -+ * Alexey Tarasov -+ * -+ * 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 -+#include -+#include -+#include -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include "sysdeps.h" -+ -+#define TRACE_TAG TRACE_USB -+#include "adb.h" -+ -+static adb_mutex_t usb_lock = ADB_MUTEX_INITIALIZER; -+static libusb_context *ctx = NULL; -+ -+struct usb_handle -+{ -+ usb_handle *prev; -+ usb_handle *next; -+ -+ libusb_device *dev; -+ libusb_device_handle *devh; -+ int interface; -+ uint8_t dev_bus; -+ uint8_t dev_addr; -+ -+ int zero_mask; -+ unsigned char end_point_address[2]; -+ char serial[128]; -+ -+ adb_cond_t notify; -+ adb_mutex_t lock; -+}; -+ -+static struct usb_handle handle_list = { -+ .prev = &handle_list, -+ .next = &handle_list, -+}; -+ -+void -+usb_cleanup() -+{ -+ libusb_exit(ctx); -+} -+ -+void -+report_bulk_libusb_error(int r) -+{ -+ switch (r) { -+ case LIBUSB_ERROR_TIMEOUT: -+ D("Transfer timeout\n"); -+ break; -+ -+ case LIBUSB_ERROR_PIPE: -+ D("Control request is not supported\n"); -+ break; -+ -+ case LIBUSB_ERROR_OVERFLOW: -+ D("Device offered more data\n"); -+ break; -+ -+ case LIBUSB_ERROR_NO_DEVICE : -+ D("Device was disconnected\n"); -+ break; -+ -+ default: -+ D("Error %d during transfer\n", r); -+ break; -+ }; -+} -+ -+static int -+usb_bulk_write(usb_handle *uh, const void *data, int len) -+{ -+ int r = 0; -+ int transferred = 0; -+ -+ r = libusb_bulk_transfer(uh->devh, uh->end_point_address[1], (void *)data, len, -+ &transferred, 0); -+ -+ if (r != 0) { -+ D("usb_bulk_write(): "); -+ report_bulk_libusb_error(r); -+ return r; -+ } -+ -+ return (transferred); -+} -+ -+static int -+usb_bulk_read(usb_handle *uh, void *data, int len) -+{ -+ int r = 0; -+ int transferred = 0; -+ -+ r = libusb_bulk_transfer(uh->devh, uh->end_point_address[0], data, len, -+ &transferred, 0); -+ -+ if (r != 0) { -+ D("usb_bulk_read(): "); -+ report_bulk_libusb_error(r); -+ return r; -+ } -+ -+ return (transferred); -+} -+ -+int -+usb_write(struct usb_handle *uh, const void *_data, int len) -+{ -+ unsigned char *data = (unsigned char*) _data; -+ int n; -+ int need_zero = 0; -+ -+ if (uh->zero_mask == 1) { -+ if (!(len & uh->zero_mask)) { -+ need_zero = 1; -+ } -+ } -+ -+ D("usb_write(): %p:%d -> transport %p\n", _data, len, uh); -+ -+ while (len > 0) { -+ int xfer = (len > 4096) ? 4096 : len; -+ -+ n = usb_bulk_write(uh, data, xfer); -+ -+ if (n != xfer) { -+ D("usb_write(): failed for transport %p (%d bytes left)\n", uh, len); -+ return -1; -+ } -+ -+ len -= xfer; -+ data += xfer; -+ } -+ -+ if (need_zero){ -+ n = usb_bulk_write(uh, _data, 0); -+ -+ if (n < 0) { -+ D("usb_write(): failed to finish operation for transport %p\n", uh); -+ } -+ return n; -+ } -+ -+ return 0; -+} -+ -+int -+usb_read(struct usb_handle *uh, void *_data, int len) -+{ -+ unsigned char *data = (unsigned char*) _data; -+ int n; -+ -+ D("usb_read(): %p:%d <- transport %p\n", _data, len, uh); -+ -+ while (len > 0) { -+ int xfer = (len > 4096) ? 4096 : len; -+ -+ n = usb_bulk_read(uh, data, xfer); -+ -+ if (n != xfer) { -+ if (n > 0) { -+ data += n; -+ len -= n; -+ continue; -+ } -+ -+ D("usb_read(): failed for transport %p (%d bytes left)\n", uh, len); -+ return -1; -+ } -+ -+ len -= xfer; -+ data += xfer; -+ } -+ -+ return 0; -+ } -+ -+int -+usb_close(struct usb_handle *h) -+{ -+ D("usb_close(): closing transport %p\n", h); -+ adb_mutex_lock(&usb_lock); -+ -+ h->next->prev = h->prev; -+ h->prev->next = h->next; -+ h->prev = NULL; -+ h->next = NULL; -+ -+ libusb_release_interface(h->devh, h->interface); -+ libusb_close(h->devh); -+ libusb_unref_device(h->dev); -+ -+ adb_mutex_unlock(&usb_lock); -+ -+ free(h); -+ -+ return (0); -+} -+ -+void usb_kick(struct usb_handle *h) -+{ -+ D("usb_cick(): kicking transport %p\n", h); -+ -+ adb_mutex_lock(&h->lock); -+ unregister_usb_transport(h); -+ adb_mutex_unlock(&h->lock); -+ -+ h->next->prev = h->prev; -+ h->prev->next = h->next; -+ h->prev = NULL; -+ h->next = NULL; -+ -+ libusb_release_interface(h->devh, h->interface); -+ libusb_close(h->devh); -+ libusb_unref_device(h->dev); -+ free(h); -+} -+ -+int -+check_usb_interface(libusb_interface *interface, -+ libusb_device_descriptor *desc, -+ struct usb_handle *uh) -+{ -+ int e; -+ -+ if (interface->num_altsetting == 0) { -+ D("check_usb_interface(): No interface settings\n"); -+ return -1; -+ } -+ -+ libusb_interface_descriptor *idesc = &interface->altsetting[0]; -+ -+ if (idesc->bNumEndpoints != 2) { -+ D("check_usb_interface(): Interface have not 2 endpoints, ignoring\n"); -+ return -1; -+ } -+ -+ for (e = 0; e < idesc->bNumEndpoints; e++) { -+ libusb_endpoint_descriptor *edesc = &idesc->endpoint[e]; -+ -+ if (edesc->bmAttributes != LIBUSB_TRANSFER_TYPE_BULK) { -+ D("check_usb_interface(): Endpoint (%u) is not bulk (%u), ignoring\n", -+ edesc->bmAttributes, LIBUSB_TRANSFER_TYPE_BULK); -+ return -1; -+ } -+ -+ if (edesc->bEndpointAddress & LIBUSB_ENDPOINT_IN) -+ uh->end_point_address[0] = edesc->bEndpointAddress; -+ else -+ uh->end_point_address[1] = edesc->bEndpointAddress; -+ -+ /* aproto 01 needs 0 termination */ -+ if (idesc->bInterfaceProtocol == 0x01) { -+ uh->zero_mask = edesc->wMaxPacketSize - 1; -+ D("check_usb_interface(): Forced Android interface protocol v.1\n"); -+ } -+ } -+ -+ D("check_usb_interface(): Device: %04x:%04x " -+ "iclass: %x, isclass: %x, iproto: %x ep: %x/%x-> ", -+ desc->idVendor, desc->idProduct, idesc->bInterfaceClass, -+ idesc->bInterfaceSubClass, idesc->bInterfaceProtocol, -+ uh->end_point_address[0], uh->end_point_address[1]); -+ -+ if (!is_adb_interface(desc->idVendor, desc->idProduct, -+ idesc->bInterfaceClass, idesc->bInterfaceSubClass, -+ idesc->bInterfaceProtocol)) -+ { -+ D("not matches\n"); -+ return -1; -+ } -+ -+ D("matches\n"); -+ return 1; -+} -+ -+int -+check_usb_interfaces(libusb_config_descriptor *config, -+ libusb_device_descriptor *desc, struct usb_handle *uh) -+{ -+ int i; -+ -+ for (i = 0; i < config->bNumInterfaces; ++i) { -+ if (check_usb_interface(&config->interface[i], desc, uh) != -1) { -+ /* found some interface and saved information about it */ -+ D("check_usb_interfaces(): Interface %d of %04x:%04x " -+ "matches Android device\n", i, desc->idVendor, -+ desc->idProduct); -+ -+ return i; -+ } -+ } -+ -+ return -1; -+} -+ -+int -+register_device(struct usb_handle *uh, const char *serial) -+{ -+ D("register_device(): Registering %p [%s] as USB transport\n", -+ uh, serial); -+ -+ struct usb_handle *usb= NULL; -+ -+ usb = calloc(1, sizeof(struct usb_handle)); -+ memcpy(usb, uh, sizeof(struct usb_handle)); -+ strcpy(usb->serial, uh->serial); -+ -+ adb_cond_init(&usb->notify, 0); -+ adb_mutex_init(&usb->lock, 0); -+ -+ 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, NULL, 1); -+ -+ return (1); -+} -+ -+int -+already_registered(usb_handle *uh) -+{ -+ struct usb_handle *usb= NULL; -+ int exists = 0; -+ -+ adb_mutex_lock(&usb_lock); -+ -+ for (usb = handle_list.next; usb != &handle_list; usb = usb->next) { -+ if ((usb->dev_bus == uh->dev_bus) && -+ (usb->dev_addr == uh->dev_addr)) -+ { -+ exists = 1; -+ break; -+ } -+ } -+ -+ adb_mutex_unlock(&usb_lock); -+ -+ return exists; -+} -+ -+void -+check_device(libusb_device *dev) -+{ -+ struct usb_handle uh; -+ int i = 0; -+ int found = -1; -+ char serial[256] = {0}; -+ -+ libusb_device_descriptor desc; -+ libusb_config_descriptor *config = NULL; -+ -+ int r = libusb_get_device_descriptor(dev, &desc); -+ -+ if (r != LIBUSB_SUCCESS) { -+ D("check_device(): Failed to get device descriptor\n"); -+ return; -+ } -+ -+ if ((desc.idVendor == 0) && (desc.idProduct == 0)) -+ return; -+ -+ D("check_device(): Probing usb device %04x:%04x\n", -+ desc.idVendor, desc.idProduct); -+ -+ if (!is_adb_interface (desc.idVendor, desc.idProduct, -+ ADB_CLASS, ADB_SUBCLASS, ADB_PROTOCOL)) -+ { -+ D("check_device(): Ignored due unknown vendor id\n"); -+ return; -+ } -+ -+ uh.dev_bus = libusb_get_bus_number(dev); -+ uh.dev_addr = libusb_get_device_address(dev); -+ -+ if (already_registered(&uh)) { -+ D("check_device(): Device (bus: %d, address: %d) " -+ "is already registered\n", uh.dev_bus, uh.dev_addr); -+ return; -+ } -+ -+ D("check_device(): Device bus: %d, address: %d\n", -+ uh.dev_bus, uh.dev_addr); -+ -+ r = libusb_get_active_config_descriptor(dev, &config); -+ -+ if (r != 0) { -+ if (r == LIBUSB_ERROR_NOT_FOUND) { -+ D("check_device(): Device %4x:%4x is unconfigured\n", -+ desc.idVendor, desc.idProduct); -+ return; -+ } -+ -+ D("check_device(): Failed to get configuration for %4x:%4x\n", -+ desc.idVendor, desc.idProduct); -+ return; -+ } -+ -+ if (config == NULL) { -+ D("check_device(): Sanity check failed after " -+ "getting active config\n"); -+ return; -+ } -+ -+ if (config->interface != NULL) { -+ found = check_usb_interfaces(config, &desc, &uh); -+ } -+ -+ /* not needed anymore */ -+ libusb_free_config_descriptor(config); -+ -+ r = libusb_open(dev, &uh.devh); -+ uh.dev = dev; -+ -+ if (r != 0) { -+ switch (r) { -+ case LIBUSB_ERROR_NO_MEM: -+ D("check_device(): Memory allocation problem\n"); -+ break; -+ -+ case LIBUSB_ERROR_ACCESS: -+ D("check_device(): Permissions problem, " -+ "current user priveleges are messed up?\n"); -+ break; -+ -+ case LIBUSB_ERROR_NO_DEVICE: -+ D("check_device(): Device disconected, bad cable?\n"); -+ break; -+ -+ default: -+ D("check_device(): libusb triggered error %d\n", r); -+ } -+ // skip rest -+ found = -1; -+ } -+ -+ if (found >= 0) { -+ D("check_device(): Device matches Android interface\n"); -+ // read the device's serial number -+ memset(serial, 0, sizeof(serial)); -+ uh.interface = found; -+ -+ r = libusb_claim_interface(uh.devh, uh.interface); -+ -+ if (r < 0) { -+ D("check_device(): Failed to claim interface %d\n", -+ uh.interface); -+ -+ goto fail; -+ } -+ -+ if (desc.iSerialNumber) { -+ // reading serial -+ uint16_t buffer[128] = {0}; -+ uint16_t languages[128] = {0}; -+ int languageCount = 0; -+ -+ memset(languages, 0, sizeof(languages)); -+ r = libusb_control_transfer(uh.devh, -+ LIBUSB_ENDPOINT_IN | LIBUSB_REQUEST_TYPE_STANDARD | LIBUSB_RECIPIENT_DEVICE, -+ LIBUSB_REQUEST_GET_DESCRIPTOR, LIBUSB_DT_STRING << 8, -+ 0, (uint8_t *)languages, sizeof(languages), 0); -+ -+ if (r <= 0) { -+ D("check_device(): Failed to get languages count\n"); -+ goto fail; -+ } -+ -+ languageCount = (r - 2) / 2; -+ -+ for (i = 1; i <= languageCount; ++i) { -+ memset(buffer, 0, sizeof(buffer)); -+ -+ r = libusb_control_transfer(uh.devh, -+ LIBUSB_ENDPOINT_IN | LIBUSB_REQUEST_TYPE_STANDARD | LIBUSB_RECIPIENT_DEVICE, -+ LIBUSB_REQUEST_GET_DESCRIPTOR, (LIBUSB_DT_STRING << 8) | desc.iSerialNumber, -+ languages[i], (uint8_t *)buffer, sizeof(buffer), 0); -+ -+ if (r > 0) { /* converting serial */ -+ int j = 0; -+ r /= 2; -+ -+ for (j = 1; j < r; ++j) -+ serial[j - 1] = buffer[j]; -+ -+ serial[j - 1] = '\0'; -+ break; /* languagesCount cycle */ -+ } -+ } -+ -+ if (register_device(&uh, serial) == 0) { -+ D("check_device(): Failed to register device\n"); -+ goto fail_interface; -+ } -+ -+ libusb_ref_device(dev); -+ } -+ } -+ -+ return; -+ -+fail_interface: -+ libusb_release_interface(uh.devh, uh.interface); -+ -+fail: -+ libusb_close(uh.devh); -+ uh.devh = NULL; -+} -+ -+int -+check_device_connected(struct usb_handle *uh) -+{ -+ int r = libusb_kernel_driver_active(uh->devh, uh->interface); -+ -+ if (r == LIBUSB_ERROR_NO_DEVICE) -+ return 0; -+ -+ if (r < 0) -+ return -1; -+ -+ return 1; -+} -+ -+void -+kick_disconnected() -+{ -+ struct usb_handle *usb= NULL; -+ -+ adb_mutex_lock(&usb_lock); -+ -+ for (usb = handle_list.next; usb != &handle_list; usb = usb->next) { -+ -+ if (check_device_connected(usb) == 0) { -+ D("kick_disconnected(): Transport %p is not online anymore\n", -+ usb); -+ -+ usb_kick(usb); -+ } -+ } -+ -+ adb_mutex_unlock(&usb_lock); -+} -+ -+void -+scan_usb_devices() -+{ -+ D("scan_usb_devices(): started\n"); -+ -+ libusb_device **devs= NULL; -+ libusb_device *dev= NULL; -+ ssize_t cnt = libusb_get_device_list(ctx, &devs); -+ -+ if (cnt < 0) { -+ D("scan_usb_devices(): Failed to get device list (error: %d)\n", -+ cnt); -+ -+ return; -+ } -+ -+ int i = 0; -+ -+ while ((dev = devs[i++]) != NULL) { -+ check_device(dev); -+ } -+ -+ libusb_free_device_list(devs, 1); -+} -+ -+void * -+device_poll_thread(void* unused) -+{ -+ D("device_poll_thread(): Created USB scan thread\n"); -+ -+ for (;;) { -+ sleep(5); -+ kick_disconnected(); -+ scan_usb_devices(); -+ } -+ -+ /* never reaching this point */ -+ return (NULL); -+} -+ -+static void -+sigalrm_handler(int signo) -+{ -+ /* nothing */ -+} -+ -+void -+usb_init() -+{ -+ D("usb_init(): started\n"); -+ adb_thread_t tid; -+ struct sigaction actions; -+ -+ int r = libusb_init(&ctx); -+ -+ if (r != LIBUSB_SUCCESS) { -+ err(EX_IOERR, "Failed to init libusb\n"); -+ } -+ -+ memset(&actions, 0, sizeof(actions)); -+ -+ sigemptyset(&actions.sa_mask); -+ -+ actions.sa_flags = 0; -+ actions.sa_handler = sigalrm_handler; -+ -+ sigaction(SIGALRM, &actions, NULL); -+ -+ /* initial device scan */ -+ scan_usb_devices(); -+ -+ /* starting USB event polling thread */ -+ if (adb_thread_create(&tid, device_poll_thread, NULL)) { -+ err(EX_IOERR, "cannot create USB scan thread\n"); -+ } -+ -+ D("usb_init(): finished\n"); -+} -+ -Index: android-tools-4.2.2+git20130218/core/adbd/usb_linux.c -=================================================================== ---- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ android-tools-4.2.2+git20130218/core/adbd/usb_linux.c 2013-06-18 17:12:17.000000000 -0300 -@@ -0,0 +1,715 @@ -+/* -+ * 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 -+#include -+#include -+#include -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 20) -+#include -+#else -+#include -+#endif -+#include -+ -+#include "sysdeps.h" -+ -+#define TRACE_TAG TRACE_USB -+#include "adb.h" -+ -+ -+/* usb scan debugging is waaaay too verbose */ -+#define DBGX(x...) -+ -+ADB_MUTEX_DEFINE( usb_lock ); -+ -+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; -+ unsigned writeable; -+ -+ 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, const char *devpath, -+ unsigned char ep_in, unsigned char ep_out, -+ int ifc, int serial_index, unsigned zero_mask); -+ -+static inline int badname(const char *name) -+{ -+ while(*name) { -+ if(!isdigit(*name++)) return 1; -+ } -+ return 0; -+} -+ -+static void find_usb_device(const char *base, -+ void (*register_device_callback) -+ (const char *, const char *, unsigned char, unsigned char, int, int, unsigned)) -+{ -+ char busname[32], devname[32]; -+ unsigned char local_ep_in, local_ep_out; -+ DIR *busdir , *devdir ; -+ struct dirent *de; -+ int fd ; -+ -+ busdir = opendir(base); -+ if(busdir == 0) return; -+ -+ 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[4096]; -+ unsigned char* bufptr = devdesc; -+ unsigned char* bufend; -+ 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; -+ 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_RDONLY)) < 0) { -+ continue; -+ } -+ -+ desclength = adb_read(fd, devdesc, sizeof(devdesc)); -+ bufend = bufptr + desclength; -+ -+ // 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 = device->idVendor; -+ pid = device->idProduct; -+ 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 descriptors and look for the ADB interface -+ while (bufptr < bufend) { -+ unsigned char length = bufptr[0]; -+ unsigned char type = bufptr[1]; -+ -+ if (type == USB_DT_INTERFACE) { -+ interface = (struct usb_interface_descriptor *)bufptr; -+ bufptr += length; -+ -+ if (length != USB_DT_INTERFACE_SIZE) { -+ D("interface descriptor has wrong size\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)) { -+ -+ struct stat st; -+ char pathbuf[128]; -+ char link[256]; -+ char *devpath = NULL; -+ -+ 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; -+ } -+ -+ // Determine the device path -+ if (!fstat(fd, &st) && S_ISCHR(st.st_mode)) { -+ char *slash; -+ ssize_t link_len; -+ snprintf(pathbuf, sizeof(pathbuf), "/sys/dev/char/%d:%d", -+ major(st.st_rdev), minor(st.st_rdev)); -+ link_len = readlink(pathbuf, link, sizeof(link) - 1); -+ if (link_len > 0) { -+ link[link_len] = '\0'; -+ slash = strrchr(link, '/'); -+ if (slash) { -+ snprintf(pathbuf, sizeof(pathbuf), -+ "usb:%s", slash + 1); -+ devpath = pathbuf; -+ } -+ } -+ } -+ -+ register_device_callback(devname, devpath, -+ local_ep_in, local_ep_out, -+ interface->bInterfaceNumber, device->iSerialNumber, zero_mask); -+ break; -+ } -+ } else { -+ bufptr += length; -+ } -+ } // end of while -+ -+ adb_close(fd); -+ } // end of devdir while -+ closedir(devdir); -+ } //end of busdir while -+ closedir(busdir); -+} -+ -+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; -+ struct timeval tv; -+ struct timespec ts; -+ -+ 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(;;) { -+ /* time out after five seconds */ -+ gettimeofday(&tv, NULL); -+ ts.tv_sec = tv.tv_sec + 5; -+ ts.tv_nsec = tv.tv_usec * 1000L; -+ res = pthread_cond_timedwait(&h->notify, &h->lock, &ts); -+ if(res < 0 || 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); -+ int saved_errno = errno; -+ adb_mutex_lock(&h->lock); -+ h->reaper_thread = 0; -+ if(h->dead) { -+ res = -1; -+ break; -+ } -+ if(res < 0) { -+ if(saved_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; -+ -+ if (h->writeable) { -+ /* 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); -+ } else { -+ unregister_usb_transport(h); -+ } -+ } -+ 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, const char *devpath, -+ unsigned char ep_in, unsigned char ep_out, -+ int interface, int serial_index, unsigned zero_mask) -+{ -+ usb_handle* usb = 0; -+ int n = 0; -+ char serial[256]; -+ -+ /* 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; -+ usb->writeable = 1; -+ -+ 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) { -+ /* if we fail, see if have read-only access */ -+ usb->desc = unix_open(usb->fname, O_RDONLY); -+ if(usb->desc < 0) goto fail; -+ usb->writeable = 0; -+ D("[ usb open read-only %s fd = %d]\n", usb->fname, usb->desc); -+ } else { -+ D("[ usb open %s fd = %d]\n", usb->fname, usb->desc); -+ n = ioctl(usb->desc, USBDEVFS_CLAIMINTERFACE, &interface); -+ if(n != 0) goto fail; -+ } -+ -+ /* read the device's serial number */ -+ serial[0] = 0; -+ memset(serial, 0, sizeof(serial)); -+ if (serial_index) { -+ struct usbdevfs_ctrltransfer ctrl; -+ __u16 buffer[128]; -+ __u16 languages[128]; -+ int i, result; -+ int languageCount = 0; -+ -+ memset(languages, 0, sizeof(languages)); -+ memset(&ctrl, 0, sizeof(ctrl)); -+ -+ // read list of supported languages -+ ctrl.bRequestType = USB_DIR_IN|USB_TYPE_STANDARD|USB_RECIP_DEVICE; -+ ctrl.bRequest = USB_REQ_GET_DESCRIPTOR; -+ ctrl.wValue = (USB_DT_STRING << 8) | 0; -+ ctrl.wIndex = 0; -+ ctrl.wLength = sizeof(languages); -+ ctrl.data = languages; -+ ctrl.timeout = 1000; -+ -+ result = ioctl(usb->desc, USBDEVFS_CONTROL, &ctrl); -+ if (result > 0) -+ languageCount = (result - 2) / 2; -+ -+ for (i = 1; i <= languageCount; i++) { -+ 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) | serial_index; -+ ctrl.wIndex = __le16_to_cpu(languages[i]); -+ ctrl.wLength = sizeof(buffer); -+ ctrl.data = buffer; -+ ctrl.timeout = 1000; -+ -+ result = ioctl(usb->desc, 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] = __le16_to_cpu(buffer[i]); -+ serial[i - 1] = 0; -+ break; -+ } -+ } -+ } -+ -+ /* 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, devpath, usb->writeable); -+ 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"); -+ } -+} -Index: android-tools-4.2.2+git20130218/core/adbd/usb_linux_client.c -=================================================================== ---- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ android-tools-4.2.2+git20130218/core/adbd/usb_linux_client.c 2013-06-18 17:12:17.000000000 -0300 -@@ -0,0 +1,492 @@ -+/* -+ * 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 -+#include -+#include -+#include -+ -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include "sysdeps.h" -+ -+#define TRACE_TAG TRACE_USB -+#include "adb.h" -+ -+#define MAX_PACKET_SIZE_FS 64 -+#define MAX_PACKET_SIZE_HS 512 -+ -+#define cpu_to_le16(x) htole16(x) -+#define cpu_to_le32(x) htole32(x) -+ -+struct usb_handle -+{ -+ adb_cond_t notify; -+ adb_mutex_t lock; -+ -+ int (*write)(usb_handle *h, const void *data, int len); -+ int (*read)(usb_handle *h, void *data, int len); -+ void (*kick)(usb_handle *h); -+ -+ // Legacy f_adb -+ int fd; -+ -+ // FunctionFS -+ int control; -+ int bulk_out; /* "out" from the host's perspective => source for adbd */ -+ int bulk_in; /* "in" from the host's perspective => sink for adbd */ -+}; -+ -+static const struct { -+ struct usb_functionfs_descs_head header; -+ struct { -+ struct usb_interface_descriptor intf; -+ struct usb_endpoint_descriptor_no_audio source; -+ struct usb_endpoint_descriptor_no_audio sink; -+ } __attribute__((packed)) fs_descs, hs_descs; -+} __attribute__((packed)) descriptors = { -+ .header = { -+ .magic = cpu_to_le32(FUNCTIONFS_DESCRIPTORS_MAGIC), -+ .length = cpu_to_le32(sizeof(descriptors)), -+ .fs_count = 3, -+ .hs_count = 3, -+ }, -+ .fs_descs = { -+ .intf = { -+ .bLength = sizeof(descriptors.fs_descs.intf), -+ .bDescriptorType = USB_DT_INTERFACE, -+ .bInterfaceNumber = 0, -+ .bNumEndpoints = 2, -+ .bInterfaceClass = ADB_CLASS, -+ .bInterfaceSubClass = ADB_SUBCLASS, -+ .bInterfaceProtocol = ADB_PROTOCOL, -+ .iInterface = 1, /* first string from the provided table */ -+ }, -+ .source = { -+ .bLength = sizeof(descriptors.fs_descs.source), -+ .bDescriptorType = USB_DT_ENDPOINT, -+ .bEndpointAddress = 1 | USB_DIR_OUT, -+ .bmAttributes = USB_ENDPOINT_XFER_BULK, -+ .wMaxPacketSize = MAX_PACKET_SIZE_FS, -+ }, -+ .sink = { -+ .bLength = sizeof(descriptors.fs_descs.sink), -+ .bDescriptorType = USB_DT_ENDPOINT, -+ .bEndpointAddress = 2 | USB_DIR_IN, -+ .bmAttributes = USB_ENDPOINT_XFER_BULK, -+ .wMaxPacketSize = MAX_PACKET_SIZE_FS, -+ }, -+ }, -+ .hs_descs = { -+ .intf = { -+ .bLength = sizeof(descriptors.hs_descs.intf), -+ .bDescriptorType = USB_DT_INTERFACE, -+ .bInterfaceNumber = 0, -+ .bNumEndpoints = 2, -+ .bInterfaceClass = ADB_CLASS, -+ .bInterfaceSubClass = ADB_SUBCLASS, -+ .bInterfaceProtocol = ADB_PROTOCOL, -+ .iInterface = 1, /* first string from the provided table */ -+ }, -+ .source = { -+ .bLength = sizeof(descriptors.hs_descs.source), -+ .bDescriptorType = USB_DT_ENDPOINT, -+ .bEndpointAddress = 1 | USB_DIR_OUT, -+ .bmAttributes = USB_ENDPOINT_XFER_BULK, -+ .wMaxPacketSize = MAX_PACKET_SIZE_HS, -+ }, -+ .sink = { -+ .bLength = sizeof(descriptors.hs_descs.sink), -+ .bDescriptorType = USB_DT_ENDPOINT, -+ .bEndpointAddress = 2 | USB_DIR_IN, -+ .bmAttributes = USB_ENDPOINT_XFER_BULK, -+ .wMaxPacketSize = MAX_PACKET_SIZE_HS, -+ }, -+ }, -+}; -+ -+#define STR_INTERFACE_ "ADB Interface" -+ -+static const struct { -+ struct usb_functionfs_strings_head header; -+ struct { -+ __le16 code; -+ const char str1[sizeof(STR_INTERFACE_)]; -+ } __attribute__((packed)) lang0; -+} __attribute__((packed)) strings = { -+ .header = { -+ .magic = cpu_to_le32(FUNCTIONFS_STRINGS_MAGIC), -+ .length = cpu_to_le32(sizeof(strings)), -+ .str_count = cpu_to_le32(1), -+ .lang_count = cpu_to_le32(1), -+ }, -+ .lang0 = { -+ cpu_to_le16(0x0409), /* en-us */ -+ STR_INTERFACE_, -+ }, -+}; -+ -+ -+ -+static void *usb_adb_open_thread(void *x) -+{ -+ struct usb_handle *usb = (struct usb_handle *)x; -+ int fd; -+ -+ while (1) { -+ // wait until the USB device needs opening -+ adb_mutex_lock(&usb->lock); -+ while (usb->fd != -1) -+ adb_cond_wait(&usb->notify, &usb->lock); -+ adb_mutex_unlock(&usb->lock); -+ -+ D("[ usb_thread - opening device ]\n"); -+ do { -+ /* XXX use inotify? */ -+ fd = unix_open("/dev/android_adb", O_RDWR); -+ if (fd < 0) { -+ // to support older kernels -+ fd = unix_open("/dev/android", O_RDWR); -+ } -+ 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, 0, 1); -+ } -+ -+ // never gets here -+ return 0; -+} -+ -+static int usb_adb_write(usb_handle *h, const void *data, int len) -+{ -+ int n; -+ -+ D("about to write (fd=%d, len=%d)\n", h->fd, len); -+ n = adb_write(h->fd, data, len); -+ if(n != len) { -+ D("ERROR: fd = %d, n = %d, errno = %d (%s)\n", -+ h->fd, n, errno, strerror(errno)); -+ return -1; -+ } -+ D("[ done fd=%d ]\n", h->fd); -+ return 0; -+} -+ -+static int usb_adb_read(usb_handle *h, void *data, int len) -+{ -+ int n; -+ -+ D("about to read (fd=%d, len=%d)\n", h->fd, len); -+ n = adb_read(h->fd, data, len); -+ if(n != len) { -+ D("ERROR: fd = %d, n = %d, errno = %d (%s)\n", -+ h->fd, n, errno, strerror(errno)); -+ return -1; -+ } -+ D("[ done fd=%d ]\n", h->fd); -+ return 0; -+} -+ -+static void usb_adb_kick(usb_handle *h) -+{ -+ D("usb_kick\n"); -+ adb_mutex_lock(&h->lock); -+ adb_close(h->fd); -+ h->fd = -1; -+ -+ // notify usb_adb_open_thread that we are disconnected -+ adb_cond_signal(&h->notify); -+ adb_mutex_unlock(&h->lock); -+} -+ -+static void usb_adb_init() -+{ -+ usb_handle *h; -+ adb_thread_t tid; -+ int fd; -+ -+ h = calloc(1, sizeof(usb_handle)); -+ -+ h->write = usb_adb_write; -+ h->read = usb_adb_read; -+ h->kick = usb_adb_kick; -+ h->fd = -1; -+ -+ adb_cond_init(&h->notify, 0); -+ adb_mutex_init(&h->lock, 0); -+ -+ // 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_adb_open_thread, h)){ -+ fatal_errno("cannot create usb thread"); -+ } -+} -+ -+ -+static void init_functionfs(struct usb_handle *h) -+{ -+ ssize_t ret; -+ -+ D("OPENING %s\n", USB_FFS_ADB_EP0); -+ h->control = adb_open(USB_FFS_ADB_EP0, O_RDWR); -+ if (h->control < 0) { -+ D("[ %s: cannot open control endpoint: errno=%d]\n", USB_FFS_ADB_EP0, errno); -+ goto err; -+ } -+ -+ ret = adb_write(h->control, &descriptors, sizeof(descriptors)); -+ if (ret < 0) { -+ D("[ %s: write descriptors failed: errno=%d ]\n", USB_FFS_ADB_EP0, errno); -+ goto err; -+ } -+ -+ ret = adb_write(h->control, &strings, sizeof(strings)); -+ if (ret < 0) { -+ D("[ %s: writing strings failed: errno=%d]\n", USB_FFS_ADB_EP0, errno); -+ goto err; -+ } -+ -+ h->bulk_out = adb_open(USB_FFS_ADB_OUT, O_RDWR); -+ if (h->bulk_out < 0) { -+ D("[ %s: cannot open bulk-out ep: errno=%d ]\n", USB_FFS_ADB_OUT, errno); -+ goto err; -+ } -+ -+ h->bulk_in = adb_open(USB_FFS_ADB_IN, O_RDWR); -+ if (h->bulk_in < 0) { -+ D("[ %s: cannot open bulk-in ep: errno=%d ]\n", USB_FFS_ADB_IN, errno); -+ goto err; -+ } -+ -+ return; -+ -+err: -+ if (h->bulk_in > 0) { -+ adb_close(h->bulk_in); -+ h->bulk_in = -1; -+ } -+ if (h->bulk_out > 0) { -+ adb_close(h->bulk_out); -+ h->bulk_out = -1; -+ } -+ if (h->control > 0) { -+ adb_close(h->control); -+ h->control = -1; -+ } -+ return; -+} -+ -+static void *usb_ffs_open_thread(void *x) -+{ -+ struct usb_handle *usb = (struct usb_handle *)x; -+ -+ while (1) { -+ // wait until the USB device needs opening -+ adb_mutex_lock(&usb->lock); -+ while (usb->control != -1) -+ adb_cond_wait(&usb->notify, &usb->lock); -+ adb_mutex_unlock(&usb->lock); -+ -+ while (1) { -+ init_functionfs(usb); -+ -+ if (usb->control >= 0) -+ break; -+ -+ adb_sleep_ms(1000); -+ } -+ -+ D("[ usb_thread - registering device ]\n"); -+ register_usb_transport(usb, 0, 0, 1); -+ } -+ -+ // never gets here -+ return 0; -+} -+ -+static int bulk_write(int bulk_in, const char *buf, size_t length) -+{ -+ size_t count = 0; -+ int ret; -+ -+ do { -+ ret = adb_write(bulk_in, buf + count, length - count); -+ if (ret < 0) { -+ if (errno != EINTR) -+ return ret; -+ } else { -+ count += ret; -+ } -+ } while (count < length); -+ -+ D("[ bulk_write done fd=%d ]\n", bulk_in); -+ return count; -+} -+ -+static int usb_ffs_write(usb_handle *h, const void *data, int len) -+{ -+ int n; -+ -+ D("about to write (fd=%d, len=%d)\n", h->bulk_in, len); -+ n = bulk_write(h->bulk_in, data, len); -+ if (n != len) { -+ D("ERROR: fd = %d, n = %d, errno = %d (%s)\n", -+ h->bulk_in, n, errno, strerror(errno)); -+ return -1; -+ } -+ D("[ done fd=%d ]\n", h->bulk_in); -+ return 0; -+} -+ -+static int bulk_read(int bulk_out, char *buf, size_t length) -+{ -+ size_t count = 0; -+ int ret; -+ -+ do { -+ ret = adb_read(bulk_out, buf + count, length - count); -+ if (ret < 0) { -+ if (errno != EINTR) { -+ D("[ bulk_read failed fd=%d length=%d count=%d ]\n", -+ bulk_out, length, count); -+ return ret; -+ } -+ } else { -+ count += ret; -+ } -+ } while (count < length); -+ -+ return count; -+} -+ -+static int usb_ffs_read(usb_handle *h, void *data, int len) -+{ -+ int n; -+ -+ D("about to read (fd=%d, len=%d)\n", h->bulk_out, len); -+ n = bulk_read(h->bulk_out, data, len); -+ if (n != len) { -+ D("ERROR: fd = %d, n = %d, errno = %d (%s)\n", -+ h->bulk_out, n, errno, strerror(errno)); -+ return -1; -+ } -+ D("[ done fd=%d ]\n", h->bulk_out); -+ return 0; -+} -+ -+static void usb_ffs_kick(usb_handle *h) -+{ -+ int err; -+ -+ err = ioctl(h->bulk_in, FUNCTIONFS_CLEAR_HALT); -+ if (err < 0) -+ D("[ kick: source (fd=%d) clear halt failed (%d) ]", h->bulk_in, errno); -+ -+ err = ioctl(h->bulk_out, FUNCTIONFS_CLEAR_HALT); -+ if (err < 0) -+ D("[ kick: sink (fd=%d) clear halt failed (%d) ]", h->bulk_out, errno); -+ -+ adb_mutex_lock(&h->lock); -+ adb_close(h->control); -+ adb_close(h->bulk_out); -+ adb_close(h->bulk_in); -+ h->control = h->bulk_out = h->bulk_in = -1; -+ -+ // notify usb_ffs_open_thread that we are disconnected -+ adb_cond_signal(&h->notify); -+ adb_mutex_unlock(&h->lock); -+} -+ -+static void usb_ffs_init() -+{ -+ usb_handle *h; -+ adb_thread_t tid; -+ -+ D("[ usb_init - using FunctionFS ]\n"); -+ -+ h = calloc(1, sizeof(usb_handle)); -+ -+ h->write = usb_ffs_write; -+ h->read = usb_ffs_read; -+ h->kick = usb_ffs_kick; -+ -+ h->control = -1; -+ h->bulk_out = -1; -+ h->bulk_out = -1; -+ -+ adb_cond_init(&h->notify, 0); -+ adb_mutex_init(&h->lock, 0); -+ -+ D("[ usb_init - starting thread ]\n"); -+ if (adb_thread_create(&tid, usb_ffs_open_thread, h)){ -+ fatal_errno("[ cannot create usb thread ]\n"); -+ } -+} -+ -+void usb_init() -+{ -+ if (access(USB_FFS_ADB_EP0, F_OK) == 0) -+ usb_ffs_init(); -+ else -+ usb_adb_init(); -+} -+ -+void usb_cleanup() -+{ -+} -+ -+int usb_write(usb_handle *h, const void *data, int len) -+{ -+ return h->write(h, data, len); -+} -+ -+int usb_read(usb_handle *h, void *data, int len) -+{ -+ return h->read(h, data, len); -+} -+int usb_close(usb_handle *h) -+{ -+ return 0; -+} -+ -+void usb_kick(usb_handle *h) -+{ -+ h->kick(h); -+} -Index: android-tools-4.2.2+git20130218/core/adbd/usb_osx.c -=================================================================== ---- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ android-tools-4.2.2+git20130218/core/adbd/usb_osx.c 2013-06-18 17:12:17.000000000 -0300 -@@ -0,0 +1,545 @@ -+/* -+ * 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 -+ -+#include -+#include -+#include -+#include -+#include -+ -+#include "sysdeps.h" -+ -+#include -+ -+#define TRACE_TAG TRACE_USB -+#include "adb.h" -+#include "usb_vendors.h" -+ -+#define DBG D -+ -+static IONotificationPortRef notificationPort = 0; -+static io_iterator_t* notificationIterators; -+ -+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 AndroidInterfaceAdded(void *refCon, io_iterator_t iterator); -+static void AndroidInterfaceNotify(void *refCon, io_iterator_t iterator, -+ natural_t messageType, -+ void *messageArgument); -+static usb_handle* CheckInterface(IOUSBInterfaceInterface **iface, -+ UInt16 vendor, UInt16 product); -+ -+static int -+InitUSB() -+{ -+ CFMutableDictionaryRef matchingDict; -+ CFRunLoopSourceRef runLoopSource; -+ SInt32 vendor, if_subclass, if_protocol; -+ unsigned 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 vendors -+ for (i = 0; i < vendorIdCount; i++) { -+ //* Create our matching dictionary to find the Android device's -+ //* adb interface -+ //* IOServiceAddMatchingNotification consumes the reference, so we do -+ //* not need to release this -+ matchingDict = IOServiceMatching(kIOUSBInterfaceClassName); -+ -+ if (!matchingDict) { -+ DBG("ERR: Couldn't create USB matching dictionary.\n"); -+ return -1; -+ } -+ -+ //* Match based on vendor id, interface subclass and protocol -+ vendor = vendorIds[i]; -+ if_subclass = ADB_SUBCLASS; -+ if_protocol = ADB_PROTOCOL; -+ CFDictionarySetValue(matchingDict, CFSTR(kUSBVendorID), -+ CFNumberCreate(kCFAllocatorDefault, -+ kCFNumberSInt32Type, &vendor)); -+ CFDictionarySetValue(matchingDict, CFSTR(kUSBInterfaceSubClass), -+ CFNumberCreate(kCFAllocatorDefault, -+ kCFNumberSInt32Type, &if_subclass)); -+ CFDictionarySetValue(matchingDict, CFSTR(kUSBInterfaceProtocol), -+ CFNumberCreate(kCFAllocatorDefault, -+ kCFNumberSInt32Type, &if_protocol)); -+ IOServiceAddMatchingNotification( -+ notificationPort, -+ kIOFirstMatchNotification, -+ matchingDict, -+ AndroidInterfaceAdded, -+ NULL, -+ ¬ificationIterators[i]); -+ -+ //* Iterate over set of matching interfaces to access already-present -+ //* devices and to arm the notification -+ AndroidInterfaceAdded(NULL, notificationIterators[i]); -+ } -+ -+ return 0; -+} -+ -+static void -+AndroidInterfaceAdded(void *refCon, io_iterator_t iterator) -+{ -+ kern_return_t kr; -+ io_service_t usbDevice; -+ io_service_t usbInterface; -+ IOCFPlugInInterface **plugInInterface = NULL; -+ IOUSBInterfaceInterface220 **iface = NULL; -+ IOUSBDeviceInterface197 **dev = NULL; -+ HRESULT result; -+ SInt32 score; -+ UInt32 locationId; -+ UInt16 vendor; -+ UInt16 product; -+ UInt8 serialIndex; -+ char serial[256]; -+ char devpathBuf[64]; -+ char *devpath = NULL; -+ -+ while ((usbInterface = IOIteratorNext(iterator))) { -+ //* Create an intermediate interface plugin -+ kr = IOCreatePlugInInterfaceForService(usbInterface, -+ kIOUSBInterfaceUserClientTypeID, -+ kIOCFPlugInInterfaceID, -+ &plugInInterface, &score); -+ IOObjectRelease(usbInterface); -+ if ((kIOReturnSuccess != kr) || (!plugInInterface)) { -+ DBG("ERR: Unable to create an interface plug-in (%08x)\n", kr); -+ continue; -+ } -+ -+ //* This gets us the interface object -+ result = (*plugInInterface)->QueryInterface(plugInInterface, -+ CFUUIDGetUUIDBytes(kIOUSBInterfaceInterfaceID), (LPVOID) -+ &iface); -+ //* We only needed the plugin to get the interface, so discard it -+ (*plugInInterface)->Release(plugInInterface); -+ if (result || !iface) { -+ DBG("ERR: Couldn't query the interface (%08x)\n", (int) result); -+ continue; -+ } -+ -+ //* this gets us an ioservice, with which we will find the actual -+ //* device; after getting a plugin, and querying the interface, of -+ //* course. -+ //* Gotta love OS X -+ kr = (*iface)->GetDevice(iface, &usbDevice); -+ if (kIOReturnSuccess != kr || !usbDevice) { -+ DBG("ERR: Couldn't grab device from interface (%08x)\n", kr); -+ continue; -+ } -+ -+ plugInInterface = NULL; -+ score = 0; -+ //* create an intermediate device plugin -+ kr = IOCreatePlugInInterfaceForService(usbDevice, -+ kIOUSBDeviceUserClientTypeID, -+ kIOCFPlugInInterfaceID, -+ &plugInInterface, &score); -+ //* only needed this to find the plugin -+ (void)IOObjectRelease(usbDevice); -+ if ((kIOReturnSuccess != kr) || (!plugInInterface)) { -+ DBG("ERR: Unable to create a device plug-in (%08x)\n", kr); -+ continue; -+ } -+ -+ result = (*plugInInterface)->QueryInterface(plugInInterface, -+ CFUUIDGetUUIDBytes(kIOUSBDeviceInterfaceID), (LPVOID) &dev); -+ //* only needed this to query the plugin -+ (*plugInInterface)->Release(plugInInterface); -+ if (result || !dev) { -+ DBG("ERR: Couldn't create a device interface (%08x)\n", -+ (int) result); -+ continue; -+ } -+ -+ //* Now after all that, we actually have a ref to the device and -+ //* the interface that matched our criteria -+ -+ kr = (*dev)->GetDeviceVendor(dev, &vendor); -+ kr = (*dev)->GetDeviceProduct(dev, &product); -+ kr = (*dev)->GetLocationID(dev, &locationId); -+ if (kr == 0) { -+ snprintf(devpathBuf, sizeof(devpathBuf), "usb:%lX", locationId); -+ devpath = devpathBuf; -+ } -+ kr = (*dev)->USBGetSerialNumberStringIndex(dev, &serialIndex); -+ -+ if (serialIndex > 0) { -+ IOUSBDevRequest req; -+ UInt16 buffer[256]; -+ UInt16 languages[128]; -+ -+ memset(languages, 0, sizeof(languages)); -+ -+ req.bmRequestType = -+ USBmakebmRequestType(kUSBIn, kUSBStandard, kUSBDevice); -+ req.bRequest = kUSBRqGetDescriptor; -+ req.wValue = (kUSBStringDesc << 8) | 0; -+ req.wIndex = 0; -+ req.pData = languages; -+ req.wLength = sizeof(languages); -+ kr = (*dev)->DeviceRequest(dev, &req); -+ -+ if (kr == kIOReturnSuccess && req.wLenDone > 0) { -+ -+ int langCount = (req.wLenDone - 2) / 2, lang; -+ -+ for (lang = 1; lang <= langCount; lang++) { -+ -+ memset(buffer, 0, sizeof(buffer)); -+ memset(&req, 0, sizeof(req)); -+ -+ req.bmRequestType = -+ USBmakebmRequestType(kUSBIn, kUSBStandard, kUSBDevice); -+ req.bRequest = kUSBRqGetDescriptor; -+ req.wValue = (kUSBStringDesc << 8) | serialIndex; -+ req.wIndex = languages[lang]; -+ 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; -+ break; -+ } -+ } -+ } -+ } -+ (*dev)->Release(dev); -+ -+ DBG("INFO: Found vid=%04x pid=%04x serial=%s\n", vendor, product, -+ serial); -+ -+ usb_handle* handle = CheckInterface((IOUSBInterfaceInterface**)iface, -+ vendor, product); -+ if (handle == NULL) { -+ DBG("ERR: Could not find device interface: %08x\n", kr); -+ (*iface)->Release(iface); -+ continue; -+ } -+ -+ DBG("AndroidDeviceAdded calling register_usb_transport\n"); -+ register_usb_transport(handle, (serial[0] ? serial : NULL), devpath, 1); -+ -+ // 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, -+ usbInterface, -+ kIOGeneralInterest, -+ AndroidInterfaceNotify, -+ handle, -+ &handle->usbNotification); -+ -+ if (kIOReturnSuccess != kr) { -+ DBG("ERR: Unable to create interest notification (%08x)\n", kr); -+ } -+ } -+} -+ -+static void -+AndroidInterfaceNotify(void *refCon, io_service_t service, natural_t messageType, void *messageArgument) -+{ -+ usb_handle *handle = (usb_handle *)refCon; -+ -+ if (messageType == kIOMessageServiceIsTerminated) { -+ if (!handle) { -+ DBG("ERR: NULL handle\n"); -+ return; -+ } -+ DBG("AndroidInterfaceNotify\n"); -+ IOObjectRelease(handle->usbNotification); -+ usb_kick(handle); -+ } -+} -+ -+//* TODO: simplify this further since we only register to get ADB interface -+//* subclass+protocol events -+static usb_handle* -+CheckInterface(IOUSBInterfaceInterface **interface, UInt16 vendor, UInt16 product) -+{ -+ usb_handle* handle = NULL; -+ IOReturn kr; -+ UInt8 interfaceNumEndpoints, interfaceClass, interfaceSubClass, interfaceProtocol; -+ UInt8 endpoint; -+ -+ -+ //* 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); -+ return NULL; -+ } -+ -+ //* 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 err_get_num_ep; -+ } -+ -+ //* 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 err_get_interface_class; -+ } -+ -+ //* 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)) -+ goto err_bad_adb_interface; -+ -+ 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; -+ -+ handle->zero_mask = maxPacketSize - 1; -+ } else { -+ DBG("ERR: FindDeviceInterface - could not get pipe properties\n"); -+ goto err_get_pipe_props; -+ } -+ } -+ -+ handle->interface = interface; -+ return handle; -+ -+err_get_pipe_props: -+ free(handle); -+err_bad_adb_interface: -+err_get_interface_class: -+err_get_num_ep: -+ (*interface)->USBInterfaceClose(interface); -+ return NULL; -+} -+ -+ -+void* RunLoopThread(void* unused) -+{ -+ unsigned 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 < vendorIdCount; 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; -+ -+ notificationIterators = (io_iterator_t*)malloc( -+ vendorIdCount * sizeof(io_iterator_t)); -+ -+ 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); -+ -+ if (notificationIterators != NULL) { -+ free(notificationIterators); -+ notificationIterators = NULL; -+ } -+} -+ -+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) -+ return; -+ -+ if (handle->interface) -+ { -+ (*handle->interface)->USBInterfaceClose(handle->interface); -+ (*handle->interface)->Release(handle->interface); -+ handle->interface = 0; -+ } -+} -Index: android-tools-4.2.2+git20130218/core/adbd/usb_vendors.c -=================================================================== ---- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ android-tools-4.2.2+git20130218/core/adbd/usb_vendors.c 2013-06-18 17:12:17.000000000 -0300 -@@ -0,0 +1,273 @@ -+/* -+ * Copyright (C) 2009 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 "usb_vendors.h" -+ -+#include -+ -+#ifdef _WIN32 -+# define WIN32_LEAN_AND_MEAN -+# include "windows.h" -+# include "shlobj.h" -+#else -+# include -+# include -+#endif -+ -+#include "sysdeps.h" -+#include "adb.h" -+ -+#define ANDROID_PATH ".android" -+#define ANDROID_ADB_INI "adb_usb.ini" -+ -+#define TRACE_TAG TRACE_USB -+ -+// Google's USB Vendor ID -+#define VENDOR_ID_GOOGLE 0x18d1 -+// Intel's USB Vendor ID -+#define VENDOR_ID_INTEL 0x8087 -+// HTC's USB Vendor ID -+#define VENDOR_ID_HTC 0x0bb4 -+// Samsung's USB Vendor ID -+#define VENDOR_ID_SAMSUNG 0x04e8 -+// Motorola's USB Vendor ID -+#define VENDOR_ID_MOTOROLA 0x22b8 -+// LG's USB Vendor ID -+#define VENDOR_ID_LGE 0x1004 -+// Huawei's USB Vendor ID -+#define VENDOR_ID_HUAWEI 0x12D1 -+// Acer's USB Vendor ID -+#define VENDOR_ID_ACER 0x0502 -+// Sony Ericsson's USB Vendor ID -+#define VENDOR_ID_SONY_ERICSSON 0x0FCE -+// Foxconn's USB Vendor ID -+#define VENDOR_ID_FOXCONN 0x0489 -+// Dell's USB Vendor ID -+#define VENDOR_ID_DELL 0x413c -+// Nvidia's USB Vendor ID -+#define VENDOR_ID_NVIDIA 0x0955 -+// Garmin-Asus's USB Vendor ID -+#define VENDOR_ID_GARMIN_ASUS 0x091E -+// Sharp's USB Vendor ID -+#define VENDOR_ID_SHARP 0x04dd -+// ZTE's USB Vendor ID -+#define VENDOR_ID_ZTE 0x19D2 -+// Kyocera's USB Vendor ID -+#define VENDOR_ID_KYOCERA 0x0482 -+// Pantech's USB Vendor ID -+#define VENDOR_ID_PANTECH 0x10A9 -+// Qualcomm's USB Vendor ID -+#define VENDOR_ID_QUALCOMM 0x05c6 -+// On-The-Go-Video's USB Vendor ID -+#define VENDOR_ID_OTGV 0x2257 -+// NEC's USB Vendor ID -+#define VENDOR_ID_NEC 0x0409 -+// Panasonic Mobile Communication's USB Vendor ID -+#define VENDOR_ID_PMC 0x04DA -+// Toshiba's USB Vendor ID -+#define VENDOR_ID_TOSHIBA 0x0930 -+// SK Telesys's USB Vendor ID -+#define VENDOR_ID_SK_TELESYS 0x1F53 -+// KT Tech's USB Vendor ID -+#define VENDOR_ID_KT_TECH 0x2116 -+// Asus's USB Vendor ID -+#define VENDOR_ID_ASUS 0x0b05 -+// Philips's USB Vendor ID -+#define VENDOR_ID_PHILIPS 0x0471 -+// Texas Instruments's USB Vendor ID -+#define VENDOR_ID_TI 0x0451 -+// Funai's USB Vendor ID -+#define VENDOR_ID_FUNAI 0x0F1C -+// Gigabyte's USB Vendor ID -+#define VENDOR_ID_GIGABYTE 0x0414 -+// IRiver's USB Vendor ID -+#define VENDOR_ID_IRIVER 0x2420 -+// Compal's USB Vendor ID -+#define VENDOR_ID_COMPAL 0x1219 -+// T & A Mobile Phones' USB Vendor ID -+#define VENDOR_ID_T_AND_A 0x1BBB -+// LenovoMobile's USB Vendor ID -+#define VENDOR_ID_LENOVOMOBILE 0x2006 -+// Lenovo's USB Vendor ID -+#define VENDOR_ID_LENOVO 0x17EF -+// Vizio's USB Vendor ID -+#define VENDOR_ID_VIZIO 0xE040 -+// K-Touch's USB Vendor ID -+#define VENDOR_ID_K_TOUCH 0x24E3 -+// Pegatron's USB Vendor ID -+#define VENDOR_ID_PEGATRON 0x1D4D -+// Archos's USB Vendor ID -+#define VENDOR_ID_ARCHOS 0x0E79 -+// Positivo's USB Vendor ID -+#define VENDOR_ID_POSITIVO 0x1662 -+// Fujitsu's USB Vendor ID -+#define VENDOR_ID_FUJITSU 0x04C5 -+// Lumigon's USB Vendor ID -+#define VENDOR_ID_LUMIGON 0x25E3 -+// Quanta's USB Vendor ID -+#define VENDOR_ID_QUANTA 0x0408 -+// INQ Mobile's USB Vendor ID -+#define VENDOR_ID_INQ_MOBILE 0x2314 -+// Sony's USB Vendor ID -+#define VENDOR_ID_SONY 0x054C -+// Lab126's USB Vendor ID -+#define VENDOR_ID_LAB126 0x1949 -+// Yulong Coolpad's USB Vendor ID -+#define VENDOR_ID_YULONG_COOLPAD 0x1EBF -+// Kobo's USB Vendor ID -+#define VENDOR_ID_KOBO 0x2237 -+// Teleepoch's USB Vendor ID -+#define VENDOR_ID_TELEEPOCH 0x2340 -+ -+ -+/** built-in vendor list */ -+int builtInVendorIds[] = { -+ VENDOR_ID_GOOGLE, -+ VENDOR_ID_INTEL, -+ VENDOR_ID_HTC, -+ VENDOR_ID_SAMSUNG, -+ VENDOR_ID_MOTOROLA, -+ VENDOR_ID_LGE, -+ VENDOR_ID_HUAWEI, -+ VENDOR_ID_ACER, -+ VENDOR_ID_SONY_ERICSSON, -+ VENDOR_ID_FOXCONN, -+ VENDOR_ID_DELL, -+ VENDOR_ID_NVIDIA, -+ VENDOR_ID_GARMIN_ASUS, -+ VENDOR_ID_SHARP, -+ VENDOR_ID_ZTE, -+ VENDOR_ID_KYOCERA, -+ VENDOR_ID_PANTECH, -+ VENDOR_ID_QUALCOMM, -+ VENDOR_ID_OTGV, -+ VENDOR_ID_NEC, -+ VENDOR_ID_PMC, -+ VENDOR_ID_TOSHIBA, -+ VENDOR_ID_SK_TELESYS, -+ VENDOR_ID_KT_TECH, -+ VENDOR_ID_ASUS, -+ VENDOR_ID_PHILIPS, -+ VENDOR_ID_TI, -+ VENDOR_ID_FUNAI, -+ VENDOR_ID_GIGABYTE, -+ VENDOR_ID_IRIVER, -+ VENDOR_ID_COMPAL, -+ VENDOR_ID_T_AND_A, -+ VENDOR_ID_LENOVOMOBILE, -+ VENDOR_ID_LENOVO, -+ VENDOR_ID_VIZIO, -+ VENDOR_ID_K_TOUCH, -+ VENDOR_ID_PEGATRON, -+ VENDOR_ID_ARCHOS, -+ VENDOR_ID_POSITIVO, -+ VENDOR_ID_FUJITSU, -+ VENDOR_ID_LUMIGON, -+ VENDOR_ID_QUANTA, -+ VENDOR_ID_INQ_MOBILE, -+ VENDOR_ID_SONY, -+ VENDOR_ID_LAB126, -+ VENDOR_ID_YULONG_COOLPAD, -+ VENDOR_ID_KOBO, -+ VENDOR_ID_TELEEPOCH, -+}; -+ -+#define BUILT_IN_VENDOR_COUNT (sizeof(builtInVendorIds)/sizeof(builtInVendorIds[0])) -+ -+/* max number of supported vendor ids (built-in + 3rd party). increase as needed */ -+#define VENDOR_COUNT_MAX 128 -+ -+int vendorIds[VENDOR_COUNT_MAX]; -+unsigned vendorIdCount = 0; -+ -+int get_adb_usb_ini(char* buff, size_t len); -+ -+void usb_vendors_init(void) -+{ -+ if (VENDOR_COUNT_MAX < BUILT_IN_VENDOR_COUNT) { -+ fprintf(stderr, "VENDOR_COUNT_MAX not big enough for built-in vendor list.\n"); -+ exit(2); -+ } -+ -+ /* add the built-in vendors at the beginning of the array */ -+ memcpy(vendorIds, builtInVendorIds, sizeof(builtInVendorIds)); -+ -+ /* default array size is the number of built-in vendors */ -+ vendorIdCount = BUILT_IN_VENDOR_COUNT; -+ -+ if (VENDOR_COUNT_MAX == BUILT_IN_VENDOR_COUNT) -+ return; -+ -+ char temp[PATH_MAX]; -+ if (get_adb_usb_ini(temp, sizeof(temp)) == 0) { -+ FILE * f = fopen(temp, "rt"); -+ -+ if (f != NULL) { -+ /* The vendor id file is pretty basic. 1 vendor id per line. -+ Lines starting with # are comments */ -+ while (fgets(temp, sizeof(temp), f) != NULL) { -+ if (temp[0] == '#') -+ continue; -+ -+ long value = strtol(temp, NULL, 0); -+ if (errno == EINVAL || errno == ERANGE || value > INT_MAX || value < 0) { -+ fprintf(stderr, "Invalid content in %s. Quitting.\n", ANDROID_ADB_INI); -+ exit(2); -+ } -+ -+ vendorIds[vendorIdCount++] = (int)value; -+ -+ /* make sure we don't go beyond the array */ -+ if (vendorIdCount == VENDOR_COUNT_MAX) { -+ break; -+ } -+ } -+ } -+ } -+} -+ -+/* Utils methods */ -+ -+/* builds the path to the adb vendor id file. returns 0 if success */ -+int build_path(char* buff, size_t len, const char* format, const char* home) -+{ -+ if (snprintf(buff, len, format, home, ANDROID_PATH, ANDROID_ADB_INI) >= (signed)len) { -+ return 1; -+ } -+ -+ return 0; -+} -+ -+/* fills buff with the path to the adb vendor id file. returns 0 if success */ -+int get_adb_usb_ini(char* buff, size_t len) -+{ -+#ifdef _WIN32 -+ const char* home = getenv("ANDROID_SDK_HOME"); -+ if (home != NULL) { -+ return build_path(buff, len, "%s\\%s\\%s", home); -+ } else { -+ char path[MAX_PATH]; -+ SHGetFolderPath( NULL, CSIDL_PROFILE, NULL, 0, path); -+ return build_path(buff, len, "%s\\%s\\%s", path); -+ } -+#else -+ const char* home = getenv("HOME"); -+ if (home == NULL) -+ home = "/tmp"; -+ -+ return build_path(buff, len, "%s/%s/%s", home); -+#endif -+} -Index: android-tools-4.2.2+git20130218/core/adbd/usb_vendors.h -=================================================================== ---- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ android-tools-4.2.2+git20130218/core/adbd/usb_vendors.h 2013-06-18 17:12:17.000000000 -0300 -@@ -0,0 +1,25 @@ -+/* -+ * Copyright (C) 2009 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 __USB_VENDORS_H -+#define __USB_VENDORS_H -+ -+extern int vendorIds[]; -+extern unsigned vendorIdCount; -+ -+void usb_vendors_init(void); -+ -+#endif -Index: android-tools-4.2.2+git20130218/core/adbd/usb_windows.c -=================================================================== ---- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ android-tools-4.2.2+git20130218/core/adbd/usb_windows.c 2013-06-18 17:12:17.000000000 -0300 -@@ -0,0 +1,515 @@ -+/* -+ * 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 -+#include -+#include -+#include -+#include -+#include -+ -+#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. -+ int saved_errno = GetLastError(); -+ usb_cleanup_handle(ret); -+ free(ret); -+ SetLastError(saved_errno); -+ -+ return NULL; -+} -+ -+int usb_write(usb_handle* handle, const void* data, int len) { -+ unsigned long time_out = 5000; -+ 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); -+ int saved_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 (saved_errno == ERROR_INVALID_HANDLE) -+ usb_kick(handle); -+ } -+ errno = saved_errno; -+ } 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 = 0; -+ 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); -+ int saved_errno = GetLastError(); -+ D("usb_write got: %ld, expected: %d, errno: %d\n", read, xfer, saved_errno); -+ if (ret) { -+ data += read; -+ len -= read; -+ -+ if (len == 0) -+ return 0; -+ } else { -+ // assume ERROR_INVALID_HANDLE indicates we are disconnected -+ if (saved_errno == ERROR_INVALID_HANDLE) -+ usb_kick(handle); -+ break; -+ } -+ errno = saved_errno; -+ } -+ } 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, NULL, 1); -+ } 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); -+} -Index: android-tools-4.2.2+git20130218/core/adbd/utils.c -=================================================================== ---- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ android-tools-4.2.2+git20130218/core/adbd/utils.c 2013-06-18 17:12:17.000000000 -0300 -@@ -0,0 +1,106 @@ -+/* -+ * 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 -+#include -+#include -+ -+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; -+} -Index: android-tools-4.2.2+git20130218/core/adbd/utils.h -=================================================================== ---- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ android-tools-4.2.2+git20130218/core/adbd/utils.h 2013-06-18 17:12:17.000000000 -0300 -@@ -0,0 +1,68 @@ -+/* -+ * 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 */ diff -Nru android-tools-4.2.2+git20130218/debian/patches/add-bq-vendor-id.patch android-tools-4.2.2+git20130529/debian/patches/add-bq-vendor-id.patch --- android-tools-4.2.2+git20130218/debian/patches/add-bq-vendor-id.patch 1970-01-01 00:00:00.000000000 +0000 +++ android-tools-4.2.2+git20130529/debian/patches/add-bq-vendor-id.patch 2014-11-24 20:27:47.000000000 +0000 @@ -0,0 +1,23 @@ +## Description: Let adb detect devices from BQ. +## Origin/Author: Jani Monoses +Index: android-tools-4.2.2+git20130218/core/adb/usb_vendors.c +=================================================================== +--- android-tools-4.2.2+git20130218.orig/core/adb/usb_vendors.c ++++ android-tools-4.2.2+git20130218/core/adb/usb_vendors.c +@@ -143,6 +143,8 @@ + #define VENDOR_ID_BYD 0x19D1 + // OUYA's USB Vendor ID + #define VENDOR_ID_OUYA 0x2836 ++// BQ's USB Vendor ID ++#define VENDOR_ID_BQ 0x2a47 + + + /** built-in vendor list */ +@@ -201,6 +203,7 @@ int builtInVendorIds[] = { + VENDOR_ID_XIAOMI, + VENDOR_ID_BYD, + VENDOR_ID_OUYA, ++ VENDOR_ID_BQ, + }; + + #define BUILT_IN_VENDOR_COUNT (sizeof(builtInVendorIds)/sizeof(builtInVendorIds[0])) diff -Nru android-tools-4.2.2+git20130218/debian/patches/cve-2014-1909.patch android-tools-4.2.2+git20130529/debian/patches/cve-2014-1909.patch --- android-tools-4.2.2+git20130218/debian/patches/cve-2014-1909.patch 1970-01-01 00:00:00.000000000 +0000 +++ android-tools-4.2.2+git20130529/debian/patches/cve-2014-1909.patch 2014-11-24 20:33:57.000000000 +0000 @@ -0,0 +1,24 @@ +Fix for CVE-2014-1909 as described in http://www.droidsec.org/advisories/2014/02/04/two-security-issues-found-in-the-android-sdk-tools.html + +Index: android-tools/core/adb/adb_client.c +=================================================================== +--- android-tools.orig/core/adb/adb_client.c ++++ android-tools/core/adb/adb_client.c +@@ -242,7 +242,7 @@ int adb_connect(const char *service) + } else { + // if server was running, check its version to make sure it is not out of date + char buf[100]; +- int n; ++ unsigned n; + int version = ADB_SERVER_VERSION - 1; + + // if we have a file descriptor, then parse version result +@@ -251,7 +251,7 @@ int adb_connect(const char *service) + + buf[4] = 0; + n = strtoul(buf, 0, 16); +- if(n > (int)sizeof(buf)) goto error; ++ if(n > sizeof(buf)) goto error; + if(readx(fd, buf, n)) goto error; + adb_close(fd); + diff -Nru android-tools-4.2.2+git20130218/debian/patches/enable-emulator.patch android-tools-4.2.2+git20130529/debian/patches/enable-emulator.patch --- android-tools-4.2.2+git20130218/debian/patches/enable-emulator.patch 2014-03-14 04:05:30.000000000 +0000 +++ android-tools-4.2.2+git20130529/debian/patches/enable-emulator.patch 1970-01-01 00:00:00.000000000 +0000 @@ -1,26 +0,0 @@ -Description: enable emulator check -Author: Dmitrijs Ledkovs - ---- android-tools-4.2.2+git20130218.orig/core/adbd/transport_local.c -+++ android-tools-4.2.2+git20130218/core/adbd/transport_local.c -@@ -309,15 +309,16 @@ void local_init(int port) - #else - /* For the adbd daemon in the system image we need to distinguish - * between the device, and the emulator. */ -- char is_qemu[PROPERTY_VALUE_MAX]; -+ //char is_qemu[PROPERTY_VALUE_MAX]; - //property_get("ro.kernel.qemu", is_qemu, ""); - //if (!strcmp(is_qemu, "1")) { -+ if (access("/dev/qemu_pipe", R_OK|W_OK) != -1) { - /* Running inside the emulator: use QEMUD pipe as the transport. */ -- // func = qemu_socket_thread; -- //} else { -+ func = qemu_socket_thread; -+ } else { - /* Running inside the device: use TCP socket as the transport. */ - func = server_socket_thread; -- //} -+ } - #endif // !ADB_HOST - } - diff -Nru android-tools-4.2.2+git20130218/debian/patches/reboot-syscall.patch android-tools-4.2.2+git20130529/debian/patches/reboot-syscall.patch --- android-tools-4.2.2+git20130218/debian/patches/reboot-syscall.patch 2014-03-14 04:05:30.000000000 +0000 +++ android-tools-4.2.2+git20130529/debian/patches/reboot-syscall.patch 1970-01-01 00:00:00.000000000 +0000 @@ -1,25 +0,0 @@ -Subject: port android_reboot() to call the reboot syscall via syscall() (glibc) rather than __reboot (bionic) -Author: Loïc Minier - ---- a/core/libcutils/android_reboot.c -+++ b/core/libcutils/android_reboot.c -@@ -21,6 +21,8 @@ - #include - #include - #include -+#include -+#include - - #include - -@@ -121,8 +123,8 @@ - break; - - case ANDROID_RB_RESTART2: -- ret = __reboot(LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2, -- LINUX_REBOOT_CMD_RESTART2, arg); -+ ret = syscall(SYS_reboot, LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2, -+ LINUX_REBOOT_CMD_RESTART2, arg); - break; - - default: diff -Nru android-tools-4.2.2+git20130218/debian/patches/series android-tools-4.2.2+git20130529/debian/patches/series --- android-tools-4.2.2+git20130218/debian/patches/series 2014-03-14 04:05:30.000000000 +0000 +++ android-tools-4.2.2+git20130529/debian/patches/series 2014-11-24 20:32:13.000000000 +0000 @@ -1,5 +1,6 @@ remove-selinux-android.patch -add_adbd.patch -reboot-syscall.patch -enable-emulator.patch +use-capability.patch +use-local-socket.patch ppc64el-ftbfs.patch +add-bq-vendor-id.patch +cve-2014-1909.patch diff -Nru android-tools-4.2.2+git20130218/debian/patches/use-capability.patch android-tools-4.2.2+git20130529/debian/patches/use-capability.patch --- android-tools-4.2.2+git20130218/debian/patches/use-capability.patch 1970-01-01 00:00:00.000000000 +0000 +++ android-tools-4.2.2+git20130529/debian/patches/use-capability.patch 2014-11-24 20:27:47.000000000 +0000 @@ -0,0 +1,14 @@ +Subject: use linux/capability.h on linux systems too +Author: Loïc Minier + +--- a/core/include/private/android_filesystem_config.h ++++ b/core/include/private/android_filesystem_config.h +@@ -27,7 +27,7 @@ + #include + #include + +-#ifdef HAVE_ANDROID_OS ++#if defined(HAVE_ANDROID_OS) || defined(__linux__) + #include + #else + #include "android_filesystem_capability.h" diff -Nru android-tools-4.2.2+git20130218/debian/patches/use-local-socket.patch android-tools-4.2.2+git20130529/debian/patches/use-local-socket.patch --- android-tools-4.2.2+git20130218/debian/patches/use-local-socket.patch 1970-01-01 00:00:00.000000000 +0000 +++ android-tools-4.2.2+git20130529/debian/patches/use-local-socket.patch 2014-11-24 20:27:47.000000000 +0000 @@ -0,0 +1,61 @@ +Subject: adb: Use local sockets where appropriate +Author: Hilko Bengen + +Index: android-tools/core/adb/adb.c +=================================================================== +--- android-tools.orig/core/adb/adb.c 2013-07-19 23:26:22.408974096 +0200 ++++ android-tools/core/adb/adb.c 2013-07-19 23:26:22.396974391 +0200 +@@ -1154,7 +1154,11 @@ int launch_server(int server_port) + */ + void build_local_name(char* target_str, size_t target_size, int server_port) + { +- snprintf(target_str, target_size, "tcp:%d", server_port); ++ if (gListenAll > 0) { ++ snprintf(target_str, target_size, "tcp:%d", server_port); ++ } else { ++ snprintf(target_str, target_size, "local:%d", server_port); ++ } + } + + #if !ADB_HOST +Index: android-tools/core/adb/adb_client.c +=================================================================== +--- android-tools.orig/core/adb/adb_client.c 2013-07-19 23:26:22.408974096 +0200 ++++ android-tools/core/adb/adb_client.c 2013-07-19 23:26:22.396974391 +0200 +@@ -185,12 +185,12 @@ int _adb_connect(const char *service) + strcpy(__adb_error, "service name too long"); + return -1; + } +- snprintf(tmp, sizeof tmp, "%04x", len); ++ snprintf(tmp, sizeof tmp, "%d", __adb_server_port); + + if (__adb_server_name) + fd = socket_network_client(__adb_server_name, __adb_server_port, SOCK_STREAM); + else +- fd = socket_loopback_client(__adb_server_port, SOCK_STREAM); ++ fd = socket_local_client(tmp, ANDROID_SOCKET_NAMESPACE_ABSTRACT, SOCK_STREAM); + + if(fd < 0) { + strcpy(__adb_error, "cannot connect to daemon"); +@@ -201,6 +201,7 @@ int _adb_connect(const char *service) + return -1; + } + ++ 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); +Index: android-tools/core/adb/transport_local.c +=================================================================== +--- android-tools.orig/core/adb/transport_local.c 2013-07-19 23:26:22.408974096 +0200 ++++ android-tools/core/adb/transport_local.c 2013-07-19 23:26:22.400974292 +0200 +@@ -118,7 +118,8 @@ int local_connect_arbitrary_ports(int co + } + #endif + if (fd < 0) { +- fd = socket_loopback_client(adb_port, SOCK_STREAM); ++ snprintf(buf, sizeof buf, "%d", adb_port); ++ fd = socket_local_client(buf, ANDROID_SOCKET_NAMESPACE_ABSTRACT, SOCK_STREAM); + } + + if (fd >= 0) { diff -Nru android-tools-4.2.2+git20130218/debian/README.source android-tools-4.2.2+git20130529/debian/README.source --- android-tools-4.2.2+git20130218/debian/README.source 2014-03-14 04:05:30.000000000 +0000 +++ android-tools-4.2.2+git20130529/debian/README.source 2014-11-24 20:27:47.000000000 +0000 @@ -10,3 +10,15 @@ The debian/create-snapshot script may be used to generate an android-tools.tar.xz from the latest upstream; see this script for a list of files to copy from upstream into the tarball. + + +udev rules +---------- + +The udev rules were derived from this project: +https://github.com/M0Rf30/android-udev-rules + +The direct download link is: +https://raw.githubusercontent.com/M0Rf30/android-udev-rules/master/51-android.rules + + -- Hans-Christoph Steiner , Tue, 21 Oct 2014 00:16:55 -0400 diff -Nru android-tools-4.2.2+git20130218/debian/rules android-tools-4.2.2+git20130529/debian/rules --- android-tools-4.2.2+git20130218/debian/rules 2014-03-14 04:06:05.000000000 +0000 +++ android-tools-4.2.2+git20130529/debian/rules 2014-11-24 20:27:47.000000000 +0000 @@ -3,6 +3,7 @@ export DEB_HOST_GNU_TYPE ?= $(shell dpkg-architecture -qDEB_HOST_GNU_TYPE) export CC := $(DEB_HOST_GNU_TYPE)-gcc +export SRCDIR := $(CURDIR) M := $(CURDIR)/debian/makefiles @@ -14,23 +15,18 @@ override_dh_clean: dh_clean - $(MAKE) -f $(M)/adb.mk -C core/adb clean -ifeq (,$(filter $(DEB_HOST_ARCH),powerpc)) - $(MAKE) -f $(M)/adbd.mk -C core/adbd clean -endif - $(MAKE) -f $(M)/fastboot.mk -C core/fastboot clean - $(MAKE) -f $(M)/ext4_utils.mk -C extras/ext4_utils clean + rm -rf builddir/ override_dh_auto_build: - $(MAKE) -f $(M)/adb.mk -C core/adb -ifeq (,$(filter $(DEB_HOST_ARCH),powerpc)) - $(MAKE) -f $(M)/adbd.mk -C core/adbd -endif - $(MAKE) -f $(M)/fastboot.mk -C core/fastboot - $(MAKE) -f $(M)/ext4_utils.mk -C extras/ext4_utils + mkdir -p builddir/adb + $(MAKE) -f $(M)/adb.mk -C builddir/adb + mkdir -p builddir/fastboot + $(MAKE) -f $(M)/fastboot.mk -C builddir/fastboot + mkdir -p builddir/ext4_utils + $(MAKE) -f $(M)/ext4_utils.mk -C builddir/ext4_utils override_dh_install: - dh_install --sourcedir=. + dh_install $(INSTALL_PROGRAM) core/libsparse/simg_dump.py debian/android-tools-fsutils/usr/bin/simg_dump $(INSTALL_PROGRAM) extras/ext4_utils/mkuserimg.sh debian/android-tools-fsutils/usr/bin/mkuserimg diff -Nru android-tools-4.2.2+git20130218/debian/TODO.Debian android-tools-4.2.2+git20130529/debian/TODO.Debian --- android-tools-4.2.2+git20130218/debian/TODO.Debian 1970-01-01 00:00:00.000000000 +0000 +++ android-tools-4.2.2+git20130529/debian/TODO.Debian 2014-11-24 20:27:47.000000000 +0000 @@ -0,0 +1,6 @@ +Currently this package is only built on linux-based Debian architectures. + +To build on kfreebsd, this source requires porting of the selinux calls in +extras/ext4_utils and core/fastboot/usb_*.c. + +Concerning hurd, even more porting work is needed for e.g. the USB stack. diff -Nru android-tools-4.2.2+git20130218/extras/ext4_utils/allocate.c android-tools-4.2.2+git20130529/extras/ext4_utils/allocate.c --- android-tools-4.2.2+git20130218/extras/ext4_utils/allocate.c 2013-02-18 14:49:03.000000000 +0000 +++ android-tools-4.2.2+git20130529/extras/ext4_utils/allocate.c 2013-05-29 20:16:54.000000000 +0000 @@ -60,6 +60,12 @@ u16 used_dirs; }; +struct xattr_list_element { + struct ext4_inode *inode; + struct ext4_xattr_header *header; + struct xattr_list_element *next; +}; + struct block_allocation *create_allocation() { struct block_allocation *alloc = malloc(sizeof(struct block_allocation)); @@ -74,6 +80,25 @@ return alloc; } +static struct ext4_xattr_header *xattr_list_find(struct ext4_inode *inode) +{ + struct xattr_list_element *element; + for (element = aux_info.xattrs; element != NULL; element = element->next) { + if (element->inode == inode) + return element->header; + } + return NULL; +} + +static void xattr_list_insert(struct ext4_inode *inode, struct ext4_xattr_header *header) +{ + struct xattr_list_element *element = malloc(sizeof(struct xattr_list_element)); + element->inode = inode; + element->header = header; + element->next = aux_info.xattrs; + aux_info.xattrs = element; +} + static void region_list_remove(struct region_list *list, struct region *reg) { if (reg->prev) @@ -673,6 +698,35 @@ info.inode_size); } +struct ext4_xattr_header *get_xattr_block_for_inode(struct ext4_inode *inode) +{ + struct ext4_xattr_header *block = xattr_list_find(inode); + if (block != NULL) + return block; + + u32 block_num = allocate_block(); + block = calloc(info.block_size, 1); + if (block == NULL) { + error("get_xattr: failed to allocate %d", info.block_size); + return NULL; + } + + block->h_magic = cpu_to_le32(EXT4_XATTR_MAGIC); + block->h_refcount = cpu_to_le32(1); + block->h_blocks = cpu_to_le32(1); + inode->i_blocks_lo = cpu_to_le32(le32_to_cpu(inode->i_blocks_lo) + (info.block_size / 512)); + inode->i_file_acl_lo = cpu_to_le32(block_num); + + int result = sparse_file_add_data(info.sparse_file, block, info.block_size, block_num); + if (result != 0) { + error("get_xattr: sparse_file_add_data failure %d", result); + free(block); + return NULL; + } + xattr_list_insert(inode, block); + return block; +} + /* Mark the first len inodes in a block group as used */ u32 reserve_inodes(int bg, u32 num) { diff -Nru android-tools-4.2.2+git20130218/extras/ext4_utils/allocate.h android-tools-4.2.2+git20130529/extras/ext4_utils/allocate.h --- android-tools-4.2.2+git20130218/extras/ext4_utils/allocate.h 2013-02-18 14:49:03.000000000 +0000 +++ android-tools-4.2.2+git20130529/extras/ext4_utils/allocate.h 2013-05-29 20:16:54.000000000 +0000 @@ -21,6 +21,7 @@ #include "ext4_utils.h" #include "ext4.h" +#include "xattr.h" struct block_allocation; @@ -31,6 +32,7 @@ int block_allocation_num_regions(struct block_allocation *alloc); int block_allocation_len(struct block_allocation *alloc); struct ext4_inode *get_inode(u32 inode); +struct ext4_xattr_header *get_xattr_block_for_inode(struct ext4_inode *inode); void reduce_allocation(struct block_allocation *alloc, u32 len); u32 get_block(struct block_allocation *alloc, u32 block); u32 get_oob_block(struct block_allocation *alloc, u32 block); diff -Nru android-tools-4.2.2+git20130218/extras/ext4_utils/contents.c android-tools-4.2.2+git20130529/extras/ext4_utils/contents.c --- android-tools-4.2.2+git20130218/extras/ext4_utils/contents.c 2013-02-18 14:49:03.000000000 +0000 +++ android-tools-4.2.2+git20130529/extras/ext4_utils/contents.c 2013-05-29 20:16:54.000000000 +0000 @@ -18,6 +18,15 @@ #include #include +#ifdef HAVE_ANDROID_OS +#include +#else +#include +#endif + +#define XATTR_SELINUX_SUFFIX "selinux" +#define XATTR_CAPS_SUFFIX "capability" + #include "ext4_utils.h" #include "ext4.h" #include "make_ext4fs.h" @@ -190,7 +199,7 @@ } /* Creates a file on disk. Returns the inode number of the new file */ -u32 make_link(const char *filename, const char *link) +u32 make_link(const char *link) { struct ext4_inode *inode; u32 inode_num; @@ -242,44 +251,231 @@ return 0; } -#define XATTR_SELINUX_SUFFIX "selinux" +/* + * Returns the amount of free space available in the specified + * xattr region + */ +static size_t xattr_free_space(struct ext4_xattr_entry *entry, char *end) +{ + while(!IS_LAST_ENTRY(entry) && (((char *) entry) < end)) { + end -= EXT4_XATTR_SIZE(le32_to_cpu(entry->e_value_size)); + entry = EXT4_XATTR_NEXT(entry); + } -/* XXX */ -#define cpu_to_le32(x) (x) -#define cpu_to_le16(x) (x) + if (((char *) entry) > end) { + error("unexpected read beyond end of xattr space"); + return 0; + } -int inode_set_selinux(u32 inode_num, const char *secon) + return end - ((char *) entry); +} + +/* + * Returns a pointer to the free space immediately after the + * last xattr element + */ +static struct ext4_xattr_entry* xattr_get_last(struct ext4_xattr_entry *entry) { - struct ext4_inode *inode = get_inode(inode_num); - u32 *hdr; - struct ext4_xattr_entry *entry; - size_t name_len = strlen(XATTR_SELINUX_SUFFIX); - size_t value_len; - size_t size, min_offs; - char *val; + for (; !IS_LAST_ENTRY(entry); entry = EXT4_XATTR_NEXT(entry)) { + // skip entry + } + return entry; +} - if (!secon) - return 0; +/* + * assert that the elements in the ext4 xattr section are in sorted order + * + * The ext4 filesystem requires extended attributes to be sorted when + * they're not stored in the inode. The kernel ext4 code uses the following + * sorting algorithm: + * + * 1) First sort extended attributes by their name_index. For example, + * EXT4_XATTR_INDEX_USER (1) comes before EXT4_XATTR_INDEX_SECURITY (6). + * 2) If the name_indexes are equal, then sorting is based on the length + * of the name. For example, XATTR_SELINUX_SUFFIX ("selinux") comes before + * XATTR_CAPS_SUFFIX ("capability") because "selinux" is shorter than "capability" + * 3) If the name_index and name_length are equal, then memcmp() is used to determine + * which name comes first. For example, "selinux" would come before "yelinux". + * + * This method is intended to implement the sorting function defined in + * the Linux kernel file fs/ext4/xattr.c function ext4_xattr_find_entry(). + */ +static void xattr_assert_sane(struct ext4_xattr_entry *entry) +{ + for( ; !IS_LAST_ENTRY(entry); entry = EXT4_XATTR_NEXT(entry)) { + struct ext4_xattr_entry *next = EXT4_XATTR_NEXT(entry); + if (IS_LAST_ENTRY(next)) { + return; + } - if (!inode) + int cmp = next->e_name_index - entry->e_name_index; + if (cmp == 0) + cmp = next->e_name_len - entry->e_name_len; + if (cmp == 0) + cmp = memcmp(next->e_name, entry->e_name, next->e_name_len); + if (cmp < 0) { + error("BUG: extended attributes are not sorted\n"); + return; + } + if (cmp == 0) { + error("BUG: duplicate extended attributes detected\n"); + return; + } + } +} + +#define NAME_HASH_SHIFT 5 +#define VALUE_HASH_SHIFT 16 + +static void ext4_xattr_hash_entry(struct ext4_xattr_header *header, + struct ext4_xattr_entry *entry) +{ + __u32 hash = 0; + char *name = entry->e_name; + int n; + + for (n = 0; n < entry->e_name_len; n++) { + hash = (hash << NAME_HASH_SHIFT) ^ + (hash >> (8*sizeof(hash) - NAME_HASH_SHIFT)) ^ + *name++; + } + + if (entry->e_value_block == 0 && entry->e_value_size != 0) { + __le32 *value = (__le32 *)((char *)header + + le16_to_cpu(entry->e_value_offs)); + for (n = (le32_to_cpu(entry->e_value_size) + + EXT4_XATTR_ROUND) >> EXT4_XATTR_PAD_BITS; n; n--) { + hash = (hash << VALUE_HASH_SHIFT) ^ + (hash >> (8*sizeof(hash) - VALUE_HASH_SHIFT)) ^ + le32_to_cpu(*value++); + } + } + entry->e_hash = cpu_to_le32(hash); +} + +#undef NAME_HASH_SHIFT +#undef VALUE_HASH_SHIFT + +static struct ext4_xattr_entry* xattr_addto_range( + void *block_start, + void *block_end, + struct ext4_xattr_entry *first, + int name_index, + const char *name, + const void *value, + size_t value_len) +{ + size_t name_len = strlen(name); + if (name_len > 255) + return NULL; + + size_t available_size = xattr_free_space(first, block_end); + size_t needed_size = EXT4_XATTR_LEN(name_len) + EXT4_XATTR_SIZE(value_len); + + if (needed_size > available_size) + return NULL; + + struct ext4_xattr_entry *new_entry = xattr_get_last(first); + memset(new_entry, 0, EXT4_XATTR_LEN(name_len)); + + new_entry->e_name_len = name_len; + new_entry->e_name_index = name_index; + memcpy(new_entry->e_name, name, name_len); + new_entry->e_value_block = 0; + new_entry->e_value_size = cpu_to_le32(value_len); + + char *val = (char *) new_entry + available_size - EXT4_XATTR_SIZE(value_len); + size_t e_value_offs = val - (char *) block_start; + + new_entry->e_value_offs = cpu_to_le16(e_value_offs); + memset(val, 0, EXT4_XATTR_SIZE(value_len)); + memcpy(val, value, value_len); + + xattr_assert_sane(first); + return new_entry; +} + +static int xattr_addto_inode(struct ext4_inode *inode, int name_index, + const char *name, const void *value, size_t value_len) +{ + struct ext4_xattr_ibody_header *hdr = (struct ext4_xattr_ibody_header *) (inode + 1); + struct ext4_xattr_entry *first = (struct ext4_xattr_entry *) (hdr + 1); + char *block_end = ((char *) inode) + info.inode_size; + + struct ext4_xattr_entry *result = + xattr_addto_range(first, block_end, first, name_index, name, value, value_len); + + if (result == NULL) return -1; - hdr = (u32 *) (inode + 1); - *hdr = cpu_to_le32(EXT4_XATTR_MAGIC); - entry = (struct ext4_xattr_entry *) (hdr+1); - memset(entry, 0, EXT4_XATTR_LEN(name_len)); - entry->e_name_index = EXT4_XATTR_INDEX_SECURITY; - entry->e_name_len = name_len; - memcpy(entry->e_name, XATTR_SELINUX_SUFFIX, name_len); - value_len = strlen(secon)+1; - entry->e_value_size = cpu_to_le32(value_len); - min_offs = (char *)inode + info.inode_size - (char*) entry; - size = EXT4_XATTR_SIZE(value_len); - val = (char *)entry + min_offs - size; - entry->e_value_offs = cpu_to_le16(min_offs - size); - memset(val + size - EXT4_XATTR_PAD, 0, EXT4_XATTR_PAD); - memcpy(val, secon, value_len); + hdr->h_magic = cpu_to_le32(EXT4_XATTR_MAGIC); inode->i_extra_isize = cpu_to_le16(sizeof(struct ext4_inode) - EXT4_GOOD_OLD_INODE_SIZE); return 0; } + +static int xattr_addto_block(struct ext4_inode *inode, int name_index, + const char *name, const void *value, size_t value_len) +{ + struct ext4_xattr_header *header = get_xattr_block_for_inode(inode); + if (!header) + return -1; + + struct ext4_xattr_entry *first = (struct ext4_xattr_entry *) (header + 1); + char *block_end = ((char *) header) + info.block_size; + + struct ext4_xattr_entry *result = + xattr_addto_range(header, block_end, first, name_index, name, value, value_len); + + if (result == NULL) + return -1; + + ext4_xattr_hash_entry(header, result); + return 0; +} + + +static int xattr_add(u32 inode_num, int name_index, const char *name, + const void *value, size_t value_len) +{ + if (!value) + return 0; + + struct ext4_inode *inode = get_inode(inode_num); + + if (!inode) + return -1; + + int result = xattr_addto_inode(inode, name_index, name, value, value_len); + if (result != 0) { + result = xattr_addto_block(inode, name_index, name, value, value_len); + } + return result; +} + +int inode_set_selinux(u32 inode_num, const char *secon) +{ + if (!secon) + return 0; + + return xattr_add(inode_num, EXT4_XATTR_INDEX_SECURITY, + XATTR_SELINUX_SUFFIX, secon, strlen(secon) + 1); +} + +int inode_set_capabilities(u32 inode_num, uint64_t capabilities) { + if (capabilities == 0) + return 0; + + struct vfs_cap_data cap_data; + memset(&cap_data, 0, sizeof(cap_data)); + + cap_data.magic_etc = VFS_CAP_REVISION | VFS_CAP_FLAGS_EFFECTIVE; + cap_data.data[0].permitted = (uint32_t) (capabilities & 0xffffffff); + cap_data.data[0].inheritable = 0; + cap_data.data[1].permitted = (uint32_t) (capabilities >> 32); + cap_data.data[1].inheritable = 0; + + return xattr_add(inode_num, EXT4_XATTR_INDEX_SECURITY, + XATTR_CAPS_SUFFIX, &cap_data, sizeof(cap_data)); +} + diff -Nru android-tools-4.2.2+git20130218/extras/ext4_utils/contents.h android-tools-4.2.2+git20130529/extras/ext4_utils/contents.h --- android-tools-4.2.2+git20130218/extras/ext4_utils/contents.h 2013-02-18 14:49:03.000000000 +0000 +++ android-tools-4.2.2+git20130529/extras/ext4_utils/contents.h 2013-05-29 20:16:54.000000000 +0000 @@ -30,12 +30,14 @@ u32 *inode; u32 mtime; char *secon; + uint64_t capabilities; }; u32 make_directory(u32 dir_inode_num, u32 entries, struct dentry *dentries, u32 dirs); u32 make_file(const char *filename, u64 len); -u32 make_link(const char *filename, const char *link); +u32 make_link(const char *link); int inode_set_permissions(u32 inode_num, u16 mode, u16 uid, u16 gid, u32 mtime); int inode_set_selinux(u32 inode_num, const char *secon); +int inode_set_capabilities(u32 inode_num, uint64_t capabilities); #endif diff -Nru android-tools-4.2.2+git20130218/extras/ext4_utils/ext2simg.c android-tools-4.2.2+git20130529/extras/ext4_utils/ext2simg.c --- android-tools-4.2.2+git20130218/extras/ext4_utils/ext2simg.c 2013-02-18 14:49:03.000000000 +0000 +++ android-tools-4.2.2+git20130529/extras/ext4_utils/ext2simg.c 2013-05-29 20:16:54.000000000 +0000 @@ -57,7 +57,6 @@ { off64_t ret; struct ext4_super_block sb; - unsigned int i; ret = lseek64(fd, 1024, SEEK_SET); if (ret < 0) diff -Nru android-tools-4.2.2+git20130218/extras/ext4_utils/ext4fixup.c android-tools-4.2.2+git20130529/extras/ext4_utils/ext4fixup.c --- android-tools-4.2.2+git20130218/extras/ext4_utils/ext4fixup.c 2013-02-18 14:49:03.000000000 +0000 +++ android-tools-4.2.2+git20130529/extras/ext4_utils/ext4fixup.c 2013-05-29 20:16:54.000000000 +0000 @@ -200,7 +200,6 @@ { off64_t ret; struct ext4_super_block sb; - unsigned int i; read_sb(fd, &sb); @@ -510,7 +509,7 @@ return count; } -static int get_extent_ents(int fd, struct ext4_extent_header *ext_hdr, unsigned long long *block_list) +static int get_extent_ents(struct ext4_extent_header *ext_hdr, unsigned long long *block_list) { int i, j; struct ext4_extent *extent; @@ -560,7 +559,7 @@ tmp_ext_hdr = (struct ext4_extent_header *)block; if (tmp_ext_hdr->eh_depth == 0) { - get_extent_ents(fd, tmp_ext_hdr, block_list); /* leaf node, fill in block_list */ + get_extent_ents(tmp_ext_hdr, block_list); /* leaf node, fill in block_list */ } else { get_extent_idx(fd, tmp_ext_hdr, block_list); /* recurse down the tree */ } @@ -581,7 +580,7 @@ } if (extent_hdr->eh_depth == 0) { - get_extent_ents(fd, (struct ext4_extent_header *)inode->i_block, block_list); + get_extent_ents((struct ext4_extent_header *)inode->i_block, block_list); return 0; } diff -Nru android-tools-4.2.2+git20130218/extras/ext4_utils/ext4_utils.c android-tools-4.2.2+git20130529/extras/ext4_utils/ext4_utils.c --- android-tools-4.2.2+git20130218/extras/ext4_utils/ext4_utils.c 2013-02-18 14:49:03.000000000 +0000 +++ android-tools-4.2.2+git20130529/extras/ext4_utils/ext4_utils.c 2013-05-29 20:16:54.000000000 +0000 @@ -126,6 +126,7 @@ aux_info.bg_desc = calloc(info.block_size, aux_info.bg_desc_blocks); if (!aux_info.bg_desc) critical_error_errno("calloc"); + aux_info.xattrs = NULL; } void ext4_free_fs_aux_info() diff -Nru android-tools-4.2.2+git20130218/extras/ext4_utils/ext4_utils.h android-tools-4.2.2+git20130529/extras/ext4_utils/ext4_utils.h --- android-tools-4.2.2+git20130218/extras/ext4_utils/ext4_utils.h 2013-02-18 14:49:03.000000000 +0000 +++ android-tools-4.2.2+git20130529/extras/ext4_utils/ext4_utils.h 2013-05-29 20:16:54.000000000 +0000 @@ -36,6 +36,7 @@ #include #include #include +#include #if defined(__APPLE__) && defined(__MACH__) #define lseek64 lseek @@ -84,6 +85,12 @@ #define __u16 u16 #define __u8 u8 +/* XXX */ +#define cpu_to_le32(x) (x) +#define cpu_to_le16(x) (x) +#define le32_to_cpu(x) (x) +#define le16_to_cpu(x) (x) + typedef unsigned long long u64; typedef signed long long s64; typedef unsigned int u32; @@ -91,6 +98,7 @@ typedef unsigned char u8; struct block_group_info; +struct xattr_list_element; struct ext2_group_desc { __le32 bg_block_bitmap; @@ -130,6 +138,7 @@ struct ext4_super_block **backup_sb; struct ext2_group_desc *bg_desc; struct block_group_info *bgs; + struct xattr_list_element *xattrs; u32 first_data_block; u64 len_blocks; u32 inode_table_blocks; @@ -171,7 +180,7 @@ u16 ext4_crc16(u16 crc_in, const void *buf, int size); typedef void (*fs_config_func_t)(const char *path, int dir, unsigned *uid, unsigned *gid, - unsigned *mode); + unsigned *mode, uint64_t *capabilities); struct selabel_handle; diff -Nru android-tools-4.2.2+git20130218/extras/ext4_utils/indirect.c android-tools-4.2.2+git20130529/extras/ext4_utils/indirect.c --- android-tools-4.2.2+git20130218/extras/ext4_utils/indirect.c 2013-02-18 14:49:03.000000000 +0000 +++ android-tools-4.2.2+git20130529/extras/ext4_utils/indirect.c 2013-05-29 20:16:54.000000000 +0000 @@ -387,7 +387,7 @@ } static struct block_allocation *do_inode_allocate_indirect( - struct ext4_inode *inode, u32 block_len) + u32 block_len) { u32 indirect_len = indirect_blocks_needed(block_len); @@ -408,7 +408,7 @@ u32 block_len = DIV_ROUND_UP(len, info.block_size); u32 indirect_len = indirect_blocks_needed(block_len); - alloc = do_inode_allocate_indirect(inode, block_len); + alloc = do_inode_allocate_indirect(block_len); if (alloc == NULL) { error("failed to allocate extents for %lu bytes", len); return; @@ -494,7 +494,7 @@ u32 block_len = DIV_ROUND_UP(len, info.block_size); u8 *data = NULL; - alloc = do_inode_allocate_indirect(inode, block_len); + alloc = do_inode_allocate_indirect(block_len); if (alloc == NULL) { error("failed to allocate extents for %lu bytes", len); return NULL; diff -Nru android-tools-4.2.2+git20130218/extras/ext4_utils/make_ext4fs.c android-tools-4.2.2+git20130529/extras/ext4_utils/make_ext4fs.c --- android-tools-4.2.2+git20130218/extras/ext4_utils/make_ext4fs.c 2013-02-18 14:49:03.000000000 +0000 +++ android-tools-4.2.2+git20130529/extras/ext4_utils/make_ext4fs.c 2013-05-29 20:16:54.000000000 +0000 @@ -164,16 +164,18 @@ dentries[i].size = stat.st_size; dentries[i].mode = stat.st_mode & (S_ISUID|S_ISGID|S_ISVTX|S_IRWXU|S_IRWXG|S_IRWXO); dentries[i].mtime = stat.st_mtime; + uint64_t capabilities; if (fs_config_func != NULL) { #ifdef ANDROID unsigned int mode = 0; unsigned int uid = 0; unsigned int gid = 0; int dir = S_ISDIR(stat.st_mode); - fs_config_func(dentries[i].path, dir, &uid, &gid, &mode); + fs_config_func(dentries[i].path, dir, &uid, &gid, &mode, &capabilities); dentries[i].mode = mode; dentries[i].uid = uid; dentries[i].gid = gid; + dentries[i].capabilities = capabilities; #else error("can't set android permissions - built without android support"); #endif @@ -258,7 +260,7 @@ free(subdir_full_path); free(subdir_dir_path); } else if (dentries[i].file_type == EXT4_FT_SYMLINK) { - entry_inode = make_link(dentries[i].full_path, dentries[i].link); + entry_inode = make_link(dentries[i].link); } else { error("unknown file type on %s", dentries[i].path); entry_inode = 0; @@ -270,9 +272,20 @@ dentries[i].mtime); if (ret) error("failed to set permissions on %s\n", dentries[i].path); + + /* + * It's important to call inode_set_selinux() before + * inode_set_capabilities(). Extended attributes need to + * be stored sorted order, and we guarantee this by making + * the calls in the proper order. + * Please see xattr_assert_sane() in contents.c + */ ret = inode_set_selinux(entry_inode, dentries[i].secon); if (ret) error("failed to set SELinux context on %s\n", dentries[i].path); + ret = inode_set_capabilities(entry_inode, dentries[i].capabilities); + if (ret) + error("failed to set capability on %s\n", dentries[i].path); free(dentries[i].path); free(dentries[i].full_path); @@ -451,7 +464,6 @@ u16 root_mode; char *mountpoint; char *directory = NULL; - int ret; if (setjmp(setjmp_env)) return EXIT_FAILURE; /* Handle a call to longjmp() */ @@ -503,7 +515,8 @@ info.inodes_per_group = compute_inodes_per_group(); info.feat_compat |= - EXT4_FEATURE_COMPAT_RESIZE_INODE; + EXT4_FEATURE_COMPAT_RESIZE_INODE | + EXT4_FEATURE_COMPAT_EXT_ATTR; info.feat_ro_compat |= EXT4_FEATURE_RO_COMPAT_SPARSE_SUPER | diff -Nru android-tools-4.2.2+git20130218/extras/ext4_utils/xattr.h android-tools-4.2.2+git20130529/extras/ext4_utils/xattr.h --- android-tools-4.2.2+git20130218/extras/ext4_utils/xattr.h 2013-02-18 14:49:03.000000000 +0000 +++ android-tools-4.2.2+git20130529/extras/ext4_utils/xattr.h 2013-05-29 20:16:54.000000000 +0000 @@ -1,8 +1,24 @@ #include +#ifndef _SYSTEM_EXTRAS_EXT4_UTILS_XATTR_H +#define _SYSTEM_EXTRAS_EXT4_UTILS_XATTR_H 1 + #define EXT4_XATTR_MAGIC 0xEA020000 #define EXT4_XATTR_INDEX_SECURITY 6 +struct ext4_xattr_header { + __le32 h_magic; + __le32 h_refcount; + __le32 h_blocks; + __le32 h_hash; + __le32 h_checksum; + __u32 h_reserved[3]; +}; + +struct ext4_xattr_ibody_header { + __le32 h_magic; +}; + struct ext4_xattr_entry { __u8 e_name_len; __u8 e_name_index; @@ -19,5 +35,11 @@ #define EXT4_XATTR_LEN(name_len) \ (((name_len) + EXT4_XATTR_ROUND + \ sizeof(struct ext4_xattr_entry)) & ~EXT4_XATTR_ROUND) +#define EXT4_XATTR_NEXT(entry) \ + ((struct ext4_xattr_entry *)( \ + (char *)(entry) + EXT4_XATTR_LEN((entry)->e_name_len))) #define EXT4_XATTR_SIZE(size) \ (((size) + EXT4_XATTR_ROUND) & ~EXT4_XATTR_ROUND) +#define IS_LAST_ENTRY(entry) (*(__u32 *)(entry) == 0) + +#endif /* !_SYSTEM_EXTRAS_EXT4_UTILS_XATTR_H */ diff -Nru android-tools-4.2.2+git20130218/libhardware/hardware.c android-tools-4.2.2+git20130529/libhardware/hardware.c --- android-tools-4.2.2+git20130218/libhardware/hardware.c 1970-01-01 00:00:00.000000000 +0000 +++ android-tools-4.2.2+git20130529/libhardware/hardware.c 2013-05-29 20:16:54.000000000 +0000 @@ -0,0 +1,175 @@ +/* + * 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 + +#include + +#include +#include +#include +#include +#include + +#define LOG_TAG "HAL" +#include + +/** Base path of the hal modules */ +#define HAL_LIBRARY_PATH1 "/system/lib/hw" +#define HAL_LIBRARY_PATH2 "/vendor/lib/hw" + +/** + * There are a set of variant filename for modules. The form of the filename + * is ".variant.so" so for the led module the Dream variants + * of base "ro.product.board", "ro.board.platform" and "ro.arch" would be: + * + * led.trout.so + * led.msm7k.so + * led.ARMV6.so + * led.default.so + */ + +static const char *variant_keys[] = { + "ro.hardware", /* This goes first so that it can pick up a different + file on the emulator. */ + "ro.product.board", + "ro.board.platform", + "ro.arch" +}; + +static const int HAL_VARIANT_KEYS_COUNT = + (sizeof(variant_keys)/sizeof(variant_keys[0])); + +/** + * Load the file defined by the variant and if successful + * return the dlopen handle and the hmi. + * @return 0 = success, !0 = failure. + */ +static int load(const char *id, + const char *path, + const struct hw_module_t **pHmi) +{ + int status; + void *handle; + struct hw_module_t *hmi; + + /* + * load the symbols resolving undefined symbols before + * dlopen returns. Since RTLD_GLOBAL is not or'd in with + * RTLD_NOW the external symbols will not be global + */ + handle = dlopen(path, RTLD_NOW); + if (handle == NULL) { + char const *err_str = dlerror(); + ALOGE("load: module=%s\n%s", path, err_str?err_str:"unknown"); + status = -EINVAL; + goto done; + } + + /* Get the address of the struct hal_module_info. */ + const char *sym = HAL_MODULE_INFO_SYM_AS_STR; + hmi = (struct hw_module_t *)dlsym(handle, sym); + if (hmi == NULL) { + ALOGE("load: couldn't find symbol %s", sym); + status = -EINVAL; + goto done; + } + + /* Check that the id matches */ + if (strcmp(id, hmi->id) != 0) { + ALOGE("load: id=%s != hmi->id=%s", id, hmi->id); + status = -EINVAL; + goto done; + } + + hmi->dso = handle; + + /* success */ + status = 0; + + done: + if (status != 0) { + hmi = NULL; + if (handle != NULL) { + dlclose(handle); + handle = NULL; + } + } else { + ALOGV("loaded HAL id=%s path=%s hmi=%p handle=%p", + id, path, *pHmi, handle); + } + + *pHmi = hmi; + + return status; +} + +int hw_get_module_by_class(const char *class_id, const char *inst, + const struct hw_module_t **module) +{ + int status; + int i; + const struct hw_module_t *hmi = NULL; + char prop[PATH_MAX]; + char path[PATH_MAX]; + char name[PATH_MAX]; + + if (inst) + snprintf(name, PATH_MAX, "%s.%s", class_id, inst); + else + strlcpy(name, class_id, PATH_MAX); + + /* + * Here we rely on the fact that calling dlopen multiple times on + * the same .so will simply increment a refcount (and not load + * a new copy of the library). + * We also assume that dlopen() is thread-safe. + */ + + /* Loop through the configuration variants looking for a module */ + for (i=0 ; i +#include +#include +#include +#include + +#include + +#include + + +__BEGIN_DECLS + + +///////////////////////////////////////////////// +// Common Definitions +///////////////////////////////////////////////// + +// +//--- Effect descriptor structure effect_descriptor_t +// + +// Unique effect ID (can be generated from the following site: +// http://www.itu.int/ITU-T/asn1/uuid.html) +// This format is used for both "type" and "uuid" fields of the effect descriptor structure. +// - When used for effect type and the engine is implementing and effect corresponding to a standard +// OpenSL ES interface, this ID must be the one defined in OpenSLES_IID.h for that interface. +// - When used as uuid, it should be a unique UUID for this particular implementation. +typedef struct effect_uuid_s { + uint32_t timeLow; + uint16_t timeMid; + uint16_t timeHiAndVersion; + uint16_t clockSeq; + uint8_t node[6]; +} effect_uuid_t; + +// Maximum length of character strings in structures defines by this API. +#define EFFECT_STRING_LEN_MAX 64 + +// NULL UUID definition (matches SL_IID_NULL_) +#define EFFECT_UUID_INITIALIZER { 0xec7178ec, 0xe5e1, 0x4432, 0xa3f4, \ + { 0x46, 0x57, 0xe6, 0x79, 0x52, 0x10 } } +static const effect_uuid_t EFFECT_UUID_NULL_ = EFFECT_UUID_INITIALIZER; +const effect_uuid_t * const EFFECT_UUID_NULL = &EFFECT_UUID_NULL_; +const char * const EFFECT_UUID_NULL_STR = "ec7178ec-e5e1-4432-a3f4-4657e6795210"; + +// The effect descriptor contains necessary information to facilitate the enumeration of the effect +// engines present in a library. +typedef struct effect_descriptor_s { + effect_uuid_t type; // UUID of to the OpenSL ES interface implemented by this effect + effect_uuid_t uuid; // UUID for this particular implementation + uint32_t apiVersion; // Version of the effect control API implemented + uint32_t flags; // effect engine capabilities/requirements flags (see below) + uint16_t cpuLoad; // CPU load indication (see below) + uint16_t memoryUsage; // Data Memory usage (see below) + char name[EFFECT_STRING_LEN_MAX]; // human readable effect name + char implementor[EFFECT_STRING_LEN_MAX]; // human readable effect implementor name +} effect_descriptor_t; + +// CPU load and memory usage indication: each effect implementation must provide an indication of +// its CPU and memory usage for the audio effect framework to limit the number of effects +// instantiated at a given time on a given platform. +// The CPU load is expressed in 0.1 MIPS units as estimated on an ARM9E core (ARMv5TE) with 0 WS. +// The memory usage is expressed in KB and includes only dynamically allocated memory + +// Definitions for flags field of effect descriptor. +// +---------------------------+-----------+----------------------------------- +// | description | bits | values +// +---------------------------+-----------+----------------------------------- +// | connection mode | 0..2 | 0 insert: after track process +// | | | 1 auxiliary: connect to track auxiliary +// | | | output and use send level +// | | | 2 replace: replaces track process function; +// | | | must implement SRC, volume and mono to stereo. +// | | | 3 pre processing: applied below audio HAL on input +// | | | 4 post processing: applied below audio HAL on output +// | | | 5 - 7 reserved +// +---------------------------+-----------+----------------------------------- +// | insertion preference | 3..5 | 0 none +// | | | 1 first of the chain +// | | | 2 last of the chain +// | | | 3 exclusive (only effect in the insert chain) +// | | | 4..7 reserved +// +---------------------------+-----------+----------------------------------- +// | Volume management | 6..8 | 0 none +// | | | 1 implements volume control +// | | | 2 requires volume indication +// | | | 4 reserved +// +---------------------------+-----------+----------------------------------- +// | Device indication | 9..11 | 0 none +// | | | 1 requires device updates +// | | | 2, 4 reserved +// +---------------------------+-----------+----------------------------------- +// | Sample input mode | 12..13 | 1 direct: process() function or EFFECT_CMD_SET_CONFIG +// | | | command must specify a buffer descriptor +// | | | 2 provider: process() function uses the +// | | | bufferProvider indicated by the +// | | | EFFECT_CMD_SET_CONFIG command to request input. +// | | | buffers. +// | | | 3 both: both input modes are supported +// +---------------------------+-----------+----------------------------------- +// | Sample output mode | 14..15 | 1 direct: process() function or EFFECT_CMD_SET_CONFIG +// | | | command must specify a buffer descriptor +// | | | 2 provider: process() function uses the +// | | | bufferProvider indicated by the +// | | | EFFECT_CMD_SET_CONFIG command to request output +// | | | buffers. +// | | | 3 both: both output modes are supported +// +---------------------------+-----------+----------------------------------- +// | Hardware acceleration | 16..17 | 0 No hardware acceleration +// | | | 1 non tunneled hw acceleration: the process() function +// | | | reads the samples, send them to HW accelerated +// | | | effect processor, reads back the processed samples +// | | | and returns them to the output buffer. +// | | | 2 tunneled hw acceleration: the process() function is +// | | | transparent. The effect interface is only used to +// | | | control the effect engine. This mode is relevant for +// | | | global effects actually applied by the audio +// | | | hardware on the output stream. +// +---------------------------+-----------+----------------------------------- +// | Audio Mode indication | 18..19 | 0 none +// | | | 1 requires audio mode updates +// | | | 2..3 reserved +// +---------------------------+-----------+----------------------------------- +// | Audio source indication | 20..21 | 0 none +// | | | 1 requires audio source updates +// | | | 2..3 reserved +// +---------------------------+-----------+----------------------------------- + +// Insert mode +#define EFFECT_FLAG_TYPE_SHIFT 0 +#define EFFECT_FLAG_TYPE_SIZE 3 +#define EFFECT_FLAG_TYPE_MASK (((1 << EFFECT_FLAG_TYPE_SIZE) -1) \ + << EFFECT_FLAG_TYPE_SHIFT) +#define EFFECT_FLAG_TYPE_INSERT (0 << EFFECT_FLAG_TYPE_SHIFT) +#define EFFECT_FLAG_TYPE_AUXILIARY (1 << EFFECT_FLAG_TYPE_SHIFT) +#define EFFECT_FLAG_TYPE_REPLACE (2 << EFFECT_FLAG_TYPE_SHIFT) +#define EFFECT_FLAG_TYPE_PRE_PROC (3 << EFFECT_FLAG_TYPE_SHIFT) +#define EFFECT_FLAG_TYPE_POST_PROC (4 << EFFECT_FLAG_TYPE_SHIFT) + +// Insert preference +#define EFFECT_FLAG_INSERT_SHIFT (EFFECT_FLAG_TYPE_SHIFT + EFFECT_FLAG_TYPE_SIZE) +#define EFFECT_FLAG_INSERT_SIZE 3 +#define EFFECT_FLAG_INSERT_MASK (((1 << EFFECT_FLAG_INSERT_SIZE) -1) \ + << EFFECT_FLAG_INSERT_SHIFT) +#define EFFECT_FLAG_INSERT_ANY (0 << EFFECT_FLAG_INSERT_SHIFT) +#define EFFECT_FLAG_INSERT_FIRST (1 << EFFECT_FLAG_INSERT_SHIFT) +#define EFFECT_FLAG_INSERT_LAST (2 << EFFECT_FLAG_INSERT_SHIFT) +#define EFFECT_FLAG_INSERT_EXCLUSIVE (3 << EFFECT_FLAG_INSERT_SHIFT) + + +// Volume control +#define EFFECT_FLAG_VOLUME_SHIFT (EFFECT_FLAG_INSERT_SHIFT + EFFECT_FLAG_INSERT_SIZE) +#define EFFECT_FLAG_VOLUME_SIZE 3 +#define EFFECT_FLAG_VOLUME_MASK (((1 << EFFECT_FLAG_VOLUME_SIZE) -1) \ + << EFFECT_FLAG_VOLUME_SHIFT) +#define EFFECT_FLAG_VOLUME_CTRL (1 << EFFECT_FLAG_VOLUME_SHIFT) +#define EFFECT_FLAG_VOLUME_IND (2 << EFFECT_FLAG_VOLUME_SHIFT) +#define EFFECT_FLAG_VOLUME_NONE (0 << EFFECT_FLAG_VOLUME_SHIFT) + +// Device indication +#define EFFECT_FLAG_DEVICE_SHIFT (EFFECT_FLAG_VOLUME_SHIFT + EFFECT_FLAG_VOLUME_SIZE) +#define EFFECT_FLAG_DEVICE_SIZE 3 +#define EFFECT_FLAG_DEVICE_MASK (((1 << EFFECT_FLAG_DEVICE_SIZE) -1) \ + << EFFECT_FLAG_DEVICE_SHIFT) +#define EFFECT_FLAG_DEVICE_IND (1 << EFFECT_FLAG_DEVICE_SHIFT) +#define EFFECT_FLAG_DEVICE_NONE (0 << EFFECT_FLAG_DEVICE_SHIFT) + +// Sample input modes +#define EFFECT_FLAG_INPUT_SHIFT (EFFECT_FLAG_DEVICE_SHIFT + EFFECT_FLAG_DEVICE_SIZE) +#define EFFECT_FLAG_INPUT_SIZE 2 +#define EFFECT_FLAG_INPUT_MASK (((1 << EFFECT_FLAG_INPUT_SIZE) -1) \ + << EFFECT_FLAG_INPUT_SHIFT) +#define EFFECT_FLAG_INPUT_DIRECT (1 << EFFECT_FLAG_INPUT_SHIFT) +#define EFFECT_FLAG_INPUT_PROVIDER (2 << EFFECT_FLAG_INPUT_SHIFT) +#define EFFECT_FLAG_INPUT_BOTH (3 << EFFECT_FLAG_INPUT_SHIFT) + +// Sample output modes +#define EFFECT_FLAG_OUTPUT_SHIFT (EFFECT_FLAG_INPUT_SHIFT + EFFECT_FLAG_INPUT_SIZE) +#define EFFECT_FLAG_OUTPUT_SIZE 2 +#define EFFECT_FLAG_OUTPUT_MASK (((1 << EFFECT_FLAG_OUTPUT_SIZE) -1) \ + << EFFECT_FLAG_OUTPUT_SHIFT) +#define EFFECT_FLAG_OUTPUT_DIRECT (1 << EFFECT_FLAG_OUTPUT_SHIFT) +#define EFFECT_FLAG_OUTPUT_PROVIDER (2 << EFFECT_FLAG_OUTPUT_SHIFT) +#define EFFECT_FLAG_OUTPUT_BOTH (3 << EFFECT_FLAG_OUTPUT_SHIFT) + +// Hardware acceleration mode +#define EFFECT_FLAG_HW_ACC_SHIFT (EFFECT_FLAG_OUTPUT_SHIFT + EFFECT_FLAG_OUTPUT_SIZE) +#define EFFECT_FLAG_HW_ACC_SIZE 2 +#define EFFECT_FLAG_HW_ACC_MASK (((1 << EFFECT_FLAG_HW_ACC_SIZE) -1) \ + << EFFECT_FLAG_HW_ACC_SHIFT) +#define EFFECT_FLAG_HW_ACC_SIMPLE (1 << EFFECT_FLAG_HW_ACC_SHIFT) +#define EFFECT_FLAG_HW_ACC_TUNNEL (2 << EFFECT_FLAG_HW_ACC_SHIFT) + +// Audio mode indication +#define EFFECT_FLAG_AUDIO_MODE_SHIFT (EFFECT_FLAG_HW_ACC_SHIFT + EFFECT_FLAG_HW_ACC_SIZE) +#define EFFECT_FLAG_AUDIO_MODE_SIZE 2 +#define EFFECT_FLAG_AUDIO_MODE_MASK (((1 << EFFECT_FLAG_AUDIO_MODE_SIZE) -1) \ + << EFFECT_FLAG_AUDIO_MODE_SHIFT) +#define EFFECT_FLAG_AUDIO_MODE_IND (1 << EFFECT_FLAG_AUDIO_MODE_SHIFT) +#define EFFECT_FLAG_AUDIO_MODE_NONE (0 << EFFECT_FLAG_AUDIO_MODE_SHIFT) + +// Audio source indication +#define EFFECT_FLAG_AUDIO_SOURCE_SHIFT (EFFECT_FLAG_AUDIO_MODE_SHIFT + EFFECT_FLAG_AUDIO_MODE_SIZE) +#define EFFECT_FLAG_AUDIO_SOURCE_SIZE 2 +#define EFFECT_FLAG_AUDIO_SOURCE_MASK (((1 << EFFECT_FLAG_AUDIO_SOURCE_SIZE) -1) \ + << EFFECT_FLAG_AUDIO_SOURCE_SHIFT) +#define EFFECT_FLAG_AUDIO_SOURCE_IND (1 << EFFECT_FLAG_AUDIO_SOURCE_SHIFT) +#define EFFECT_FLAG_AUDIO_SOURCE_NONE (0 << EFFECT_FLAG_AUDIO_SOURCE_SHIFT) + +#define EFFECT_MAKE_API_VERSION(M, m) (((M)<<16) | ((m) & 0xFFFF)) +#define EFFECT_API_VERSION_MAJOR(v) ((v)>>16) +#define EFFECT_API_VERSION_MINOR(v) ((m) & 0xFFFF) + + + +///////////////////////////////////////////////// +// Effect control interface +///////////////////////////////////////////////// + +// Effect control interface version 2.0 +#define EFFECT_CONTROL_API_VERSION EFFECT_MAKE_API_VERSION(2,0) + +// Effect control interface structure: effect_interface_s +// The effect control interface is exposed by each effect engine implementation. It consists of +// a set of functions controlling the configuration, activation and process of the engine. +// The functions are grouped in a structure of type effect_interface_s. +// +// Effect control interface handle: effect_handle_t +// The effect_handle_t serves two purposes regarding the implementation of the effect engine: +// - 1 it is the address of a pointer to an effect_interface_s structure where the functions +// of the effect control API for a particular effect are located. +// - 2 it is the address of the context of a particular effect instance. +// A typical implementation in the effect library would define a structure as follows: +// struct effect_module_s { +// const struct effect_interface_s *itfe; +// effect_config_t config; +// effect_context_t context; +// } +// The implementation of EffectCreate() function would then allocate a structure of this +// type and return its address as effect_handle_t +typedef struct effect_interface_s **effect_handle_t; + + +// Forward definition of type audio_buffer_t +typedef struct audio_buffer_s audio_buffer_t; + + + + + + +// Effect control interface definition +struct effect_interface_s { + //////////////////////////////////////////////////////////////////////////////// + // + // Function: process + // + // Description: Effect process function. Takes input samples as specified + // (count and location) in input buffer descriptor and output processed + // samples as specified in output buffer descriptor. If the buffer descriptor + // is not specified the function must use either the buffer or the + // buffer provider function installed by the EFFECT_CMD_SET_CONFIG command. + // The effect framework will call the process() function after the EFFECT_CMD_ENABLE + // command is received and until the EFFECT_CMD_DISABLE is received. When the engine + // receives the EFFECT_CMD_DISABLE command it should turn off the effect gracefully + // and when done indicate that it is OK to stop calling the process() function by + // returning the -ENODATA status. + // + // NOTE: the process() function implementation should be "real-time safe" that is + // it should not perform blocking calls: malloc/free, sleep, read/write/open/close, + // pthread_cond_wait/pthread_mutex_lock... + // + // Input: + // self: handle to the effect interface this function + // is called on. + // inBuffer: buffer descriptor indicating where to read samples to process. + // If NULL, use the configuration passed by EFFECT_CMD_SET_CONFIG command. + // + // outBuffer: buffer descriptor indicating where to write processed samples. + // If NULL, use the configuration passed by EFFECT_CMD_SET_CONFIG command. + // + // Output: + // returned value: 0 successful operation + // -ENODATA the engine has finished the disable phase and the framework + // can stop calling process() + // -EINVAL invalid interface handle or + // invalid input/output buffer description + //////////////////////////////////////////////////////////////////////////////// + int32_t (*process)(effect_handle_t self, + audio_buffer_t *inBuffer, + audio_buffer_t *outBuffer); + //////////////////////////////////////////////////////////////////////////////// + // + // Function: command + // + // Description: Send a command and receive a response to/from effect engine. + // + // Input: + // self: handle to the effect interface this function + // is called on. + // cmdCode: command code: the command can be a standardized command defined in + // effect_command_e (see below) or a proprietary command. + // cmdSize: size of command in bytes + // pCmdData: pointer to command data + // pReplyData: pointer to reply data + // + // Input/Output: + // replySize: maximum size of reply data as input + // actual size of reply data as output + // + // Output: + // returned value: 0 successful operation + // -EINVAL invalid interface handle or + // invalid command/reply size or format according to command code + // The return code should be restricted to indicate problems related to the this + // API specification. Status related to the execution of a particular command should be + // indicated as part of the reply field. + // + // *pReplyData updated with command response + // + //////////////////////////////////////////////////////////////////////////////// + int32_t (*command)(effect_handle_t self, + uint32_t cmdCode, + uint32_t cmdSize, + void *pCmdData, + uint32_t *replySize, + void *pReplyData); + //////////////////////////////////////////////////////////////////////////////// + // + // Function: get_descriptor + // + // Description: Returns the effect descriptor + // + // Input: + // self: handle to the effect interface this function + // is called on. + // + // Input/Output: + // pDescriptor: address where to return the effect descriptor. + // + // Output: + // returned value: 0 successful operation. + // -EINVAL invalid interface handle or invalid pDescriptor + // *pDescriptor: updated with the effect descriptor. + // + //////////////////////////////////////////////////////////////////////////////// + int32_t (*get_descriptor)(effect_handle_t self, + effect_descriptor_t *pDescriptor); + //////////////////////////////////////////////////////////////////////////////// + // + // Function: process_reverse + // + // Description: Process reverse stream function. This function is used to pass + // a reference stream to the effect engine. If the engine does not need a reference + // stream, this function pointer can be set to NULL. + // This function would typically implemented by an Echo Canceler. + // + // Input: + // self: handle to the effect interface this function + // is called on. + // inBuffer: buffer descriptor indicating where to read samples to process. + // If NULL, use the configuration passed by EFFECT_CMD_SET_CONFIG_REVERSE command. + // + // outBuffer: buffer descriptor indicating where to write processed samples. + // If NULL, use the configuration passed by EFFECT_CMD_SET_CONFIG_REVERSE command. + // If the buffer and buffer provider in the configuration received by + // EFFECT_CMD_SET_CONFIG_REVERSE are also NULL, do not return modified reverse + // stream data + // + // Output: + // returned value: 0 successful operation + // -ENODATA the engine has finished the disable phase and the framework + // can stop calling process_reverse() + // -EINVAL invalid interface handle or + // invalid input/output buffer description + //////////////////////////////////////////////////////////////////////////////// + int32_t (*process_reverse)(effect_handle_t self, + audio_buffer_t *inBuffer, + audio_buffer_t *outBuffer); +}; + + +// +//--- Standardized command codes for command() function +// +enum effect_command_e { + EFFECT_CMD_INIT, // initialize effect engine + EFFECT_CMD_SET_CONFIG, // configure effect engine (see effect_config_t) + EFFECT_CMD_RESET, // reset effect engine + EFFECT_CMD_ENABLE, // enable effect process + EFFECT_CMD_DISABLE, // disable effect process + EFFECT_CMD_SET_PARAM, // set parameter immediately (see effect_param_t) + EFFECT_CMD_SET_PARAM_DEFERRED, // set parameter deferred + EFFECT_CMD_SET_PARAM_COMMIT, // commit previous set parameter deferred + EFFECT_CMD_GET_PARAM, // get parameter + EFFECT_CMD_SET_DEVICE, // set audio device (see audio.h, audio_devices_t) + EFFECT_CMD_SET_VOLUME, // set volume + EFFECT_CMD_SET_AUDIO_MODE, // set the audio mode (normal, ring, ...) + EFFECT_CMD_SET_CONFIG_REVERSE, // configure effect engine reverse stream(see effect_config_t) + EFFECT_CMD_SET_INPUT_DEVICE, // set capture device (see audio.h, audio_devices_t) + EFFECT_CMD_GET_CONFIG, // read effect engine configuration + EFFECT_CMD_GET_CONFIG_REVERSE, // read configure effect engine reverse stream configuration + EFFECT_CMD_GET_FEATURE_SUPPORTED_CONFIGS,// get all supported configurations for a feature. + EFFECT_CMD_GET_FEATURE_CONFIG, // get current feature configuration + EFFECT_CMD_SET_FEATURE_CONFIG, // set current feature configuration + EFFECT_CMD_SET_AUDIO_SOURCE, // set the audio source (see audio.h, audio_source_t) + EFFECT_CMD_FIRST_PROPRIETARY = 0x10000 // first proprietary command code +}; + +//================================================================================================== +// command: EFFECT_CMD_INIT +//-------------------------------------------------------------------------------------------------- +// description: +// Initialize effect engine: All configurations return to default +//-------------------------------------------------------------------------------------------------- +// command format: +// size: 0 +// data: N/A +//-------------------------------------------------------------------------------------------------- +// reply format: +// size: sizeof(int) +// data: status +//================================================================================================== +// command: EFFECT_CMD_SET_CONFIG +//-------------------------------------------------------------------------------------------------- +// description: +// Apply new audio parameters configurations for input and output buffers +//-------------------------------------------------------------------------------------------------- +// command format: +// size: sizeof(effect_config_t) +// data: effect_config_t +//-------------------------------------------------------------------------------------------------- +// reply format: +// size: sizeof(int) +// data: status +//================================================================================================== +// command: EFFECT_CMD_RESET +//-------------------------------------------------------------------------------------------------- +// description: +// Reset the effect engine. Keep configuration but resets state and buffer content +//-------------------------------------------------------------------------------------------------- +// command format: +// size: 0 +// data: N/A +//-------------------------------------------------------------------------------------------------- +// reply format: +// size: 0 +// data: N/A +//================================================================================================== +// command: EFFECT_CMD_ENABLE +//-------------------------------------------------------------------------------------------------- +// description: +// Enable the process. Called by the framework before the first call to process() +//-------------------------------------------------------------------------------------------------- +// command format: +// size: 0 +// data: N/A +//-------------------------------------------------------------------------------------------------- +// reply format: +// size: sizeof(int) +// data: status +//================================================================================================== +// command: EFFECT_CMD_DISABLE +//-------------------------------------------------------------------------------------------------- +// description: +// Disable the process. Called by the framework after the last call to process() +//-------------------------------------------------------------------------------------------------- +// command format: +// size: 0 +// data: N/A +//-------------------------------------------------------------------------------------------------- +// reply format: +// size: sizeof(int) +// data: status +//================================================================================================== +// command: EFFECT_CMD_SET_PARAM +//-------------------------------------------------------------------------------------------------- +// description: +// Set a parameter and apply it immediately +//-------------------------------------------------------------------------------------------------- +// command format: +// size: sizeof(effect_param_t) + size of param and value +// data: effect_param_t + param + value. See effect_param_t definition below for value offset +//-------------------------------------------------------------------------------------------------- +// reply format: +// size: sizeof(int) +// data: status +//================================================================================================== +// command: EFFECT_CMD_SET_PARAM_DEFERRED +//-------------------------------------------------------------------------------------------------- +// description: +// Set a parameter but apply it only when receiving EFFECT_CMD_SET_PARAM_COMMIT command +//-------------------------------------------------------------------------------------------------- +// command format: +// size: sizeof(effect_param_t) + size of param and value +// data: effect_param_t + param + value. See effect_param_t definition below for value offset +//-------------------------------------------------------------------------------------------------- +// reply format: +// size: 0 +// data: N/A +//================================================================================================== +// command: EFFECT_CMD_SET_PARAM_COMMIT +//-------------------------------------------------------------------------------------------------- +// description: +// Apply all previously received EFFECT_CMD_SET_PARAM_DEFERRED commands +//-------------------------------------------------------------------------------------------------- +// command format: +// size: 0 +// data: N/A +//-------------------------------------------------------------------------------------------------- +// reply format: +// size: sizeof(int) +// data: status +//================================================================================================== +// command: EFFECT_CMD_GET_PARAM +//-------------------------------------------------------------------------------------------------- +// description: +// Get a parameter value +//-------------------------------------------------------------------------------------------------- +// command format: +// size: sizeof(effect_param_t) + size of param +// data: effect_param_t + param +//-------------------------------------------------------------------------------------------------- +// reply format: +// size: sizeof(effect_param_t) + size of param and value +// data: effect_param_t + param + value. See effect_param_t definition below for value offset +//================================================================================================== +// command: EFFECT_CMD_SET_DEVICE +//-------------------------------------------------------------------------------------------------- +// description: +// Set the rendering device the audio output path is connected to. See audio.h, audio_devices_t +// for device values. +// The effect implementation must set EFFECT_FLAG_DEVICE_IND flag in its descriptor to receive this +// command when the device changes +//-------------------------------------------------------------------------------------------------- +// command format: +// size: sizeof(uint32_t) +// data: uint32_t +//-------------------------------------------------------------------------------------------------- +// reply format: +// size: 0 +// data: N/A +//================================================================================================== +// command: EFFECT_CMD_SET_VOLUME +//-------------------------------------------------------------------------------------------------- +// description: +// Set and get volume. Used by audio framework to delegate volume control to effect engine. +// The effect implementation must set EFFECT_FLAG_VOLUME_IND or EFFECT_FLAG_VOLUME_CTRL flag in +// its descriptor to receive this command before every call to process() function +// If EFFECT_FLAG_VOLUME_CTRL flag is set in the effect descriptor, the effect engine must return +// the volume that should be applied before the effect is processed. The overall volume (the volume +// actually applied by the effect engine multiplied by the returned value) should match the value +// indicated in the command. +//-------------------------------------------------------------------------------------------------- +// command format: +// size: n * sizeof(uint32_t) +// data: volume for each channel defined in effect_config_t for output buffer expressed in +// 8.24 fixed point format +//-------------------------------------------------------------------------------------------------- +// reply format: +// size: n * sizeof(uint32_t) / 0 +// data: - if EFFECT_FLAG_VOLUME_CTRL is set in effect descriptor: +// volume for each channel defined in effect_config_t for output buffer expressed in +// 8.24 fixed point format +// - if EFFECT_FLAG_VOLUME_CTRL is not set in effect descriptor: +// N/A +// It is legal to receive a null pointer as pReplyData in which case the effect framework has +// delegated volume control to another effect +//================================================================================================== +// command: EFFECT_CMD_SET_AUDIO_MODE +//-------------------------------------------------------------------------------------------------- +// description: +// Set the audio mode. The effect implementation must set EFFECT_FLAG_AUDIO_MODE_IND flag in its +// descriptor to receive this command when the audio mode changes. +//-------------------------------------------------------------------------------------------------- +// command format: +// size: sizeof(uint32_t) +// data: audio_mode_t +//-------------------------------------------------------------------------------------------------- +// reply format: +// size: 0 +// data: N/A +//================================================================================================== +// command: EFFECT_CMD_SET_CONFIG_REVERSE +//-------------------------------------------------------------------------------------------------- +// description: +// Apply new audio parameters configurations for input and output buffers of reverse stream. +// An example of reverse stream is the echo reference supplied to an Acoustic Echo Canceler. +//-------------------------------------------------------------------------------------------------- +// command format: +// size: sizeof(effect_config_t) +// data: effect_config_t +//-------------------------------------------------------------------------------------------------- +// reply format: +// size: sizeof(int) +// data: status +//================================================================================================== +// command: EFFECT_CMD_SET_INPUT_DEVICE +//-------------------------------------------------------------------------------------------------- +// description: +// Set the capture device the audio input path is connected to. See audio.h, audio_devices_t +// for device values. +// The effect implementation must set EFFECT_FLAG_DEVICE_IND flag in its descriptor to receive this +// command when the device changes +//-------------------------------------------------------------------------------------------------- +// command format: +// size: sizeof(uint32_t) +// data: uint32_t +//-------------------------------------------------------------------------------------------------- +// reply format: +// size: 0 +// data: N/A +//================================================================================================== +// command: EFFECT_CMD_GET_CONFIG +//-------------------------------------------------------------------------------------------------- +// description: +// Read audio parameters configurations for input and output buffers +//-------------------------------------------------------------------------------------------------- +// command format: +// size: 0 +// data: N/A +//-------------------------------------------------------------------------------------------------- +// reply format: +// size: sizeof(effect_config_t) +// data: effect_config_t +//================================================================================================== +// command: EFFECT_CMD_GET_CONFIG_REVERSE +//-------------------------------------------------------------------------------------------------- +// description: +// Read audio parameters configurations for input and output buffers of reverse stream +//-------------------------------------------------------------------------------------------------- +// command format: +// size: 0 +// data: N/A +//-------------------------------------------------------------------------------------------------- +// reply format: +// size: sizeof(effect_config_t) +// data: effect_config_t +//================================================================================================== +// command: EFFECT_CMD_GET_FEATURE_SUPPORTED_CONFIGS +//-------------------------------------------------------------------------------------------------- +// description: +// Queries for supported configurations for a particular feature (e.g. get the supported +// combinations of main and auxiliary channels for a noise suppressor). +// The command parameter is the feature identifier (See effect_feature_e for a list of defined +// features) followed by the maximum number of configuration descriptor to return. +// The reply is composed of: +// - status (uint32_t): +// - 0 if feature is supported +// - -ENOSYS if the feature is not supported, +// - -ENOMEM if the feature is supported but the total number of supported configurations +// exceeds the maximum number indicated by the caller. +// - total number of supported configurations (uint32_t) +// - an array of configuration descriptors. +// The actual number of descriptors returned must not exceed the maximum number indicated by +// the caller. +//-------------------------------------------------------------------------------------------------- +// command format: +// size: 2 x sizeof(uint32_t) +// data: effect_feature_e + maximum number of configurations to return +//-------------------------------------------------------------------------------------------------- +// reply format: +// size: 2 x sizeof(uint32_t) + n x sizeof () +// data: status + total number of configurations supported + array of n config descriptors +//================================================================================================== +// command: EFFECT_CMD_GET_FEATURE_CONFIG +//-------------------------------------------------------------------------------------------------- +// description: +// Retrieves current configuration for a given feature. +// The reply status is: +// - 0 if feature is supported +// - -ENOSYS if the feature is not supported, +//-------------------------------------------------------------------------------------------------- +// command format: +// size: sizeof(uint32_t) +// data: effect_feature_e +//-------------------------------------------------------------------------------------------------- +// reply format: +// size: sizeof(uint32_t) + sizeof () +// data: status + config descriptor +//================================================================================================== +// command: EFFECT_CMD_SET_FEATURE_CONFIG +//-------------------------------------------------------------------------------------------------- +// description: +// Sets current configuration for a given feature. +// The reply status is: +// - 0 if feature is supported +// - -ENOSYS if the feature is not supported, +// - -EINVAL if the configuration is invalid +//-------------------------------------------------------------------------------------------------- +// command format: +// size: sizeof(uint32_t) + sizeof () +// data: effect_feature_e + config descriptor +//-------------------------------------------------------------------------------------------------- +// reply format: +// size: sizeof(uint32_t) +// data: status +//================================================================================================== +// command: EFFECT_CMD_SET_AUDIO_SOURCE +//-------------------------------------------------------------------------------------------------- +// description: +// Set the audio source the capture path is configured for (Camcorder, voice recognition...). +// See audio.h, audio_source_t for values. +//-------------------------------------------------------------------------------------------------- +// command format: +// size: sizeof(uint32_t) +// data: uint32_t +//-------------------------------------------------------------------------------------------------- +// reply format: +// size: 0 +// data: N/A +//================================================================================================== +// command: EFFECT_CMD_FIRST_PROPRIETARY +//-------------------------------------------------------------------------------------------------- +// description: +// All proprietary effect commands must use command codes above this value. The size and format of +// command and response fields is free in this case +//================================================================================================== + + +// Audio buffer descriptor used by process(), bufferProvider() functions and buffer_config_t +// structure. Multi-channel audio is always interleaved. The channel order is from LSB to MSB with +// regard to the channel mask definition in audio.h, audio_channel_mask_t e.g : +// Stereo: left, right +// 5 point 1: front left, front right, front center, low frequency, back left, back right +// The buffer size is expressed in frame count, a frame being composed of samples for all +// channels at a given time. Frame size for unspecified format (AUDIO_FORMAT_OTHER) is 8 bit by +// definition +struct audio_buffer_s { + size_t frameCount; // number of frames in buffer + union { + void* raw; // raw pointer to start of buffer + int32_t* s32; // pointer to signed 32 bit data at start of buffer + int16_t* s16; // pointer to signed 16 bit data at start of buffer + uint8_t* u8; // pointer to unsigned 8 bit data at start of buffer + }; +}; + +// The buffer_provider_s structure contains functions that can be used +// by the effect engine process() function to query and release input +// or output audio buffer. +// The getBuffer() function is called to retrieve a buffer where data +// should read from or written to by process() function. +// The releaseBuffer() function MUST be called when the buffer retrieved +// with getBuffer() is not needed anymore. +// The process function should use the buffer provider mechanism to retrieve +// input or output buffer if the inBuffer or outBuffer passed as argument is NULL +// and the buffer configuration (buffer_config_t) given by the EFFECT_CMD_SET_CONFIG +// command did not specify an audio buffer. + +typedef int32_t (* buffer_function_t)(void *cookie, audio_buffer_t *buffer); + +typedef struct buffer_provider_s { + buffer_function_t getBuffer; // retrieve next buffer + buffer_function_t releaseBuffer; // release used buffer + void *cookie; // for use by client of buffer provider functions +} buffer_provider_t; + + +// The buffer_config_s structure specifies the input or output audio format +// to be used by the effect engine. It is part of the effect_config_t +// structure that defines both input and output buffer configurations and is +// passed by the EFFECT_CMD_SET_CONFIG or EFFECT_CMD_SET_CONFIG_REVERSE command. +typedef struct buffer_config_s { + audio_buffer_t buffer; // buffer for use by process() function if not passed explicitly + uint32_t samplingRate; // sampling rate + uint32_t channels; // channel mask (see audio_channel_mask_t in audio.h) + buffer_provider_t bufferProvider; // buffer provider + uint8_t format; // Audio format (see see audio_format_t in audio.h) + uint8_t accessMode; // read/write or accumulate in buffer (effect_buffer_access_e) + uint16_t mask; // indicates which of the above fields is valid +} buffer_config_t; + +// Values for "accessMode" field of buffer_config_t: +// overwrite, read only, accumulate (read/modify/write) +enum effect_buffer_access_e { + EFFECT_BUFFER_ACCESS_WRITE, + EFFECT_BUFFER_ACCESS_READ, + EFFECT_BUFFER_ACCESS_ACCUMULATE + +}; + +// feature identifiers for EFFECT_CMD_GET_FEATURE_SUPPORTED_CONFIGS command +enum effect_feature_e { + EFFECT_FEATURE_AUX_CHANNELS, // supports auxiliary channels (e.g. dual mic noise suppressor) + EFFECT_FEATURE_CNT +}; + +// EFFECT_FEATURE_AUX_CHANNELS feature configuration descriptor. Describe a combination +// of main and auxiliary channels supported +typedef struct channel_config_s { + audio_channel_mask_t main_channels; // channel mask for main channels + audio_channel_mask_t aux_channels; // channel mask for auxiliary channels +} channel_config_t; + + +// Values for bit field "mask" in buffer_config_t. If a bit is set, the corresponding field +// in buffer_config_t must be taken into account when executing the EFFECT_CMD_SET_CONFIG command +#define EFFECT_CONFIG_BUFFER 0x0001 // buffer field must be taken into account +#define EFFECT_CONFIG_SMP_RATE 0x0002 // samplingRate field must be taken into account +#define EFFECT_CONFIG_CHANNELS 0x0004 // channels field must be taken into account +#define EFFECT_CONFIG_FORMAT 0x0008 // format field must be taken into account +#define EFFECT_CONFIG_ACC_MODE 0x0010 // accessMode field must be taken into account +#define EFFECT_CONFIG_PROVIDER 0x0020 // bufferProvider field must be taken into account +#define EFFECT_CONFIG_ALL (EFFECT_CONFIG_BUFFER | EFFECT_CONFIG_SMP_RATE | \ + EFFECT_CONFIG_CHANNELS | EFFECT_CONFIG_FORMAT | \ + EFFECT_CONFIG_ACC_MODE | EFFECT_CONFIG_PROVIDER) + + +// effect_config_s structure describes the format of the pCmdData argument of EFFECT_CMD_SET_CONFIG +// command to configure audio parameters and buffers for effect engine input and output. +typedef struct effect_config_s { + buffer_config_t inputCfg; + buffer_config_t outputCfg; +} effect_config_t; + + +// effect_param_s structure describes the format of the pCmdData argument of EFFECT_CMD_SET_PARAM +// command and pCmdData and pReplyData of EFFECT_CMD_GET_PARAM command. +// psize and vsize represent the actual size of parameter and value. +// +// NOTE: the start of value field inside the data field is always on a 32 bit boundary: +// +// +-----------+ +// | status | sizeof(int) +// +-----------+ +// | psize | sizeof(int) +// +-----------+ +// | vsize | sizeof(int) +// +-----------+ +// | | | | +// ~ parameter ~ > psize | +// | | | > ((psize - 1)/sizeof(int) + 1) * sizeof(int) +// +-----------+ | +// | padding | | +// +-----------+ +// | | | +// ~ value ~ > vsize +// | | | +// +-----------+ + +typedef struct effect_param_s { + int32_t status; // Transaction status (unused for command, used for reply) + uint32_t psize; // Parameter size + uint32_t vsize; // Value size + char data[]; // Start of Parameter + Value data +} effect_param_t; + + + +///////////////////////////////////////////////// +// Effect library interface +///////////////////////////////////////////////// + +// Effect library interface version 2.0 +#define EFFECT_LIBRARY_API_VERSION EFFECT_MAKE_API_VERSION(2,0) + +#define AUDIO_EFFECT_LIBRARY_TAG ((('A') << 24) | (('E') << 16) | (('L') << 8) | ('T')) + +// Every effect library must have a data structure named AUDIO_EFFECT_LIBRARY_INFO_SYM +// and the fields of this data structure must begin with audio_effect_library_t + +typedef struct audio_effect_library_s { + // tag must be initialized to AUDIO_EFFECT_LIBRARY_TAG + uint32_t tag; + // Version of the effect library API : 0xMMMMmmmm MMMM: Major, mmmm: minor + uint32_t version; + // Name of this library + const char *name; + // Author/owner/implementor of the library + const char *implementor; + + //////////////////////////////////////////////////////////////////////////////// + // + // Function: query_num_effects + // + // Description: Returns the number of different effects exposed by the + // library. Each effect must have a unique effect uuid (see + // effect_descriptor_t). This function together with EffectQueryEffect() + // is used to enumerate all effects present in the library. + // + // Input/Output: + // pNumEffects: address where the number of effects should be returned. + // + // Output: + // returned value: 0 successful operation. + // -ENODEV library failed to initialize + // -EINVAL invalid pNumEffects + // *pNumEffects: updated with number of effects in library + // + //////////////////////////////////////////////////////////////////////////////// + int32_t (*query_num_effects)(uint32_t *pNumEffects); + + //////////////////////////////////////////////////////////////////////////////// + // + // Function: query_effect + // + // Description: Returns the descriptor of the effect engine which index is + // given as argument. + // See effect_descriptor_t for details on effect descriptors. + // This function together with EffectQueryNumberEffects() is used to enumerate all + // effects present in the library. The enumeration sequence is: + // EffectQueryNumberEffects(&num_effects); + // for (i = 0; i < num_effects; i++) + // EffectQueryEffect(i,...); + // + // Input/Output: + // index: index of the effect + // pDescriptor: address where to return the effect descriptor. + // + // Output: + // returned value: 0 successful operation. + // -ENODEV library failed to initialize + // -EINVAL invalid pDescriptor or index + // -ENOSYS effect list has changed since last execution of + // EffectQueryNumberEffects() + // -ENOENT no more effect available + // *pDescriptor: updated with the effect descriptor. + // + //////////////////////////////////////////////////////////////////////////////// + int32_t (*query_effect)(uint32_t index, + effect_descriptor_t *pDescriptor); + + //////////////////////////////////////////////////////////////////////////////// + // + // Function: create_effect + // + // Description: Creates an effect engine of the specified implementation uuid and + // returns an effect control interface on this engine. The function will allocate the + // resources for an instance of the requested effect engine and return + // a handle on the effect control interface. + // + // Input: + // uuid: pointer to the effect uuid. + // sessionId: audio session to which this effect instance will be attached. All effects + // created with the same session ID are connected in series and process the same signal + // stream. Knowing that two effects are part of the same effect chain can help the + // library implement some kind of optimizations. + // ioId: identifies the output or input stream this effect is directed to at audio HAL. + // For future use especially with tunneled HW accelerated effects + // + // Input/Output: + // pHandle: address where to return the effect interface handle. + // + // Output: + // returned value: 0 successful operation. + // -ENODEV library failed to initialize + // -EINVAL invalid pEffectUuid or pHandle + // -ENOENT no effect with this uuid found + // *pHandle: updated with the effect interface handle. + // + //////////////////////////////////////////////////////////////////////////////// + int32_t (*create_effect)(const effect_uuid_t *uuid, + int32_t sessionId, + int32_t ioId, + effect_handle_t *pHandle); + + //////////////////////////////////////////////////////////////////////////////// + // + // Function: release_effect + // + // Description: Releases the effect engine whose handle is given as argument. + // All resources allocated to this particular instance of the effect are + // released. + // + // Input: + // handle: handle on the effect interface to be released. + // + // Output: + // returned value: 0 successful operation. + // -ENODEV library failed to initialize + // -EINVAL invalid interface handle + // + //////////////////////////////////////////////////////////////////////////////// + int32_t (*release_effect)(effect_handle_t handle); + + //////////////////////////////////////////////////////////////////////////////// + // + // Function: get_descriptor + // + // Description: Returns the descriptor of the effect engine which implementation UUID is + // given as argument. + // + // Input/Output: + // uuid: pointer to the effect uuid. + // pDescriptor: address where to return the effect descriptor. + // + // Output: + // returned value: 0 successful operation. + // -ENODEV library failed to initialize + // -EINVAL invalid pDescriptor or uuid + // *pDescriptor: updated with the effect descriptor. + // + //////////////////////////////////////////////////////////////////////////////// + int32_t (*get_descriptor)(const effect_uuid_t *uuid, + effect_descriptor_t *pDescriptor); +} audio_effect_library_t; + +// Name of the hal_module_info +#define AUDIO_EFFECT_LIBRARY_INFO_SYM AELI + +// Name of the hal_module_info as a string +#define AUDIO_EFFECT_LIBRARY_INFO_SYM_AS_STR "AELI" + +__END_DECLS + +#endif // ANDROID_AUDIO_EFFECT_H diff -Nru android-tools-4.2.2+git20130218/libhardware/include/hardware/audio.h android-tools-4.2.2+git20130529/libhardware/include/hardware/audio.h --- android-tools-4.2.2+git20130218/libhardware/include/hardware/audio.h 1970-01-01 00:00:00.000000000 +0000 +++ android-tools-4.2.2+git20130529/libhardware/include/hardware/audio.h 2013-05-29 20:16:54.000000000 +0000 @@ -0,0 +1,453 @@ +/* + * Copyright (C) 2011 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 ANDROID_AUDIO_HAL_INTERFACE_H +#define ANDROID_AUDIO_HAL_INTERFACE_H + +#include +#include +#include +#include + +#include + +#include +#include +#include + +__BEGIN_DECLS + +/** + * The id of this module + */ +#define AUDIO_HARDWARE_MODULE_ID "audio" + +/** + * Name of the audio devices to open + */ +#define AUDIO_HARDWARE_INTERFACE "audio_hw_if" + + +/* Use version 0.1 to be compatible with first generation of audio hw module with version_major + * hardcoded to 1. No audio module API change. + */ +#define AUDIO_MODULE_API_VERSION_0_1 HARDWARE_MODULE_API_VERSION(0, 1) +#define AUDIO_MODULE_API_VERSION_CURRENT AUDIO_MODULE_API_VERSION_0_1 + +/* First generation of audio devices had version hardcoded to 0. all devices with versions < 1.0 + * will be considered of first generation API. + */ +#define AUDIO_DEVICE_API_VERSION_0_0 HARDWARE_DEVICE_API_VERSION(0, 0) +#define AUDIO_DEVICE_API_VERSION_1_0 HARDWARE_DEVICE_API_VERSION(1, 0) +#define AUDIO_DEVICE_API_VERSION_2_0 HARDWARE_DEVICE_API_VERSION(2, 0) +#define AUDIO_DEVICE_API_VERSION_CURRENT AUDIO_DEVICE_API_VERSION_2_0 + +/** + * List of known audio HAL modules. This is the base name of the audio HAL + * library composed of the "audio." prefix, one of the base names below and + * a suffix specific to the device. + * e.g: audio.primary.goldfish.so or audio.a2dp.default.so + */ + +#define AUDIO_HARDWARE_MODULE_ID_PRIMARY "primary" +#define AUDIO_HARDWARE_MODULE_ID_A2DP "a2dp" +#define AUDIO_HARDWARE_MODULE_ID_USB "usb" +#define AUDIO_HARDWARE_MODULE_ID_REMOTE_SUBMIX "r_submix" + +/**************************************/ + +/** + * standard audio parameters that the HAL may need to handle + */ + +/** + * audio device parameters + */ + +/* BT SCO Noise Reduction + Echo Cancellation parameters */ +#define AUDIO_PARAMETER_KEY_BT_NREC "bt_headset_nrec" +#define AUDIO_PARAMETER_VALUE_ON "on" +#define AUDIO_PARAMETER_VALUE_OFF "off" + +/* TTY mode selection */ +#define AUDIO_PARAMETER_KEY_TTY_MODE "tty_mode" +#define AUDIO_PARAMETER_VALUE_TTY_OFF "tty_off" +#define AUDIO_PARAMETER_VALUE_TTY_VCO "tty_vco" +#define AUDIO_PARAMETER_VALUE_TTY_HCO "tty_hco" +#define AUDIO_PARAMETER_VALUE_TTY_FULL "tty_full" + +/* A2DP sink address set by framework */ +#define AUDIO_PARAMETER_A2DP_SINK_ADDRESS "a2dp_sink_address" + +/* Screen state */ +#define AUDIO_PARAMETER_KEY_SCREEN_STATE "screen_state" + +/** + * audio stream parameters + */ + +#define AUDIO_PARAMETER_STREAM_ROUTING "routing" // audio_devices_t +#define AUDIO_PARAMETER_STREAM_FORMAT "format" // audio_format_t +#define AUDIO_PARAMETER_STREAM_CHANNELS "channels" // audio_channel_mask_t +#define AUDIO_PARAMETER_STREAM_FRAME_COUNT "frame_count" // size_t +#define AUDIO_PARAMETER_STREAM_INPUT_SOURCE "input_source" // audio_source_t +#define AUDIO_PARAMETER_STREAM_SAMPLING_RATE "sampling_rate" // uint32_t + +/* Query supported formats. The response is a '|' separated list of strings from + * audio_format_t enum e.g: "sup_formats=AUDIO_FORMAT_PCM_16_BIT" */ +#define AUDIO_PARAMETER_STREAM_SUP_FORMATS "sup_formats" +/* Query supported channel masks. The response is a '|' separated list of strings from + * audio_channel_mask_t enum e.g: "sup_channels=AUDIO_CHANNEL_OUT_STEREO|AUDIO_CHANNEL_OUT_MONO" */ +#define AUDIO_PARAMETER_STREAM_SUP_CHANNELS "sup_channels" +/* Query supported sampling rates. The response is a '|' separated list of integer values e.g: + * "sup_sampling_rates=44100|48000" */ +#define AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES "sup_sampling_rates" + + +/**************************************/ + +/* common audio stream configuration parameters */ +struct audio_config { + uint32_t sample_rate; + audio_channel_mask_t channel_mask; + audio_format_t format; +}; + +typedef struct audio_config audio_config_t; + +/* common audio stream parameters and operations */ +struct audio_stream { + + /** + * Return the sampling rate in Hz - eg. 44100. + */ + uint32_t (*get_sample_rate)(const struct audio_stream *stream); + + /* currently unused - use set_parameters with key + * AUDIO_PARAMETER_STREAM_SAMPLING_RATE + */ + int (*set_sample_rate)(struct audio_stream *stream, uint32_t rate); + + /** + * Return size of input/output buffer in bytes for this stream - eg. 4800. + * It should be a multiple of the frame size. See also get_input_buffer_size. + */ + size_t (*get_buffer_size)(const struct audio_stream *stream); + + /** + * Return the channel mask - + * e.g. AUDIO_CHANNEL_OUT_STEREO or AUDIO_CHANNEL_IN_STEREO + */ + audio_channel_mask_t (*get_channels)(const struct audio_stream *stream); + + /** + * Return the audio format - e.g. AUDIO_FORMAT_PCM_16_BIT + */ + audio_format_t (*get_format)(const struct audio_stream *stream); + + /* currently unused - use set_parameters with key + * AUDIO_PARAMETER_STREAM_FORMAT + */ + int (*set_format)(struct audio_stream *stream, audio_format_t format); + + /** + * Put the audio hardware input/output into standby mode. + * Driver should exit from standby mode at the next I/O operation. + * Returns 0 on success and <0 on failure. + */ + int (*standby)(struct audio_stream *stream); + + /** dump the state of the audio input/output device */ + int (*dump)(const struct audio_stream *stream, int fd); + + /** Return the set of device(s) which this stream is connected to */ + audio_devices_t (*get_device)(const struct audio_stream *stream); + + /** + * Currently unused - set_device() corresponds to set_parameters() with key + * AUDIO_PARAMETER_STREAM_ROUTING for both input and output. + * AUDIO_PARAMETER_STREAM_INPUT_SOURCE is an additional information used by + * input streams only. + */ + int (*set_device)(struct audio_stream *stream, audio_devices_t device); + + /** + * set/get audio stream parameters. The function accepts a list of + * parameter key value pairs in the form: key1=value1;key2=value2;... + * + * Some keys are reserved for standard parameters (See AudioParameter class) + * + * If the implementation does not accept a parameter change while + * the output is active but the parameter is acceptable otherwise, it must + * return -ENOSYS. + * + * The audio flinger will put the stream in standby and then change the + * parameter value. + */ + int (*set_parameters)(struct audio_stream *stream, const char *kv_pairs); + + /* + * Returns a pointer to a heap allocated string. The caller is responsible + * for freeing the memory for it using free(). + */ + char * (*get_parameters)(const struct audio_stream *stream, + const char *keys); + int (*add_audio_effect)(const struct audio_stream *stream, + effect_handle_t effect); + int (*remove_audio_effect)(const struct audio_stream *stream, + effect_handle_t effect); +}; +typedef struct audio_stream audio_stream_t; + +/** + * audio_stream_out is the abstraction interface for the audio output hardware. + * + * It provides information about various properties of the audio output + * hardware driver. + */ + +struct audio_stream_out { + struct audio_stream common; + + /** + * Return the audio hardware driver estimated latency in milliseconds. + */ + uint32_t (*get_latency)(const struct audio_stream_out *stream); + + /** + * Use this method in situations where audio mixing is done in the + * hardware. This method serves as a direct interface with hardware, + * allowing you to directly set the volume as apposed to via the framework. + * This method might produce multiple PCM outputs or hardware accelerated + * codecs, such as MP3 or AAC. + */ + int (*set_volume)(struct audio_stream_out *stream, float left, float right); + + /** + * Write audio buffer to driver. Returns number of bytes written, or a + * negative status_t. If at least one frame was written successfully prior to the error, + * it is suggested that the driver return that successful (short) byte count + * and then return an error in the subsequent call. + */ + ssize_t (*write)(struct audio_stream_out *stream, const void* buffer, + size_t bytes); + + /* return the number of audio frames written by the audio dsp to DAC since + * the output has exited standby + */ + int (*get_render_position)(const struct audio_stream_out *stream, + uint32_t *dsp_frames); + + /** + * get the local time at which the next write to the audio driver will be presented. + * The units are microseconds, where the epoch is decided by the local audio HAL. + */ + int (*get_next_write_timestamp)(const struct audio_stream_out *stream, + int64_t *timestamp); + +}; +typedef struct audio_stream_out audio_stream_out_t; + +struct audio_stream_in { + struct audio_stream common; + + /** set the input gain for the audio driver. This method is for + * for future use */ + int (*set_gain)(struct audio_stream_in *stream, float gain); + + /** Read audio buffer in from audio driver. Returns number of bytes read, or a + * negative status_t. If at least one frame was read prior to the error, + * read should return that byte count and then return an error in the subsequent call. + */ + ssize_t (*read)(struct audio_stream_in *stream, void* buffer, + size_t bytes); + + /** + * Return the amount of input frames lost in the audio driver since the + * last call of this function. + * Audio driver is expected to reset the value to 0 and restart counting + * upon returning the current value by this function call. + * Such loss typically occurs when the user space process is blocked + * longer than the capacity of audio driver buffers. + * + * Unit: the number of input audio frames + */ + uint32_t (*get_input_frames_lost)(struct audio_stream_in *stream); +}; +typedef struct audio_stream_in audio_stream_in_t; + +/** + * return the frame size (number of bytes per sample). + */ +static inline size_t audio_stream_frame_size(const struct audio_stream *s) +{ + size_t chan_samp_sz; + + switch (s->get_format(s)) { + case AUDIO_FORMAT_PCM_16_BIT: + chan_samp_sz = sizeof(int16_t); + break; + case AUDIO_FORMAT_PCM_8_BIT: + default: + chan_samp_sz = sizeof(int8_t); + break; + } + + return popcount(s->get_channels(s)) * chan_samp_sz; +} + + +/**********************************************************************/ + +/** + * Every hardware module must have a data structure named HAL_MODULE_INFO_SYM + * and the fields of this data structure must begin with hw_module_t + * followed by module specific information. + */ +struct audio_module { + struct hw_module_t common; +}; + +struct audio_hw_device { + struct hw_device_t common; + + /** + * used by audio flinger to enumerate what devices are supported by + * each audio_hw_device implementation. + * + * Return value is a bitmask of 1 or more values of audio_devices_t + * + * NOTE: audio HAL implementations starting with + * AUDIO_DEVICE_API_VERSION_2_0 do not implement this function. + * All supported devices should be listed in audio_policy.conf + * file and the audio policy manager must choose the appropriate + * audio module based on information in this file. + */ + uint32_t (*get_supported_devices)(const struct audio_hw_device *dev); + + /** + * check to see if the audio hardware interface has been initialized. + * returns 0 on success, -ENODEV on failure. + */ + int (*init_check)(const struct audio_hw_device *dev); + + /** set the audio volume of a voice call. Range is between 0.0 and 1.0 */ + int (*set_voice_volume)(struct audio_hw_device *dev, float volume); + + /** + * set the audio volume for all audio activities other than voice call. + * Range between 0.0 and 1.0. If any value other than 0 is returned, + * the software mixer will emulate this capability. + */ + int (*set_master_volume)(struct audio_hw_device *dev, float volume); + + /** + * Get the current master volume value for the HAL, if the HAL supports + * master volume control. AudioFlinger will query this value from the + * primary audio HAL when the service starts and use the value for setting + * the initial master volume across all HALs. HALs which do not support + * this method may leave it set to NULL. + */ + int (*get_master_volume)(struct audio_hw_device *dev, float *volume); + + /** + * set_mode is called when the audio mode changes. AUDIO_MODE_NORMAL mode + * is for standard audio playback, AUDIO_MODE_RINGTONE when a ringtone is + * playing, and AUDIO_MODE_IN_CALL when a call is in progress. + */ + int (*set_mode)(struct audio_hw_device *dev, audio_mode_t mode); + + /* mic mute */ + int (*set_mic_mute)(struct audio_hw_device *dev, bool state); + int (*get_mic_mute)(const struct audio_hw_device *dev, bool *state); + + /* set/get global audio parameters */ + int (*set_parameters)(struct audio_hw_device *dev, const char *kv_pairs); + + /* + * Returns a pointer to a heap allocated string. The caller is responsible + * for freeing the memory for it using free(). + */ + char * (*get_parameters)(const struct audio_hw_device *dev, + const char *keys); + + /* Returns audio input buffer size according to parameters passed or + * 0 if one of the parameters is not supported. + * See also get_buffer_size which is for a particular stream. + */ + size_t (*get_input_buffer_size)(const struct audio_hw_device *dev, + const struct audio_config *config); + + /** This method creates and opens the audio hardware output stream */ + int (*open_output_stream)(struct audio_hw_device *dev, + audio_io_handle_t handle, + audio_devices_t devices, + audio_output_flags_t flags, + struct audio_config *config, + struct audio_stream_out **stream_out); + + void (*close_output_stream)(struct audio_hw_device *dev, + struct audio_stream_out* stream_out); + + /** This method creates and opens the audio hardware input stream */ + int (*open_input_stream)(struct audio_hw_device *dev, + audio_io_handle_t handle, + audio_devices_t devices, + struct audio_config *config, + struct audio_stream_in **stream_in); + + void (*close_input_stream)(struct audio_hw_device *dev, + struct audio_stream_in *stream_in); + + /** This method dumps the state of the audio hardware */ + int (*dump)(const struct audio_hw_device *dev, int fd); + + /** + * set the audio mute status for all audio activities. If any value other + * than 0 is returned, the software mixer will emulate this capability. + */ + int (*set_master_mute)(struct audio_hw_device *dev, bool mute); + + /** + * Get the current master mute status for the HAL, if the HAL supports + * master mute control. AudioFlinger will query this value from the primary + * audio HAL when the service starts and use the value for setting the + * initial master mute across all HALs. HALs which do not support this + * method may leave it set to NULL. + */ + int (*get_master_mute)(struct audio_hw_device *dev, bool *mute); +}; +typedef struct audio_hw_device audio_hw_device_t; + +/** convenience API for opening and closing a supported device */ + +static inline int audio_hw_device_open(const struct hw_module_t* module, + struct audio_hw_device** device) +{ + return module->methods->open(module, AUDIO_HARDWARE_INTERFACE, + (struct hw_device_t**)device); +} + +static inline int audio_hw_device_close(struct audio_hw_device* device) +{ + return device->common.close(&device->common); +} + + +__END_DECLS + +#endif // ANDROID_AUDIO_INTERFACE_H diff -Nru android-tools-4.2.2+git20130218/libhardware/include/hardware/audio_policy.h android-tools-4.2.2+git20130529/libhardware/include/hardware/audio_policy.h --- android-tools-4.2.2+git20130218/libhardware/include/hardware/audio_policy.h 1970-01-01 00:00:00.000000000 +0000 +++ android-tools-4.2.2+git20130529/libhardware/include/hardware/audio_policy.h 2013-05-29 20:16:54.000000000 +0000 @@ -0,0 +1,445 @@ +/* + * Copyright (C) 2011 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 ANDROID_AUDIO_POLICY_INTERFACE_H +#define ANDROID_AUDIO_POLICY_INTERFACE_H + +#include +#include +#include + +#include + +#include +#include + +__BEGIN_DECLS + +/** + * The id of this module + */ +#define AUDIO_POLICY_HARDWARE_MODULE_ID "audio_policy" + +/** + * Name of the audio devices to open + */ +#define AUDIO_POLICY_INTERFACE "policy" + +/* ---------------------------------------------------------------------------- */ + +/* + * The audio_policy and audio_policy_service_ops structs define the + * communication interfaces between the platform specific audio policy manager + * and Android generic audio policy manager. + * The platform specific audio policy manager must implement methods of the + * audio_policy struct. + * This implementation makes use of the audio_policy_service_ops to control + * the activity and configuration of audio input and output streams. + * + * The platform specific audio policy manager is in charge of the audio + * routing and volume control policies for a given platform. + * The main roles of this module are: + * - keep track of current system state (removable device connections, phone + * state, user requests...). + * System state changes and user actions are notified to audio policy + * manager with methods of the audio_policy. + * + * - process get_output() queries received when AudioTrack objects are + * created: Those queries return a handler on an output that has been + * selected, configured and opened by the audio policy manager and that + * must be used by the AudioTrack when registering to the AudioFlinger + * with the createTrack() method. + * When the AudioTrack object is released, a release_output() query + * is received and the audio policy manager can decide to close or + * reconfigure the output depending on other streams using this output and + * current system state. + * + * - similarly process get_input() and release_input() queries received from + * AudioRecord objects and configure audio inputs. + * - process volume control requests: the stream volume is converted from + * an index value (received from UI) to a float value applicable to each + * output as a function of platform specific settings and current output + * route (destination device). It also make sure that streams are not + * muted if not allowed (e.g. camera shutter sound in some countries). + */ + +/* XXX: this should be defined OUTSIDE of frameworks/base */ +struct effect_descriptor_s; + +struct audio_policy { + /* + * configuration functions + */ + + /* indicate a change in device connection status */ + int (*set_device_connection_state)(struct audio_policy *pol, + audio_devices_t device, + audio_policy_dev_state_t state, + const char *device_address); + + /* retrieve a device connection status */ + audio_policy_dev_state_t (*get_device_connection_state)( + const struct audio_policy *pol, + audio_devices_t device, + const char *device_address); + + /* indicate a change in phone state. Valid phones states are defined + * by audio_mode_t */ + void (*set_phone_state)(struct audio_policy *pol, audio_mode_t state); + + /* deprecated, never called (was "indicate a change in ringer mode") */ + void (*set_ringer_mode)(struct audio_policy *pol, uint32_t mode, + uint32_t mask); + + /* force using a specific device category for the specified usage */ + void (*set_force_use)(struct audio_policy *pol, + audio_policy_force_use_t usage, + audio_policy_forced_cfg_t config); + + /* retrieve current device category forced for a given usage */ + audio_policy_forced_cfg_t (*get_force_use)(const struct audio_policy *pol, + audio_policy_force_use_t usage); + + /* if can_mute is true, then audio streams that are marked ENFORCED_AUDIBLE + * can still be muted. */ + void (*set_can_mute_enforced_audible)(struct audio_policy *pol, + bool can_mute); + + /* check proper initialization */ + int (*init_check)(const struct audio_policy *pol); + + /* + * Audio routing query functions + */ + + /* request an output appropriate for playback of the supplied stream type and + * parameters */ + audio_io_handle_t (*get_output)(struct audio_policy *pol, + audio_stream_type_t stream, + uint32_t samplingRate, + audio_format_t format, + audio_channel_mask_t channelMask, + audio_output_flags_t flags); + + /* indicates to the audio policy manager that the output starts being used + * by corresponding stream. */ + int (*start_output)(struct audio_policy *pol, + audio_io_handle_t output, + audio_stream_type_t stream, + int session); + + /* indicates to the audio policy manager that the output stops being used + * by corresponding stream. */ + int (*stop_output)(struct audio_policy *pol, + audio_io_handle_t output, + audio_stream_type_t stream, + int session); + + /* releases the output. */ + void (*release_output)(struct audio_policy *pol, audio_io_handle_t output); + + /* request an input appropriate for record from the supplied device with + * supplied parameters. */ + audio_io_handle_t (*get_input)(struct audio_policy *pol, audio_source_t inputSource, + uint32_t samplingRate, + audio_format_t format, + audio_channel_mask_t channelMask, + audio_in_acoustics_t acoustics); + + /* indicates to the audio policy manager that the input starts being used */ + int (*start_input)(struct audio_policy *pol, audio_io_handle_t input); + + /* indicates to the audio policy manager that the input stops being used. */ + int (*stop_input)(struct audio_policy *pol, audio_io_handle_t input); + + /* releases the input. */ + void (*release_input)(struct audio_policy *pol, audio_io_handle_t input); + + /* + * volume control functions + */ + + /* initialises stream volume conversion parameters by specifying volume + * index range. The index range for each stream is defined by AudioService. */ + void (*init_stream_volume)(struct audio_policy *pol, + audio_stream_type_t stream, + int index_min, + int index_max); + + /* sets the new stream volume at a level corresponding to the supplied + * index. The index is within the range specified by init_stream_volume() */ + int (*set_stream_volume_index)(struct audio_policy *pol, + audio_stream_type_t stream, + int index); + + /* retrieve current volume index for the specified stream */ + int (*get_stream_volume_index)(const struct audio_policy *pol, + audio_stream_type_t stream, + int *index); + + /* sets the new stream volume at a level corresponding to the supplied + * index for the specified device. + * The index is within the range specified by init_stream_volume() */ + int (*set_stream_volume_index_for_device)(struct audio_policy *pol, + audio_stream_type_t stream, + int index, + audio_devices_t device); + + /* retrieve current volume index for the specified stream for the specified device */ + int (*get_stream_volume_index_for_device)(const struct audio_policy *pol, + audio_stream_type_t stream, + int *index, + audio_devices_t device); + + /* return the strategy corresponding to a given stream type */ + uint32_t (*get_strategy_for_stream)(const struct audio_policy *pol, + audio_stream_type_t stream); + + /* return the enabled output devices for the given stream type */ + audio_devices_t (*get_devices_for_stream)(const struct audio_policy *pol, + audio_stream_type_t stream); + + /* Audio effect management */ + audio_io_handle_t (*get_output_for_effect)(struct audio_policy *pol, + const struct effect_descriptor_s *desc); + + int (*register_effect)(struct audio_policy *pol, + const struct effect_descriptor_s *desc, + audio_io_handle_t output, + uint32_t strategy, + int session, + int id); + + int (*unregister_effect)(struct audio_policy *pol, int id); + + int (*set_effect_enabled)(struct audio_policy *pol, int id, bool enabled); + + bool (*is_stream_active)(const struct audio_policy *pol, + audio_stream_type_t stream, + uint32_t in_past_ms); + + bool (*is_source_active)(const struct audio_policy *pol, + audio_source_t source); + + /* dump state */ + int (*dump)(const struct audio_policy *pol, int fd); +}; + +/* audio hw module handle used by load_hw_module(), open_output_on_module() + * and open_input_on_module() */ +typedef int audio_module_handle_t; + +struct audio_policy_service_ops { + /* + * Audio output Control functions + */ + + /* Opens an audio output with the requested parameters. + * + * The parameter values can indicate to use the default values in case the + * audio policy manager has no specific requirements for the output being + * opened. + * + * When the function returns, the parameter values reflect the actual + * values used by the audio hardware output stream. + * + * The audio policy manager can check if the proposed parameters are + * suitable or not and act accordingly. + */ + audio_io_handle_t (*open_output)(void *service, + audio_devices_t *pDevices, + uint32_t *pSamplingRate, + audio_format_t *pFormat, + audio_channel_mask_t *pChannelMask, + uint32_t *pLatencyMs, + audio_output_flags_t flags); + + /* creates a special output that is duplicated to the two outputs passed as + * arguments. The duplication is performed by + * a special mixer thread in the AudioFlinger. + */ + audio_io_handle_t (*open_duplicate_output)(void *service, + audio_io_handle_t output1, + audio_io_handle_t output2); + + /* closes the output stream */ + int (*close_output)(void *service, audio_io_handle_t output); + + /* suspends the output. + * + * When an output is suspended, the corresponding audio hardware output + * stream is placed in standby and the AudioTracks attached to the mixer + * thread are still processed but the output mix is discarded. + */ + int (*suspend_output)(void *service, audio_io_handle_t output); + + /* restores a suspended output. */ + int (*restore_output)(void *service, audio_io_handle_t output); + + /* */ + /* Audio input Control functions */ + /* */ + + /* opens an audio input + * deprecated - new implementations should use open_input_on_module, + * and the acoustics parameter is ignored + */ + audio_io_handle_t (*open_input)(void *service, + audio_devices_t *pDevices, + uint32_t *pSamplingRate, + audio_format_t *pFormat, + audio_channel_mask_t *pChannelMask, + audio_in_acoustics_t acoustics); + + /* closes an audio input */ + int (*close_input)(void *service, audio_io_handle_t input); + + /* */ + /* misc control functions */ + /* */ + + /* set a stream volume for a particular output. + * + * For the same user setting, a given stream type can have different + * volumes for each output (destination device) it is attached to. + */ + int (*set_stream_volume)(void *service, + audio_stream_type_t stream, + float volume, + audio_io_handle_t output, + int delay_ms); + + /* reroute a given stream type to the specified output */ + int (*set_stream_output)(void *service, + audio_stream_type_t stream, + audio_io_handle_t output); + + /* function enabling to send proprietary informations directly from audio + * policy manager to audio hardware interface. */ + void (*set_parameters)(void *service, + audio_io_handle_t io_handle, + const char *kv_pairs, + int delay_ms); + + /* function enabling to receive proprietary informations directly from + * audio hardware interface to audio policy manager. + * + * Returns a pointer to a heap allocated string. The caller is responsible + * for freeing the memory for it using free(). + */ + + char * (*get_parameters)(void *service, audio_io_handle_t io_handle, + const char *keys); + + /* request the playback of a tone on the specified stream. + * used for instance to replace notification sounds when playing over a + * telephony device during a phone call. + */ + int (*start_tone)(void *service, + audio_policy_tone_t tone, + audio_stream_type_t stream); + + int (*stop_tone)(void *service); + + /* set down link audio volume. */ + int (*set_voice_volume)(void *service, + float volume, + int delay_ms); + + /* move effect to the specified output */ + int (*move_effects)(void *service, + int session, + audio_io_handle_t src_output, + audio_io_handle_t dst_output); + + /* loads an audio hw module. + * + * The module name passed is the base name of the HW module library, e.g "primary" or "a2dp". + * The function returns a handle on the module that will be used to specify a particular + * module when calling open_output_on_module() or open_input_on_module() + */ + audio_module_handle_t (*load_hw_module)(void *service, + const char *name); + + /* Opens an audio output on a particular HW module. + * + * Same as open_output() but specifying a specific HW module on which the output must be opened. + */ + audio_io_handle_t (*open_output_on_module)(void *service, + audio_module_handle_t module, + audio_devices_t *pDevices, + uint32_t *pSamplingRate, + audio_format_t *pFormat, + audio_channel_mask_t *pChannelMask, + uint32_t *pLatencyMs, + audio_output_flags_t flags); + + /* Opens an audio input on a particular HW module. + * + * Same as open_input() but specifying a specific HW module on which the input must be opened. + * Also removed deprecated acoustics parameter + */ + audio_io_handle_t (*open_input_on_module)(void *service, + audio_module_handle_t module, + audio_devices_t *pDevices, + uint32_t *pSamplingRate, + audio_format_t *pFormat, + audio_channel_mask_t *pChannelMask); + +}; + +/**********************************************************************/ + +/** + * Every hardware module must have a data structure named HAL_MODULE_INFO_SYM + * and the fields of this data structure must begin with hw_module_t + * followed by module specific information. + */ +typedef struct audio_policy_module { + struct hw_module_t common; +} audio_policy_module_t; + +struct audio_policy_device { + struct hw_device_t common; + + int (*create_audio_policy)(const struct audio_policy_device *device, + struct audio_policy_service_ops *aps_ops, + void *service, + struct audio_policy **ap); + + int (*destroy_audio_policy)(const struct audio_policy_device *device, + struct audio_policy *ap); +}; + +/** convenience API for opening and closing a supported device */ + +static inline int audio_policy_dev_open(const hw_module_t* module, + struct audio_policy_device** device) +{ + return module->methods->open(module, AUDIO_POLICY_INTERFACE, + (hw_device_t**)device); +} + +static inline int audio_policy_dev_close(struct audio_policy_device* device) +{ + return device->common.close(&device->common); +} + + +__END_DECLS + +#endif // ANDROID_AUDIO_POLICY_INTERFACE_H diff -Nru android-tools-4.2.2+git20130218/libhardware/include/hardware/bluetooth.h android-tools-4.2.2+git20130529/libhardware/include/hardware/bluetooth.h --- android-tools-4.2.2+git20130218/libhardware/include/hardware/bluetooth.h 1970-01-01 00:00:00.000000000 +0000 +++ android-tools-4.2.2+git20130529/libhardware/include/hardware/bluetooth.h 2013-05-29 20:16:54.000000000 +0000 @@ -0,0 +1,441 @@ +/* + * Copyright (C) 2012 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 ANDROID_INCLUDE_BLUETOOTH_H +#define ANDROID_INCLUDE_BLUETOOTH_H + +#include +#include +#include + +#include + +__BEGIN_DECLS + +/** + * The Bluetooth Hardware Module ID + */ + +#define BT_HARDWARE_MODULE_ID "bluetooth" +#define BT_STACK_MODULE_ID "bluetooth" +#define BT_STACK_TEST_MODULE_ID "bluetooth_test" + + +/* Bluetooth profile interface IDs */ + +#define BT_PROFILE_HANDSFREE_ID "handsfree" +#define BT_PROFILE_ADVANCED_AUDIO_ID "a2dp" +#define BT_PROFILE_HEALTH_ID "health" +#define BT_PROFILE_SOCKETS_ID "socket" +#define BT_PROFILE_HIDHOST_ID "hidhost" +#define BT_PROFILE_PAN_ID "pan" + + +/** Bluetooth Address */ +typedef struct { + uint8_t address[6]; +} __attribute__((packed))bt_bdaddr_t; + +/** Bluetooth Device Name */ +typedef struct { + uint8_t name[248]; +} __attribute__((packed))bt_bdname_t; + +/** Bluetooth Adapter Visibility Modes*/ +typedef enum { + BT_SCAN_MODE_NONE, + BT_SCAN_MODE_CONNECTABLE, + BT_SCAN_MODE_CONNECTABLE_DISCOVERABLE +} bt_scan_mode_t; + +/** Bluetooth Adapter State */ +typedef enum { + BT_STATE_OFF, + BT_STATE_ON +} bt_state_t; + +/** Bluetooth Error Status */ +/** We need to build on this */ + +typedef enum { + BT_STATUS_SUCCESS, + BT_STATUS_FAIL, + BT_STATUS_NOT_READY, + BT_STATUS_NOMEM, + BT_STATUS_BUSY, + BT_STATUS_DONE, /* request already completed */ + BT_STATUS_UNSUPPORTED, + BT_STATUS_PARM_INVALID, + BT_STATUS_UNHANDLED, + BT_STATUS_AUTH_FAILURE, + BT_STATUS_RMT_DEV_DOWN + +} bt_status_t; + +/** Bluetooth PinKey Code */ +typedef struct { + uint8_t pin[16]; +} __attribute__((packed))bt_pin_code_t; + +/** Bluetooth Adapter Discovery state */ +typedef enum { + BT_DISCOVERY_STOPPED, + BT_DISCOVERY_STARTED +} bt_discovery_state_t; + +/** Bluetooth ACL connection state */ +typedef enum { + BT_ACL_STATE_CONNECTED, + BT_ACL_STATE_DISCONNECTED +} bt_acl_state_t; + +/** Bluetooth 128-bit UUID */ +typedef struct { + uint8_t uu[16]; +} bt_uuid_t; + +/** Bluetooth SDP service record */ +typedef struct +{ + bt_uuid_t uuid; + uint16_t channel; + char name[256]; // what's the maximum length +} bt_service_record_t; + +/* Bluetooth Adapter and Remote Device property types */ +typedef enum { + /* Properties common to both adapter and remote device */ + /** + * Description - Bluetooth Device Name + * Access mode - Adapter name can be GET/SET. Remote device can be GET + * Data type - bt_bdname_t + */ + BT_PROPERTY_BDNAME = 0x1, + /** + * Description - Bluetooth Device Address + * Access mode - Only GET. + * Data type - bt_bdaddr_t + */ + BT_PROPERTY_BDADDR, + /** + * Description - Bluetooth Service 128-bit UUIDs + * Access mode - Only GET. + * Data type - Array of bt_uuid_t (Array size inferred from property length). + */ + BT_PROPERTY_UUIDS, + /** + * Description - Bluetooth Class of Device as found in Assigned Numbers + * Access mode - Only GET. + * Data type - uint32_t. + */ + BT_PROPERTY_CLASS_OF_DEVICE, + /** + * Description - Device Type - BREDR, BLE or DUAL Mode + * Access mode - Only GET. + * Data type - bt_device_type_t + */ + BT_PROPERTY_TYPE_OF_DEVICE, + /** + * Description - Bluetooth Service Record + * Access mode - Only GET. + * Data type - bt_service_record_t + */ + BT_PROPERTY_SERVICE_RECORD, + + /* Properties unique to adapter */ + /** + * Description - Bluetooth Adapter scan mode + * Access mode - GET and SET + * Data type - bt_scan_mode_t. + */ + BT_PROPERTY_ADAPTER_SCAN_MODE, + /** + * Description - List of bonded devices + * Access mode - Only GET. + * Data type - Array of bt_bdaddr_t of the bonded remote devices + * (Array size inferred from property length). + */ + BT_PROPERTY_ADAPTER_BONDED_DEVICES, + /** + * Description - Bluetooth Adapter Discovery timeout (in seconds) + * Access mode - GET and SET + * Data type - uint32_t + */ + BT_PROPERTY_ADAPTER_DISCOVERY_TIMEOUT, + + /* Properties unique to remote device */ + /** + * Description - User defined friendly name of the remote device + * Access mode - GET and SET + * Data type - bt_bdname_t. + */ + BT_PROPERTY_REMOTE_FRIENDLY_NAME, + /** + * Description - RSSI value of the inquired remote device + * Access mode - Only GET. + * Data type - int32_t. + */ + BT_PROPERTY_REMOTE_RSSI, + + BT_PROPERTY_REMOTE_DEVICE_TIMESTAMP = 0xFF, +} bt_property_type_t; + +/** Bluetooth Adapter Property data structure */ +typedef struct +{ + bt_property_type_t type; + int len; + void *val; +} bt_property_t; + +/** Bluetooth Device Type */ +typedef enum { + BT_DEVICE_DEVTYPE_BREDR = 0x1, + BT_DEVICE_DEVTYPE_BLE, + BT_DEVICE_DEVTYPE_DUAL +} bt_device_type_t; +/** Bluetooth Bond state */ +typedef enum { + BT_BOND_STATE_NONE, + BT_BOND_STATE_BONDING, + BT_BOND_STATE_BONDED +} bt_bond_state_t; + +/** Bluetooth SSP Bonding Variant */ +typedef enum { + BT_SSP_VARIANT_PASSKEY_CONFIRMATION, + BT_SSP_VARIANT_PASSKEY_ENTRY, + BT_SSP_VARIANT_CONSENT, + BT_SSP_VARIANT_PASSKEY_NOTIFICATION +} bt_ssp_variant_t; + +#define BT_MAX_NUM_UUIDS 32 + +/** Bluetooth Interface callbacks */ + +/** Bluetooth Enable/Disable Callback. */ +typedef void (*adapter_state_changed_callback)(bt_state_t state); + +/** GET/SET Adapter Properties callback */ +/* TODO: For the GET/SET property APIs/callbacks, we may need a session + * identifier to associate the call with the callback. This would be needed + * whenever more than one simultaneous instance of the same adapter_type + * is get/set. + * + * If this is going to be handled in the Java framework, then we do not need + * to manage sessions here. + */ +typedef void (*adapter_properties_callback)(bt_status_t status, + int num_properties, + bt_property_t *properties); + +/** GET/SET Remote Device Properties callback */ +/** TODO: For remote device properties, do not see a need to get/set + * multiple properties - num_properties shall be 1 + */ +typedef void (*remote_device_properties_callback)(bt_status_t status, + bt_bdaddr_t *bd_addr, + int num_properties, + bt_property_t *properties); + +/** New device discovered callback */ +/** If EIR data is not present, then BD_NAME and RSSI shall be NULL and -1 + * respectively */ +typedef void (*device_found_callback)(int num_properties, + bt_property_t *properties); + +/** Discovery state changed callback */ +typedef void (*discovery_state_changed_callback)(bt_discovery_state_t state); + +/** Bluetooth Legacy PinKey Request callback */ +typedef void (*pin_request_callback)(bt_bdaddr_t *remote_bd_addr, + bt_bdname_t *bd_name, uint32_t cod); + +/** Bluetooth SSP Request callback - Just Works & Numeric Comparison*/ +/** pass_key - Shall be 0 for BT_SSP_PAIRING_VARIANT_CONSENT & + * BT_SSP_PAIRING_PASSKEY_ENTRY */ +/* TODO: Passkey request callback shall not be needed for devices with display + * capability. We still need support this in the stack for completeness */ +typedef void (*ssp_request_callback)(bt_bdaddr_t *remote_bd_addr, + bt_bdname_t *bd_name, + uint32_t cod, + bt_ssp_variant_t pairing_variant, + uint32_t pass_key); + +/** Bluetooth Bond state changed callback */ +/* Invoked in response to create_bond, cancel_bond or remove_bond */ +typedef void (*bond_state_changed_callback)(bt_status_t status, + bt_bdaddr_t *remote_bd_addr, + bt_bond_state_t state); + +/** Bluetooth ACL connection state changed callback */ +typedef void (*acl_state_changed_callback)(bt_status_t status, bt_bdaddr_t *remote_bd_addr, + bt_acl_state_t state); + +typedef enum { + ASSOCIATE_JVM, + DISASSOCIATE_JVM +} bt_cb_thread_evt; + +/** Thread Associate/Disassociate JVM Callback */ +/* Callback that is invoked by the callback thread to allow upper layer to attach/detach to/from + * the JVM */ +typedef void (*callback_thread_event)(bt_cb_thread_evt evt); + +/** Bluetooth Test Mode Callback */ +/* Receive any HCI event from controller. Must be in DUT Mode for this callback to be received */ +typedef void (*dut_mode_recv_callback)(uint16_t opcode, uint8_t *buf, uint8_t len); + +/** TODO: Add callbacks for Link Up/Down and other generic + * notifications/callbacks */ + +/** Bluetooth DM callback structure. */ +typedef struct { + /** set to sizeof(bt_callbacks_t) */ + size_t size; + adapter_state_changed_callback adapter_state_changed_cb; + adapter_properties_callback adapter_properties_cb; + remote_device_properties_callback remote_device_properties_cb; + device_found_callback device_found_cb; + discovery_state_changed_callback discovery_state_changed_cb; + pin_request_callback pin_request_cb; + ssp_request_callback ssp_request_cb; + bond_state_changed_callback bond_state_changed_cb; + acl_state_changed_callback acl_state_changed_cb; + callback_thread_event thread_evt_cb; + dut_mode_recv_callback dut_mode_recv_cb; +} bt_callbacks_t; + +/** NOTE: By default, no profiles are initialized at the time of init/enable. + * Whenever the application invokes the 'init' API of a profile, then one of + * the following shall occur: + * + * 1.) If Bluetooth is not enabled, then the Bluetooth core shall mark the + * profile as enabled. Subsequently, when the application invokes the + * Bluetooth 'enable', as part of the enable sequence the profile that were + * marked shall be enabled by calling appropriate stack APIs. The + * 'adapter_properties_cb' shall return the list of UUIDs of the + * enabled profiles. + * + * 2.) If Bluetooth is enabled, then the Bluetooth core shall invoke the stack + * profile API to initialize the profile and trigger a + * 'adapter_properties_cb' with the current list of UUIDs including the + * newly added profile's UUID. + * + * The reverse shall occur whenever the profile 'cleanup' APIs are invoked + */ + +/** Represents the standard Bluetooth DM interface. */ +typedef struct { + /** set to sizeof(bt_interface_t) */ + size_t size; + /** + * Opens the interface and provides the callback routines + * to the implemenation of this interface. + */ + int (*init)(bt_callbacks_t* callbacks ); + + /** Enable Bluetooth. */ + int (*enable)(void); + + /** Disable Bluetooth. */ + int (*disable)(void); + + /** Closes the interface. */ + void (*cleanup)(void); + + /** Get all Bluetooth Adapter properties at init */ + int (*get_adapter_properties)(void); + + /** Get Bluetooth Adapter property of 'type' */ + int (*get_adapter_property)(bt_property_type_t type); + + /** Set Bluetooth Adapter property of 'type' */ + /* Based on the type, val shall be one of + * bt_bdaddr_t or bt_bdname_t or bt_scanmode_t etc + */ + int (*set_adapter_property)(const bt_property_t *property); + + /** Get all Remote Device properties */ + int (*get_remote_device_properties)(bt_bdaddr_t *remote_addr); + + /** Get Remote Device property of 'type' */ + int (*get_remote_device_property)(bt_bdaddr_t *remote_addr, + bt_property_type_t type); + + /** Set Remote Device property of 'type' */ + int (*set_remote_device_property)(bt_bdaddr_t *remote_addr, + const bt_property_t *property); + + /** Get Remote Device's service record for the given UUID */ + int (*get_remote_service_record)(bt_bdaddr_t *remote_addr, + bt_uuid_t *uuid); + + /** Start SDP to get remote services */ + int (*get_remote_services)(bt_bdaddr_t *remote_addr); + + /** Start Discovery */ + int (*start_discovery)(void); + + /** Cancel Discovery */ + int (*cancel_discovery)(void); + + /** Create Bluetooth Bonding */ + int (*create_bond)(const bt_bdaddr_t *bd_addr); + + /** Remove Bond */ + int (*remove_bond)(const bt_bdaddr_t *bd_addr); + + /** Cancel Bond */ + int (*cancel_bond)(const bt_bdaddr_t *bd_addr); + + /** BT Legacy PinKey Reply */ + /** If accept==FALSE, then pin_len and pin_code shall be 0x0 */ + int (*pin_reply)(const bt_bdaddr_t *bd_addr, uint8_t accept, + uint8_t pin_len, bt_pin_code_t *pin_code); + + /** BT SSP Reply - Just Works, Numeric Comparison and Passkey + * passkey shall be zero for BT_SSP_VARIANT_PASSKEY_COMPARISON & + * BT_SSP_VARIANT_CONSENT + * For BT_SSP_VARIANT_PASSKEY_ENTRY, if accept==FALSE, then passkey + * shall be zero */ + int (*ssp_reply)(const bt_bdaddr_t *bd_addr, bt_ssp_variant_t variant, + uint8_t accept, uint32_t passkey); + + /** Get Bluetooth profile interface */ + const void* (*get_profile_interface) (const char *profile_id); + + /** Bluetooth Test Mode APIs - Bluetooth must be enabled for these APIs */ + /* Configure DUT Mode - Use this mode to enter/exit DUT mode */ + int (*dut_mode_configure)(uint8_t enable); + + /* Send any test HCI (vendor-specific) command to the controller. Must be in DUT Mode */ + int (*dut_mode_send)(uint16_t opcode, uint8_t *buf, uint8_t len); +} bt_interface_t; + +/** TODO: Need to add APIs for Service Discovery, Service authorization and + * connection management. Also need to add APIs for configuring + * properties of remote bonded devices such as name, UUID etc. */ + +typedef struct { + struct hw_device_t common; + const bt_interface_t* (*get_bluetooth_interface)(); +} bluetooth_device_t; + +typedef bluetooth_device_t bluetooth_module_t; +__END_DECLS + +#endif /* ANDROID_INCLUDE_BLUETOOTH_H */ diff -Nru android-tools-4.2.2+git20130218/libhardware/include/hardware/bt_av.h android-tools-4.2.2+git20130529/libhardware/include/hardware/bt_av.h --- android-tools-4.2.2+git20130218/libhardware/include/hardware/bt_av.h 1970-01-01 00:00:00.000000000 +0000 +++ android-tools-4.2.2+git20130529/libhardware/include/hardware/bt_av.h 2013-05-29 20:16:54.000000000 +0000 @@ -0,0 +1,90 @@ +/* + * Copyright (C) 2012 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 ANDROID_INCLUDE_BT_AV_H +#define ANDROID_INCLUDE_BT_AV_H + +__BEGIN_DECLS + +/* Bluetooth AV connection states */ +typedef enum { + BTAV_CONNECTION_STATE_DISCONNECTED = 0, + BTAV_CONNECTION_STATE_CONNECTING, + BTAV_CONNECTION_STATE_CONNECTED, + BTAV_CONNECTION_STATE_DISCONNECTING +} btav_connection_state_t; + +/* Bluetooth AV datapath states */ +typedef enum { + BTAV_AUDIO_STATE_REMOTE_SUSPEND = 0, + BTAV_AUDIO_STATE_STOPPED, + BTAV_AUDIO_STATE_STARTED, +} btav_audio_state_t; + + +/** Callback for connection state change. + * state will have one of the values from btav_connection_state_t + */ +typedef void (* btav_connection_state_callback)(btav_connection_state_t state, + bt_bdaddr_t *bd_addr); + +/** Callback for audiopath state change. + * state will have one of the values from btav_audio_state_t + */ +typedef void (* btav_audio_state_callback)(btav_audio_state_t state, + bt_bdaddr_t *bd_addr); + +/** BT-AV callback structure. */ +typedef struct { + /** set to sizeof(btav_callbacks_t) */ + size_t size; + btav_connection_state_callback connection_state_cb; + btav_audio_state_callback audio_state_cb; +} btav_callbacks_t; + +/** + * NOTE: + * + * 1. AVRCP 1.0 shall be supported initially. AVRCP passthrough commands + * shall be handled internally via uinput + * + * 2. A2DP data path shall be handled via a socket pipe between the AudioFlinger + * android_audio_hw library and the Bluetooth stack. + * + */ +/** Represents the standard BT-AV interface. */ +typedef struct { + + /** set to sizeof(btav_interface_t) */ + size_t size; + /** + * Register the BtAv callbacks + */ + bt_status_t (*init)( btav_callbacks_t* callbacks ); + + /** connect to headset */ + bt_status_t (*connect)( bt_bdaddr_t *bd_addr ); + + /** dis-connect from headset */ + bt_status_t (*disconnect)( bt_bdaddr_t *bd_addr ); + + /** Closes the interface. */ + void (*cleanup)( void ); +} btav_interface_t; + +__END_DECLS + +#endif /* ANDROID_INCLUDE_BT_AV_H */ diff -Nru android-tools-4.2.2+git20130218/libhardware/include/hardware/bt_hf.h android-tools-4.2.2+git20130529/libhardware/include/hardware/bt_hf.h --- android-tools-4.2.2+git20130218/libhardware/include/hardware/bt_hf.h 1970-01-01 00:00:00.000000000 +0000 +++ android-tools-4.2.2+git20130529/libhardware/include/hardware/bt_hf.h 2013-05-29 20:16:54.000000000 +0000 @@ -0,0 +1,284 @@ +/* + * Copyright (C) 2012 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 ANDROID_INCLUDE_BT_HF_H +#define ANDROID_INCLUDE_BT_HF_H + +__BEGIN_DECLS + +/* AT response code - OK/Error */ +typedef enum { + BTHF_AT_RESPONSE_ERROR = 0, + BTHF_AT_RESPONSE_OK +} bthf_at_response_t; + +typedef enum { + BTHF_CONNECTION_STATE_DISCONNECTED = 0, + BTHF_CONNECTION_STATE_CONNECTING, + BTHF_CONNECTION_STATE_CONNECTED, + BTHF_CONNECTION_STATE_SLC_CONNECTED, + BTHF_CONNECTION_STATE_DISCONNECTING +} bthf_connection_state_t; + +typedef enum { + BTHF_AUDIO_STATE_DISCONNECTED = 0, + BTHF_AUDIO_STATE_CONNECTING, + BTHF_AUDIO_STATE_CONNECTED, + BTHF_AUDIO_STATE_DISCONNECTING +} bthf_audio_state_t; + +typedef enum { + BTHF_VR_STATE_STOPPED = 0, + BTHF_VR_STATE_STARTED +} bthf_vr_state_t; + +typedef enum { + BTHF_VOLUME_TYPE_SPK = 0, + BTHF_VOLUME_TYPE_MIC +} bthf_volume_type_t; + +/* Noise Reduction and Echo Cancellation */ +typedef enum +{ + BTHF_NREC_STOP, + BTHF_NREC_START +} bthf_nrec_t; + +/* CHLD - Call held handling */ +typedef enum +{ + BTHF_CHLD_TYPE_RELEASEHELD, // Terminate all held or set UDUB("busy") to a waiting call + BTHF_CHLD_TYPE_RELEASEACTIVE_ACCEPTHELD, // Terminate all active calls and accepts a waiting/held call + BTHF_CHLD_TYPE_HOLDACTIVE_ACCEPTHELD, // Hold all active calls and accepts a waiting/held call + BTHF_CHLD_TYPE_ADDHELDTOCONF, // Add all held calls to a conference +} bthf_chld_type_t; + +/** Callback for connection state change. + * state will have one of the values from BtHfConnectionState + */ +typedef void (* bthf_connection_state_callback)(bthf_connection_state_t state, bt_bdaddr_t *bd_addr); + +/** Callback for audio connection state change. + * state will have one of the values from BtHfAudioState + */ +typedef void (* bthf_audio_state_callback)(bthf_audio_state_t state, bt_bdaddr_t *bd_addr); + +/** Callback for VR connection state change. + * state will have one of the values from BtHfVRState + */ +typedef void (* bthf_vr_cmd_callback)(bthf_vr_state_t state); + +/** Callback for answer incoming call (ATA) + */ +typedef void (* bthf_answer_call_cmd_callback)(); + +/** Callback for disconnect call (AT+CHUP) + */ +typedef void (* bthf_hangup_call_cmd_callback)(); + +/** Callback for disconnect call (AT+CHUP) + * type will denote Speaker/Mic gain (BtHfVolumeControl). + */ +typedef void (* bthf_volume_cmd_callback)(bthf_volume_type_t type, int volume); + +/** Callback for dialing an outgoing call + * If number is NULL, redial + */ +typedef void (* bthf_dial_call_cmd_callback)(char *number); + +/** Callback for sending DTMF tones + * tone contains the dtmf character to be sent + */ +typedef void (* bthf_dtmf_cmd_callback)(char tone); + +/** Callback for enabling/disabling noise reduction/echo cancellation + * value will be 1 to enable, 0 to disable + */ +typedef void (* bthf_nrec_cmd_callback)(bthf_nrec_t nrec); + +/** Callback for call hold handling (AT+CHLD) + * value will contain the call hold command (0, 1, 2, 3) + */ +typedef void (* bthf_chld_cmd_callback)(bthf_chld_type_t chld); + +/** Callback for CNUM (subscriber number) + */ +typedef void (* bthf_cnum_cmd_callback)(); + +/** Callback for indicators (CIND) + */ +typedef void (* bthf_cind_cmd_callback)(); + +/** Callback for operator selection (COPS) + */ +typedef void (* bthf_cops_cmd_callback)(); + +/** Callback for call list (AT+CLCC) + */ +typedef void (* bthf_clcc_cmd_callback) (); + +/** Callback for unknown AT command recd from HF + * at_string will contain the unparsed AT string + */ +typedef void (* bthf_unknown_at_cmd_callback)(char *at_string); + +/** Callback for keypressed (HSP) event. + */ +typedef void (* bthf_key_pressed_cmd_callback)(); + +/** BT-HF callback structure. */ +typedef struct { + /** set to sizeof(BtHfCallbacks) */ + size_t size; + bthf_connection_state_callback connection_state_cb; + bthf_audio_state_callback audio_state_cb; + bthf_vr_cmd_callback vr_cmd_cb; + bthf_answer_call_cmd_callback answer_call_cmd_cb; + bthf_hangup_call_cmd_callback hangup_call_cmd_cb; + bthf_volume_cmd_callback volume_cmd_cb; + bthf_dial_call_cmd_callback dial_call_cmd_cb; + bthf_dtmf_cmd_callback dtmf_cmd_cb; + bthf_nrec_cmd_callback nrec_cmd_cb; + bthf_chld_cmd_callback chld_cmd_cb; + bthf_cnum_cmd_callback cnum_cmd_cb; + bthf_cind_cmd_callback cind_cmd_cb; + bthf_cops_cmd_callback cops_cmd_cb; + bthf_clcc_cmd_callback clcc_cmd_cb; + bthf_unknown_at_cmd_callback unknown_at_cmd_cb; + bthf_key_pressed_cmd_callback key_pressed_cmd_cb; +} bthf_callbacks_t; + +/** Network Status */ +typedef enum +{ + BTHF_NETWORK_STATE_NOT_AVAILABLE = 0, + BTHF_NETWORK_STATE_AVAILABLE +} bthf_network_state_t; + +/** Service type */ +typedef enum +{ + BTHF_SERVICE_TYPE_HOME = 0, + BTHF_SERVICE_TYPE_ROAMING +} bthf_service_type_t; + +typedef enum { + BTHF_CALL_STATE_ACTIVE = 0, + BTHF_CALL_STATE_HELD, + BTHF_CALL_STATE_DIALING, + BTHF_CALL_STATE_ALERTING, + BTHF_CALL_STATE_INCOMING, + BTHF_CALL_STATE_WAITING, + BTHF_CALL_STATE_IDLE +} bthf_call_state_t; + +typedef enum { + BTHF_CALL_DIRECTION_OUTGOING = 0, + BTHF_CALL_DIRECTION_INCOMING +} bthf_call_direction_t; + +typedef enum { + BTHF_CALL_TYPE_VOICE = 0, + BTHF_CALL_TYPE_DATA, + BTHF_CALL_TYPE_FAX +} bthf_call_mode_t; + +typedef enum { + BTHF_CALL_MPTY_TYPE_SINGLE = 0, + BTHF_CALL_MPTY_TYPE_MULTI +} bthf_call_mpty_type_t; + +typedef enum { + BTHF_CALL_ADDRTYPE_UNKNOWN = 0x81, + BTHF_CALL_ADDRTYPE_INTERNATIONAL = 0x91 +} bthf_call_addrtype_t; +/** Represents the standard BT-HF interface. */ +typedef struct { + + /** set to sizeof(BtHfInterface) */ + size_t size; + /** + * Register the BtHf callbacks + */ + bt_status_t (*init)( bthf_callbacks_t* callbacks ); + + /** connect to headset */ + bt_status_t (*connect)( bt_bdaddr_t *bd_addr ); + + /** dis-connect from headset */ + bt_status_t (*disconnect)( bt_bdaddr_t *bd_addr ); + + /** create an audio connection */ + bt_status_t (*connect_audio)( bt_bdaddr_t *bd_addr ); + + /** close the audio connection */ + bt_status_t (*disconnect_audio)( bt_bdaddr_t *bd_addr ); + + /** start voice recognition */ + bt_status_t (*start_voice_recognition)(); + + /** stop voice recognition */ + bt_status_t (*stop_voice_recognition)(); + + /** volume control */ + bt_status_t (*volume_control) (bthf_volume_type_t type, int volume); + + /** Combined device status change notification */ + bt_status_t (*device_status_notification)(bthf_network_state_t ntk_state, bthf_service_type_t svc_type, int signal, + int batt_chg); + + /** Response for COPS command */ + bt_status_t (*cops_response)(const char *cops); + + /** Response for CIND command */ + bt_status_t (*cind_response)(int svc, int num_active, int num_held, bthf_call_state_t call_setup_state, + int signal, int roam, int batt_chg); + + /** Pre-formatted AT response, typically in response to unknown AT cmd */ + bt_status_t (*formatted_at_response)(const char *rsp); + + /** ok/error response + * ERROR (0) + * OK (1) + */ + bt_status_t (*at_response) (bthf_at_response_t response_code, int error_code); + + /** response for CLCC command + * Can be iteratively called for each call index + * Call index of 0 will be treated as NULL termination (Completes response) + */ + bt_status_t (*clcc_response) (int index, bthf_call_direction_t dir, + bthf_call_state_t state, bthf_call_mode_t mode, + bthf_call_mpty_type_t mpty, const char *number, + bthf_call_addrtype_t type); + + /** notify of a call state change + * Each update notifies + * 1. Number of active/held/ringing calls + * 2. call_state: This denotes the state change that triggered this msg + * This will take one of the values from BtHfCallState + * 3. number & type: valid only for incoming & waiting call + */ + bt_status_t (*phone_state_change) (int num_active, int num_held, bthf_call_state_t call_setup_state, + const char *number, bthf_call_addrtype_t type); + + /** Closes the interface. */ + void (*cleanup)( void ); +} bthf_interface_t; + +__END_DECLS + +#endif /* ANDROID_INCLUDE_BT_HF_H */ diff -Nru android-tools-4.2.2+git20130218/libhardware/include/hardware/bt_hh.h android-tools-4.2.2+git20130529/libhardware/include/hardware/bt_hh.h --- android-tools-4.2.2+git20130218/libhardware/include/hardware/bt_hh.h 1970-01-01 00:00:00.000000000 +0000 +++ android-tools-4.2.2+git20130529/libhardware/include/hardware/bt_hh.h 2013-05-29 20:16:54.000000000 +0000 @@ -0,0 +1,179 @@ +/* + * Copyright (C) 2012 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 ANDROID_INCLUDE_BT_HH_H +#define ANDROID_INCLUDE_BT_HH_H + +#include + +__BEGIN_DECLS + +#define BTHH_MAX_DSC_LEN 884 + +/* HH connection states */ +typedef enum +{ + BTHH_CONN_STATE_CONNECTED = 0, + BTHH_CONN_STATE_CONNECTING, + BTHH_CONN_STATE_DISCONNECTED, + BTHH_CONN_STATE_DISCONNECTING, + BTHH_CONN_STATE_FAILED_MOUSE_FROM_HOST, + BTHH_CONN_STATE_FAILED_KBD_FROM_HOST, + BTHH_CONN_STATE_FAILED_TOO_MANY_DEVICES, + BTHH_CONN_STATE_FAILED_NO_BTHID_DRIVER, + BTHH_CONN_STATE_FAILED_GENERIC, + BTHH_CONN_STATE_UNKNOWN +} bthh_connection_state_t; + +typedef enum +{ + BTHH_OK = 0, + BTHH_HS_HID_NOT_READY, /* handshake error : device not ready */ + BTHH_HS_INVALID_RPT_ID, /* handshake error : invalid report ID */ + BTHH_HS_TRANS_NOT_SPT, /* handshake error : transaction not spt */ + BTHH_HS_INVALID_PARAM, /* handshake error : invalid paremter */ + BTHH_HS_ERROR, /* handshake error : unspecified HS error */ + BTHH_ERR, /* general BTA HH error */ + BTHH_ERR_SDP, /* SDP error */ + BTHH_ERR_PROTO, /* SET_Protocol error, + only used in BTA_HH_OPEN_EVT callback */ + BTHH_ERR_DB_FULL, /* device database full error, used */ + BTHH_ERR_TOD_UNSPT, /* type of device not supported */ + BTHH_ERR_NO_RES, /* out of system resources */ + BTHH_ERR_AUTH_FAILED, /* authentication fail */ + BTHH_ERR_HDL +}bthh_status_t; + +/* Protocol modes */ +typedef enum { + BTHH_REPORT_MODE = 0x00, + BTHH_BOOT_MODE = 0x01, + BTHH_UNSUPPORTED_MODE = 0xff +}bthh_protocol_mode_t; + +/* Report types */ +typedef enum { + BTHH_INPUT_REPORT = 1, + BTHH_OUTPUT_REPORT, + BTHH_FEATURE_REPORT +}bthh_report_type_t; + +typedef struct +{ + int attr_mask; + uint8_t sub_class; + uint8_t app_id; + int vendor_id; + int product_id; + int version; + uint8_t ctry_code; + int dl_len; + uint8_t dsc_list[BTHH_MAX_DSC_LEN]; +} bthh_hid_info_t; + +/** Callback for connection state change. + * state will have one of the values from bthh_connection_state_t + */ +typedef void (* bthh_connection_state_callback)(bt_bdaddr_t *bd_addr, bthh_connection_state_t state); + +/** Callback for vitual unplug api. + * the status of the vitual unplug + */ +typedef void (* bthh_virtual_unplug_callback)(bt_bdaddr_t *bd_addr, bthh_status_t hh_status); + +/** Callback for get hid info + * hid_info will contain attr_mask, sub_class, app_id, vendor_id, product_id, version, ctry_code, len + */ +typedef void (* bthh_hid_info_callback)(bt_bdaddr_t *bd_addr, bthh_hid_info_t hid_info); + +/** Callback for get/set protocal api. + * the protocol mode is one of the value from bthh_protocol_mode_t + */ +typedef void (* bthh_protocol_mode_callback)(bt_bdaddr_t *bd_addr, bthh_status_t hh_status,bthh_protocol_mode_t mode); + +/** Callback for get/set_idle_time api. + */ +typedef void (* bthh_idle_time_callback)(bt_bdaddr_t *bd_addr, bthh_status_t hh_status, int idle_rate); + + +/** Callback for get report api. + * if staus is ok rpt_data contains the report data + */ +typedef void (* bthh_get_report_callback)(bt_bdaddr_t *bd_addr, bthh_status_t hh_status, uint8_t* rpt_data, int rpt_size); + + +/** BT-HH callback structure. */ +typedef struct { + /** set to sizeof(BtHfCallbacks) */ + size_t size; + bthh_connection_state_callback connection_state_cb; + bthh_hid_info_callback hid_info_cb; + bthh_protocol_mode_callback protocol_mode_cb; + bthh_idle_time_callback idle_time_cb; + bthh_get_report_callback get_report_cb; + bthh_virtual_unplug_callback virtual_unplug_cb; + +} bthh_callbacks_t; + + + +/** Represents the standard BT-HH interface. */ +typedef struct { + + /** set to sizeof(BtHhInterface) */ + size_t size; + + /** + * Register the BtHh callbacks + */ + bt_status_t (*init)( bthh_callbacks_t* callbacks ); + + /** connect to hid device */ + bt_status_t (*connect)( bt_bdaddr_t *bd_addr); + + /** dis-connect from hid device */ + bt_status_t (*disconnect)( bt_bdaddr_t *bd_addr ); + + /** Virtual UnPlug (VUP) the specified HID device */ + bt_status_t (*virtual_unplug)(bt_bdaddr_t *bd_addr); + + /** Set the HID device descriptor for the specified HID device. */ + bt_status_t (*set_info)(bt_bdaddr_t *bd_addr, bthh_hid_info_t hid_info ); + + /** Get the HID proto mode. */ + bt_status_t (*get_protocol) (bt_bdaddr_t *bd_addr, bthh_protocol_mode_t protocolMode); + + /** Set the HID proto mode. */ + bt_status_t (*set_protocol)(bt_bdaddr_t *bd_addr, bthh_protocol_mode_t protocolMode); + + /** Send a GET_REPORT to HID device. */ + bt_status_t (*get_report)(bt_bdaddr_t *bd_addr, bthh_report_type_t reportType, uint8_t reportId, int bufferSize); + + /** Send a SET_REPORT to HID device. */ + bt_status_t (*set_report)(bt_bdaddr_t *bd_addr, bthh_report_type_t reportType, char* report); + + /** Send data to HID device. */ + bt_status_t (*send_data)(bt_bdaddr_t *bd_addr, char* data); + + /** Closes the interface. */ + void (*cleanup)( void ); + +} bthh_interface_t; +__END_DECLS + +#endif /* ANDROID_INCLUDE_BT_HH_H */ + + diff -Nru android-tools-4.2.2+git20130218/libhardware/include/hardware/bt_hl.h android-tools-4.2.2+git20130529/libhardware/include/hardware/bt_hl.h --- android-tools-4.2.2+git20130218/libhardware/include/hardware/bt_hl.h 1970-01-01 00:00:00.000000000 +0000 +++ android-tools-4.2.2+git20130529/libhardware/include/hardware/bt_hl.h 2013-05-29 20:16:54.000000000 +0000 @@ -0,0 +1,123 @@ +/* + * Copyright (C) 2012 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 ANDROID_INCLUDE_BT_HL_H +#define ANDROID_INCLUDE_BT_HL_H + +__BEGIN_DECLS + +/* HL connection states */ + +typedef enum +{ + BTHL_MDEP_ROLE_SOURCE, + BTHL_MDEP_ROLE_SINK +} bthl_mdep_role_t; + +typedef enum { + BTHL_APP_REG_STATE_REG_SUCCESS, + BTHL_APP_REG_STATE_REG_FAILED, + BTHL_APP_REG_STATE_DEREG_SUCCESS, + BTHL_APP_REG_STATE_DEREG_FAILED +} bthl_app_reg_state_t; + +typedef enum +{ + BTHL_CHANNEL_TYPE_RELIABLE, + BTHL_CHANNEL_TYPE_STREAMING, + BTHL_CHANNEL_TYPE_ANY +} bthl_channel_type_t; + + +/* HL connection states */ +typedef enum { + BTHL_CONN_STATE_CONNECTING, + BTHL_CONN_STATE_CONNECTED, + BTHL_CONN_STATE_DISCONNECTING, + BTHL_CONN_STATE_DISCONNECTED, + BTHL_CONN_STATE_DESTROYED +} bthl_channel_state_t; + +typedef struct +{ + bthl_mdep_role_t mdep_role; + int data_type; + bthl_channel_type_t channel_type; + const char *mdep_description; /* MDEP description to be used in the SDP (optional); null terminated */ +} bthl_mdep_cfg_t; + +typedef struct +{ + const char *application_name; + const char *provider_name; /* provider name to be used in the SDP (optional); null terminated */ + const char *srv_name; /* service name to be used in the SDP (optional); null terminated*/ + const char *srv_desp; /* service description to be used in the SDP (optional); null terminated */ + int number_of_mdeps; + bthl_mdep_cfg_t *mdep_cfg; /* Dynamic array */ +} bthl_reg_param_t; + +/** Callback for application registration status. + * state will have one of the values from bthl_app_reg_state_t + */ +typedef void (* bthl_app_reg_state_callback)(int app_id, bthl_app_reg_state_t state); + +/** Callback for channel connection state change. + * state will have one of the values from + * bthl_connection_state_t and fd (file descriptor) + */ +typedef void (* bthl_channel_state_callback)(int app_id, bt_bdaddr_t *bd_addr, int mdep_cfg_index, int channel_id, bthl_channel_state_t state, int fd); + +/** BT-HL callback structure. */ +typedef struct { + /** set to sizeof(bthl_callbacks_t) */ + size_t size; + bthl_app_reg_state_callback app_reg_state_cb; + bthl_channel_state_callback channel_state_cb; +} bthl_callbacks_t; + + +/** Represents the standard BT-HL interface. */ +typedef struct { + + /** set to sizeof(bthl_interface_t) */ + size_t size; + + /** + * Register the Bthl callbacks + */ + bt_status_t (*init)( bthl_callbacks_t* callbacks ); + + /** Register HL application */ + bt_status_t (*register_application) ( bthl_reg_param_t *p_reg_param, int *app_id); + + /** Unregister HL application */ + bt_status_t (*unregister_application) (int app_id); + + /** connect channel */ + bt_status_t (*connect_channel)(int app_id, bt_bdaddr_t *bd_addr, int mdep_cfg_index, int *channel_id); + + /** destroy channel */ + bt_status_t (*destroy_channel)(int channel_id); + + /** Close the Bthl callback **/ + void (*cleanup)(void); + +} bthl_interface_t; +__END_DECLS + +#endif /* ANDROID_INCLUDE_BT_HL_H */ + + diff -Nru android-tools-4.2.2+git20130218/libhardware/include/hardware/bt_pan.h android-tools-4.2.2+git20130529/libhardware/include/hardware/bt_pan.h --- android-tools-4.2.2+git20130218/libhardware/include/hardware/bt_pan.h 1970-01-01 00:00:00.000000000 +0000 +++ android-tools-4.2.2+git20130529/libhardware/include/hardware/bt_pan.h 2013-05-29 20:16:54.000000000 +0000 @@ -0,0 +1,87 @@ +/* + * Copyright (C) 2012 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 ANDROID_INCLUDE_BT_PAN_H +#define ANDROID_INCLUDE_BT_PAN_H + +__BEGIN_DECLS + +#define BTPAN_ROLE_NONE 0 +#define BTPAN_ROLE_PANNAP 1 +#define BTPAN_ROLE_PANU 2 + +typedef enum { + BTPAN_STATE_CONNECTED = 0, + BTPAN_STATE_CONNECTING = 1, + BTPAN_STATE_DISCONNECTED = 2, + BTPAN_STATE_DISCONNECTING = 3 +} btpan_connection_state_t; + +typedef enum { + BTPAN_STATE_ENABLED = 0, + BTPAN_STATE_DISABLED = 1 +} btpan_control_state_t; + +/** +* Callback for pan connection state +*/ +typedef void (*btpan_connection_state_callback)(btpan_connection_state_t state, bt_status_t error, + const bt_bdaddr_t *bd_addr, int local_role, int remote_role); +typedef void (*btpan_control_state_callback)(btpan_control_state_t state, bt_status_t error, + int local_role, const char* ifname); + +typedef struct { + size_t size; + btpan_control_state_callback control_state_cb; + btpan_connection_state_callback connection_state_cb; +} btpan_callbacks_t; +typedef struct { + /** set to size of this struct*/ + size_t size; + /** + * Initialize the pan interface and register the btpan callbacks + */ + bt_status_t (*init)(const btpan_callbacks_t* callbacks); + /* + * enable the pan service by specified role. The result state of + * enabl will be returned by btpan_control_state_callback. when pan-nap is enabled, + * the state of connecting panu device will be notified by btpan_connection_state_callback + */ + bt_status_t (*enable)(int local_role); + /* + * get current pan local role + */ + int (*get_local_role)(void); + /** + * start bluetooth pan connection to the remote device by specified pan role. The result state will be + * returned by btpan_connection_state_callback + */ + bt_status_t (*connect)(const bt_bdaddr_t *bd_addr, int local_role, int remote_role); + /** + * stop bluetooth pan connection. The result state will be returned by btpan_connection_state_callback + */ + bt_status_t (*disconnect)(const bt_bdaddr_t *bd_addr); + + /** + * Cleanup the pan interface + */ + void (*cleanup)(void); + +} btpan_interface_t; + +__END_DECLS + +#endif /* ANDROID_INCLUDE_BT_PAN_H */ diff -Nru android-tools-4.2.2+git20130218/libhardware/include/hardware/bt_sock.h android-tools-4.2.2+git20130529/libhardware/include/hardware/bt_sock.h --- android-tools-4.2.2+git20130218/libhardware/include/hardware/bt_sock.h 1970-01-01 00:00:00.000000000 +0000 +++ android-tools-4.2.2+git20130529/libhardware/include/hardware/bt_sock.h 2013-05-29 20:16:54.000000000 +0000 @@ -0,0 +1,58 @@ +/* + * Copyright (C) 2012 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 ANDROID_INCLUDE_BT_SOCK_H +#define ANDROID_INCLUDE_BT_SOCK_H + +__BEGIN_DECLS + +#define BTSOCK_FLAG_ENCRYPT 1 +#define BTSOCK_FLAG_AUTH (1 << 1) + +typedef enum { + BTSOCK_RFCOMM = 1, + BTSOCK_SCO = 2, + BTSOCK_L2CAP = 3 +} btsock_type_t; + +/** Represents the standard BT SOCKET interface. */ +typedef struct { + short size; + bt_bdaddr_t bd_addr; + int channel; + int status; +} __attribute__((packed)) sock_connect_signal_t; + +typedef struct { + + /** set to size of this struct*/ + size_t size; + /** + * listen to a rfcomm uuid or channel. It returns the socket fd from which + * btsock_connect_signal can be read out when a remote device connected + */ + bt_status_t (*listen)(btsock_type_t type, const char* service_name, const uint8_t* service_uuid, int channel, int* sock_fd, int flags); + /* + * connect to a rfcomm uuid channel of remote device, It returns the socket fd from which + * the btsock_connect_signal and a new socket fd to be accepted can be read out when connected + */ + bt_status_t (*connect)(const bt_bdaddr_t *bd_addr, btsock_type_t type, const uint8_t* uuid, int channel, int* sock_fd, int flags); + +} btsock_interface_t; + +__END_DECLS + +#endif /* ANDROID_INCLUDE_BT_SOCK_H */ diff -Nru android-tools-4.2.2+git20130218/libhardware/include/hardware/camera2.h android-tools-4.2.2+git20130529/libhardware/include/hardware/camera2.h --- android-tools-4.2.2+git20130218/libhardware/include/hardware/camera2.h 1970-01-01 00:00:00.000000000 +0000 +++ android-tools-4.2.2+git20130529/libhardware/include/hardware/camera2.h 2013-05-29 20:16:54.000000000 +0000 @@ -0,0 +1,808 @@ +/* + * Copyright (C) 2012 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 ANDROID_INCLUDE_CAMERA2_H +#define ANDROID_INCLUDE_CAMERA2_H + +#include "camera_common.h" +#include "system/camera_metadata.h" + +/** + * Camera device HAL 2.0 [ CAMERA_DEVICE_API_VERSION_2_0 ] + * + * EXPERIMENTAL. + * + * Supports both the android.hardware.ProCamera and + * android.hardware.Camera APIs. + * + * Camera devices that support this version of the HAL must return + * CAMERA_DEVICE_API_VERSION_2_0 in camera_device_t.common.version and in + * camera_info_t.device_version (from camera_module_t.get_camera_info). + * + * Camera modules that may contain version 2.0 devices must implement at least + * version 2.0 of the camera module interface (as defined by + * camera_module_t.common.module_api_version). + * + * See camera_common.h for more versioning details. + * + */ + +__BEGIN_DECLS + +struct camera2_device; + +/********************************************************************** + * + * Input/output stream buffer queue interface definitions + * + */ + +/** + * Output image stream queue interface. A set of these methods is provided to + * the HAL device in allocate_stream(), and are used to interact with the + * gralloc buffer queue for that stream. They may not be called until after + * allocate_stream returns. + */ +typedef struct camera2_stream_ops { + /** + * Get a buffer to fill from the queue. The size and format of the buffer + * are fixed for a given stream (defined in allocate_stream), and the stride + * should be queried from the platform gralloc module. The gralloc buffer + * will have been allocated based on the usage flags provided by + * allocate_stream, and will be locked for use. + */ + int (*dequeue_buffer)(const struct camera2_stream_ops* w, + buffer_handle_t** buffer); + + /** + * Push a filled buffer to the stream to be used by the consumer. + * + * The timestamp represents the time at start of exposure of the first row + * of the image; it must be from a monotonic clock, and is measured in + * nanoseconds. The timestamps do not need to be comparable between + * different cameras, or consecutive instances of the same camera. However, + * they must be comparable between streams from the same camera. If one + * capture produces buffers for multiple streams, each stream must have the + * same timestamp for that buffer, and that timestamp must match the + * timestamp in the output frame metadata. + */ + int (*enqueue_buffer)(const struct camera2_stream_ops* w, + int64_t timestamp, + buffer_handle_t* buffer); + /** + * Return a buffer to the queue without marking it as filled. + */ + int (*cancel_buffer)(const struct camera2_stream_ops* w, + buffer_handle_t* buffer); + /** + * Set the crop window for subsequently enqueued buffers. The parameters are + * measured in pixels relative to the buffer width and height. + */ + int (*set_crop)(const struct camera2_stream_ops *w, + int left, int top, int right, int bottom); + +} camera2_stream_ops_t; + +/** + * Temporary definition during transition. + * + * These formats will be removed and replaced with + * HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED. To maximize forward compatibility, + * HAL implementations are strongly recommended to treat FORMAT_OPAQUE and + * FORMAT_ZSL as equivalent to HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED, and + * return HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED in the format_actual output + * parameter of allocate_stream, allowing the gralloc module to select the + * specific format based on the usage flags from the camera and the stream + * consumer. + */ +enum { + CAMERA2_HAL_PIXEL_FORMAT_OPAQUE = HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED, + CAMERA2_HAL_PIXEL_FORMAT_ZSL = -1 +}; + +/** + * Transport header for compressed JPEG buffers in output streams. + * + * To capture JPEG images, a stream is created using the pixel format + * HAL_PIXEL_FORMAT_BLOB, and the static metadata field android.jpeg.maxSize is + * used as the buffer size. Since compressed JPEG images are of variable size, + * the HAL needs to include the final size of the compressed image using this + * structure inside the output stream buffer. The JPEG blob ID field must be set + * to CAMERA2_JPEG_BLOB_ID. + * + * Transport header should be at the end of the JPEG output stream buffer. That + * means the jpeg_blob_id must start at byte[android.jpeg.maxSize - + * sizeof(camera2_jpeg_blob)]. Any HAL using this transport header must + * account for it in android.jpeg.maxSize. The JPEG data itself starts at + * byte[0] and should be jpeg_size bytes long. + */ +typedef struct camera2_jpeg_blob { + uint16_t jpeg_blob_id; + uint32_t jpeg_size; +}; + +enum { + CAMERA2_JPEG_BLOB_ID = 0x00FF +}; + +/** + * Input reprocess stream queue management. A set of these methods is provided + * to the HAL device in allocate_reprocess_stream(); they are used to interact + * with the reprocess stream's input gralloc buffer queue. + */ +typedef struct camera2_stream_in_ops { + /** + * Get the next buffer of image data to reprocess. The width, height, and + * format of the buffer is fixed in allocate_reprocess_stream(), and the + * stride and other details should be queried from the platform gralloc + * module as needed. The buffer will already be locked for use. + */ + int (*acquire_buffer)(const struct camera2_stream_in_ops *w, + buffer_handle_t** buffer); + /** + * Return a used buffer to the buffer queue for reuse. + */ + int (*release_buffer)(const struct camera2_stream_in_ops *w, + buffer_handle_t* buffer); + +} camera2_stream_in_ops_t; + +/********************************************************************** + * + * Metadata queue management, used for requests sent to HAL module, and for + * frames produced by the HAL. + * + */ + +enum { + CAMERA2_REQUEST_QUEUE_IS_BOTTOMLESS = -1 +}; + +/** + * Request input queue protocol: + * + * The framework holds the queue and its contents. At start, the queue is empty. + * + * 1. When the first metadata buffer is placed into the queue, the framework + * signals the device by calling notify_request_queue_not_empty(). + * + * 2. After receiving notify_request_queue_not_empty, the device must call + * dequeue() once it's ready to handle the next buffer. + * + * 3. Once the device has processed a buffer, and is ready for the next buffer, + * it must call dequeue() again instead of waiting for a notification. If + * there are no more buffers available, dequeue() will return NULL. After + * this point, when a buffer becomes available, the framework must call + * notify_request_queue_not_empty() again. If the device receives a NULL + * return from dequeue, it does not need to query the queue again until a + * notify_request_queue_not_empty() call is received from the source. + * + * 4. If the device calls buffer_count() and receives 0, this does not mean that + * the framework will provide a notify_request_queue_not_empty() call. The + * framework will only provide such a notification after the device has + * received a NULL from dequeue, or on initial startup. + * + * 5. The dequeue() call in response to notify_request_queue_not_empty() may be + * on the same thread as the notify_request_queue_not_empty() call, and may + * be performed from within the notify call. + * + * 6. All dequeued request buffers must be returned to the framework by calling + * free_request, including when errors occur, a device flush is requested, or + * when the device is shutting down. + */ +typedef struct camera2_request_queue_src_ops { + /** + * Get the count of request buffers pending in the queue. May return + * CAMERA2_REQUEST_QUEUE_IS_BOTTOMLESS if a repeating request (stream + * request) is currently configured. Calling this method has no effect on + * whether the notify_request_queue_not_empty() method will be called by the + * framework. + */ + int (*request_count)(const struct camera2_request_queue_src_ops *q); + + /** + * Get a metadata buffer from the framework. Returns OK if there is no + * error. If the queue is empty, returns NULL in buffer. In that case, the + * device must wait for a notify_request_queue_not_empty() message before + * attempting to dequeue again. Buffers obtained in this way must be + * returned to the framework with free_request(). + */ + int (*dequeue_request)(const struct camera2_request_queue_src_ops *q, + camera_metadata_t **buffer); + /** + * Return a metadata buffer to the framework once it has been used, or if + * an error or shutdown occurs. + */ + int (*free_request)(const struct camera2_request_queue_src_ops *q, + camera_metadata_t *old_buffer); + +} camera2_request_queue_src_ops_t; + +/** + * Frame output queue protocol: + * + * The framework holds the queue and its contents. At start, the queue is empty. + * + * 1. When the device is ready to fill an output metadata frame, it must dequeue + * a metadata buffer of the required size. + * + * 2. It should then fill the metadata buffer, and place it on the frame queue + * using enqueue_frame. The framework takes ownership of the frame. + * + * 3. In case of an error, a request to flush the pipeline, or shutdown, the + * device must return any affected dequeued frames to the framework by + * calling cancel_frame. + */ +typedef struct camera2_frame_queue_dst_ops { + /** + * Get an empty metadata buffer to fill from the framework. The new metadata + * buffer will have room for entries number of metadata entries, plus + * data_bytes worth of extra storage. Frames dequeued here must be returned + * to the framework with either cancel_frame or enqueue_frame. + */ + int (*dequeue_frame)(const struct camera2_frame_queue_dst_ops *q, + size_t entries, size_t data_bytes, + camera_metadata_t **buffer); + + /** + * Return a dequeued metadata buffer to the framework for reuse; do not mark it as + * filled. Use when encountering errors, or flushing the internal request queue. + */ + int (*cancel_frame)(const struct camera2_frame_queue_dst_ops *q, + camera_metadata_t *buffer); + + /** + * Place a completed metadata frame on the frame output queue. + */ + int (*enqueue_frame)(const struct camera2_frame_queue_dst_ops *q, + camera_metadata_t *buffer); + +} camera2_frame_queue_dst_ops_t; + +/********************************************************************** + * + * Notification callback and message definition, and trigger definitions + * + */ + +/** + * Asynchronous notification callback from the HAL, fired for various + * reasons. Only for information independent of frame capture, or that require + * specific timing. The user pointer must be the same one that was passed to the + * device in set_notify_callback(). + */ +typedef void (*camera2_notify_callback)(int32_t msg_type, + int32_t ext1, + int32_t ext2, + int32_t ext3, + void *user); + +/** + * Possible message types for camera2_notify_callback + */ +enum { + /** + * An error has occurred. Argument ext1 contains the error code, and + * ext2 and ext3 contain any error-specific information. + */ + CAMERA2_MSG_ERROR = 0x0001, + /** + * The exposure of a given request has begun. Argument ext1 contains the + * frame number, and ext2 and ext3 contain the low-order and high-order + * bytes of the timestamp for when exposure began. + * (timestamp = (ext3 << 32 | ext2)) + */ + CAMERA2_MSG_SHUTTER = 0x0010, + /** + * The autofocus routine has changed state. Argument ext1 contains the new + * state; the values are the same as those for the metadata field + * android.control.afState. Ext2 contains the latest trigger ID passed to + * trigger_action(CAMERA2_TRIGGER_AUTOFOCUS) or + * trigger_action(CAMERA2_TRIGGER_CANCEL_AUTOFOCUS), or 0 if trigger has not + * been called with either of those actions. + */ + CAMERA2_MSG_AUTOFOCUS = 0x0020, + /** + * The autoexposure routine has changed state. Argument ext1 contains the + * new state; the values are the same as those for the metadata field + * android.control.aeState. Ext2 contains the latest trigger ID value passed to + * trigger_action(CAMERA2_TRIGGER_PRECAPTURE_METERING), or 0 if that method + * has not been called. + */ + CAMERA2_MSG_AUTOEXPOSURE = 0x0021, + /** + * The auto-whitebalance routine has changed state. Argument ext1 contains + * the new state; the values are the same as those for the metadata field + * android.control.awbState. Ext2 contains the latest trigger ID passed to + * trigger_action(CAMERA2_TRIGGER_PRECAPTURE_METERING), or 0 if that method + * has not been called. + */ + CAMERA2_MSG_AUTOWB = 0x0022 +}; + +/** + * Error codes for CAMERA_MSG_ERROR + */ +enum { + /** + * A serious failure occured. Camera device may not work without reboot, and + * no further frames or buffer streams will be produced by the + * device. Device should be treated as closed. + */ + CAMERA2_MSG_ERROR_HARDWARE = 0x0001, + /** + * A serious failure occured. No further frames or buffer streams will be + * produced by the device. Device should be treated as closed. The client + * must reopen the device to use it again. + */ + CAMERA2_MSG_ERROR_DEVICE, + /** + * An error has occurred in processing a request. No output (metadata or + * buffers) will be produced for this request. ext2 contains the frame + * number of the request. Subsequent requests are unaffected, and the device + * remains operational. + */ + CAMERA2_MSG_ERROR_REQUEST, + /** + * An error has occurred in producing an output frame metadata buffer for a + * request, but image buffers for it will still be available. Subsequent + * requests are unaffected, and the device remains operational. ext2 + * contains the frame number of the request. + */ + CAMERA2_MSG_ERROR_FRAME, + /** + * An error has occurred in placing an output buffer into a stream for a + * request. The frame metadata and other buffers may still be + * available. Subsequent requests are unaffected, and the device remains + * operational. ext2 contains the frame number of the request, and ext3 + * contains the stream id. + */ + CAMERA2_MSG_ERROR_STREAM, + /** + * Number of error types + */ + CAMERA2_MSG_NUM_ERRORS +}; + +/** + * Possible trigger ids for trigger_action() + */ +enum { + /** + * Trigger an autofocus cycle. The effect of the trigger depends on the + * autofocus mode in effect when the trigger is received, which is the mode + * listed in the latest capture request to be dequeued by the HAL. If the + * mode is OFF, EDOF, or FIXED, the trigger has no effect. In AUTO, MACRO, + * or CONTINUOUS_* modes, see below for the expected behavior. The state of + * the autofocus cycle can be tracked in android.control.afMode and the + * corresponding notifications. + * + ** + * In AUTO or MACRO mode, the AF state transitions (and notifications) + * when calling with trigger ID = N with the previous ID being K are: + * + * Initial state Transitions + * INACTIVE (K) -> ACTIVE_SCAN (N) -> AF_FOCUSED (N) or AF_NOT_FOCUSED (N) + * AF_FOCUSED (K) -> ACTIVE_SCAN (N) -> AF_FOCUSED (N) or AF_NOT_FOCUSED (N) + * AF_NOT_FOCUSED (K) -> ACTIVE_SCAN (N) -> AF_FOCUSED (N) or AF_NOT_FOCUSED (N) + * ACTIVE_SCAN (K) -> AF_FOCUSED(N) or AF_NOT_FOCUSED(N) + * PASSIVE_SCAN (K) Not used in AUTO/MACRO mode + * PASSIVE_FOCUSED (K) Not used in AUTO/MACRO mode + * + ** + * In CONTINUOUS_PICTURE mode, triggering AF must lock the AF to the current + * lens position and transition the AF state to either AF_FOCUSED or + * NOT_FOCUSED. If a passive scan is underway, that scan must complete and + * then lock the lens position and change AF state. TRIGGER_CANCEL_AUTOFOCUS + * will allow the AF to restart its operation. + * + * Initial state Transitions + * INACTIVE (K) -> immediate AF_FOCUSED (N) or AF_NOT_FOCUSED (N) + * PASSIVE_FOCUSED (K) -> immediate AF_FOCUSED (N) or AF_NOT_FOCUSED (N) + * PASSIVE_SCAN (K) -> AF_FOCUSED (N) or AF_NOT_FOCUSED (N) + * AF_FOCUSED (K) no effect except to change next notification ID to N + * AF_NOT_FOCUSED (K) no effect except to change next notification ID to N + * + ** + * In CONTINUOUS_VIDEO mode, triggering AF must lock the AF to the current + * lens position and transition the AF state to either AF_FOCUSED or + * NOT_FOCUSED. If a passive scan is underway, it must immediately halt, in + * contrast with CONTINUOUS_PICTURE mode. TRIGGER_CANCEL_AUTOFOCUS will + * allow the AF to restart its operation. + * + * Initial state Transitions + * INACTIVE (K) -> immediate AF_FOCUSED (N) or AF_NOT_FOCUSED (N) + * PASSIVE_FOCUSED (K) -> immediate AF_FOCUSED (N) or AF_NOT_FOCUSED (N) + * PASSIVE_SCAN (K) -> immediate AF_FOCUSED (N) or AF_NOT_FOCUSED (N) + * AF_FOCUSED (K) no effect except to change next notification ID to N + * AF_NOT_FOCUSED (K) no effect except to change next notification ID to N + * + * Ext1 is an ID that must be returned in subsequent auto-focus state change + * notifications through camera2_notify_callback() and stored in + * android.control.afTriggerId. + */ + CAMERA2_TRIGGER_AUTOFOCUS = 0x0001, + /** + * Send a cancel message to the autofocus algorithm. The effect of the + * cancellation depends on the autofocus mode in effect when the trigger is + * received, which is the mode listed in the latest capture request to be + * dequeued by the HAL. If the AF mode is OFF or EDOF, the cancel has no + * effect. For other modes, the lens should return to its default position, + * any current autofocus scan must be canceled, and the AF state should be + * set to INACTIVE. + * + * The state of the autofocus cycle can be tracked in android.control.afMode + * and the corresponding notification. Continuous autofocus modes may resume + * focusing operations thereafter exactly as if the camera had just been set + * to a continuous AF mode. + * + * Ext1 is an ID that must be returned in subsequent auto-focus state change + * notifications through camera2_notify_callback() and stored in + * android.control.afTriggerId. + */ + CAMERA2_TRIGGER_CANCEL_AUTOFOCUS, + /** + * Trigger a pre-capture metering cycle, which may include firing the flash + * to determine proper capture parameters. Typically, this trigger would be + * fired for a half-depress of a camera shutter key, or before a snapshot + * capture in general. The state of the metering cycle can be tracked in + * android.control.aeMode and the corresponding notification. If the + * auto-exposure mode is OFF, the trigger does nothing. + * + * Ext1 is an ID that must be returned in subsequent + * auto-exposure/auto-white balance state change notifications through + * camera2_notify_callback() and stored in android.control.aePrecaptureId. + */ + CAMERA2_TRIGGER_PRECAPTURE_METERING +}; + +/** + * Possible template types for construct_default_request() + */ +enum { + /** + * Standard camera preview operation with 3A on auto. + */ + CAMERA2_TEMPLATE_PREVIEW = 1, + /** + * Standard camera high-quality still capture with 3A and flash on auto. + */ + CAMERA2_TEMPLATE_STILL_CAPTURE, + /** + * Standard video recording plus preview with 3A on auto, torch off. + */ + CAMERA2_TEMPLATE_VIDEO_RECORD, + /** + * High-quality still capture while recording video. Application will + * include preview, video record, and full-resolution YUV or JPEG streams in + * request. Must not cause stuttering on video stream. 3A on auto. + */ + CAMERA2_TEMPLATE_VIDEO_SNAPSHOT, + /** + * Zero-shutter-lag mode. Application will request preview and + * full-resolution data for each frame, and reprocess it to JPEG when a + * still image is requested by user. Settings should provide highest-quality + * full-resolution images without compromising preview frame rate. 3A on + * auto. + */ + CAMERA2_TEMPLATE_ZERO_SHUTTER_LAG, + + /* Total number of templates */ + CAMERA2_TEMPLATE_COUNT +}; + + +/********************************************************************** + * + * Camera device operations + * + */ +typedef struct camera2_device_ops { + + /********************************************************************** + * Request and frame queue setup and management methods + */ + + /** + * Pass in input request queue interface methods. + */ + int (*set_request_queue_src_ops)(const struct camera2_device *, + const camera2_request_queue_src_ops_t *request_src_ops); + + /** + * Notify device that the request queue is no longer empty. Must only be + * called when the first buffer is added a new queue, or after the source + * has returned NULL in response to a dequeue call. + */ + int (*notify_request_queue_not_empty)(const struct camera2_device *); + + /** + * Pass in output frame queue interface methods + */ + int (*set_frame_queue_dst_ops)(const struct camera2_device *, + const camera2_frame_queue_dst_ops_t *frame_dst_ops); + + /** + * Number of camera requests being processed by the device at the moment + * (captures/reprocesses that have had their request dequeued, but have not + * yet been enqueued onto output pipeline(s) ). No streams may be released + * by the framework until the in-progress count is 0. + */ + int (*get_in_progress_count)(const struct camera2_device *); + + /** + * Flush all in-progress captures. This includes all dequeued requests + * (regular or reprocessing) that have not yet placed any outputs into a + * stream or the frame queue. Partially completed captures must be completed + * normally. No new requests may be dequeued from the request queue until + * the flush completes. + */ + int (*flush_captures_in_progress)(const struct camera2_device *); + + /** + * Create a filled-in default request for standard camera use cases. + * + * The device must return a complete request that is configured to meet the + * requested use case, which must be one of the CAMERA2_TEMPLATE_* + * enums. All request control fields must be included, except for + * android.request.outputStreams. + * + * The metadata buffer returned must be allocated with + * allocate_camera_metadata. The framework takes ownership of the buffer. + */ + int (*construct_default_request)(const struct camera2_device *, + int request_template, + camera_metadata_t **request); + + /********************************************************************** + * Stream management + */ + + /** + * allocate_stream: + * + * Allocate a new output stream for use, defined by the output buffer width, + * height, target, and possibly the pixel format. Returns the new stream's + * ID, gralloc usage flags, minimum queue buffer count, and possibly the + * pixel format, on success. Error conditions: + * + * - Requesting a width/height/format combination not listed as + * supported by the sensor's static characteristics + * + * - Asking for too many streams of a given format type (2 bayer raw + * streams, for example). + * + * Input parameters: + * + * - width, height, format: Specification for the buffers to be sent through + * this stream. Format is a value from the HAL_PIXEL_FORMAT_* list. If + * HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED is used, then the platform + * gralloc module will select a format based on the usage flags provided + * by the camera HAL and the consumer of the stream. The camera HAL should + * inspect the buffers handed to it in the register_stream_buffers call to + * obtain the implementation-specific format if necessary. + * + * - stream_ops: A structure of function pointers for obtaining and queuing + * up buffers for this stream. The underlying stream will be configured + * based on the usage and max_buffers outputs. The methods in this + * structure may not be called until after allocate_stream returns. + * + * Output parameters: + * + * - stream_id: An unsigned integer identifying this stream. This value is + * used in incoming requests to identify the stream, and in releasing the + * stream. + * + * - usage: The gralloc usage mask needed by the HAL device for producing + * the requested type of data. This is used in allocating new gralloc + * buffers for the stream buffer queue. + * + * - max_buffers: The maximum number of buffers the HAL device may need to + * have dequeued at the same time. The device may not dequeue more buffers + * than this value at the same time. + * + */ + int (*allocate_stream)( + const struct camera2_device *, + // inputs + uint32_t width, + uint32_t height, + int format, + const camera2_stream_ops_t *stream_ops, + // outputs + uint32_t *stream_id, + uint32_t *format_actual, // IGNORED, will be removed + uint32_t *usage, + uint32_t *max_buffers); + + /** + * Register buffers for a given stream. This is called after a successful + * allocate_stream call, and before the first request referencing the stream + * is enqueued. This method is intended to allow the HAL device to map or + * otherwise prepare the buffers for later use. num_buffers is guaranteed to + * be at least max_buffers (from allocate_stream), but may be larger. The + * buffers will already be locked for use. At the end of the call, all the + * buffers must be ready to be returned to the queue. If the stream format + * was set to HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED, the camera HAL should + * inspect the passed-in buffers here to determine any platform-private + * pixel format information. + */ + int (*register_stream_buffers)( + const struct camera2_device *, + uint32_t stream_id, + int num_buffers, + buffer_handle_t *buffers); + + /** + * Release a stream. Returns an error if called when get_in_progress_count + * is non-zero, or if the stream id is invalid. + */ + int (*release_stream)( + const struct camera2_device *, + uint32_t stream_id); + + /** + * allocate_reprocess_stream: + * + * Allocate a new input stream for use, defined by the output buffer width, + * height, and the pixel format. Returns the new stream's ID, gralloc usage + * flags, and required simultaneously acquirable buffer count, on + * success. Error conditions: + * + * - Requesting a width/height/format combination not listed as + * supported by the sensor's static characteristics + * + * - Asking for too many reprocessing streams to be configured at once. + * + * Input parameters: + * + * - width, height, format: Specification for the buffers to be sent through + * this stream. Format must be a value from the HAL_PIXEL_FORMAT_* list. + * + * - reprocess_stream_ops: A structure of function pointers for acquiring + * and releasing buffers for this stream. The underlying stream will be + * configured based on the usage and max_buffers outputs. + * + * Output parameters: + * + * - stream_id: An unsigned integer identifying this stream. This value is + * used in incoming requests to identify the stream, and in releasing the + * stream. These ids are numbered separately from the input stream ids. + * + * - consumer_usage: The gralloc usage mask needed by the HAL device for + * consuming the requested type of data. This is used in allocating new + * gralloc buffers for the stream buffer queue. + * + * - max_buffers: The maximum number of buffers the HAL device may need to + * have acquired at the same time. The device may not have more buffers + * acquired at the same time than this value. + * + */ + int (*allocate_reprocess_stream)(const struct camera2_device *, + uint32_t width, + uint32_t height, + uint32_t format, + const camera2_stream_in_ops_t *reprocess_stream_ops, + // outputs + uint32_t *stream_id, + uint32_t *consumer_usage, + uint32_t *max_buffers); + + /** + * allocate_reprocess_stream_from_stream: + * + * Allocate a new input stream for use, which will use the buffers allocated + * for an existing output stream. That is, after the HAL enqueues a buffer + * onto the output stream, it may see that same buffer handed to it from + * this input reprocessing stream. After the HAL releases the buffer back to + * the reprocessing stream, it will be returned to the output queue for + * reuse. + * + * Error conditions: + * + * - Using an output stream of unsuitable size/format for the basis of the + * reprocessing stream. + * + * - Attempting to allocatee too many reprocessing streams at once. + * + * Input parameters: + * + * - output_stream_id: The ID of an existing output stream which has + * a size and format suitable for reprocessing. + * + * - reprocess_stream_ops: A structure of function pointers for acquiring + * and releasing buffers for this stream. The underlying stream will use + * the same graphics buffer handles as the output stream uses. + * + * Output parameters: + * + * - stream_id: An unsigned integer identifying this stream. This value is + * used in incoming requests to identify the stream, and in releasing the + * stream. These ids are numbered separately from the input stream ids. + * + * The HAL client must always release the reprocessing stream before it + * releases the output stream it is based on. + * + */ + int (*allocate_reprocess_stream_from_stream)(const struct camera2_device *, + uint32_t output_stream_id, + const camera2_stream_in_ops_t *reprocess_stream_ops, + // outputs + uint32_t *stream_id); + + /** + * Release a reprocessing stream. Returns an error if called when + * get_in_progress_count is non-zero, or if the stream id is not + * valid. + */ + int (*release_reprocess_stream)( + const struct camera2_device *, + uint32_t stream_id); + + /********************************************************************** + * Miscellaneous methods + */ + + /** + * Trigger asynchronous activity. This is used for triggering special + * behaviors of the camera 3A routines when they are in use. See the + * documentation for CAMERA2_TRIGGER_* above for details of the trigger ids + * and their arguments. + */ + int (*trigger_action)(const struct camera2_device *, + uint32_t trigger_id, + int32_t ext1, + int32_t ext2); + + /** + * Notification callback setup + */ + int (*set_notify_callback)(const struct camera2_device *, + camera2_notify_callback notify_cb, + void *user); + + /** + * Get methods to query for vendor extension metadata tag infomation. May + * set ops to NULL if no vendor extension tags are defined. + */ + int (*get_metadata_vendor_tag_ops)(const struct camera2_device*, + vendor_tag_query_ops_t **ops); + + /** + * Dump state of the camera hardware + */ + int (*dump)(const struct camera2_device *, int fd); + +} camera2_device_ops_t; + +/********************************************************************** + * + * Camera device definition + * + */ +typedef struct camera2_device { + /** + * common.version must equal CAMERA_DEVICE_API_VERSION_2_0 to identify + * this device as implementing version 2.0 of the camera device HAL. + */ + hw_device_t common; + camera2_device_ops_t *ops; + void *priv; +} camera2_device_t; + +__END_DECLS + +#endif /* #ifdef ANDROID_INCLUDE_CAMERA2_H */ diff -Nru android-tools-4.2.2+git20130218/libhardware/include/hardware/camera_common.h android-tools-4.2.2+git20130529/libhardware/include/hardware/camera_common.h --- android-tools-4.2.2+git20130218/libhardware/include/hardware/camera_common.h 1970-01-01 00:00:00.000000000 +0000 +++ android-tools-4.2.2+git20130529/libhardware/include/hardware/camera_common.h 2013-05-29 20:16:54.000000000 +0000 @@ -0,0 +1,166 @@ +/* + * Copyright (C) 2012 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. + */ + +// FIXME: add well-defined names for cameras + +#ifndef ANDROID_INCLUDE_CAMERA_COMMON_H +#define ANDROID_INCLUDE_CAMERA_COMMON_H + +#include +#include +#include +#include +#include +#include +#include + +__BEGIN_DECLS + +/** + * The id of this module + */ +#define CAMERA_HARDWARE_MODULE_ID "camera" + +/** + * Module versioning information for the Camera hardware module, based on + * camera_module_t.common.module_api_version. The two most significant hex + * digits represent the major version, and the two least significant represent + * the minor version. + * + ******************************************************************************* + * Versions: 0.X - 1.X [CAMERA_MODULE_API_VERSION_1_0] + * + * Camera modules that report these version numbers implement the initial + * camera module HAL interface. All camera devices openable through this + * module support only version 1 of the camera device HAL. The device_version + * and static_camera_characteristics fields of camera_info are not valid. Only + * the android.hardware.Camera API can be supported by this module and its + * devices. + * + ******************************************************************************* + * Version: 2.0 [CAMERA_MODULE_API_VERSION_2_0] + * + * Camera modules that report this version number implement the second version + * of the camera module HAL interface. Camera devices openable through this + * module may support either version 1.0 or version 2.0 of the camera device + * HAL interface. The device_version field of camera_info is always valid; the + * static_camera_characteristics field of camera_info is valid if the + * device_version field is 2.0 or higher. + */ + +/** + * Predefined macros for currently-defined version numbers + */ + +/** + * All module versions <= HARDWARE_MODULE_API_VERSION(1, 0xFF) must be treated + * as CAMERA_MODULE_API_VERSION_1_0 + */ +#define CAMERA_MODULE_API_VERSION_1_0 HARDWARE_MODULE_API_VERSION(1, 0) +#define CAMERA_MODULE_API_VERSION_2_0 HARDWARE_MODULE_API_VERSION(2, 0) + +#define CAMERA_MODULE_API_VERSION_CURRENT CAMERA_MODULE_API_VERSION_2_0 + +/** + * All device versions <= HARDWARE_DEVICE_API_VERSION(1, 0xFF) must be treated + * as CAMERA_DEVICE_API_VERSION_1_0 + */ +#define CAMERA_DEVICE_API_VERSION_1_0 HARDWARE_DEVICE_API_VERSION(1, 0) +#define CAMERA_DEVICE_API_VERSION_2_0 HARDWARE_DEVICE_API_VERSION(2, 0) + +// Device version 2.0 is experimental +#define CAMERA_DEVICE_API_VERSION_CURRENT CAMERA_DEVICE_API_VERSION_1_0 + +/** + * Defined in /system/media/camera/include/system/camera_metadata.h + */ +typedef struct camera_metadata camera_metadata_t; + +struct camera_info { + /** + * The direction that the camera faces to. It should be CAMERA_FACING_BACK + * or CAMERA_FACING_FRONT. + * + * Version information: + * Valid in all camera_module versions + */ + int facing; + + /** + * The orientation of the camera image. The value is the angle that the + * camera image needs to be rotated clockwise so it shows correctly on the + * display in its natural orientation. It should be 0, 90, 180, or 270. + * + * For example, suppose a device has a naturally tall screen. The + * back-facing camera sensor is mounted in landscape. You are looking at + * the screen. If the top side of the camera sensor is aligned with the + * right edge of the screen in natural orientation, the value should be + * 90. If the top side of a front-facing camera sensor is aligned with the + * right of the screen, the value should be 270. + * + * Version information: + * Valid in all camera_module versions + */ + int orientation; + + /** + * The value of camera_device_t.common.version. + * + * Version information (based on camera_module_t.common.module_api_version): + * + * CAMERA_MODULE_API_VERSION_1_0: + * + * Not valid. Can be assumed to be CAMERA_DEVICE_API_VERSION_1_0. Do + * not read this field. + * + * CAMERA_MODULE_API_VERSION_2_0: + * + * Always valid + * + */ + uint32_t device_version; + + /** + * The camera's fixed characteristics, which include all camera metadata in + * the android.*.info.* sections. This should be a sorted metadata buffer, + * and may not be modified or freed by the caller. The pointer should remain + * valid for the lifetime of the camera module. + * + * Version information (based on camera_module_t.common.module_api_version): + * + * CAMERA_MODULE_API_VERSION_1_0: + * + * Not valid. Extra characteristics are not available. Do not read this + * field. + * + * CAMERA_MODULE_API_VERSION_2_0: + * + * Valid if device_version >= CAMERA_DEVICE_API_VERSION_2_0. Do not read + * otherwise. + * + */ + const camera_metadata_t *static_camera_characteristics; +}; + +typedef struct camera_module { + hw_module_t common; + int (*get_number_of_cameras)(void); + int (*get_camera_info)(int camera_id, struct camera_info *info); +} camera_module_t; + +__END_DECLS + +#endif /* ANDROID_INCLUDE_CAMERA_COMMON_H */ diff -Nru android-tools-4.2.2+git20130218/libhardware/include/hardware/camera.h android-tools-4.2.2+git20130529/libhardware/include/hardware/camera.h --- android-tools-4.2.2+git20130218/libhardware/include/hardware/camera.h 1970-01-01 00:00:00.000000000 +0000 +++ android-tools-4.2.2+git20130529/libhardware/include/hardware/camera.h 2013-05-29 20:16:54.000000000 +0000 @@ -0,0 +1,295 @@ +/* + * Copyright (C) 2010-2011 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 ANDROID_INCLUDE_CAMERA_H +#define ANDROID_INCLUDE_CAMERA_H + +#include "camera_common.h" + +/** + * Camera device HAL, initial version [ CAMERA_DEVICE_API_VERSION_1_0 ] + * + * Supports the android.hardware.Camera API. + * + * Camera devices that support this version of the HAL must return a value in + * the range HARDWARE_DEVICE_API_VERSION(0,0)-(1,FF) in + * camera_device_t.common.version. CAMERA_DEVICE_API_VERSION_1_0 is the + * recommended value. + * + * Camera modules that implement version 2.0 or higher of camera_module_t must + * also return the value of camera_device_t.common.version in + * camera_info_t.device_version. + * + * See camera_common.h for more details. + */ + +__BEGIN_DECLS + +struct camera_memory; +typedef void (*camera_release_memory)(struct camera_memory *mem); + +typedef struct camera_memory { + void *data; + size_t size; + void *handle; + camera_release_memory release; +} camera_memory_t; + +typedef camera_memory_t* (*camera_request_memory)(int fd, size_t buf_size, unsigned int num_bufs, + void *user); + +typedef void (*camera_notify_callback)(int32_t msg_type, + int32_t ext1, + int32_t ext2, + void *user); + +typedef void (*camera_data_callback)(int32_t msg_type, + const camera_memory_t *data, unsigned int index, + camera_frame_metadata_t *metadata, void *user); + +typedef void (*camera_data_timestamp_callback)(int64_t timestamp, + int32_t msg_type, + const camera_memory_t *data, unsigned int index, + void *user); + +#define HAL_CAMERA_PREVIEW_WINDOW_TAG 0xcafed00d + +typedef struct preview_stream_ops { + int (*dequeue_buffer)(struct preview_stream_ops* w, + buffer_handle_t** buffer, int *stride); + int (*enqueue_buffer)(struct preview_stream_ops* w, + buffer_handle_t* buffer); + int (*cancel_buffer)(struct preview_stream_ops* w, + buffer_handle_t* buffer); + int (*set_buffer_count)(struct preview_stream_ops* w, int count); + int (*set_buffers_geometry)(struct preview_stream_ops* pw, + int w, int h, int format); + int (*set_crop)(struct preview_stream_ops *w, + int left, int top, int right, int bottom); + int (*set_usage)(struct preview_stream_ops* w, int usage); + int (*set_swap_interval)(struct preview_stream_ops *w, int interval); + int (*get_min_undequeued_buffer_count)(const struct preview_stream_ops *w, + int *count); + int (*lock_buffer)(struct preview_stream_ops* w, + buffer_handle_t* buffer); + // Timestamps are measured in nanoseconds, and must be comparable + // and monotonically increasing between two frames in the same + // preview stream. They do not need to be comparable between + // consecutive or parallel preview streams, cameras, or app runs. + int (*set_timestamp)(struct preview_stream_ops *w, int64_t timestamp); +} preview_stream_ops_t; + +struct camera_device; +typedef struct camera_device_ops { + /** Set the ANativeWindow to which preview frames are sent */ + int (*set_preview_window)(struct camera_device *, + struct preview_stream_ops *window); + + /** Set the notification and data callbacks */ + void (*set_callbacks)(struct camera_device *, + camera_notify_callback notify_cb, + camera_data_callback data_cb, + camera_data_timestamp_callback data_cb_timestamp, + camera_request_memory get_memory, + void *user); + + /** + * The following three functions all take a msg_type, which is a bitmask of + * the messages defined in include/ui/Camera.h + */ + + /** + * Enable a message, or set of messages. + */ + void (*enable_msg_type)(struct camera_device *, int32_t msg_type); + + /** + * Disable a message, or a set of messages. + * + * Once received a call to disableMsgType(CAMERA_MSG_VIDEO_FRAME), camera + * HAL should not rely on its client to call releaseRecordingFrame() to + * release video recording frames sent out by the cameral HAL before and + * after the disableMsgType(CAMERA_MSG_VIDEO_FRAME) call. Camera HAL + * clients must not modify/access any video recording frame after calling + * disableMsgType(CAMERA_MSG_VIDEO_FRAME). + */ + void (*disable_msg_type)(struct camera_device *, int32_t msg_type); + + /** + * Query whether a message, or a set of messages, is enabled. Note that + * this is operates as an AND, if any of the messages queried are off, this + * will return false. + */ + int (*msg_type_enabled)(struct camera_device *, int32_t msg_type); + + /** + * Start preview mode. + */ + int (*start_preview)(struct camera_device *); + + /** + * Stop a previously started preview. + */ + void (*stop_preview)(struct camera_device *); + + /** + * Returns true if preview is enabled. + */ + int (*preview_enabled)(struct camera_device *); + + /** + * Request the camera HAL to store meta data or real YUV data in the video + * buffers sent out via CAMERA_MSG_VIDEO_FRAME for a recording session. If + * it is not called, the default camera HAL behavior is to store real YUV + * data in the video buffers. + * + * This method should be called before startRecording() in order to be + * effective. + * + * If meta data is stored in the video buffers, it is up to the receiver of + * the video buffers to interpret the contents and to find the actual frame + * data with the help of the meta data in the buffer. How this is done is + * outside of the scope of this method. + * + * Some camera HALs may not support storing meta data in the video buffers, + * but all camera HALs should support storing real YUV data in the video + * buffers. If the camera HAL does not support storing the meta data in the + * video buffers when it is requested to do do, INVALID_OPERATION must be + * returned. It is very useful for the camera HAL to pass meta data rather + * than the actual frame data directly to the video encoder, since the + * amount of the uncompressed frame data can be very large if video size is + * large. + * + * @param enable if true to instruct the camera HAL to store + * meta data in the video buffers; false to instruct + * the camera HAL to store real YUV data in the video + * buffers. + * + * @return OK on success. + */ + int (*store_meta_data_in_buffers)(struct camera_device *, int enable); + + /** + * Start record mode. When a record image is available, a + * CAMERA_MSG_VIDEO_FRAME message is sent with the corresponding + * frame. Every record frame must be released by a camera HAL client via + * releaseRecordingFrame() before the client calls + * disableMsgType(CAMERA_MSG_VIDEO_FRAME). After the client calls + * disableMsgType(CAMERA_MSG_VIDEO_FRAME), it is the camera HAL's + * responsibility to manage the life-cycle of the video recording frames, + * and the client must not modify/access any video recording frames. + */ + int (*start_recording)(struct camera_device *); + + /** + * Stop a previously started recording. + */ + void (*stop_recording)(struct camera_device *); + + /** + * Returns true if recording is enabled. + */ + int (*recording_enabled)(struct camera_device *); + + /** + * Release a record frame previously returned by CAMERA_MSG_VIDEO_FRAME. + * + * It is camera HAL client's responsibility to release video recording + * frames sent out by the camera HAL before the camera HAL receives a call + * to disableMsgType(CAMERA_MSG_VIDEO_FRAME). After it receives the call to + * disableMsgType(CAMERA_MSG_VIDEO_FRAME), it is the camera HAL's + * responsibility to manage the life-cycle of the video recording frames. + */ + void (*release_recording_frame)(struct camera_device *, + const void *opaque); + + /** + * Start auto focus, the notification callback routine is called with + * CAMERA_MSG_FOCUS once when focusing is complete. autoFocus() will be + * called again if another auto focus is needed. + */ + int (*auto_focus)(struct camera_device *); + + /** + * Cancels auto-focus function. If the auto-focus is still in progress, + * this function will cancel it. Whether the auto-focus is in progress or + * not, this function will return the focus position to the default. If + * the camera does not support auto-focus, this is a no-op. + */ + int (*cancel_auto_focus)(struct camera_device *); + + /** + * Take a picture. + */ + int (*take_picture)(struct camera_device *); + + /** + * Cancel a picture that was started with takePicture. Calling this method + * when no picture is being taken is a no-op. + */ + int (*cancel_picture)(struct camera_device *); + + /** + * Set the camera parameters. This returns BAD_VALUE if any parameter is + * invalid or not supported. + */ + int (*set_parameters)(struct camera_device *, const char *parms); + + /** Retrieve the camera parameters. The buffer returned by the camera HAL + must be returned back to it with put_parameters, if put_parameters + is not NULL. + */ + char *(*get_parameters)(struct camera_device *); + + /** The camera HAL uses its own memory to pass us the parameters when we + call get_parameters. Use this function to return the memory back to + the camera HAL, if put_parameters is not NULL. If put_parameters + is NULL, then you have to use free() to release the memory. + */ + void (*put_parameters)(struct camera_device *, char *); + + /** + * Send command to camera driver. + */ + int (*send_command)(struct camera_device *, + int32_t cmd, int32_t arg1, int32_t arg2); + + /** + * Release the hardware resources owned by this object. Note that this is + * *not* done in the destructor. + */ + void (*release)(struct camera_device *); + + /** + * Dump state of the camera hardware + */ + int (*dump)(struct camera_device *, int fd); +} camera_device_ops_t; + +typedef struct camera_device { + /** + * camera_device.common.version must be in the range + * HARDWARE_DEVICE_API_VERSION(0,0)-(1,FF). CAMERA_DEVICE_API_VERSION_1_0 is + * recommended. + */ + hw_device_t common; + camera_device_ops_t *ops; + void *priv; +} camera_device_t; + +__END_DECLS + +#endif /* #ifdef ANDROID_INCLUDE_CAMERA_H */ diff -Nru android-tools-4.2.2+git20130218/libhardware/include/hardware/fb.h android-tools-4.2.2+git20130529/libhardware/include/hardware/fb.h --- android-tools-4.2.2+git20130218/libhardware/include/hardware/fb.h 1970-01-01 00:00:00.000000000 +0000 +++ android-tools-4.2.2+git20130529/libhardware/include/hardware/fb.h 2013-05-29 20:16:54.000000000 +0000 @@ -0,0 +1,167 @@ +/* + * 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 ANDROID_FB_INTERFACE_H +#define ANDROID_FB_INTERFACE_H + +#include +#include +#include + +#include + +#include + +__BEGIN_DECLS + +#define GRALLOC_HARDWARE_FB0 "fb0" + +/*****************************************************************************/ + + +/*****************************************************************************/ + +typedef struct framebuffer_device_t { + struct hw_device_t common; + + /* flags describing some attributes of the framebuffer */ + const uint32_t flags; + + /* dimensions of the framebuffer in pixels */ + const uint32_t width; + const uint32_t height; + + /* frambuffer stride in pixels */ + const int stride; + + /* framebuffer pixel format */ + const int format; + + /* resolution of the framebuffer's display panel in pixel per inch*/ + const float xdpi; + const float ydpi; + + /* framebuffer's display panel refresh rate in frames per second */ + const float fps; + + /* min swap interval supported by this framebuffer */ + const int minSwapInterval; + + /* max swap interval supported by this framebuffer */ + const int maxSwapInterval; + + /* Number of framebuffers supported*/ + const int numFramebuffers; + + int reserved[7]; + + /* + * requests a specific swap-interval (same definition than EGL) + * + * Returns 0 on success or -errno on error. + */ + int (*setSwapInterval)(struct framebuffer_device_t* window, + int interval); + + /* + * This hook is OPTIONAL. + * + * It is non NULL If the framebuffer driver supports "update-on-demand" + * and the given rectangle is the area of the screen that gets + * updated during (*post)(). + * + * This is useful on devices that are able to DMA only a portion of + * the screen to the display panel, upon demand -- as opposed to + * constantly refreshing the panel 60 times per second, for instance. + * + * Only the area defined by this rectangle is guaranteed to be valid, that + * is, the driver is not allowed to post anything outside of this + * rectangle. + * + * The rectangle evaluated during (*post)() and specifies which area + * of the buffer passed in (*post)() shall to be posted. + * + * return -EINVAL if width or height <=0, or if left or top < 0 + */ + int (*setUpdateRect)(struct framebuffer_device_t* window, + int left, int top, int width, int height); + + /* + * Post to the display (display it on the screen) + * The buffer must have been allocated with the + * GRALLOC_USAGE_HW_FB usage flag. + * buffer must be the same width and height as the display and must NOT + * be locked. + * + * The buffer is shown during the next VSYNC. + * + * If the same buffer is posted again (possibly after some other buffer), + * post() will block until the the first post is completed. + * + * Internally, post() is expected to lock the buffer so that a + * subsequent call to gralloc_module_t::(*lock)() with USAGE_RENDER or + * USAGE_*_WRITE will block until it is safe; that is typically once this + * buffer is shown and another buffer has been posted. + * + * Returns 0 on success or -errno on error. + */ + int (*post)(struct framebuffer_device_t* dev, buffer_handle_t buffer); + + + /* + * The (*compositionComplete)() method must be called after the + * compositor has finished issuing GL commands for client buffers. + */ + + int (*compositionComplete)(struct framebuffer_device_t* dev); + + /* + * This hook is OPTIONAL. + * + * If non NULL it will be caused by SurfaceFlinger on dumpsys + */ + void (*dump)(struct framebuffer_device_t* dev, char *buff, int buff_len); + + /* + * (*enableScreen)() is used to either blank (enable=0) or + * unblank (enable=1) the screen this framebuffer is attached to. + * + * Returns 0 on success or -errno on error. + */ + int (*enableScreen)(struct framebuffer_device_t* dev, int enable); + + void* reserved_proc[6]; + +} framebuffer_device_t; + + +/** convenience API for opening and closing a supported device */ + +static inline int framebuffer_open(const struct hw_module_t* module, + struct framebuffer_device_t** device) { + return module->methods->open(module, + GRALLOC_HARDWARE_FB0, (struct hw_device_t**)device); +} + +static inline int framebuffer_close(struct framebuffer_device_t* device) { + return device->common.close(&device->common); +} + + +__END_DECLS + +#endif // ANDROID_FB_INTERFACE_H diff -Nru android-tools-4.2.2+git20130218/libhardware/include/hardware/gps.h android-tools-4.2.2+git20130529/libhardware/include/hardware/gps.h --- android-tools-4.2.2+git20130218/libhardware/include/hardware/gps.h 1970-01-01 00:00:00.000000000 +0000 +++ android-tools-4.2.2+git20130529/libhardware/include/hardware/gps.h 2013-05-29 20:16:54.000000000 +0000 @@ -0,0 +1,679 @@ +/* + * Copyright (C) 2010 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 ANDROID_INCLUDE_HARDWARE_GPS_H +#define ANDROID_INCLUDE_HARDWARE_GPS_H + +#include +#include +#include +#include + +#include + +__BEGIN_DECLS + +/** + * The id of this module + */ +#define GPS_HARDWARE_MODULE_ID "gps" + + +/** Milliseconds since January 1, 1970 */ +typedef int64_t GpsUtcTime; + +/** Maximum number of SVs for gps_sv_status_callback(). */ +#define GPS_MAX_SVS 32 + +/** Requested operational mode for GPS operation. */ +typedef uint32_t GpsPositionMode; +// IMPORTANT: Note that the following values must match +// constants in GpsLocationProvider.java. +/** Mode for running GPS standalone (no assistance). */ +#define GPS_POSITION_MODE_STANDALONE 0 +/** AGPS MS-Based mode. */ +#define GPS_POSITION_MODE_MS_BASED 1 +/** AGPS MS-Assisted mode. */ +#define GPS_POSITION_MODE_MS_ASSISTED 2 + +/** Requested recurrence mode for GPS operation. */ +typedef uint32_t GpsPositionRecurrence; +// IMPORTANT: Note that the following values must match +// constants in GpsLocationProvider.java. +/** Receive GPS fixes on a recurring basis at a specified period. */ +#define GPS_POSITION_RECURRENCE_PERIODIC 0 +/** Request a single shot GPS fix. */ +#define GPS_POSITION_RECURRENCE_SINGLE 1 + +/** GPS status event values. */ +typedef uint16_t GpsStatusValue; +// IMPORTANT: Note that the following values must match +// constants in GpsLocationProvider.java. +/** GPS status unknown. */ +#define GPS_STATUS_NONE 0 +/** GPS has begun navigating. */ +#define GPS_STATUS_SESSION_BEGIN 1 +/** GPS has stopped navigating. */ +#define GPS_STATUS_SESSION_END 2 +/** GPS has powered on but is not navigating. */ +#define GPS_STATUS_ENGINE_ON 3 +/** GPS is powered off. */ +#define GPS_STATUS_ENGINE_OFF 4 + +/** Flags to indicate which values are valid in a GpsLocation. */ +typedef uint16_t GpsLocationFlags; +// IMPORTANT: Note that the following values must match +// constants in GpsLocationProvider.java. +/** GpsLocation has valid latitude and longitude. */ +#define GPS_LOCATION_HAS_LAT_LONG 0x0001 +/** GpsLocation has valid altitude. */ +#define GPS_LOCATION_HAS_ALTITUDE 0x0002 +/** GpsLocation has valid speed. */ +#define GPS_LOCATION_HAS_SPEED 0x0004 +/** GpsLocation has valid bearing. */ +#define GPS_LOCATION_HAS_BEARING 0x0008 +/** GpsLocation has valid accuracy. */ +#define GPS_LOCATION_HAS_ACCURACY 0x0010 + +/** Flags for the gps_set_capabilities callback. */ + +/** GPS HAL schedules fixes for GPS_POSITION_RECURRENCE_PERIODIC mode. + If this is not set, then the framework will use 1000ms for min_interval + and will start and call start() and stop() to schedule the GPS. + */ +#define GPS_CAPABILITY_SCHEDULING 0x0000001 +/** GPS supports MS-Based AGPS mode */ +#define GPS_CAPABILITY_MSB 0x0000002 +/** GPS supports MS-Assisted AGPS mode */ +#define GPS_CAPABILITY_MSA 0x0000004 +/** GPS supports single-shot fixes */ +#define GPS_CAPABILITY_SINGLE_SHOT 0x0000008 +/** GPS supports on demand time injection */ +#define GPS_CAPABILITY_ON_DEMAND_TIME 0x0000010 + +/** Flags used to specify which aiding data to delete + when calling delete_aiding_data(). */ +typedef uint16_t GpsAidingData; +// IMPORTANT: Note that the following values must match +// constants in GpsLocationProvider.java. +#define GPS_DELETE_EPHEMERIS 0x0001 +#define GPS_DELETE_ALMANAC 0x0002 +#define GPS_DELETE_POSITION 0x0004 +#define GPS_DELETE_TIME 0x0008 +#define GPS_DELETE_IONO 0x0010 +#define GPS_DELETE_UTC 0x0020 +#define GPS_DELETE_HEALTH 0x0040 +#define GPS_DELETE_SVDIR 0x0080 +#define GPS_DELETE_SVSTEER 0x0100 +#define GPS_DELETE_SADATA 0x0200 +#define GPS_DELETE_RTI 0x0400 +#define GPS_DELETE_CELLDB_INFO 0x8000 +#define GPS_DELETE_ALL 0xFFFF + +/** AGPS type */ +typedef uint16_t AGpsType; +#define AGPS_TYPE_SUPL 1 +#define AGPS_TYPE_C2K 2 + +typedef uint16_t AGpsSetIDType; +#define AGPS_SETID_TYPE_NONE 0 +#define AGPS_SETID_TYPE_IMSI 1 +#define AGPS_SETID_TYPE_MSISDN 2 + +/** + * String length constants + */ +#define GPS_NI_SHORT_STRING_MAXLEN 256 +#define GPS_NI_LONG_STRING_MAXLEN 2048 + +/** + * GpsNiType constants + */ +typedef uint32_t GpsNiType; +#define GPS_NI_TYPE_VOICE 1 +#define GPS_NI_TYPE_UMTS_SUPL 2 +#define GPS_NI_TYPE_UMTS_CTRL_PLANE 3 + +/** + * GpsNiNotifyFlags constants + */ +typedef uint32_t GpsNiNotifyFlags; +/** NI requires notification */ +#define GPS_NI_NEED_NOTIFY 0x0001 +/** NI requires verification */ +#define GPS_NI_NEED_VERIFY 0x0002 +/** NI requires privacy override, no notification/minimal trace */ +#define GPS_NI_PRIVACY_OVERRIDE 0x0004 + +/** + * GPS NI responses, used to define the response in + * NI structures + */ +typedef int GpsUserResponseType; +#define GPS_NI_RESPONSE_ACCEPT 1 +#define GPS_NI_RESPONSE_DENY 2 +#define GPS_NI_RESPONSE_NORESP 3 + +/** + * NI data encoding scheme + */ +typedef int GpsNiEncodingType; +#define GPS_ENC_NONE 0 +#define GPS_ENC_SUPL_GSM_DEFAULT 1 +#define GPS_ENC_SUPL_UTF8 2 +#define GPS_ENC_SUPL_UCS2 3 +#define GPS_ENC_UNKNOWN -1 + +/** AGPS status event values. */ +typedef uint16_t AGpsStatusValue; +/** GPS requests data connection for AGPS. */ +#define GPS_REQUEST_AGPS_DATA_CONN 1 +/** GPS releases the AGPS data connection. */ +#define GPS_RELEASE_AGPS_DATA_CONN 2 +/** AGPS data connection initiated */ +#define GPS_AGPS_DATA_CONNECTED 3 +/** AGPS data connection completed */ +#define GPS_AGPS_DATA_CONN_DONE 4 +/** AGPS data connection failed */ +#define GPS_AGPS_DATA_CONN_FAILED 5 + +#define AGPS_REF_LOCATION_TYPE_GSM_CELLID 1 +#define AGPS_REF_LOCATION_TYPE_UMTS_CELLID 2 +#define AGPS_REG_LOCATION_TYPE_MAC 3 + +/** Network types for update_network_state "type" parameter */ +#define AGPS_RIL_NETWORK_TYPE_MOBILE 0 +#define AGPS_RIL_NETWORK_TYPE_WIFI 1 +#define AGPS_RIL_NETWORK_TYPE_MOBILE_MMS 2 +#define AGPS_RIL_NETWORK_TYPE_MOBILE_SUPL 3 +#define AGPS_RIL_NETWORK_TTYPE_MOBILE_DUN 4 +#define AGPS_RIL_NETWORK_TTYPE_MOBILE_HIPRI 5 +#define AGPS_RIL_NETWORK_TTYPE_WIMAX 6 + +/** + * Name for the GPS XTRA interface. + */ +#define GPS_XTRA_INTERFACE "gps-xtra" + +/** + * Name for the GPS DEBUG interface. + */ +#define GPS_DEBUG_INTERFACE "gps-debug" + +/** + * Name for the AGPS interface. + */ +#define AGPS_INTERFACE "agps" + +/** + * Name for NI interface + */ +#define GPS_NI_INTERFACE "gps-ni" + +/** + * Name for the AGPS-RIL interface. + */ +#define AGPS_RIL_INTERFACE "agps_ril" + +/** Represents a location. */ +typedef struct { + /** set to sizeof(GpsLocation) */ + size_t size; + /** Contains GpsLocationFlags bits. */ + uint16_t flags; + /** Represents latitude in degrees. */ + double latitude; + /** Represents longitude in degrees. */ + double longitude; + /** Represents altitude in meters above the WGS 84 reference + * ellipsoid. */ + double altitude; + /** Represents speed in meters per second. */ + float speed; + /** Represents heading in degrees. */ + float bearing; + /** Represents expected accuracy in meters. */ + float accuracy; + /** Timestamp for the location fix. */ + GpsUtcTime timestamp; +} GpsLocation; + +/** Represents the status. */ +typedef struct { + /** set to sizeof(GpsStatus) */ + size_t size; + GpsStatusValue status; +} GpsStatus; + +/** Represents SV information. */ +typedef struct { + /** set to sizeof(GpsSvInfo) */ + size_t size; + /** Pseudo-random number for the SV. */ + int prn; + /** Signal to noise ratio. */ + float snr; + /** Elevation of SV in degrees. */ + float elevation; + /** Azimuth of SV in degrees. */ + float azimuth; +} GpsSvInfo; + +/** Represents SV status. */ +typedef struct { + /** set to sizeof(GpsSvStatus) */ + size_t size; + + /** Number of SVs currently visible. */ + int num_svs; + + /** Contains an array of SV information. */ + GpsSvInfo sv_list[GPS_MAX_SVS]; + + /** Represents a bit mask indicating which SVs + * have ephemeris data. + */ + uint32_t ephemeris_mask; + + /** Represents a bit mask indicating which SVs + * have almanac data. + */ + uint32_t almanac_mask; + + /** + * Represents a bit mask indicating which SVs + * were used for computing the most recent position fix. + */ + uint32_t used_in_fix_mask; +} GpsSvStatus; + +/* 2G and 3G */ +/* In 3G lac is discarded */ +typedef struct { + uint16_t type; + uint16_t mcc; + uint16_t mnc; + uint16_t lac; + uint32_t cid; +} AGpsRefLocationCellID; + +typedef struct { + uint8_t mac[6]; +} AGpsRefLocationMac; + +/** Represents ref locations */ +typedef struct { + uint16_t type; + union { + AGpsRefLocationCellID cellID; + AGpsRefLocationMac mac; + } u; +} AGpsRefLocation; + +/** Callback with location information. + * Can only be called from a thread created by create_thread_cb. + */ +typedef void (* gps_location_callback)(GpsLocation* location); + +/** Callback with status information. + * Can only be called from a thread created by create_thread_cb. + */ +typedef void (* gps_status_callback)(GpsStatus* status); + +/** Callback with SV status information. + * Can only be called from a thread created by create_thread_cb. + */ +typedef void (* gps_sv_status_callback)(GpsSvStatus* sv_info); + +/** Callback for reporting NMEA sentences. + * Can only be called from a thread created by create_thread_cb. + */ +typedef void (* gps_nmea_callback)(GpsUtcTime timestamp, const char* nmea, int length); + +/** Callback to inform framework of the GPS engine's capabilities. + * Capability parameter is a bit field of GPS_CAPABILITY_* flags. + */ +typedef void (* gps_set_capabilities)(uint32_t capabilities); + +/** Callback utility for acquiring the GPS wakelock. + * This can be used to prevent the CPU from suspending while handling GPS events. + */ +typedef void (* gps_acquire_wakelock)(); + +/** Callback utility for releasing the GPS wakelock. */ +typedef void (* gps_release_wakelock)(); + +/** Callback for requesting NTP time */ +typedef void (* gps_request_utc_time)(); + +/** Callback for creating a thread that can call into the Java framework code. + * This must be used to create any threads that report events up to the framework. + */ +typedef pthread_t (* gps_create_thread)(const char* name, void (*start)(void *), void* arg); + +/** GPS callback structure. */ +typedef struct { + /** set to sizeof(GpsCallbacks) */ + size_t size; + gps_location_callback location_cb; + gps_status_callback status_cb; + gps_sv_status_callback sv_status_cb; + gps_nmea_callback nmea_cb; + gps_set_capabilities set_capabilities_cb; + gps_acquire_wakelock acquire_wakelock_cb; + gps_release_wakelock release_wakelock_cb; + gps_create_thread create_thread_cb; + gps_request_utc_time request_utc_time_cb; +} GpsCallbacks; + + +/** Represents the standard GPS interface. */ +typedef struct { + /** set to sizeof(GpsInterface) */ + size_t size; + /** + * Opens the interface and provides the callback routines + * to the implemenation of this interface. + */ + int (*init)( GpsCallbacks* callbacks ); + + /** Starts navigating. */ + int (*start)( void ); + + /** Stops navigating. */ + int (*stop)( void ); + + /** Closes the interface. */ + void (*cleanup)( void ); + + /** Injects the current time. */ + int (*inject_time)(GpsUtcTime time, int64_t timeReference, + int uncertainty); + + /** Injects current location from another location provider + * (typically cell ID). + * latitude and longitude are measured in degrees + * expected accuracy is measured in meters + */ + int (*inject_location)(double latitude, double longitude, float accuracy); + + /** + * Specifies that the next call to start will not use the + * information defined in the flags. GPS_DELETE_ALL is passed for + * a cold start. + */ + void (*delete_aiding_data)(GpsAidingData flags); + + /** + * min_interval represents the time between fixes in milliseconds. + * preferred_accuracy represents the requested fix accuracy in meters. + * preferred_time represents the requested time to first fix in milliseconds. + */ + int (*set_position_mode)(GpsPositionMode mode, GpsPositionRecurrence recurrence, + uint32_t min_interval, uint32_t preferred_accuracy, uint32_t preferred_time); + + /** Get a pointer to extension information. */ + const void* (*get_extension)(const char* name); +} GpsInterface; + +/** Callback to request the client to download XTRA data. + * The client should download XTRA data and inject it by calling inject_xtra_data(). + * Can only be called from a thread created by create_thread_cb. + */ +typedef void (* gps_xtra_download_request)(); + +/** Callback structure for the XTRA interface. */ +typedef struct { + gps_xtra_download_request download_request_cb; + gps_create_thread create_thread_cb; +} GpsXtraCallbacks; + +/** Extended interface for XTRA support. */ +typedef struct { + /** set to sizeof(GpsXtraInterface) */ + size_t size; + /** + * Opens the XTRA interface and provides the callback routines + * to the implemenation of this interface. + */ + int (*init)( GpsXtraCallbacks* callbacks ); + /** Injects XTRA data into the GPS. */ + int (*inject_xtra_data)( char* data, int length ); +} GpsXtraInterface; + +/** Extended interface for DEBUG support. */ +typedef struct { + /** set to sizeof(GpsDebugInterface) */ + size_t size; + + /** + * This function should return any information that the native + * implementation wishes to include in a bugreport. + */ + size_t (*get_internal_state)(char* buffer, size_t bufferSize); +} GpsDebugInterface; + +/** Represents the status of AGPS. */ +typedef struct { + /** set to sizeof(AGpsStatus) */ + size_t size; + + AGpsType type; + AGpsStatusValue status; + uint32_t ipaddr; +} AGpsStatus; + +/** Callback with AGPS status information. + * Can only be called from a thread created by create_thread_cb. + */ +typedef void (* agps_status_callback)(AGpsStatus* status); + +/** Callback structure for the AGPS interface. */ +typedef struct { + agps_status_callback status_cb; + gps_create_thread create_thread_cb; +} AGpsCallbacks; + + +/** Extended interface for AGPS support. */ +typedef struct { + /** set to sizeof(AGpsInterface) */ + size_t size; + + /** + * Opens the AGPS interface and provides the callback routines + * to the implemenation of this interface. + */ + void (*init)( AGpsCallbacks* callbacks ); + /** + * Notifies that a data connection is available and sets + * the name of the APN to be used for SUPL. + */ + int (*data_conn_open)( const char* apn ); + /** + * Notifies that the AGPS data connection has been closed. + */ + int (*data_conn_closed)(); + /** + * Notifies that a data connection is not available for AGPS. + */ + int (*data_conn_failed)(); + /** + * Sets the hostname and port for the AGPS server. + */ + int (*set_server)( AGpsType type, const char* hostname, int port ); +} AGpsInterface; + + +/** Represents an NI request */ +typedef struct { + /** set to sizeof(GpsNiNotification) */ + size_t size; + + /** + * An ID generated by HAL to associate NI notifications and UI + * responses + */ + int notification_id; + + /** + * An NI type used to distinguish different categories of NI + * events, such as GPS_NI_TYPE_VOICE, GPS_NI_TYPE_UMTS_SUPL, ... + */ + GpsNiType ni_type; + + /** + * Notification/verification options, combinations of GpsNiNotifyFlags constants + */ + GpsNiNotifyFlags notify_flags; + + /** + * Timeout period to wait for user response. + * Set to 0 for no time out limit. + */ + int timeout; + + /** + * Default response when time out. + */ + GpsUserResponseType default_response; + + /** + * Requestor ID + */ + char requestor_id[GPS_NI_SHORT_STRING_MAXLEN]; + + /** + * Notification message. It can also be used to store client_id in some cases + */ + char text[GPS_NI_LONG_STRING_MAXLEN]; + + /** + * Client name decoding scheme + */ + GpsNiEncodingType requestor_id_encoding; + + /** + * Client name decoding scheme + */ + GpsNiEncodingType text_encoding; + + /** + * A pointer to extra data. Format: + * key_1 = value_1 + * key_2 = value_2 + */ + char extras[GPS_NI_LONG_STRING_MAXLEN]; + +} GpsNiNotification; + +/** Callback with NI notification. + * Can only be called from a thread created by create_thread_cb. + */ +typedef void (*gps_ni_notify_callback)(GpsNiNotification *notification); + +/** GPS NI callback structure. */ +typedef struct +{ + /** + * Sends the notification request from HAL to GPSLocationProvider. + */ + gps_ni_notify_callback notify_cb; + gps_create_thread create_thread_cb; +} GpsNiCallbacks; + +/** + * Extended interface for Network-initiated (NI) support. + */ +typedef struct +{ + /** set to sizeof(GpsNiInterface) */ + size_t size; + + /** Registers the callbacks for HAL to use. */ + void (*init) (GpsNiCallbacks *callbacks); + + /** Sends a response to HAL. */ + void (*respond) (int notif_id, GpsUserResponseType user_response); +} GpsNiInterface; + +struct gps_device_t { + struct hw_device_t common; + + /** + * Set the provided lights to the provided values. + * + * Returns: 0 on succes, error code on failure. + */ + const GpsInterface* (*get_gps_interface)(struct gps_device_t* dev); +}; + +#define AGPS_RIL_REQUEST_SETID_IMSI (1<<0L) +#define AGPS_RIL_REQUEST_SETID_MSISDN (1<<1L) + +#define AGPS_RIL_REQUEST_REFLOC_CELLID (1<<0L) +#define AGPS_RIL_REQUEST_REFLOC_MAC (1<<1L) + +typedef void (*agps_ril_request_set_id)(uint32_t flags); +typedef void (*agps_ril_request_ref_loc)(uint32_t flags); + +typedef struct { + agps_ril_request_set_id request_setid; + agps_ril_request_ref_loc request_refloc; + gps_create_thread create_thread_cb; +} AGpsRilCallbacks; + +/** Extended interface for AGPS_RIL support. */ +typedef struct { + /** set to sizeof(AGpsRilInterface) */ + size_t size; + /** + * Opens the AGPS interface and provides the callback routines + * to the implemenation of this interface. + */ + void (*init)( AGpsRilCallbacks* callbacks ); + + /** + * Sets the reference location. + */ + void (*set_ref_location) (const AGpsRefLocation *agps_reflocation, size_t sz_struct); + /** + * Sets the set ID. + */ + void (*set_set_id) (AGpsSetIDType type, const char* setid); + + /** + * Send network initiated message. + */ + void (*ni_message) (uint8_t *msg, size_t len); + + /** + * Notify GPS of network status changes. + * These parameters match values in the android.net.NetworkInfo class. + */ + void (*update_network_state) (int connected, int type, int roaming, const char* extra_info); + + /** + * Notify GPS of network status changes. + * These parameters match values in the android.net.NetworkInfo class. + */ + void (*update_network_availability) (int avaiable, const char* apn); +} AGpsRilInterface; + +__END_DECLS + +#endif /* ANDROID_INCLUDE_HARDWARE_GPS_H */ + diff -Nru android-tools-4.2.2+git20130218/libhardware/include/hardware/gralloc.h android-tools-4.2.2+git20130529/libhardware/include/hardware/gralloc.h --- android-tools-4.2.2+git20130218/libhardware/include/hardware/gralloc.h 1970-01-01 00:00:00.000000000 +0000 +++ android-tools-4.2.2+git20130529/libhardware/include/hardware/gralloc.h 2013-05-29 20:16:54.000000000 +0000 @@ -0,0 +1,269 @@ +/* + * 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 ANDROID_GRALLOC_INTERFACE_H +#define ANDROID_GRALLOC_INTERFACE_H + +#include +#include + +#include +#include +#include + +#include + +#include +#include + +__BEGIN_DECLS + +#define GRALLOC_API_VERSION 1 + +/** + * The id of this module + */ +#define GRALLOC_HARDWARE_MODULE_ID "gralloc" + +/** + * Name of the graphics device to open + */ + +#define GRALLOC_HARDWARE_GPU0 "gpu0" + +enum { + /* buffer is never read in software */ + GRALLOC_USAGE_SW_READ_NEVER = 0x00000000, + /* buffer is rarely read in software */ + GRALLOC_USAGE_SW_READ_RARELY = 0x00000002, + /* buffer is often read in software */ + GRALLOC_USAGE_SW_READ_OFTEN = 0x00000003, + /* mask for the software read values */ + GRALLOC_USAGE_SW_READ_MASK = 0x0000000F, + + /* buffer is never written in software */ + GRALLOC_USAGE_SW_WRITE_NEVER = 0x00000000, + /* buffer is never written in software */ + GRALLOC_USAGE_SW_WRITE_RARELY = 0x00000020, + /* buffer is never written in software */ + GRALLOC_USAGE_SW_WRITE_OFTEN = 0x00000030, + /* mask for the software write values */ + GRALLOC_USAGE_SW_WRITE_MASK = 0x000000F0, + + /* buffer will be used as an OpenGL ES texture */ + GRALLOC_USAGE_HW_TEXTURE = 0x00000100, + /* buffer will be used as an OpenGL ES render target */ + GRALLOC_USAGE_HW_RENDER = 0x00000200, + /* buffer will be used by the 2D hardware blitter */ + GRALLOC_USAGE_HW_2D = 0x00000400, + /* buffer will be used by the HWComposer HAL module */ + GRALLOC_USAGE_HW_COMPOSER = 0x00000800, + /* buffer will be used with the framebuffer device */ + GRALLOC_USAGE_HW_FB = 0x00001000, + /* buffer will be used with the HW video encoder */ + GRALLOC_USAGE_HW_VIDEO_ENCODER = 0x00010000, + /* buffer will be written by the HW camera pipeline */ + GRALLOC_USAGE_HW_CAMERA_WRITE = 0x00020000, + /* buffer will be read by the HW camera pipeline */ + GRALLOC_USAGE_HW_CAMERA_READ = 0x00040000, + /* buffer will be used as part of zero-shutter-lag queue */ + GRALLOC_USAGE_HW_CAMERA_ZSL = 0x00060000, + /* mask for the camera access values */ + GRALLOC_USAGE_HW_CAMERA_MASK = 0x00060000, + /* mask for the software usage bit-mask */ + GRALLOC_USAGE_HW_MASK = 0x00071F00, + + /* buffer should be displayed full-screen on an external display when + * possible + */ + GRALLOC_USAGE_EXTERNAL_DISP = 0x00002000, + + /* Must have a hardware-protected path to external display sink for + * this buffer. If a hardware-protected path is not available, then + * either don't composite only this buffer (preferred) to the + * external sink, or (less desirable) do not route the entire + * composition to the external sink. + */ + GRALLOC_USAGE_PROTECTED = 0x00004000, + + /* implementation-specific private usage flags */ + GRALLOC_USAGE_PRIVATE_0 = 0x10000000, + GRALLOC_USAGE_PRIVATE_1 = 0x20000000, + GRALLOC_USAGE_PRIVATE_2 = 0x40000000, + GRALLOC_USAGE_PRIVATE_3 = 0x80000000, + GRALLOC_USAGE_PRIVATE_MASK = 0xF0000000, +}; + +/*****************************************************************************/ + +/** + * Every hardware module must have a data structure named HAL_MODULE_INFO_SYM + * and the fields of this data structure must begin with hw_module_t + * followed by module specific information. + */ +typedef struct gralloc_module_t { + struct hw_module_t common; + + /* + * (*registerBuffer)() must be called before a buffer_handle_t that has not + * been created with (*alloc_device_t::alloc)() can be used. + * + * This is intended to be used with buffer_handle_t's that have been + * received in this process through IPC. + * + * This function checks that the handle is indeed a valid one and prepares + * it for use with (*lock)() and (*unlock)(). + * + * It is not necessary to call (*registerBuffer)() on a handle created + * with (*alloc_device_t::alloc)(). + * + * returns an error if this buffer_handle_t is not valid. + */ + int (*registerBuffer)(struct gralloc_module_t const* module, + buffer_handle_t handle); + + /* + * (*unregisterBuffer)() is called once this handle is no longer needed in + * this process. After this call, it is an error to call (*lock)(), + * (*unlock)(), or (*registerBuffer)(). + * + * This function doesn't close or free the handle itself; this is done + * by other means, usually through libcutils's native_handle_close() and + * native_handle_free(). + * + * It is an error to call (*unregisterBuffer)() on a buffer that wasn't + * explicitly registered first. + */ + int (*unregisterBuffer)(struct gralloc_module_t const* module, + buffer_handle_t handle); + + /* + * The (*lock)() method is called before a buffer is accessed for the + * specified usage. This call may block, for instance if the h/w needs + * to finish rendering or if CPU caches need to be synchronized. + * + * The caller promises to modify only pixels in the area specified + * by (l,t,w,h). + * + * The content of the buffer outside of the specified area is NOT modified + * by this call. + * + * If usage specifies GRALLOC_USAGE_SW_*, vaddr is filled with the address + * of the buffer in virtual memory. + * + * THREADING CONSIDERATIONS: + * + * It is legal for several different threads to lock a buffer from + * read access, none of the threads are blocked. + * + * However, locking a buffer simultaneously for write or read/write is + * undefined, but: + * - shall not result in termination of the process + * - shall not block the caller + * It is acceptable to return an error or to leave the buffer's content + * into an indeterminate state. + * + * If the buffer was created with a usage mask incompatible with the + * requested usage flags here, -EINVAL is returned. + * + */ + + int (*lock)(struct gralloc_module_t const* module, + buffer_handle_t handle, int usage, + int l, int t, int w, int h, + void** vaddr); + + + /* + * The (*unlock)() method must be called after all changes to the buffer + * are completed. + */ + + int (*unlock)(struct gralloc_module_t const* module, + buffer_handle_t handle); + + + /* reserved for future use */ + int (*perform)(struct gralloc_module_t const* module, + int operation, ... ); + + /* reserved for future use */ + void* reserved_proc[7]; +} gralloc_module_t; + +/*****************************************************************************/ + +/** + * Every device data structure must begin with hw_device_t + * followed by module specific public methods and attributes. + */ + +typedef struct alloc_device_t { + struct hw_device_t common; + + /* + * (*alloc)() Allocates a buffer in graphic memory with the requested + * parameters and returns a buffer_handle_t and the stride in pixels to + * allow the implementation to satisfy hardware constraints on the width + * of a pixmap (eg: it may have to be multiple of 8 pixels). + * The CALLER TAKES OWNERSHIP of the buffer_handle_t. + * + * Returns 0 on success or -errno on error. + */ + + int (*alloc)(struct alloc_device_t* dev, + int w, int h, int format, int usage, + buffer_handle_t* handle, int* stride); + + /* + * (*free)() Frees a previously allocated buffer. + * Behavior is undefined if the buffer is still mapped in any process, + * but shall not result in termination of the program or security breaches + * (allowing a process to get access to another process' buffers). + * THIS FUNCTION TAKES OWNERSHIP of the buffer_handle_t which becomes + * invalid after the call. + * + * Returns 0 on success or -errno on error. + */ + int (*free)(struct alloc_device_t* dev, + buffer_handle_t handle); + + /* This hook is OPTIONAL. + * + * If non NULL it will be caused by SurfaceFlinger on dumpsys + */ + void (*dump)(struct alloc_device_t *dev, char *buff, int buff_len); + + void* reserved_proc[7]; +} alloc_device_t; + + +/** convenience API for opening and closing a supported device */ + +static inline int gralloc_open(const struct hw_module_t* module, + struct alloc_device_t** device) { + return module->methods->open(module, + GRALLOC_HARDWARE_GPU0, (struct hw_device_t**)device); +} + +static inline int gralloc_close(struct alloc_device_t* device) { + return device->common.close(&device->common); +} + +__END_DECLS + +#endif // ANDROID_GRALLOC_INTERFACE_H diff -Nru android-tools-4.2.2+git20130218/libhardware/include/hardware/hardware.h android-tools-4.2.2+git20130529/libhardware/include/hardware/hardware.h --- android-tools-4.2.2+git20130218/libhardware/include/hardware/hardware.h 1970-01-01 00:00:00.000000000 +0000 +++ android-tools-4.2.2+git20130529/libhardware/include/hardware/hardware.h 2013-05-29 20:16:54.000000000 +0000 @@ -0,0 +1,230 @@ +/* + * 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 ANDROID_INCLUDE_HARDWARE_HARDWARE_H +#define ANDROID_INCLUDE_HARDWARE_HARDWARE_H + +#include +#include + +#include +#include + +__BEGIN_DECLS + +/* + * Value for the hw_module_t.tag field + */ + +#define MAKE_TAG_CONSTANT(A,B,C,D) (((A) << 24) | ((B) << 16) | ((C) << 8) | (D)) + +#define HARDWARE_MODULE_TAG MAKE_TAG_CONSTANT('H', 'W', 'M', 'T') +#define HARDWARE_DEVICE_TAG MAKE_TAG_CONSTANT('H', 'W', 'D', 'T') + +#define HARDWARE_MAKE_API_VERSION(maj,min) \ + ((((maj) & 0xff) << 8) | ((min) & 0xff)) + +#define HARDWARE_MAKE_API_VERSION_2(maj,min,hdr) \ + ((((maj) & 0xff) << 24) | (((min) & 0xff) << 16) | ((hdr) & 0xffff)) +#define HARDWARE_API_VERSION_2_MAJ_MIN_MASK 0xffff0000 +#define HARDWARE_API_VERSION_2_HEADER_MASK 0x0000ffff + + +/* + * The current HAL API version. + * + * All module implementations must set the hw_module_t.hal_api_version field + * to this value when declaring the module with HAL_MODULE_INFO_SYM. + * + * Note that previous implementations have always set this field to 0. + * Therefore, libhardware HAL API will always consider versions 0.0 and 1.0 + * to be 100% binary compatible. + * + */ +#define HARDWARE_HAL_API_VERSION HARDWARE_MAKE_API_VERSION(1, 0) + +/* + * Helper macros for module implementors. + * + * The derived modules should provide convenience macros for supported + * versions so that implementations can explicitly specify module/device + * versions at definition time. + * + * Use this macro to set the hw_module_t.module_api_version field. + */ +#define HARDWARE_MODULE_API_VERSION(maj,min) HARDWARE_MAKE_API_VERSION(maj,min) +#define HARDWARE_MODULE_API_VERSION_2(maj,min,hdr) HARDWARE_MAKE_API_VERSION_2(maj,min,hdr) + +/* + * Use this macro to set the hw_device_t.version field + */ +#define HARDWARE_DEVICE_API_VERSION(maj,min) HARDWARE_MAKE_API_VERSION(maj,min) +#define HARDWARE_DEVICE_API_VERSION_2(maj,min,hdr) HARDWARE_MAKE_API_VERSION_2(maj,min,hdr) + +struct hw_module_t; +struct hw_module_methods_t; +struct hw_device_t; + +/** + * Every hardware module must have a data structure named HAL_MODULE_INFO_SYM + * and the fields of this data structure must begin with hw_module_t + * followed by module specific information. + */ +typedef struct hw_module_t { + /** tag must be initialized to HARDWARE_MODULE_TAG */ + uint32_t tag; + + /** + * The API version of the implemented module. The module owner is + * responsible for updating the version when a module interface has + * changed. + * + * The derived modules such as gralloc and audio own and manage this field. + * The module user must interpret the version field to decide whether or + * not to inter-operate with the supplied module implementation. + * For example, SurfaceFlinger is responsible for making sure that + * it knows how to manage different versions of the gralloc-module API, + * and AudioFlinger must know how to do the same for audio-module API. + * + * The module API version should include a major and a minor component. + * For example, version 1.0 could be represented as 0x0100. This format + * implies that versions 0x0100-0x01ff are all API-compatible. + * + * In the future, libhardware will expose a hw_get_module_version() + * (or equivalent) function that will take minimum/maximum supported + * versions as arguments and would be able to reject modules with + * versions outside of the supplied range. + */ + uint16_t module_api_version; +#define version_major module_api_version + /** + * version_major/version_minor defines are supplied here for temporary + * source code compatibility. They will be removed in the next version. + * ALL clients must convert to the new version format. + */ + + /** + * The API version of the HAL module interface. This is meant to + * version the hw_module_t, hw_module_methods_t, and hw_device_t + * structures and definitions. + * + * The HAL interface owns this field. Module users/implementations + * must NOT rely on this value for version information. + * + * Presently, 0 is the only valid value. + */ + uint16_t hal_api_version; +#define version_minor hal_api_version + + /** Identifier of module */ + const char *id; + + /** Name of this module */ + const char *name; + + /** Author/owner/implementor of the module */ + const char *author; + + /** Modules methods */ + struct hw_module_methods_t* methods; + + /** module's dso */ + void* dso; + + /** padding to 128 bytes, reserved for future use */ + uint32_t reserved[32-7]; + +} hw_module_t; + +typedef struct hw_module_methods_t { + /** Open a specific device */ + int (*open)(const struct hw_module_t* module, const char* id, + struct hw_device_t** device); + +} hw_module_methods_t; + +/** + * Every device data structure must begin with hw_device_t + * followed by module specific public methods and attributes. + */ +typedef struct hw_device_t { + /** tag must be initialized to HARDWARE_DEVICE_TAG */ + uint32_t tag; + + /** + * Version of the module-specific device API. This value is used by + * the derived-module user to manage different device implementations. + * + * The module user is responsible for checking the module_api_version + * and device version fields to ensure that the user is capable of + * communicating with the specific module implementation. + * + * One module can support multiple devices with different versions. This + * can be useful when a device interface changes in an incompatible way + * but it is still necessary to support older implementations at the same + * time. One such example is the Camera 2.0 API. + * + * This field is interpreted by the module user and is ignored by the + * HAL interface itself. + */ + uint32_t version; + + /** reference to the module this device belongs to */ + struct hw_module_t* module; + + /** padding reserved for future use */ + uint32_t reserved[12]; + + /** Close this device */ + int (*close)(struct hw_device_t* device); + +} hw_device_t; + +/** + * Name of the hal_module_info + */ +#define HAL_MODULE_INFO_SYM HMI + +/** + * Name of the hal_module_info as a string + */ +#define HAL_MODULE_INFO_SYM_AS_STR "HMI" + +/** + * Get the module info associated with a module by id. + * + * @return: 0 == success, <0 == error and *module == NULL + */ +int hw_get_module(const char *id, const struct hw_module_t **module); + +/** + * Get the module info associated with a module instance by class 'class_id' + * and instance 'inst'. + * + * Some modules types necessitate multiple instances. For example audio supports + * multiple concurrent interfaces and thus 'audio' is the module class + * and 'primary' or 'a2dp' are module interfaces. This implies that the files + * providing these modules would be named audio.primary..so and + * audio.a2dp..so + * + * @return: 0 == success, <0 == error and *module == NULL + */ +int hw_get_module_by_class(const char *class_id, const char *inst, + const struct hw_module_t **module); + +__END_DECLS + +#endif /* ANDROID_INCLUDE_HARDWARE_HARDWARE_H */ diff -Nru android-tools-4.2.2+git20130218/libhardware/include/hardware/hwcomposer_defs.h android-tools-4.2.2+git20130529/libhardware/include/hardware/hwcomposer_defs.h --- android-tools-4.2.2+git20130218/libhardware/include/hardware/hwcomposer_defs.h 1970-01-01 00:00:00.000000000 +0000 +++ android-tools-4.2.2+git20130529/libhardware/include/hardware/hwcomposer_defs.h 2013-05-29 20:16:54.000000000 +0000 @@ -0,0 +1,196 @@ +/* + * Copyright (C) 2010 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 ANDROID_INCLUDE_HARDWARE_HWCOMPOSER_DEFS_H +#define ANDROID_INCLUDE_HARDWARE_HWCOMPOSER_DEFS_H + +#include +#include + +#include +#include +#include + +__BEGIN_DECLS + +/*****************************************************************************/ + +#define HWC_HEADER_VERSION 1 + +#define HWC_MODULE_API_VERSION_0_1 HARDWARE_MODULE_API_VERSION(0, 1) + +#define HWC_DEVICE_API_VERSION_1_0 HARDWARE_DEVICE_API_VERSION_2(1, 0, HWC_HEADER_VERSION) +#define HWC_DEVICE_API_VERSION_1_1 HARDWARE_DEVICE_API_VERSION_2(1, 1, HWC_HEADER_VERSION) +#define HWC_DEVICE_API_VERSION_1_2 HARDWARE_DEVICE_API_VERSION_2(1, 2, HWC_HEADER_VERSION) + +enum { + /* hwc_composer_device_t::set failed in EGL */ + HWC_EGL_ERROR = -1 +}; + +/* + * hwc_layer_t::hints values + * Hints are set by the HAL and read by SurfaceFlinger + */ +enum { + /* + * HWC can set the HWC_HINT_TRIPLE_BUFFER hint to indicate to SurfaceFlinger + * that it should triple buffer this layer. Typically HWC does this when + * the layer will be unavailable for use for an extended period of time, + * e.g. if the display will be fetching data directly from the layer and + * the layer can not be modified until after the next set(). + */ + HWC_HINT_TRIPLE_BUFFER = 0x00000001, + + /* + * HWC sets HWC_HINT_CLEAR_FB to tell SurfaceFlinger that it should clear the + * framebuffer with transparent pixels where this layer would be. + * SurfaceFlinger will only honor this flag when the layer has no blending + * + */ + HWC_HINT_CLEAR_FB = 0x00000002 +}; + +/* + * hwc_layer_t::flags values + * Flags are set by SurfaceFlinger and read by the HAL + */ +enum { + /* + * HWC_SKIP_LAYER is set by SurfaceFlnger to indicate that the HAL + * shall not consider this layer for composition as it will be handled + * by SurfaceFlinger (just as if compositionType was set to HWC_OVERLAY). + */ + HWC_SKIP_LAYER = 0x00000001, +}; + +/* + * hwc_layer_t::compositionType values + */ +enum { + /* this layer is to be drawn into the framebuffer by SurfaceFlinger */ + HWC_FRAMEBUFFER = 0, + + /* this layer will be handled in the HWC */ + HWC_OVERLAY = 1, + + /* this is the background layer. it's used to set the background color. + * there is only a single background layer */ + HWC_BACKGROUND = 2, + + /* this layer holds the result of compositing the HWC_FRAMEBUFFER layers. + * Added in HWC_DEVICE_API_VERSION_1_1. */ + HWC_FRAMEBUFFER_TARGET = 3, +}; + +/* + * hwc_layer_t::blending values + */ +enum { + /* no blending */ + HWC_BLENDING_NONE = 0x0100, + + /* ONE / ONE_MINUS_SRC_ALPHA */ + HWC_BLENDING_PREMULT = 0x0105, + + /* SRC_ALPHA / ONE_MINUS_SRC_ALPHA */ + HWC_BLENDING_COVERAGE = 0x0405 +}; + +/* + * hwc_layer_t::transform values + */ +enum { + /* flip source image horizontally */ + HWC_TRANSFORM_FLIP_H = HAL_TRANSFORM_FLIP_H, + /* flip source image vertically */ + HWC_TRANSFORM_FLIP_V = HAL_TRANSFORM_FLIP_V, + /* rotate source image 90 degrees clock-wise */ + HWC_TRANSFORM_ROT_90 = HAL_TRANSFORM_ROT_90, + /* rotate source image 180 degrees */ + HWC_TRANSFORM_ROT_180 = HAL_TRANSFORM_ROT_180, + /* rotate source image 270 degrees clock-wise */ + HWC_TRANSFORM_ROT_270 = HAL_TRANSFORM_ROT_270, +}; + +/* attributes queriable with query() */ +enum { + /* + * Must return 1 if the background layer is supported, 0 otherwise. + */ + HWC_BACKGROUND_LAYER_SUPPORTED = 0, + + /* + * Returns the vsync period in nanoseconds. + * + * This query is not used for HWC_DEVICE_API_VERSION_1_1 and later. + * Instead, the per-display attribute HWC_DISPLAY_VSYNC_PERIOD is used. + */ + HWC_VSYNC_PERIOD = 1, + + /* + * Availability: HWC_DEVICE_API_VERSION_1_1 + * Returns a mask of supported display types. + */ + HWC_DISPLAY_TYPES_SUPPORTED = 2, +}; + +/* display attributes returned by getDisplayAttributes() */ +enum { + /* Indicates the end of an attribute list */ + HWC_DISPLAY_NO_ATTRIBUTE = 0, + + /* The vsync period in nanoseconds */ + HWC_DISPLAY_VSYNC_PERIOD = 1, + + /* The number of pixels in the horizontal and vertical directions. */ + HWC_DISPLAY_WIDTH = 2, + HWC_DISPLAY_HEIGHT = 3, + + /* The number of pixels per thousand inches of this configuration. + * + * Scaling DPI by 1000 allows it to be stored in an int without losing + * too much precision. + * + * If the DPI for a configuration is unavailable or the HWC implementation + * considers it unreliable, it should set these attributes to zero. + */ + HWC_DISPLAY_DPI_X = 4, + HWC_DISPLAY_DPI_Y = 5, +}; + +/* Allowed events for hwc_methods::eventControl() */ +enum { + HWC_EVENT_VSYNC = 0 +}; + +/* Display types and associated mask bits. */ +enum { + HWC_DISPLAY_PRIMARY = 0, + HWC_DISPLAY_EXTERNAL = 1, // HDMI, DP, etc. + HWC_NUM_DISPLAY_TYPES +}; + +enum { + HWC_DISPLAY_PRIMARY_BIT = 1 << HWC_DISPLAY_PRIMARY, + HWC_DISPLAY_EXTERNAL_BIT = 1 << HWC_DISPLAY_EXTERNAL, +}; + +/*****************************************************************************/ + +__END_DECLS + +#endif /* ANDROID_INCLUDE_HARDWARE_HWCOMPOSER_DEFS_H */ diff -Nru android-tools-4.2.2+git20130218/libhardware/include/hardware/hwcomposer.h android-tools-4.2.2+git20130529/libhardware/include/hardware/hwcomposer.h --- android-tools-4.2.2+git20130218/libhardware/include/hardware/hwcomposer.h 1970-01-01 00:00:00.000000000 +0000 +++ android-tools-4.2.2+git20130529/libhardware/include/hardware/hwcomposer.h 2013-05-29 20:16:54.000000000 +0000 @@ -0,0 +1,571 @@ +/* + * Copyright (C) 2010 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 ANDROID_INCLUDE_HARDWARE_HWCOMPOSER_H +#define ANDROID_INCLUDE_HARDWARE_HWCOMPOSER_H + +#include +#include + +#include +#include +#include + +#include + +__BEGIN_DECLS + +/*****************************************************************************/ + +/* for compatibility */ +#define HWC_MODULE_API_VERSION HWC_MODULE_API_VERSION_0_1 +#define HWC_DEVICE_API_VERSION HWC_DEVICE_API_VERSION_0_1 +#define HWC_API_VERSION HWC_DEVICE_API_VERSION + +/*****************************************************************************/ + +/** + * The id of this module + */ +#define HWC_HARDWARE_MODULE_ID "hwcomposer" + +/** + * Name of the sensors device to open + */ +#define HWC_HARDWARE_COMPOSER "composer" + +typedef struct hwc_rect { + int left; + int top; + int right; + int bottom; +} hwc_rect_t; + +typedef struct hwc_region { + size_t numRects; + hwc_rect_t const* rects; +} hwc_region_t; + +typedef struct hwc_color { + uint8_t r; + uint8_t g; + uint8_t b; + uint8_t a; +} hwc_color_t; + +typedef struct hwc_layer_1 { + /* + * compositionType is used to specify this layer's type and is set by either + * the hardware composer implementation, or by the caller (see below). + * + * This field is always reset to HWC_BACKGROUND or HWC_FRAMEBUFFER + * before (*prepare)() is called when the HWC_GEOMETRY_CHANGED flag is + * also set, otherwise, this field is preserved between (*prepare)() + * calls. + * + * HWC_BACKGROUND + * Always set by the caller before calling (*prepare)(), this value + * indicates this is a special "background" layer. The only valid field + * is backgroundColor. + * The HWC can toggle this value to HWC_FRAMEBUFFER to indicate it CANNOT + * handle the background color. + * + * + * HWC_FRAMEBUFFER_TARGET + * Always set by the caller before calling (*prepare)(), this value + * indicates this layer is the framebuffer surface used as the target of + * OpenGL ES composition. If the HWC sets all other layers to HWC_OVERLAY + * or HWC_BACKGROUND, then no OpenGL ES composition will be done, and + * this layer should be ignored during set(). + * + * This flag (and the framebuffer surface layer) will only be used if the + * HWC version is HWC_DEVICE_API_VERSION_1_1 or higher. In older versions, + * the OpenGL ES target surface is communicated by the (dpy, sur) fields + * in hwc_compositor_device_1_t. + * + * This value cannot be set by the HWC implementation. + * + * + * HWC_FRAMEBUFFER + * Set by the caller before calling (*prepare)() ONLY when the + * HWC_GEOMETRY_CHANGED flag is also set. + * + * Set by the HWC implementation during (*prepare)(), this indicates + * that the layer will be drawn into the framebuffer using OpenGL ES. + * The HWC can toggle this value to HWC_OVERLAY to indicate it will + * handle the layer. + * + * + * HWC_OVERLAY + * Set by the HWC implementation during (*prepare)(), this indicates + * that the layer will be handled by the HWC (ie: it must not be + * composited with OpenGL ES). + * + */ + int32_t compositionType; + + /* + * hints is bit mask set by the HWC implementation during (*prepare)(). + * It is preserved between (*prepare)() calls, unless the + * HWC_GEOMETRY_CHANGED flag is set, in which case it is reset to 0. + * + * see hwc_layer_t::hints + */ + uint32_t hints; + + /* see hwc_layer_t::flags */ + uint32_t flags; + + union { + /* color of the background. hwc_color_t.a is ignored */ + hwc_color_t backgroundColor; + + struct { + /* handle of buffer to compose. This handle is guaranteed to have been + * allocated from gralloc using the GRALLOC_USAGE_HW_COMPOSER usage flag. If + * the layer's handle is unchanged across two consecutive prepare calls and + * the HWC_GEOMETRY_CHANGED flag is not set for the second call then the + * HWComposer implementation may assume that the contents of the buffer have + * not changed. */ + buffer_handle_t handle; + + /* transformation to apply to the buffer during composition */ + uint32_t transform; + + /* blending to apply during composition */ + int32_t blending; + + /* area of the source to consider, the origin is the top-left corner of + * the buffer */ + hwc_rect_t sourceCrop; + + /* where to composite the sourceCrop onto the display. The sourceCrop + * is scaled using linear filtering to the displayFrame. The origin is the + * top-left corner of the screen. + */ + hwc_rect_t displayFrame; + + /* visible region in screen space. The origin is the + * top-left corner of the screen. + * The visible region INCLUDES areas overlapped by a translucent layer. + */ + hwc_region_t visibleRegionScreen; + + /* Sync fence object that will be signaled when the buffer's + * contents are available. May be -1 if the contents are already + * available. This field is only valid during set(), and should be + * ignored during prepare(). The set() call must not wait for the + * fence to be signaled before returning, but the HWC must wait for + * all buffers to be signaled before reading from them. + * + * HWC_FRAMEBUFFER layers will never have an acquire fence, since + * reads from them are complete before the framebuffer is ready for + * display. + * + * The HWC takes ownership of the acquireFenceFd and is responsible + * for closing it when no longer needed. + */ + int acquireFenceFd; + + /* During set() the HWC must set this field to a file descriptor for + * a sync fence object that will signal after the HWC has finished + * reading from the buffer. The field is ignored by prepare(). Each + * layer should have a unique file descriptor, even if more than one + * refer to the same underlying fence object; this allows each to be + * closed independently. + * + * If buffer reads can complete at significantly different times, + * then using independent fences is preferred. For example, if the + * HWC handles some layers with a blit engine and others with + * overlays, then the blit layers can be reused immediately after + * the blit completes, but the overlay layers can't be reused until + * a subsequent frame has been displayed. + * + * Since HWC doesn't read from HWC_FRAMEBUFFER layers, it shouldn't + * produce a release fence for them. The releaseFenceFd will be -1 + * for these layers when set() is called. + * + * The HWC client taks ownership of the releaseFenceFd and is + * responsible for closing it when no longer needed. + */ + int releaseFenceFd; + }; + }; + + /* Allow for expansion w/o breaking binary compatibility. + * Pad layer to 96 bytes, assuming 32-bit pointers. + */ + int32_t reserved[24 - 18]; + +} hwc_layer_1_t; + +/* This represents a display, typically an EGLDisplay object */ +typedef void* hwc_display_t; + +/* This represents a surface, typically an EGLSurface object */ +typedef void* hwc_surface_t; + +/* + * hwc_display_contents_1_t::flags values + */ +enum { + /* + * HWC_GEOMETRY_CHANGED is set by SurfaceFlinger to indicate that the list + * passed to (*prepare)() has changed by more than just the buffer handles + * and acquire fences. + */ + HWC_GEOMETRY_CHANGED = 0x00000001, +}; + +/* + * Description of the contents to output on a display. + * + * This is the top-level structure passed to the prepare and set calls to + * negotiate and commit the composition of a display image. + */ +typedef struct hwc_display_contents_1 { + /* File descriptor referring to a Sync HAL fence object which will signal + * when this composition is retired. For a physical display, a composition + * is retired when it has been replaced on-screen by a subsequent set. For + * a virtual display, the composition is retired when the writes to + * outputBuffer are complete and can be read. The fence object is created + * and returned by the set call; this field will be -1 on entry to prepare + * and set. SurfaceFlinger will close the returned file descriptor. + */ + int retireFenceFd; + + union { + /* Fields only relevant for HWC_DEVICE_VERSION_1_0. */ + struct { + /* (dpy, sur) is the target of SurfaceFlinger's OpenGL ES + * composition for HWC_DEVICE_VERSION_1_0. They aren't relevant to + * prepare. The set call should commit this surface atomically to + * the display along with any overlay layers. + */ + hwc_display_t dpy; + hwc_surface_t sur; + }; + + /* Fields only relevant for HWC_DEVICE_VERSION_1_2 and later. */ + struct { + /* outbuf is the buffer that receives the composed image for + * virtual displays. Writes to the outbuf must wait until + * outbufAcquireFenceFd signals. A fence that will signal when + * writes to outbuf are complete should be returned in + * retireFenceFd. + * + * For physical displays, outbuf will be NULL. + */ + buffer_handle_t outbuf; + + /* File descriptor for a fence that will signal when outbuf is + * ready to be written. The h/w composer is responsible for closing + * this when no longer needed. + * + * Will be -1 whenever outbuf is NULL, or when the outbuf can be + * written immediately. + */ + int outbufAcquireFenceFd; + }; + }; + + /* List of layers that will be composed on the display. The buffer handles + * in the list will be unique. If numHwLayers is 0, all composition will be + * performed by SurfaceFlinger. + */ + uint32_t flags; + size_t numHwLayers; + hwc_layer_1_t hwLayers[0]; + +} hwc_display_contents_1_t; + +/* see hwc_composer_device::registerProcs() + * All of the callbacks are required and non-NULL unless otherwise noted. + */ +typedef struct hwc_procs { + /* + * (*invalidate)() triggers a screen refresh, in particular prepare and set + * will be called shortly after this call is made. Note that there is + * NO GUARANTEE that the screen refresh will happen after invalidate() + * returns (in particular, it could happen before). + * invalidate() is GUARANTEED TO NOT CALL BACK into the h/w composer HAL and + * it is safe to call invalidate() from any of hwc_composer_device + * hooks, unless noted otherwise. + */ + void (*invalidate)(const struct hwc_procs* procs); + + /* + * (*vsync)() is called by the h/w composer HAL when a vsync event is + * received and HWC_EVENT_VSYNC is enabled on a display + * (see: hwc_event_control). + * + * the "disp" parameter indicates which display the vsync event is for. + * the "timestamp" parameter is the system monotonic clock timestamp in + * nanosecond of when the vsync event happened. + * + * vsync() is GUARANTEED TO NOT CALL BACK into the h/w composer HAL. + * + * It is expected that vsync() is called from a thread of at least + * HAL_PRIORITY_URGENT_DISPLAY with as little latency as possible, + * typically less than 0.5 ms. + * + * It is a (silent) error to have HWC_EVENT_VSYNC enabled when calling + * hwc_composer_device.set(..., 0, 0, 0) (screen off). The implementation + * can either stop or continue to process VSYNC events, but must not + * crash or cause other problems. + */ + void (*vsync)(const struct hwc_procs* procs, int disp, int64_t timestamp); + + /* + * (*hotplug)() is called by the h/w composer HAL when a display is + * connected or disconnected. The PRIMARY display is always connected and + * the hotplug callback should not be called for it. + * + * The disp parameter indicates which display type this event is for. + * The connected parameter indicates whether the display has just been + * connected (1) or disconnected (0). + * + * The hotplug() callback may call back into the h/w composer on the same + * thread to query refresh rate and dpi for the display. Additionally, + * other threads may be calling into the h/w composer while the callback + * is in progress. + * + * The h/w composer must serialize calls to the hotplug callback; only + * one thread may call it at a time. + * + * This callback will be NULL if the h/w composer is using + * HWC_DEVICE_API_VERSION_1_0. + */ + void (*hotplug)(const struct hwc_procs* procs, int disp, int connected); + +} hwc_procs_t; + + +/*****************************************************************************/ + +typedef struct hwc_module { + struct hw_module_t common; +} hwc_module_t; + +typedef struct hwc_composer_device_1 { + struct hw_device_t common; + + /* + * (*prepare)() is called for each frame before composition and is used by + * SurfaceFlinger to determine what composition steps the HWC can handle. + * + * (*prepare)() can be called more than once, the last call prevails. + * + * The HWC responds by setting the compositionType field in each layer to + * either HWC_FRAMEBUFFER or HWC_OVERLAY. In the former case, the + * composition for the layer is handled by SurfaceFlinger with OpenGL ES, + * in the later case, the HWC will have to handle the layer's composition. + * compositionType and hints are preserved between (*prepare)() calles + * unless the HWC_GEOMETRY_CHANGED flag is set. + * + * (*prepare)() is called with HWC_GEOMETRY_CHANGED to indicate that the + * list's geometry has changed, that is, when more than just the buffer's + * handles have been updated. Typically this happens (but is not limited to) + * when a window is added, removed, resized or moved. In this case + * compositionType and hints are reset to their default value. + * + * For HWC 1.0, numDisplays will always be one, and displays[0] will be + * non-NULL. + * + * For HWC 1.1, numDisplays will always be HWC_NUM_DISPLAY_TYPES. Entries + * for unsupported or disabled/disconnected display types will be NULL. + * + * For HWC 1.2 and later, numDisplays will be HWC_NUM_DISPLAY_TYPES or more. + * The extra entries correspond to enabled virtual displays, and will be + * non-NULL. In HWC 1.2, support for one virtual display is required, and + * no more than one will be used. Future HWC versions might require more. + * + * returns: 0 on success. An negative error code on error. If an error is + * returned, SurfaceFlinger will assume that none of the layer will be + * handled by the HWC. + */ + int (*prepare)(struct hwc_composer_device_1 *dev, + size_t numDisplays, hwc_display_contents_1_t** displays); + + /* + * (*set)() is used in place of eglSwapBuffers(), and assumes the same + * functionality, except it also commits the work list atomically with + * the actual eglSwapBuffers(). + * + * The layer lists are guaranteed to be the same as the ones returned from + * the last call to (*prepare)(). + * + * When this call returns the caller assumes that the displays will be + * updated in the near future with the content of their work lists, without + * artifacts during the transition from the previous frame. + * + * A display with zero layers indicates that the entire composition has + * been handled by SurfaceFlinger with OpenGL ES. In this case, (*set)() + * behaves just like eglSwapBuffers(). + * + * For HWC 1.0, numDisplays will always be one, and displays[0] will be + * non-NULL. + * + * For HWC 1.1, numDisplays will always be HWC_NUM_DISPLAY_TYPES. Entries + * for unsupported or disabled/disconnected display types will be NULL. + * + * For HWC 1.2 and later, numDisplays will be HWC_NUM_DISPLAY_TYPES or more. + * The extra entries correspond to enabled virtual displays, and will be + * non-NULL. In HWC 1.2, support for one virtual display is required, and + * no more than one will be used. Future HWC versions might require more. + * + * IMPORTANT NOTE: There is an implicit layer containing opaque black + * pixels behind all the layers in the list. It is the responsibility of + * the hwcomposer module to make sure black pixels are output (or blended + * from). + * + * IMPORTANT NOTE: In the event of an error this call *MUST* still cause + * any fences returned in the previous call to set to eventually become + * signaled. The caller may have already issued wait commands on these + * fences, and having set return without causing those fences to signal + * will likely result in a deadlock. + * + * returns: 0 on success. A negative error code on error: + * HWC_EGL_ERROR: eglGetError() will provide the proper error code (only + * allowed prior to HWComposer 1.1) + * Another code for non EGL errors. + */ + int (*set)(struct hwc_composer_device_1 *dev, + size_t numDisplays, hwc_display_contents_1_t** displays); + + /* + * eventControl(..., event, enabled) + * Enables or disables h/w composer events for a display. + * + * eventControl can be called from any thread and takes effect + * immediately. + * + * Supported events are: + * HWC_EVENT_VSYNC + * + * returns -EINVAL if the "event" parameter is not one of the value above + * or if the "enabled" parameter is not 0 or 1. + */ + int (*eventControl)(struct hwc_composer_device_1* dev, int disp, + int event, int enabled); + + /* + * blank(..., blank) + * Blanks or unblanks a display's screen. + * + * Turns the screen off when blank is nonzero, on when blank is zero. + * Multiple sequential calls with the same blank value must be supported. + * The screen state transition must be be complete when the function + * returns. + * + * returns 0 on success, negative on error. + */ + int (*blank)(struct hwc_composer_device_1* dev, int disp, int blank); + + /* + * Used to retrieve information about the h/w composer + * + * Returns 0 on success or -errno on error. + */ + int (*query)(struct hwc_composer_device_1* dev, int what, int* value); + + /* + * (*registerProcs)() registers callbacks that the h/w composer HAL can + * later use. It will be called immediately after the composer device is + * opened with non-NULL procs. It is FORBIDDEN to call any of the callbacks + * from within registerProcs(). registerProcs() must save the hwc_procs_t + * pointer which is needed when calling a registered callback. + */ + void (*registerProcs)(struct hwc_composer_device_1* dev, + hwc_procs_t const* procs); + + /* + * This field is OPTIONAL and can be NULL. + * + * If non NULL it will be called by SurfaceFlinger on dumpsys + */ + void (*dump)(struct hwc_composer_device_1* dev, char *buff, int buff_len); + + /* + * (*getDisplayConfigs)() returns handles for the configurations available + * on the connected display. These handles must remain valid as long as the + * display is connected. + * + * Configuration handles are written to configs. The number of entries + * allocated by the caller is passed in *numConfigs; getDisplayConfigs must + * not try to write more than this number of config handles. On return, the + * total number of configurations available for the display is returned in + * *numConfigs. If *numConfigs is zero on entry, then configs may be NULL. + * + * HWC_DEVICE_API_VERSION_1_1 does not provide a way to choose a config. + * For displays that support multiple configurations, the h/w composer + * implementation should choose one and report it as the first config in + * the list. Reporting the not-chosen configs is not required. + * + * Returns 0 on success or -errno on error. If disp is a hotpluggable + * display type and no display is connected, an error should be returned. + * + * This field is REQUIRED for HWC_DEVICE_API_VERSION_1_1 and later. + * It should be NULL for previous versions. + */ + int (*getDisplayConfigs)(struct hwc_composer_device_1* dev, int disp, + uint32_t* configs, size_t* numConfigs); + + /* + * (*getDisplayAttributes)() returns attributes for a specific config of a + * connected display. The config parameter is one of the config handles + * returned by getDisplayConfigs. + * + * The list of attributes to return is provided in the attributes + * parameter, terminated by HWC_DISPLAY_NO_ATTRIBUTE. The value for each + * requested attribute is written in order to the values array. The + * HWC_DISPLAY_NO_ATTRIBUTE attribute does not have a value, so the values + * array will have one less value than the attributes array. + * + * This field is REQUIRED for HWC_DEVICE_API_VERSION_1_1 and later. + * It should be NULL for previous versions. + * + * If disp is a hotpluggable display type and no display is connected, + * or if config is not a valid configuration for the display, a negative + * value should be returned. + */ + int (*getDisplayAttributes)(struct hwc_composer_device_1* dev, int disp, + uint32_t config, const uint32_t* attributes, int32_t* values); + + /* + * Reserved for future use. Must be NULL. + */ + void* reserved_proc[4]; + +} hwc_composer_device_1_t; + +/** convenience API for opening and closing a device */ + +static inline int hwc_open_1(const struct hw_module_t* module, + hwc_composer_device_1_t** device) { + return module->methods->open(module, + HWC_HARDWARE_COMPOSER, (struct hw_device_t**)device); +} + +static inline int hwc_close_1(hwc_composer_device_1_t* device) { + return device->common.close(&device->common); +} + +/*****************************************************************************/ + +__END_DECLS + +#endif /* ANDROID_INCLUDE_HARDWARE_HWCOMPOSER_H */ diff -Nru android-tools-4.2.2+git20130218/libhardware/include/hardware/keymaster.h android-tools-4.2.2+git20130529/libhardware/include/hardware/keymaster.h --- android-tools-4.2.2+git20130218/libhardware/include/hardware/keymaster.h 1970-01-01 00:00:00.000000000 +0000 +++ android-tools-4.2.2+git20130529/libhardware/include/hardware/keymaster.h 2013-05-29 20:16:54.000000000 +0000 @@ -0,0 +1,214 @@ +/* + * Copyright (C) 2011 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 ANDROID_HARDWARE_KEYMASTER_H +#define ANDROID_HARDWARE_KEYMASTER_H + +#include +#include +#include + +#include + +__BEGIN_DECLS + +/** + * The id of this module + */ +#define KEYSTORE_HARDWARE_MODULE_ID "keystore" + +#define KEYSTORE_KEYMASTER "keymaster" + +/** + * The API level of this version of the header. The allows the implementing + * module to recognize which API level of the client it is dealing with in + * the case of pre-compiled binary clients. + */ +#define KEYMASTER_API_VERSION 1 + +/** + * Flags for keymaster_device::flags + */ +enum { + /* + * Indicates this keymaster implementation does not have hardware that + * keeps private keys out of user space. + * + * This should not be implemented on anything other than the default + * implementation. + */ + KEYMASTER_SOFTWARE_ONLY = 0x00000001, +}; + +struct keystore_module { + hw_module_t common; +}; + +/** + * Asymmetric key pair types. + */ +typedef enum { + TYPE_RSA = 1, +} keymaster_keypair_t; + +/** + * Parameters needed to generate an RSA key. + */ +typedef struct { + uint32_t modulus_size; + uint64_t public_exponent; +} keymaster_rsa_keygen_params_t; + +/** + * Digest type used for RSA operations. + */ +typedef enum { + DIGEST_NONE, +} keymaster_rsa_digest_t; + +/** + * Type of padding used for RSA operations. + */ +typedef enum { + PADDING_NONE, +} keymaster_rsa_padding_t; + +typedef struct { + keymaster_rsa_digest_t digest_type; + keymaster_rsa_padding_t padding_type; +} keymaster_rsa_sign_params_t; + +/** + * The parameters that can be set for a given keymaster implementation. + */ +struct keymaster_device { + struct hw_device_t common; + + uint32_t client_version; + + /** + * See flags defined for keymaster_device::flags above. + */ + uint32_t flags; + + void* context; + + /** + * Generates a public and private key. The key-blob returned is opaque + * and must subsequently provided for signing and verification. + * + * Returns: 0 on success or an error code less than 0. + */ + int (*generate_keypair)(const struct keymaster_device* dev, + const keymaster_keypair_t key_type, const void* key_params, + uint8_t** key_blob, size_t* key_blob_length); + + /** + * Imports a public and private key pair. The imported keys will be in + * PKCS#8 format with DER encoding (Java standard). The key-blob + * returned is opaque and will be subsequently provided for signing + * and verification. + * + * Returns: 0 on success or an error code less than 0. + */ + int (*import_keypair)(const struct keymaster_device* dev, + const uint8_t* key, const size_t key_length, + uint8_t** key_blob, size_t* key_blob_length); + + /** + * Gets the public key part of a key pair. The public key must be in + * X.509 format (Java standard) encoded byte array. + * + * Returns: 0 on success or an error code less than 0. + * On error, x509_data should not be allocated. + */ + int (*get_keypair_public)(const struct keymaster_device* dev, + const uint8_t* key_blob, const size_t key_blob_length, + uint8_t** x509_data, size_t* x509_data_length); + + /** + * Deletes the key pair associated with the key blob. + * + * This function is optional and should be set to NULL if it is not + * implemented. + * + * Returns 0 on success or an error code less than 0. + */ + int (*delete_keypair)(const struct keymaster_device* dev, + const uint8_t* key_blob, const size_t key_blob_length); + + /** + * Deletes all keys in the hardware keystore. Used when keystore is + * reset completely. + * + * This function is optional and should be set to NULL if it is not + * implemented. + * + * Returns 0 on success or an error code less than 0. + */ + int (*delete_all)(const struct keymaster_device* dev); + + /** + * Signs data using a key-blob generated before. This can use either + * an asymmetric key or a secret key. + * + * Returns: 0 on success or an error code less than 0. + */ + int (*sign_data)(const struct keymaster_device* dev, + const void* signing_params, + const uint8_t* key_blob, const size_t key_blob_length, + const uint8_t* data, const size_t data_length, + uint8_t** signed_data, size_t* signed_data_length); + + /** + * Verifies data signed with a key-blob. This can use either + * an asymmetric key or a secret key. + * + * Returns: 0 on successful verification or an error code less than 0. + */ + int (*verify_data)(const struct keymaster_device* dev, + const void* signing_params, + const uint8_t* key_blob, const size_t key_blob_length, + const uint8_t* signed_data, const size_t signed_data_length, + const uint8_t* signature, const size_t signature_length); +}; +typedef struct keymaster_device keymaster_device_t; + + +/* Convenience API for opening and closing keymaster devices */ + +static inline int keymaster_open(const struct hw_module_t* module, + keymaster_device_t** device) +{ + int rc = module->methods->open(module, KEYSTORE_KEYMASTER, + (struct hw_device_t**) device); + + if (!rc) { + (*device)->client_version = KEYMASTER_API_VERSION; + } + + return rc; +} + +static inline int keymaster_close(keymaster_device_t* device) +{ + return device->common.close(&device->common); +} + +__END_DECLS + +#endif // ANDROID_HARDWARE_KEYMASTER_H + diff -Nru android-tools-4.2.2+git20130218/libhardware/include/hardware/lights.h android-tools-4.2.2+git20130529/libhardware/include/hardware/lights.h --- android-tools-4.2.2+git20130218/libhardware/include/hardware/lights.h 1970-01-01 00:00:00.000000000 +0000 +++ android-tools-4.2.2+git20130529/libhardware/include/hardware/lights.h 2013-05-29 20:16:54.000000000 +0000 @@ -0,0 +1,137 @@ +/* + * 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 ANDROID_LIGHTS_INTERFACE_H +#define ANDROID_LIGHTS_INTERFACE_H + +#include +#include +#include + +#include + +__BEGIN_DECLS + +/** + * The id of this module + */ +#define LIGHTS_HARDWARE_MODULE_ID "lights" + +/* + * These light IDs correspond to logical lights, not physical. + * So for example, if your INDICATOR light is in line with your + * BUTTONS, it might make sense to also light the INDICATOR + * light to a reasonable color when the BUTTONS are lit. + */ +#define LIGHT_ID_BACKLIGHT "backlight" +#define LIGHT_ID_KEYBOARD "keyboard" +#define LIGHT_ID_BUTTONS "buttons" +#define LIGHT_ID_BATTERY "battery" +#define LIGHT_ID_NOTIFICATIONS "notifications" +#define LIGHT_ID_ATTENTION "attention" + +/* + * These lights aren't currently supported by the higher + * layers, but could be someday, so we have the constants + * here now. + */ +#define LIGHT_ID_BLUETOOTH "bluetooth" +#define LIGHT_ID_WIFI "wifi" + +/* ************************************************************************ + * Flash modes for the flashMode field of light_state_t. + */ + +#define LIGHT_FLASH_NONE 0 + +/** + * To flash the light at a given rate, set flashMode to LIGHT_FLASH_TIMED, + * and then flashOnMS should be set to the number of milliseconds to turn + * the light on, followed by the number of milliseconds to turn the light + * off. + */ +#define LIGHT_FLASH_TIMED 1 + +/** + * To flash the light using hardware assist, set flashMode to + * the hardware mode. + */ +#define LIGHT_FLASH_HARDWARE 2 + +/** + * Light brightness is managed by a user setting. + */ +#define BRIGHTNESS_MODE_USER 0 + +/** + * Light brightness is managed by a light sensor. + */ +#define BRIGHTNESS_MODE_SENSOR 1 + +/** + * The parameters that can be set for a given light. + * + * Not all lights must support all parameters. If you + * can do something backward-compatible, you should. + */ +struct light_state_t { + /** + * The color of the LED in ARGB. + * + * Do your best here. + * - If your light can only do red or green, if they ask for blue, + * you should do green. + * - If you can only do a brightness ramp, then use this formula: + * unsigned char brightness = ((77*((color>>16)&0x00ff)) + * + (150*((color>>8)&0x00ff)) + (29*(color&0x00ff))) >> 8; + * - If you can only do on or off, 0 is off, anything else is on. + * + * The high byte should be ignored. Callers will set it to 0xff (which + * would correspond to 255 alpha). + */ + unsigned int color; + + /** + * See the LIGHT_FLASH_* constants + */ + int flashMode; + int flashOnMS; + int flashOffMS; + + /** + * Policy used by the framework to manage the light's brightness. + * Currently the values are BRIGHTNESS_MODE_USER and BRIGHTNESS_MODE_SENSOR. + */ + int brightnessMode; +}; + +struct light_device_t { + struct hw_device_t common; + + /** + * Set the provided lights to the provided values. + * + * Returns: 0 on succes, error code on failure. + */ + int (*set_light)(struct light_device_t* dev, + struct light_state_t const* state); +}; + + +__END_DECLS + +#endif // ANDROID_LIGHTS_INTERFACE_H + diff -Nru android-tools-4.2.2+git20130218/libhardware/include/hardware/local_time_hal.h android-tools-4.2.2+git20130529/libhardware/include/hardware/local_time_hal.h --- android-tools-4.2.2+git20130218/libhardware/include/hardware/local_time_hal.h 1970-01-01 00:00:00.000000000 +0000 +++ android-tools-4.2.2+git20130529/libhardware/include/hardware/local_time_hal.h 2013-05-29 20:16:54.000000000 +0000 @@ -0,0 +1,117 @@ +/* + * Copyright (C) 2011 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 ANDROID_LOCAL_TIME_HAL_INTERFACE_H +#define ANDROID_LOCAL_TIME_HAL_INTERFACE_H + +#include + +#include + +__BEGIN_DECLS + +/** + * The id of this module + */ +#define LOCAL_TIME_HARDWARE_MODULE_ID "local_time" + +/** + * Name of the local time devices to open + */ +#define LOCAL_TIME_HARDWARE_INTERFACE "local_time_hw_if" + +/**********************************************************************/ + +/** + * A structure used to collect low level sync data in a lab environment. Most + * HAL implementations will never need this structure. + */ +struct local_time_debug_event { + int64_t local_timesync_event_id; + int64_t local_time; +}; + +/** + * Every hardware module must have a data structure named HAL_MODULE_INFO_SYM + * and the fields of this data structure must begin with hw_module_t + * followed by module specific information. + */ +struct local_time_module { + struct hw_module_t common; +}; + +struct local_time_hw_device { + struct hw_device_t common; + + /** + * + * Returns the current value of the system wide local time counter + */ + int64_t (*get_local_time)(struct local_time_hw_device* dev); + + /** + * + * Returns the nominal frequency (in hertz) of the system wide local time + * counter + */ + uint64_t (*get_local_freq)(struct local_time_hw_device* dev); + + /** + * + * Sets the HW slew rate of oscillator which drives the system wide local + * time counter. On success, platforms should return 0. Platforms which + * do not support HW slew should leave this method set to NULL. + * + * Valid values for rate range from MIN_INT16 to MAX_INT16. Platform + * implementations should attempt map this range linearly to the min/max + * slew rate of their hardware. + */ + int (*set_local_slew)(struct local_time_hw_device* dev, int16_t rate); + + /** + * + * A method used to collect low level sync data in a lab environments. + * Most HAL implementations will simply set this member to NULL, or return + * -EINVAL to indicate that this functionality is not supported. + * Production HALs should never support this method. + */ + int (*get_debug_log)(struct local_time_hw_device* dev, + struct local_time_debug_event* records, + int max_records); +}; + +typedef struct local_time_hw_device local_time_hw_device_t; + +/** convenience API for opening and closing a supported device */ + +static inline int local_time_hw_device_open( + const struct hw_module_t* module, + struct local_time_hw_device** device) +{ + return module->methods->open(module, LOCAL_TIME_HARDWARE_INTERFACE, + (struct hw_device_t**)device); +} + +static inline int local_time_hw_device_close(struct local_time_hw_device* device) +{ + return device->common.close(&device->common); +} + + +__END_DECLS + +#endif // ANDROID_LOCAL_TIME_INTERFACE_H diff -Nru android-tools-4.2.2+git20130218/libhardware/include/hardware/nfc.h android-tools-4.2.2+git20130529/libhardware/include/hardware/nfc.h --- android-tools-4.2.2+git20130218/libhardware/include/hardware/nfc.h 1970-01-01 00:00:00.000000000 +0000 +++ android-tools-4.2.2+git20130529/libhardware/include/hardware/nfc.h 2013-05-29 20:16:54.000000000 +0000 @@ -0,0 +1,276 @@ +/* + * Copyright (C) 2011, 2012 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 ANDROID_NFC_HAL_INTERFACE_H +#define ANDROID_NFC_HAL_INTERFACE_H + +#include +#include +#include +#include + +#include + +__BEGIN_DECLS + + +/* NFC device HAL for NCI-based NFC controllers. + * + * This HAL allows NCI silicon vendors to make use + * of the core NCI stack in Android for their own silicon. + * + * The responibilities of the NCI HAL implementation + * are as follows: + * + * - Implement the transport to the NFC controller + * - Implement each of the HAL methods specified below as applicable to their silicon + * - Pass up received NCI messages from the controller to the stack + * + * A simplified timeline of NCI HAL method calls: + * 1) Core NCI stack calls open() + * 2) Core NCI stack executes CORE_RESET and CORE_INIT through calls to write() + * 3) Core NCI stack calls core_initialized() to allow HAL to do post-init configuration + * 4) Core NCI stack calls pre_discover() to allow HAL to prepare for RF discovery + * 5) Core NCI stack starts discovery through calls to write() + * 6) Core NCI stack stops discovery through calls to write() (e.g. screen turns off) + * 7) Core NCI stack calls pre_discover() to prepare for RF discovery (e.g. screen turned back on) + * 8) Core NCI stack starts discovery through calls to write() + * ... + * ... + * 9) Core NCI stack calls close() + */ +#define NFC_NCI_HARDWARE_MODULE_ID "nfc_nci" +#define NFC_NCI_CONTROLLER "nci" + +/* + * nfc_nci_module_t should contain module-specific parameters + */ +typedef struct nfc_nci_module_t { + struct hw_module_t common; +} nfc_nci_module_t; + +/* + * HAL events that can be passed back to the stack + */ +typedef uint8_t nfc_event_t; + +enum { + HAL_NFC_OPEN_CPLT_EVT = 0x00, + HAL_NFC_CLOSE_CPLT_EVT = 0x01, + HAL_NFC_POST_INIT_CPLT_EVT = 0x02, + HAL_NFC_PRE_DISCOVER_CPLT_EVT = 0x03, + HAL_NFC_REQUEST_CONTROL_EVT = 0x04, + HAL_NFC_RELEASE_CONTROL_EVT = 0x05, + HAL_NFC_ERROR_EVT = 0x06 +}; + +/* + * Allowed status return values for each of the HAL methods + */ +typedef uint8_t nfc_status_t; + +enum { + HAL_NFC_STATUS_OK = 0x00, + HAL_NFC_STATUS_FAILED = 0x01, + HAL_NFC_STATUS_ERR_TRANSPORT = 0x02, + HAL_NFC_STATUS_ERR_CMD_TIMEOUT = 0x03, + HAL_NFC_STATUS_REFUSED = 0x04 +}; + +/* + * The callback passed in from the NFC stack that the HAL + * can use to pass events back to the stack. + */ +typedef void (nfc_stack_callback_t) (nfc_event_t event, nfc_status_t event_status); + +/* + * The callback passed in from the NFC stack that the HAL + * can use to pass incomming data to the stack. + */ +typedef void (nfc_stack_data_callback_t) (uint16_t data_len, uint8_t* p_data); + +/* nfc_nci_device_t starts with a hw_device_t struct, + * followed by device-specific methods and members. + * + * All methods in the NCI HAL are asynchronous. + */ +typedef struct nfc_nci_device { + struct hw_device_t common; + /* + * (*open)() Opens the NFC controller device and performs initialization. + * This may include patch download and other vendor-specific initialization. + * + * If open completes successfully, the controller should be ready to perform + * NCI initialization - ie accept CORE_RESET and subsequent commands through + * the write() call. + * + * If open() returns 0, the NCI stack will wait for a HAL_NFC_OPEN_CPLT_EVT + * before continuing. + * + * If open() returns any other value, the NCI stack will stop. + * + */ + int (*open)(const struct nfc_nci_device *p_dev, nfc_stack_callback_t *p_cback, + nfc_stack_data_callback_t *p_data_cback); + + /* + * (*write)() Performs an NCI write. + * + * This method may queue writes and return immediately. The only + * requirement is that the writes are executed in order. + */ + int (*write)(const struct nfc_nci_device *p_dev, uint16_t data_len, const uint8_t *p_data); + + /* + * (*core_initialized)() is called after the CORE_INIT_RSP is received from the NFCC. + * At this time, the HAL can do any chip-specific configuration. + * + * If core_initialized() returns 0, the NCI stack will wait for a HAL_NFC_POST_INIT_CPLT_EVT + * before continuing. + * + * If core_initialized() returns any other value, the NCI stack will continue + * immediately. + */ + int (*core_initialized)(const struct nfc_nci_device *p_dev, uint8_t* p_core_init_rsp_params); + + /* + * (*pre_discover)() Is called every time before starting RF discovery. + * It is a good place to do vendor-specific configuration that must be + * performed every time RF discovery is about to be started. + * + * If pre_discover() returns 0, the NCI stack will wait for a HAL_NFC_PRE_DISCOVER_CPLT_EVT + * before continuing. + * + * If pre_discover() returns any other value, the NCI stack will start + * RF discovery immediately. + */ + int (*pre_discover)(const struct nfc_nci_device *p_dev); + + /* + * (*close)() Closed the NFC controller. Should free all resources. + */ + int (*close)(const struct nfc_nci_device *p_dev); + + /* + * (*control_granted)() Grant HAL the exclusive control to send NCI commands. + * Called in response to HAL_REQUEST_CONTROL_EVT. + * Must only be called when there are no NCI commands pending. + * HAL_RELEASE_CONTROL_EVT will notify when HAL no longer needs exclusive control. + */ + int (*control_granted)(const struct nfc_nci_device *p_dev); + + /* + * (*power_cycle)() Restart controller by power cyle; + * HAL_OPEN_CPLT_EVT will notify when operation is complete. + */ + int (*power_cycle)(const struct nfc_nci_device *p_dev); +} nfc_nci_device_t; + +/* + * Convenience methods that the NFC stack can use to open + * and close an NCI device + */ +static inline int nfc_nci_open(const struct hw_module_t* module, + nfc_nci_device_t** dev) { + return module->methods->open(module, NFC_NCI_CONTROLLER, + (struct hw_device_t**) dev); +} + +static inline int nfc_nci_close(nfc_nci_device_t* dev) { + return dev->common.close(&dev->common); +} +/* + * End NFC NCI HAL + */ + +/* + * This is a limited NFC HAL for NXP PN544-based devices. + * This HAL as Android is moving to + * an NCI-based NFC stack. + * + * All NCI-based NFC controllers should use the NFC-NCI + * HAL instead. + * Begin PN544 specific HAL + */ +#define NFC_HARDWARE_MODULE_ID "nfc" + +#define NFC_PN544_CONTROLLER "pn544" + +typedef struct nfc_module_t { + struct hw_module_t common; +} nfc_module_t; + +/* + * PN544 linktypes. + * UART + * I2C + * USB (uses UART DAL) + */ +typedef enum { + PN544_LINK_TYPE_UART, + PN544_LINK_TYPE_I2C, + PN544_LINK_TYPE_USB, + PN544_LINK_TYPE_INVALID, +} nfc_pn544_linktype; + +typedef struct { + struct hw_device_t common; + + /* The number of EEPROM registers to write */ + uint32_t num_eeprom_settings; + + /* The actual EEPROM settings + * For PN544, each EEPROM setting is a 4-byte entry, + * of the format [0x00, addr_msb, addr_lsb, value]. + */ + uint8_t* eeprom_settings; + + /* The link type to which the PN544 is connected */ + nfc_pn544_linktype linktype; + + /* The device node to which the PN544 is connected */ + const char* device_node; + + /* On Crespo we had an I2C issue that would cause us to sometimes read + * the I2C slave address (0x57) over the bus. libnfc contains + * a hack to ignore this byte and try to read the length byte + * again. + * Set to 0 to disable the workaround, 1 to enable it. + */ + uint8_t enable_i2c_workaround; + /* I2C slave address. Multiple I2C addresses are + * possible for PN544 module. Configure address according to + * board design. + */ + uint8_t i2c_device_address; +} nfc_pn544_device_t; + +static inline int nfc_pn544_open(const struct hw_module_t* module, + nfc_pn544_device_t** dev) { + return module->methods->open(module, NFC_PN544_CONTROLLER, + (struct hw_device_t**) dev); +} + +static inline int nfc_pn544_close(nfc_pn544_device_t* dev) { + return dev->common.close(&dev->common); +} +/* + * End PN544 specific HAL + */ + +__END_DECLS + +#endif // ANDROID_NFC_HAL_INTERFACE_H diff -Nru android-tools-4.2.2+git20130218/libhardware/include/hardware/power.h android-tools-4.2.2+git20130529/libhardware/include/hardware/power.h --- android-tools-4.2.2+git20130218/libhardware/include/hardware/power.h 1970-01-01 00:00:00.000000000 +0000 +++ android-tools-4.2.2+git20130529/libhardware/include/hardware/power.h 2013-05-29 20:16:54.000000000 +0000 @@ -0,0 +1,123 @@ +/* + * Copyright (C) 2012 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 ANDROID_INCLUDE_HARDWARE_POWER_H +#define ANDROID_INCLUDE_HARDWARE_POWER_H + +#include +#include +#include + +#include + +__BEGIN_DECLS + +#define POWER_MODULE_API_VERSION_0_1 HARDWARE_MODULE_API_VERSION(0, 1) +#define POWER_MODULE_API_VERSION_0_2 HARDWARE_MODULE_API_VERSION(0, 2) + + +/** + * The id of this module + */ +#define POWER_HARDWARE_MODULE_ID "power" + +/* + * Power hint identifiers passed to (*powerHint) + */ + +typedef enum { + POWER_HINT_VSYNC = 0x00000001, + POWER_HINT_INTERACTION = 0x00000002, +} power_hint_t; + +/** + * Every hardware module must have a data structure named HAL_MODULE_INFO_SYM + * and the fields of this data structure must begin with hw_module_t + * followed by module specific information. + */ +typedef struct power_module { + struct hw_module_t common; + + /* + * (*init)() performs power management setup actions at runtime + * startup, such as to set default cpufreq parameters. This is + * called only by the Power HAL instance loaded by + * PowerManagerService. + */ + void (*init)(struct power_module *module); + + /* + * (*setInteractive)() performs power management actions upon the + * system entering interactive state (that is, the system is awake + * and ready for interaction, often with UI devices such as + * display and touchscreen enabled) or non-interactive state (the + * system appears asleep, display usually turned off). The + * non-interactive state is usually entered after a period of + * inactivity, in order to conserve battery power during + * such inactive periods. + * + * Typical actions are to turn on or off devices and adjust + * cpufreq parameters. This function may also call the + * appropriate interfaces to allow the kernel to suspend the + * system to low-power sleep state when entering non-interactive + * state, and to disallow low-power suspend when the system is in + * interactive state. When low-power suspend state is allowed, the + * kernel may suspend the system whenever no wakelocks are held. + * + * on is non-zero when the system is transitioning to an + * interactive / awake state, and zero when transitioning to a + * non-interactive / asleep state. + * + * This function is called to enter non-interactive state after + * turning off the screen (if present), and called to enter + * interactive state prior to turning on the screen. + */ + void (*setInteractive)(struct power_module *module, int on); + + /* + * (*powerHint) is called to pass hints on power requirements, which + * may result in adjustment of power/performance parameters of the + * cpufreq governor and other controls. The possible hints are: + * + * POWER_HINT_VSYNC + * + * Foreground app has started or stopped requesting a VSYNC pulse + * from SurfaceFlinger. If the app has started requesting VSYNC + * then CPU and GPU load is expected soon, and it may be appropriate + * to raise speeds of CPU, memory bus, etc. The data parameter is + * non-zero to indicate VSYNC pulse is now requested, or zero for + * VSYNC pulse no longer requested. + * + * POWER_HINT_INTERACTION + * + * User is interacting with the device, for example, touchscreen + * events are incoming. CPU and GPU load may be expected soon, + * and it may be appropriate to raise speeds of CPU, memory bus, + * etc. The data parameter is unused. + * + * A particular platform may choose to ignore any hint. + * + * availability: version 0.2 + * + */ + void (*powerHint)(struct power_module *module, power_hint_t hint, + void *data); +} power_module_t; + + +__END_DECLS + +#endif // ANDROID_INCLUDE_HARDWARE_POWER_H diff -Nru android-tools-4.2.2+git20130218/libhardware/include/hardware/qemud.h android-tools-4.2.2+git20130529/libhardware/include/hardware/qemud.h --- android-tools-4.2.2+git20130218/libhardware/include/hardware/qemud.h 1970-01-01 00:00:00.000000000 +0000 +++ android-tools-4.2.2+git20130529/libhardware/include/hardware/qemud.h 2013-05-29 20:16:54.000000000 +0000 @@ -0,0 +1,153 @@ +/* + * 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 ANDROID_INCLUDE_HARDWARE_QEMUD_H +#define ANDROID_INCLUDE_HARDWARE_QEMUD_H + +#include +#include "qemu_pipe.h" + +/* the following is helper code that is used by the QEMU-specific + * hardware HAL modules to communicate with the emulator program + * through the 'qemud' multiplexing daemon, or through the qemud + * pipe. + * + * see the documentation comments for details in + * development/emulator/qemud/qemud.c + * + * all definitions here are built into the HAL module to avoid + * having to write a tiny shared library for this. + */ + +/* we expect the D macro to be defined to a function macro + * that sends its formatted string argument(s) to the log. + * If not, ignore the traces. + */ +#ifndef D +# define D(...) ((void)0) +#endif + +static __inline__ int +qemud_fd_write(int fd, const void* buff, int len) +{ + int len2; + do { + len2 = write(fd, buff, len); + } while (len2 < 0 && errno == EINTR); + return len2; +} + +static __inline__ int +qemud_fd_read(int fd, void* buff, int len) +{ + int len2; + do { + len2 = read(fd, buff, len); + } while (len2 < 0 && errno == EINTR); + return len2; +} + +static __inline__ int +qemud_channel_open(const char* name) +{ + int fd; + int namelen = strlen(name); + char answer[2]; + char pipe_name[256]; + + /* First, try to connect to the pipe. */ + snprintf(pipe_name, sizeof(pipe_name), "qemud:%s", name); + fd = qemu_pipe_open(pipe_name); + if (fd < 0) { + D("QEMUD pipe is not available for %s: %s", name, strerror(errno)); + /* If pipe is not available, connect to qemud control socket */ + fd = socket_local_client( "qemud", + ANDROID_SOCKET_NAMESPACE_RESERVED, + SOCK_STREAM ); + if (fd < 0) { + D("no qemud control socket: %s", strerror(errno)); + return -1; + } + + /* send service name to connect */ + if (qemud_fd_write(fd, name, namelen) != namelen) { + D("can't send service name to qemud: %s", + strerror(errno)); + close(fd); + return -1; + } + + /* read answer from daemon */ + if (qemud_fd_read(fd, answer, 2) != 2 || + answer[0] != 'O' || answer[1] != 'K') { + D("cant' connect to %s service through qemud", name); + close(fd); + return -1; + } + } + return fd; +} + +static __inline__ int +qemud_channel_send(int fd, const void* msg, int msglen) +{ + char header[5]; + + if (msglen < 0) + msglen = strlen((const char*)msg); + + if (msglen == 0) + return 0; + + snprintf(header, sizeof header, "%04x", msglen); + if (qemud_fd_write(fd, header, 4) != 4) { + D("can't write qemud frame header: %s", strerror(errno)); + return -1; + } + + if (qemud_fd_write(fd, msg, msglen) != msglen) { + D("can4t write qemud frame payload: %s", strerror(errno)); + return -1; + } + return 0; +} + +static __inline__ int +qemud_channel_recv(int fd, void* msg, int msgsize) +{ + char header[5]; + int size, avail; + + if (qemud_fd_read(fd, header, 4) != 4) { + D("can't read qemud frame header: %s", strerror(errno)); + return -1; + } + header[4] = 0; + if (sscanf(header, "%04x", &size) != 1) { + D("malformed qemud frame header: '%.*s'", 4, header); + return -1; + } + if (size > msgsize) + return -1; + + if (qemud_fd_read(fd, msg, size) != size) { + D("can't read qemud frame payload: %s", strerror(errno)); + return -1; + } + return size; +} + +#endif /* ANDROID_INCLUDE_HARDWARE_QEMUD_H */ diff -Nru android-tools-4.2.2+git20130218/libhardware/include/hardware/qemu_pipe.h android-tools-4.2.2+git20130529/libhardware/include/hardware/qemu_pipe.h --- android-tools-4.2.2+git20130218/libhardware/include/hardware/qemu_pipe.h 1970-01-01 00:00:00.000000000 +0000 +++ android-tools-4.2.2+git20130529/libhardware/include/hardware/qemu_pipe.h 2013-05-29 20:16:54.000000000 +0000 @@ -0,0 +1,91 @@ +/* + * Copyright (C) 2011 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 ANDROID_INCLUDE_HARDWARE_QEMU_PIPE_H +#define ANDROID_INCLUDE_HARDWARE_QEMU_PIPE_H + +#include +#include +#include +#include +#include /* for pthread_once() */ +#include +#include +#include + +#ifndef D +# define D(...) do{}while(0) +#endif + +/* Try to open a new Qemu fast-pipe. This function returns a file descriptor + * that can be used to communicate with a named service managed by the + * emulator. + * + * This file descriptor can be used as a standard pipe/socket descriptor. + * + * 'pipeName' is the name of the emulator service you want to connect to. + * E.g. 'opengles' or 'camera'. + * + * On success, return a valid file descriptor + * Returns -1 on error, and errno gives the error code, e.g.: + * + * EINVAL -> unknown/unsupported pipeName + * ENOSYS -> fast pipes not available in this system. + * + * ENOSYS should never happen, except if you're trying to run within a + * misconfigured emulator. + * + * You should be able to open several pipes to the same pipe service, + * except for a few special cases (e.g. GSM modem), where EBUSY will be + * returned if more than one client tries to connect to it. + */ +static __inline__ int +qemu_pipe_open(const char* pipeName) +{ + char buff[256]; + int buffLen; + int fd, ret; + + if (pipeName == NULL || pipeName[0] == '\0') { + errno = EINVAL; + return -1; + } + + snprintf(buff, sizeof buff, "pipe:%s", pipeName); + + fd = open("/dev/qemu_pipe", O_RDWR); + if (fd < 0) { + D("%s: Could not open /dev/qemu_pipe: %s", __FUNCTION__, strerror(errno)); + //errno = ENOSYS; + return -1; + } + + buffLen = strlen(buff); + + ret = TEMP_FAILURE_RETRY(write(fd, buff, buffLen+1)); + if (ret != buffLen+1) { + D("%s: Could not connect to %s pipe service: %s", __FUNCTION__, pipeName, strerror(errno)); + if (ret == 0) { + errno = ECONNRESET; + } else if (ret > 0) { + errno = EINVAL; + } + return -1; + } + + return fd; +} + +#endif /* ANDROID_INCLUDE_HARDWARE_QEMUD_PIPE_H */ diff -Nru android-tools-4.2.2+git20130218/libhardware/include/hardware/sensors.h android-tools-4.2.2+git20130529/libhardware/include/hardware/sensors.h --- android-tools-4.2.2+git20130218/libhardware/include/hardware/sensors.h 1970-01-01 00:00:00.000000000 +0000 +++ android-tools-4.2.2+git20130529/libhardware/include/hardware/sensors.h 2013-05-29 20:16:54.000000000 +0000 @@ -0,0 +1,485 @@ +/* + * 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 ANDROID_SENSORS_INTERFACE_H +#define ANDROID_SENSORS_INTERFACE_H + +#include +#include +#include + +#include +#include + +__BEGIN_DECLS + +/** + * The id of this module + */ +#define SENSORS_HARDWARE_MODULE_ID "sensors" + +/** + * Name of the sensors device to open + */ +#define SENSORS_HARDWARE_POLL "poll" + +/** + * Handles must be higher than SENSORS_HANDLE_BASE and must be unique. + * A Handle identifies a given sensors. The handle is used to activate + * and/or deactivate sensors. + * In this version of the API there can only be 256 handles. + */ +#define SENSORS_HANDLE_BASE 0 +#define SENSORS_HANDLE_BITS 8 +#define SENSORS_HANDLE_COUNT (1<0 + * ^ + * | + * +-----------+--> y>0 + * | | + * | | + * | | + * | | / z<0 + * | | / + * | | / + * O-----------+/ + * |[] [ ] []/ + * +----------/+ y<0 + * / + * / + * |/ z>0 (toward the sky) + * + * O: Origin (x=0,y=0,z=0) + * + * + * SENSOR_TYPE_ORIENTATION + * ----------------------- + * + * All values are angles in degrees. + * + * Orientation sensors return sensor events for all 3 axes at a constant + * rate defined by setDelay(). + * + * azimuth: angle between the magnetic north direction and the Y axis, around + * the Z axis (0<=azimuth<360). + * 0=North, 90=East, 180=South, 270=West + * + * pitch: Rotation around X axis (-180<=pitch<=180), with positive values when + * the z-axis moves toward the y-axis. + * + * roll: Rotation around Y axis (-90<=roll<=90), with positive values when + * the x-axis moves towards the z-axis. + * + * Note: For historical reasons the roll angle is positive in the clockwise + * direction (mathematically speaking, it should be positive in the + * counter-clockwise direction): + * + * Z + * ^ + * (+roll) .--> | + * / | + * | | roll: rotation around Y axis + * X <-------(.) + * Y + * note that +Y == -roll + * + * + * + * Note: This definition is different from yaw, pitch and roll used in aviation + * where the X axis is along the long side of the plane (tail to nose). + * + * + * SENSOR_TYPE_ACCELEROMETER + * ------------------------- + * + * All values are in SI units (m/s^2) and measure the acceleration of the + * device minus the force of gravity. + * + * Acceleration sensors return sensor events for all 3 axes at a constant + * rate defined by setDelay(). + * + * x: Acceleration minus Gx on the x-axis + * y: Acceleration minus Gy on the y-axis + * z: Acceleration minus Gz on the z-axis + * + * Examples: + * When the device lies flat on a table and is pushed on its left side + * toward the right, the x acceleration value is positive. + * + * When the device lies flat on a table, the acceleration value is +9.81, + * which correspond to the acceleration of the device (0 m/s^2) minus the + * force of gravity (-9.81 m/s^2). + * + * When the device lies flat on a table and is pushed toward the sky, the + * acceleration value is greater than +9.81, which correspond to the + * acceleration of the device (+A m/s^2) minus the force of + * gravity (-9.81 m/s^2). + * + * + * SENSOR_TYPE_MAGNETIC_FIELD + * -------------------------- + * + * All values are in micro-Tesla (uT) and measure the ambient magnetic + * field in the X, Y and Z axis. + * + * Magnetic Field sensors return sensor events for all 3 axes at a constant + * rate defined by setDelay(). + * + * SENSOR_TYPE_GYROSCOPE + * --------------------- + * + * All values are in radians/second and measure the rate of rotation + * around the X, Y and Z axis. The coordinate system is the same as is + * used for the acceleration sensor. Rotation is positive in the + * counter-clockwise direction (right-hand rule). That is, an observer + * looking from some positive location on the x, y or z axis at a device + * positioned on the origin would report positive rotation if the device + * appeared to be rotating counter clockwise. Note that this is the + * standard mathematical definition of positive rotation and does not agree + * with the definition of roll given earlier. + * The range should at least be 17.45 rad/s (ie: ~1000 deg/s). + * + * SENSOR_TYPE_PROXIMITY + * ---------------------- + * + * The distance value is measured in centimeters. Note that some proximity + * sensors only support a binary "close" or "far" measurement. In this case, + * the sensor should report its maxRange value in the "far" state and a value + * less than maxRange in the "near" state. + * + * Proximity sensors report a value only when it changes and each time the + * sensor is enabled. + * + * SENSOR_TYPE_LIGHT + * ----------------- + * + * The light sensor value is returned in SI lux units. + * + * Light sensors report a value only when it changes and each time the + * sensor is enabled. + * + * SENSOR_TYPE_PRESSURE + * -------------------- + * + * The pressure sensor return the athmospheric pressure in hectopascal (hPa) + * + * Pressure sensors report events at a constant rate defined by setDelay(). + * + * SENSOR_TYPE_GRAVITY + * ------------------- + * + * A gravity output indicates the direction of and magnitude of gravity in + * the devices's coordinates. On Earth, the magnitude is 9.8 m/s^2. + * Units are m/s^2. The coordinate system is the same as is used for the + * acceleration sensor. When the device is at rest, the output of the + * gravity sensor should be identical to that of the accelerometer. + * + * SENSOR_TYPE_LINEAR_ACCELERATION + * -------------------------------- + * + * Indicates the linear acceleration of the device in device coordinates, + * not including gravity. + * This output is essentially Acceleration - Gravity. Units are m/s^2. + * The coordinate system is the same as is used for the acceleration sensor. + * + * + * SENSOR_TYPE_ROTATION_VECTOR + * --------------------------- + * + * A rotation vector represents the orientation of the device as a combination + * of an angle and an axis, in which the device has rotated through an angle + * theta around an axis . The three elements of the rotation vector + * are , such that the magnitude + * of the rotation vector is equal to sin(theta/2), and the direction of the + * rotation vector is equal to the direction of the axis of rotation. The three + * elements of the rotation vector are equal to the last three components of a + * unit quaternion . + * Elements of the rotation vector are unitless. The x, y, and z axis are defined + * in the same was as for the acceleration sensor. + * + * The reference coordinate system is defined as a direct orthonormal basis, + * where: + * + * - X is defined as the vector product Y.Z (It is tangential to + * the ground at the device's current location and roughly points East). + * + * - Y is tangential to the ground at the device's current location and + * points towards the magnetic North Pole. + * + * - Z points towards the sky and is perpendicular to the ground. + * + * + * The rotation-vector is stored as: + * + * sensors_event_t.data[0] = x*sin(theta/2) + * sensors_event_t.data[1] = y*sin(theta/2) + * sensors_event_t.data[2] = z*sin(theta/2) + * sensors_event_t.data[3] = cos(theta/2) + * + * + * SENSOR_TYPE_RELATIVE_HUMIDITY + * ------------------------------ + * + * A relative humidity sensor measures relative ambient air humidity and + * returns a value in percent. + * + * Relative humidity sensors report a value only when it changes and each + * time the sensor is enabled. + * + * + * SENSOR_TYPE_AMBIENT_TEMPERATURE + * ------------------------------- + * + * The ambient (room) temperature in degree Celsius. + * + * Temperature sensors report a value only when it changes and each time the + * sensor is enabled. + * + */ + +typedef struct { + union { + float v[3]; + struct { + float x; + float y; + float z; + }; + struct { + float azimuth; + float pitch; + float roll; + }; + }; + int8_t status; + uint8_t reserved[3]; +} sensors_vec_t; + +/** + * Union of the various types of sensor data + * that can be returned. + */ +typedef struct sensors_event_t { + /* must be sizeof(struct sensors_event_t) */ + int32_t version; + + /* sensor identifier */ + int32_t sensor; + + /* sensor type */ + int32_t type; + + /* reserved */ + int32_t reserved0; + + /* time is in nanosecond */ + int64_t timestamp; + + union { + float data[16]; + + /* acceleration values are in meter per second per second (m/s^2) */ + sensors_vec_t acceleration; + + /* magnetic vector values are in micro-Tesla (uT) */ + sensors_vec_t magnetic; + + /* orientation values are in degrees */ + sensors_vec_t orientation; + + /* gyroscope values are in rad/s */ + sensors_vec_t gyro; + + /* temperature is in degrees centigrade (Celsius) */ + float temperature; + + /* distance in centimeters */ + float distance; + + /* light in SI lux units */ + float light; + + /* pressure in hectopascal (hPa) */ + float pressure; + + /* relative humidity in percent */ + float relative_humidity; + }; + uint32_t reserved1[4]; +} sensors_event_t; + + + +struct sensor_t; + +/** + * Every hardware module must have a data structure named HAL_MODULE_INFO_SYM + * and the fields of this data structure must begin with hw_module_t + * followed by module specific information. + */ +struct sensors_module_t { + struct hw_module_t common; + + /** + * Enumerate all available sensors. The list is returned in "list". + * @return number of sensors in the list + */ + int (*get_sensors_list)(struct sensors_module_t* module, + struct sensor_t const** list); +}; + +struct sensor_t { + /* name of this sensors */ + const char* name; + /* vendor of the hardware part */ + const char* vendor; + /* version of the hardware part + driver. The value of this field + * must increase when the driver is updated in a way that changes the + * output of this sensor. This is important for fused sensors when the + * fusion algorithm is updated. + */ + int version; + /* handle that identifies this sensors. This handle is used to activate + * and deactivate this sensor. The value of the handle must be 8 bits + * in this version of the API. + */ + int handle; + /* this sensor's type. */ + int type; + /* maximaum range of this sensor's value in SI units */ + float maxRange; + /* smallest difference between two values reported by this sensor */ + float resolution; + /* rough estimate of this sensor's power consumption in mA */ + float power; + /* minimum delay allowed between events in microseconds. A value of zero + * means that this sensor doesn't report events at a constant rate, but + * rather only when a new data is available */ + int32_t minDelay; + /* reserved fields, must be zero */ + void* reserved[8]; +}; + + +/** + * Every device data structure must begin with hw_device_t + * followed by module specific public methods and attributes. + */ +struct sensors_poll_device_t { + struct hw_device_t common; + + /** Activate/deactivate one sensor. + * + * @param handle is the handle of the sensor to change. + * @param enabled set to 1 to enable, or 0 to disable the sensor. + * + * @return 0 on success, negative errno code otherwise + */ + int (*activate)(struct sensors_poll_device_t *dev, + int handle, int enabled); + + /** + * Set the delay between sensor events in nanoseconds for a given sensor. + * + * If the requested value is less than sensor_t::minDelay, then it's + * silently clamped to sensor_t::minDelay unless sensor_t::minDelay is + * 0, in which case it is clamped to >= 1ms. + * + * @return 0 if successful, < 0 on error + */ + int (*setDelay)(struct sensors_poll_device_t *dev, + int handle, int64_t ns); + + /** + * Returns an array of sensor data. + * This function must block until events are available. + * + * @return the number of events read on success, or -errno in case of an error. + * This function should never return 0 (no event). + * + */ + int (*poll)(struct sensors_poll_device_t *dev, + sensors_event_t* data, int count); +}; + +/** convenience API for opening and closing a device */ + +static inline int sensors_open(const struct hw_module_t* module, + struct sensors_poll_device_t** device) { + return module->methods->open(module, + SENSORS_HARDWARE_POLL, (struct hw_device_t**)device); +} + +static inline int sensors_close(struct sensors_poll_device_t* device) { + return device->common.close(&device->common); +} + +__END_DECLS + +#endif // ANDROID_SENSORS_INTERFACE_H