Merge change I4e5c1c26

* changes:
  Fix use of memset function
diff --git a/adb/Android.mk b/adb/Android.mk
index f3eaa6e..6325e53 100644
--- a/adb/Android.mk
+++ b/adb/Android.mk
@@ -25,6 +25,12 @@
   LOCAL_LDLIBS += -lpthread -framework CoreFoundation -framework IOKit -framework Carbon
 endif
 
+ifeq ($(HOST_OS),freebsd)
+  USB_SRCS := usb_libusb.c
+  EXTRA_SRCS := get_my_path_freebsd.c
+  LOCAL_LDLIBS += -lpthread -lusb
+endif
+
 ifeq ($(HOST_OS),windows)
   USB_SRCS := usb_windows.c
   EXTRA_SRCS := get_my_path_windows.c
diff --git a/adb/MODULE_LICENSE_APACHE2 b/adb/MODULE_LICENSE_APACHE2
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/adb/MODULE_LICENSE_APACHE2
diff --git a/adb/NOTICE b/adb/NOTICE
new file mode 100644
index 0000000..9ffcc08
--- /dev/null
+++ b/adb/NOTICE
@@ -0,0 +1,191 @@
+
+   Copyright (c) 2006-2009, The Android Open Source Project
+   Copyright 2006, Brian Swetland <swetland@frotz.net>
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+
+   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.
+
+
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
diff --git a/adb/adb.c b/adb/adb.c
index 283ebce..7df3f7b 100644
--- a/adb/adb.c
+++ b/adb/adb.c
@@ -783,7 +783,7 @@
         fprintf(stderr, "pipe failed in launch_server, errno: %d\n", errno);
         return -1;
     }
-    get_my_path(path);
+    get_my_path(path, PATH_MAX);
     pid_t pid = fork();
     if(pid < 0) return -1;
 
@@ -1020,19 +1020,24 @@
         char* portstr = strchr(host, ':');
 
         if (!portstr) {
-            snprintf(buffer, sizeof(buffer), "unable to parse %s as <host>:<port>\n", host);
+            snprintf(buffer, sizeof(buffer), "unable to parse %s as <host>:<port>", host);
             goto done;
         }
+        if (find_transport(host)) {
+            snprintf(buffer, sizeof(buffer), "Already connected to %s", host);
+            goto done;
+        }
+
         // zero terminate host by overwriting the ':'
         *portstr++ = 0;
         if (sscanf(portstr, "%d", &port) == 0) {
-            snprintf(buffer, sizeof(buffer), "bad port number %s\n", portstr);
+            snprintf(buffer, sizeof(buffer), "bad port number %s", portstr);
             goto done;
         }
 
         fd = socket_network_client(host, port, SOCK_STREAM);
         if (fd < 0) {
-            snprintf(buffer, sizeof(buffer), "unable to connect to %s:%d\n", host, port);
+            snprintf(buffer, sizeof(buffer), "unable to connect to %s:%d", host, port);
             goto done;
         }
 
@@ -1041,10 +1046,28 @@
         disable_tcp_nagle(fd);
         snprintf(buf, sizeof buf, "%s:%d", host, port);
         register_socket_transport(fd, buf, port, 0);
-        snprintf(buffer, sizeof(buffer), "connected to %s:%d\n", host, port);
+        snprintf(buffer, sizeof(buffer), "connected to %s:%d", host, port);
 
 done:
-        snprintf(buf, sizeof(buf), "OKAY%04x%s",(unsigned)strlen(buffer),buffer);
+        snprintf(buf, sizeof(buf), "OKAY%04x%s",(unsigned)strlen(buffer), buffer);
+        writex(reply_fd, buf, strlen(buf));
+        return 0;
+    }
+
+    // remove TCP transport
+    if (!strncmp(service, "disconnect:", 11)) {
+        char buffer[4096];
+        memset(buffer, 0, sizeof(buffer));
+        char* serial = service + 11;
+        atransport *t = find_transport(serial);
+
+        if (t) {
+            unregister_transport(t);
+        } else {
+            snprintf(buffer, sizeof(buffer), "No such device %s", serial);
+        }
+
+        snprintf(buf, sizeof(buf), "OKAY%04x%s",(unsigned)strlen(buffer), buffer);
         writex(reply_fd, buf, strlen(buf));
         return 0;
     }
diff --git a/adb/adb.h b/adb/adb.h
index 713666f..a148019 100644
--- a/adb/adb.h
+++ b/adb/adb.h
@@ -236,7 +236,7 @@
 void handle_packet(apacket *p, atransport *t);
 void send_packet(apacket *p, atransport *t);
 
-void get_my_path(char s[PATH_MAX]);
+void get_my_path(char *s, size_t maxLen);
 int launch_server();
 int adb_main(int is_daemon);
 
@@ -270,11 +270,17 @@
 
 /* cause new transports to be init'd and added to the list */
 void register_socket_transport(int s, const char *serial, int port, int local);
+
+/* this should only be used for the "adb disconnect" command */
+void unregister_transport(atransport *t);
+
 void register_usb_transport(usb_handle *h, const char *serial, unsigned writeable);
 
 /* this should only be used for transports with connection_state == CS_NOPERM */
 void unregister_usb_transport(usb_handle *usb);
 
+atransport *find_transport(const char *serial);
+
 int service_to_fd(const char *name);
 #if ADB_HOST
 asocket *host_service_to_socket(const char*  name, const char *serial);
diff --git a/adb/commandline.c b/adb/commandline.c
index 411bb82..52bcedc 100644
--- a/adb/commandline.c
+++ b/adb/commandline.c
@@ -50,7 +50,7 @@
 
 static int do_cmd(transport_type ttype, char* serial, char *cmd, ...);
 
-void get_my_path(char s[PATH_MAX]);
+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);
@@ -106,6 +106,7 @@
         "                                 be an absolute path.\n"
         " devices                       - list all connected devices\n"
         " connect <host>:<port>         - connect to a device via TCP/IP"
+        " disconnect <host>:<port>      - disconnect from a TCP/IP device"
         "\n"
         "device commands:\n"
         "  adb push <local> <remote>    - copy file/dir to device\n"
@@ -672,7 +673,7 @@
         /* If the CWD isn't under a good-looking top, see if the
          * executable is.
          */
-        get_my_path(dir);
+        get_my_path(dir, PATH_MAX);
         top = find_top_from(dir, path_buf);
     }
     return top;
@@ -853,10 +854,10 @@
         }
     }
 
-    if(!strcmp(argv[0], "connect")) {
+    if(!strcmp(argv[0], "connect") || !strcmp(argv[0], "disconnect")) {
         char *tmp;
         if (argc != 2) {
-            fprintf(stderr, "Usage: adb connect <host>:<port>\n");
+            fprintf(stderr, "Usage: adb %s <host>:<port>\n", argv[0]);
             return 1;
         }
         snprintf(buf, sizeof buf, "host:%s:%s", argv[0], argv[1]);
diff --git a/adb/get_my_path_darwin.c b/adb/get_my_path_darwin.c
index 6125cb4..5b95d15 100644
--- a/adb/get_my_path_darwin.c
+++ b/adb/get_my_path_darwin.c
@@ -17,7 +17,7 @@
 #import <Carbon/Carbon.h>
 #include <unistd.h>
 
-void get_my_path(char s[PATH_MAX])
+void get_my_path(char *s, size_t maxLen)
 {
     ProcessSerialNumber psn;
     GetCurrentProcess(&psn);
@@ -25,6 +25,6 @@
     dict = ProcessInformationCopyDictionary(&psn, 0xffffffff);
     CFStringRef value = (CFStringRef)CFDictionaryGetValue(dict,
                 CFSTR("CFBundleExecutable"));
-    CFStringGetCString(value, s, PATH_MAX - 1, kCFStringEncodingUTF8);
+    CFStringGetCString(value, s, maxLen, kCFStringEncodingUTF8);
 }
 
diff --git a/adb/get_my_path_freebsd.c b/adb/get_my_path_freebsd.c
new file mode 100644
index 0000000..b06ec66
--- /dev/null
+++ b/adb/get_my_path_freebsd.c
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2009 bsdroid project
+ *               Alexey Tarasov <tarasov@dodologics.com>
+ *
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <sys/types.h>
+#include <unistd.h>
+#include <limits.h>
+#include <stdio.h>
+
+void
+get_my_path(char *exe, 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';
+}
+
diff --git a/adb/get_my_path_linux.c b/adb/get_my_path_linux.c
index f516e59..179c3dd 100644
--- a/adb/get_my_path_linux.c
+++ b/adb/get_my_path_linux.c
@@ -19,15 +19,15 @@
 #include <limits.h>
 #include <stdio.h>
 
-void get_my_path(char exe[PATH_MAX])
+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, PATH_MAX - 1);
+    int err = readlink(proc, exe, maxLen - 1);
     if(err > 0) {
-        exe[err] = 0;
+        exe[err] = '\0';
     } else {
-        exe[0] = 0;
+        exe[0] = '\0';
     }
 }
 
diff --git a/adb/get_my_path_windows.c b/adb/get_my_path_windows.c
index fc7143c..ddf2816 100644
--- a/adb/get_my_path_windows.c
+++ b/adb/get_my_path_windows.c
@@ -18,14 +18,17 @@
 #include <assert.h>
 #include <windows.h>
 
-void get_my_path(char exe[PATH_MAX])
+void get_my_path(char *exe, size_t maxLen)
 {
-    char*  r;
+    char  *r;
 
-    GetModuleFileName( NULL, exe, PATH_MAX-1 );
-    exe[PATH_MAX-1] = 0;
-    r = strrchr( exe, '\\' );
-    if (r)
-        *r = 0;
+    /* XXX: should be GetModuleFileNameA */
+    if (GetModuleFileName(NULL, exe, maxLen) > 0) {
+        r = strrchr(exe, '\\');
+        if (r != NULL)
+            *r = '\0';
+    } else {
+        exe[0] = '\0';
+    }
 }
 
diff --git a/adb/jdwp_service.c b/adb/jdwp_service.c
index ae7f12d..0c26f7b 100644
--- a/adb/jdwp_service.c
+++ b/adb/jdwp_service.c
@@ -164,7 +164,7 @@
         proc->next->prev = proc->prev;
 
         if (proc->socket >= 0) {
-            shutdown(proc->socket, SHUT_RDWR);
+            adb_shutdown(proc->socket);
             adb_close(proc->socket);
             proc->socket = -1;
         }
diff --git a/adb/services.c b/adb/services.c
index 2864ac9..b5df554 100644
--- a/adb/services.c
+++ b/adb/services.c
@@ -32,8 +32,7 @@
 #    include <netdb.h>
 #  endif
 #else
-#include <sys/poll.h>
-#include <sys/reboot.h>
+#  include <sys/reboot.h>
 #endif
 
 typedef struct stinfo stinfo;
@@ -64,6 +63,7 @@
 
     adb_mutex_lock(&dns_lock);
     hp = gethostbyname(hostname);
+    free(cookie);
     if(hp == 0) {
         writex(fd, &zero, 4);
     } else {
@@ -185,6 +185,7 @@
         snprintf(buf, sizeof(buf), "reboot failed: %s\n", strerror(errno));
         writex(fd, buf, strlen(buf));
     }
+    free(arg);
     adb_close(fd);
 }
 
@@ -253,9 +254,12 @@
     return s[0];
 }
 
-#if !ADB_HOST
 static int create_subprocess(const char *cmd, const char *arg0, const char *arg1)
 {
+#ifdef HAVE_WIN32_PROC
+	fprintf(stderr, "error: create_subprocess not implemented on Win32 (%s %s %s)\n", cmd, arg0, arg1);
+	return -1;
+#else /* !HAVE_WIN32_PROC */
     char *devname;
     int ptm;
     pid_t pid;
@@ -298,6 +302,7 @@
                 cmd, strerror(errno), errno);
         exit(-1);
     } else {
+#if !ADB_HOST
         // set child's OOM adjustment to zero
         char text[64];
         snprintf(text, sizeof text, "/proc/%d/oom_adj", pid);
@@ -308,11 +313,11 @@
         } else {
            D("adb: unable to open %s\n", text);
         }
-
+#endif
         return ptm;
     }
+#endif /* !HAVE_WIN32_PROC */
 }
-#endif /* !ADB_HOST */
 
 #if ADB_HOST
 #define SHELL_COMMAND "/bin/sh"
@@ -320,76 +325,6 @@
 #define SHELL_COMMAND "/system/bin/sh"
 #endif
 
-#if !ADB_HOST
-static void shell_service(int s, void *command)
-{
-    char    buffer[MAX_PAYLOAD];
-    char    buffer2[MAX_PAYLOAD];
-    struct pollfd ufds[2];
-    int     fd, ret = 0;
-    unsigned count = 0;
-    char** args = (char **)command;
-    fd = create_subprocess(SHELL_COMMAND, args[0], args[1]);
-
-    while (1) {
-        while (count < sizeof(buffer)) {
-            ufds[0].fd = fd;
-            ufds[0].events = POLLIN | POLLHUP;
-            ufds[0].revents = 0;
-            ufds[1].fd = s;
-            ufds[1].events = POLLIN | POLLHUP;
-            ufds[1].revents = 0;
-            // use a 100ms timeout so we don't block indefinitely with our
-            // buffer partially filled.
-            ret = poll(ufds, 2, 100);
-            if (ret <= 0) {
-                D("poll returned %d\n", ret);
-                // file has closed or we timed out
-                // set ret to 1 so we don't exit the outer loop
-                ret = 1;
-                break;
-            }
-
-            if (ufds[0].revents & POLLIN) {
-                ret = adb_read(fd, buffer + count, sizeof(buffer) - count);
-                D("read fd ret: %d, count: %d\n", ret, count);
-                if (ret > 0)
-                    count += ret;
-                else
-                    break;
-            }
-            if (ufds[1].revents & POLLIN) {
-                ret = adb_read(s, buffer2, sizeof(buffer2));
-                D("read s ret: %d\n", ret);
-                if (ret > 0)
-                    adb_write(fd, buffer2, ret);
-                else
-                    break;
-            }
-
-            if ((ufds[0].revents & POLLHUP) || (ufds[1].revents & POLLHUP)) {
-                // set flag to exit after flushing the buffer
-                ret = -1;
-                break;
-            }
-        }
-
-        D("writing: %d\n", count);
-        if (count > 0) {
-            adb_write(s, buffer, count);
-            count = 0;
-        }
-        if (ret <= 0)
-            break;
-    }
-
-    D("shell_service done\n");
-
-    adb_close(fd);
-    adb_close(s);
-}
-#endif // !ADB_HOST
-
 int service_to_fd(const char *name)
 {
     int ret = -1;
@@ -440,25 +375,22 @@
         ret = create_jdwp_connection_fd(atoi(name+5));
     } else if (!strncmp(name, "log:", 4)) {
         ret = create_service_thread(log_service, get_log_file_path(name + 4));
+#endif
     } else if(!HOST && !strncmp(name, "shell:", 6)) {
-        const char* args[2];
         if(name[6]) {
-            args[0] = "-c";
-            args[1] = name + 6;
+            ret = create_subprocess(SHELL_COMMAND, "-c", name + 6);
         } else {
-            args[0] = "-";
-            args[1] = 0;
+            ret = create_subprocess(SHELL_COMMAND, "-", 0);
         }
-        ret = create_service_thread(shell_service, (void *)args);
+#if !ADB_HOST
     } else if(!strncmp(name, "sync:", 5)) {
         ret = create_service_thread(file_sync_service, NULL);
     } else if(!strncmp(name, "remount:", 8)) {
         ret = create_service_thread(remount_service, NULL);
     } else if(!strncmp(name, "reboot:", 7)) {
-        const char* arg = name + 7;
-        if (*name == 0)
-            arg = NULL;
-        ret = create_service_thread(reboot_service, (void *)arg);
+        void* arg = strdup(name + 7);
+        if(arg == 0) return -1;
+        ret = create_service_thread(reboot_service, arg);
     } else if(!strncmp(name, "root:", 5)) {
         ret = create_service_thread(restart_root_service, NULL);
     } else if(!strncmp(name, "tcpip:", 6)) {
diff --git a/adb/sysdeps.h b/adb/sysdeps.h
index 389fbd2..6372649 100644
--- a/adb/sysdeps.h
+++ b/adb/sysdeps.h
@@ -113,6 +113,7 @@
 extern int  adb_read(int  fd, void* buf, int len);
 extern int  adb_write(int  fd, const void*  buf, int  len);
 extern int  adb_lseek(int  fd, int  pos, int  where);
+extern int  adb_shutdown(int  fd);
 extern int  adb_close(int  fd);
 
 static __inline__ int  unix_close(int fd)
@@ -327,6 +328,13 @@
 #undef   open
 #define  open    ___xxx_open
 
+static __inline__ int  adb_shutdown(int fd)
+{
+    return shutdown(fd, SHUT_RDWR);
+}
+#undef   shutdown
+#define  shutdown   ____xxx_shutdown
+
 static __inline__ int  adb_close(int fd)
 {
     return close(fd);
diff --git a/adb/sysdeps_win32.c b/adb/sysdeps_win32.c
index a8e3bb9..ced91e8 100644
--- a/adb/sysdeps_win32.c
+++ b/adb/sysdeps_win32.c
@@ -435,6 +435,20 @@
 }
 
 
+int  adb_shutdown(int  fd)
+{
+    FH   f = _fh_from_int(fd);
+
+    if (!f) {
+        return -1;
+    }
+
+    D( "adb_shutdown: %s\n", f->name);
+    shutdown( f->fh_socket, SD_BOTH );
+    return 0;
+}
+
+
 int  adb_close(int  fd)
 {
     FH   f = _fh_from_int(fd);
diff --git a/adb/transport.c b/adb/transport.c
index 617dabf..c2877d2 100644
--- a/adb/transport.c
+++ b/adb/transport.c
@@ -864,6 +864,38 @@
     register_transport(t);
 }
 
+#if ADB_HOST
+atransport *find_transport(const char *serial)
+{
+    atransport *t;
+
+    adb_mutex_lock(&transport_lock);
+    for(t = transport_list.next; t != &transport_list; t = t->next) {
+        if (t->serial && !strcmp(serial, t->serial)) {
+            break;
+        }
+     }
+    adb_mutex_unlock(&transport_lock);
+
+    if (t != &transport_list)
+        return t;
+    else
+        return 0;
+}
+
+void unregister_transport(atransport *t)
+{
+    adb_mutex_lock(&transport_lock);
+    t->next->prev = t->prev;
+    t->prev->next = t->next;
+    adb_mutex_unlock(&transport_lock);
+
+    kick_transport(t);
+    transport_unref(t);
+}
+
+#endif
+
 void register_usb_transport(usb_handle *usb, const char *serial, unsigned writeable)
 {
     atransport *t = calloc(1, sizeof(atransport));
diff --git a/adb/transport_local.c b/adb/transport_local.c
index c528d1f..81d120e 100644
--- a/adb/transport_local.c
+++ b/adb/transport_local.c
@@ -204,6 +204,7 @@
 {
     int fd = t->sfd;
     t->sfd = -1;
+    adb_shutdown(fd);
     adb_close(fd);
 
 #if ADB_HOST
diff --git a/adb/usb_libusb.c b/adb/usb_libusb.c
new file mode 100644
index 0000000..8c75266
--- /dev/null
+++ b/adb/usb_libusb.c
@@ -0,0 +1,657 @@
+/* 
+ * Copyright (C) 2009 bsdroid project
+ *               Alexey Tarasov <tarasov@dodologics.com>
+ *   
+ * Copyright (C) 2007 The Android Open Source Project
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <sys/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 "adb.h"
+
+static adb_mutex_t usb_lock = ADB_MUTEX_INITIALIZER;
+static libusb_context *ctx = NULL;
+
+struct usb_handle
+{
+    usb_handle            *prev;
+    usb_handle            *next;
+
+    libusb_device         *dev;
+    libusb_device_handle  *devh;
+    int                   interface;
+    uint8_t               dev_bus;
+    uint8_t               dev_addr;
+	
+    int                   zero_mask;
+    unsigned char         end_point_address[2];
+    char                  serial[128];
+    
+    adb_cond_t            notify;
+    adb_mutex_t           lock;
+};
+
+static struct usb_handle handle_list = {
+        .prev = &handle_list,
+        .next = &handle_list,
+};
+
+void
+usb_cleanup()
+{
+	libusb_exit(ctx);
+}
+
+void
+report_bulk_libusb_error(int r)
+{
+    switch (r) {
+    case LIBUSB_ERROR_TIMEOUT:
+        D("Transfer timeout\n");
+        break;
+
+    case LIBUSB_ERROR_PIPE:
+        D("Control request is not supported\n");
+        break;
+
+    case LIBUSB_ERROR_OVERFLOW:
+        D("Device offered more data\n");
+        break;
+
+    case LIBUSB_ERROR_NO_DEVICE :
+        D("Device was disconnected\n");
+        break;
+
+    default:
+        D("Error %d during transfer\n", r);
+        break;
+    };
+}
+
+static int
+usb_bulk_write(usb_handle *uh, const void *data, int len)
+{
+    int r = 0;
+    int transferred = 0;
+
+    r = libusb_bulk_transfer(uh->devh, uh->end_point_address[1], (void *)data, len,
+                             &transferred, 0);
+   
+    if (r != 0) {
+        D("usb_bulk_write(): ");
+        report_bulk_libusb_error(r);
+        return r;
+    }
+   
+    return (transferred);
+}
+
+static int
+usb_bulk_read(usb_handle *uh, void *data, int len)
+{
+    int r = 0;
+    int transferred = 0;
+
+    r = libusb_bulk_transfer(uh->devh, uh->end_point_address[0], data, len,
+                             &transferred, 0);
+
+    if (r != 0) {
+        D("usb_bulk_read(): ");
+        report_bulk_libusb_error(r);
+        return r;
+    }
+   
+    return (transferred);
+}
+
+int
+usb_write(struct usb_handle *uh, const void *_data, int len)
+{
+    unsigned char *data = (unsigned char*) _data;
+    int n;
+    int need_zero = 0;
+
+    if (uh->zero_mask == 1) {
+        if (!(len & uh->zero_mask)) {
+            need_zero = 1;
+        }
+    }
+
+    D("usb_write(): %p:%d -> transport %p\n", _data, len, uh);
+    
+    while (len > 0) {
+        int xfer = (len > 4096) ? 4096 : len;
+
+        n = usb_bulk_write(uh, data, xfer);
+        
+        if (n != xfer) {
+            D("usb_write(): failed for transport %p (%d bytes left)\n", uh, len);
+            return -1;
+        }
+
+        len -= xfer;
+        data += xfer;
+    }
+
+    if (need_zero){
+        n = usb_bulk_write(uh, _data, 0);
+        
+        if (n < 0) {
+            D("usb_write(): failed to finish operation for transport %p\n", uh);
+        }
+        return n;
+    }
+
+    return 0;
+}
+
+int
+usb_read(struct usb_handle *uh, void *_data, int len)
+{
+    unsigned char *data = (unsigned char*) _data;
+    int n;
+
+    D("usb_read(): %p:%d <- transport %p\n", _data, len, uh);
+    
+    while (len > 0) {
+        int xfer = (len > 4096) ? 4096 : len;
+
+        n = usb_bulk_read(uh, data, xfer);
+        
+        if (n != xfer) {
+            if (n > 0) {
+                data += n;
+                len -= n;
+                continue;
+            }
+            
+            D("usb_read(): failed for transport %p (%d bytes left)\n", uh, len);
+            return -1;
+        }
+
+        len -= xfer;
+        data += xfer;
+    }
+
+    return 0;
+ }
+
+int
+usb_close(struct usb_handle *h)
+{
+    D("usb_close(): closing transport %p\n", h);
+    adb_mutex_lock(&usb_lock);
+    
+    h->next->prev = h->prev;
+    h->prev->next = h->next;
+    h->prev = NULL;
+    h->next = NULL;
+
+    libusb_release_interface(h->devh, h->interface);
+    libusb_close(h->devh);
+    libusb_unref_device(h->dev);
+    
+    adb_mutex_unlock(&usb_lock);
+
+    free(h);
+
+    return (0);
+}
+
+void usb_kick(struct usb_handle *h)
+{
+    D("usb_cick(): kicking transport %p\n", h);
+    
+    adb_mutex_lock(&h->lock);
+    unregister_usb_transport(h);
+    adb_mutex_unlock(&h->lock);
+    
+    h->next->prev = h->prev;
+    h->prev->next = h->next;
+    h->prev = NULL;
+    h->next = NULL;
+
+    libusb_release_interface(h->devh, h->interface);
+    libusb_close(h->devh);
+    libusb_unref_device(h->dev);
+    free(h);
+}
+
+int
+check_usb_interface(libusb_interface *interface,
+                    libusb_device_descriptor *desc,
+                    struct usb_handle *uh)
+{    
+    int e;
+    
+    if (interface->num_altsetting == 0) {
+        D("check_usb_interface(): No interface settings\n");
+        return -1;
+    }
+    
+    libusb_interface_descriptor *idesc = &interface->altsetting[0];
+    
+    if (idesc->bNumEndpoints != 2) {
+        D("check_usb_interface(): Interface have not 2 endpoints, ignoring\n");
+        return -1;
+    }
+
+    for (e = 0; e < idesc->bNumEndpoints; e++) {
+        libusb_endpoint_descriptor *edesc = &idesc->endpoint[e];
+        
+        if (edesc->bmAttributes != LIBUSB_TRANSFER_TYPE_BULK) {
+            D("check_usb_interface(): Endpoint (%u) is not bulk (%u), ignoring\n",
+                    edesc->bmAttributes, LIBUSB_TRANSFER_TYPE_BULK);
+            return -1;
+        }
+        
+        if (edesc->bEndpointAddress & LIBUSB_ENDPOINT_IN)
+            uh->end_point_address[0] = edesc->bEndpointAddress;
+        else
+            uh->end_point_address[1] = edesc->bEndpointAddress;
+        
+            /* aproto 01 needs 0 termination */
+        if (idesc->bInterfaceProtocol == 0x01) {
+            uh->zero_mask = edesc->wMaxPacketSize - 1;
+            D("check_usb_interface(): Forced Android interface protocol v.1\n");
+        }
+    }
+
+    D("check_usb_interface(): Device: %04x:%04x "
+      "iclass: %x, isclass: %x, iproto: %x ep: %x/%x-> ",
+        desc->idVendor, desc->idProduct, idesc->bInterfaceClass,
+	idesc->bInterfaceSubClass, idesc->bInterfaceProtocol,
+	uh->end_point_address[0], uh->end_point_address[1]);
+    
+    if (!is_adb_interface(desc->idVendor, desc->idProduct,
+            idesc->bInterfaceClass, idesc->bInterfaceSubClass,
+            idesc->bInterfaceProtocol))
+    {
+        D("not matches\n");
+        return -1;
+    }
+
+    D("matches\n");
+    return 1;
+}
+
+int
+check_usb_interfaces(libusb_config_descriptor *config,
+                     libusb_device_descriptor *desc, struct usb_handle *uh)
+{  
+    int i;
+    
+    for (i = 0; i < config->bNumInterfaces; ++i) {
+        if (check_usb_interface(&config->interface[i], desc, uh) != -1) {
+            /* found some interface and saved information about it */
+            D("check_usb_interfaces(): Interface %d of %04x:%04x "
+              "matches Android device\n", i, desc->idVendor,
+	      desc->idProduct);
+            
+            return  i;
+        }
+    }
+    
+    return -1;
+}
+
+int
+register_device(struct usb_handle *uh, const char *serial)
+{
+    D("register_device(): Registering %p [%s] as USB transport\n",
+       uh, serial);
+
+    struct usb_handle *usb= NULL;
+
+    usb = calloc(1, sizeof(struct usb_handle));
+    memcpy(usb, uh, sizeof(struct usb_handle));
+    strcpy(usb->serial, uh->serial);
+
+    adb_cond_init(&usb->notify, 0);
+    adb_mutex_init(&usb->lock, 0);
+
+    adb_mutex_lock(&usb_lock);
+    
+    usb->next = &handle_list;
+    usb->prev = handle_list.prev;
+    usb->prev->next = usb;
+    usb->next->prev = usb;
+
+    adb_mutex_unlock(&usb_lock);
+
+    register_usb_transport(usb, serial, 1); 
+
+    return (1);
+}
+
+int
+already_registered(usb_handle *uh)
+{
+    struct usb_handle *usb= NULL;
+    int exists = 0;
+    
+    adb_mutex_lock(&usb_lock);
+
+    for (usb = handle_list.next; usb != &handle_list; usb = usb->next) {
+        if ((usb->dev_bus == uh->dev_bus) &&
+            (usb->dev_addr == uh->dev_addr))
+        {
+            exists = 1;
+            break;
+        }
+    }
+
+    adb_mutex_unlock(&usb_lock);
+
+    return exists;
+}
+
+void
+check_device(libusb_device *dev) 
+{
+    struct usb_handle uh;
+    int i = 0;
+    int found = -1;
+    char serial[256] = {0};
+
+    libusb_device_descriptor desc;
+    libusb_config_descriptor *config = NULL;
+    
+    int r = libusb_get_device_descriptor(dev, &desc);
+
+    if (r != LIBUSB_SUCCESS) {
+        D("check_device(): Failed to get device descriptor\n");
+        return;
+    }
+    
+    if ((desc.idVendor == 0) && (desc.idProduct == 0))
+        return;
+    
+    D("check_device(): Probing usb device %04x:%04x\n",
+        desc.idVendor, desc.idProduct);
+    
+    if (!is_adb_interface (desc.idVendor, desc.idProduct,
+                           ADB_CLASS, ADB_SUBCLASS, ADB_PROTOCOL))
+    {
+        D("check_device(): Ignored due unknown vendor id\n");
+        return;
+    }
+    
+    uh.dev_bus = libusb_get_bus_number(dev);
+    uh.dev_addr = libusb_get_device_address(dev);
+    
+    if (already_registered(&uh)) {
+        D("check_device(): Device (bus: %d, address: %d) "
+          "is already registered\n", uh.dev_bus, uh.dev_addr);
+        return;
+    }
+    
+    D("check_device(): Device bus: %d, address: %d\n",
+        uh.dev_bus, uh.dev_addr);
+
+    r = libusb_get_active_config_descriptor(dev, &config);
+    
+    if (r != 0) {
+        if (r == LIBUSB_ERROR_NOT_FOUND) {
+            D("check_device(): Device %4x:%4x is unconfigured\n", 
+                desc.idVendor, desc.idProduct);
+            return;
+        }
+        
+        D("check_device(): Failed to get configuration for %4x:%4x\n",
+            desc.idVendor, desc.idProduct);
+        return;
+    }
+    
+    if (config == NULL) {
+        D("check_device(): Sanity check failed after "
+          "getting active config\n");
+        return;
+    }
+    
+    if (config->interface != NULL) {
+        found = check_usb_interfaces(config, &desc, &uh);
+    }
+    
+    /* not needed anymore */
+    libusb_free_config_descriptor(config);
+    
+    r = libusb_open(dev, &uh.devh);
+    uh.dev = dev;
+
+    if (r != 0) {
+        switch (r) {
+            case LIBUSB_ERROR_NO_MEM:
+                D("check_device(): Memory allocation problem\n");
+                break;
+                
+            case LIBUSB_ERROR_ACCESS:
+                D("check_device(): Permissions problem, "
+                  "current user priveleges are messed up?\n");
+                break;
+                
+            case LIBUSB_ERROR_NO_DEVICE:
+                D("check_device(): Device disconected, bad cable?\n");
+                break;
+            
+            default:
+                D("check_device(): libusb triggered error %d\n", r);
+        }
+        // skip rest
+        found = -1;
+    }
+    
+    if (found >= 0) {
+        D("check_device(): Device matches Android interface\n");
+        // read the device's serial number
+        memset(serial, 0, sizeof(serial));
+        uh.interface = found;
+        
+        r = libusb_claim_interface(uh.devh, uh.interface);
+        
+        if (r < 0) {
+            D("check_device(): Failed to claim interface %d\n",
+                uh.interface);
+
+            goto fail;
+        }
+
+        if (desc.iSerialNumber) {
+            // reading serial
+            uint16_t    buffer[128] = {0};
+            uint16_t    languages[128] = {0};
+            int languageCount = 0;
+
+            memset(languages, 0, sizeof(languages));
+            r = libusb_control_transfer(uh.devh, 
+                LIBUSB_ENDPOINT_IN |  LIBUSB_REQUEST_TYPE_STANDARD | LIBUSB_RECIPIENT_DEVICE,
+                LIBUSB_REQUEST_GET_DESCRIPTOR, LIBUSB_DT_STRING << 8,
+		0, (uint8_t *)languages, sizeof(languages), 0);
+
+            if (r <= 0) {
+                D("check_device(): Failed to get languages count\n");
+                goto fail;
+            } 
+            
+            languageCount = (r - 2) / 2;
+            
+            for (i = 1; i <= languageCount; ++i) {
+                memset(buffer, 0, sizeof(buffer));
+
+                r = libusb_control_transfer(uh.devh, 
+                    LIBUSB_ENDPOINT_IN |  LIBUSB_REQUEST_TYPE_STANDARD | LIBUSB_RECIPIENT_DEVICE,
+                    LIBUSB_REQUEST_GET_DESCRIPTOR, (LIBUSB_DT_STRING << 8) | desc.iSerialNumber,
+		    languages[i], (uint8_t *)buffer, sizeof(buffer), 0);
+            
+                if (r > 0) { /* converting serial */
+                    int j = 0;
+                    r /= 2;
+                
+                    for (j = 1; j < r; ++j)
+                        serial[j - 1] = buffer[j];
+                
+                    serial[j - 1] = '\0';
+                    break; /* languagesCount cycle */
+                }
+            }
+            
+            if (register_device(&uh, serial) == 0) {
+                D("check_device(): Failed to register device\n");
+                goto fail_interface;
+            }
+            
+            libusb_ref_device(dev);
+        }
+    }
+    
+    return;
+
+fail_interface:
+    libusb_release_interface(uh.devh, uh.interface);
+
+fail:
+    libusb_close(uh.devh);
+    uh.devh = NULL;
+}
+
+int
+check_device_connected(struct usb_handle *uh)
+{
+    int r = libusb_kernel_driver_active(uh->devh, uh->interface);
+    
+    if (r == LIBUSB_ERROR_NO_DEVICE)
+        return 0;
+    
+    if (r < 0)
+        return -1;
+    
+    return 1;
+}
+
+void
+kick_disconnected()
+{
+    struct usb_handle *usb= NULL;
+    
+    adb_mutex_lock(&usb_lock);
+
+    for (usb = handle_list.next; usb != &handle_list; usb = usb->next) {
+        
+        if (check_device_connected(usb) == 0) {
+            D("kick_disconnected(): Transport %p is not online anymore\n",
+                usb);
+
+            usb_kick(usb);
+        }
+    }
+    
+    adb_mutex_unlock(&usb_lock);
+}
+
+void
+scan_usb_devices()
+{
+    D("scan_usb_devices(): started\n");
+    
+    libusb_device **devs= NULL;
+    libusb_device *dev= NULL;
+    ssize_t cnt = libusb_get_device_list(ctx, &devs);
+
+    if (cnt < 0) {
+        D("scan_usb_devices(): Failed to get device list (error: %d)\n",
+            cnt);
+
+        return;
+    }
+    
+    int i = 0;
+
+    while ((dev = devs[i++]) != NULL) {
+        check_device(dev);
+    }
+
+    libusb_free_device_list(devs, 1);
+}
+
+void *
+device_poll_thread(void* unused)
+{
+    D("device_poll_thread(): Created USB scan thread\n");
+    
+    for (;;) {
+        sleep(5);
+        kick_disconnected();
+        scan_usb_devices();
+    }
+
+    /* never reaching this point */
+    return (NULL);
+}
+
+static void
+sigalrm_handler(int signo)
+{
+    /* nothing */
+}
+
+void
+usb_init()
+{
+    D("usb_init(): started\n");
+    adb_thread_t        tid;
+    struct sigaction actions;
+
+    int r = libusb_init(&ctx);
+
+    if (r != LIBUSB_SUCCESS) {
+        err(EX_IOERR, "Failed to init libusb\n");
+    }
+
+    memset(&actions, 0, sizeof(actions));
+    
+    sigemptyset(&actions.sa_mask);
+    
+    actions.sa_flags = 0;
+    actions.sa_handler = sigalrm_handler;
+    
+    sigaction(SIGALRM, &actions, NULL);
+
+	/* initial device scan */
+	scan_usb_devices();
+	
+	/* starting USB event polling thread */
+    if (adb_thread_create(&tid, device_poll_thread, NULL)) {
+            err(EX_IOERR, "cannot create USB scan thread\n");
+    }
+    
+    D("usb_init(): finished\n");
+}
+
diff --git a/adb/usb_vendors.c b/adb/usb_vendors.c
index f8c54d7..5534fd9 100644
--- a/adb/usb_vendors.c
+++ b/adb/usb_vendors.c
@@ -43,6 +43,12 @@
 #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
 
 /** built-in vendor list */
 int builtInVendorIds[] = {
@@ -50,6 +56,9 @@
     VENDOR_ID_HTC,
     VENDOR_ID_SAMSUNG,
     VENDOR_ID_MOTOROLA,
+    VENDOR_ID_LGE,
+    VENDOR_ID_HUAWEI,
+    VENDOR_ID_ACER,
 };
 
 #define BUILT_IN_VENDOR_COUNT    (sizeof(builtInVendorIds)/sizeof(builtInVendorIds[0]))
diff --git a/include/arch/linux-sh/AndroidConfig.h b/include/arch/linux-sh/AndroidConfig.h
new file mode 100644
index 0000000..4af39d9
--- /dev/null
+++ b/include/arch/linux-sh/AndroidConfig.h
@@ -0,0 +1,327 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * Android config -- "android-sh".  Used for SuperH device builds.
+ */
+#ifndef _ANDROID_CONFIG_H
+#define _ANDROID_CONFIG_H
+
+/*
+ * ===========================================================================
+ *                              !!! IMPORTANT !!!
+ * ===========================================================================
+ *
+ * This file is included by ALL C/C++ source files.  Don't put anything in
+ * here unless you are absolutely certain it can't go anywhere else.
+ *
+ * Any C++ stuff must be wrapped with "#ifdef __cplusplus".  Do not use "//"
+ * comments.
+ */
+
+/*
+ * Threading model.  Choose one:
+ *
+ * HAVE_PTHREADS - use the pthreads library.
+ * HAVE_WIN32_THREADS - use Win32 thread primitives.
+ *  -- combine HAVE_CREATETHREAD, HAVE_CREATEMUTEX, and HAVE__BEGINTHREADEX
+ */
+#define HAVE_PTHREADS
+
+/*
+ * Do we have the futex syscall?
+ */
+
+#define HAVE_FUTEX
+
+/*
+ * Define if we already have the futex wrapper functions defined. Yes if
+ * compiling against bionic.
+ */
+#define HAVE_FUTEX_WRAPPERS 1
+
+/*
+ * Process creation model.  Choose one:
+ *
+ * HAVE_FORKEXEC - use fork() and exec()
+ * HAVE_WIN32_PROC - use CreateProcess()
+ */
+#define HAVE_FORKEXEC
+
+/*
+ * Process out-of-memory adjustment.  Set if running on Linux,
+ * where we can write to /proc/<pid>/oom_adj to modify the out-of-memory
+ * badness adjustment.
+ */
+#define HAVE_OOM_ADJ
+
+/*
+ * IPC model.  Choose one:
+ *
+ * HAVE_SYSV_IPC - use the classic SysV IPC mechanisms (semget, shmget).
+ * HAVE_MACOSX_IPC - use Macintosh IPC mechanisms (sem_open, mmap).
+ * HAVE_WIN32_IPC - use Win32 IPC (CreateSemaphore, CreateFileMapping).
+ * HAVE_ANDROID_IPC - use Android versions (?, mmap).
+ */
+#define HAVE_ANDROID_IPC
+
+/*
+ * Memory-mapping model. Choose one:
+ *
+ * HAVE_POSIX_FILEMAP - use the Posix sys/mmap.h
+ * HAVE_WIN32_FILEMAP - use Win32 filemaps
+ */
+#define  HAVE_POSIX_FILEMAP
+
+/*
+ * Define this if you have <termio.h>
+ */
+#define  HAVE_TERMIO_H
+
+/*
+ * Define this if you build against MSVCRT.DLL
+ */
+/* #define HAVE_MS_C_RUNTIME */
+
+/*
+ * Define this if you have sys/uio.h
+ */
+#define  HAVE_SYS_UIO_H
+
+/*
+ * Define this if your platforms implements symbolic links
+ * in its filesystems
+ */
+#define HAVE_SYMLINKS
+
+/*
+ * Define this if we have localtime_r().
+ */
+/* #define HAVE_LOCALTIME_R */
+
+/*
+ * Define this if we have gethostbyname_r().
+ */
+/* #define HAVE_GETHOSTBYNAME_R */
+
+/*
+ * Define this if we have ioctl().
+ */
+#define HAVE_IOCTL
+
+/*
+ * Define this if we want to use WinSock.
+ */
+/* #define HAVE_WINSOCK */
+
+/*
+ * Define this if have clock_gettime() and friends
+ */
+#define HAVE_POSIX_CLOCKS
+
+/*
+ * Define this if we have pthread_cond_timedwait_monotonic() and
+ * clock_gettime(CLOCK_MONOTONIC).
+ */
+/* #define HAVE_TIMEDWAIT_MONOTONIC */
+
+/*
+ * Define this if we have linux style epoll()
+ */
+#define HAVE_EPOLL
+
+/*
+ * Endianness of the target machine.  Choose one:
+ *
+ * HAVE_ENDIAN_H -- have endian.h header we can include.
+ * HAVE_LITTLE_ENDIAN -- we are little endian.
+ * HAVE_BIG_ENDIAN -- we are big endian.
+ */
+#define HAVE_ENDIAN_H
+#define HAVE_LITTLE_ENDIAN
+
+/*
+ * We need to choose between 32-bit and 64-bit off_t.  All of our code should
+ * agree on the same size.  For desktop systems, use 64-bit values,
+ * because some of our libraries (e.g. wxWidgets) expect to be built that way.
+ */
+/* #define _FILE_OFFSET_BITS 64 */
+/* #define _LARGEFILE_SOURCE 1 */
+
+/*
+ * Defined if we have the backtrace() call for retrieving a stack trace.
+ * Needed for CallStack to operate; if not defined, CallStack is
+ * non-functional.
+ */
+#define HAVE_BACKTRACE 0
+
+/*
+ * Defined if we have the dladdr() call for retrieving the symbol associated
+ * with a memory address.  If not defined, stack crawls will not have symbolic
+ * information.
+ */
+#define HAVE_DLADDR 0
+
+/*
+ * Defined if we have the cxxabi.h header for demangling C++ symbols.  If
+ * not defined, stack crawls will be displayed with raw mangled symbols
+ */
+#define HAVE_CXXABI 0
+
+/*
+ * Defined if we have the gettid() system call.
+ */
+#define HAVE_GETTID
+
+/*
+ * Defined if we have the sched_setscheduler() call
+ */
+#define HAVE_SCHED_SETSCHEDULER
+
+/*
+ * Add any extra platform-specific defines here.
+ */
+/* #define __linux__ */ /* for SuperH */
+
+/*
+ * Define if we have <malloc.h> header
+ */
+#define HAVE_MALLOC_H
+
+/*
+ * Define if we're running on *our* linux on device or emulator.
+ */
+#define HAVE_ANDROID_OS 1
+
+/*
+ * Define if we have Linux-style non-filesystem Unix Domain Sockets
+ */
+#define HAVE_LINUX_LOCAL_SOCKET_NAMESPACE 1
+
+/*
+ * Define if we have Linux's inotify in <sys/inotify.h>.
+ */
+#define HAVE_INOTIFY 1
+
+/*
+ * Define if we have madvise() in <sys/mman.h>
+ */
+#define HAVE_MADVISE 1
+
+/*
+ * Define if tm struct has tm_gmtoff field
+ */
+#define HAVE_TM_GMTOFF 1
+
+/*
+ * Define if dirent struct has d_type field
+ */
+#define HAVE_DIRENT_D_TYPE 1
+
+/*
+ * Define if libc includes Android system properties implementation.
+ */
+#define HAVE_LIBC_SYSTEM_PROPERTIES 1
+
+/*
+ * Define if system provides a system property server (should be
+ * mutually exclusive with HAVE_LIBC_SYSTEM_PROPERTIES).
+ */
+/* #define HAVE_SYSTEM_PROPERTY_SERVER */
+
+/*
+ * What CPU architecture does this platform use?
+ */
+#define ARCH_SH
+
+/*
+ * Define if the size of enums is as short as possible,
+ */
+/* #define HAVE_SHORT_ENUMS */
+
+/*
+ * sprintf() format string for shared library naming.
+ */
+#define OS_SHARED_LIB_FORMAT_STR    "lib%s.so"
+
+/*
+ * Do we have __memcmp16()?
+ *
+ * TODO : Investigate the perfomance impact of __memcmp16()
+ *        and implement it.
+ *        This influences on dalvikVM's string performance.
+ *        See dalvik/vm/InlineNative.c.
+ */
+/* #define HAVE__MEMCMP16 */
+
+/*
+ * type for the third argument to mincore().
+ */
+#define MINCORE_POINTER_TYPE unsigned char *
+
+/*
+ * Do we have the sigaction flag SA_NOCLDWAIT?
+ */
+#define HAVE_SA_NOCLDWAIT
+
+/*
+ * The default path separator for the platform
+ */
+#define OS_PATH_SEPARATOR '/'
+
+/*
+ * Is the filesystem case sensitive?
+ */
+#define OS_CASE_SENSITIVE
+
+/*
+ * Define if <sys/socket.h> exists.
+ */
+#define HAVE_SYS_SOCKET_H 1
+
+/*
+ * Define if the strlcpy() function exists on the system.
+ */
+#define HAVE_STRLCPY 1
+
+/*
+ * Define if prctl() exists
+ */
+#define HAVE_PRCTL 1
+
+/*
+ * Define if writev() exists
+ */
+#define HAVE_WRITEV 1
+
+/*
+ * For dalvik/libcore
+ */
+#define CANT_PASS_VALIST_AS_CHARPTR
+
+/*
+ * For external/bluez/utils/tools/hciattach.c
+ * TODO : This definition should be somewhere in bionic/libc/kernel/(*).
+ *        Cosider the place and move it there.
+ */
+#define N_TTY 0
+
+/*
+ * Whether or not _Unwind_Context is defined as a struct.
+ */
+#define HAVE_UNWIND_CONTEXT_STRUCT
+
+#endif /* _ANDROID_CONFIG_H */
diff --git a/include/sysutils/NetlinkListener.h b/include/sysutils/NetlinkListener.h
index 6dcc005..2880046 100644
--- a/include/sysutils/NetlinkListener.h
+++ b/include/sysutils/NetlinkListener.h
@@ -26,7 +26,9 @@
 public:
     NetlinkListener(int socket);
     virtual ~NetlinkListener() {}
+
 protected:
     virtual bool onDataAvailable(SocketClient *cli);
+    virtual void onEvent(NetlinkEvent *evt) = 0;
 };
 #endif
diff --git a/init/devices.c b/init/devices.c
index 606a074..c5f681f 100644
--- a/init/devices.c
+++ b/init/devices.c
@@ -114,6 +114,7 @@
     { "/dev/pmem_camera",   0660,   AID_SYSTEM,     AID_CAMERA,     1 },
     { "/dev/oncrpc/",       0660,   AID_ROOT,       AID_SYSTEM,     1 },
     { "/dev/adsp/",         0660,   AID_SYSTEM,     AID_AUDIO,      1 },
+    { "/dev/snd/",          0660,   AID_SYSTEM,     AID_AUDIO,      1 },
     { "/dev/mt9t013",       0660,   AID_SYSTEM,     AID_SYSTEM,     0 },
     { "/dev/msm_camera/",   0660,   AID_SYSTEM,     AID_SYSTEM,     1 },
     { "/dev/akm8976_daemon",0640,   AID_COMPASS,    AID_SYSTEM,     0 },
diff --git a/libcutils/Android.mk b/libcutils/Android.mk
index 98e59ee..30f4a49 100644
--- a/libcutils/Android.mk
+++ b/libcutils/Android.mk
@@ -98,7 +98,11 @@
 ifeq ($(TARGET_ARCH),arm)
 LOCAL_SRC_FILES += memset32.S atomic-android-arm.S
 else  # !arm
+ifeq ($(TARGET_ARCH),sh)
+LOCAL_SRC_FILES += memory.c atomic-android-sh.c
+else  # !sh
 LOCAL_SRC_FILES += memory.c
+endif # !sh
 endif # !arm
 
 LOCAL_C_INCLUDES := $(KERNEL_HEADERS)
diff --git a/libcutils/atomic-android-arm.S b/libcutils/atomic-android-arm.S
index c56ec5d..9a24976 100644
--- a/libcutils/atomic-android-arm.S
+++ b/libcutils/atomic-android-arm.S
@@ -17,8 +17,7 @@
 #include <machine/cpu-features.h>
 
 /*
- * NOTE: these atomic operations are SMP safe on all architectures, 
- * except swap(), see below.
+ * NOTE: these atomic operations are SMP safe on all architectures. 
  */
 
 	.text
@@ -228,11 +227,18 @@
  * output: r0 = old value
  */
 
-/* FIXME: this is not safe on SMP systems 
- * a general way to do it is to use kernel_cmpxchg */
-
+/* replaced swp instruction with ldrex/strex for ARMv6 & ARMv7 */
 android_atomic_swap:
+#if defined (_ARM_HAVE_LDREX_STREX)
+1:  ldrex   r2, [r1]
+    strex   r3, r0, [r1]
+    teq     r3, #0
+    bne     1b
+    mov     r0, r2
+    mcr     p15, 0, r0, c7, c10, 5 /* or, use dmb */
+#else
     swp     r0, r0, [r1]
+#endif
     bx      lr
 
 /*
diff --git a/libcutils/atomic-android-sh.c b/libcutils/atomic-android-sh.c
new file mode 100644
index 0000000..acbea97
--- /dev/null
+++ b/libcutils/atomic-android-sh.c
@@ -0,0 +1,159 @@
+/*
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <cutils/atomic.h>
+#ifdef HAVE_WIN32_THREADS
+#include <windows.h>
+#else
+#include <sched.h>
+#endif
+
+/*
+ * Note :
+ *
+ * (1) SuperH does not have CMPXCHG.  It has only TAS for atomic
+ *     operations.  It does not seem a good idea to implement CMPXCHG,
+ *     with TAS.  So, we choose to implemnt these operations with
+ *     posix mutexes.  Please be sure that this might cause performance
+ *     problem for Android-SH. Using LL/SC instructions supported in SH-X3,
+ *     best performnace would be realized.
+ *
+ * (2) Mutex initialization problem happens, which is commented for
+ *     ARM implementation, in this file above.
+ *     We follow the fact that the initializer for mutex is a simple zero
+ *     value.
+ */
+
+#include <pthread.h>
+
+#define  SWAP_LOCK_COUNT  32U
+static pthread_mutex_t  _swap_locks[SWAP_LOCK_COUNT];
+
+#define  SWAP_LOCK(addr)   \
+   &_swap_locks[((unsigned)(void*)(addr) >> 3U) % SWAP_LOCK_COUNT]
+
+
+void android_atomic_write(int32_t value, volatile int32_t* addr) {
+    int32_t oldValue;
+    do {
+        oldValue = *addr;
+    } while (android_atomic_cmpxchg(oldValue, value, addr));
+}
+
+int32_t android_atomic_inc(volatile int32_t* addr) {
+    int32_t oldValue;
+    do {
+        oldValue = *addr;
+    } while (android_atomic_cmpxchg(oldValue, oldValue+1, addr));
+    return oldValue;
+}
+
+int32_t android_atomic_dec(volatile int32_t* addr) {
+    int32_t oldValue;
+    do {
+        oldValue = *addr;
+    } while (android_atomic_cmpxchg(oldValue, oldValue-1, addr));
+    return oldValue;
+}
+
+int32_t android_atomic_add(int32_t value, volatile int32_t* addr) {
+    int32_t oldValue;
+    do {
+        oldValue = *addr;
+    } while (android_atomic_cmpxchg(oldValue, oldValue+value, addr));
+    return oldValue;
+}
+
+int32_t android_atomic_and(int32_t value, volatile int32_t* addr) {
+    int32_t oldValue;
+    do {
+        oldValue = *addr;
+    } while (android_atomic_cmpxchg(oldValue, oldValue&value, addr));
+    return oldValue;
+}
+
+int32_t android_atomic_or(int32_t value, volatile int32_t* addr) {
+    int32_t oldValue;
+    do {
+        oldValue = *addr;
+    } while (android_atomic_cmpxchg(oldValue, oldValue|value, addr));
+    return oldValue;
+}
+
+int32_t android_atomic_swap(int32_t value, volatile int32_t* addr) {
+    int32_t oldValue;
+    do {
+        oldValue = *addr;
+    } while (android_atomic_cmpxchg(oldValue, value, addr));
+    return oldValue;
+}
+
+int android_atomic_cmpxchg(int32_t oldvalue, int32_t newvalue,
+                           volatile int32_t* addr) {
+    int result;
+    pthread_mutex_t*  lock = SWAP_LOCK(addr);
+
+    pthread_mutex_lock(lock);
+
+    if (*addr == oldvalue) {
+        *addr  = newvalue;
+        result = 0;
+    } else {
+        result = 1;
+    }
+    pthread_mutex_unlock(lock);
+    return result;
+}
+
+int64_t android_quasiatomic_swap_64(int64_t value, volatile int64_t* addr) {
+    int64_t oldValue;
+    pthread_mutex_t*  lock = SWAP_LOCK(addr);
+
+    pthread_mutex_lock(lock);
+
+    oldValue = *addr;
+    *addr    = value;
+
+    pthread_mutex_unlock(lock);
+    return oldValue;
+}
+
+int android_quasiatomic_cmpxchg_64(int64_t oldvalue, int64_t newvalue,
+        volatile int64_t* addr) {
+    int result;
+    pthread_mutex_t*  lock = SWAP_LOCK(addr);
+
+    pthread_mutex_lock(lock);
+
+    if (*addr == oldvalue) {
+        *addr  = newvalue;
+        result = 0;
+    } else {
+        result = 1;
+    }
+    pthread_mutex_unlock(lock);
+    return result;
+}
+
+int64_t android_quasiatomic_read_64(volatile int64_t* addr) {
+    int64_t result;
+    pthread_mutex_t*  lock = SWAP_LOCK(addr);
+
+    pthread_mutex_lock(lock);
+    result = *addr;
+    pthread_mutex_unlock(lock);
+    return result;
+}
diff --git a/libcutils/atomic.c b/libcutils/atomic.c
index 65d7af0..41faaa2 100644
--- a/libcutils/atomic.c
+++ b/libcutils/atomic.c
@@ -245,6 +245,10 @@
     return result;
 }    
 
+/*****************************************************************************/
+#elif __sh__
+// implementation for SuperH is in atomic-android-sh.c.
+
 #else
 
 #error "Unsupported atomic operations for this platform"
diff --git a/libsysutils/src/NetlinkEvent.cpp b/libsysutils/src/NetlinkEvent.cpp
index 5573c3f..5f959a7 100644
--- a/libsysutils/src/NetlinkEvent.cpp
+++ b/libsysutils/src/NetlinkEvent.cpp
@@ -28,6 +28,9 @@
 
 NetlinkEvent::NetlinkEvent() {
     mAction = NlActionUnknown;
+    memset(mParams, 0, sizeof(mParams));
+    mPath = NULL;
+    mSubsystem = NULL;
 }
 
 NetlinkEvent::~NetlinkEvent() {
diff --git a/libsysutils/src/NetlinkListener.cpp b/libsysutils/src/NetlinkListener.cpp
index 3ec9d9d..5586dcc 100644
--- a/libsysutils/src/NetlinkListener.cpp
+++ b/libsysutils/src/NetlinkListener.cpp
@@ -32,8 +32,6 @@
 bool NetlinkListener::onDataAvailable(SocketClient *cli)
 {
     int socket = cli->getSocket();
-    LOGD("NetlinkListener::onDataAvailable()");
-
     int count;
 
     if ((count = recv(socket, mBuffer, sizeof(mBuffer), 0)) < 0) {
@@ -47,8 +45,7 @@
         goto out;
     }
 
-    LOGD("Ignoring '%s' netlink event", evt->getSubsystem());
-
+    onEvent(evt);
 out:
     delete evt;
     return true;
diff --git a/logcat/Android.mk b/logcat/Android.mk
index f9fd2c9..5a9f12d 100644
--- a/logcat/Android.mk
+++ b/logcat/Android.mk
@@ -21,5 +21,6 @@
 LOCAL_MODULE_CLASS := ETC
 
 LOCAL_SRC_FILES := $(LOCAL_MODULE)
+LOCAL_PREBUILT_STRIP_COMMENTS := 1
 
 include $(BUILD_PREBUILT)
diff --git a/rootdir/init.rc b/rootdir/init.rc
index aa0ef59..9d30518 100644
--- a/rootdir/init.rc
+++ b/rootdir/init.rc
@@ -51,7 +51,8 @@
     mkdir /dev/cpuctl/bg_non_interactive
     chown system system /dev/cpuctl/bg_non_interactive/tasks
     chmod 0777 /dev/cpuctl/bg_non_interactive/tasks
-    write /dev/cpuctl/bg_non_interactive/cpu.shares 16
+    # 5.0 %
+    write /dev/cpuctl/bg_non_interactive/cpu.shares 52
 
 # mount mtd partitions
     # Mount /system rw first to give the filesystem a chance to save a checkpoint