libusb读取鼠标数据

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

通过源码安装libusb:

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

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

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

解压源码: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,读取过程需要移动鼠标,否则会提示读取失败。

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

缥缈孤鸿_jason

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

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

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

打赏作者

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

抵扣说明:

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

余额充值