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;
}
HID 设备类读写 #include //! Defines the maximum length of a serial number #define SERNUM_LEN 40 //! Defines the maximum number of physical devices #define MAX_PHYS_DEVICES 6 //! \name HID Device return codes //! @{ // //! HID action/transfer was successful #define HID_DEVICE_SUCCESS 0x00 //! HID device was not found #define HID_DEVICE_NOT_FOUND 0x01 //! HID device is not opened #define HID_DEVICE_NOT_OPENED 0x02 //! HID device is allready opened #define HID_DEVICE_ALREADY_OPENED 0x03 //! Timeout occurs during transfer #define HID_DEVICE_TRANSFER_TIMEOUT 0x04 //! HID transfer failed #define HID_DEVICE_TRANSFER_FAILED 0x05 //! Invalid handle #define HID_DEVICE_HANDLE_ERROR 0x06 //! Unknown error #define HID_DEVICE_UNKNOWN_ERROR 0xFF //! @} // Enabled only when debugging HID connection issues //#define DEBUG_MODE //****************************************************************************** // //! \brief Device information structure. // //****************************************************************************** struct strHidDevice{ //! Handle for hid device HANDLE hndHidDevice; //! Indicator if device is opened BOOL bDeviceOpen; //! Timeout for GetReport requests UINT uGetReportTimeout; //! Timeout for SetReport requests UINT uSetReportTimeout; //! Asynchronous I/O structure OVERLAPPED oRead; //! Asynchronous I/O structure OVERLAPPED oWrite; //! Maximum length of InReport's WORD wInReportBufferLength; //! Maximum length of OutReport's WORD wOutReportBufferLength; //! InBuffer contains data, if InReport provides more data then the application actual need BYTE inBuffer[8192]; //! Number of current used bytes in inBuffer WORD inBufferUsed; }; //****************************************************************************** // //! A structure that tracks the number of serial numbers // //****************************************************************************** struct strTrackSerialNumbers { //! Index number DWORD deviceNum; //! Serial number of physical device char serialNum[SERNUM_LEN]; }; //****************************************************************************** // //! \addtogroup hiddevice_api //! @{ // //****************************************************************************** //****************************************************************************** // //! \brief Close a HID Device. //! //! This function will close a HID device based on the HID structure //! //! \param pstrHidDevice Structure which contains important data of an HID //! device //! //! \return Returns the error status, as one of //! \n \b HID_DEVICE_SUCCESS //! \n \b HID_DEVICE_NOT_OPENED //! \n \b HID_DEVICE_HANDLE_ERROR // //****************************************************************************** BYTE HID_Close(struct strHidDevice* pstrHidDevice); //****************************************************************************** // //! \brief Flush USB buffer for the given device //! //! \param pstrHidDevice Structure which contains important data of an HID //! device. //! //! \return Returns the error status, as one of //! \n \b HID_DEVICE_SUCCESS //! \n \b HID_DEVICE_HANDLE_ERROR //! \n \b HID_DEVICE_UNKNOWN_ERROR // //****************************************************************************** BYTE HID_FlushBuffer(struct strHidDevice* pstrHidDevice); //****************************************************************************** // //! \brief Gets the number of HID devices //! //! This function will return the number of interfaces connected with a //! specified VID, PID and serial number, if no devices are connected, //! it will return a 0 //! //! \param vid Vendor-Id of the device //! \param pid Product-Id of the device //! \param numSerNums Total number of connected physical devices //! //! \return Return the number of connected devices with the specific VID, PID, //! and serial number. // //****************************************************************************** DWORD HID_GetNumOfInterfaces(WORD vid, WORD pid, DWORD numSerNums); //****************************************************************************** // //! \brief Gets the number of serial number and serial number list //! //! Scans the HID Devices on the system for any whose VID/PID match the //! ones specified. For every one it finds, it returns that device's //! serial number in serialNumList. Every physical USB device within a //! given VID/PID space has a unique serial number; therefore, each //! item in the list corresponds with a separate physical USB device //! attached to this host; that is, different physical instances of the //! same product or design. The function returns the total number of //! serial numbers found; if none are found, it returns 0. //! //! \param vid Vendor-ID of the device //! \param pid Product-ID of the device //! \param serialNumList List of serial numbers corresponding to the passed //! VID and PID //! //! \return Returns the number of connected physical devices with the specific //! VID and PID // //****************************************************************************** DWORD HID_GetSerNums(WORD vid, WORD pid, struct strTrackSerialNumbers * serialNumList); //****************************************************************************** // //! \brief Returns the version number of a device. //! //! \param pstrHidDevice Structure which contains important data of an HID //! device. //! \param VersionNumber Pointer to USHORT variable. //! //! \return Returns the error status, as one of //! \n \b HID_DEVICE_SUCCESS //! \n \b HID_DEVICE_HANDLE_ERROR // //****************************************************************************** BYTE HID_GetVersionNumber(struct strHidDevice* pstrHidDevice, USHORT * VersionNumber); //****************************************************************************** // //! \brief Init structure with default values. //! //! It is important to call HID_Init() before calling HID_Open() to //! avoid unpredictable behavoir. //! //! \param pstrHidDevice Structure which contains important data of a HID //! device //! //! \return None // //****************************************************************************** void HID_Init(struct strHidDevice* pstrHidDevice); //****************************************************************************** // //! \brief This has to be called inside WM_ON_DEVICECHANGE notification window //! //! This function checks if the particular HID device structure is //! still connected or disconnected. //! //! \param pstrHidDevice Structure which contains important data of an HID //! device. //! //! \return Returns the error status, as one of //! \n \b HID_DEVICE_SUCCESS //! \n \b HID_DEVICE_HANDLE_ERROR // //****************************************************************************** BOOL HID_IsDeviceAffected(struct strHidDevice* pstrHidDevice); //****************************************************************************** // //! \brief Open a HID Device. //! //! This function opens the HID device associated with the HID interface //! 'deviceIndex' (0-7), on the physical device described by the VID, //! PID, and serial number. //! \param pstrHidDevice Structure which contains important data of an HID //! device //! \param vid Vendor-ID of the device //! \param pid Product-ID of the device //! \param deviceIndex Index of the device.If only one HID is connected, //! deviceIndex is 0. //! - Starts with zero //! - Maximum value is (HID_GetNumOfInterfaces() - 1) //! \param serialNumber Serial number of device to be opened. //! \param totalDevNum Total number of interfaces associated with the //! serial number //! \param totalSerNum Total number of physical devices associated with //! the VID/PID //! //! \return Returns the error status, as one of //! \n \b HID_DEVICE_SUCCESS //! \n \b HID_DEVICE_NOT_FOUND //! \n \b HID_DEVICE_ALREADY_OPENED // //****************************************************************************** BYTE HID_Open(struct strHidDevice* pstrHidDevice, WORD vid, WORD pid, DWORD deviceIndex, char serialNumber[SERNUM_LEN], DWORD totalDevNum, DWORD totalSerNum); //****************************************************************************** // //! \brief Reads a data stream from the given HID device. //! //! Prefixed report ID will be skipped. //! //! \param pstrHidDevice Structure which contains important data of an HID //! device //! \param buffer Pointer to buffer in which will be written //! \param bufferSize Number of bytes to read //! \param bytesReturned Number of actual read bytes //! //! \return Returns the error status, as one of //! \n \b HID_DEVICE_SUCCESS //! \n \b HID_DEVICE_NOT_OPENED //! \n \b HID_DEVICE_TRANSFER_TIMEOUT //! \n \b HID_DEVICE_TRANSFER_FAILED // //****************************************************************************** BYTE HID_ReadFile(struct strHidDevice* pstrHidDevice, BYTE* buffer, DWORD bufferSize, DWORD* bytesReturned); //****************************************************************************** // //! \brief Registers a device for program Windows notification. //! //! Registers the window pointed to by handle hWnd to receive //! notification when devices are added or removed from the system. //! //! \param hWnd Windows handle //! \param diNotifyHandle Device notification handle pointer address //! //! \return Returns the error status, as one of //! \n \b HID_DEVICE_SUCCESS //! \n \b HID_DEVICE_HANDLE_ERROR // //****************************************************************************** BYTE HID_RegisterForDeviceNotification(HWND hWnd, HDEVNOTIFY* diNotifyHandle); //****************************************************************************** // //! \brief Un-Registers a device from Windows notification. //! //! Un-registers the window pointed to by handle hWnd to receive //! notification when devices are added or removed from the system. //! //! \param diNotifyHandle: Device notification handle pointer address. //! //! \return Returns the error status, as one of //! \n \b HID_DEVICE_SUCCESS //! \n \b HID_DEVICE_HANDLE_ERROR // //****************************************************************************** BYTE HID_UnRegisterForDeviceNotification(HDEVNOTIFY* diNotifyHandle); //****************************************************************************** // //! \brief Writes a data stream to the given HID device. //! //! Needed report IDs will be generated automatically. //! //! \param pstrHidDevice Structure which contains important data of an HID //! device //! \param buffer Buffer which will be send //! \param bufferSize Number of bytes to send //! //! \return Returns the error status, as one of //! \n \b HID_DEVICE_SUCCESS //! \n \b HID_DEVICE_NOT_OPENED //! \n \b HID_DEVICE_TRANSFER_TIMEOUT //! \n \b HID_DEVICE_TRANSFER_FAILED // //****************************************************************************** BYTE HID_WriteFile(struct strHidDevice* pstrHidDevice, BYTE* buffer, DWORD bufferSize);
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、付费专栏及课程。

余额充值