USB HID设备数据的读取

USB设备(HID)

Android下获取HID数据的方式:

1.通过读取/dev/hidrawX设备节点 看名字就知道意思了(这个需要在编译的时候打开)

2.如果是标准HID设备,还可以通过/dev/input里的设备节点读取

方式一.通过input/event获得数据

这里的数据被转化为统一的结构,结构的定义在input.h中,值也在头文件中定义。几个结构体定义如下:
我们在event节点读取设备,所以格式就是input_event,单帧timeval时间数据结构长度加8字节数据。

struct input_event {
 struct timeval time;
 __u16 type;
 __u16 code;
 __s32 value;
};

#define EV_VERSION 0x010000

struct input_id {
 __u16 bustype;
 __u16 vendor;
 __u16 product;
 __u16 version;
};

struct input_absinfo {
 __s32 value;
 __s32 minimum;
 __s32 maximum;
 __s32 fuzz;
 __s32 flat;
};

题外话:之前比较好奇USB设备为什么能将不同的设备的协议转化为相同的结构。得到的结果好像是可以将自己的协议解析告诉USB协议告诉系统,然后让系统按自己的协议进行解析。[…]

获取数据

首先获取数据作为测试test.cpp。这里数据解析是绝对数据解析。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include <linux/input.h>

#define MOUSE_DEV_PATH    "/dev/input/event1"
int x = 0;
int y = 0;

int main()
{
        unsigned char data[sizeof(input_event)];
        input_event dev_data;
        int fd = open(MOUSE_DEV_PATH, O_RDONLY);
        if (fd == -1)
        {
                printf("mouse device open fail\n");
                return -1;
        }

        printf("open successful");
        while (1)
        {
                int size = read (fd, (unsigned char*)data, sizeof(input_event));
                printf("size:%d", size);
                memcpy(&dev_data, data, sizeof(input_event));
                        if (dev_data.type == EV_REL)
                        {
                                if (dev_data.code == REL_X)
                                {
                                        x += dev_data.value;
                                        if (x < 0) x = 0;
                                        printf("rel X:%d", dev_data.value);
                                }
                                else if(dev_data.code == REL_Y)
                                {
                                        printf("rel Y:%d", dev_data.value);
                                        y += dev_data.value;
                                        if (y < 0) y = 0;
                                }
                                printf("\nx=%d,y=%d\n", x, y);
                        }

                printf("\n");
                for (int i = 0; i < size; ++i)
                        printf(" %3d", data[i]);
                printf("\n");

        }
        close(fd);
}

Android.mk

MY_LOCAL_PATH:=$(call my-dir)
LOCAL_PATH:=$(MY_LOCAL_PATH)
MY_LOCAL_ANDSRC:=/home/Android7.1.1
include $(CLEAR_VARS)


LOCAL_MODULE:=mytest
LOCAL_SRC_FILES:=test.cpp


include $(BUILD_EXECUTABLE)

获得设备

event的设备号会因插入顺序而不同,所以需要自动获得设备。
可以通过查看:
cat /proc/bus/input/devices
可以得到对应的vid和pid对应的event

I: Bus=0003 Vendor=17ef Product=6019 Version=0111
N: Name=" Mouse"
P: Phys=usb-fe3c0000.usb-1.7/input0
S: Sysfs=/devices/platform/fe3c0000.usb/usb2/2-1/2-1.7/2-1.7:1.0/0003:XXXX:XXXX.0001/input/input2
U: Uniq=
H: Handlers=event2 cpufreq
B: PROP=0
B: EV=17
B: KEY=70000 0 0 0 0
B: REL=103
B: MSC=10

一种解决思路是通过解析这个设备文件进行查找

也可也通过ioctl EVIOCGID来获得VID和PID,参考:https://blog.csdn.net/tankai19880619/article/details/38663709


方式二.通过hidraw节点获得原生数据

这种方式很普通直接读写设备获得数据即可,然后按照协议的数据解析即可。

#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include <linux/input.h>
#include <linux/hidraw.h>

#define MOUSE_DEV_PATH    "/dev/hidraw0"

unsigned char buffer[1000];

int main()
{
        struct hidraw_devinfo info;

        int fd = open(MOUSE_DEV_PATH, O_RDONLY);
        if (fd == -1)
        {
                printf("mouse device open fail\n");
                return -1;
        }

        int rc = ioctl(fd, HIDIOCGRAWINFO, &info);
        if (rc < 0)
        {
                printf("readerror!\n");
                return 1;
        }
        printf("HID device info %04x:%04x:%04x is\n", info.bustype,info.vendor, info.product);

        
        unsigned char buff[96];
        printf("open successful\n");
        while (1)
        {
                int size = read(fd, buffer, 64);
                printf("\nsize:%d\t", size);
                for (int i = 0; i < size; ++i)
                        printf("%d ", buffer[i]);
              printf("\n");
        }
        return 0;
}

如果没有hidraw设备节点,可参考这个:
https://blog.csdn.net/qq_33750826/article/details/78952249

hidraw的参考文档:https://www.kernel.org/doc/Documentation/hid/hidraw.txt

获取设别节点的VID和PID可以通过ioctl查询HIDIOCGRAWINFO获得。
结构体定义在hidraw.h中

修改hidrawX设备节点权限的方法

1.修改uevent.rc文件

修改编译后的uevent.rc文件。文件位置在 out/target/product/XXXXXXX/root 路径下
增加:

/dev/hidraw*              0666   root       root

这样默认是把hidraw*的所有权限都改成0666了。然后在进行打包成镜像。

2.修改源码

如果要在源码里修改配置信息可参考:
https://www.jb51.net/article/73073.htm

其实应该还有种方法是在源码创建hidraw的节点时的权限。

3.监听修改权限服务

这种方法是。写一个监听服务,可以轮询查看插上的hid设备。根据hid的PID和VID修改权限。

然后把服务设置成开机启动

#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <linux/types.h>
#include <dirent.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <linux/input.h>
#include <linux/hidraw.h>

#define  DEV_BASE_PATH    "/dev/hidraw"
#define  MAX_SUPPORT_DEV   20
#define  PRODUCT_VID        
#define  PRODUCT_PID 

int main()
{
	int fd;
	struct hidraw_devinfo info;
	char path[20];
	struct stat buf;
	
	while (1)
	{	
		for (int i = 0; i < MAX_SUPPORT_DEV; ++i)
		{
			sprintf(path, "%s%d", DEV_BASE_PATH, i);
			stat(path, &buf);
			if (!(buf.st_mode & S_IROTH))
			{
				if((fd = open(path, O_RDONLY)) < 0)
					continue;

				int rc = ioctl(fd, HIDIOCGRAWINFO, &info);
				if (rc < 0)			
					continue;
				if ((info.vendor == PRODUCT_VID) && (info.product == PRODUCT_PID))
				{
					fchmod(fd,0666);
					close(fd);
					break;	
				}	
			}
		}
		
		sleep(3);
	}
	return 0;
}
  • 7
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
USB HID设备是一种使用USB接口进行通信的设备,它可以通过发送和接收数据来实现和计算机的交互。为了读写USB HID设备数据,我们需要编写一个程序来实现这个功能。 首先,我们需要使用合适的编程语言和相关的库来开发这样一个程序。对于Windows系统,我们可以使用C#、C++或者Python等语言来编写程序;对于Linux系统,则可以选择C语言、Python等来实现。然后,我们需要选择一个合适的USB库,比如libusb,它提供了一些用于控制USB设备的函数和结构体。 接着,我们需要编写程序来进行USB设备的初始化和连接。一般来说,我们需要找到目标设备的vendor ID和product ID,然后使用相关函数来打开设备并进行数据的读写。 在程序运行的过程中,我们可以使用相关函数来读取设备发送的数据,也可以发送命令或者数据设备。在读取数据时,我们需要根据设备的协议和数据格式进行解析和处理,以确保能正确地获取到设备发送的信息。 最后,我们需要进行错误处理和资源释放。当程序出现错误时,我们需要进行相应的处理,比如关闭设备,释放相关资源等,以确保程序的稳定性和可靠性。 总的来说,编写USB HID设备数据读写程序是一个需要考虑设备协议、数据格式等因素的复杂任务,但通过合适的编程语言和库的选择,以及认真的编程实现,我们可以成功地实现这一功能。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值