前几天发帖讨论自动化测试中 adb 掉线的解决方法,大家在下面回复了一些软件解决方案。
本着折腾精神,这几天收集了一些软件方案,现总结下,方便碰到同样问题的小伙伴参考。
设备实例路径查看办法:win+r 打开运行窗口 ——> 输入 devmgmt.msc 打开设备管理器 ——> 选择你的设备双击 ——> 切换到属性 tab 页 ——> 在属性下拉框选择设备实例路径
# coding:utf-8
import os
import fcntl
import subprocess
USBDEVFS_RESET = ord('U') << (4 * 2) | 20
def get_adb_usb_devices():
lines = os.popen('lsusb').readlines()
target_lines = []
for line in lines:
if 'MediaTek' in line or 'Spreadtrum' in line or 'Qualcomm' in line:
target_lines.append(line)
adb_usb_devices = []
for line in target_lines:
parts = line.split()
# print parts
bus = parts[1]
dev = parts[3][:3]
adb_usb_devices.append('/dev/bus/usb/%s/%s' % (bus, dev))
return adb_usb_devices
def send_reset(adb_device_path):
fd = os.open(adb_device_path, os.O_WRONLY)
print fd
try:
ret = fcntl.ioctl(fd, USBDEVFS_RESET, 0)
finally:
os.close(fd)
if ret < 0:
return False
else:
return True
def main():
# 请求root权限
if (os.getuid() != 0):
exe = subprocess.Popen(['sudo', 'python', __file__])
exe.wait()
exit(1)
# 打印信息
print '-' * 75
print 'Usage : USB device Reset Tool for android QCom|Sprd|MTK device'
print 'Coder : Wanyor'
print '-' * 75
adb_usb_devices = get_adb_usb_devices()
print 'usb:', adb_usb_devices
for adb_device_path in adb_usb_devices:
if (send_reset(adb_device_path)):
print 'Reset {0} Success!'.format(adb_device_path)
else:
print 'Reset {0} Fail!'.format(adb_device_path)
if __name__ == '__main__':
main()
usbreset.c
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <sys/ioctl.h>
#include <linux/usbdevice_fs.h>
int main(int argc, char **argv)
{
const char *filename;
int fd;
int rc;
if (argc != 2) {
fprintf(stderr, "Usage: usbreset device-filename\n");
return 1;
}
filename = argv[1];
fd = open(filename, O_WRONLY);
if (fd < 0) {
perror("Error opening output file");
return 1;
}
printf("Resetting USB device %s\n", filename);
rc = ioctl(fd, USBDEVFS_RESET, 0);
if (rc < 0) {
perror("Error in ioctl");
return 1;
}
printf("Reset successful\n");
close(fd);
return 0;
}
然后用 gcc usbreset.c -o usbreset 编译下,sudo chmod a+x usbreset 给 cli 程序执行权限即可运行,参数为设备的挂载路径(例如:/dev/bus/usb/002/007)
设备挂载路径查看办法:lsusb 即可查看
usbreset.c
#include <stdio.h>
#include <stdlib.h>
#include <libusb-1.0/libusb.h>
//compile: gcc usbreset.c -o usbreset -lusb-1.0
//usage: ./usbreset 2 6
//use lsusb to check out the bus number and device number
struct libusb_device_handle *devh;
struct libusb_device *dev;
struct libusb_device **devs;
void resetUSB() {
int success;
int bpoint = 0;
do {
success = libusb_reset_device(devh);
if ((bpoint % 10) == 0) {
printf(".");
}
++bpoint;
if (bpoint > 100) {
success = 1;
}
} while (success < 0);
if (success) {
printf("nreset usb device failed:%dn", success);
} else {
printf("nreset usb device okn");
}
}
struct libusb_device* search_device(int _busNum, int _devNum) {
libusb_device *l_dev;
int i = 0;
int l_busNum, l_devNum;
while ((l_dev = devs[i++]) != NULL) {
printf("check against %d devicen", i);
l_busNum =(int) libusb_get_bus_number(l_dev);
l_devNum =(int) libusb_get_device_address(l_dev);
printf("bus number: %d; device number: %dn", l_busNum, l_devNum);
if ((l_busNum == _busNum) && (l_devNum == _devNum)) {
printf("found devicen");
return l_dev;
}
}
return NULL;
}
int main(int argc, char **argv) {
//parse the input parameters to get the bus number and device number
int l_busNum, l_devNum;
int l_ret;
printf("program started!n");
if (argc < 3) {
printf("not enough arguments!n");
printf("usage: ./usbreset <bus number> <dev number>n");
return 0;
}
printf("bus number: %sn", argv[1]);
printf("dev number: %sn", argv[2]);
l_busNum = atoi(argv[1]);
l_devNum = atoi(argv[2]);
printf("bus number: %d; dev number: %dn", l_busNum, l_devNum);
l_ret = libusb_init(NULL);
if (l_ret < 0) {
return l_ret;
}
l_ret = libusb_get_device_list(NULL, &devs);
if (l_ret < 0) {
return (int) l_ret;
}
dev = search_device(l_busNum, l_devNum);
if (dev == NULL) {
printf("device not foundn");
return 0;
}
l_ret = libusb_open(dev, &devh);
if (l_ret == 0) {
printf("got the usb handle successfully.n");
} else {
printf("error getting usb handle.n");
}
//reset the usb device
resetUSB();
//free the device list
libusb_free_device_list(devs, 1);
libusb_exit(NULL);
return 0;
}
使用 gcc usbreset.c -o usbreset -lusb-1.0 编译下,sudo chmod a+x usbreset 给 cli 程序执行权限即可运行,参数为设备的 bus id 和 device id
跨平台方案也可以使用 python 的 libusb 的 cython 封装写,各位小伙伴可自由尝试。
汇报完毕...