+++ /dev/null
-/*
- * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
- *
- * Licensed under the Apache License, Version 2.0 (the License);
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an AS IS BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <errno.h>
-#include <unistd.h>
-#include <limits.h>
-#include <stdarg.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <ctype.h>
-#include <assert.h>
-
-#include "sysdeps.h"
-
-#ifdef HAVE_TERMIO_H
-#include <termios.h>
-#endif
-
-#define TRACE_TAG TRACE_SDB
-#include "sdb.h"
-#include "sdb_client.h"
-#include "file_sync_service.h"
-#include <tzplatform_config.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_sdb(const char *app_id);
-int install_app_sdb(const char *srcpath);
-int launch_app(transport_type transport, char* serial, int argc, char** argv);
-int uninstall_app(transport_type transport, char* serial, int argc, char** argv);
-int sdb_command2(const char* cmd);
-void version_sdbd(transport_type ttype, char* serial);
-
-static const char *gProductOutPath = NULL;
-
-static char *product_file(const char *extra)
-{
- int n;
- char *x;
-
- if (gProductOutPath == NULL) {
- fprintf(stderr, "sdb: 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, "sdb: 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, "Smart Development Bridge version %d.%d.%d\n",
- SDB_VERSION_MAJOR, SDB_VERSION_MINOR, SDB_SERVER_VERSION);
-}
-
-void help()
-{
- version(stderr);
-
- fprintf(stderr,
- "\n"
- " Usage : sdb [option] <command> [parameters]\n"
- "\n"
- " options:\n"
- " -d - direct command to the only connected USB device\n"
- " return an error if more than one USB device is present.\n"
- " -e - direct command to the only running emulator.\n"
- " return an error if more than one emulator is running.\n"
- " -s <serial number> - direct command to the USB device or emulator with\n"
- " the given serial number.\n"
- " devices - list all connected devices\n"
- " connect <host>[:<port>] - connect to a device via TCP/IP\n"
- " Port 26101 is used by default if no port number is specified.\n"
- " disconnect [<host>[:<port>]] - disconnect from a TCP/IP device.\n"
- " Port 26101 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"
- " commands:\n"
- " sdb push <local> <remote> [--with-utf8]\n"
- " - copy file/dir to device\n"
- " (--with-utf8 means to create the remote file with utf-8 character encoding)\n"
- " sdb pull <remote> [<local>] - copy file/dir from device\n"
- " sdb shell - run remote shell interactively\n"
- " sdb shell <command> - run remote shell \n"
- " sdb dlog [<filter-spec>] - view device log\n"
- " sdb install <path-to-tpk> - push tpk package file and install it\n"
- " sdb uninstall <appid> - uninstall this app from the device\n"
- " sdb forward <local> <remote> - forward socket connections\n"
-
- " forward spec is : \n"
- " tcp:<port>\n"
- " sdb help - show this help message\n"
- " sdb version - show version num\n"
- "\n"
- " sdb start-server - ensure that there is a server running\n"
- " sdb kill-server - kill the server if it is running\n"
- " sdb get-state - print: offline | bootloader | device\n"
- " sdb get-serialno - print: <serial-number>\n"
- " sdb status-window - continuously print device status for a specified device\n"
-// " sdb usb - restarts the sdbd daemon listing on USB\n"
-// " sdb tcpip - restarts the sdbd daemon listing on TCP\n"
- " sdb root <on|off> - switch to root or sdk user account mode\n"
- " 'on' means to root mode, and vice versa"
- "\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 sdb_read(fd=%d)\n", fd);
- len = sdb_read(fd, buf, 4096);
- D("read_and_dump(): post sdb_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 = sdb_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;
- }
- sdb_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 sdb_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 = sdb_write(fd, buf, r);
- if(r <= 0) {
- break;
- }
- }
- return 0;
-}
-
-int interactive_shell(void)
-{
- sdb_thread_t thr;
- int fdi, fd;
- int *fds;
-
- fd = sdb_connect("shell:");
- if(fd < 0) {
- fprintf(stderr,"error: %s\n", sdb_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
- sdb_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);
- }
-}
-#if 0 /* tizen specific */
-int sdb_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 = sdb_connect(buf);
- if(fd < 0) {
- fprintf(stderr,"error: %s\n", sdb_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)) {
- sdb_status(fd);
- fprintf(stderr,"* failed to write data '%s' *\n", sdb_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");
- sdb_close(fd);
- return -1;
- }
- if(memcmp(buf, "OKAY", 4)) {
- buf[4] = 0;
- fprintf(stderr,"* error response '%s' *\n", buf);
- sdb_close(fd);
- return -1;
- }
-
- sdb_close(fd);
- return 0;
-}
-
-int sdb_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 = sdb_download_buffer(service, data, sz, progress);
- free(data);
- return status;
-}
-#endif
-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);
- sdb_close(fd);
-#endif
-
- format_host_command(command, sizeof command, "get-state", ttype, serial);
-
- for(;;) {
- sdb_sleep_ms(250);
-
- if(state) {
- free(state);
- state = 0;
- }
-
- state = sdb_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("Samsung Development Bridge\n");
- printf("State: %s\n", state ? state : "offline");
- fflush(stdout);
- }
-}
-
-/** duplicate string and quote all \ " ( ) chars + space character. */
-static char *
-dupAndQuote(const char *s)
-{
- const char *ts;
- size_t alloc_len;
- char *ret;
- char *dest;
-
- ts = s;
-
- alloc_len = 0;
-
- for( ;*ts != '\0'; ts++) {
- alloc_len++;
- if (*ts == ' ' || *ts == '"' || *ts == '\\' || *ts == '(' || *ts == ')') {
- alloc_len++;
- }
- }
-
- ret = (char *)malloc(alloc_len + 1);
-
- ts = s;
- dest = ret;
-
- for ( ;*ts != '\0'; ts++) {
- if (*ts == ' ' || *ts == '"' || *ts == '\\' || *ts == '(' || *ts == ')') {
- *dest++ = '\\';
- }
-
- *dest++ = *ts;
- }
-
- *dest++ = '\0';
-
- return ret;
-}
-
-/**
- * Run ppp in "notty" mode against a resource listed as the first parameter
- * eg:
- *
- * ppp dev:/dev/omap_csmi_tty0 <ppp options>
- *
- */
-int ppp(int argc, char **argv)
-{
-#ifdef HAVE_WIN32_PROC
- fprintf(stderr, "error: sdb %s not implemented on Win32\n", argv[0]);
- return -1;
-#else
- char *sdb_service_name;
- pid_t pid;
- int fd;
-
- if (argc < 2) {
- fprintf(stderr, "usage: sdb %s <sdb service name> [ppp opts]\n",
- argv[0]);
-
- return 1;
- }
-
- sdb_service_name = argv[1];
-
- fd = sdb_connect(sdb_service_name);
-
- if(fd < 0) {
- fprintf(stderr,"Error: Could not open sdb service: %s. Error: %s\n",
- sdb_service_name, sdb_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);
- sdb_close(STDERR_FILENO);
- sdb_close(fd);
-
- err = execvp("pppd", (char * const *)ppp_args);
-
- if (err < 0) {
- perror("execing pppd");
- }
- exit(-1);
- } else {
- // parent side
-
- sdb_close(fd);
- return 0;
- }
-#endif /* !HAVE_WIN32_PROC */
-}
-
-static int send_shellcommand(transport_type transport, char* serial, char* buf)
-{
- int fd, ret;
-
- for(;;) {
- fd = sdb_connect(buf);
- if(fd >= 0)
- break;
- fprintf(stderr,"- waiting for device -\n");
- sdb_sleep_ms(1000);
- do_cmd(transport, serial, "wait-for-device", 0);
- }
-
- read_and_dump(fd);
- ret = sdb_close(fd);
- if (ret)
- perror("close");
-
- return ret;
-}
-
-static int logcat(transport_type transport, char* serial, int argc, char **argv)
-{
- char buf[4096];
-
- snprintf(buf, sizeof(buf),
- "shell:/usr/bin/dlogutil");
-
-/*
- 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 = sdb_dirstart(x);
- if(x == 0) return 0;
- *x = 0;
- ret = sdb_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, "sdb: -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 "sdb backup" or "sdb backup -f filename" are not valid invocations */
- if (argc < 2) return usage();
-
- sdb_unlink(filename);
- mkdirs((char *)filename);
- outFd = sdb_creat(filename, 0640);
- if (outFd < 0) {
- fprintf(stderr, "sdb: 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 = sdb_connect(buf);
- if (fd < 0) {
- fprintf(stderr, "sdb: unable to connect for backup\n");
- sdb_close(outFd);
- return -1;
- }
-
- printf("Now unlock your device and confirm the backup operation.\n");
- copy_to_file(fd, outFd);
-
- sdb_close(fd);
- sdb_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 = sdb_open(filename, O_RDONLY);
- if (tarFd < 0) {
- fprintf(stderr, "sdb: unable to open file %s\n", filename);
- return -1;
- }
-
- fd = sdb_connect("restore:");
- if (fd < 0) {
- fprintf(stderr, "sdb: unable to connect for backup\n");
- sdb_close(tarFd);
- return -1;
- }
-
- printf("Now unlock your device and confirm the restore operation.\n");
- copy_to_file(tarFd, fd);
-
- sdb_close(fd);
- sdb_close(tarFd);
- return 0;
-}
-
-#define SENTINEL_FILE "config" OS_PATH_SEPARATOR_STR "envsetup.make"
-static int top_works(const char *top)
-{
- if (top != NULL && sdb_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 = sdb_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, "sdb: 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, "sdb: 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;
-}
-
-/* <hint> may be:
- * - A simple product name
- * e.g., "sooner"
-TODO: debug? sooner-debug, sooner:debug?
- * - A relative path from the CWD to the ANDROID_PRODUCT_OUT dir
- * e.g., "out/target/product/sooner"
- * - An absolute path to the PRODUCT_OUT dir
- * e.g., "/src/device/out/target/product/sooner"
- *
- * Given <hint>, try to construct an absolute path to the
- * ANDROID_PRODUCT_OUT dir.
- */
-static const char *find_product_out_path(const char *hint)
-{
- static char path_buf[PATH_MAX];
-
- if (hint == NULL || hint[0] == '\0') {
- return NULL;
- }
-
- /* If it's already absolute, don't bother doing any work.
- */
- if (sdb_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 (sdb_dirstart(hint) != NULL) {
- if (getcwd(path_buf, sizeof(path_buf)) == NULL) {
- fprintf(stderr, "sdb: Couldn't get CWD: errno:%d\n", errno);
- return NULL;
- }
- if (strlen(path_buf) + 1 + strlen(hint) >= sizeof(path_buf)) {
- fprintf(stderr, "sdb: 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, "sdb: 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, "sdb: Couldn't find a product dir "
- "based on \"-p %s\"; \"%s\" doesn't exist\n", hint, path_buf);
- return NULL;
- }
- return path_buf;
-}
-
-int sdb_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 sdb
- * 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_SDB_SERVER_PORT");
- int server_port = DEFAULT_SDB_PORT;
- if (server_port_str && strlen(server_port_str) > 0) {
- server_port = (int) strtol(server_port_str, NULL, 0);
- if (server_port <= 0) {
- fprintf(stderr,
- "sdb: Env var ANDROID_SDB_SERVER_PORT must be a positive number. 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 SDB client launches the SDB Server */
- is_daemon = 1;
- } else if(!strcmp(argv[0],"persist")) {
- persist = 1;
- } else if(!strncmp(argv[0], "-p", 2)) {
- const char *product = NULL;
- if (argv[0][2] == '\0') {
- if (argc < 2) return usage();
- product = argv[1];
- argc--;
- argv++;
- } else {
- product = argv[1] + 2;
- }
- gProductOutPath = find_product_out_path(product);
- if (gProductOutPath == NULL) {
- fprintf(stderr, "sdb: 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 {
- /* out of recognized modifiers and flags */
- break;
- }
- argc--;
- argv++;
- }
-
-
-// sdb_set_transport(ttype, serial);
-// sdb_set_tcp_specifics(server_port);
-
- if (is_server) {
- if (no_daemon || is_daemon) {
- r = sdb_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();
- }
-
- // first, get the uniq device from the partial serial with prefix matching
- if (serial) {
- char *tmp;
- snprintf(buf, sizeof(buf), "host:serial-match:%s", serial);
- tmp = sdb_query(buf);
- if (tmp) {
- //printf("connect to device: %s\n", tmp);
- serial = strdup(tmp);
- sdb_set_transport(ttype, serial);
- sdb_set_tcp_specifics(server_port);
- } else {
- return 1;
- }
- } else {
- sdb_set_transport(ttype, serial);
- sdb_set_tcp_specifics(server_port);
- }
- /* sdb_connect() commands */
-
- if(!strcmp(argv[0], "devices")) {
- char *tmp;
- snprintf(buf, sizeof buf, "host:%s", argv[0]);
- tmp = sdb_query(buf);
- if(tmp) {
- printf("List of devices attached \n");
- printf("%s", tmp);
- return 0;
- } else {
- return 1;
- }
- }
-
- if(!strcmp(argv[0], "connect")) {
- char *tmp;
- if (argc != 2) {
- fprintf(stderr, "Usage: sdb connect <host>[:<port>]\n");
- return 1;
- }
- snprintf(buf, sizeof buf, "host:connect:%s", argv[1]);
- tmp = sdb_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: sdb disconnect [<host>[:<port>]]\n");
- return 1;
- }
- if (argc == 2) {
- snprintf(buf, sizeof buf, "host:disconnect:%s", argv[1]);
- } else {
- snprintf(buf, sizeof buf, "host:disconnect:");
- }
- tmp = sdb_query(buf);
- if(tmp) {
- printf("%s\n", tmp);
- return 0;
- } else {
- return 1;
- }
- }
-
- if (!strcmp(argv[0], "emu")) {
- return sdb_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 = sdb_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");
- sdb_close(fd);
- r = 0;
- } else {
- fprintf(stderr,"error: %s\n", sdb_error());
- r = -1;
- }
-
- if(persist) {
- fprintf(stderr,"\n- waiting for device -\n");
- sdb_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 = _sdb_connect("host:kill");
- if(fd == -1) {
- fprintf(stderr,"* server not running *\n");
- return 1;
- }
- return 0;
- }
-#if 0 /* tizen specific */
- if(!strcmp(argv[0], "sideload")) {
- if(argc != 2) return usage();
- if(sdb_download("sideload", argv[1], 1)) {
- return 1;
- } else {
- return 0;
- }
- }
-#endif
- 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 = sdb_connect(command);
- if(fd >= 0) {
- read_and_dump(fd);
- sdb_close(fd);
- return 0;
- }
- fprintf(stderr,"error: %s\n", sdb_error());
- return 1;
- }
-
- if(!strcmp(argv[0], "bugreport")) {
- if (argc != 1) return usage();
- do_cmd(ttype, serial, "shell", "bugreport", 0);
- return 0;
- }
-
- /* sdb_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 (sdb_command(buf)) {
- D("failure: %s *\n",sdb_error());
- fprintf(stderr,"error: %s\n", sdb_error());
- return 1;
- }
-
- /* Allow a command to be run after wait-for-device,
- * e.g. 'sdb wait-for-device shell'.
- */
- if(argc > 1) {
- argc--;
- argv++;
- goto top;
- }
- return 0;
- }
-
- if(!strcmp(argv[0], "forward")) {
- if(argc != 3) return usage();
- if (serial) {
- snprintf(buf, sizeof buf, "host-serial:%s:forward:%s;%s",serial, argv[1], argv[2]);
- } else if (ttype == kTransportUsb) {
- snprintf(buf, sizeof buf, "host-usb:forward:%s;%s", argv[1], argv[2]);
- } else if (ttype == kTransportLocal) {
- snprintf(buf, sizeof buf, "host-local:forward:%s;%s", argv[1], argv[2]);
- } else {
- snprintf(buf, sizeof buf, "host:forward:%s;%s", argv[1], argv[2]);
- }
- if(sdb_command(buf)) {
- fprintf(stderr,"error: %s\n", sdb_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")) {
- int i=0;
- int utf8=0;
-
- if(argc < 3) return usage();
- if (argv[argc-1][0] == '-') {
- if (!strcmp(argv[argc-1], "--with-utf8")) {
- utf8 = 1;
- argc = argc - 1;
- } else {
- return usage();
- }
- }
- for (i=1; i<argc-1; i++) {
- do_sync_push(argv[i], argv[argc-1], 0 /* no verify APK */, utf8);
- }
- return 0;
- }
-
- if(!strcmp(argv[0], "install")) {
- if(argc != 2) return usage();
-
- return install_app_sdb(argv[1]);
- }
-
- if(!strcmp(argv[0], "uninstall")) {
- if(argc != 2) return usage();
-
- return uninstall_app_sdb(argv[1]);
- }
-
- 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], "launch")) {
- //if (argc < 2) return usage();
- return launch_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"))
- {
- char *tmp;
-
- format_host_command(buf, sizeof buf, argv[0], ttype, serial);
- tmp = sdb_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],"dlog")) {
- return logcat(ttype, serial, argc, argv);
- }
-
- if(!strcmp(argv[0],"ppp")) {
- return ppp(argc, argv);
- }
-
- if (!strcmp(argv[0], "start-server")) {
- return sdb_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 = sdb_connect("jdwp");
- if (fd >= 0) {
- read_and_dump(fd);
- sdb_close(fd);
- return 0;
- } else {
- fprintf(stderr, "error: %s\n", sdb_error());
- return -1;
- }
- }
-
- /* "sdb /?" is a common idiom under Windows */
- if(!strcmp(argv[0], "help") || !strcmp(argv[0], "/?")) {
- help();
- return 0;
- }
-
- if(!strcmp(argv[0], "version")) {
- if (ttype == kTransportUsb || ttype == kTransportLocal) {
- version_sdbd(ttype, serial);
- } else {
- 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 sdb_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 sdb_command2(const char* cmd) {
- int result = sdb_connect(cmd);
-
- if(result < 0) {
- return result;
- }
-
- D("about to read_and_dump(fd=%d)\n", result);
- read_and_dump(result);
- D("read_and_dump() done.\n");
- sdb_close(result);
-
- return 0;
-}
-
-int install_app_sdb(const char *srcpath) {
- D("Install start\n");
- const char * APP_DEST = tzplatform_mkpath(TZ_SYS_RW_APP,"PKGS/%s");
- const char* filename = sdb_dirstop(srcpath);
- char destination[PATH_MAX];
-
- if (filename) {
- filename++;
- snprintf(destination, sizeof destination, APP_DEST, filename);
- } else {
- snprintf(destination, sizeof destination, APP_DEST, srcpath);
- }
-
- D("Push file: %s to %s\n", srcpath, destination);
- int result = do_sync_push(srcpath, destination, 0, 0);
-
- if(result < 0) {
- fprintf(stderr, "error: %s\n", sdb_error());
- return -1;
- }
-
- const char* SHELL_INSTALL_CMD ="shell:pkgcmd -i -t tpk -p %s -q";
- char full_cmd[PATH_MAX];
- snprintf(full_cmd, sizeof full_cmd, SHELL_INSTALL_CMD, destination);
- D("Install command: %s\n", full_cmd);
- result = sdb_command2(full_cmd);
-
- if(result < 0) {
- fprintf(stderr, "error: %s\n", sdb_error());
- return result;
- }
-
- const char* SHELL_REMOVE_CMD = "shell:rm %s";
- snprintf(full_cmd, sizeof full_cmd, SHELL_REMOVE_CMD, destination);
- D("Remove file command: %s\n", full_cmd);
- result = sdb_command2(full_cmd);
-
- if(result < 0) {
- fprintf(stderr, "error: %s\n", sdb_error());
- return result;
- }
-
- return 0;
-}
-
-int uninstall_app_sdb(const char *appid) {
- const char* SHELL_UNINSTALL_CMD ="shell:pkgcmd -u -t tpk -n %s -q";
- char full_cmd[PATH_MAX];
- int result = 0;
- snprintf(full_cmd, sizeof full_cmd, SHELL_UNINSTALL_CMD, appid);
- result = sdb_command2(full_cmd);
-
- if(result < 0) {
- fprintf(stderr, "error: %s\n", sdb_error());
- return result;
- }
-
- 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 (sdb/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 'sdb shell pm uninstall -k %s'\n", argv[2]);
- return -1;
- }
-
- /* 'sdb 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;
-}
-
-const char* get_basename(const char* filename)
-{
- const char* basename = sdb_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, 0);
- 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 */, 0);
- 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;
-}
-
-int launch_app(transport_type transport, char* serial, int argc, char** argv)
-{
- static const char *const SHELL_LAUNCH_CMD = "shell:/usr/bin/sdk_launch_app ";
- char full_cmd[PATH_MAX];
- int i;
- int result = 0;
-
- snprintf(full_cmd, sizeof full_cmd, "%s", SHELL_LAUNCH_CMD);
-
- //TODO: check argument validation
-
- for (i=1 ; i<argc ; i++) {
- strncat(full_cmd, " ", sizeof(full_cmd)-strlen(" ")-1);
- strncat(full_cmd, argv[i], sizeof(full_cmd)-strlen(argv[i])-1);
- }
-
- D("launch command: %s\n", full_cmd);
- result = sdb_command2(full_cmd);
-
- if(result < 0) {
- fprintf(stderr, "error: %s\n", sdb_error());
- return result;
- }
-
- if(result < 0) {
- fprintf(stderr, "error: %s\n", sdb_error());
- return result;
- }
- sdb_close(result);
- return 0;
-
-}
-
-
-void version_sdbd(transport_type ttype, char* serial) {
- char* VERSION_QUERY ="shell:rpm -qa | grep sdbd";
- send_shellcommand(ttype, serial, VERSION_QUERY);
-}
+++ /dev/null
-/*
- * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
- *
- * 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 "sysdeps.h"
-#include "sdb.h"
-#include "sdb_client.h"
-#include <stdio.h>
-
-static int connect_to_console(void)
-{
- int fd, port;
-
- port = sdb_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 sdb_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++) {
- sdb_write( fd, argv[nn], strlen(argv[nn]) );
- sdb_write( fd, (nn == argc-1) ? "\n" : " ", 1 );
- }
- sdb_write( fd, QUIT, sizeof(QUIT)-1 );
- sdb_close(fd);
-
- return 0;
-}
+++ /dev/null
-/*
- * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
- *
- * Licensed under the Apache License, Version 2.0 (the License);
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an AS IS BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <errno.h>
-#include <sys/stat.h>
-#include <sys/time.h>
-#include <time.h>
-#include <dirent.h>
-#include <limits.h>
-#include <sys/types.h>
-// tizen specific #include <zipfile/zipfile.h>
-
-#include "sysdeps.h"
-#include "sdb.h"
-#include "sdb_client.h"
-#include "file_sync_service.h"
-
-
-static unsigned total_bytes;
-static long long start_time;
-extern const char* get_basename(const char* filename);
-
-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(const char* filename)
-{
- long long t = NOW() - start_time;
- if(total_bytes == 0) return;
-
- if (t == 0) /* prevent division by 0 :-) */
- t = 1000000;
-
- fprintf(stderr,"%-30s %lld KB/s (%lld bytes in %lld.%03llds)\n",
- filename,
- ((((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:
- sdb_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 = sdb_open(path, O_RDONLY);
- if(lfd < 0) {
- fprintf(stderr,"cannot open '%s': errno:%d\n", path, errno);
- return -1;
- }
-
- sbuf->id = ID_DATA;
- for(;;) {
- int ret;
-
- ret = sdb_read(lfd, sbuf->data, SYNC_DATA_MAX);
- if(!ret)
- break;
-
- if(ret < 0) {
- if(errno == EINTR)
- continue;
- fprintf(stderr,"cannot read '%s': errno:%d\n", path, errno);
- break;
- }
-
- sbuf->size = htoll(ret);
- if(writex(fd, sbuf, sizeof(unsigned) * 2 + ret)){
- err = -1;
- break;
- }
- total_bytes += ret;
- }
-
- sdb_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': errno:%d\n", path, 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 0 /* tizen specific */
- 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 = sdb_open(lpath, O_RDONLY);
- if(lfd < 0) {
- fprintf(stderr,"cannot open '%s': errno:%d\n", lpath, errno);
- return -1;
- }
-
- size = sdb_lseek(lfd, 0, SEEK_END);
- if (size == -1 || -1 == sdb_lseek(lfd, 0, SEEK_SET)) {
- fprintf(stderr, "error seeking in file '%s'\n", lpath);
- sdb_close(lfd);
- return 1;
- }
-
- file_buffer = (char *)malloc(size);
- if (file_buffer == NULL) {
- fprintf(stderr, "could not allocate buffer for '%s'\n",
- lpath);
- sdb_close(lfd);
- return 1;
- }
- amt = sdb_read(lfd, file_buffer, size);
- if (amt != size) {
- fprintf(stderr, "error reading from file: '%s'\n", lpath);
- sdb_close(lfd);
- free(file_buffer);
- return 1;
- }
-
- sdb_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;
- }
- }
-#endif
- 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");
- sdb_close(fd);
- return -1;
-}
-
-static int mkdirs(char *name)
-{
- int ret;
- char *x = name + 1;
-
- for(;;) {
- x = sdb_dirstart(x);
- if(x == 0) return 0;
- *x = 0;
- ret = sdb_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)) {
- sdb_unlink(lpath);
- mkdirs((char *)lpath);
- lfd = sdb_creat(lpath, 0644);
- if(lfd < 0) {
- fprintf(stderr,"cannot create '%s': errno:%d\n", lpath, 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");
- sdb_close(lfd);
- return -1;
- }
-
- if(readx(fd, buffer, len)) {
- sdb_close(lfd);
- return -1;
- }
-
- if(writex(lfd, buffer, len)) {
- fprintf(stderr,"cannot write '%s': errno:%d\n", rpath, errno);
- sdb_close(lfd);
- return -1;
- }
-
- total_bytes += len;
- }
-
- sdb_close(lfd);
- return 0;
-
-remote_error:
- sdb_close(lfd);
- sdb_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 = sdb_connect("sync:");
- if(fd < 0) {
- fprintf(stderr,"error: %s\n", sdb_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': errno:%d\n", lpath, 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': errno:%d\n", ci->src, errno);
- closedir(d);
-
- return -1;
- }
- if(!S_ISREG(st.st_mode) && !S_ISLNK(st.st_mode)) {
- fprintf(stderr, "skipping special file\n");
- 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, int isUtf8)
-{
- struct stat st;
- unsigned mode;
- int fd;
- char *tmp = NULL;
- char *utf8 = NULL;
- int ret = 0;
-
- fd = sdb_connect("sync:");
- if(fd < 0) {
- fprintf(stderr,"error: %s\n", sdb_error());
- return 1;
- }
-
- if(stat(lpath, &st)) {
- fprintf(stderr,"cannot stat '%s': errno:%d\n", lpath, 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(get_basename(lpath));
- 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 = sdb_dirstop(lpath);
- if(name == 0) {
- name = lpath;
- } else {
- name++;
- }
- int tmplen = strlen(name) + strlen(rpath) + 2;
- tmp = malloc(strlen(name) + strlen(rpath) + 2);
- if(tmp == 0) return 1;
- snprintf(tmp, tmplen, "%s/%s", rpath, name);
- if (isUtf8 != 0) { //ansi to utf8
- utf8 = ansi_to_utf8(tmp);
- rpath = utf8;
- } else {
- rpath = tmp;
- }
- }
- BEGIN();
- if(sync_send(fd, lpath, rpath, st.st_mtime, st.st_mode, verifyApk)) {
- ret = 1;
- goto cleanup;
- } else {
- END(get_basename(lpath));
- sync_quit(fd);
- ret = 0;
- goto cleanup;
- }
- }
- return 0;
-cleanup:
- if (tmp != NULL) {
- free(tmp);
- }
- if (utf8 != NULL) {
- free(utf8);
- }
- return ret;
-}
-
-
-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 = sdb_connect("sync:");
- if(fd < 0) {
- fprintf(stderr,"error: %s\n", sdb_error());
- return 1;
- }
-
- if(sync_readmode(fd, rpath, &mode)) {
- return 1;
- }
- if(mode == 0) {
- fprintf(stderr,"'%s': No such file or directory\n", rpath);
- sync_quit(fd);
- 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 = sdb_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(get_basename(rpath));
- sync_quit(fd);
- return 0;
- }
- } else if(S_ISDIR(mode)) {
- BEGIN();
- if (copy_remote_dir_local(fd, rpath, lpath, 0)) {
- return 1;
- } else {
- END(get_basename(rpath));
- sync_quit(fd);
- return 0;
- }
- } else {
- fprintf(stderr,"'%s': No such 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 = sdb_connect("sync:");
- if(fd < 0) {
- fprintf(stderr,"error: %s\n", sdb_error());
- return 1;
- }
-
- BEGIN();
- if(copy_local_dir_remote(fd, lpath, rpath, 1, listonly)){
- return 1;
- } else {
- END(get_basename(lpath));
- sync_quit(fd);
- return 0;
- }
-}
+++ /dev/null
-/*
- * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
- *
- * 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 <Carbon/Carbon.h>
-#include <unistd.h>
-
-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);
-}
-
+++ /dev/null
-/*
- * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
- *
- * Licensed under the Apache License, Version 2.0 (the License);
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an AS IS BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <sys/types.h>
-#include <unistd.h>
-#include <limits.h>
-#include <stdio.h>
-
-void
-get_my_path(char *exe, 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';
-}
-
+++ /dev/null
-/*
- * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
- *
- * Licensed under the Apache License, Version 2.0 (the License);
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an AS IS BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <sys/types.h>
-#include <unistd.h>
-#include <limits.h>
-#include <stdio.h>
-
-void get_my_path(char *exe, 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';
- }
-}
-
+++ /dev/null
-/*
- * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
- *
- * Licensed under the Apache License, Version 2.0 (the License);
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an AS IS BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <limits.h>
-#include <assert.h>
-#include <windows.h>
-
-void get_my_path(char *exe, 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';
- }
-}
-
+++ /dev/null
-/*
- * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
- *
- * 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.
- */
-/* implement the "debug-ports" and "track-debug-ports" device services */
-#include "sysdeps.h"
-#define TRACE_TAG TRACE_JDWP
-#include "sdb.h"
-#include <errno.h>
-#include <stdio.h>
-#include <string.h>
-#include <unistd.h>
-
-/* here's how these things work.
-
- when sdbd starts, it creates a unix server socket
- named @vm-debug-control (@ is a shortcut for "first byte is zero"
- to use the private namespace instead of the file system)
-
- when a new JDWP daemon thread starts in a new VM process, it creates
- a connection to @vm-debug-control to announce its availability.
-
-
- JDWP thread @vm-debug-control
- | |
- |-------------------------------> |
- | hello I'm in process <pid> |
- | |
- | |
-
- the connection is kept alive. it will be closed automatically if
- the JDWP process terminates (this allows sdbd to detect dead
- processes).
-
- sdbd 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 "sdb forward tcp:<hostport> jdwp:<pid>"
-
- "jdwp:<pid>" is a new forward destination format used to target
- a given JDWP process on the device. when sutch a request arrives,
- sdbd 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:
- ____________________________________
- | |
- | SDB Server (host) |
- | |
- Debugger <---> LocalSocket <----> RemoteSocket |
- | ^^ |
- |___________________________||_______|
- ||
- Transport ||
- (TCP for emulator - USB for device) ||
- ||
- ___________________________||_______
- | || |
- | SDBD (device) || |
- | VV |
- JDWP <======> LocalSocket <----> RemoteSocket |
- | |
- |____________________________________|
-
- due to the way sdb 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 !SDB_HOST
-
-#include <sys/socket.h>
-#include <sys/un.h>
-
-typedef struct JdwpProcess JdwpProcess;
-struct JdwpProcess {
- JdwpProcess* next;
- JdwpProcess* prev;
- int pid;
- int socket;
- fdevent* fde;
-
- char in_buff[4]; /* input character to read PID */
- int in_len; /* number from JDWP process */
-
- int out_fds[MAX_OUT_FDS]; /* output array of file descriptors */
- int out_count; /* to send to the JDWP process */
-};
-
-static JdwpProcess _jdwp_list;
-
-static int
-jdwp_process_list( char* buffer, int bufferlen )
-{
- char* end = buffer + bufferlen;
- char* p = buffer;
- JdwpProcess* proc = _jdwp_list.next;
-
- for ( ; proc != &_jdwp_list; proc = proc->next ) {
- int len;
-
- /* skip transient connections */
- if (proc->pid < 0)
- continue;
-
- len = snprintf(p, end-p, "%d\n", proc->pid);
- if (p + len >= end)
- break;
- p += len;
- }
- p[0] = 0;
- return (p - buffer);
-}
-
-
-static int
-jdwp_process_list_msg( char* buffer, int bufferlen )
-{
- char head[5];
- int len = jdwp_process_list( buffer+4, bufferlen-4 );
- snprintf(head, sizeof head, "%04x", len);
- memcpy(buffer, head, 4);
- return len + 4;
-}
-
-
-static void jdwp_process_list_updated(void);
-
-static void
-jdwp_process_free( JdwpProcess* proc )
-{
- if (proc) {
- int n;
-
- proc->prev->next = proc->next;
- proc->next->prev = proc->prev;
-
- if (proc->socket >= 0) {
- sdb_shutdown(proc->socket);
- sdb_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++) {
- sdb_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) {
- sdb_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 (sdb_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) );
- sdb_close(s);
- return -1;
- }
-
- if ( listen(s, 4) < 0 ) {
- D("listen failed in jdwp control socket: %d: %s\n",
- errno, strerror(errno));
- sdb_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" );
- sdb_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 = sdb_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 /* !SDB_HOST */
#if !SDB_HOST
#include <linux/prctl.h>
#define SDB_PIDPATH "/tmp/.sdbd.pid"
-#else
-#include "usb_vendors.h"
#endif
#include <system_info.h>
#include <vconf.h>
#if SDB_HOST
HOST = 1;
- usb_vendors_init();
usb_init();
local_init(DEFAULT_SDB_LOCAL_TRANSPORT_PORT);
+++ /dev/null
-/*
- * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
- *
- * Licensed under the Apache License, Version 2.0 (the License);
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an AS IS BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <errno.h>
-#include <limits.h>
-#include <stdarg.h>
-// tizen specific #include <zipfile/zipfile.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-
-#include "sysdeps.h"
-
-#define TRACE_TAG TRACE_SDB
-#include "sdb_client.h"
-
-static transport_type __sdb_transport = kTransportAny;
-static const char* __sdb_serial = NULL;
-
-static int __sdb_server_port = DEFAULT_SDB_PORT;
-
-void sdb_set_transport(transport_type type, const char* serial)
-{
- __sdb_transport = type;
- __sdb_serial = serial;
-}
-
-void sdb_set_tcp_specifics(int server_port)
-{
- __sdb_server_port = server_port;
-}
-
-int sdb_get_emulator_console_port(void)
-{
- const char* serial = __sdb_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 = sdb_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 __sdb_error[256] = { 0 };
-
-const char *sdb_error(void)
-{
- return __sdb_error;
-}
-
-static int switch_socket_transport(int fd)
-{
- char service[64];
- char tmp[5];
- int len;
-
- if (__sdb_serial)
- snprintf(service, sizeof service, "host:transport:%s", __sdb_serial);
- else {
- char* transport_type = "???";
-
- switch (__sdb_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(__sdb_error, "write failure during connection");
- sdb_close(fd);
- return -1;
- }
- D("Switch transport in progress\n");
-
- if(sdb_status(fd)) {
- sdb_close(fd);
- D("Switch transport failed\n");
- return -1;
- }
- D("Switch transport success\n");
- return 0;
-}
-
-int sdb_status(int fd)
-{
- unsigned char buf[5];
- unsigned len;
-
- if(readx(fd, buf, 4)) {
- strcpy(__sdb_error, "protocol fault (no status)");
- return -1;
- }
-
- if(!memcmp(buf, "OKAY", 4)) {
- return 0;
- }
-
- if(memcmp(buf, "FAIL", 4)) {
- sprintf(__sdb_error,
- "protocol fault (status %02x %02x %02x %02x?!)",
- buf[0], buf[1], buf[2], buf[3]);
- return -1;
- }
-
- if(readx(fd, buf, 4)) {
- strcpy(__sdb_error, "protocol fault (status len)");
- return -1;
- }
- buf[4] = 0;
- len = strtoul((char*)buf, 0, 16);
- if(len > 255) len = 255;
- if(readx(fd, __sdb_error, len)) {
- strcpy(__sdb_error, "protocol fault (status read)");
- return -1;
- }
- __sdb_error[len] = 0;
- return -1;
-}
-
-int _sdb_connect(const char *service)
-{
- char tmp[5];
- int len;
- int fd;
-
- D("_sdb_connect: %s\n", service);
- len = strlen(service);
- if((len < 1) || (len > 1024)) {
- strcpy(__sdb_error, "service name too long");
- return -1;
- }
- snprintf(tmp, sizeof tmp, "%04x", len);
-
- fd = socket_loopback_client(__sdb_server_port, SOCK_STREAM);
- if(fd < 0) {
- strcpy(__sdb_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(__sdb_error, "write failure during connection");
- sdb_close(fd);
- return -1;
- }
-
- if(sdb_status(fd)) {
- sdb_close(fd);
- return -1;
- }
-
- D("_sdb_connect: return fd %d\n", fd);
- return fd;
-}
-
-int sdb_connect(const char *service)
-{
- // first query the sdb server's version
- int fd = _sdb_connect("host:version");
-
- D("sdb_connect: service %s\n", service);
- if(fd == -2) {
- fprintf(stdout,"* daemon not running. starting it now on port %d *\n",
- __sdb_server_port);
- start_server:
- if(launch_server(__sdb_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 */
- sdb_sleep_ms(3000);
- // fall through to _sdb_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 = SDB_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;
- sdb_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 sdb that does not support the version command
- if (strcmp(__sdb_error, "unknown host service") != 0)
- return fd;
- }
-
- if(version != SDB_SERVER_VERSION) {
- printf("sdb server is out of date. killing...\n");
- fd = _sdb_connect("host:kill");
- sdb_close(fd);
-
- /* XXX can we better detect its death? */
- sdb_sleep_ms(2000);
- goto start_server;
- }
- }
-
- // if the command is start-server, we are done.
- if (!strcmp(service, "host:start-server"))
- return 0;
-
- fd = _sdb_connect(service);
- if(fd == -2) {
- fprintf(stderr,"** daemon still not running");
- }
- D("sdb_connect: return fd %d\n", fd);
-
- return fd;
-error:
- sdb_close(fd);
- return -1;
-}
-
-
-int sdb_command(const char *service)
-{
- int fd = sdb_connect(service);
- if(fd < 0) {
- return -1;
- }
-
- if(sdb_status(fd)) {
- sdb_close(fd);
- return -1;
- }
-
- return 0;
-}
-
-char *sdb_query(const char *service)
-{
- char buf[5];
- unsigned n;
- char *tmp;
-
- D("sdb_query: %s\n", service);
- int fd = sdb_connect(service);
- if(fd < 0) {
- fprintf(stderr,"error: %s\n", __sdb_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;
- sdb_close(fd);
- return tmp;
- }
- free(tmp);
-
-oops:
- sdb_close(fd);
- return 0;
-}
+++ /dev/null
-/*
- * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
- *
- * 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 _SDB_CLIENT_H_
-#define _SDB_CLIENT_H_
-
-#include "sdb.h"
-
-/* connect to sdb, connect to the named service, and return
-** a valid fd for interacting with that service upon success
-** or a negative number on failure
-*/
-int sdb_connect(const char *service);
-int _sdb_connect(const char *service);
-
-/* connect to sdb, connect to the named service, return 0 if
-** the connection succeeded AND the service returned OKAY
-*/
-int sdb_command(const char *service);
-
-/* connect to sdb, connect to the named service, return
-** a malloc'd string of its response upon success or NULL
-** on failure.
-*/
-
-char *sdb_query(const char *service);
-
-/* Set the preferred transport to connect to.
-*/
-void sdb_set_transport(transport_type type, const char* serial);
-
-/* Set TCP specifics of the transport to use
-*/
-void sdb_set_tcp_specifics(int server_port);
-
-/* 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 sdb_set_transport() was alled previously...
- */
-int sdb_get_emulator_console_port(void);
-
-/* send commands to the current emulator instance. will fail if there
- * is zero, or more than one emulator connected (or if you use -s <serial>
- * with a <serial> that does not designate an emulator)
- */
-int sdb_send_emulator_command(int argc, char** argv);
-
-/* return verbose error string from last operation */
-const char *sdb_error(void);
-
-/* read a standard sdb status response (OKAY|FAIL) and
-** return 0 in the event of OKAY, -1 in the event of FAIL
-** or protocol error
-*/
-int sdb_status(int fd);
-
-#endif
+++ /dev/null
-/*
- * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
- *
- * 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 "sysdeps.h"
-#include <windows.h>
-#include <winsock2.h>
-#include <stdio.h>
-#include <errno.h>
-#define TRACE_TAG TRACE_SYSDEPS
-#include "sdb.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 sdb_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;
-
- sdb_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);
- }
- sdb_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( "sdb_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( "sdb_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 sdb_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("sdb_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( "sdb_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( "sdb_open: '%s' => fd %d\n", path, _fh_to_int(f) );
- return _fh_to_int(f);
-}
-
-/* ignore mode on Win32 */
-int sdb_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( "sdb_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( "sdb_creat: '%s' => fd %d\n", path, _fh_to_int(f) );
- return _fh_to_int(f);
-}
-
-
-int sdb_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 sdb_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 sdb_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 sdb_shutdown(int fd)
-{
- FH f = _fh_from_int(fd);
-
- if (!f) {
- return -1;
- }
-
- D( "sdb_shutdown: %s\n", f->name);
- shutdown( f->fh_socket, SD_BOTH );
- return 0;
-}
-
-
-int sdb_close(int fd)
-{
- FH f = _fh_from_int(fd);
-
- if (!f) {
- return -1;
- }
-
- D( "sdb_close: %s\n", f->name);
- _fh_close(f);
- return 0;
-}
-
-/**************************************************************************/
-/**************************************************************************/
-/***** *****/
-/***** socket-based file descriptors *****/
-/***** *****/
-/**************************************************************************/
-/**************************************************************************/
-
-static void
-_socket_set_errno( void )
-{
- switch (WSAGetLastError()) {
- case 0: errno = 0; break;
- case WSAEWOULDBLOCK: errno = EAGAIN; break;
- case WSAEINTR: errno = EINTR; break;
- default:
- D( "_socket_set_errno: unhandled value %d\n", WSAGetLastError() );
- errno = EINVAL;
- }
-}
-
-static void
-_fh_socket_init( FH f )
-{
- f->fh_socket = INVALID_SOCKET;
- f->event = WSACreateEvent();
- f->mask = 0;
-}
-
-static int
-_fh_socket_close( FH f )
-{
- /* gently tell any peer that we're closing the socket */
- shutdown( f->fh_socket, SD_BOTH );
- closesocket( f->fh_socket );
- f->fh_socket = INVALID_SOCKET;
- CloseHandle( f->event );
- f->mask = 0;
- return 0;
-}
-
-static int
-_fh_socket_lseek( FH f, int pos, int origin )
-{
- errno = EPIPE;
- return -1;
-}
-
-static int
-_fh_socket_read( FH f, void* buf, int len )
-{
- int result = recv( f->fh_socket, buf, len, 0 );
- if (result == SOCKET_ERROR) {
- _socket_set_errno();
- result = -1;
- }
- return result;
-}
-
-static int
-_fh_socket_write( FH f, const void* buf, int len )
-{
- int result = send( f->fh_socket, buf, len, 0 );
- if (result == SOCKET_ERROR) {
- _socket_set_errno();
- result = -1;
- }
- return result;
-}
-
-static void _fh_socket_hook( FH f, int event, EventHook hook ); /* forward */
-
-static const FHClassRec _fh_socket_class =
-{
- _fh_socket_init,
- _fh_socket_close,
- _fh_socket_lseek,
- _fh_socket_read,
- _fh_socket_write,
- _fh_socket_hook
-};
-
-/**************************************************************************/
-/**************************************************************************/
-/***** *****/
-/***** replacement for libs/cutils/socket_xxxx.c *****/
-/***** *****/
-/**************************************************************************/
-/**************************************************************************/
-
-#include <winsock2.h>
-
-static int _winsock_init;
-
-static void
-_cleanup_winsock( void )
-{
- WSACleanup();
-}
-
-static void
-_init_winsock( void )
-{
- if (!_winsock_init) {
- WSADATA wsaData;
- int rc = WSAStartup( MAKEWORD(2,2), &wsaData);
- if (rc != 0) {
- fatal( "sdb: 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 sdb_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( "sdb_socket_accept: invalid fd %d\n", serverfd );
- return -1;
- }
-
- fh = _fh_alloc( &_fh_socket_class );
- if (!fh) {
- D( "sdb_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( "sdb_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( "sdb_socket_accept on fd %d returns fd %d\n", serverfd, _fh_to_int(fh) );
- return _fh_to_int(fh);
-}
-
-
-void disable_tcp_nagle(int fd)
-{
- FH fh = _fh_from_int(fd);
- int on;
-
- if ( !fh || fh->clazz != &_fh_socket_class )
- return;
-
- setsockopt( fh->fh_socket, IPPROTO_TCP, TCP_NODELAY, (const char*)&on, sizeof(on) );
-}
-
-/**************************************************************************/
-/**************************************************************************/
-/***** *****/
-/***** emulated socketpairs *****/
-/***** *****/
-/**************************************************************************/
-/**************************************************************************/
-
-/* we implement socketpairs directly in use space for the following reasons:
- * - it avoids copying data from/to the Nt kernel
- * - it allows us to implement fdevent hooks easily and cheaply, something
- * that is not possible with standard Win32 pipes !!
- *
- * basically, we use two circular buffers, each one corresponding to a given
- * direction.
- *
- * each buffer is implemented as two regions:
- *
- * region A which is (a_start,a_end)
- * region B which is (0, b_end) with b_end <= a_start
- *
- * an empty buffer has: a_start = a_end = b_end = 0
- *
- * a_start is the pointer where we start reading data
- * a_end is the pointer where we start writing data, unless it is BUFFER_SIZE,
- * then you start writing at b_end
- *
- * the buffer is full when b_end == a_start && a_end == BUFFER_SIZE
- *
- * there is room when b_end < a_start || a_end < BUFER_SIZE
- *
- * when reading, a_start is incremented, it a_start meets a_end, then
- * we do: a_start = 0, a_end = b_end, b_end = 0, and keep going on..
- */
-
-#define BIP_BUFFER_SIZE 4096
-
-#if 0
-#include <stdio.h>
-# define BIPD(x) D x
-# define BIPDUMP bip_dump_hex
-
-static void bip_dump_hex( const unsigned char* ptr, size_t len )
-{
- int nn, len2 = len;
-
- if (len2 > 8) len2 = 8;
-
- for (nn = 0; nn < len2; nn++)
- printf("%02x", ptr[nn]);
- printf(" ");
-
- for (nn = 0; nn < len2; nn++) {
- int c = ptr[nn];
- if (c < 32 || c > 127)
- c = '.';
- printf("%c", c);
- }
- printf("\n");
- fflush(stdout);
-}
-
-#else
-# define BIPD(x) do {} while (0)
-# define BIPDUMP(p,l) BIPD(p)
-#endif
-
-typedef struct BipBufferRec_
-{
- int a_start;
- int a_end;
- int b_end;
- int fdin;
- int fdout;
- int closed;
- int can_write; /* boolean */
- HANDLE evt_write; /* event signaled when one can write to a buffer */
- int can_read; /* boolean */
- HANDLE evt_read; /* event signaled when one can read from a buffer */
- CRITICAL_SECTION lock;
- unsigned char buff[ BIP_BUFFER_SIZE ];
-
-} BipBufferRec, *BipBuffer;
-
-static void
-bip_buffer_init( BipBuffer buffer )
-{
- D( "bit_buffer_init %p\n", buffer );
- buffer->a_start = 0;
- buffer->a_end = 0;
- buffer->b_end = 0;
- buffer->can_write = 1;
- buffer->can_read = 0;
- buffer->fdin = 0;
- buffer->fdout = 0;
- buffer->closed = 0;
- buffer->evt_write = CreateEvent( NULL, TRUE, TRUE, NULL );
- buffer->evt_read = CreateEvent( NULL, TRUE, FALSE, NULL );
- InitializeCriticalSection( &buffer->lock );
-}
-
-static void
-bip_buffer_close( BipBuffer bip )
-{
- bip->closed = 1;
-
- if (!bip->can_read) {
- SetEvent( bip->evt_read );
- }
- if (!bip->can_write) {
- SetEvent( bip->evt_write );
- }
-}
-
-static void
-bip_buffer_done( BipBuffer bip )
-{
- BIPD(( "bip_buffer_done: %d->%d\n", bip->fdin, bip->fdout ));
- CloseHandle( bip->evt_read );
- CloseHandle( bip->evt_write );
- DeleteCriticalSection( &bip->lock );
-}
-
-static int
-bip_buffer_write( BipBuffer bip, const void* src, int len )
-{
- int avail, count = 0;
-
- if (len <= 0)
- return 0;
-
- BIPD(( "bip_buffer_write: enter %d->%d len %d\n", bip->fdin, bip->fdout, len ));
- BIPDUMP( src, len );
-
- EnterCriticalSection( &bip->lock );
-
- while (!bip->can_write) {
- int ret;
- LeaveCriticalSection( &bip->lock );
-
- if (bip->closed) {
- errno = EPIPE;
- return -1;
- }
- /* spinlocking here is probably unfair, but let's live with it */
- ret = WaitForSingleObject( bip->evt_write, INFINITE );
- if (ret != WAIT_OBJECT_0) { /* buffer probably closed */
- D( "bip_buffer_write: error %d->%d WaitForSingleObject returned %d, error %ld\n", bip->fdin, bip->fdout, ret, GetLastError() );
- return 0;
- }
- if (bip->closed) {
- errno = EPIPE;
- return -1;
- }
- EnterCriticalSection( &bip->lock );
- }
-
- BIPD(( "bip_buffer_write: exec %d->%d len %d\n", bip->fdin, bip->fdout, len ));
-
- avail = BIP_BUFFER_SIZE - bip->a_end;
- if (avail > 0)
- {
- /* we can append to region A */
- if (avail > len)
- avail = len;
-
- memcpy( bip->buff + bip->a_end, src, avail );
- src += avail;
- count += avail;
- len -= avail;
-
- bip->a_end += avail;
- if (bip->a_end == BIP_BUFFER_SIZE && bip->a_start == 0) {
- bip->can_write = 0;
- ResetEvent( bip->evt_write );
- goto Exit;
- }
- }
-
- if (len == 0)
- goto Exit;
-
- avail = bip->a_start - bip->b_end;
- assert( avail > 0 ); /* since can_write is TRUE */
-
- if (avail > len)
- avail = len;
-
- memcpy( bip->buff + bip->b_end, src, avail );
- count += avail;
- bip->b_end += avail;
-
- if (bip->b_end == bip->a_start) {
- bip->can_write = 0;
- ResetEvent( bip->evt_write );
- }
-
-Exit:
- assert( count > 0 );
-
- if ( !bip->can_read ) {
- bip->can_read = 1;
- SetEvent( bip->evt_read );
- }
-
- BIPD(( "bip_buffer_write: exit %d->%d count %d (as=%d ae=%d be=%d cw=%d cr=%d\n",
- bip->fdin, bip->fdout, count, bip->a_start, bip->a_end, bip->b_end, bip->can_write, bip->can_read ));
- LeaveCriticalSection( &bip->lock );
-
- return count;
- }
-
-static int
-bip_buffer_read( BipBuffer bip, void* dst, int len )
-{
- int avail, count = 0;
-
- if (len <= 0)
- return 0;
-
- BIPD(( "bip_buffer_read: enter %d->%d len %d\n", bip->fdin, bip->fdout, len ));
-
- EnterCriticalSection( &bip->lock );
- while ( !bip->can_read )
- {
-#if 0
- LeaveCriticalSection( &bip->lock );
- errno = EAGAIN;
- return -1;
-#else
- int ret;
- LeaveCriticalSection( &bip->lock );
-
- if (bip->closed) {
- errno = EPIPE;
- return -1;
- }
-
- ret = WaitForSingleObject( bip->evt_read, INFINITE );
- if (ret != WAIT_OBJECT_0) { /* probably closed buffer */
- D( "bip_buffer_read: error %d->%d WaitForSingleObject returned %d, error %ld\n", bip->fdin, bip->fdout, ret, GetLastError());
- return 0;
- }
- if (bip->closed) {
- errno = EPIPE;
- return -1;
- }
- EnterCriticalSection( &bip->lock );
-#endif
- }
-
- BIPD(( "bip_buffer_read: exec %d->%d len %d\n", bip->fdin, bip->fdout, len ));
-
- avail = bip->a_end - bip->a_start;
- assert( avail > 0 ); /* since can_read is TRUE */
-
- if (avail > len)
- avail = len;
-
- memcpy( dst, bip->buff + bip->a_start, avail );
- dst += avail;
- count += avail;
- len -= avail;
-
- bip->a_start += avail;
- if (bip->a_start < bip->a_end)
- goto Exit;
-
- bip->a_start = 0;
- bip->a_end = bip->b_end;
- bip->b_end = 0;
-
- avail = bip->a_end;
- if (avail > 0) {
- if (avail > len)
- avail = len;
- memcpy( dst, bip->buff, avail );
- count += avail;
- bip->a_start += avail;
-
- if ( bip->a_start < bip->a_end )
- goto Exit;
-
- bip->a_start = bip->a_end = 0;
- }
-
- bip->can_read = 0;
- ResetEvent( bip->evt_read );
-
-Exit:
- assert( count > 0 );
-
- if (!bip->can_write ) {
- bip->can_write = 1;
- SetEvent( bip->evt_write );
- }
-
- BIPDUMP( (const unsigned char*)dst - count, count );
- BIPD(( "bip_buffer_read: exit %d->%d count %d (as=%d ae=%d be=%d cw=%d cr=%d\n",
- bip->fdin, bip->fdout, count, bip->a_start, bip->a_end, bip->b_end, bip->can_write, bip->can_read ));
- LeaveCriticalSection( &bip->lock );
-
- return count;
-}
-
-typedef struct SocketPairRec_
-{
- BipBufferRec a2b_bip;
- BipBufferRec b2a_bip;
- FH a_fd;
- int used;
-
-} SocketPairRec;
-
-void _fh_socketpair_init( FH f )
-{
- f->fh_pair = NULL;
-}
-
-static int
-_fh_socketpair_close( FH f )
-{
- if ( f->fh_pair ) {
- SocketPair pair = f->fh_pair;
-
- if ( f == pair->a_fd ) {
- pair->a_fd = NULL;
- }
-
- bip_buffer_close( &pair->b2a_bip );
- bip_buffer_close( &pair->a2b_bip );
-
- if ( --pair->used == 0 ) {
- bip_buffer_done( &pair->b2a_bip );
- bip_buffer_done( &pair->a2b_bip );
- free( pair );
- }
- f->fh_pair = NULL;
- }
- return 0;
-}
-
-static int
-_fh_socketpair_lseek( FH f, int pos, int origin )
-{
- errno = ESPIPE;
- return -1;
-}
-
-static int
-_fh_socketpair_read( FH f, void* buf, int len )
-{
- SocketPair pair = f->fh_pair;
- BipBuffer bip;
-
- if (!pair)
- return -1;
-
- if ( f == pair->a_fd )
- bip = &pair->b2a_bip;
- else
- bip = &pair->a2b_bip;
-
- return bip_buffer_read( bip, buf, len );
-}
-
-static int
-_fh_socketpair_write( FH f, const void* buf, int len )
-{
- SocketPair pair = f->fh_pair;
- BipBuffer bip;
-
- if (!pair)
- return -1;
-
- if ( f == pair->a_fd )
- bip = &pair->a2b_bip;
- else
- bip = &pair->b2a_bip;
-
- return bip_buffer_write( bip, buf, len );
-}
-
-
-static void _fh_socketpair_hook( FH f, int event, EventHook hook ); /* forward */
-
-static const FHClassRec _fh_socketpair_class =
-{
- _fh_socketpair_init,
- _fh_socketpair_close,
- _fh_socketpair_lseek,
- _fh_socketpair_read,
- _fh_socketpair_write,
- _fh_socketpair_hook
-};
-
-
-int sdb_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("sdb_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( "sdb_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 SDB doesn't use FDE_ERROR. *****/
-/***** *****/
-/**************************************************************************/
-/**************************************************************************/
-
-#define FATAL(x...) fatal(__FUNCTION__, x)
-
-#if DEBUG
-static void dump_fde(fdevent *fde, const char *info)
-{
- fprintf(stderr,"FDE #%03d %c%c%c %s\n", fde->fd,
- fde->state & FDE_READ ? 'R' : ' ',
- fde->state & FDE_WRITE ? 'W' : ' ',
- fde->state & FDE_ERROR ? 'E' : ' ',
- info);
-}
-#else
-#define dump_fde(fde, info) do { } while(0)
-#endif
-
-#define FDE_EVENTMASK 0x00ff
-#define FDE_STATEMASK 0xff00
-
-#define FDE_ACTIVE 0x0100
-#define FDE_PENDING 0x0200
-#define FDE_CREATED 0x0400
-
-static void fdevent_plist_enqueue(fdevent *node);
-static void fdevent_plist_remove(fdevent *node);
-static fdevent *fdevent_plist_dequeue(void);
-
-static fdevent list_pending = {
- .next = &list_pending,
- .prev = &list_pending,
-};
-
-static fdevent **fd_table = 0;
-static int fd_table_max = 0;
-
-typedef struct EventLooperRec_* EventLooper;
-
-typedef struct EventHookRec_
-{
- EventHook next;
- FH fh;
- HANDLE h;
- int wanted; /* wanted event flags */
- int ready; /* ready event flags */
- void* aux;
- void (*prepare)( EventHook hook );
- int (*start) ( EventHook hook );
- void (*stop) ( EventHook hook );
- int (*check) ( EventHook hook );
- int (*peek) ( EventHook hook );
-} EventHookRec;
-
-static EventHook _free_hooks;
-
-static EventHook
-event_hook_alloc( FH fh )
-{
- EventHook hook = _free_hooks;
- if (hook != NULL)
- _free_hooks = hook->next;
- else {
- hook = malloc( sizeof(*hook) );
- if (hook == NULL)
- fatal( "could not allocate event hook\n" );
- }
- hook->next = NULL;
- hook->fh = fh;
- hook->wanted = 0;
- hook->ready = 0;
- hook->h = INVALID_HANDLE_VALUE;
- hook->aux = NULL;
-
- hook->prepare = NULL;
- hook->start = NULL;
- hook->stop = NULL;
- hook->check = NULL;
- hook->peek = NULL;
-
- return hook;
-}
-
-static void
-event_hook_free( EventHook hook )
-{
- hook->fh = NULL;
- hook->wanted = 0;
- hook->ready = 0;
- hook->next = _free_hooks;
- _free_hooks = hook;
-}
-
-
-static void
-event_hook_signal( EventHook hook )
-{
- FH f = hook->fh;
- int fd = _fh_to_int(f);
- fdevent* fde = fd_table[ fd - WIN32_FH_BASE ];
-
- if (fde != NULL && fde->fd == fd) {
- if ((fde->state & FDE_PENDING) == 0) {
- fde->state |= FDE_PENDING;
- fdevent_plist_enqueue( fde );
- }
- fde->events |= hook->wanted;
- }
-}
-
-
-#define MAX_LOOPER_HANDLES WIN32_MAX_FHS
-
-typedef struct EventLooperRec_
-{
- EventHook hooks;
- HANDLE htab[ MAX_LOOPER_HANDLES ];
- int htab_count;
-
-} EventLooperRec;
-
-static EventHook*
-event_looper_find_p( EventLooper looper, FH fh )
-{
- EventHook *pnode = &looper->hooks;
- EventHook node = *pnode;
- for (;;) {
- if ( node == NULL || node->fh == fh )
- break;
- pnode = &node->next;
- node = *pnode;
- }
- return pnode;
-}
-
-static void
-event_looper_hook( EventLooper looper, int fd, int events )
-{
- FH f = _fh_from_int(fd);
- EventHook *pnode;
- EventHook node;
-
- if (f == NULL) /* invalid arg */ {
- D("event_looper_hook: invalid fd=%d\n", fd);
- return;
- }
-
- pnode = event_looper_find_p( looper, f );
- node = *pnode;
- if ( node == NULL ) {
- node = event_hook_alloc( f );
- node->next = *pnode;
- *pnode = node;
- }
-
- if ( (node->wanted & events) != events ) {
- /* this should update start/stop/check/peek */
- D("event_looper_hook: call hook for %d (new=%x, old=%x)\n",
- fd, node->wanted, events);
- f->clazz->_fh_hook( f, events & ~node->wanted, node );
- node->wanted |= events;
- } else {
- D("event_looper_hook: ignoring events %x for %d wanted=%x)\n",
- events, fd, node->wanted);
- }
-}
-
-static void
-event_looper_unhook( EventLooper looper, int fd, int events )
-{
- FH fh = _fh_from_int(fd);
- EventHook *pnode = event_looper_find_p( looper, fh );
- EventHook node = *pnode;
-
- if (node != NULL) {
- int events2 = events & node->wanted;
- if ( events2 == 0 ) {
- D( "event_looper_unhook: events %x not registered for fd %d\n", events, fd );
- return;
- }
- node->wanted &= ~events2;
- if (!node->wanted) {
- *pnode = node->next;
- event_hook_free( node );
- }
- }
-}
-
-static EventLooperRec win32_looper;
-
-static void fdevent_init(void)
-{
- win32_looper.htab_count = 0;
- win32_looper.hooks = NULL;
-}
-
-static void fdevent_connect(fdevent *fde)
-{
- EventLooper looper = &win32_looper;
- int events = fde->state & FDE_EVENTMASK;
-
- if (events != 0)
- event_looper_hook( looper, fde->fd, events );
-}
-
-static void fdevent_disconnect(fdevent *fde)
-{
- EventLooper looper = &win32_looper;
- int events = fde->state & FDE_EVENTMASK;
-
- if (events != 0)
- event_looper_unhook( looper, fde->fd, events );
-}
-
-static void fdevent_update(fdevent *fde, unsigned events)
-{
- EventLooper looper = &win32_looper;
- unsigned events0 = fde->state & FDE_EVENTMASK;
-
- if (events != events0) {
- int removes = events0 & ~events;
- int adds = events & ~events0;
- if (removes) {
- D("fdevent_update: remove %x from %d\n", removes, fde->fd);
- event_looper_unhook( looper, fde->fd, removes );
- }
- if (adds) {
- D("fdevent_update: add %x to %d\n", adds, fde->fd);
- event_looper_hook ( looper, fde->fd, adds );
- }
- }
-}
-
-static void fdevent_process()
-{
- EventLooper looper = &win32_looper;
- EventHook hook;
- int gotone = 0;
-
- /* if we have at least one ready hook, execute it/them */
- for (hook = looper->hooks; hook; hook = hook->next) {
- hook->ready = 0;
- if (hook->prepare) {
- hook->prepare(hook);
- if (hook->ready != 0) {
- event_hook_signal( hook );
- gotone = 1;
- }
- }
- }
-
- /* nothing's ready yet, so wait for something to happen */
- if (!gotone)
- {
- looper->htab_count = 0;
-
- for (hook = looper->hooks; hook; hook = hook->next)
- {
- if (hook->start && !hook->start(hook)) {
- D( "fdevent_process: error when starting a hook\n" );
- return;
- }
- if (hook->h != INVALID_HANDLE_VALUE) {
- int nn;
-
- for (nn = 0; nn < looper->htab_count; nn++)
- {
- if ( looper->htab[nn] == hook->h )
- goto DontAdd;
- }
- looper->htab[ looper->htab_count++ ] = hook->h;
- DontAdd:
- ;
- }
- }
-
- if (looper->htab_count == 0) {
- D( "fdevent_process: nothing to wait for !!\n" );
- return;
- }
-
- do
- {
- int wait_ret;
-
- D( "sdb_win32: waiting for %d events\n", looper->htab_count );
- if (looper->htab_count > MAXIMUM_WAIT_OBJECTS) {
- D("handle count %d exceeds MAXIMUM_WAIT_OBJECTS, aborting!\n", looper->htab_count);
- abort();
- }
- wait_ret = WaitForMultipleObjects( looper->htab_count, looper->htab, FALSE, INFINITE );
- if (wait_ret == (int)WAIT_FAILED) {
- D( "sdb_win32: wait failed, error %ld\n", GetLastError() );
- } else {
- D( "sdb_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( "sdb_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");
- sdb_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
-sdb_sysdeps_init( void )
-{
-#define SDB_MUTEX(x) InitializeCriticalSection( & x );
-#include "mutex_list.h"
- InitializeCriticalSection( &_win32_lock );
-}
#define TRACE_TAG TRACE_TRANSPORT
#include "sdb.h"
-#if SDB_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)
+++ /dev/null
-/*
- * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
- *
- * Licensed under the Apache License, Version 2.0 (the License);
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an AS IS BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <sys/endian.h>
-#include <sys/ioctl.h>
-#include <sys/types.h>
-#include <sys/uio.h>
-
-#include <err.h>
-#include <errno.h>
-#include <poll.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <strings.h>
-#include <string.h>
-#include <sysexits.h>
-#include <unistd.h>
-#include <libusb.h>
-#include "sysdeps.h"
-
-#define TRACE_TAG TRACE_USB
-#include "sdb.h"
-
-static sdb_mutex_t usb_lock = SDB_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];
-
- sdb_cond_t notify;
- sdb_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, size_t 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);
- sdb_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);
-
- sdb_mutex_unlock(&usb_lock);
-
- free(h);
-
- return (0);
-}
-
-void usb_kick(struct usb_handle *h)
-{
- D("usb_cick(): kicking transport %p\n", h);
-
- sdb_mutex_lock(&h->lock);
- unregister_usb_transport(h);
- sdb_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_sdb_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);
-
- sdb_cond_init(&usb->notify, 0);
- sdb_mutex_init(&usb->lock, 0);
-
- sdb_mutex_lock(&usb_lock);
-
- usb->next = &handle_list;
- usb->prev = handle_list.prev;
- usb->prev->next = usb;
- usb->next->prev = usb;
-
- sdb_mutex_unlock(&usb_lock);
-
- register_usb_transport(usb, serial, 1);
-
- return (1);
-}
-
-int
-already_registered(usb_handle *uh)
-{
- struct usb_handle *usb= NULL;
- int exists = 0;
-
- sdb_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;
- }
- }
-
- sdb_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_sdb_interface (desc.idVendor, desc.idProduct,
- SDB_CLASS, SDB_SUBCLASS, SDB_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;
-
- sdb_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);
- }
- }
-
- sdb_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");
- sdb_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 (sdb_thread_create(&tid, device_poll_thread, NULL)) {
- err(EX_IOERR, "cannot create USB scan thread\n");
- }
-
- D("usb_init(): finished\n");
-}
-
+++ /dev/null
-/*
- * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
- *
- * Licensed under the Apache License, Version 2.0 (the License);
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an AS IS BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <CoreFoundation/CoreFoundation.h>
-
-#include <IOKit/IOKitLib.h>
-#include <IOKit/IOCFPlugIn.h>
-#include <IOKit/usb/IOUSBLib.h>
-#include <IOKit/IOMessage.h>
-#include <mach/mach_port.h>
-
-#include "sysdeps.h"
-
-#include <stdio.h>
-
-#define TRACE_TAG TRACE_USB
-#include "sdb.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
- //* sdb 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 = SDB_SUBCLASS;
- if_protocol = SDB_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;
- UInt16 vendor;
- UInt16 product;
- UInt8 serialIndex;
- char serial[256];
-
- 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)->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), 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 SDB 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 SDB
- //* avoid opening mass storage endpoints
- if (!is_sdb_interface(vendor, product, interfaceClass,
- interfaceSubClass, interfaceProtocol))
- goto err_bad_sdb_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_sdb_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
- sdb_mutex_lock(&start_lock);
- sdb_cond_signal(&start_cond);
- sdb_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)
- {
- sdb_thread_t tid;
-
- notificationIterators = (io_iterator_t*)malloc(
- vendorIdCount * sizeof(io_iterator_t));
-
- sdb_mutex_init(&start_lock, NULL);
- sdb_cond_init(&start_cond, NULL);
-
- if(sdb_thread_create(&tid, RunLoopThread, NULL))
- fatal_errno("cannot create input thread");
-
- // Wait for initialization to finish
- sdb_mutex_lock(&start_lock);
- sdb_cond_wait(&start_cond, &start_lock);
- sdb_mutex_unlock(&start_lock);
-
- sdb_mutex_destroy(&start_lock);
- sdb_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;
- }
-}
+++ /dev/null
-/*
- * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
- *
- * 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 <stdio.h>
-
-#ifdef _WIN32
-# define WIN32_LEAN_AND_MEAN
-# include "windows.h"
-# include "shlobj.h"
-#else
-# include <unistd.h>
-# include <sys/stat.h>
-#endif
-
-#include "sysdeps.h"
-#include "sdb.h"
-
-#define ANDROID_PATH ".android"
-#define ANDROID_SDB_INI "sdb_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
-
-/** 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,
-};
-
-#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_sdb_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_sdb_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_SDB_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 sdb 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_SDB_INI) >= (signed)len) {
- return 1;
- }
-
- return 0;
-}
-
-/* fills buff with the path to the sdb vendor id file. returns 0 if success */
-int get_sdb_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
-}
+++ /dev/null
-/*
- * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
- *
- * 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
+++ /dev/null
-/*
- * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
- *
- * Licensed under the Apache License, Version 2.0 (the License);
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an AS IS BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <windows.h>
-#include <winerror.h>
-#include <errno.h>
-#include <usb100.h>
-#include <sdb_api.h>
-#include <stdio.h>
-
-#include "sysdeps.h"
-
-#define TRACE_TAG TRACE_USB
-#include "sdb.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
- SDBAPIHANDLE sdb_interface;
-
- /// Handle to USB read pipe (endpoint)
- SDBAPIHANDLE sdb_read_pipe;
-
- /// Handle to USB write pipe (endpoint)
- SDBAPIHANDLE sdb_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
-SDB_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) {
- sdb_mutex_lock(&usb_lock);
- ret = known_device_locked(dev_name);
- sdb_mutex_unlock(&usb_lock);
- }
-
- return ret;
-}
-
-int register_new_device(usb_handle* handle) {
- if (NULL == handle)
- return 0;
-
- sdb_mutex_lock(&usb_lock);
-
- // Check if device is already in the list
- if (known_device_locked(handle->interface_name)) {
- sdb_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;
-
- sdb_mutex_unlock(&usb_lock);
-
- return 1;
-}
-
-void* device_poll_thread(void* unused) {
- D("Created device thread\n");
-
- while(1) {
- find_devices();
- sdb_sleep_ms(1000);
- }
-
- return NULL;
-}
-
-void usb_init() {
- sdb_thread_t tid;
-
- if(sdb_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->sdb_interface = SdbCreateInterfaceByName(interface_name);
-
- if (NULL == ret->sdb_interface) {
- free(ret);
- errno = GetLastError();
- return NULL;
- }
-
- // Open read pipe (endpoint)
- ret->sdb_read_pipe =
- SdbOpenDefaultBulkReadEndpoint(ret->sdb_interface,
- SdbOpenAccessTypeReadWrite,
- SdbOpenSharingModeReadWrite);
- if (NULL != ret->sdb_read_pipe) {
- // Open write pipe (endpoint)
- ret->sdb_write_pipe =
- SdbOpenDefaultBulkWriteEndpoint(ret->sdb_interface,
- SdbOpenAccessTypeReadWrite,
- SdbOpenSharingModeReadWrite);
- if (NULL != ret->sdb_write_pipe) {
- // Save interface name
- unsigned long name_len = 0;
-
- // First get expected name length
- SdbGetInterfaceName(ret->sdb_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 (SdbGetInterfaceName(ret->sdb_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 = SdbWriteEndpointSync(handle->sdb_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
- SdbWriteEndpointSync(handle->sdb_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 = SdbReadEndpointSync(handle->sdb_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->sdb_write_pipe)
- SdbCloseHandle(handle->sdb_write_pipe);
- if (NULL != handle->sdb_read_pipe)
- SdbCloseHandle(handle->sdb_read_pipe);
- if (NULL != handle->sdb_interface)
- SdbCloseHandle(handle->sdb_interface);
-
- handle->interface_name = NULL;
- handle->sdb_write_pipe = NULL;
- handle->sdb_read_pipe = NULL;
- handle->sdb_interface = NULL;
- }
-}
-
-void usb_kick(usb_handle* handle) {
- if (NULL != handle) {
- sdb_mutex_lock(&usb_lock);
-
- usb_cleanup_handle(handle);
-
- sdb_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
- sdb_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;
- }
-
- sdb_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 (!SdbGetUsbDeviceDescriptor(handle->sdb_interface,
- &device_desc)) {
- return 0;
- }
-
- // Then check interface properties
- USB_INTERFACE_DESCRIPTOR interf_desc;
-
- if (!SdbGetUsbInterfaceDescriptor(handle->sdb_interface,
- &interf_desc)) {
- return 0;
- }
-
- // Must have two endpoints
- if (2 != interf_desc.bNumEndpoints) {
- return 0;
- }
-
- if (is_sdb_interface(device_desc.idVendor, device_desc.idProduct,
- interf_desc.bInterfaceClass, interf_desc.bInterfaceSubClass, interf_desc.bInterfaceProtocol)) {
-
- if(interf_desc.bInterfaceProtocol == 0x01) {
- SdbEndpointInformation endpoint_info;
- // assuming zero is a valid bulk endpoint ID
- if (SdbGetEndpointInformation(handle->sdb_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];
- SdbInterfaceInfo* next_interface = (SdbInterfaceInfo*)(&entry_buffer[0]);
- unsigned long entry_buffer_size = sizeof(entry_buffer);
- char* copy_name;
-
- // Enumerate all present and active interfaces.
- SDBAPIHANDLE enum_handle =
- SdbEnumInterfaces(usb_class_id, true, true, true);
-
- if (NULL == enum_handle)
- return;
-
- while (SdbNextInterface(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 (SdbGetSerialNumber(handle->sdb_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, 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);
- }
-
- SdbCloseHandle(enum_handle);
-}
+++ /dev/null
-/*\r
- * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved\r
- *\r
- * Licensed under the Apache License, Version 2.0 (the License);\r
- * you may not use this file except in compliance with the License.\r
- * You may obtain a copy of the License at\r
- *\r
- * http://www.apache.org/licenses/LICENSE-2.0\r
- *\r
- * Unless required by applicable law or agreed to in writing, software\r
- * distributed under the License is distributed on an AS IS BASIS,\r
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
- * See the License for the specific language governing permissions and\r
- * limitations under the License.\r
- */\r
-\r
-/* a simple test program, connects to SDB server, and opens a track-devices session */\r
-#include <netdb.h>\r
-#include <sys/socket.h>\r
-#include <stdio.h>\r
-#include <stdlib.h>\r
-#include <errno.h>\r
-#include <memory.h>\r
-\r
-static void\r
-panic( const char* msg )\r
-{\r
- fprintf(stderr, "PANIC: %s: %s\n", msg, strerror(errno));\r
- exit(1);\r
-}\r
-\r
-static int\r
-unix_write( int fd, const char* buf, int len )\r
-{\r
- int result = 0;\r
- while (len > 0) {\r
- int len2 = write(fd, buf, len);\r
- if (len2 < 0) {\r
- if (errno == EINTR || errno == EAGAIN)\r
- continue;\r
- return -1;\r
- }\r
- result += len2;\r
- len -= len2;\r
- buf += len2;\r
- }\r
- return result;\r
-}\r
-\r
-static int unix_read( int fd, char* buf, int len )\r
-{\r
- int result = 0;\r
- while (len > 0) {\r
- int len2 = read(fd, buf, len);\r
- if (len2 < 0) {\r
- if (errno == EINTR || errno == EAGAIN)\r
- continue;\r
- return -1;\r
- }\r
- result += len2;\r
- len -= len2;\r
- buf += len2;\r
- }\r
- return result;\r
-}\r
-\r
-int main( void )\r
-{\r
- int ret, s;\r
- struct sockaddr_in server;\r
- char buffer[1024];\r
- const char* transport = "host:transport-a";\r
- const char* request = "cs:";\r
- int len;\r
-\r
- memset( &server, 0, sizeof(server) );\r
- server.sin_family = AF_INET;\r
- server.sin_port = htons(26099);\r
- server.sin_addr.s_addr = htonl(INADDR_LOOPBACK);\r
-\r
- s = socket( PF_INET, SOCK_STREAM, 0 );\r
- ret = connect( s, (struct sockaddr*) &server, sizeof(server) );\r
- if (ret < 0) panic( "could not connect to server" );\r
-\r
- /* send the transport */\r
- len = snprintf( buffer, sizeof buffer, "%04x%s", strlen(transport), transport );\r
- if (unix_write(s, buffer, len) < 0)\r
- panic( "could not send request" );\r
-\r
- /* read the OKAY answer */\r
- if (unix_read(s, buffer, 4) != 4)\r
- panic( "could not read request" );\r
-\r
- /* send the request */\r
- len = snprintf( buffer, sizeof buffer, "%04x%s", strlen(request), request );\r
- if (unix_write(s, buffer, len) < 0)\r
- panic( "could not send request" );\r
-\r
- /* read the OKAY answer */\r
- if (unix_read(s, buffer, 4) != 4)\r
- panic( "could not read request" );\r
-\r
- printf( "server answer: %.*s\n", 4, buffer );\r
-\r
- /* now loop */\r
- for (;;) {\r
- memset(buffer, 0, sizeof(buffer));\r
- if (unix_read(s, buffer, 30) < 0)\r
- panic("could not read length");\r
-\r
- printf( "server answer: %s\n",buffer );\r
- break;\r
- }\r
- close(s);\r
-}\r
+++ /dev/null
-/*
- * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
- *
- * 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.
- */
-
-/* a simple test program, connects to SDB server, and opens a track-devices session */
-#include <netdb.h>
-#include <sys/socket.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <errno.h>
-#include <memory.h>
-
-static void
-panic( const char* msg )
-{
- fprintf(stderr, "PANIC: %s: %s\n", msg, strerror(errno));
- exit(1);
-}
-
-static int
-unix_write( int fd, const char* buf, int len )
-{
- int result = 0;
- while (len > 0) {
- int len2 = write(fd, buf, len);
- if (len2 < 0) {
- if (errno == EINTR || errno == EAGAIN)
- continue;
- return -1;
- }
- result += len2;
- len -= len2;
- buf += len2;
- }
- return result;
-}
-
-static int
-unix_read( int fd, char* buf, int len )
-{
- int result = 0;
- while (len > 0) {
- int len2 = read(fd, buf, len);
- if (len2 < 0) {
- if (errno == EINTR || errno == EAGAIN)
- continue;
- return -1;
- }
- result += len2;
- len -= len2;
- buf += len2;
- }
- return result;
-}
-
-
-int main( void )
-{
- int ret, s;
- struct sockaddr_in server;
- char buffer[1024];
- const char* request = "host:track-devices";
- int len;
-
- memset( &server, 0, sizeof(server) );
- server.sin_family = AF_INET;
- server.sin_port = htons(5037);
- server.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
-
- s = socket( PF_INET, SOCK_STREAM, 0 );
- ret = connect( s, (struct sockaddr*) &server, sizeof(server) );
- if (ret < 0) panic( "could not connect to server" );
-
- /* send the request */
- len = snprintf( buffer, sizeof buffer, "%04x%s", strlen(request), request );
- if (unix_write(s, buffer, len) < 0)
- panic( "could not send request" );
-
- /* read the OKAY answer */
- if (unix_read(s, buffer, 4) != 4)
- panic( "could not read request" );
-
- printf( "server answer: %.*s\n", 4, buffer );
-
- /* now loop */
- for (;;) {
- char head[5] = "0000";
-
- if (unix_read(s, head, 4) < 0)
- panic("could not read length");
-
- if ( sscanf( head, "%04x", &len ) != 1 )
- panic("could not decode length");
-
- if (unix_read(s, buffer, len) != len)
- panic("could not read data");
-
- printf( "received header %.*s (%d bytes):\n%.*s", 4, head, len, len, buffer );
- }
- close(s);
-}
+++ /dev/null
-/*
- * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
- *
- * 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.
- */
-
-/* a simple test program, connects to SDB server, and opens a track-devices session */
-#include <netdb.h>
-#include <sys/socket.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <errno.h>
-#include <memory.h>
-
-static void
-panic( const char* msg )
-{
- fprintf(stderr, "PANIC: %s: %s\n", msg, strerror(errno));
- exit(1);
-}
-
-static int
-unix_write( int fd, const char* buf, int len )
-{
- int result = 0;
- while (len > 0) {
- int len2 = write(fd, buf, len);
- if (len2 < 0) {
- if (errno == EINTR || errno == EAGAIN)
- continue;
- return -1;
- }
- result += len2;
- len -= len2;
- buf += len2;
- }
- return result;
-}
-
-static int
-unix_read( int fd, char* buf, int len )
-{
- int result = 0;
- while (len > 0) {
- int len2 = read(fd, buf, len);
- if (len2 < 0) {
- if (errno == EINTR || errno == EAGAIN)
- continue;
- return -1;
- }
- result += len2;
- len -= len2;
- buf += len2;
- }
- return result;
-}
-
-
-int main( void )
-{
- int ret, s;
- struct sockaddr_in server;
- char buffer[1024];
- const char* request = "track-jdwp";
- int len;
-
- memset( &server, 0, sizeof(server) );
- server.sin_family = AF_INET;
- server.sin_port = htons(5037);
- server.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
-
- s = socket( PF_INET, SOCK_STREAM, 0 );
- ret = connect( s, (struct sockaddr*) &server, sizeof(server) );
- if (ret < 0) panic( "could not connect to server" );
-
- /* send the request */
- len = snprintf( buffer, sizeof buffer, "%04x%s", strlen(request), request );
- if (unix_write(s, buffer, len) < 0)
- panic( "could not send request" );
-
- /* read the OKAY answer */
- if (unix_read(s, buffer, 4) != 4)
- panic( "could not read request" );
-
- printf( "server answer: %.*s\n", 4, buffer );
-
- /* now loop */
- for (;;) {
- char head[5] = "0000";
-
- if (unix_read(s, head, 4) < 0)
- panic("could not read length");
-
- if ( sscanf( head, "%04x", &len ) != 1 )
- panic("could not decode length");
-
- if (unix_read(s, buffer, len) != len)
- panic("could not read data");
-
- printf( "received header %.*s (%d bytes):\n%.*s", 4, head, len, len, buffer );
- }
- close(s);
-}