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查看内核日志信息,看是否识别到该设备节点。

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

/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博客

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

BUU [网鼎杯 2020 朱雀组]phpweb

BUU [网鼎杯 2020 朱雀组]phpweb 众生皆懒狗。打开题目&#xff0c;只有一个报错&#xff0c;不知何从下手。 翻译一下报错&#xff0c;data()函数:,还是没有头绪&#xff0c;中国有句古话说的好“遇事不决抓个包” 抓个包果然有东西&#xff0c;仔细一看这不就分别是函数和参…

软件外包开发的JAVA开发框架

Java的开发框架有很多&#xff0c;以下是一些常见的Java开发框架及其特点&#xff0c;每个框架都有其特定的使用场景和优势&#xff0c;开发者可以根据项目的需求选择合适的框架。今天和大家介绍常见的框架及特点&#xff0c;希望对大家有所帮助。北京木奇移动技术有限公司&…

【Golang 接口自动化01】使用标准库net/http发送Get请求

目录 发送Get请求 响应信息 拓展 资料获取方法 发送Get请求 使用Golang发送get请求很容易&#xff0c;我们还是使用http://httpbin.org作为服务端来进行演示。 package mainimport ("bytes""fmt""log""net/http""net/url&qu…

echarts图表基本使用

折线图 import * as echarts from echarts;const chartDom document.getElementById(main); const myChart echarts.init(chartDom); const option {xAxis: {type: category,data: [Mon, Tue, Wed, Thu, Fri, Sat, Sun]},yAxis: {type: value},series: [{data: [820, 932, …

【HarmonyOS】键盘遮挡输入框时,实现输入框显示在键盘上方

【关键字】 harmonyOS、键盘遮挡input&#xff0c;键盘高度监听 【写在前面】 在使用API6、API7开发HarmonyOS应用时&#xff0c;常出现页面中需要输入input&#xff0c;但是若input位置在页面下方&#xff0c;在input获取焦点的时候&#xff0c;会出现软键盘挡住input情况&a…

【JAVA】String ,StringBuffer 和 StringBuilder 三者有何联系?

个人主页&#xff1a;【&#x1f60a;个人主页】 系列专栏&#xff1a;【❤️初识JAVA】 文章目录 前言StringBufferStringBuffer方法 StringBuilderStringBuilder方法 String &#xff0c;StringBuffer 和 StringBuilder的区别String和StringBuffer互相转换 前言 在之前的文章…

解密Redis:应对面试中的缓存相关问题

文章目录 1. 缓存穿透问题及解决方案2. 缓存击穿问题及解决方案3. 缓存雪崩问题及解决方案4. Redis的数据持久化5. Redis的过期删除策略和数据淘汰策略6. Redis分布式锁和主从同步7. Redis集群方案8. Redis的数据一致性保障和高可用性方案 导语&#xff1a; 在面试过程中&#…

mysql 锁

1. 概述 锁 是计算机协调多个进程或线程 并发访问某一资源 的机制。在程序开发中会存在多线程同步的问题&#xff0c;当多个线程并发访问某个数据的时候&#xff0c;尤其是针对一些敏感数据&#xff08;比如订单&#xff0c;金额等&#xff09;&#xff0c;我们就需要保证这个数…

【redis】创建集群

这里介绍的是创建redis集群的方式&#xff0c;一种是通过create-cluster配置文件创建部署在一个物理机上的伪集群&#xff0c;一种是先在不同物理机启动单体redis&#xff0c;然后通过命令行使这些redis加入集群的方式。 一&#xff0c;通过配置文件创建伪集群 进入redis源码…

R语言【Tidyverse、Tidymodel】的机器学习方法

机器学习已经成为继理论、实验和数值计算之后的科研“第四范式”&#xff0c;是发现新规律&#xff0c;总结和分析实验结果的利器。机器学习涉及的理论和方法繁多&#xff0c;编程相当复杂&#xff0c;一直是阻碍机器学习大范围应用的主要困难之一&#xff0c;由此诞生了Python…

牛客网Verilog刷题——VL55

牛客网Verilog刷题——VL55 题目答案 题目 请用Verilog实现4位约翰逊计数器&#xff08;扭环形计数器&#xff09;&#xff0c;计数器的循环状态如下&#xff1a;   电路的接口如下图所示&#xff1a; 输入输出描述&#xff1a; 信号类型输入/输出位宽描述clkwireInput1系统…

数据库的分库分表

#!/bin/bash ######################### #File name:db_fen.sh #Version:v1.0 #Email:admintest.com #Created time:2023-07-29 09:18:52 #Description: ########################## MySQL连接信息 db_user"root" db_password"RedHat123" db_cmd"-u${…

Gitlab CI/CD笔记-第一天-GitOps和以前的和jenkins的集成的区别

一、GitOps-CI/CD的流程图 简单解释&#xff1a; 1.提交代码 2.编译构建 3.测试 4.部署 二、gitlab的实现 1、Runer 1.这个就是jenkins里的worker-slave的角色&#xff0c; 2.git-lab server 下发任务&#xff0c;Runner执行。 3.这个R…

windows上给oracle打补丁注意事项

打补丁的过程 1、升级opatch工具&#xff0c;检查剩余空间用于存放ORACLE_HOME的备份&#xff0c;设置oracle_home环境变量,通过readme中的先决条件来检查现有补丁是否和本次补丁冲突 2、opatch apply 升级数据库软件&#xff0c;这个必须数据库文件不要被进程调用 在windows上…

路由动态选择协议之RIP(路由信息协议)

软件&#xff1a;cicso packet tracer 8.0 拓扑图&#xff1a;路由器&#xff1a;Router-PT、连接线&#xff1a;Serial DTE、连接口&#xff1a;Serial口 1、配置基础ip R1配置&#xff1a;虚拟接口——1.1.1.1&#xff1b;S3/0——192.168.1.1 R1(config)#int s3/0 R1(con…

Spring之BeanDefinition(三)

Spring之BeanDefinition&#xff08;三&#xff09; 文章目录 Spring之BeanDefinition&#xff08;三&#xff09;一、Spring的启动类三行代码研究二、Spring创建工厂类型和属性三、Spring中内置的BeanDefinition四、注册配置类五、BeanDefinition总结 一、Spring的启动类三行代…

C++ 对象的生存期

对象&#xff08;包括简单变量&#xff09;都有诞生和消失的时刻。对象诞生到结束的这段时间就是它的生存期。在生存期内&#xff0c;对象将保持它的状态&#xff08;即数据成员的值&#xff09;&#xff0c;变量也将保持它的值不变&#xff0c;直到它们被更新为止。对象的生存…

城市内涝 | 复杂城市排水管网系统快速建模、管网水力性能专题图制作、城市内涝一维二维耦合模拟、海绵城市关键控制指标计算

随着计算机的广泛应用和各类模型软件的发展&#xff0c;将排水系统模型作为城市洪灾评价与防治的技术手段已经成为防洪防灾的重要技术途径。本次培训将聚焦于综合利用GIS及CAD等工具高效地进行大规模城市排水系统水力模型的建立&#xff0c;利用SWMM实现排水系统水力模拟。讲解…

微信小程序(van-tabs) 去除横向滚动条样式(附加源码解决方案+报错图)

问题描述 今天第一次接触vant组件库。 ant官网地址适用于Vue3 支持Vue2、Vue3、微信小程序等 我在使用van-tabs组件时遇到了一个问题&#xff0c;如下图所示&#xff1a; 从图片上可以看到有个灰色的横向滚动条&#xff0c;一开始领导给我说这个问题&#xff0c;我反反复复都…

mybatisJava对象、list和json转换

1. 参考mybatis-plus mybatis Java对象、list和json转换 网上好多不靠谱&#xff0c;参考mybatis-plus中TableField&#xff0c;mybatis中自定义实现 这样不需要对象中属性字符串接收&#xff0c;保存到表中&#xff0c;都是转义字符&#xff0c;使用时还要手动转换为对象或者…