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

2023-05-16

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 
​

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

应用程序利用libusb读取usb设备数据 的相关文章

随机推荐

  • 拷贝构造函数的三种常见的调用时机 c++简单易懂

    拷贝构造函数的调用时机 xff1a 1 用一个已经创好的对象来初始化一个新对象 2 用值传递来给形参传值的时候 3 以值传递的方式返回局部对象都是利用拷贝构造函数的形式 分别用三个测试案例来举例 span class token macro
  • linux操作系统之cp命令(复制文件或文件夹)和mv(移动文件或文件夹) 通俗易懂

    一 xff1a cp命令 1 cp命令使用格式 xff1a cp 原文件 目标文件 2 简化 xff1a 当使用cp命令复制一个文件的时候 xff0c 如果文件名不发生改变那么目标文件只需要指明目标文件的路径即可 xff0c 就不用指明文件
  • 全局变量和局部变量的理解及注意事项 超详细 简单易懂

    一全局变量和局部变量 xff08 1 xff09 全局变量和局部变量的含义 xff1a 在函数体内部定义的变量叫做局部变量 xff0c 在函数体外部定义的变量叫做全局变量 局部变脸只能在定义的那个函数体的内部进行使用 xff0c 而全局变量
  • 光速幂

    warning xff1a 如果你还没有学过快速幂 xff0c 请掉头先学快速幂因为快速幂的适用范围比这个东西更广 我们先回忆一下快速幂是怎么解决的 我们是利用二进制的性质将复杂度优化到单词询问 O log i n
  • 队列的线性存储结构 c语言 数据结构 简单易懂 超详细~~

    include lt stdio h gt include lt stdlib h gt typedef int Elemtype define maxsize 100 typedef struct queue 注意再用顺序结构来表示栈和队
  • 复杂网络入门详解 适用于初学者。超详细~~

    一复杂网络的特性 1 复杂网络的特性之 小世界特性 xff1a xff08 1 xff09 社交网络中任何一个成员和任何一个认识的人之间的间隔人数不会超过六个人 即通过小于六个人 xff0c 总能找到社交网络中任何一个成员 xff08 2
  • Ubuntu系统中/usr/share/applications/目录下都是.desktop文件没有快捷方式

    在虚拟机中运行Ubuntu系统不免要安装一些linux应用软件 xff0c 为了方便我们会在虚拟机的桌面添加相应软件的快捷方式 一般情况下 xff0c 软件的快捷方式会保存在 usr share applications 目录下 我们可能会
  • my.cnf 中方便使用的设置

    记录my cnf 中一些方便使用的设置 vi etc my cnf 1 通过 prompt 61 name可以自定义提示信息 xff0c 通过配置显示登入的主机地址 xff0c 登陆用户名 xff0c 当前时间 xff0c 当前数据库sch
  • ubuntu环境下安装Jenkins

    文章目录 ubuntu环境下安装Jenkins方法一 war包安装1 34 启动脚本设置5 创建配置文件6 运行Jenkins 方法二 apt安装 问题记录1 启动jenkins报错 Failed to start Jetty或Failed
  • 打印1-100之间所有素数

    代码 方法1 方法2 执行结果 求1 10之间非素数之和
  • 打印出所有水仙花数

    水仙花数是指一个三位数 xff0c 其各位数字立方和等于该数本身 例如153 61 43 43 一重循环方式实现 首先分别求出三位数 i 的百位数 a 十位数 b 和个位数 c 之后判断a的立方和加b的立方和和c的立方和是否等于该三位数 i
  • LT8618SX寄存器配置

    LT8618SX功能 RGB输入 支持24位RGB xff0c YUV和BT656 BT601 BT1120输入 支持SDR和DDR数据采样 可编程上升 下降边缘时钟输入 支持高达148 5MHz DDR或297MHz SDR时钟输入 支持
  • linux重定向串口打印到telnet ssh远程终端

    源码 xff1a log c span class token macro property span class token directive hash span span class token directive keyword i
  • [HAOI2012] 高速公路

    这道题有一种解法是维护区间和 xff0c 区间和 i times i i xff0c 区间和 i 2
  • rtsp鉴权认证(密码登录)

    Rtsp认证主要分为两种 xff1a 基本认证 xff08 basic authentication xff09 和摘要认证 xff08 digest authentication xff09 基本认证是http 1 0提出的认证方案 xf
  • 基于RK3399的LED驱动开发

    1 添加设备树 在设备树 arch arm64 boot dts rockchip rk3399 firefly linux dts 中添加 gpio span class token operator span led span clas
  • RK3399 CAN接口配置设备树(mcp2515)

    RK3399 CAN接口配置设备树 xff08 mcp2515 xff09 kernel需先配置config xff0c 增加mcp2515支持 xff0c Networking support gt CAN bus subsystem s
  • RK3399 ALC5640芯片配置

    说明 xff1a 本文适用于 RK3399 linux 4 4 内核系列SDK 硬件上 xff0c 音频外部 codec 芯片 i2s 引脚与 RK3399 i2s1连接 软件上需要加下述patch解决噪声问题 xff08 以 rt5640
  • random: crng init done太慢影响程序运行

    现象 xff1a 内核打印random crng init done之后QT应用程序才启动 xff08 特别是emmc分区后很慢 xff09 3 412968 usb 1 1 New USB device found idVendor 61
  • 应用程序利用libusb读取usb设备数据

    USB HID 类是 USB 设备的一个标准设备类 xff0c 属于人机交互操作的 设备 xff0c 包括鼠标 键盘等 xff0c 主要用于人与计算机进行交互 xff0c 它还可用来传输数据 控制设备等 非标USB设备 xff0c 应用程序