应用程序利用libusb读取usb设备数据

USB HID类是USB设备的一个标准设备类,属于人机交互操作的设备,包括鼠标、键盘等,主要用于人与计算机进行交互,它还可用来传输数据、控制设备等。
非标USB设备,应用程序可以通过libusb读取数据,当然也可以读取标准HID类设备如鼠标等。
一、移植libusb-1.0.24
./configure --host=arm-linux-gnueabihf --prefix=$PWD/_install --disable-udev
二、编写usb_test程序并编译
arm-linux-gnueabihf-gcc main.c -I ../libusb-1.0.24/_install/include/libusb-1.0/ ../libusb-1.0.24/_install/lib/libusb-1.0.a -o usb_test -lpthread
测试代码:
#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;
}

 
三、测试
lsusb查看鼠标设备的VID和PID
Bus 001 Device 001: ID 1d6b:0002
Bus 001 Device 003: ID 413c:301a
Bus 001 Device 002: ID 1a86:8091
usb_test -v 0x413c -p 0x301a 根据VID和PID读取数据
 
vid:0x413c pid:0x301a devicename:(null)
Dev (bus 1, device 3): 413C - 301A speed: 1.5M
  Manufacturer:              PixArt
  Product:                   Dell MS116 USB Optical Mouse
  Configuration:
    wTotalLength:            34
    bNumInterfaces:          1
    bConfigurationValue:     1
    iConfiguration:          0
    bmAttributes:            a0h
    MaxPower:                50
    Interface:
      bInterfaceNumber:      0
      bAlternateSetting:     0
      bNumEndpoints:         1
      bInterfaceClass:       3
      bInterfaceSubClass:    1
      bInterfaceProtocol:    2
      iInterface:            0
      Endpoint:
        bEndpointAddress:    81h
        bmAttributes:        03h
        wMaxPacketSize:      4
        bInterval:           10
        bRefresh:            0
        bSynchAddress:       0
Kernel Driver Active
Detach Kernel Driver
bulk recive error,r:-7 length:0
receive data:
0x0 0x1 0x0 0x0 0x0 
receive data:
0x0 0x7f 0xd4 0x0 0x0 
receive data:
0x0 0x7f 0xa7 0x0 0x0 
receive data:
0x0 0x7f 0x81 0x0 0x0 
receive data:
0x0 0x81 0x81 0x0 0x0 
receive data:
0x0 0x81 0x7f 0x0 0x0 
receive data:
0x0 0x83 0xcc 0x0 0x0 
receive data:
0x0 0x7f 0x6e 0x0 0x0 
receive data:
0x0 0x7f 0xc2 0x0 0x0 
receive data:
0x0 0x81 0x5e 0x0 0x0 
receive data:
0x0 0x7f 0xde 0x0 0x0 
receive data:
0x0 0xdd 0xf6 0x0 0x0 
​

  • 0
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

悠哉无忧

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值