本文主要是介绍基于 NXP QN9080 三模鼠标开发 —— USB 模式,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
一、应用背景概述
当今时代可以称之为电竞时代,越来越多的电竞游戏被人们所热爱,随着电竞行业发展,传统的鼠标已经不能满足于这个游戏时代了,一个好的鼠标对于游戏玩家的作用无异于在战场上一把好的武器对于一个士兵的作用。鼠标,是 HID(Human Interface Device)中的一种,鼠标可以是有线模式(USB 模式)也可以是无线模式(BLE 或者 2.4G 模式),下面将会为大家介绍一个集合了 USB 模式,BLE 模式以及 2.4G 模式的可编程电竞鼠标是怎么实现的。
二、环境搭建
2.1 SDK 下载
本文基于 NXP QN9080 IC,SDK 可在 NXP 官网 https://mcuxpresso.nxp.com 下载。
2.1 硬件
本文基于 QN9080 DK 板进行开发,DK 板如图 2.2 所示。
2.3 开发软件
SDK 支持 IAR、Keil、MCUXpreeso IDE 三种开发软件、本文以 IAR 为开发环境作为介绍。
三、工程移植
在DK_2.2.0_QN908XCDK_20190521\boards\qn908xcdk\usb_examples\usb_device_hid_mouse 目录下有一个 USB 模式的鼠标的例程,下面将会以这个例程为基础进行移植从而实现一个完整的 USB 有线鼠标的功能。
由于例程中已经有一套完整的 USB 协议,所以本文将会着重于移植修改 HID 部分、数据格式,以及数据传输。
3.1 HID 添加以及修改
3.1.1 修改按键描述符
在 SDK 中,设备描述符只能实现普通的鼠标,也就是说 SDK 实现的只有左键,中键,右键三个按键,因此需要将普通的描述符修改为能够适用于电竞鼠标的描述符,图 3.1.1 为 SDK 的描述符。
图中的 ① 为按键描述符,SDK 中使用的是大小为 1 bit 的数据代表一个按键,总共使用了 3 个这样的数据,并且保留 5 bit 没有使用。如果需要增加按键数目,则可像下面的方式进行修改,将三个按键修改为 5 个按键,将预留的 5 个 bit 改成 3 个,具体修改如下:
0xA1, 0x00, /*Collection (Physical)*/0x05, 0x09, /*Usage Page (Button)*/0x19, 0x01, /*Usage Minimum (Button 1)*/0x29, 0x07, /*Usage Maximum (Button 5)*/0x15, 0x00, /*Logical Minimum (0)*/0x25, 0x01, /*Logical Maximum (1)*/0x95, 0x05, /*Report Count (5)*/ 0x75, 0x01, /*Report Size (1)*/0x81, 0x02, /*Input (Data,Var,Abs,NWrp,Lin,Pref,NNul,Bit)*/0x95, 0x01, /*Report Count (5)*/0x75, 0x03, /*Report Size (3)*/ 0x81, 0x01, /*Input (Cnst,Ary,Abs)*/
3.1.2 修改 X , Y 描述符
SDK 中的描述符对于 X ,Y 的坐标值只能取值为 8 bits,具体 X ,Y 的描述符如图 3.1.2。
图中的 ② 是 X ,Y 以及滚轮的描述符,用的是大小为 8 bits 的数据代表,数量为 3 个,也就是说 X ,Y 以及滚轮用的都是一个 Byte,但是电竞鼠标用的 Optical Navigation Sensor 基本都是使用 16 bits 的数据去表示 X 以及 Y。因此需要扩大 X、Y 的取值范围,将原本的 8 bits 修改为 16 bits,具体修改如下:
0x05, 0x01, /*Usage Page (Generic Desktop)*/0x09, 0x30, /*Usage (X)*/0x09, 0x31, /*Usage (Y)*/0x16, 0x01, 0x80, /*Logical Minimum (-32767)*/0x26, 0xFF, 0x7F, /*Logical Maximum (32767)*/0x75, 0x10, /*Report Size (16)*/0x95, 0x02, /*Report Count (2)*/ // 2 Word(4 Byte)0x81, 0x06, /*Input (Data,Var,Rel,NWrp,Lin,Pref,NNul,Bit)*/
3.1.3 修改多媒体功能描述符
相对于普通鼠标,电竞鼠标可能会拥有其他功能,例如可以通过按键实现多媒体的功能,那么多媒体的功能在鼠标上面是怎么实现的呢,这个也是涉及到描述符的,多媒体功能可以与鼠标功能在同一个 Interface 中进行发送,因此可以使用同一个描述符,但是需要与鼠标功能进行区分,具体添加如下:
0x05u, 0x0Cu, /* USAGE_PAGE */0x09u, 0x01u, /* USAGE */0xA1u, 0x01u, /* COLLECTION */ 0x85u, 0x05u, /* REPORT_ID */0x19u, 0x00u, /* USAGE_MINIMUM */0x2Au, 0x3Cu, 0x02u, /* USAGE_MAXIMUM */0x15u, 0x00u, /* LOGICAL_MINIMUM */0x26u, 0x3Cu, 0x02u, /* LOGICAL_MAXIMUM */0x95u, 0x01u, /* REPORT_COUNT */0x75u, 0x10u, /* REPORT_SIZE */0x81u, 0x00u, /* INPUT */0xC0u, /* END_COLLECTION */
其中的 0x85u, 0x05u, /* REPORT_ID */ 是为了区分鼠标功能,由于鼠标功能与多媒体功能共用了一个 Interface,相同的 Endpoint 进行发送,因此需要使用不同的 Report ID 进行区分。
3.2 USB 数据传输速率的修改
电竞鼠标与普通鼠标有一个比较大的区别就是电竞鼠标的 ReportRate 相对于普通鼠标会高出不少,通常电竞鼠标的 ReportRate 可以达到 1K,也就是 1ms 上报一次数据,SDK 中的 ReportRate 是设置的是 250,如何将 USB 的传输速率提高为 1K,具体修改如图 3.2.1:
将图中的 ① 0x04修改成 0x01,这样就可以将 USB 的传输速率设置为 1K 了。
3.3 USB 数据格式说明
3.3.1 鼠标功能的数据格式修改
SDK 中的数据格式为 4 个 Bytes,具体含义如下:
① Byte 0:按键数据
② Byte 1:X 坐标取值
③ Byte 2:Y 坐标取值
④ Byte 3:滚轮数据
其中 Byte 0 中每一个 bit 的分布如下:
① Bit 0:左键
② Bit 1:右键
③ Bit 3:中键
④ Bit 4 - 7:保留
那么如果使用文中 3.1 提及的按键描述符修改,X ,Y 描述符修改,添加多媒体功能描述符的操作后,数据格式将变成什么样子呢,下面将进行说明:
修改后的数据格式为 7 个 Bytes,具体含义如下:
① Byte 0:Mouse ID
② Byte 1:按键数据
③ Byte 2:X 低 8 位坐标取值
④ Byte 3:X 高 8 位坐标取值
⑤ Byte 4:Y 低 8 位坐标取值
⑥ Byte 5:Y 低 8 位坐标取值
⑦ Byte 6:滚轮数据
其中 Byte 1 中每一个 bit 的分布如下:
① Bit 0:左键② Bit 1:右键③ Bit 3:中键④ Bit 4:前进按键⑤ Bit 5:后退按键⑥ Bit 6 - 7:保留
具体代码格式的如图 3.3.1
3.3.2 多媒体功能的数据格式添加
由于 SDK 中没有多媒体功能,但是可以从描述符中推出具体的数据格式。3.1.3 中有提到多媒体功能需要使用 Report ID 区别于鼠标功能的数据发送,并且从描述符
0x95u, 0x01u, /* REPORT_COUNT */0x75u, 0x10u, /* REPORT_SIZE */
可以看出多媒体功能的数据是一个是使用了大小为 16 bits ,数量为 1 的数据,因此多媒体具体的数据格式如下:
① Byte 0:Mouse Multimedia ID
① Byte 1:多媒体数据低 8 位
② Byte 2:多媒体数据高 8 位
具体代码格式的如图 3.3.2
3.4 USB 数据发送说明
SDK 的数据发送主要是发送一个数据长度为 4 的 Buffer 给 PC 设备,但是经过修改后,我们的数据长度已经发生了改变,因此,发送数据时也需要作出相应的调整,具体调整如下:
USB_DeviceHidSend( g_UsbDeviceHidMouse.hidHandle,USB_HID_MOUSE_ENDPOINT_IN, // 用于发送数据的 Endpointg_UsbDeviceHidMouse.buffer, // 需要发送的 BufferUSB_HID_MOUSE_REPORT_LENGTH); // 需要发送的数据长度
需要将 USB_HID_MOUSE_REPORT_LENGTH 的值由原本的 4 修改为当前的数据长度 7,才能将鼠标的数据上报给 PC 设备,但是由于速率比较快,如果遇到通信没有完成的时候继续发送下一包数据可能会导致通信通道堵死的情况,所以必须保证在发送数据的时候上一包数据发送完成才能发送下一包数据。
另外,由于新添加的多媒体功能是与鼠标功能是使用同一个 Endpoint 进行发送,因此只需要将多媒体功能的 Buffer 以及相应的数据长度进行替换就可以实现多媒体功能了。当然如果是使用不同的 Endpoint 进行发送,就需要修改相应的 Endpoint 了。
四、总结
经过前面的解析说明,相信大家都能够基于 QN9080 SDK 进行移植修改出一个有线模式的电竞鼠标功能了,之后将会从蓝牙广播,蓝牙回连,以及蓝牙数据传输等方面去给大家介绍蓝牙模式的鼠标是如何实现的,并且还会有 2.4G 模式鼠标的实现教学。
五、参考资料
http://www.usbzh.com/article/detail-327.html
这篇关于基于 NXP QN9080 三模鼠标开发 —— USB 模式的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!