使用adb devices命令,可以轻松获取到所有连接到PC的adb设备的serial值。
但是adb命令无法获取adb usb设备的vendor id和product id。
本程序根据adb协议,遍历usb设备,使用ioctrl获取serial和vid,pid,这样可以将serial和vid pid匹配起来。
Windows版本的实现可以根据adb_api.h实现,但是有一个问题,adb的服务会独占adb设备,如果adb服务正在运行,那么,这个实现是无法兑现功能的。
谁有好的办法,欢迎共享。Linux平台则无此限制。
下面提供Linux平台的实现,Windows的实现,因为受限于adb服务独占设备,就不贴出来了,谁有兴趣的,可以问我要代码。
具体Linux实现参见代码:
1 #include <cstdio> 2 #include <cstdlib> 3 #include <cstring> 4 5 #include <unistd.h> 6 #include <sys/ioctl.h> 7 #include <sys/types.h> 8 #include <sys/stat.h> 9 #include <sys/time.h> 10 #include <dirent.h> 11 #include <fcntl.h> 12 #include <errno.h> 13 #include <ctype.h> 14 15 #include <linux/usbdevice_fs.h> 16 #include <linux/version.h> 17 #if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 20) 18 #include <linux/usb/ch9.h> 19 #else 20 #include <linux/usb_ch9.h> 21 #endif 22 #include <asm/byteorder.h> 23 24 #define ADB_CLASS 0xff 25 #define ADB_SUBCLASS 0x42 26 #define ADB_PROTOCOL 0x1 27 28 #include <string> 29 #include <vector> 30 31 typedef struct tag_devpath { 32 int serial_index; 33 std::string adb_dev_path; 34 }ADB_DEV; 35 36 std::vector<ADB_DEV> va; 37 38 inline int badname(const char *name) 39 { 40 while(*name) { 41 if(!isdigit(*name++)) return 1; 42 } 43 return 0; 44 } 45 46 int is_adb_interface(int usb_class, int usb_subclass, int usb_protocol) 47 { 48 if (usb_class == ADB_CLASS && usb_subclass == ADB_SUBCLASS && 49 usb_protocol == ADB_PROTOCOL) { 50 return 1; 51 } 52 53 return 0; 54 } 55 56 int get_serial() 57 { 58 for(int i = 0; i < va.size(); ++i) 59 { 60 int fd = open(va[i].adb_dev_path.c_str(), O_RDWR); 61 if(fd > 0) 62 { 63 char serial[256]; 64 int n = 256; 65 int serial_index = va[i].serial_index; 66 serial[0] = 0; 67 memset(serial, 0, n); 68 if (serial_index) { 69 struct usbdevfs_ctrltransfer ctrl; 70 __u16 buffer[128]; 71 __u16 languages[128]; 72 int i, result; 73 int languageCount = 0; 74 75 memset(languages, 0, sizeof(languages)); 76 memset(&ctrl, 0, sizeof(ctrl)); 77 78 // read list of supported languages 79 ctrl.bRequestType = USB_DIR_IN|USB_TYPE_STANDARD|USB_RECIP_DEVICE; 80 ctrl.bRequest = USB_REQ_GET_DESCRIPTOR; 81 ctrl.wValue = (USB_DT_STRING << 8) | 0; 82 ctrl.wIndex = 0; 83 ctrl.wLength = sizeof(languages); 84 ctrl.data = languages; 85 ctrl.timeout = 1000; 86 87 result = ioctl(fd, USBDEVFS_CONTROL, &ctrl); 88 if (result > 0) 89 languageCount = (result - 2) / 2; 90 else if(result < 0) 91 printf("ioctl failed: %s\n", strerror(errno)); 92 93 printf("languageCount = %d\n", languageCount); 94 for (i = 1; i <= languageCount; i++) { 95 memset(buffer, 0, sizeof(buffer)); 96 memset(&ctrl, 0, sizeof(ctrl)); 97 98 ctrl.bRequestType = USB_DIR_IN|USB_TYPE_STANDARD|USB_RECIP_DEVICE; 99 ctrl.bRequest = USB_REQ_GET_DESCRIPTOR; 100 ctrl.wValue = (USB_DT_STRING << 8) | serial_index; 101 ctrl.wIndex = __le16_to_cpu(languages[i]); 102 ctrl.wLength = sizeof(buffer); 103 ctrl.data = buffer; 104 ctrl.timeout = 1000; 105 106 result = ioctl(fd, USBDEVFS_CONTROL, &ctrl); 107 if (result > 0) { 108 int i; 109 // skip first word, and copy the rest to the serial string, changing shorts to bytes. 110 result /= 2; 111 for (i = 1; i < result; i++) 112 serial[i - 1] = __le16_to_cpu(buffer[i]); 113 serial[i - 1] = 0; 114 printf("serial: %s\n", serial); 115 break; 116 } 117 else if(result < 0) 118 { 119 printf("ioctl failed: %s\n", strerror(errno)); 120 } 121 } 122 } 123 } 124 else 125 { 126 printf("open %s failed: %s", va[i].adb_dev_path.c_str(), strerror(errno)); 127 } 128 } 129 130 return 0; 131 } 132 133 void find_usb_device(void) 134 { 135 const char* base = "/dev/bus/usb"; 136 char busname[32], devname[32]; 137 DIR *busdir , *devdir ; 138 struct dirent *de; 139 int fd ; 140 141 busdir = opendir(base); 142 if(busdir == 0) return; 143 144 va.clear(); 145 146 while((de = readdir(busdir)) != 0) { 147 if(badname(de->d_name)) continue; 148 149 snprintf(busname, sizeof busname, "%s/%s", base, de->d_name); 150 devdir = opendir(busname); 151 if(devdir == 0) continue; 152 153 while((de = readdir(devdir))) { 154 unsigned char devdesc[4096]; 155 unsigned char* bufptr = devdesc; 156 unsigned char* bufend; 157 struct usb_device_descriptor* device; 158 struct usb_config_descriptor* config; 159 struct usb_interface_descriptor* interface; 160 struct usb_endpoint_descriptor *ep1, *ep2; 161 unsigned zero_mask = 0; 162 unsigned vid, pid; 163 size_t desclength; 164 165 if(badname(de->d_name)) continue; 166 snprintf(devname, sizeof devname, "%s/%s", busname, de->d_name); 167 168 if((fd = open(devname, O_RDONLY)) < 0) { 169 continue; 170 } 171 172 desclength = read(fd, devdesc, sizeof(devdesc)); 173 bufend = bufptr + desclength; 174 175 // should have device and configuration descriptors, and atleast two endpoints 176 if (desclength < USB_DT_DEVICE_SIZE + USB_DT_CONFIG_SIZE) { 177 close(fd); 178 continue; 179 } 180 181 device = (struct usb_device_descriptor*)bufptr; 182 bufptr += USB_DT_DEVICE_SIZE; 183 184 if((device->bLength != USB_DT_DEVICE_SIZE) || (device->bDescriptorType != USB_DT_DEVICE)) { 185 close(fd); 186 continue; 187 } 188 189 vid = device->idVendor; 190 pid = device->idProduct; 191 192 config = (struct usb_config_descriptor *)bufptr; 193 bufptr += USB_DT_CONFIG_SIZE; 194 if (config->bLength != USB_DT_CONFIG_SIZE || config->bDescriptorType != USB_DT_CONFIG) { 195 close(fd); 196 continue; 197 } 198 199 // loop through all the descriptors and look for the ADB interface 200 while (bufptr < bufend) { 201 unsigned char length = bufptr[0]; 202 unsigned char type = bufptr[1]; 203 204 if (type == USB_DT_INTERFACE) { 205 interface = (struct usb_interface_descriptor *)bufptr; 206 bufptr += length; 207 208 if (length != USB_DT_INTERFACE_SIZE) { 209 break; 210 } 211 212 if (is_adb_interface(interface->bInterfaceClass, 213 interface->bInterfaceSubClass, interface->bInterfaceProtocol)) { 214 215 ADB_DEV ad; 216 ad.serial_index = device->iSerialNumber; 217 ad.adb_dev_path = devname; 218 va.push_back(ad); 219 220 //get devname vendor_id product_id 221 printf("get:\ndevname = %s\nidVendor=0x%x idProduct=0x%x\n", 222 devname, vid, pid); 223 224 break; 225 } 226 } else { 227 bufptr += length; 228 } 229 } // end of while 230 231 close(fd); 232 } // end of devdir while 233 closedir(devdir); 234 } //end of busdir while 235 closedir(busdir); 236 } 237 238 int main(void) 239 { 240 find_usb_device(); 241 for(int i = 0; i < va.size(); ++i) 242 { 243 printf("dev:%s ===> serial index: %d\n", va[i].adb_dev_path.c_str(), va[i].serial_index); 244 } 245 246 get_serial(); 247 248 return 0; 249 }