草帽路飞UU 发表于 2017-6-29 09:14:06

解决自动化测试设备掉线:软件方案

本着折腾精神,这几天收集了一些软件方案,现总结下,方便碰到同样问题的小伙伴参考。
windows软件解决方案
[*]命令行实现:

[*]参考:> http://digital.ni.com/public.nsf/allkb/1D120A90884C25AF862573A700602459
[*]原理:使用devcon工具,重启设备
[*]代码: devcon restart *设备实例路径*
设备实例路径查看办法:win+r打开运行窗口 ——> 输入devmgmt.msc打开设备管理器 ——> 选择你的设备双击 ——> 切换到属性tab页 ——> 在属性下拉框选择设备实例路径
https://testerhome.com/uploads/photo/2017/d89bab6f-d24a-4aeb-bf0b-74e02ac5cc69.png%21large
linux/ubuntu软件解决方案
[*]python代码实现:

[*]原理:ioctl
[*]代码:
# 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
      dev = parts[: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()
[*]c语言编写cli程序实现:

[*]原理:ioctl
[*]代码:
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;
    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即可查看
跨平台解决方案
[*]libusb库实现:

[*]原理:libusb自带usb_reset函数,写个c代码调用下就可以了
[*]代码:
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
//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) != 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);
    printf("dev number: %sn", argv);

    l_busNum = atoi(argv);
    l_devNum = atoi(argv);
    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封装写,各位小伙伴可自由尝试。
汇报完毕,硬件方案正在买元件,画pcb,找时间再更..

乐哈哈yoyo 发表于 2017-6-29 09:49:35


我认为adb掉线的原因是电源供电不足,这是其一,后面我在STF官网上面看到他们的分析另一个原因是usb3.0驱动与adb间的问题,只要选择使用usb2.0的usb-hub就可以了。已经通过实践证明,双管齐下后usb都很正常。

八戒你干嘛 发表于 2017-6-29 09:50:22

乐哈哈yoyo 发表于 2017-6-29 09:49
我认为adb掉线的原因是电源供电不足,这是其一,后面我在STF官网上面看到他们的分析另一个原因是usb3.0驱 ...

嗯,见解很到位!

八戒你干嘛 发表于 2017-6-29 09:50:27

乐哈哈yoyo 发表于 2017-6-29 09:49
我认为adb掉线的原因是电源供电不足,这是其一,后面我在STF官网上面看到他们的分析另一个原因是usb3.0驱 ...

嗯,见解很到位!
页: [1]
查看完整版本: 解决自动化测试设备掉线:软件方案