通过 libusb 与 USB 设备通信的蛮力方法

Posted

技术标签:

【中文标题】通过 libusb 与 USB 设备通信的蛮力方法【英文标题】:Brute force method to communicate with USB device via libusb 【发布时间】:2013-12-11 03:16:12 【问题描述】:

我有一个 USB 设备(6 个灯:2 个红外灯、2 个白灯、2 个 LED),我无法使用 windows 驱动程序(我也不喜欢 windows),所以我想尝试通过 C 控制它和 libusb(请参阅下面的脚本,我从 here 获得)。是否有一种蛮力方式(或更好的程序)来找出它所期望的信号?基本上循环一些值并在我观察灯是否打开时发送这些值?

control_lights.cpp:

#include <iostream>
#include <libusb-1.0/libusb.h>

using namespace std;

#define VENDOR_ID 1133
#define PRODUCT_ID 2449

int main() 
   libusb_device **devs; //pointer to pointer of device, used to retrieve a list of devices
   libusb_device_handle *dev_handle; //a device handle
   libusb_context *ctx = NULL; //a libusb session
   int r; //for return values
   ssize_t cnt; //holding number of devices in list
   r = libusb_init(&ctx); //initialize the library for the session we just declared
   if(r < 0) 
      cout<<"Init Error "<<r<<endl; //there was an error
      return 1;
   
   libusb_set_debug(ctx, 3); //set verbosity level to 3, as suggested in the documentation

   cnt = libusb_get_device_list(ctx, &devs); //get the list of devices
   if(cnt < 0) 
      cout<<"Get Device Error"<<endl; //there was an error
      return 1;
   
   cout<<cnt<<" Devices in list."<<endl;

   dev_handle = libusb_open_device_with_vid_pid(ctx, VENDOR_ID, PRODUCT_ID ); //these are vendorID and productID I found for my usb device
   if(dev_handle == NULL)
      cout<<"Cannot open device"<<endl;
   else
      cout<<"Device Opened"<<endl;
   libusb_free_device_list(devs, 1); //free the list, unref the devices in it

   unsigned char *data = new unsigned char[4]; //data to write
   data[0]='a';data[1]='b';data[2]='c';data[3]='d'; //some dummy values

   int actual; //used to find out how many bytes were written
   if(libusb_kernel_driver_active(dev_handle, 0) == 1)  //find out if kernel driver is attached
      cout<<"Kernel Driver Active"<<endl;
      if(libusb_detach_kernel_driver(dev_handle, 0) == 0) //detach it
         cout<<"Kernel Driver Detached!"<<endl;
   
   r = libusb_claim_interface(dev_handle, 0); //claim interface 0 (the first) of device (mine had jsut 1)
   if(r < 0) 
      cout<<"Cannot Claim Interface"<<endl;
      return 1;
   
   cout<<"Claimed Interface"<<endl;

   cout<<"Data->"<<data<<"<-"<<endl; //just to see the data we want to write : abcd
   cout<<"Writing Data..."<<endl;
   r = libusb_bulk_transfer(dev_handle, (2 | LIBUSB_ENDPOINT_OUT), data, 4, &actual, 0); //my device's out endpoint was 2, found with trial- the device had 2 endpoints: 2 and 129
   if(r == 0 && actual == 4) //we wrote the 4 bytes successfully
      cout<<"Writing Successful!"<<endl;
   else
      cout<<"Write Error"<<endl;

   r = libusb_release_interface(dev_handle, 0); //release the claimed interface
   if(r!=0) 
      cout<<"Cannot Release Interface"<<endl;
      return 1;
   
   cout<<"Released Interface"<<endl;

   libusb_close(dev_handle); //close the device we opened
   libusb_exit(ctx); //needs to be called to end the

   delete[] data; //delete the allocated memory for data
   return 0;

编辑:我觉得这些信息会很有用。我查到usb设备的名字是什么,稍加编辑后,这是lsusb -v的相关内容:

Bus 002 Device 007: ID 03eb:f003 Atmel Corp. 
Device Descriptor:
  bLength                18
  bDescriptorType         1
  bcdUSB               2.00
  bDeviceClass            0 (Defined at Interface level)
  bDeviceSubClass         0 
  bDeviceProtocol         0 
  bMaxPacketSize0        32
  idVendor           0x03eb Atmel Corp.
  idProduct          0xf003 
  bcdDevice            1.03
  iManufacturer           1 REMOVED www.REMOVED.com powered by Atmel
  iProduct                2 SSS-Cube Document Reader 500mW UV
  iSerial                 3 290720080x
  bNumConfigurations      1
  Configuration Descriptor:
    bLength                 9
    bDescriptorType         2
    wTotalLength           41
    bNumInterfaces          1
    bConfigurationValue     1
    iConfiguration          0 
    bmAttributes         0x80
      (Bus Powered)
    MaxPower              500mA
    Interface Descriptor:
      bLength                 9
      bDescriptorType         4
      bInterfaceNumber        0
      bAlternateSetting       0
      bNumEndpoints           2
      bInterfaceClass         3 Human Interface Device
      bInterfaceSubClass      0 No Subclass
      bInterfaceProtocol      0 None
      iInterface              0 
        HID Device Descriptor:
          bLength                 9
          bDescriptorType        33
          bcdHID               1.11
          bCountryCode            8 French
          bNumDescriptors         1
          bDescriptorType        34 Report
          wDescriptorLength      53
         Report Descriptors: 
           ** UNAVAILABLE **
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x81  EP 1 IN
        bmAttributes            3
          Transfer Type            Interrupt
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0008  1x 8 bytes
        bInterval              20
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x02  EP 2 OUT
        bmAttributes            3
          Transfer Type            Interrupt
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0008  1x 8 bytes
        bInterval              20
Device Status:     0x0000
  (Bus Powered)

【问题讨论】:

【参考方案1】:

libusb_bulk_transfer(...)

您有一个 HID 设备,它没有批量端点。您可能需要控制传输或中断传输,可能两者都需要。

如果您非常幸运,HID 报告桌面(很遗憾,lsusb 没有显示给您)可能包含足够的信息来推断如何为这些端点格式化数据。

【讨论】:

什么是“HID 报告描述符”以及它与 libusb_bulk_transfer(...) 的关系如何 USB 是一个相当复杂的协议。答案会写满一本书——所以我建议买一本读一读。 我原来的问题的答案,还是我上面的评论?

以上是关于通过 libusb 与 USB 设备通信的蛮力方法的主要内容,如果未能解决你的问题,请参考以下文章

libusb简介

libusb 未列出的 USB/IP 仿真设备

在 Android 上使用 libusb 而不生根

Windows下Qt+libusb PC程序与斑马打印机使用USB通信

USB开发——内核USB驱动+libusb开发方法

linux / libusb 获取usb设备路径