Initial Contribution
diff --git a/adb/kdbg.c b/adb/kdbg.c
new file mode 100644
index 0000000..60de53c
--- /dev/null
+++ b/adb/kdbg.c
@@ -0,0 +1,474 @@
+/*
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define _GNU_SOURCE
+#include <stdio.h>
+
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+
+#include <sys/ioctl.h>
+#include <sys/types.h>
+#include <dirent.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <pthread.h>
+#include <ctype.h>
+
+#include <linux/usbdevice_fs.h>
+#include <linux/version.h>
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 20)
+#include <linux/usb/ch9.h>
+#else
+#include <linux/usb_ch9.h>
+#endif
+#include <asm/byteorder.h>
+
+#include <cutils/fdevent.h>
+#include "adb.h"
+
+
+#define TRACE_USB 0
+
+#if TRACE_USB
+#define DBG1(x...) fprintf(stderr, x)
+#define DBG(x...) fprintf(stderr, x)
+#else
+#define DBG(x...)
+#define DBG1(x...)
+#endif
+
+struct usb_handle
+{
+    struct usb_handle *next;
+    char fname[32];
+    int desc;
+    unsigned char ep_in;
+    unsigned char ep_out;
+    unsigned int interface;
+};
+
+static struct usb_handle *g_first_usb_device;
+static struct usb_handle *g_last_usb_device;
+
+static void new_device(char *dev_name, unsigned char ep_in, unsigned char ep_out, unsigned int interface)
+{
+    struct usb_handle* usb;
+
+    DBG("New device being added %s \n", dev_name);
+
+    usb = (struct usb_handle *)calloc(1, sizeof(struct usb_handle));
+    strcpy(usb->fname, dev_name);
+    usb->ep_in = ep_in;
+    usb->ep_out = ep_out;
+    usb->interface = interface;
+    usb->next = NULL;
+    if(g_last_usb_device)
+        g_last_usb_device->next = usb;
+    else
+        g_first_usb_device = usb;
+    g_last_usb_device = usb;
+}
+
+
+static inline int badname(const char *name)
+{
+    if(!isdigit(name[0])) return 1;
+    if(!isdigit(name[1])) return 1;
+    if(!isdigit(name[2])) return 1;
+    if(name[3] != 0) return 1;
+    return 0;
+}
+
+static int find_usb_devices(const char *base, unsigned vendor, unsigned product1, unsigned product2,
+                            unsigned ifclass, unsigned ifsubclass,
+                            unsigned ifprotocol, unsigned numendpoints)
+{
+    char busname[32], devname[32];
+    unsigned char local_ep_in, local_ep_out;
+    DIR *busdir , *devdir ;
+    struct dirent *de;
+    int fd ;
+    int ret_val = -1;
+    int found_device = 0;
+
+    busdir = opendir(base);
+    if(busdir == 0) return 0;
+
+    while((de = readdir(busdir)) != 0) {
+        if(badname(de->d_name)) continue;
+
+        snprintf(busname, sizeof busname, "%s/%s", base, de->d_name);
+        devdir = opendir(busname);
+        if(devdir == 0) continue;
+
+        DBG("[ scanning %s ]\n", busname);
+        while((de = readdir(devdir))) {
+            if(badname(de->d_name)) continue;
+            snprintf(devname, sizeof devname, "%s/%s", busname, de->d_name);
+
+            DBG("[ scanning %s ]\n", devname);
+            fd = open(devname, O_RDWR);
+            if(fd < 0) {
+                continue;
+            } else {
+                unsigned char devdesc[256];
+                unsigned char* bufptr = devdesc;
+                struct usb_device_descriptor* device;
+                struct usb_config_descriptor* config;
+                struct usb_interface_descriptor* interface;
+                struct usb_endpoint_descriptor *ep1, *ep2;
+                unsigned vid, pid;
+                int i, interfaces;
+
+                size_t desclength = read(fd, devdesc, sizeof(devdesc));
+
+                // should have device and configuration descriptors, and atleast two endpoints
+                if (desclength < USB_DT_DEVICE_SIZE + USB_DT_CONFIG_SIZE) {
+                    DBG("desclength %d is too small\n", desclength);
+                    close(fd);
+                    continue;
+                }
+
+                device = (struct usb_device_descriptor*)bufptr;
+                bufptr += USB_DT_DEVICE_SIZE;
+                if(device->bLength == USB_DT_DEVICE_SIZE && device->bDescriptorType == USB_DT_DEVICE) {
+                    vid = __le16_to_cpu(device->idVendor);
+                    pid = __le16_to_cpu(device->idProduct);
+                    pid = devdesc[10] | (devdesc[11] << 8);
+                    DBG("[ %s is V:%04x P:%04x ]\n", devname, vid, pid);
+                    if((vendor == vid) && (product1 == pid || product2 == pid)){
+
+                       // should have config descriptor next
+                       config = (struct usb_config_descriptor *)bufptr;
+                       bufptr += USB_DT_CONFIG_SIZE;
+                       if (config->bLength != USB_DT_CONFIG_SIZE || config->bDescriptorType != USB_DT_CONFIG) {
+                            DBG("usb_config_descriptor not found\n");
+                            close(fd);
+                            continue;
+                           }
+
+                           // loop through all the interfaces and look for the ADB interface
+                           interfaces = config->bNumInterfaces;
+                           for (i = 0; i < interfaces; i++) {
+                              if (bufptr + USB_DT_ENDPOINT_SIZE > devdesc + desclength)
+                                 break;
+
+                              interface = (struct usb_interface_descriptor *)bufptr;
+                              bufptr += USB_DT_INTERFACE_SIZE;
+                              if (interface->bLength != USB_DT_INTERFACE_SIZE ||
+                              interface->bDescriptorType != USB_DT_INTERFACE) {
+                              DBG("usb_interface_descriptor not found\n");
+                                  break;
+                              }
+
+                          DBG("bInterfaceClass: %d,  bInterfaceSubClass: %d,\
+                              bInterfaceProtocol: %d, bNumEndpoints: %d\n",
+                              interface->bInterfaceClass, interface->bInterfaceSubClass,
+                              interface->bInterfaceProtocol, interface->bNumEndpoints);
+                          // Sooner bootloader has zero for bInterfaceClass, while adb has USB_CLASS_CDC_DATA
+                              if (interface->bInterfaceClass == ifclass &&
+                                   interface->bInterfaceSubClass == ifsubclass &&
+                                   interface->bInterfaceProtocol == ifprotocol &&
+                                   interface->bNumEndpoints == numendpoints) {
+
+                                   DBG("looking for bulk endpoints\n");
+                                   // looks like ADB...
+                                   ep1 = (struct usb_endpoint_descriptor *)bufptr;
+                                   bufptr += USB_DT_ENDPOINT_SIZE;
+                                   ep2 = (struct usb_endpoint_descriptor *)bufptr;
+                                   bufptr += USB_DT_ENDPOINT_SIZE;
+
+                                   if (bufptr > devdesc + desclength ||
+                                       ep1->bLength != USB_DT_ENDPOINT_SIZE ||
+                                       ep1->bDescriptorType != USB_DT_ENDPOINT ||
+                                       ep2->bLength != USB_DT_ENDPOINT_SIZE ||
+                                       ep2->bDescriptorType != USB_DT_ENDPOINT) {
+                                       DBG("endpoints not found\n");
+                                       break;
+                                  }
+
+                                  // both endpoints should be bulk
+                                  if (ep1->bmAttributes != USB_ENDPOINT_XFER_BULK ||
+                                     ep2->bmAttributes != USB_ENDPOINT_XFER_BULK) {
+                                      DBG("bulk endpoints not found\n");
+                                      continue;
+                                  }
+
+                                  // we have a match.  now we just need to figure out which is in and which is out.
+                                  if (ep1->bEndpointAddress & USB_ENDPOINT_DIR_MASK) {
+                                      local_ep_in = ep1->bEndpointAddress;
+                                      local_ep_out = ep2->bEndpointAddress;
+                                  } else {
+                                      local_ep_in = ep2->bEndpointAddress;
+                                      local_ep_out = ep1->bEndpointAddress;
+                                  }
+
+                                  new_device(devname, local_ep_in, local_ep_out, i);
+                                  found_device = 1;
+                                  close(fd);
+                              } else {
+                                  // skip to next interface
+                                  bufptr += (interface->bNumEndpoints * USB_DT_ENDPOINT_SIZE);
+                              }
+                          } // end of for
+                    } //end of productid if
+                }
+                close(fd);
+            } // end of if
+        } // end of devdir while
+        closedir(devdir);
+    } //end of busdir while
+    closedir(busdir);
+
+    return found_device;
+}
+
+
+static void find_devices(unsigned vendor, unsigned product1, unsigned product2)
+{
+    // don't scan /proc/bus/usb if we find something in /dev/bus/usb, to avoid duplication of devices.
+    if (!find_usb_devices("/dev/bus/usb", vendor, product1, product2, USB_CLASS_VENDOR_SPEC, 1, 0, 2)) {
+        find_usb_devices("/proc/bus/usb", vendor, product1, product2, USB_CLASS_VENDOR_SPEC, 1, 0, 2);
+    }
+}
+
+void usb_open_device(struct usb_handle *h)
+{
+    int n = 0;
+
+    h->desc = open(h->fname, O_RDWR);
+    //DBG("[ usb open %s fd = %d]\n", h->fname, h->desc);
+    n = ioctl(h->desc, USBDEVFS_CLAIMINTERFACE, &h->interface);
+    if(n != 0) goto fail;
+//    t->usb_is_open = 1;
+    return;
+
+
+fail:
+    DBG("[ usb open %s error=%d, err_str = %s]\n",
+                h->fname,  errno, strerror(errno));
+    if(h->desc >= 0) {
+        close(h->desc);
+        h->desc = -1;
+    }
+//    t->usb_is_open = 0;
+}
+
+int usb_write(struct usb_handle *h, const void *_data, int len)
+{
+    unsigned char *data = (unsigned char*) _data;
+    struct usbdevfs_bulktransfer bulk;
+    int n;
+
+    while(len >= 0) {
+        int xfer = (len > 4096) ? 4096 : len;
+
+        bulk.ep = h->ep_out;
+        bulk.len = xfer;
+        bulk.data = data;
+        bulk.timeout = 500 + xfer * 8;
+
+        bulk.timeout *= 10;
+
+        n = ioctl(h->desc, USBDEVFS_BULK, &bulk);
+        if(n != xfer) {
+            DBG("ERROR: n = %d, errno = %d (%s)\n",
+                n, errno, strerror(errno));
+            return -1;
+        }
+        if(len == 0)
+            break;
+
+        len -= xfer;
+        data += xfer;
+        if(len == 0)
+            break;
+    }
+
+    return 0;
+}
+
+int usb_read(struct usb_handle *h, void *_data, int len)
+{
+    unsigned char *data_start = (unsigned char*) _data;
+    unsigned char *data = (unsigned char*) _data;
+    struct usbdevfs_bulktransfer bulk;
+    int n;
+
+    while(len > 0) {
+        int xfer = (len > 4096) ? 4096 : len;
+
+        bulk.ep = h->ep_in;
+        bulk.len = xfer;
+        bulk.data = data;
+
+            // adjust timeout based on the data we're transferring,
+            // otherwise the timeout interrupts us partway through
+            // and we get out of sync...
+        bulk.timeout = 500 + xfer * 8;
+
+        bulk.timeout = 500 + xfer / 128;
+
+//        bulk.timeout *= 10;
+        DBG1("[ usb read %d fd = %d], fname=%s\n", xfer, h->desc, h->fname);
+        n = ioctl(h->desc, USBDEVFS_BULK, &bulk);
+        DBG1("[ usb read %d ] = %d, fname=%s\n", xfer, n, h->fname);
+        if(n < 0) {
+            if((errno == ETIMEDOUT) && (h->desc != -1)) {
+                DBG("[ timeout ]\n");
+                if(n > 0){
+                    data += n;
+                    len -= n;
+                }
+                continue;
+            }
+            DBG1("ERROR: n = %d, errno = %d (%s)\n",
+                n, errno, strerror(errno));
+            return -1;
+        }
+
+        len -= n;
+        data += n;
+        if(n != xfer)
+            break;
+    }
+
+    return data - data_start;
+}
+
+void usb_kick(struct usb_handle *h)
+{
+    close(h->desc);
+    h->desc = -1;
+}
+
+int usb_close(struct usb_handle *h)
+{
+    close(h->desc);
+    h->desc = -1;
+    return 0;
+}
+
+void list_devices()
+{
+    int i = 0;
+    struct usb_handle *h = g_first_usb_device;
+    while(h) {
+        printf("%d: %s\n", i, h->fname);
+        i++;
+        h = h->next;
+    }
+}
+
+int main(int argc, char **argv)
+{
+    char buffer[4096/*-64*/];
+    int len;
+    int c;
+    char *arg;
+    int device_index = 0;
+    struct usb_handle *h;
+    int i;
+
+    find_devices(VENDOR_ID_GOOGLE, PRODUCT_ID_SOONER, PRODUCT_ID_SOONER_COMP);
+    while(1) {
+        c = getopt(argc, argv, "d:l");
+        if (c == EOF)
+            break;
+        switch(c) {
+            case 'd':
+                device_index = strtol(optarg, NULL, 0);
+                break;
+            case 'l':
+                list_devices();
+                return 0;
+            case '?':
+                fprintf(stderr, "%s: invalid option -%c\n",
+                        argv[0], optopt);
+                return 1;
+        }
+    }
+
+    argc -= optind - 1;
+    argv += optind - 1;
+
+    h = g_first_usb_device;
+    i = device_index;
+    while(i-- > 0 && h) {
+        h = h->next;
+    }
+    if(h == NULL) {
+        fprintf(stderr, "no device %d\n", device_index);
+        return 1;
+    }
+
+    usb_open_device(h);
+    if(g_first_usb_device->desc < 0) {
+        fprintf(stderr, "could not open device (%s), %s\n", h->fname, strerror(errno));
+        return 1;
+    }
+    len = 0;
+    if(argc == 1) {
+        char *line = NULL;
+        size_t line_size = 0;
+        while((len = getline(&line, &line_size, stdin)) >= 0) {
+            //if(len > 0 && line[len - 1] == '\n')
+            //  len--;
+            usb_write(h, line, len);
+            while(1) {
+                len = usb_read(h, buffer, sizeof(buffer));
+                if(len < 0)
+                    break;
+                write(STDOUT_FILENO, buffer, len);
+                if(len < (int)sizeof(buffer))
+                    break;
+            }
+        }
+        return 0;
+    }
+    while(argc > 1) {
+        argc--;
+        argv++;
+        arg = *argv;
+        while(arg) {
+            if(*arg)
+                buffer[len++] = *arg++;
+            else {
+                arg = NULL;
+                if(argc > 1)
+                    buffer[len++] = ' ';
+                else
+                    break;
+            }
+            if(len == sizeof(buffer)) {
+                usb_write(h, buffer, len);
+                len = 0;
+            }
+        }
+    }
+    usb_write(h, buffer, len);
+    while(1) {
+        len = usb_read(h, buffer, sizeof(buffer));
+        if(len < 0)
+            break;
+        write(STDOUT_FILENO, buffer, len);
+        if(len < (int)sizeof(buffer))
+            break;
+    }
+    return 0;
+}