adb设备,根据serial获取vid pid

时间:2024-02-29 12:32:08

使用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 }