使用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 ;
  42. }
  43. return ;
  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 ;
  51. }
  52.  
  53. return ;
  54. }
  55.  
  56. int get_serial()
  57. {
  58. for(int i = ; i < va.size(); ++i)
  59. {
  60. int fd = open(va[i].adb_dev_path.c_str(), O_RDWR);
  61. if(fd > )
  62. {
  63. char serial[];
  64. int n = ;
  65. int serial_index = va[i].serial_index;
  66. serial[] = ;
  67. memset(serial, , n);
  68. if (serial_index) {
  69. struct usbdevfs_ctrltransfer ctrl;
  70. __u16 buffer[];
  71. __u16 languages[];
  72. int i, result;
  73. int languageCount = ;
  74.  
  75. memset(languages, , sizeof(languages));
  76. memset(&ctrl, , 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 << ) | ;
  82. ctrl.wIndex = ;
  83. ctrl.wLength = sizeof(languages);
  84. ctrl.data = languages;
  85. ctrl.timeout = ;
  86.  
  87. result = ioctl(fd, USBDEVFS_CONTROL, &ctrl);
  88. if (result > )
  89. languageCount = (result - ) / ;
  90. else if(result < )
  91. printf("ioctl failed: %s\n", strerror(errno));
  92.  
  93. printf("languageCount = %d\n", languageCount);
  94. for (i = ; i <= languageCount; i++) {
  95. memset(buffer, , sizeof(buffer));
  96. memset(&ctrl, , 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 << ) | serial_index;
  101. ctrl.wIndex = __le16_to_cpu(languages[i]);
  102. ctrl.wLength = sizeof(buffer);
  103. ctrl.data = buffer;
  104. ctrl.timeout = ;
  105.  
  106. result = ioctl(fd, USBDEVFS_CONTROL, &ctrl);
  107. if (result > ) {
  108. int i;
  109. // skip first word, and copy the rest to the serial string, changing shorts to bytes.
  110. result /= ;
  111. for (i = ; i < result; i++)
  112. serial[i - ] = __le16_to_cpu(buffer[i]);
  113. serial[i - ] = ;
  114. printf("serial: %s\n", serial);
  115. break;
  116. }
  117. else if(result < )
  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 ;
  131. }
  132.  
  133. void find_usb_device(void)
  134. {
  135. const char* base = "/dev/bus/usb";
  136. char busname[], devname[];
  137. DIR *busdir , *devdir ;
  138. struct dirent *de;
  139. int fd ;
  140.  
  141. busdir = opendir(base);
  142. if(busdir == ) return;
  143.  
  144. va.clear();
  145.  
  146. while((de = readdir(busdir)) != ) {
  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 == ) continue;
  152.  
  153. while((de = readdir(devdir))) {
  154. unsigned char devdesc[];
  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 = ;
  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)) < ) {
  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[];
  202. unsigned char type = bufptr[];
  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 = ; 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 ;
  249. }

adb设备,根据serial获取vid pid的更多相关文章

  1. USB VID PID 查询

    USB VID PID 查询:http://www.linux-usb.org/usb.ids 说明: USB设备中有VID何PID,分别表示此USB设备是哪个厂商的哪种设备. 一个USB的VID对应 ...

  2. adb 设备命令

    一.adb 设备命令1.查看机型时,可以使用以下命令$ adb shell getprop ro.product.model 2.如果我们忘记具体系统属性的名字$ adb shell getprop ...

  3. Bash Shell 获取进程 PID

    转载地址:http://weyo.me/pages/techs/linux-get-pid/ 导读 Linux 的交互式 Shell 与 Shell 脚本存在一定的差异,主要是由于后者存在一个独立的运 ...

  4. linux命令(26):Bash Shell 获取进程 PID

    转载地址:http://weyo.me/pages/techs/linux-get-pid/ 根据pid,kill该进程:http://www.cnblogs.com/lovychen/p/54113 ...

  5. Python 使用标准库根据进程名获取进程PID

    应用场景 在进行 Linux 运维的环境中,我们经常会遇到维护同一台服务器上的多个程序,涉及到程序的启动.关闭和重启操作. 通常这些程序之间存在着相互依存的关系需要进行依次的启动关闭操作. 下面介绍几 ...

  6. [TimLinux] Linux shell获取进程pid

    调用脚本时,获取进程PID: (/this/is/a/script/file.sh > /out/to/log.txt & echo $!) & 脚本内部,获取进程PID: ec ...

  7. 014-交互式Shell和shell脚本获取进程 pid

    Linux 的交互式 Shell 与 Shell 脚本存在一定的差异,主要是由于后者存在一个独立的运行进程 1.交互式 Bash Shell 获取进程 pid 在已知进程名(name)的前提下,交互式 ...

  8. Ubuntu及Windows ADB设备no permissions的解决方案

    不少人曾在Windows下及Ubuntu下都遇到过Android设备无法识别的情况,就是run as Android Application的时候,target显示"??????" ...

  9. android唯一设备标识、设备号、设备ID的获取方法

    ##如何获取Android设备唯一ID? ###问题 每一个android设备都有唯一ID吗?如果有?怎么用java最简单取得呢? ###回答1(最佳) 如何取得android唯一码? 好处: 1.不 ...

随机推荐

  1. Qt 线程基础(Thread Basics的翻译,线程的五种使用情况)

    Qt 线程基础(QThread.QtConcurrent等) 转载自:http://blog.csdn.net/dbzhang800/article/details/6554104 昨晚看Qt的Man ...

  2. python之json学习

    1. 从python原始类型向json类型的转换过程,具体的转换如下: import json json.dump(obj, fp, skipkeys=False,ensure_ascii=True, ...

  3. jquery_EasyUI的学习

    1 Accordion(可折叠标签) 1.1 实例 1.1.1 代码 <html> <head> <meta http-equiv="Content-Type& ...

  4. cocos2d-x创建的九宫图变白块

    用UIImageView 创建的九宫图变白,直接用CCScale9Sprite创建的也是变白,找了半天原来是自己为了调整UI方便,开启了CCSprite边缘画线导致的,在ccConfig.h下 宏CC ...

  5. android 25 跨进程启动activity

    跨进程启动activity,启动系统预定义的activity就是跨进程的. client项目启动server项目的activity. clientActivity.java package com.s ...

  6. iOS-iPad开发之popoverController使用介绍

    iOS-iPad开发之popoverController使用介绍 iOS开发UI篇-popoverController使用注意 iOS SDK:自定义Popover(弹出窗口) 实现的简单例子: // ...

  7. java中调用js脚本

    JDK1.6加入了对Script(JSR223)的支持.这是一个脚本框架,提供了让脚本语言来访问Java内部的方法.你可以在运行的时候找到脚本引擎,然后调用这个引擎去执行脚本.这个脚本API允许你为脚 ...

  8. MySQL存储过程学习笔记

    MySQL在5.0以前并不支持存储过程,这使得MySQL在应用上大打折扣.MySQL 5.0终于开始支持存储过程了. MySQL的关键字大小写通用.该学习笔记对关键字使用大写:变量名,表名使用小写. ...

  9. PHP 通过随机数获得ASCII 值返回字符。

    for($i=0;$i<20;$i++){ $Matrix .= chr(65 + rand(0,26)); }

  10. 【转】Windows环境下.NET 操作Oracle问题

    目前,Windows操作系统可以分成两类,32位和64位(64位也区分x86_64位和Itanium ),同时Oracle客户端也做了同样的区分. 在安装和开发的过程中,经常会遇到一些问题,本文就总结 ...