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;
+}