Linux gadget 模拟触控屏 支持多点触控

news2024/12/22 15:27:40

通过gadget命令行生成hid设备

下面xxx自己根据需要修改,例如VID,PID,产品名称


const char *INSTALL_GADGET_CMDS[] = {
    "modprobe libcomposite",

    "mkdir /sys/kernel/config/usb_gadget/g1",

    "echo 'xxx' > /sys/kernel/config/usb_gadget/g1/idVendor",
    "echo 'xxx' > /sys/kernel/config/usb_gadget/g1/idProduct",

    "mkdir /sys/kernel/config/usb_gadget/g1/strings/0x409",                                  // 设备信息目录
    "echo 'xxx' > /sys/kernel/config/usb_gadget/g1/strings/0x409/serialnumber", // 产品序列号
    "echo 'xxx' > /sys/kernel/config/usb_gadget/g1/strings/0x409/manufacturer",             // 产品制造商
    "echo 'xxx' > /sys/kernel/config/usb_gadget/g1/strings/0x409/product",            // 产品名字

    "mkdir /sys/kernel/config/usb_gadget/g1/configs/c.1", // 配置目录
    "mkdir /sys/kernel/config/usb_gadget/g1/configs/c.1/strings/0x409",
    "echo 'config' > /sys/kernel/config/usb_gadget/g1/configs/c.1/strings/0x409/configuration",
    "echo 0x80 > /sys/kernel/config/usb_gadget/g1/configs/c.1/bmAttributes",
    "echo 100 > /sys/kernel/config/usb_gadget/g1/configs/c.1/MaxPower",

    // 下面这些functions下的目配置都是接口描述符配置,一个目录是一个接口

    // Touchscreen
    "mkdir -p /sys/kernel/config/usb_gadget/g1/functions/hid.usb0", // 功能描述
    "echo 1 > /sys/kernel/config/usb_gadget/g1/functions/hid.usb0/subclass",
    "echo 0 > /sys/kernel/config/usb_gadget/g1/functions/hid.usb0/protocol",
    "echo 12 > /sys/kernel/config/usb_gadget/g1/functions/hid.usb0/report_length", // hid report max size
    "echo '050d0904a1018501050d0922a102050d9501750609511500253f810209422501750195018102750195018103050195017510550e65110930260040350046a6148142093126004046a40b8142c0050d0922a102050d9501750609511500253f810209422501750195018102750195018103050195017510550e65110930260040350046a6148142093126004046a40b8142c0050d0954257f95017508810285020955250a75089501b102c0' | xxd " XXD_ARGS " > /sys/kernel/config/usb_gadget/g1/functions/hid.usb0/report_desc", // hid desc
    "ln -s /sys/kernel/config/usb_gadget/g1/functions/hid.usb0 /sys/kernel/config/usb_gadget/g1/configs/c.1", // 关联配置和功能文件
    "ls /sys/class/udc > /sys/kernel/config/usb_gadget/g1/UDC", // 启动设备
};

const char *UNINSTALL_GADGET_CMDS[] = {
    "echo '' > /sys/kernel/config/usb_gadget/g1/UDC",

    "rm /sys/kernel/config/usb_gadget/g1/configs/c.1/hid.usb0",
    "rmdir /sys/kernel/config/usb_gadget/g1/configs/c.1/strings/0x409",
    "rmdir /sys/kernel/config/usb_gadget/g1/configs/c.1",
    "rmdir /sys/kernel/config/usb_gadget/g1/functions/hid.usb0",
    "rmdir /sys/kernel/config/usb_gadget/g1/strings/0x409",
    "rmdir /sys/kernel/config/usb_gadget/g1",
};

里面很长的那个字符串,是hid报告描述符,下面详细讲。

hid报告描述符

把上面hid报告描述符贴到 https://www.usbzh.com/tool/usb.html,可以分析出结构,我已经在关键位置加了注释。

0x05, 0x0D,        // Usage Page (Digitizer)
0x09, 0x04,        // Usage (Touch Screen)	//触控屏
	0xA1, 0x01,        // Collection (Application)	//每一个collection相当于c++里面的花括号,里面是一个集合
	0x85, 0x01,        //   Report ID (1)
	0x05, 0x0D,        //   Usage Page (Digitizer)
	0x09, 0x22,        //   Usage (Finger)
		//下面是一个触控点的数据包,也就是第一个手指
		0xA1, 0x02,        //   Collection (Logical)	//这里主要描述到时候上报数据的数据格式,例如触控id/坐标xy,占用几个bit这些信息
			0x05, 0x0D,        //     Usage Page (Digitizer)
			0x95, 0x01,        //     Report Count (1)  一段
			0x75, 0x06,        //     Report Size (6)	每段占用6个bit
			0x09, 0x51,        //     Usage (Contact Identifier)	每个触控点的触控ID
			0x15, 0x00,        //     Logical Minimum (0)	最小值
			0x25, 0x3F,        //     Logical Maximum (63)	最大值
			0x81, 0x02,        //     Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position) 需要用户输出
			
			0x09, 0x42,        //     Usage (Tip Switch)	这个点是按下还是松开
			0x25, 0x01,        //     Logical Maximum (1) 最大值1,前面定义了最小是0
			0x75, 0x01,        //     Report Size (1)	每段占用1bit
			0x95, 0x01,        //     Report Count (1)	一段
			0x81, 0x02,        //     Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position) 需要用户输入
			
			0x75, 0x01,        //     Report Size (1) 	每段占用1bit
			0x95, 0x01,        //     Report Count (1)	一段
			0x81, 0x03,        //     Input (Const,Var,Abs,No Wrap,Linear,Preferred State,No Null Position) const值,需要用户输入
			//上面 6+1+1刚好一个byte
			
			0x05, 0x01,        //     Usage Page (Generic Desktop Ctrls)
			0x95, 0x01,        //     Report Count (1)	一段
			0x75, 0x10,        //     Report Size (16)	每段占用16bit
			0x55, 0x0E,        //     Unit Exponent (-2)
			0x65, 0x11,        //     Unit (System: SI Linear, Length: Centimeter)
			0x09, 0x30,        //     Usage (X)		x坐标
			0x26, 0x00, 0x40,  //     Logical Maximum (16384)
			0x35, 0x00,        //     Physical Minimum (0)
			0x46, 0xA6, 0x14,  //     Physical Maximum (5286)
			0x81, 0x42,        //     Input (Data,Var,Abs,No Wrap,Linear,Preferred State,Null State)	用户输入
			
			0x09, 0x31,        //     Usage (Y)	y坐标
			0x26, 0x00, 0x40,  //     Logical Maximum (16384)
			0x46, 0xA4, 0x0B,  //     Physical Maximum (2980)
			0x81, 0x42,        //     Input (Data,Var,Abs,No Wrap,Linear,Preferred State,Null State)	用户输入
			//上面是xy坐标,每个占用2byte
		0xC0,              //   End Collection
		//下面也是一个触控点的数据包,也就是第二个手指,可以定义多个手指,这里只会影响一次发送给主机多少个数据,不影响多点触控
		//如果你10点同时触控,定义了两个手指,就会2-2-2-2-2发5次包,每次发两个手指,不影响多点触控
		0x05, 0x0D,        //   Usage Page (Digitizer)
		0x09, 0x22,        //   Usage (Finger)
			0xA1, 0x02,        //   Collection (Logical)
				0x05, 0x0D,        //     Usage Page (Digitizer)
				0x95, 0x01,        //     Report Count (1)
				0x75, 0x06,        //     Report Size (6)
				0x09, 0x51,        //     Usage (0x51)
				0x15, 0x00,        //     Logical Minimum (0)
				0x25, 0x3F,        //     Logical Maximum (63)
				0x81, 0x02,        //     Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
				0x09, 0x42,        //     Usage (Tip Switch)
				0x25, 0x01,        //     Logical Maximum (1)
				0x75, 0x01,        //     Report Size (1)
				0x95, 0x01,        //     Report Count (1)
				0x81, 0x02,        //     Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
				0x75, 0x01,        //     Report Size (1)
				0x95, 0x01,        //     Report Count (1)
				0x81, 0x03,        //     Input (Const,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
				0x05, 0x01,        //     Usage Page (Generic Desktop Ctrls)
				0x95, 0x01,        //     Report Count (1)
				0x75, 0x10,        //     Report Size (16)
				0x55, 0x0E,        //     Unit Exponent (-2)
				0x65, 0x11,        //     Unit (System: SI Linear, Length: Centimeter)
				0x09, 0x30,        //     Usage (X)
				0x26, 0x00, 0x40,  //     Logical Maximum (16384)
				0x35, 0x00,        //     Physical Minimum (0)
				0x46, 0xA6, 0x14,  //     Physical Maximum (5286)
				0x81, 0x42,        //     Input (Data,Var,Abs,No Wrap,Linear,Preferred State,Null State)
				0x09, 0x31,        //     Usage (Y)
				0x26, 0x00, 0x40,  //     Logical Maximum (16384)
				0x46, 0xA4, 0x0B,  //     Physical Maximum (2980)
				0x81, 0x42,        //     Input (Data,Var,Abs,No Wrap,Linear,Preferred State,Null State)
			0xC0,              //   End Collection
	//下面是其他信息,安卓主机不需要这些信息也能正常多点触控,可是windows主机就一定需要这些
	0x05, 0x0D,        //   Usage Page (Digitizer)
	0x09, 0x54,        //   Usage (Contact Count)	//这一帧总共多少个触控点
	0x25, 0x7F,        //   Logical Maximum (127)
	0x95, 0x01,        //   Report Count (1)
	0x75, 0x08,        //   Report Size (8)		8bit
	0x81, 0x02,        //   Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)	需要用户输入
	
	0x85, 0x02,        //   Report ID (2)
	0x09, 0x55,        //   Usage (Contact Count Maximum)	//最大支持多少点触控,这个很重要,没有这个你发多少个点去windows都不响应
	0x25, 0x0A,        //   Logical Maximum (10)	
	0x75, 0x08,        //   Report Size (8)	8bit
	0x95, 0x01,        //   Report Count (1)
	0xB1, 0x02,        //   Feature (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile) 特性描述,这个下面详细分析
0xC0,              // End Collection

// 171 bytes

发送数据

按照上面的报告描述符,我们上报触控点的数据应该如下

buf[0]:报告ID
buf[1]:第一点ID(6) + 第一点触摸状态(bit 6):有触摸为1,无触摸为0,bit7不用管
buf[2]:第一点X坐标低8位
buf[3]:第一点X坐标高8位
buf[4]:第一点Y坐标低8位
buf[5]:第一点Y坐标高8位
buf[6]:第二点ID + 第二点触摸状态:有触摸为1,无触摸为0
buf[7]:第二点X坐标低8位
buf[8]:第二点X坐标高8位
buf[9]:第二点Y坐标低8位
buf[10]:第二点Y坐标高8位
buf[11]:第一个报告最后一个字节表示有效的触摸点数(包含按下状态和第一次松开),其他报告最后一个字节为0

可以看到这个buf长度12,也就是我们上面gadget配置的,这两个要对应,不然HID交互会异常

"echo 12 > /sys/kernel/config/usb_gadget/g1/functions/hid.usb0/report_length", // hid report max size

Windows支持多点触控

对于Windows支持多点触控,官网有详细描述:
https://learn.microsoft.com/zh-cn/windows-hardware/design/component-guidelines/touchscreen-required-hid-top-level-collections

在这里插入图片描述
在这里插入图片描述
所以最大触摸点数量的特性报告是必须要的

可是按上面报告描述符写了Contact Count Maximum,逻辑最大值10,windows还是不支持多点响应
0x25, 0x0A, // Logical Maximum (10)

通过Bus Hound抓包分析,左边是增加Contact Count Maximum描述的,右边是没有Contact Count Maximum描述的,
左边主机会发送一个GET REPORT包给设备,设备回复了00 00。
在这里插入图片描述
我猜测逻辑是:设备报告描述符里面有最大支持点数特性,所以主机询问设备支持多少点,设备需要回复值。可是我们设备回复了0,所以就不支持多点了,单点都不支持了。
找了个正常支持多点触控的平台,抓出来包如下,别人真的回复了02 0a,02就是报告ID,0a就是10点触控。证实了我的猜想。
在这里插入图片描述

如何发送这个最大支持点数?

由于我的代码使用的是命令行 gadget初始化设备,网上找了很久都没找到应用层如何设置这个回复包。
最后是在kernel代码里面,这个文件找到了回复逻辑
在这里插入图片描述
可以看到hid收到 HID_REQ_GET_REPORT 包后,直接回复了个全0的包。我不知道为什么kernel的逻辑这样写。
尝试把这里改成回复 02 0a,主机就响应多点了!!!

但是肯定不能直接这样改,现在定位到问题了,就是这个包如何回复,如何能在应用层回复。
继续研究,有知道的朋友可以评论区提点下。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2183592.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

github项目--crawl4ai

github项目--crawl4ai 输出html输出markdown格式输出结构化数据与BeautifulSoup的对比 crawl4ai github上这个项目,没记错的话,昨天涨了3000多的star,今天又新增2000star。一款抓取和解析工具,简单写个demo感受下 这里我们使用cra…

衡水中学资料大全-重构版(状元、学霸笔记)

文章目录 一、衡水中学:教育界的璀璨明珠二、状元笔记:学霸的智慧传承三、学霸笔记:高效学习的秘籍四、全面复习资料:覆盖所有考点五、思维导图:构建知识框架六、获取方式 一、衡水中学:教育界的璀璨明珠 …

【React】入门Day01 —— 从基础概念到实战应用

目录 一、React 概述 二、开发环境创建 三、JSX 基础 四、React 的事件绑定 五、React 组件基础使用 六、组件状态管理 - useState 七、组件的基础样式处理 快速入门 – React 中文文档 一、React 概述 React 是什么 由 Meta 公司开发,是用于构建 Web 和原生…

语音转文字免费利器:助力高效办公与学习

语音转文字免费的软件如同一股清流,让我们能够更轻松地将语音信息转化为可编辑的文字内容。今天我们一起来分析它们的功能、特点以及如何为我们的生活和工作带来便利。 1.365在线转文字 链接直达:https://www.pdf365.cn/ 这是一个功能强大的在线工具…

网站集群批量管理-密钥认证与Ansible模块

一、集群批量管理-密钥认证 1、概述 管理更加轻松:两个节点,通过密钥形式进行访问,不需要输入密码,仅支持单向. 服务要求(应用场景): 一些服务在使用前要求我们做秘钥认证.手动写批量管理脚本. 名字: 密钥认证,免密码登录,双机互信. 2、原理 税钥对…

MySQL 的复制延迟:理解与解决方案

一、什么是 MySQL 的复制延迟? 在 MySQL 数据库中,复制是一种将数据从一个数据库服务器(主服务器)复制到一个或多个数据库服务器(从服务器)的机制。复制延迟指的是主服务器上的数据更改与这些更改在从服务…

DBeaver显示PostgreSQL数据库的信息模式

DBeaver连接PostgreSQL数据库后,默认情况下是不加载信息模式的,如果有需要,我们可以通过设置显示信息模式。 具体步骤:点击数据库连接–>右键打开设置–>连接设置–>常规–>导航视图–>自定义–>勾选显示系统对…

Python 基于 flask 的前程无忧招聘可视化系统,Python大数据招聘爬虫可视化分析

博主介绍:✌程序员徐师兄、7年大厂程序员经历。全网粉丝12w、csdn博客专家、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ 🍅文末获取源码联系🍅 👇🏻 精彩专栏推荐订阅👇…

springboot的调度服务与异步服务实操

1.调度服务 1.1.JDK之ScheduledExecutorService 讲到调度任务,我们脑海里马上会想到ScheduledExecutorService。 ScheduledExecutorService是 Java java.util.concurrent 包中的一个接口,它继承自 ExecutorService 接口。它主要用于在给定的延迟后运行…

计算机毕业设计Python+Spark知识图谱微博舆情预测 微博推荐系统 微博可视化 微博数据分析 微博大数据 微博爬虫 Hadoop 大数据毕业设计

《PythonSpark知识图谱微博舆情预测》开题报告 一、课题背景与意义 随着互联网技术的飞速发展,社交媒体平台如微博已成为人们表达观点、交流信息的重要渠道。微博每天产生海量的数据,这些数据中蕴含着丰富的社会情绪、事件动态等信息,对于政…

从概念到使用全面了解Llama 3 这个迄今为止最强大的开源模型

概述 mate最近发布了 Llama3,下一代最先进的开源大语言模型(LLM)。正如本文的综合评论所述,Llama 3 以其前身奠定的基础为基础,旨在增强 Llama 2 成为 ChatGPT 重要开源竞争对手的能力 Llama 2:深入探讨 C…

【更新】红色文化之红色博物馆数据集(经纬度+地址)

数据简介:红色博物馆作为国家红色文化传承与爱国主义教育的重要基地,遍布全国各地,承载着丰富的革命历史与文化记忆。本数据说明旨在汇总并分析全国范围内具有代表性的红色博物馆的基本信息,包括其地址、特色及教育意义&#xff0…

Scrapy框架入门

一、Scrapy简介 Scrapy是一款快速而强大的web爬虫框架,基于Twisted的异步处理框架、Twisted是事件驱动的。 Scrapy是由python实现的爬虫框架:架构清晰、可扩展性强、可以灵活完成需求。 一、Scrapy应用 scrapy及其他模块的安装 pip3 install scrapy…

【Java编程系列】使用java接入Microsoft Graph,实现发送邮件功能

1、前言 微软与2022年10月1号,开始停止了部分服务的 basic auth (账密登录)功能,需要改用 oauth2.0 协议接入相应服务。邮件方面主要在于IMAP和pop协议。并且与2023年1月1日时,正式全面停止账密登录使用去接入上述服务…

【Python报错已解决】[notice] A new release of pip available: 22.2 -> 22.2.2

🎬 鸽芷咕:个人主页 🔥 个人专栏: 《C干货基地》《粉丝福利》 ⛺️生活的理想,就是为了理想的生活! 专栏介绍 在软件开发和日常使用中,BUG是不可避免的。本专栏致力于为广大开发者和技术爱好者提供一个关于BUG解决的经…

共享单车轨迹数据分析:以厦门市共享单车数据为例(九)

副标题:基于站点800m范围内评价指标探究——以吕厝站为例 上篇文章我们以厦门市为例,来通过POI和优劣解距离法(TOPSIS)来研究厦门岛内以800m作为辐射范围的地铁站哪些地铁站发展的最好,根据综合得分指数可以知道&…

架构设计笔记-5-软件工程基础知识-2

知识要点 构件组装是将库中的构件经适当修改后相互连接,或者将它们与当前开发项目中的软件元素连接,最终构成新的目标软件。 构件组装技术大体可分为: 1. 基于功能的组装技术:基于功能的组装技术采用子程序调用和参数传递的方式将构件组装起来。它要求库中的构件以子程序…

KPaaS集成平台与传统集成有什么不同?

企业的业务系统越来越复杂,集成需求也日益增长,同时也面临着如何高效、低成本地实现多系统集成的挑战。传统集成方式虽然能够提供高度定制化的解决方案,但其高昂的成本、复杂的实施过程以及后续的维护难题却让许多企业望而却步。在这样的背景…

【Python报错已解决】KeyError: ‘key‘

🎬 鸽芷咕:个人主页 🔥 个人专栏: 《C干货基地》《粉丝福利》 ⛺️生活的理想,就是为了理想的生活! 专栏介绍 在软件开发和日常使用中,BUG是不可避免的。本专栏致力于为广大开发者和技术爱好者提供一个关于BUG解决的经…

Nginx基础详解4(location模块、nginx跨域问题的解决、nginx防盗链的设计原理及应用、nginx模块化解剖)

续Nginx基础详解3(nginx.conf核心代码讲解、常用命令解析、Nginx日志切割)-CSDN博客 目录 10.location模块详解 10.1默认匹配规则‘ /’ 10.2精确匹配规则‘/’ 10.3正则表达式‘~* \’ 10.4精确正则匹配~ \ 10.5路径匹配‘^~ /’ 11.nginx中解决…