无法通过libusb传输数据

时间:2015-04-03 08:27:58

标签: linux usb endpoint data-transfer libusb

我正在尝试运行此程序以使用libusb发送数据。我无法找到USB端口的端点。 libusb_bulk_transfer函数中需要此参数。

#include <iostream>
#include <libusb.h>

using namespace std;

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, 5118, 7424); //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;
}

以下是我的主机PC上接收数据的程序。

#include<stdio.h>
#include<unistd.h>
#include<string.h>
#include <sys/stat.h>
#include <fcntl.h>
void main()
{

read_port();
//return 0;
}


read_port(void)
{
    int fd = open("/dev/ttyACM0", O_RDONLY | O_NOCTTY);
    if (fd == -1)
    {
    /* Could not open the port. */
    perror("open_port: Unable to open /dev/ttyACM0) - ");
    }

    char buffer[32];
    for(;;)
   {
    int n = read(fd, buffer, sizeof(buffer));
   if (n < 0)
      fputs("read failed!\n", stderr);
   printf("\n %d", n);
  }
}

请帮忙。 提前谢谢。

1 个答案:

答案 0 :(得分:1)

在回答您的实际问题时,如果您想知道设备附带了哪些实际端点,lsusb就是您的朋友

如果您不确定设备的供应商和设备ID是什么,请输入:

lsusb

你会得到这样的东西:

Bus 001 Device 005: ID 093a:2510 Pixart Imaging, Inc. Optical Mouse
Bus 001 Device 015: ID 413c:2003 Dell Computer Corp. Keyboard
Bus 001 Device 020: ID 0483:3748 STMicroelectronics ST-LINK/V2
Bus 001 Device 002: ID 8087:0020 Intel Corp. Integrated Rate Matching Hub
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub

假设我们想知道ST-LINK / V2上有哪些端点,我们使用-v选项在详细模式下使用lsusb,并使用-d选项仅指定我们感兴趣的设备ID:

lsusb -v -d 0483:3748

我们将从中获得一个很大的字段列表。拓扑大致是:

device->configuration->interface->endpoints
      |                interface->endpoints
      |                interface->endpoints
      |
      ->configuration->interface->endpoints
                       interface->endpoints
                       ...

所以找到你想要使用的界面(通常是0):

  • 找到接口描述符

  • 封装在其中的
  • 可以看到端点描述符

  • 然后查找术语bEndpointAddress以获取实际值

在这种情况下,我们在端点中有一个批量地址为0x81:

bEndpointAddress     0x81  EP 1 IN

还有一点下来:

bEndpointAddress     0x02  EP 2 OUT

另一个在端点:

bEndpointAddress     0x83  EP 3 IN

为了完整性,这里是完整转储:

总线001设备020:ID 0483:3748 STMicroelectronics ST-LINK / V2

Device Descriptor:
  bLength                18
  bDescriptorType         1
  bcdUSB               2.00
  bDeviceClass            0 (Defined at Interface level)
  bDeviceSubClass         0 
  bDeviceProtocol         0 
  bMaxPacketSize0        64
  idVendor           0x0483 STMicroelectronics
  idProduct          0x3748 ST-LINK/V2
  bcdDevice            1.00
  iManufacturer           1 STMicroelectronics
  iProduct                2 STM32 STLink
  iSerial                 3 000000000001
  bNumConfigurations      1
    Configuration Descriptor:
      bLength                 9
      bDescriptorType         2
      wTotalLength           39
      bNumInterfaces          1
      bConfigurationValue     1
      iConfiguration          0 
      bmAttributes         0x80
      (Bus Powered)
      MaxPower              100mA
        Interface Descriptor:
           bLength                 9
           bDescriptorType         4
           bInterfaceNumber        0
           bAlternateSetting       0
           bNumEndpoints           3
           bInterfaceClass       255 Vendor Specific Class
           bInterfaceSubClass    255 Vendor Specific Subclass
           bInterfaceProtocol    255 Vendor Specific Protocol
           iInterface              4 ST Link
             Endpoint Descriptor:
                bLength                 7
                bDescriptorType         5
                bEndpointAddress     0x81  EP 1 IN   *!eg end point address!*
                bmAttributes            2
                Transfer Type            Bulk
                Synch Type               None
                Usage Type               Data
                wMaxPacketSize     0x0040  1x 64 bytes
                bInterval               0
             Endpoint Descriptor:
                bLength                 7
                bDescriptorType         5
                bEndpointAddress     0x02  EP 2 OUT
                bmAttributes            2
                Transfer Type            Bulk
                Synch Type               None
                Usage Type               Data
                wMaxPacketSize     0x0040  1x 64 bytes
                bInterval               0
             Endpoint Descriptor:
                bLength                 7
                bDescriptorType         5
                bEndpointAddress     0x83  EP 3 IN
                bmAttributes            2
                Transfer Type            Bulk
                Synch Type               None
                Usage Type               Data
                wMaxPacketSize     0x0040  1x 64 bytes
                bInterval               0
  Device Status:     0x0000

(巴士供电)