0


libusb读取鼠标数据

通libusb我们可以在应用层对USB设备进行读写操作。本文以读取USB鼠标数据为例讲述libusb的使用流程。

通过源码安装libusb:

最新的版本为:libusb-1.0.24,GitHub上免费下载地址:

https://github.com/libusb/libusb/releases/tag/v1.0.24

ps: CSDN上很多人用这个公共的开源资源来赚积分,而且下载分还贼高,真不怎么地道。

解压源码:tar xjvf libusb-1.0.24.tar.bz2

在解压跟目录下输入命令:

./configure

注意:如果报以下错误

configure: error: udev support requested but libudev header not installed

不要慌,这是由于没安装libudev库,可以通过以下方式解决:

1、输入命令apt-get install libudev-dev安装libudev

2、运行configure脚本时输入:./configure --disable-udev(这种方法本人还没验证)

编译:make

安装:make install

默认安装在/usr/local/lib目录下

以上是源码编译安装流程,在线通过以下命令安装也很简单:

a、apt-get install libudev-dev

b、apt-get install libusb-dev

c、apt-get install libusb-1.0-0-dev

安装完libusb库后就可以开发应用层程序对USB设备进行读写操作了,下面是参考libusb例子中的testlibusb.c文件编写的鼠标数据读取程序test_rw.c:

​
#include <config.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <stdlib.h>
#include <stdint.h>
#include <errno.h>
#include <fcntl.h>
#include <unistd.h>
#include <time.h>
#include <getopt.h>
#include <ctype.h>
#include <signal.h>

#include "libusb.h"

int verbose = 1;

static volatile sig_atomic_t rcv_exit;

static void print_endpoint_comp(const struct libusb_ss_endpoint_companion_descriptor *ep_comp)
{
    printf("      USB 3.0 Endpoint Companion:\n");
    printf("        bMaxBurst:           %u\n", ep_comp->bMaxBurst);
    printf("        bmAttributes:        %02xh\n", ep_comp->bmAttributes);
    printf("        wBytesPerInterval:   %u\n", ep_comp->wBytesPerInterval);
}

static void print_endpoint(const struct libusb_endpoint_descriptor *endpoint)
{
    int i, ret;

    printf("      Endpoint:\n");
    printf("        bEndpointAddress:    %02xh\n", endpoint->bEndpointAddress);
    printf("        bmAttributes:        %02xh\n", endpoint->bmAttributes);
    printf("        wMaxPacketSize:      %u\n", endpoint->wMaxPacketSize);
    printf("        bInterval:           %u\n", endpoint->bInterval);
    printf("        bRefresh:            %u\n", endpoint->bRefresh);
    printf("        bSynchAddress:       %u\n", endpoint->bSynchAddress);

    for (i = 0; i < endpoint->extra_length;) {
        if (LIBUSB_DT_SS_ENDPOINT_COMPANION == endpoint->extra[i + 1]) {
            struct libusb_ss_endpoint_companion_descriptor *ep_comp;

            ret = libusb_get_ss_endpoint_companion_descriptor(NULL, endpoint, &ep_comp);
            if (LIBUSB_SUCCESS != ret)
                continue;

            print_endpoint_comp(ep_comp);

            libusb_free_ss_endpoint_companion_descriptor(ep_comp);
        }

        i += endpoint->extra[i];
    }
}

static void print_altsetting(const struct libusb_interface_descriptor *interface)
{
    uint8_t i;

    printf("    Interface:\n");
    printf("      bInterfaceNumber:      %u\n", interface->bInterfaceNumber);
    printf("      bAlternateSetting:     %u\n", interface->bAlternateSetting);
    printf("      bNumEndpoints:         %u\n", interface->bNumEndpoints);
    printf("      bInterfaceClass:       %u\n", interface->bInterfaceClass);
    printf("      bInterfaceSubClass:    %u\n", interface->bInterfaceSubClass);
    printf("      bInterfaceProtocol:    %u\n", interface->bInterfaceProtocol);
    printf("      iInterface:            %u\n", interface->iInterface);

    for (i = 0; i < interface->bNumEndpoints; i++)
        print_endpoint(&interface->endpoint[i]);
}

static void print_2_0_ext_cap(struct libusb_usb_2_0_extension_descriptor *usb_2_0_ext_cap)
{
    printf("    USB 2.0 Extension Capabilities:\n");
    printf("      bDevCapabilityType:    %u\n", usb_2_0_ext_cap->bDevCapabilityType);
    printf("      bmAttributes:          %08xh\n", usb_2_0_ext_cap->bmAttributes);
}

static void print_ss_usb_cap(struct libusb_ss_usb_device_capability_descriptor *ss_usb_cap)
{
    printf("    USB 3.0 Capabilities:\n");
    printf("      bDevCapabilityType:    %u\n", ss_usb_cap->bDevCapabilityType);
    printf("      bmAttributes:          %02xh\n", ss_usb_cap->bmAttributes);
    printf("      wSpeedSupported:       %u\n", ss_usb_cap->wSpeedSupported);
    printf("      bFunctionalitySupport: %u\n", ss_usb_cap->bFunctionalitySupport);
    printf("      bU1devExitLat:         %u\n", ss_usb_cap->bU1DevExitLat);
    printf("      bU2devExitLat:         %u\n", ss_usb_cap->bU2DevExitLat);
}

static void print_bos(libusb_device_handle *handle)
{
    struct libusb_bos_descriptor *bos;
    uint8_t i;
    int ret;

    ret = libusb_get_bos_descriptor(handle, &bos);
    if (ret < 0)
        return;

    printf("  Binary Object Store (BOS):\n");
    printf("    wTotalLength:            %u\n", bos->wTotalLength);
    printf("    bNumDeviceCaps:          %u\n", bos->bNumDeviceCaps);

    for (i = 0; i < bos->bNumDeviceCaps; i++) {
        struct libusb_bos_dev_capability_descriptor *dev_cap = bos->dev_capability[i];

        if (dev_cap->bDevCapabilityType == LIBUSB_BT_USB_2_0_EXTENSION) {
            struct libusb_usb_2_0_extension_descriptor *usb_2_0_extension;

            ret = libusb_get_usb_2_0_extension_descriptor(NULL, dev_cap, &usb_2_0_extension);
            if (ret < 0)
                return;

            print_2_0_ext_cap(usb_2_0_extension);
            libusb_free_usb_2_0_extension_descriptor(usb_2_0_extension);
        } else if (dev_cap->bDevCapabilityType == LIBUSB_BT_SS_USB_DEVICE_CAPABILITY) {
            struct libusb_ss_usb_device_capability_descriptor *ss_dev_cap;

            ret = libusb_get_ss_usb_device_capability_descriptor(NULL, dev_cap, &ss_dev_cap);
            if (ret < 0)
                return;

            print_ss_usb_cap(ss_dev_cap);
            libusb_free_ss_usb_device_capability_descriptor(ss_dev_cap);
        }
    }

    libusb_free_bos_descriptor(bos);
}

static void print_interface(const struct libusb_interface *interface)
{
    int i;

    for (i = 0; i < interface->num_altsetting; i++)
        print_altsetting(&interface->altsetting[i]);
}

static void print_configuration(struct libusb_config_descriptor *config)
{
    uint8_t i;

    printf("  Configuration:\n");
    printf("    wTotalLength:            %u\n", config->wTotalLength);
    printf("    bNumInterfaces:          %u\n", config->bNumInterfaces);
    printf("    bConfigurationValue:     %u\n", config->bConfigurationValue);
    printf("    iConfiguration:          %u\n", config->iConfiguration);
    printf("    bmAttributes:            %02xh\n", config->bmAttributes);
    printf("    MaxPower:                %u\n", config->MaxPower);

    for (i = 0; i < config->bNumInterfaces; i++)
        print_interface(&config->interface[i]);
}

static void print_device(libusb_device *dev, libusb_device_handle *handle, uint16_t vid, uint16_t pid)
{
    struct libusb_device_descriptor desc;
    unsigned char string[256];
    const char *speed;
    int ret;
    uint8_t i;

    switch (libusb_get_device_speed(dev)) {
    case LIBUSB_SPEED_LOW:        speed = "1.5M"; break;
    case LIBUSB_SPEED_FULL:        speed = "12M"; break;
    case LIBUSB_SPEED_HIGH:        speed = "480M"; break;
    case LIBUSB_SPEED_SUPER:    speed = "5G"; break;
    case LIBUSB_SPEED_SUPER_PLUS:    speed = "10G"; break;
    default:            speed = "Unknown";
    }

    ret = libusb_get_device_descriptor(dev, &desc);
    if (ret < 0) {
        fprintf(stderr, "failed to get device descriptor");
        return;
    }

    
    if (!handle)
    libusb_open(dev, &handle);

    if((desc.idVendor == vid) && (desc.idProduct == pid))
    {
        printf("Dev (bus %u, device %u): %04X - %04X speed: %s\n",
                   libusb_get_bus_number(dev), libusb_get_device_address(dev),
                   desc.idVendor, desc.idProduct, speed);
        

        if (handle)
        {
            if (desc.iManufacturer) {
                ret = libusb_get_string_descriptor_ascii(handle, desc.iManufacturer, string, sizeof(string));
                if (ret > 0)
                    printf("  Manufacturer:              %s\n", (char *)string);
            }

            if (desc.iProduct) {
                ret = libusb_get_string_descriptor_ascii(handle, desc.iProduct, string, sizeof(string));
                if (ret > 0)
                    printf("  Product:                   %s\n", (char *)string);
            }

            if (desc.iSerialNumber && verbose) {
                ret = libusb_get_string_descriptor_ascii(handle, desc.iSerialNumber, string, sizeof(string));
                if (ret > 0)
                    printf("  Serial Number:             %s\n", (char *)string);
            }
                        
        }

        if (verbose) {
            for (i = 0; i < desc.bNumConfigurations; i++) {
                struct libusb_config_descriptor *config;

                ret = libusb_get_config_descriptor(dev, i, &config);
                if (LIBUSB_SUCCESS != ret) {
                    printf("  Couldn't retrieve descriptors\n");
                    continue;
                }

                print_configuration(config);

                libusb_free_config_descriptor(config);
            }

            if (handle && desc.bcdUSB >= 0x0201)
                print_bos(handle);
        }        

    }

    
    if(handle)
    {
        libusb_close(handle);
    }
}

static int test_wrapped_device(const char *device_name, uint16_t vendor_id, uint16_t product_id)
{
    libusb_device_handle *handle;
    int r, fd;

    fd = open(device_name, O_RDWR);
    if (fd < 0) {
        printf("Error could not open %s: %s\n", device_name, strerror(errno));
        return 1;
    }
    r = libusb_wrap_sys_device(NULL, fd, &handle);
    if (r) {
        printf("Error wrapping device: %s: %s\n", device_name, libusb_strerror(r));
        close(fd);
        return 1;
    }
    print_device(libusb_get_device(handle), handle, vendor_id, product_id);
    close(fd);
    return 0;
}

static void sig_handler(int signum)
{
    switch (signum) {
    case SIGTERM:
        rcv_exit = 1;
        break;
    case SIGINT:
        rcv_exit = 1;
        break;
    case SIGUSR1:
        break;
    }
}

static void usage(char *program)
{
    printf("%s - test usb data transfers to/from usb device\n",
            program);
    printf("Usage:\n");
    printf("  %s [options]\n", program);
    printf("options are:\n");
    printf("Common:\n");
    printf("  --help (or -h)\n");    
    printf("  -v vendor_id\n");
    printf("  -p product_id\n");
    printf("  -d device name\n");
}

static int interrupt_data_rw(uint16_t vendor_id, uint16_t product_id)
{
    int kernelDriverDetached = 0;
    unsigned char data_in[64]={0};
    int length = 0;
    int r,j;
    libusb_device_handle *handle;

    handle = libusb_open_device_with_vid_pid(NULL, vendor_id, product_id);
    if (handle == NULL) 
    {
        printf("libusb_open() failed\n");
        return -1;;
    }

 
    /*驱动必须解绑定,否则数据由驱动程序处理*/    if(libusb_kernel_driver_active(handle, 0))
    {
        printf("Kernel Driver Active\n");
        r = libusb_detach_kernel_driver(handle, 0);
        if (r == 0)
        {
            printf("Detach Kernel Driver\n");
            kernelDriverDetached = 1;
        }
        else
        {
            fprintf(stderr, "Error detaching kernel driver.\n");
            return -1;;
        }
    }
    
    
     /* 指定当前接口 */
    r = libusb_claim_interface(handle, 0);
    if (r != 0)
    {
        fprintf(stderr, "Error claiming interface.\n");
        goto exit;
    }
    

    while(!rcv_exit)
    {
        memset(data_in, 0, sizeof(data_in));
        /*中断方式读取断点数据,
        由端点描述符可知端点地址 0x81 为鼠标输入端点
        读取长度为5字节,超时时间为1000ms*/    

        r = libusb_interrupt_transfer(handle, 0x81, data_in, 5, &length, 1000);
        if ((r < 0) || (length == 0))
        {
            printf("bulk recive error,r:%d length:%d\n",r,length);
        }
        else
        {
            printf("receive data:\n");
            for(j=0; j<length; j++)
            {
                printf("0x%x ",data_in[j]);
            }
            printf("\n");
        }
        usleep(500000);
    }

    
     /* 释放指定的接口 */
    r = libusb_release_interface(handle, 0);
    if (0 != r)
    {
        fprintf(stderr, "Error releasing interface.\n");
    }
    
    
exit:
    if(kernelDriverDetached)
    {
        //恢复驱动绑定,否则鼠标不可用
        libusb_attach_kernel_driver(handle, 0);
    }

    
    libusb_close(handle);
    return r;
    

}

int main(int argc, char *argv[])
{
    char *program = argv[0];
    int option;
    const char *device_name = NULL; //"/dev/bus/usb/001/005"
    libusb_device **devs;
    ssize_t cnt;
    int r, i;
    uint16_t vid=0, pid=0;
    libusb_device_handle *handle = NULL;

    static const struct option options[] = {
            { "vendid", required_argument, NULL, 'v' },
            { "productid",  required_argument, NULL, 'p' },
            { "devicename",   required_argument, NULL, 'd' },
            { "help",   no_argument, NULL, 'h' },
    };

    /* Parse command line options, if any */
    while ((option = getopt_long_only(argc, argv,
            "hv:p:d:",options, NULL)))
    {
        if (option == -1)
            break;
        switch (option) {
        case 'v':
            vid = strtoul(optarg, NULL, 0);
            break;
        case 'p':
            pid = strtoul(optarg, NULL, 0);
            break;
        case 'd':
            device_name = optarg;
            break;
        case 'h':
            usage(program);
            exit(EXIT_SUCCESS);
            break;
        default:
            printf("ERROR: Invalid command line option\n");
            usage(program);
            exit(EXIT_FAILURE);
        }
    }

    printf("vid:0x%x pid:0x%x devicename:%s\n",vid,pid,device_name);

    

    r = libusb_init(NULL);
    if (r < 0)
        return r;

    if (device_name) {
        printf("test_wrapped_device\n");
        r = test_wrapped_device(device_name,vid,pid);
    } else {
        cnt = libusb_get_device_list(NULL, &devs);
        if (cnt < 0) {
            libusb_exit(NULL);
            return 1;
        }

        for (i = 0; devs[i]; i++)
            print_device(devs[i], handle,vid,pid);

        libusb_free_device_list(devs, 1);
    }

    signal(SIGINT, sig_handler);
    signal(SIGTERM, sig_handler);

    //read mouse data
    interrupt_data_rw(vid,pid);

    libusb_exit(NULL);
    return r;
}

​

编译命令:

gcc -o test_rw test_rw.c -I/usr/local/include/libusb-1.0/ -I../ -lusb-1.0

lsusb查看鼠标设备信息如下:

根权限运行程序,读取鼠标信息:./testrw -v 0x046d -p 0xc045,读取过程需要移动鼠标,否则会提示读取失败。

标签:

本文转载自: https://blog.csdn.net/luky_zhou123/article/details/119594289
版权归原作者 缥缈孤鸿_jason 所有, 如有侵权,请联系我们删除。

“libusb读取鼠标数据”的评论:

还没有评论