kdbg.c

来自「Android 一些工具」· C语言 代码 · 共 475 行

C
475
字号
/* * 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...)#endifstruct 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;}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?