基于富芮坤fr8016 蓝牙5.0 芯片设计的BLE HID Joystick 游戏摇杆设备

2023-10-30

ble hid 学习笔记

HID报告描述符与BLE HID profile之间关系

​ 说起BLE HID(Human Interface Device)设备,就不得不提USB HID。我的理解HID 读写报告属于传输层,所以BLE和USB在关于HID协议的规定都是一样的,运输层的通信不关心底层是通过蓝牙传还是USB传输。能研究BLE HID的朋友一定明白BLE通信是通过读写GATT属性表中的特征值实现的,同样HID是基于BLE实现的,所以HID协议中的读写报告,是基于BLE属性表中特征值实现的。蓝牙联盟已经替大家想好了,推出了HID profile规范,这个规范规定了BLE HID 模型是啥样的,大家都执行这个标准就可以互通往来了。

1、HID报告描述符

​ HID类设备定义连接https://usb.org/sites/default/files/hid1_11.pdf

​ 一个报告以说USAGE_PAGE和USAGE开头 COLLECTION Application 和END_COLLECTION相当于一个大括号里面的内容是对 USAGE进行解释。 一个集合分配是一个报告ID,一个报告描述符内可以有多个集合。也就是可以有多个报告ID。每个集合内最多有3种报告。3种报告对应着input、 output、 feature三种报告。比如下图例子。最先出现的是input 其次是 output 所以这个集合有2个报告,报告顺序是input ,output 。依此类推,整理出整个报告描述符中的3种报告的顺序和数量与GATT HID profile 的report 特征值的一一对应关系。

    0x05, 0x01,     // Usage Pg (Generic Desktop)
    0x09, 0x06,     // Usage (Keyboard)
    0xA1, 0x01,     // Collection: (Application)
//    0x85, 0x03,     // Report Id (3 for keyboard)
    //
    0x05, 0x07,     // Usage Pg (Key Codes)
    0x19, 0xE0,     // Usage Min (224)
    0x29, 0xE7,     // Usage Max (231)
    0x15, 0x00,     // Log Min (0)
    0x25, 0x01,     // Log Max (1)
    //
    // Modifier byte
    0x75, 0x01,     // Report Size (1)   1 bit * 8
    0x95, 0x08,     // Report Count (8)
    0x81, 0x02,     // Input: (Data, Variable, Absolute)

    // Reserved byte
    0x95, 0x01, // Report Count (1)
    0x75, 0x08, // Report Size (8)
    0x81, 0x01, // Input: (Constant)

    //LED repor
    0x95, 0x05,    //Report Count (5)
    0x75, 0x01,    //Report Size (1)
    0x05, 0x08,    //Usage Pg (LEDs )
    0x19, 0x01,    //Usage Min
    0x29, 0x05,    //Usage Max
    0x91, 0x02,    //Output (Data, Variable, Absolute)
    //3 bit reserved
    0x95, 0x01,    //Report Count (1)
    0x75, 0x03,    //Report Size (3)
    0x91, 0x01,    //Output (Constant)

    // Key arrays (6 bytes)
    // this is key array,support simultaneously pressing 6keys report,
    // from report_buf[3]~report_buf[3]
    0x95, 0x06,     // Report Count (6)
    0x75, 0x08,     // Report Size (8)
    0x15, 0x00,     // Log Min (0)
    0x25, 0xE7,     // Log Max (237)
    0x05, 0x07,     // Usage Pg (Key Codes) , here is the key page,look usb hid key define
    0x19, 0x00,     // Usage Min (0)
    0x29, 0xE7,     // Usage Max (237)
    0x81, 0x00,     // Input: (Data, Array)
    0xC0,            // End Collection

富芮坤fr8016 设计Joystick例子

​ 使用富芮坤FR8016H 蓝牙5,0芯片,做一个蓝牙Joystick,Joystick有3个轴分别是X、Y、Z3个轴,加上8个按钮。每个轴对应一个字节,一个按钮对应一个比特所以8个按钮对应1个字节。所以输入报告需要4个字节。

数据结构如下所示:

在这里插入图片描述

1、描述X轴Y轴Z轴

​ 在报告描述符中,一个项目必须包含三个字段, 定义3轴:

//(Generic Desktop)  详细解释上摇杆上的3个轴属于桌面设备
    0x09, 0x30,                    //     USAGE (X)  定义一个X轴
    0x09, 0x31,                    //     USAGE (Y)  定义一个Y轴
    0x09, 0x32,                    //     USAGE (Z)  定义一个Z轴

​ 每个轴的逻辑范围 最小-127 最大12

  0x15, 0x81,                    //     LOGICAL_MINIMUM (-127)  对3个轴进行规范 逻辑最小值为-127
    0x25, 0x7f,                    //     LOGICAL_MAXIMUM (127)   对3个轴进行规范 逻辑最大值为127

用3个字节表示3个轴

	//报告大小为8bit 有符号 对应-127 到127
    0x75, 0x08,                    //     REPORT_SIZE (8)
    0x95, 0x03,                    //     REPORT_COUNT (3)  3个轴总共有3个字节

发送这3个轴数据到电脑:

3个轴总共有3个字节
    0x81, 0x02,                    //     INPUT (Data,Var,Abs) 报告为输入,变量,值,绝对值。

3个轴最终描述

    0x05, 0x01,                    //     USAGE_PAGE (Generic Desktop)  详细解释上摇杆上的3个轴属于桌面设备
    0x09, 0x30,                    //     USAGE (X)  定义一个X轴
    0x09, 0x31,                    //     USAGE (Y)  定义一个Y轴
    0x09, 0x32,                    //     USAGE (Z)  定义一个Z轴
	
    0x15, 0x81,                    //     LOGICAL_MINIMUM (-127)  对3个轴进行规范 逻辑最小值为-127
    0x25, 0x7f,                    //     LOGICAL_MAXIMUM (127)   对3个轴进行规范 逻辑最大值为127
	
	//报告大小为8bit 有符号 对应-127 到127
    0x75, 0x08,                    //     REPORT_SIZE (8)
    0x95, 0x03,                    //     REPORT_COUNT (3)  3个轴总共有3个字节
    0x81, 0x02,                    //     INPUT (Data,Var,Abs) 报告为输入,变量,值,绝对值。

2、描述按钮

​ 定义8个按钮

	  0x05, 0x09,                    //     USAGE_PAGE (Button)  详细解释 摇杆上有按钮 
    0x19, 0x01,                    // 		USAGE_MINIMUM (Button 1) 定义最小按钮 
    0x29, 0x08,                    // 		USAGE_MAXIMUM (Button 8) 定义最大按钮 	

每个按钮的状态有2种 0 和1

// 对8个按钮进行规范 逻辑最小值为0
    0x25, 0x01,                    //     LOGICAL_MAXIMUM (1) 对8个按钮进行规范 逻辑最大值为1
    0x95, 0x08,                    //     REPORT_COUNT (8)  8个按钮总共有1个字节  最小按钮到最大按钮对应低到高bit位

用1个字节表示8个按钮

    0x75, 0x01,                    //     REPORT_SIZE (1)  8个按钮总共1个字节
    0x81, 0x02,                    //     INPUT 

最为输入报告发送到电脑上

    0x81, 0x02,                    //     INPUT (Data,Var,Abs)  报告为输入,变量,值,绝对值。

​ 最终的按钮表示方式

	  0x05, 0x09,                    //     USAGE_PAGE (Button)  详细解释 摇杆上有按钮 
    0x19, 0x01,                    // 		USAGE_MINIMUM (Button 1) 定义最小按钮 
    0x29, 0x08,                    // 		USAGE_MAXIMUM (Button 8) 定义最大按钮 	
    0x15, 0x00,                    //     LOGICAL_MINIMUM (0) 对8个按钮进行规范 逻辑最小值为0
    0x25, 0x01,                    //     LOGICAL_MAXIMUM (1) 对8个按钮进行规范 逻辑最大值为1
    0x95, 0x08,                    //     REPORT_COUNT (8)  8个按钮总共有1个字节  最小按钮到最大按钮对应低到高bit位
    0x75, 0x01,                    //     REPORT_SIZE (1)  8个按钮总共1个字节
    0x81, 0x02,                    //     INPUT (Data,Var,Abs)  报告为输入,变量,值,绝对值。

3个轴和8个按钮合并一起

  0x05, 0x01,                    //     USAGE_PAGE (Generic Desktop)  详细解释上摇杆上的3个轴属于桌面设备
    0x09, 0x30,                    //     USAGE (X)  定义一个X轴
    0x09, 0x31,                    //     USAGE (Y)  定义一个Y轴
    0x09, 0x32,                    //     USAGE (Z)  定义一个Z轴
	
    0x15, 0x81,                    //     LOGICAL_MINIMUM (-127)  对3个轴进行规范 逻辑最小值为-127
    0x25, 0x7f,                    //     LOGICAL_MAXIMUM (127)   对3个轴进行规范 逻辑最大值为127
	
	//报告大小为8bit 有符号 对应-127 到127
    0x75, 0x08,                    //     REPORT_SIZE (8)
    0x95, 0x03,                    //     REPORT_COUNT (3)  3个轴总共有3个字节
    0x81, 0x02,                    //     INPUT (Data,Var,Abs) 报告为输入,变量,值,绝对值。
		
		
	  0x05, 0x09,                    //     USAGE_PAGE (Button)  详细解释 摇杆上有按钮 
    0x19, 0x01,                    // 		USAGE_MINIMUM (Button 1) 定义最小按钮 
    0x29, 0x08,                    // 		USAGE_MAXIMUM (Button 8) 定义最大按钮 	
    0x15, 0x00,                    //     LOGICAL_MINIMUM (0) 对8个按钮进行规范 逻辑最小值为0
    0x25, 0x01,                    //     LOGICAL_MAXIMUM (1) 对8个按钮进行规范 逻辑最大值为1
    0x95, 0x08,                    //     REPORT_COUNT (8)  8个按钮总共有1个字节  最小按钮到最大按钮对应低到高bit位
    0x75, 0x01,                    //     REPORT_SIZE (1)  8个按钮总共1个字节
    0x81, 0x02,                    //     INPUT (Data,Var,Abs)  报告为输入,变量,值,绝对值。
	

要注意的是即使按照上面的写法电脑还是解析不出来,还要给报告描述符加上个壳用了标记自己是桌面摇杆设备。(TI 可以不写报告ID也能识别到,富芮坤 的SDK 不写报告ID 电脑识别不到)

USAGE_PAGE (Generic Desktop)
USAGE (Joystick)
COLLECTION (Application)
    ``Report Id (1)  
    ``COLLECTION (Physical)
         	//上面的报告描述写到这里    
    ``END COLLECTION
END COLLECTION

3、Joystick 报告描述符

按照上诉要求整理,最后的报告描述符如下所示:

/******************************* HID Report Map characteristic defination */
static const uint8_t hid_report_map[] =
{
	
	
    0x05, 0x01,                    // USAGE_PAGE (Generic Desktop)  开始声明当前设备为 桌面设备
    0x09, 0x04,                    // USAGE (Joystick)						  指明作为一个摇杆设备
	
    //集合相当于括号,必须要以COLLECTION开始 END_COLLECTION结束
    0xa1, 0x01,                    // COLLECTION (Application)
	
    0x85, 0x01,  									 // Report Id (1)   报告ID为1  规范上不写也可以但是实测富芮坤的SDK 不加电脑识别不到
    0xa1, 0x00,                    //   COLLECTION (Physical)

    0x05, 0x01,                    //     USAGE_PAGE (Generic Desktop)  详细解释上摇杆上的3个轴属于桌面设备
    0x09, 0x30,                    //     USAGE (X)  定义一个X轴
    0x09, 0x31,                    //     USAGE (Y)  定义一个Y轴
    0x09, 0x32,                    //     USAGE (Z)  定义一个Z轴
	
    0x15, 0x81,                    //     LOGICAL_MINIMUM (-127)  对3个轴进行规范 逻辑最小值为-127
    0x25, 0x7f,                    //     LOGICAL_MAXIMUM (127)   对3个轴进行规范 逻辑最大值为127
	
	//报告大小为8bit 有符号 对应-127 到127
    0x75, 0x08,                    //     REPORT_SIZE (8)
    0x95, 0x03,                    //     REPORT_COUNT (3)  3个轴总共有3个字节
    0x81, 0x02,                    //     INPUT (Data,Var,Abs) 报告为输入,变量,值,绝对值。
		
		
	  0x05, 0x09,                    //     USAGE_PAGE (Button)  详细解释 摇杆上有按钮 
    0x19, 0x01,                    // 		USAGE_MINIMUM (Button 1) 定义最小按钮 
    0x29, 0x08,                    // 		USAGE_MAXIMUM (Button 8) 定义最大按钮 	
    0x15, 0x00,                    //     LOGICAL_MINIMUM (0) 对8个按钮进行规范 逻辑最小值为0
    0x25, 0x01,                    //     LOGICAL_MAXIMUM (1) 对8个按钮进行规范 逻辑最大值为1
    0x95, 0x08,                    //     REPORT_COUNT (8)  8个按钮总共有1个字节  最小按钮到最大按钮对应低到高bit位
    0x75, 0x01,                    //     REPORT_SIZE (1)  8个按钮总共1个字节
    0x81, 0x02,                    //     INPUT (Data,Var,Abs)  报告为输入,变量,值,绝对值。
	
	
    0xc0,                          //         END_COLLECTION  //关集合,跟上面Physical的对应
    0xc0                           //     END_COLLECTION      //关集合,跟上面Application的对应
	
	
	

};

4、程序修改

​ 富芮坤提供了 ble_hid_kbd_mice demo 在此基础上修改蓝牙的报告描述符,报告特征值数量,即可完整通信。

按照开头的分析方法,分析Joystick报告描述符可知,Joystick需要一个input 报告 这个报告向主机发送4个字节的数据。

所以先报告的数量改成 1

// Number of HID reports defined in the service
#define HID_NUM_REPORTS          1

因为只有一个报告 所以BLE HID profile中多余的报告屏蔽掉,保留一个报告特征值,用于传输HID input 报告。

// HID Feature Report No 0
    [HID_FEATURE_DECL_IDX]          =   { 
                                            { UUID_SIZE_2, UUID16_ARR(GATT_CHARACTER_UUID) },
                                            GATT_PROP_READ, 
                                            0,
                                            NULL,
                                        },
                                        
    [HID_FEATURE_IDX]               =   { 
                                            { UUID_SIZE_2, UUID16_ARR(REPORT_UUID) },
                                            GATT_PROP_READ | GATT_PROP_NOTI,
                                            60,
                                            NULL,
                                        },
                                        
    [HID_REPORT_REF_FEATURE_IDX]    =   { 
                                            { UUID_SIZE_2, UUID16_ARR(GATT_REPORT_REF_UUID) },
                                            GATT_PROP_READ,
                                            sizeof(hid_report_ref_t), 
                                            NULL,
                                        },
                                        
    [HID_FEATURE_CCCD_IDX]          =   { 
                                            { UUID_SIZE_2, UUID16_ARR(GATT_CLIENT_CHAR_CFG_UUID) },
                                            GATT_PROP_READ | GATT_PROP_WRITE, 
                                            0, 
                                            NULL,
                                        },

再修改hid_gatt_add_service中的hid 报告信息数组,因为只有一个输入报告,所以只写一个报告即可。

/*********************************************************************
 * @fn      hid_gatt_add_service
 *
 * @brief   Simple Profile add GATT service function.
 *          添加GATT service到ATT的数据库里面。
 *
 * @param   None.
 *
 *
 * @return  None.
 */
void hid_gatt_add_service(void)
{
    gatt_service_t hid_profie_svc;

    hid_profie_svc.p_att_tb = hid_profile_att_table;
    hid_profie_svc.att_nb = HID_ATT_NB;
    hid_profie_svc.gatt_msg_handler = hid_gatt_msg_handler;


    hid_rpt_info[0].report_id = 1;      //refer to report map, this is Joystick input.
    hid_rpt_info[0].report_type = HID_REPORT_TYPE_INPUT;     //att_table, perm must be GATT_PROP_READ | GATT_PROP_NOTI



    hid_svc_id = gatt_add_service(&hid_profie_svc);
}

最后是发送报告,这里测试发现如果发送报告的数据特别频繁容易导致发送出错,所以这里 程序修改成,当3个轴数据 按钮 和之前不一样则更新数据。

    adc_enable(NULL, NULL, 0);
	adc_get_result(ADC_TRANS_SOURCE_PAD, 0x01, &result);
	 myJoystick.axis_x = 255.00*result/1023;
	adc_get_result(ADC_TRANS_SOURCE_PAD, 0x02, &result);
	 myJoystick.axis_y = 255.00*result/1023;
	adc_get_result(ADC_TRANS_SOURCE_PAD, 0x04, &result);
	 myJoystick.axis_z = 255.00*result/1023;


		key[0] = myJoystick.axis_x ;         //  
		key[1] = myJoystick.axis_y ;         //  
		key[2] = myJoystick.axis_z ;   			 //   1

		if(oldMyJoystick.axis_x != myJoystick.axis_x||oldMyJoystick.axis_y != myJoystick.axis_y||oldMyJoystick.axis_z != myJoystick.axis_z)
		{
            hid_gatt_report_notify(slave_link_conidx,HID_KEYBOARD_RPT_ID,key,HID_KEYBOARD_IN_RPT_LEN);

		
		}

		oldMyJoystick.axis_x = myJoystick.axis_x ;
		oldMyJoystick.axis_y = myJoystick.axis_y ;
		oldMyJoystick.axis_z = myJoystick.axis_z ;

5、win10测试

按照上述修改将程序下载到芯片中,电脑连接蓝牙,如下图所示。

只有当摇杆出现在鼠标,键盘和笔这一栏时,说明设备连接成功可以发送数据。

在这里插入图片描述

在这里插入图片描述

电脑端可以用win10 自带的驱动对摇杆进行测试,打开控制面板下的设备和打印机,如果写的没有问题,就会在设备栏出现个手柄。

在这里插入图片描述
在手柄上右键游戏控制器设置点击属性

在这里插入图片描述

当出现下面界面时,就可以按手柄上的按钮和3个轴,界面就会显示对于的值。

在这里插入图片描述

如果觉得自带的软件麻烦可以用 joystick tester软件也可以测试。

在这里插入图片描述

6、android 测试

手机上安装 Game Pad Test 手机上只能识别到2个轴不知道啥原因

在这里插入图片描述
在这里插入图片描述

总结

​ 设计 BLE HID 设备的前提一定要搞懂 BLE特征值和HID报告描述符之间的关系,以及报告描述符中有多少个报告每个报告有多少个字节,如果这些关系弄明白了 做BLE HID 设备将轻车熟路了。

结语

有朋友反馈,找不到我,今打油诗一首

加流一壶真千金
微云澹日映寒流
信意麾毫无点误
KING_SONGING
唱奇腾怪可删修
歌咏康衢了此生
的然民仰如父母
国家涵养自建隆
王俭归来幕府非

有朋自远发来,不亦说乎!

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

基于富芮坤fr8016 蓝牙5.0 芯片设计的BLE HID Joystick 游戏摇杆设备 的相关文章

  • BLE中的Service(服务)和characteristic(特征值)

    Service 服务 和characteristic 特征值 之间的关系 Service 服务 服务是用来完成特定功能或特性的数据和相关行为的集合 在GATT中 服务由其服务定义来定义 服务定义可能包含所包含的服务 强制性特征和可选特征 可
  • Telink泰凌微TLSR8258蓝牙开发笔记(一)

    一 开发环境搭建 1 1 软件开发环境 1 1 1 开发的IDE IDE下载链接 1 1 2 烧录工具 DBT下载地址 1 1 3 蓝牙SDK 蓝牙SDK下载地址 1 2 硬件开发环境 8258开发板 烧录工具一套 二 运行例程 并使能打印
  • 2021/9/29 TX POWER 蓝牙发射功率

    1 觉得挺奇葩 如果不是扩展包的话 就是TX power 设定 没法通过hci 下发 就是 在controller 设定好 也没法中途去变化 扩展包 有这个选项 能够改变 可以通过HCI 下发指令来更改 2 AD9361 设置发射功率 要注
  • ESP32-C3 学习测试 蓝牙 篇(七、GATT 数据通信 — 发送自定义数据)

    前面我们已经入门了 GATT 的开发 更进一步 进行想要的数据通信 目录 前言 1 通信问题思考 2 如何才能每次传输不同的数据 3 对 handle 的认识 4 继续尝试 5 测试成功 结语 前言 本来计划直接做一个蓝牙的小应用 首先得实
  • CC2642 数据长度扩展(LE Data Length Extension)

    概要 数据长度扩展 LE Data Length Extension 功能允许LE控制器在连接状态下发送具有高达251字节的PDU 在连接期间的任何时刻 主从设备可以协商该PDU大小 这个和MTU不同 MTU是应用层的数据传输长度 这个是链
  • Uniapp低功耗蓝牙操作实例

    uniapp低功耗蓝牙在移动端使用较为平常 本文相较于官方文档介绍一下低功耗蓝牙的操作案例 即取即用 低功耗蓝牙虽工作原理与经典蓝牙类似 但是有着独特的架构体系 所以LE独立出来成为一种蓝牙形态 不过LE和经典蓝牙使用相同的2 4G无线电频
  • 解密蓝牙mesh系列

    转载自 蓝牙技术联盟 蓝牙mesh网络基本概念 本周跟大家分享解密蓝牙mesh系列第四篇 点这里查看第一篇 第二篇和第三篇文章 同时也是蓝牙mesh网络基本概念的第二部分 借助蓝牙mesh 您将能够创建大型网络并支持成千上万的设备之间进行安
  • BLE学习(4):蓝牙地址类型和设备的隐私

    蓝牙地址也被称为蓝牙MAC地址 它能唯一标识一个蓝牙设备的48位的值 在蓝牙规范中 它被称为BD ADDR 蓝牙的地址类型可以分为两种 public addresses和random addresses 其中random addresses
  • 使用Arduino开发ESP32(22):蓝牙作为客户端使用

    文章目录 目的 基础准备 搜索蓝牙设备 搜索设备 信息查询 连接与交互 总结 目的 ESP32的蓝牙除了作为服务器 从设备 使用还可以作为客户端 主机 使用 这篇文章将对相关内容做个简单说明 基础准备 这篇文章中测试需要先准备一个蓝牙服务器
  • Android Ble 连接设备失败 onConnectionStateChange status 返回133

    Android Ble 连接设备失败时回调函数 onConnectionStateChange status 返回133 开始找问题 各种mac地址 权限 线程 找了个遍 结果就是返回纹丝不动 又因为 mBluetoothGatt mBlu
  • 连接到特定 HID 配置文件蓝牙设备

    我将蓝牙条形码扫描仪连接到我的 Android 平板电脑 条码扫描仪与 Android 设备绑定作为输入设备 HID 配置文件 它在系统蓝牙管理器中显示为键盘或鼠标 我发现蓝牙配置文件输入设备类存在但被隐藏 class 和 btprofil
  • 使 Windows Mobile 设备模拟蓝牙 HID 设备

    我正在寻找一种通过蓝牙将 Windows Mobile 设备连接到 PC 并使其作为 HID 设备 即键盘或鼠标 显示在 PC 上的方法 我想这主要是修改 Windows Mobile 设备上可用的蓝牙配置文件的问题 以便它公开蓝牙 HID
  • Pygame 不返回操纵杆轴移动而不显示

    我见过这个问题的其他解决方案说你要么需要调用 pygame event pump 要么在 while 循环之外初始化操纵杆 然而 即使使用这些解决方案 我得到的操纵杆轴值仍为 0 如果我只取消注释pygame display set mod
  • JoyGetPosEx 在 C# 中返回 165

    我尝试用 C 读取 JoyStick 中的数据 只要我使用 jeyGetPos 就可以正常工作 但我需要使用joyGetPosEx 因为它提供了更多数据 例如我需要的操纵杆的旋转 class JoyStick JOYINFO pji JOY
  • HID 设备的 INF 文件 - 设置名称和图标

    我正在寻找为 HID 设备 具有自定义 VID PID 创建一个 inf 文件 我只想用我们的字符串替换我们设备的 HID 兼容设备 和 USB 输入设备 字符串 我知道这需要 Microsoft 签名 但是有一个很好的示例说明如何执行此操
  • 如何可靠地将 X11 键码转换回扫描码或隐藏使用 ID

    几乎自己解决了 背景信息 Linux 密钥代码 以下内容来自 linux xmodmap tutorial 扫描码 键盘发送到计算机的数字 USB用 键盘 它是由 USB 标准定义的 Keycode Linux 内核用来表示按键 或鼠标 的
  • 仿蓝牙人机界面设备

    我想知道应用程序是否有可能通过 Android 设备的蓝牙模拟人机接口设备 在我的上下文中 这将是一个模拟鼠标的应用程序 应该被计算机识别为蓝牙鼠标 理想情况下 这应该可以在 java 中实现 我知道这个问题过去已经被问过好几次了 但我想知
  • 触摸屏摇杆算法

    我想在触摸屏上模拟模拟操纵杆 如下图所示 当摇杆区域中心设置为 cx cy 时 如何计算触摸位置 tx ty 的X方向比和Y方向比 1 0 1 0 x 方向的比率为 tx cx r 其中 r 是圆的半径大小 类似地 y方向比率为 ty cy
  • 在 Windows 10 上为 BLE GATT 设备开发 HID 输入设备驱动程序

    这是一个来自 MSDN 论坛的交叉帖子 https social msdn microsoft com Forums windowsdesktop en US 01b08fbd 3320 4796 b65e 92239d9b7306 how
  • 如何对 USB/HID/蓝牙适配器进行逆向工程。使用什么工具?

    需要对蓝牙USB鼠标适配器进行逆向工程 并使用鼠标板测量距离 并用绘图库 http matplotlib org 我发现这些工具可以帮助完成此任务 Linux lsusb usbmon usbhid转储 rfcomm hidrd 转换 xx

随机推荐

  • STM32中文参考手册下载地址

    STM32中文参考手册下载地址 进入官网后点击 设计资源 选择你要下载的芯片的手册 然后找到有 完整的存储器和外设信息 字眼的文档进行下载 很多人下载的下面这种 这种只介绍电气性能和简单介绍外设资源 并不告诉你寄存器啥的 编程比较困难 vo
  • 电脑键盘指法的正确练习步骤

    电脑键盘指法的正确练习步骤 转载 http www jb51 net softjc 39858 html 如果您觉得不合适请联系QQ 2453419889 我会及时删除本博文 电脑键盘指法练习学习目的 一 正确的指法 二 熟悉字母位置 电脑
  • base64、utf-8、二进制有什么关系?

    一 引言 在开发过程中我们经常会用到GBK utf 8等编码规范 本文为大家介绍了他们的起源 差别以及应用 二 ASCII GBK Unicode Utf 8编码区别 1 文本编码的诞生背景 计算机只能处理数字 如果要处理文本文件就必须先把
  • React Native Map遍历问题

    code for let room of rooms values console log room error TypeError undefined is not a function evaluating iterator typeo
  • 【100%通过率 】【华为OD机试真题c++/java/python】开心消消乐【2022 Q4

    华为OD机试 题目列表 2023Q1 点这里 2023华为OD机试 刷题指南 点这里 题目描述 给定一个N行M列的二维矩阵 矩阵中每个位置的数字取值为0或1 矩阵示例如 1100 0001 0011 1111 现需要将矩阵中所有的1进行反转
  • Linux线程学习(三):pthread常见线程函数

    在任何一个时间点上 线程是可结合的 joinable 或者是分离的 detached 一个可结合的线程能够被其他线程收回其资源和杀死 在被其他线程回收之前 它的存储器资源 例如栈 是不释放的 相反 一个分离的线程是不能被其他线程回收或杀死的
  • 如何使用FastReport .NET 从 JetBrains Rider 中创建PDF报告?

    Fastreport是目前世界上主流的图表控件 具有超高性价比 以更具成本优势的价格 便能提供功能齐全的报表解决方案 连续三年蝉联全球文档创建组件和库的 Top 50 Publishers 奖 FastReport NET官方版下载 qun
  • android开发系列:Android Studio项目添加依赖时下载的jar包在哪

    参考 参考 https blog csdn net wudinaniya article details 75258077 结论 c盘 用户 用户名 gradle caches modules 2 files 2 1
  • python模拟登录网站_Python模拟登录的几种方法

    目录 正文 方法一 直接使用已知的cookie访问 特点 简单 但需要先在浏览器登录 原理 简单地说 cookie保存在发起请求的客户端中 服务器利用cookie来区分不同的客户端 因为http是一种无状态的连接 当服务器一下子收到好几个请
  • 【error】Doubbo 服务启动异常:java.lang.RuntimeException: [source error] getPropertyValue,问题分析,解决方案

    目录 1 报错信息 2 原因分析 3 解决方案 4 提示 1 报错信息 java lang RuntimeException source error getPropertyValue Ljava lang Object Ljava lan
  • R语言—向量

    向量 vector R 语言最基本的数据结构是向量 类似于数学上的集合的概念 由一个或多个元素构成 向量其实是用于存储数值型 字符型 或逻辑型数据的一维数组 创建向量 c 函数 gt a lt 1 给a赋值1 gt a 显示a的值 1 1
  • 解密企业级PPPoE:部署、配置和管理的最佳实践

    亲爱的读者朋友们 今天 我将带你一起探索企业级PPPoE 这个让你畅快玩转互联网的神奇协议 首先 让我们来了解一下什么是PPPoE 它代表着 点对点协议以太网 是一种强大而灵活的网络连接协议 对于企业来说 部署PPPoE意味着你可以轻松实现
  • Java实现实现简单算法之最长对称字符串

    题目 已知一字符串 求其内包含的最长对称字符串 例 已知字符串 google 输出最长对称字符串 goog 已知abada 输出aba 已知sdghjdgzzgdah 输出 dgzzgd 看到题目时 大家第一反应都是模棱两可的 好像可以这样
  • Selenium+Python3之:多线程进行跨浏览器测试

    python多线程跨浏览器测试 1 引言 2 跨浏览器操作及定义 2 1 啥是跨浏览器测试 2 2 为啥要进行跨浏览器测试 2 3 跨浏览器测试执行 3 代码编写实战 1 引言 在WebUI自动化方面的博文 我也是有好一段时间没有更新了 这
  • 什么是期货交易的技术分析(期货交易市场技术分析)

    什么是期货买卖的本领领会 拓展材料 1 期货本领领会规则 期货本领领会的规则是伴随趋向 期货本领领会的表面普通 期货本领领会的表面普通是创造在三个有理的假如之上的 商场动作具备容纳性和容纳性 价钱以一种趋向的办法兴盛 汗青将重演 在这三个假
  • 如何利用Python爬虫在网上接单,一周赚7800元,一天只要两小时 !

    1 兼职处理数据 互联网时代下 越来越多的人离不开电脑办公 而与电脑办公分隔不开的 就是处理电脑上保存的数据 虽然说Excel整理数据功能很强大 但在Python面前 曾经统治职场的它也得败下阵来 因为Python在搜集整理分析数据的过程中
  • ConstraintLayout 高级特性,工具总结

    layout constraintWidth 用法 xml中 app layout constrainedWidth true 作用 使得该view的宽受限于他的约束 app layout constrainedHeight true 同理
  • ChatGPT专业应用:基于关键词撰写原创文章

    正文共 485 字 阅读大约需要 2 分钟 内容运营 SEO投放必备技巧 您将在2分钟后获得以下超能力 基于关键词撰写原创文章 Beezy评级 B级 经过简单的寻找 大部分人能立刻掌握 主要节省时间 推荐人 Kim 编辑者 Linda 此图
  • QT CREATOR 插件开发:添加新的工程类型(上)

    Qt Creator 中 新的工程类型将出现在 文件 gt 新建 菜单项中 我们可以通过打开的选择工程类型的对话框来找到所需要的工程 在本章中 我们将学习如何向上面所示的对话框中添加新的工程类型 Core IWizard接口 Qt Crea
  • 基于富芮坤fr8016 蓝牙5.0 芯片设计的BLE HID Joystick 游戏摇杆设备

    文章目录 ble hid 学习笔记 HID报告描述符与BLE HID profile之间关系 1 HID报告描述符 富芮坤fr8016 设计Joystick例子 1 描述X轴Y轴Z轴 2 描述按钮 3 Joystick 报告描述符 4 程序