蓝牙HID无线触摸屏

蓝牙HID无线触摸屏写在前面主机 Android5 0 内核 3 4 从机 SensorTile 先上一个效果图原理解析 HID 事件到 Android 屏幕上经历发如下过程 HID amp gt linuxkerneli 子系统 amp gt Androidinput 子系统 HID 是标准的输入协议 对于不同的操作系统而言 也有自己的 input 子系统 Android 层要求

写在前面

原理解析

HID事件到Android屏幕上经历了如下过程:

HID => linux kernel input子系统 => Android input子系统

HID是标准的输入协议,对于不同的操作系统而言,也有自己的input子系统。

Android层要求

以Android为例,如果要想让Android系统认为一个输入设备是一个触摸屏,需要该内核设备上报:

// 对于单点触控而言 ABS_X ABS_Y 和 BTN_TOUCH // 对于多点触控而言 ABS_MT_POSITION_X 和 ABS_MT_POSITION_Y 绝对轴 以及 BTN_TOUCH

且需要一个配置文件放到/system/usr/idc/中,如/system/usr/idc/HID.idc,内容如下指定其为触摸屏设备类型:

touch.deviceType = touchScreen

注:标明输入设备为触摸屏还有一个方法输入设备报告存在 INPUT_PROP_DIRECT 输入属性,但是对于蓝牙HID而言,在Android中的实现是基于uhid实现的,要这样做比较难,所以一般会使用放配置文件的方式。输入设备上报的键值和输入属性可以使用getevent -i查看。
理论依据来自:https://source.android.com/devices/input/touch-devices

内核层要求

Android层要求中提到的ABS_X ABS_Y 和 BTN_TOUCH等等都是需要内核去上报的键值,内核中就需要要求HID设备按照一定要求上传HID键值,因为内核键值是由HID键值转换过来的。

// drivers/hid/hid-input.c case HID_UP_DIGITIZER: switch (usage->hid & 0xff) { case 0x00: /* Undefined */ goto ignore; case HID_DG_TIPPRESSURE: /* TipPressure */ if (!test_bit(BTN_TOUCH, input->keybit)) { device->quirks |= HID_QUIRK_NOTOUCH; set_bit(EV_KEY, input->evbit); set_bit(BTN_TOUCH, input->keybit); } map_abs_clear(ABS_PRESSURE); break; case HID_DG_INRANGE: /* InRange */ switch (field->physical & 0xff) { case 0x21: map_key(BTN_TOOL_MOUSE); break; case 0x22: map_key(BTN_TOOL_FINGER); break; default: map_key(BTN_TOOL_PEN); break; } break; case HID_DG_INVERT: /* Invert */ map_key_clear(BTN_TOOL_RUBBER); break; case HID_DG_TOUCH: /* Touch */ case HID_DG_TIPSWITCH: /* TipSwitch */ case HID_DG_TIPSWITCH2: /* TipSwitch2 */ device->quirks &= ~HID_QUIRK_NOTOUCH; map_key_clear(BTN_TOUCH); break; case HID_DG_BARRELSWITCH: /* BarrelSwitch */ map_key_clear(BTN_STYLUS); break; case HID_DG_TABLETPICK: /* TabletPick */ map_key_clear(BTN_STYLUS2); break; case HID_DG_CONTACTID: /* ContactID */ device->quirks |= HID_QUIRK_MULTITOUCH; goto unknown; default: goto unknown; }
 0x05, 0x0d, // USAGE_PAGE (Digitizers) 0x09, 0x04, // USAGE (Touch Screen) 0xa1, 0x01, // COLLECTION (Application) 0x85, 0x01, // REPORT_ID (Touch) 0x09, 0x20, // USAGE (Stylus) 0xa1, 0x00, // COLLECTION (Physical) 0x09, 0x42, // USAGE (Tip Switch) 0x15, 0x00, // LOGICAL_MINIMUM (0) 0x25, 0x01, // LOGICAL_MAXIMUM (1) 0x75, 0x01, // REPORT_SIZE (1) 0x95, 0x01, // REPORT_COUNT (1) 0x81, 0x02, // INPUT (Data,Var,Abs) 0x95, 0x03, // REPORT_COUNT (3) 0x81, 0x03, // INPUT (Cnst,Ary,Abs) // 0x09, 0x32, // USAGE (In Range) // 0x09, 0x47, // USAGE (Confidence) // 0x95, 0x02, // REPORT_COUNT (1) // 0x81, 0x02, // INPUT (Data,Var,Abs) // 0x95, 0x0a, // REPORT_COUNT (10) // 0x81, 0x03, // INPUT (Cnst,Ary,Abs) 0x05, 0x01, // USAGE_PAGE (Generic Desktop) 0x26, 0xff, 0x7f, // LOGICAL_MAXIMUM (32767) 0x75, 0x10, // REPORT_SIZE (16) 0x95, 0x01, // REPORT_COUNT (1) 0xa4, // PUSH 0x55, 0x0d, // UNIT_EXPONENT (-3) 0x65, 0x00, // UNIT (None) 0x09, 0x30, // USAGE (X) 0x35, 0x00, // PHYSICAL_MINIMUM (0) 0x46, 0x00, 0x00, // PHYSICAL_MAXIMUM (0) 0x81, 0x02, // INPUT (Data,Var,Abs) 0x09, 0x31, // USAGE (Y) 0x46, 0x00, 0x00, // PHYSICAL_MAXIMUM (0) 0x81, 0x02, // INPUT (Data,Var,Abs) 0xb4, // POP // 0x05, 0x0d, // USAGE PAGE (Digitizers) // 0x09, 0x48, // USAGE (Width) // 0x09, 0x49, // USAGE (Height) // 0x95, 0x02, // REPORT_COUNT (2) // 0x81, 0x02, // INPUT (Data,Var,Abs) // 0x95, 0x01, // REPORT_COUNT (1) // 0x81, 0x03, // INPUT (Cnst,Ary,Abs) 0xc0, // END_COLLECTION 0xc0, // END_COLLECTION

使用uhid来测试该描述符,测试代码,确实可以实现触摸屏的效果了。
注:对于多点触摸设备,那么描述符中需要包含HID_DG_CONTACTID即可,这里先不展开分析。

蓝牙HID从机

这里使用的是ST的SensorTile,根据其提供的HID的Demo,修改对应的成对应的描述符,并在while循环里实现一个从左上角滑动到右下角的模拟操作,这样就可以实现通过蓝牙HID触摸屏了。
具体的改动见:https://gitee.com/kangear/STM32CubeExpansion_BLE1_V2.8.0/commit/04e5e0af893c1099d1ce5d3658e6d

展望

目前实现了单点触摸屏,稍候会另起一个文章,讲述如何实现多点触摸屏,到那时才会是真正的蓝牙HID触摸屏。能实现之后,可以基于这个实现物理外挂,把手游的一些控制转换成体感游戏等等。

<完>

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/204198.html原文链接:https://javaforall.net

(0)
上一篇 2026年3月19日 下午8:46
下一篇 2026年3月19日 下午8:46


相关推荐

  • latex中希腊字母怎么输入_在电脑上怎么打希腊字母

    latex中希腊字母怎么输入_在电脑上怎么打希腊字母$$\alpha\quad\beta$$%\quad空格的意思$$\gamma\quad\Gamma$$$$\delta\quad\Delta$$$$\theta\quad\Theta$$$$\epsilon\quad\pi$$$$\Pi\quad\omega$$$$\Omega$$

    2022年10月13日
    4
  • 菜鸟的springboot常用注解总结

    菜鸟的springboot常用注解总结菜鸟的 springboot 常用注解总结说明 SpringBootAp Component Service Controller Repository ResponseBody RestControll AutoWired 说明更新时间 2020 7 1417 32 更新了整体内容本文主要对网上的 springboot 常见注解和自己本人在学习的过程中遇到的注解的一次总结 本文会持续更新 不断地扩充本文仅为记录学习轨迹 如有侵权 联系删除 SpringBootAp

    2026年3月26日
    4
  • html使用vue axios,使用 Vue和axios

    html使用vue axios,使用 Vue和axios昨天写完了博客以后,有人就在我的博客下面留言说现在不是使用了Axios了吗?我赶紧再把Axios的例程给补上,并且做一个更新。其实vue-resource并不复杂,就是不稳定。Vue官方放弃它也是对的,作者是这样子说的最近团队讨论了一下,Ajax本身跟Vue并没有什么需要特别整合的地方,使用fetchpolyfill或是axios、superagent等等都可以起到同等…

    2025年6月29日
    4
  • datetimepicker常用方法

    datetimepicker常用方法1 首先引用资源包 nbsp nbsp bootstrap 基础资源包 bootstrap min css bootstrap responsive min css style css jquery 1 10 1 min js nbsp datetimepick 资源包 bootstrap datetimepick min css bootstrap datetimepick min js

    2026年3月18日
    2
  • 箱体图_原理图和箱体图

    箱体图_原理图和箱体图多组维度不一样长的箱体图的画法

    2022年8月6日
    8
  • Verycd网站中不能显示下载网址的解决办法[通俗易懂]

    Verycd网站中不能显示下载网址的解决办法[通俗易懂]在verycd.com搜索资源的时候,有时候一些权利资源会出现“该内容尚未提供权利证明,无法提供下载”的版权声明。当你急着找这些资源的话,出现这个问题肯定非常烦人的,那该如何解决呢?方法其实很简单。方法0:安装浏览器Verycd链接显示的插件火狐的插件地址(安装这个插件后,可以直接在verycd上看到下载地址):https://addons.mozilla.org/zh-TW/fire

    2022年8月10日
    10

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号