iMX6ULL驱动开发 | 让imx6ull开发板支持usb接口FC游戏手柄

手边有一闲置的linux开发板iMX6ULL一直在吃灰,不用来搞点事情,总觉得对不住它。业余打发时间就玩起来吧,总比刷某音强。从某多多上8块儿大洋买来一个usb接口的游戏手柄,让开发板支持以下它,后续就可以接着在上面玩童年经典游戏啦。

 我使用的是正点原子的I.MX6U-ALPHA 开发板,板子资源很丰富。计划搞一个系列在上面玩各种有意思的事情。包含linux驱动开发和应用开发,最终学以致用,在玩中学,兴趣是最好的老师。

 展示下我买的FC游戏手柄长这样,普普通通,但便宜啊,还是经典的味道。

驱动移植过程

确定设备类型

要让板子支持这一USB接口的FC游戏手柄,首先得知道这个手柄是使用的什么接口协议。插到win10电脑上看了下,是一个USB协议接口的HID类型的设备。USB-HID是Universal Serial Bus-Human Interface Device的缩写,由其名称可以了解HID设备是直接与人交互的设备,例如键盘、鼠标与游戏杆等。

USB的硬件端口是统一的,但是USB设备却是多种多样的,USB主机根据USB设备的描述符来区分不同的USB设备。每一个USB设备都有自己的描述符,当插入USB设备之后,主机会向从机发送命令,从机收到命令之后,会返回特定的描述符信息。主机通过解析收到的描述符,来识别从机设备的相关信息,这个过程,就是设备枚举(enumeration)过程。

获取USB的VID和PID信息

我的这个FC手柄插到电脑上后识别出了usb-hid设备。查看到它的vid和pid信息,直接在电脑的设备管理器里能够查看到,这个信息很有用,后面驱动移植需要用到。

已启动设备 HID\VID_0810&PID_0001\6&1eff4ed2&0&0000。驱动程序名称: input.inf

查找linux内核源码,锁定相关驱动

在linux内核源码的linux/drivers/hid/路径下,有跟HID相关的驱动源码。打开hid-core.c文件(HID support for Linux),查看下该源文件中是否包含该usb设备的VID和PID信息。如果没有,则在hid_have_special_driver添加上VID和PID信息。这个里面的一些宏定义在文件hid-ids.h中可以查看。

torvalds大神linux源码的github地址:

GitHub - torvalds/linux: Linux kernel source tree

/** A list of devices for which there is a specialized driver on HID bus.** Please note that for multitouch devices (driven by hid-multitouch driver),* there is a proper autodetection and autoloading in place (based on presence* of HID_DG_CONTACTID), so those devices don't need to be added to this list,* as we are doing the right thing in hid_scan_usage().** Autodetection for (USB) HID sensor hubs exists too. If a collection of type* physical is found inside a usage page of type sensor, hid-sensor-hub will be* used as a driver. See hid_scan_report().*/
static const struct hid_device_id hid_have_special_driver[] = {{ HID_USB_DEVICE(USB_VENDOR_ID_A4TECH, USB_DEVICE_ID_A4TECH_WCP32PU) },{ HID_USB_DEVICE(USB_VENDOR_ID_A4TECH, USB_DEVICE_ID_A4TECH_X5_005D) },{ HID_USB_DEVICE(USB_VENDOR_ID_A4TECH, USB_DEVICE_ID_A4TECH_RP_649) },{ HID_USB_DEVICE(USB_VENDOR_ID_ACRUX, 0x0802) },{ HID_USB_DEVICE(USB_VENDOR_ID_ACRUX, 0xf705) },//......}

查找近似hid的游戏手柄驱动

通过make menuconfig打开内核配置选项查看。

 找到有个DragonRise Inc, game controller。虽然不确定它跟我的这款FC手柄完美匹配,但至少从名字上看,这就是个游戏手柄的hid设备。

 如果有默认的内核配置选项文件,也可以直接添加选项开关:

CONFIG_HID_DRAGONRISE=y

跟这个相关的驱动源文件是linux/drivers/hid/hid-dr.c。打开这个文件,添加上我的usb设备的VID和PID信息。

static const struct hid_device_id dr_devices[] = {{ HID_USB_DEVICE(USB_VENDOR_ID_DRAGONRISE, 0x0006),  },{ HID_USB_DEVICE(USB_VENDOR_ID_DRAGONRISE, 0x0011),  },{ HID_USB_DEVICE(0x0810, 0x0001),  },{ }
};

编译内核驱动

#使用Yocto SDK里的GCC 5.3.0交叉编译器编译出厂Linux源码,可不用指定ARCH等,直接执行Make
source /opt/fsl-imx-x11/4.1.15-2.1.0/environment-setup-cortexa7hf-neon-poky-linux-gnueabi
#编译前先清除
make distclean
#配置defconfig文件
make imx_v7_defconfig -j 16
#开始编译zImage
make zImage -j 16

这之后,更新板子上的内核并重启设备。把该USB游戏手柄插上去,输入dmesg查看内核日志信息,看是否识别到该设备节点。

dmesg

查看输入设备、获取输入事件信息

/dev/input/目录

/dev/input/目录下的事件都是在驱动中调用input_register_device(struct input_dev *dev)产生的。我的/dev/input/目录中的文件如下:

$ ls /dev/input/
by-id  by-path  event0  event1  event2  event3 

每个event代表一个事件。那么如何知道每个事件分别与哪个设备对应?可以借助于/proc/bus查看。

/proc/bus/input/devices

/proc/bus/input/devices存放了与event对应的相关设备信息。我的板子上查看到的内容如下:

$ cat /proc/bus/input/devices

可以看到,每一项的“H:”一行后边的内容中就是对应的event。 

直接读取/dev/input/eventx

使用cat查看输入事件的内容,操作相应输入设备,事件会上报内容。以字符串方式解读会呈现乱码。所以可以使用hexdump读取十六进制的数据。

测试读取demo

linux内核使用 input_event结构体描述所有的输入事件。

/** The event structure itself*/struct input_event {struct timeval time;__u16 type;__u16 code;__s32 value;
};

为了验证该usb的游戏手柄是否工作,以及获取它对应的键值,写一个小的demo测试读取下。

#include <stdio.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <linux/input.h> #define _EV_KEY         0x01    /* button pressed/released */
#define _EV_ABS         0x03    
#define _EV_MSC         0x04   int main() {printf("hello,usb hid joystick key test\n");int fd = open("/dev/input/event3", O_RDONLY);struct input_event e;while(1) {read(fd, &e, sizeof(e));switch(e.type) {case _EV_KEY:printf("type: %d, code: %d,value: %d, time: %d\n", e.type, e.code,e.value, e.time);break;case _EV_ABS:printf("type: %d, code: %d,value: %d, time: %d\n", e.type, e.code,e.value, e.time);break;case _EV_MSC:printf("type: %d, code: %d,value: %d, time: %d\n", e.type, e.code,e.value, e.time);break;default:if(e.type != 0){printf("type:%d, code: %d,value: %d, time: %d\n",e.type, e.code,e.value, e.time);}}}close(fd);return 0;
}

evtest测试工具

在开发input子系统驱动时,常常会使用evtest工具进行测试。evtest是打印evdev内核事件的工具,它直接从内核设备读取并打印设备描述的带有值和符号名的事件,可以用来调试鼠标、键盘、触摸板等输入设备。通常用于调试输入设备的问题。

输出数据中,“type”是input类型,可以是“EV KEY”、“EV SW”、“EV SND”、“EV LED”或数值;“value”可以是十进制也可以是十六进制,或者是查询的kev/开关/声音/LED的常量名。

evtest工具下载安装

下载地址:Index of /debian/pool/main/e/evtest/ | 南阳理工学院开源镜像站 | Nanyang Institute of Technology Open Source Mirror

交叉编译安装

#解压缩
$ tar   -xjvf   evtest_1.33.orig.tar.bz2
$ cd evtest-1.33/#加载环境
source /opt/fsl-imx-x11/4.1.15-2.1.0/environment-setup-cortexa7hf-neon-poky-linux-gnueabi#生成makefile,指定交叉编译
.confiqure --host=arm-linux#编译
make

evtest工具使用

 运行示例

time:事件产生的时间。

type:事件类型,常见的有:EV_KEY(键盘)、EV_REL(相对坐标)、EV_ABS(绝对坐标)、,定义在[input-event-codes.h] (https://github.com/torvalds/linux/blob/master/include/uapi/linux/input-event-codes.h#LC35) 或 input.h 中。

code:事件的代码,对事件进一步的描述,如:键盘事件的键值(KEY_NUMLOCK、KEY_ESC、KEY_1、KEY_A)。

value:事件的值,对事件更具体地描述,如:按键的按下/抬起。

以下是使用devtest工具,(各按一次上,下,左,右,选择,开始等按键), 抓取的各个按键的反馈信息:

手柄上的键值确定

FC手柄上一般包含以下键。左,右,上,下,start,select,A,B,X,Y。

     /*** FC手柄 bit 键位对应关系 真实手柄中有一个定时器,处理 连A  连B* 0  1   2       3       4    5      6     7* A  B   Select  Start  Up   Down   Left  Right*/

如果你买的usb接口的FC游戏手柄是DragonRise Inc. game这家的,估计就不用以上这么的测试键值了,直接启用就能用。但是我随便买的这款需要测试下对应起来才能用。

 经过以上测试,最终确定键值的对应关系如下:

游戏手柄按键读出的键值
左侧方向键上type: 3, code:1,value: 0
type: 3, code:1,value: 127
左侧方向键下type: 3, code:1,value: 255
type: 3, code:1,value: 127
左侧方向键左type: 3, code:0,value: 0
type: 3, code:0,value: 127
左侧方向键右type: 3, code:0,value: 255
type: 3, code:0,value: 127
SELECT键type: 1, code:296,value: 1
type: 1, code:296,value: 0
START键type: 1, code:297,value: 1
type: 1, code:297,value: 0
右边数字键1type: 1, code:288,value: 1
type: 1, code:288,value: 0
右边数字键2type: 1, code:289,value: 1
type: 1, code:289,value: 0
右边数字键3type: 1, code:290,value: 1
type: 1, code:290,value: 0
右边数字键4type: 1, code:291,value: 1
type: 1, code:291,value: 0

其他资源

USB HID_Soc点灯大师的博客-CSDN博客

为了V3S不吃灰,移植NES游戏 / 全志 SOC / WhyCan Forum(哇酷开发者社区)

V3S移植nes游戏模拟器(附带游戏合集)_v3s编译游戏模拟器_qq_46604211的博客-CSDN博客

Linux下查看输入设备、获取输入事件的详细方法_evtest命令_蓝天居士的博客-CSDN博客

linux驱动开发学习笔记九:menuconfig过程详解

开发者搜索-Beta-让技术搜索更简单高效
Linux系统struct input_event结构体分类型(鼠标、键盘、触屏)详解与例子_wkd_007的博客-CSDN博客开发者搜索-Beta-让技术搜索更简单高效
 

USB_HID基础_usbhid_jansert的博客-CSDN博客

玩转USB HID系列:Linux下使用C语言和libusb开发USB HID_whstudio123的博客-CSDN博客

i.MX6ULL驱动开发 | 20 - Linux input 子系统_imx6ull input驱动框架_Mculover666的博客-CSDN博客

GitHub - torvalds/linux: Linux kernel source tree

嵌入式Linux:V3s移植NES游戏,声音,游戏手柄_全志v3s 移植nes_liefyuan的博客-CSDN博客

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

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

相关文章

信息学奥赛一本通——1258:【例9.2】数字金字塔

文章目录 题目【题目描述】【输入】【输出】【输入样例】【输出样例】 AC代码 题目 【题目描述】 观察下面的数字金字塔。写一个程序查找从最高点到底部任意处结束的路径&#xff0c;使路径经过数字的和最大。每一步可以从当前点走到左下方的点也可以到达右下方的点。 在上面…

VS2019编译安装OpenMesh8.0

文章目录 一、简介二、相关准备三、编译安装四、举个栗子参考资料一、简介 多边形网格一直以来就是交互式3D图形应用程序中最合适的几何表示,它们足够灵活,可以近似任意形状,并且可以通过当前的图形硬件有效地处理,即使在今天的低成本电脑上也是如此。OpenMesh便是其中一种…

Java-很深我只知其一-泛型

Java-很深我只知其一-泛型 目录 泛型历史 泛型类/泛型接口 泛型方法 泛型属性 泛型约束 泛型历史 JAVA 泛型&#xff08;generics&#xff09;是 JDK 5 中引入的一个新特性, 允许程序员在编程时指定类型参数&#xff0c;使编译器可以在编译代码时检测到非法的类型。泛型的…

相交链表 LeetCode热题100

题目 给你两个单链表的头节点 headA 和 headB &#xff0c;请你找出并返回两个单链表相交的起始节点。如果两个链表不存在相交节点&#xff0c;返回 null 。 题目数据 保证 整个链式结构中不存在环。 思路 使用两个指针x,y同时遍历两个链表A和B。 当两个链表有相交节点时&am…

小研究 - 主动式微服务细粒度弹性缩放算法研究(四)

微服务架构已成为云数据中心的基本服务架构。但目前关于微服务系统弹性缩放的研究大多是基于服务或实例级别的水平缩放&#xff0c;忽略了能够充分利用单台服务器资源的细粒度垂直缩放&#xff0c;从而导致资源浪费。为此&#xff0c;本文设计了主动式微服务细粒度弹性缩放算法…

Centos安装libwebcam库运行 uvcdynctrl 命令

Centos 软件包仓库中没有 libwebcam 库&#xff0c;因此需要下载源文件手动编译 源文件地址&#xff1a;https://github.com/lucasrangit/libwebcam 解压后进入项目文件夹 mkdir build cd build cmake .. make make install 如果使用uvcdynctrl提示找不到库&#xff0c;则 vi…

k8s apiserver如何支持http访问?

原本是可以通过设置api-server的--insecure-port来实现&#xff0c;但是这个参数已经被废弃了&#xff0c;更好的方法则是使用proxy来实现&#xff1a; 在集群任意一个节点上起一个proxy服务&#xff0c;并设置允许所有host访问&#xff1a; kubectl proxy --address0.0.0.0 …

Java 版 spring cloud + spring boot 工程系统管理 工程项目管理系统源码 工程项目各模块及其功能点清单

工程项目各模块及其功能点清单 一、系统管理 1、数据字典&#xff1a;实现对数据字典标签的增删改查操作 2、编码管理&#xff1a;实现对系统编码的增删改查操作 3、用户管理&#xff1a;管理和查看用户角色 4、菜单管理&#xff1a;实现对系统菜单的增删改查操…

基于以太坊+IPFS的去中心化数据交易方法及平台

自己的论文&#xff0c;哎费事 目录 基于以太坊IPFS的去中心化数据交易方法及平台 基于以太坊IPFS的去中心化数据交易方法及平台 摘要&#xff1a; 数据交易过程中存在数据权属不明和数据安全问题。本文开发了一种基于以太坊IPFS的去中心化数据交易方法及平台。方法包括&am…

IPv4网络用户访问IPv6网络服务器

NAT64静态映射为一对一的对应关系&#xff0c;通常应用在IPv4网络主动访问IPv6网络的场景中。 要求位于IPv4网络中的PC通过IPv4地址1.1.1.10能够直接访问位于IPv6网络中Server。 操作步骤 配置FW。 # 配置接口GigabitEthernet 0/0/1的IPv4地址。 <FW> system-view [F…

使用okHttp不走代理问题

背景 okHttp处理流程 okHttp & 代理 为什么没走代理 okhttp选择proxy时&#xff0c;现将传入的url传换为uri&#xff0c;如果uri的host为空&#xff0c;okhttp选择直连url&#xff0c;放弃走代理 okhttp3.internal.connection.RouteSelector private fun resetNextProxy(…

1047. 删除字符串中的所有相邻重复项

给出由小写字母组成的字符串 S&#xff0c;重复项删除操作会选择两个相邻且相同的字母&#xff0c;并删除它们。 在 S 上反复执行重复项删除操作&#xff0c;直到无法继续删除。 在完成所有重复项删除操作后返回最终的字符串。答案保证唯一。 示例&#xff1a; 输入&#xff1a…

FFmpeg-channel rematrix

channel rematrix Channel rematrix 是一种音频处理技术&#xff0c;用于将多声道音频转换为不同的多声道格式。它可以将一个多声道音频信号从一种布局转换为另一种布局&#xff0c;例如从 5.1 到 7.1 或从立体声到环绕声。 ffmpeg中的rematrix可以通过fixter完成&#xff0c…

IP 工具

什么是IP 工具 IP 工具是用于轻松扫描和排除网络 IP 地址空间故障的网络工程工具。IP 工具使网络管理员能够审核、跟踪和监视 IP 地址、子网以及使用 IP 的设备和主机的性能。这个全面的网络工程工具集包括高级 IP 工具&#xff0c;如 Ping、系统资源管理器、MAC 地址解析器和…

[SQL挖掘机] - 存储过程

介绍: 当你在sql中需要多次执行相同的一组sql语句时&#xff0c;存储过程是一个非常有用的工具。它是一段预先定义好的sql代码块&#xff0c;可以被命名并保存在数据库中&#xff0c;以便重复使用。 存储过程可以包含多个sql语句、逻辑流程、条件判断和循环等&#xff0c;可以…

近7000万美元被盗:Curve被攻击事件分析

7 月 31 日&#xff0c;以太坊编程语言Vyper发布公告称&#xff0c;Vyper 0.2.15、0.2.16 和 0.3.0 版本的递归锁失效。随后Curve Finance等相关协议出现了漏洞攻击事件。 漏洞的根源都是某些版本的 Vyper 中出现故障的递归锁。攻击者通过反复重新签署合约&#xff0c;导致未经…

设计模式行为型——解释器模式

目录 什么是解释器模式 解释器模式的实现 解释器模式角色 解释器模式类图 解释器模式举例 解释器模式代码实现 解释器模式的特点 优点 缺点 使用场景 注意事项 实际应用 什么是解释器模式 解释器模式&#xff08;Interpreter Pattern&#xff09;属于行为型模式&…

​小程序 WxValidate.js ​再次封装

util.js // 合并验证规则和提示信息 const filterRules (objectItem) > {let rules {}, messages {};for (let key in objectItem) {rules[key] objectItem[key].rulesmessages[key] objectItem[key].message}return { rules, messages } }module.exports {filterRule…

html中非插件实现pdf预览【PC+H5】

这里只考虑非插件以外的方法&#xff0c;插件可以参考pdf.js 1. iframe标签 <iframe src"/file/read?fileaaa&typeupload" width"100%" height"800px"></iframe>经测试&#xff0c;chrome正常显示&#xff0c;firefox不能显示…

为什么要开源?

什么是开源&#xff1f; 开源软件是其源代码已由其版权所有者公开的软件。在真正的开源许可证下&#xff0c;软件是协作开发的&#xff0c;其他程序员可以查看、修改或使用自己的代码。这种“纯”开源模式通常被称为FOSS&#xff08;自由和开源软件&#xff09;。 开源的一个…