[joysticker]使用Ubuntu读取USB手柄/方向盘的输出控制

2023-05-16

摘要:在淘宝上买到的游戏手柄/USB卖家只给了Windows下的驱动,本来以为Ubuntu下没有驱动,没想到网上早已经有人用cpp开发出了USB手柄的驱动,搜索很多博客的方法终于从手柄拿到数据。
Linux真给力!!

目录

  • 目录
  • 1.cat命令
  • 2.hexdump命令
  • 3.获取游戏手柄的端口输出
    • (1)获取端口
    • (2)读取游戏手柄端口数据
  • 4.代码实现
      • warning:deprecated conversion from string constant to ‘char *’
  • 主要参考

1.cat命令

cat 是一个文本文件查看和连接工具。查看一个文件的内容,用cat比较简单,就是cat 后面直接接文件名,如cat linuxyw.txt

cat –help可以查看cat帮助信息,如各种参数使用方法,当然也可以用man cat来查看,建议大家养成遇到命令不懂用法时,用–help或man来查看帮助信息,养成好习惯。filename为文件名,即系统中需要查看的文件名字。
与这个命令相似功能的命令有:tac,less,tail,more

options:
-b:--number-nonblank 对非空输出行编号,即在每行前显示所在行号
-n:--number 对输出的所有行编号,即在每行前显示所在行号

注:cat命令

2.hexdump命令

hexdump命令一般用来查看“二进制”文件的十六进制编码,但实际上它能查看任何文件,而不只限于二进制文件。

hexdump [选项] [文件]...
options:
-n length 只格式化输入文件的前length个字节。
-C 输出规范的十六进制和ASCII码。
-b 单字节八进制显示。
-c 单字节字符显示。
-d 双字节十进制显示。
-o 双字节八进制显示。
-x 双字节十六进制显示。
-s 从偏移量开始输出。
-e 指定格式字符串,格式字符串包含在一对单引号中,格式字符串形如:'a/b "format1" "format2"'

注:hexdump命令

3.获取游戏手柄的端口输出

(1)获取端口

在插入设备时,linux系统会使用input子系统,操作系统会为每一个设备分配event号,先插上的为event0,后插上的为event1,首先获取linux系统为游戏手柄分配的event号。
当游戏手柄插入电脑时,需要找到手柄的even号:

cat /proc/bus/input/devices

注:或者可以使用>将输出写入一个txt文档

 cat /proc/bus/input/devices >log1.txt

获得如下输出


I: Bus=0003 Vendor=11ff Product=001c Version=0111
N: Name="PXN-V3II"
P: Phys=usb-0000:00:14.0-11/input0
S: Sysfs=/devices/pci0000:00/0000:00:14.0/usb1/1-11/1-11:1.0/0003:11FF:001C.0009/input/input29
U: Uniq=
H: Handlers=event21 js0 
B: PROP=0
B: EV=1b
B: KEY=1fff000000000000 0 0 0 0
B: ABS=30027
B: MSC=10

在端口处找到设备名字“PXN-V3II”,event21/js0我们的手柄的接口。

开始的时候有时候找不到,是手柄中的版本不对,根据产品说明书需要由X-input转换到D-input模式。(长按home键3秒)
X -input适用于XBOX360移植到PC上的即插即玩的游戏,D-input适用于早期单机游戏如极品飞车1-12等。——要不是要在unbuntu下开发哪来这么多幺蛾子。。。

(2)读取游戏手柄端口数据

查看输入

ls /dev/input

这里写图片描述

可以看见js0和event21,使用以下代码查看端口输出:

cat /dev/input/js0 | hexdump

cat /dev/input/event21 | hexdump

得到一堆16进制的数,当手柄按下时,数字便会变化。
这里写图片描述

测试手柄命令

 jstest /dev/input/js0

可以读取Axes和Button的变化。
这里写图片描述

4.代码实现

参照参考3,新建文件夹与cpp文件,实现jstest功能:
cpp文件建立执行参照

gedit first.cpp
g++ first.cpp -o test
./test

代码如下:

#include <stdio.h>  
#include <unistd.h>  
#include <string.h>  
#include <sys/types.h>  
#include <sys/stat.h>  
#include <fcntl.h>  
#include <errno.h>  
#include <linux/input.h>  
#include <linux/joystick.h>  

#define XBOX_TYPE_BUTTON    0x01  
#define XBOX_TYPE_AXIS      0x02  

#define XBOX_BUTTON_A       0x00  
#define XBOX_BUTTON_B       0x01  
#define XBOX_BUTTON_X       0x02  
#define XBOX_BUTTON_Y       0x03  
#define XBOX_BUTTON_LB      0x04  
#define XBOX_BUTTON_RB      0x05  
#define XBOX_BUTTON_START   0x06  
#define XBOX_BUTTON_BACK    0x07  
#define XBOX_BUTTON_HOME    0x08  
#define XBOX_BUTTON_LO      0x09    /* 左摇杆按键 */  
#define XBOX_BUTTON_RO      0x0a    /* 右摇杆按键 */  

#define XBOX_BUTTON_ON      0x01  
#define XBOX_BUTTON_OFF     0x00  

#define XBOX_AXIS_LX        0x00    /* 左摇杆X轴 */  
#define XBOX_AXIS_LY        0x01    /* 左摇杆Y轴 */  
#define XBOX_AXIS_RX        0x03    /* 右摇杆X轴 */  
#define XBOX_AXIS_RY        0x04    /* 右摇杆Y轴 */  
#define XBOX_AXIS_LT        0x02  
#define XBOX_AXIS_RT        0x05  
#define XBOX_AXIS_XX        0x06    /* 方向键X轴 */  
#define XBOX_AXIS_YY        0x07    /* 方向键Y轴 */  

#define XBOX_AXIS_VAL_UP        -32767  
#define XBOX_AXIS_VAL_DOWN      32767  
#define XBOX_AXIS_VAL_LEFT      -32767  
#define XBOX_AXIS_VAL_RIGHT     32767  

#define XBOX_AXIS_VAL_MIN       -32767  
#define XBOX_AXIS_VAL_MAX       32767  
#define XBOX_AXIS_VAL_MID       0x00  

typedef struct xbox_map  
{  
    int     time;  
    int     a;  
    int     b;  
    int     x;  
    int     y;  
    int     lb;  
    int     rb;  
    int     start;  
    int     back;  
    int     home;  
    int     lo;  
    int     ro;  

    int     lx;  
    int     ly;  
    int     rx;  
    int     ry;  
    int     lt;  
    int     rt;  
    int     xx;  
    int     yy;  

}xbox_map_t;  


int xbox_open(const char *file_name)  
{  
    int xbox_fd;  

    xbox_fd = open(file_name, O_RDONLY);  
    if (xbox_fd < 0)  
    {  
        perror("open");  
        return -1;  
    }  

    return xbox_fd;  
}  

int xbox_map_read(int xbox_fd, xbox_map_t *map)  
{  
    int len, type, number, value;  
    struct js_event js;  

    len = read(xbox_fd, &js, sizeof(struct js_event));  
    if (len < 0)  
    {  
        perror("read");  
        return -1;  
    }  

    type = js.type;  
    number = js.number;  
    value = js.value;  

    map->time = js.time;  

    if (type == JS_EVENT_BUTTON)  
    {  
        switch (number)  
        {  
            case XBOX_BUTTON_A:  
                map->a = value;  
                break;  

            case XBOX_BUTTON_B:  
                map->b = value;  
                break;  

            case XBOX_BUTTON_X:  
                map->x = value;  
                break;  

            case XBOX_BUTTON_Y:  
                map->y = value;  
                break;  

            case XBOX_BUTTON_LB:  
                map->lb = value;  
                break;  

            case XBOX_BUTTON_RB:  
                map->rb = value;  
                break;  

            case XBOX_BUTTON_START:  
                map->start = value;  
                break;  

            case XBOX_BUTTON_BACK:  
                map->back = value;  
                break;  

            case XBOX_BUTTON_HOME:  
                map->home = value;  
                break;  

            case XBOX_BUTTON_LO:  
                map->lo = value;  
                break;  

            case XBOX_BUTTON_RO:  
                map->ro = value;  
                break;  

            default:  
                break;  
        }  
    }  
    else if (type == JS_EVENT_AXIS)  
    {  
        switch(number)  
        {  
            case XBOX_AXIS_LX:  
                map->lx = value;  
                break;  

            case XBOX_AXIS_LY:  
                map->ly = value;  
                break;  

            case XBOX_AXIS_RX:  
                map->rx = value;  
                break;  

            case XBOX_AXIS_RY:  
                map->ry = value;  
                break;  

            case XBOX_AXIS_LT:  
                map->lt = value;  
                break;  

            case XBOX_AXIS_RT:  
                map->rt = value;  
                break;  

            case XBOX_AXIS_XX:  
                map->xx = value;  
                break;  

            case XBOX_AXIS_YY:  
                map->yy = value;  
                break;  

            default:  
                break;  
        }  
    }  
    else  
    {  
        /* Init do nothing */  
    }  

    return len;  
}  

void xbox_close(int xbox_fd)  
{  
    close(xbox_fd);  
    return;  
}  



int main(void)  
{  
    int xbox_fd ;  
    xbox_map_t map;  
    int len, type;  
    int axis_value, button_value;  
    int number_of_axis, number_of_buttons ;  

    memset(&map, 0, sizeof(xbox_map_t));  

    xbox_fd = xbox_open("/dev/input/js0");  
    if(xbox_fd < 0)  
    {  
        return -1;  
    }  

    while(1)  
    {  
        len = xbox_map_read(xbox_fd, &map);  
        if (len < 0)  
        {  
            usleep(10*1000);  
            continue;  
        }  

        printf("\rTime:%8d A:%d B:%d X:%d Y:%d LB:%d RB:%d start:%d back:%d home:%d LO:%d RO:%d XX:%-6d YY:%-6d LX:%-6d LY:%-6d RX:%-6d RY:%-6d LT:%-6d RT:%-6d",  
                map.time, map.a, map.b, map.x, map.y, map.lb, map.rb, map.start, map.back, map.home, map.lo, map.ro,  
                map.xx, map.yy, map.lx, map.ly, map.rx, map.ry, map.lt, map.rt);  
        fflush(stdout);  
    }  

    xbox_close(xbox_fd);  
    return 0;  
}  

运行结果如图:
这里写图片描述
可以从代码中获取各个键及方向盘的值~

如果代码报错:

warning:deprecated conversion from string constant to ‘char *’

解决方案:比较合理的办法是把参数类型修改为const char *
参考:https://blog.csdn.net/xyy410874116/article/details/6397549

主要参考

1.ubuntu下使用USB手柄
2.在UBUNTU中使用北通USB游戏手柄
3.Linux获取/dev/input目录下的event对应的设备
4.树莓派 使用xbox360手柄

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

[joysticker]使用Ubuntu读取USB手柄/方向盘的输出控制 的相关文章

随机推荐

  • Python爬虫Xpath方法返回值有[]引号等问题解决方法

    在搞Python爬虫的时候会使用到Xpath方法 xff0c 比如在爬取某个链接的时候返回值会是 39 http www baidu com demo jpg 39 示例链接 而后面的代码会因为有这几个字符串而受到影响 解决方法 xff1a
  • error: no configuration has been provided, try setting KUBERNETES_MASTER environment variable

    k8s报error no configuration has been provided try setting KUBERNETES MASTER environment variable错误解决方法1 18 1版本 使用vi编辑器打开
  • ubuntu 安装PHP+Apache

    安装Apache sudo apt install apache2 安装PHP 7 4 Ubuntu 20 04默认安装的版本 sudo apt install php libapache2 mod php 安装完成重启Apache服务 s
  • ASCII码判断大小

    ASCII码的值大小排列 xff1a a z gt A Z gt 0 9 在小写字母中z最大 xff0c a最小 在大写字母中Z最大 xff0c A最小 在0到9中 9最大 xff0c 0最小 故选D选项
  • 二进制运算相关的题目

    将二进制数01011010 转换成十进制数 xff0c 然后将十进制数 x 2 得到的值将其化为二进制数 01011010 十进制数为90 180 二进制数为10110100 故选C选项
  • 重装Ubuntu系统及系列软件安装

    重装Ubuntu系统及系列软件安装 1 安装ubuntu20 04 03系统下载Ubuntu20 04 03系统更换系统apt的源 2 CUDA和cudnn安装下载CUDA安装包并安装 3 pycharm的安装 4 conda的安装 5 兼
  • Qt中UI对象只能在主线程中操作,那如何在子线程中操作UI呢

    为什么在Qt中UI对象只能在主线程中操作 在Qt中 xff0c UI对象只能在主线程中操作 xff0c 因为Qt采用了事件循环机制 xff0c UI事件 xff08 如鼠标点击 键盘输入 xff09 都是在主线程中处理的 如果在子线程中直接
  • python学习记录

    python学习记录 python学习python运行顺序类的使用模块导入import不同级模块导入模块导入的重名问题 xff1a 注意的点 修饰器 正则表达式 python学习 本文是关于python的学习记录文章 比较基本 比较潦草 p
  • 案例二:基于MapReduce分词统计

    案例二 xff1a 基于MapReduce的分词统计 一 准备条件 xff1a 1 数据源 xff1a 六个 txt 诗经文件 2 Hadoop集群环境 五 功能实现 前提准备 xff1a 引入类库将Hadoop包解压 xff0c 并进入相
  • RHEL8.3 配置VNC 远程

    一 安装VNC 选取比较流行的tigervnc dnf install tigervnc span class token operator span server tigervnc span class token operator sp
  • 一次使用Dockerfile构建tomcat镜像时遇到的Linux内核问题

    当前版本 span class token punctuation span root 64 zyrox test alpine images span class token punctuation span span class tok
  • Java中Lambda表达式的使用

    Lambda表达式是Java SE 8中一个重要的新特性 lambda表达式允许你通过表达式来代替功能接口 lambda表达式就和方法一样 它提供了一个正常的参数列表和一个使用这些参数的主体 Lambda表达式还增强了集合库 Java SE
  • 用mscomm控件编写串口通信出现error reading comm device错误-已解决

    一 问题描述 用mscomm控件编写串口通信过程中 xff0c 在消息响应函数OnComm函数下接受串口发送过来的数据时 xff0c 在get Input 函数会出现error reading comm devece 错误 具体代码如下 x
  • 使用Spring Security后,页面iframe加载不出来

    错误 Refused to display http localhost 8080 console in a frame because it set X Frame Options to deny 解决办法 授权的时候开启iframe的加
  • 软件工程笔记八__面向对象

    1 面向对象方法四要点 xff08 1 xff09 对象 xff1a 客观世界有各种对象组成 xff0c 任何事物都是对象 xff0c 比如一支笔 xff0c 一张纸 xff0c 复杂的对象可由简单的对象以某种方式组合而成 对象分解取代功能
  • C++如何获取当前时间

    导读 文章首先介绍了使用C库的接口来获取当前时间的方法 xff0c 然后介绍了使用C 43 43 11标准库中的函数来获取当前时间的方法 此外 xff0c 文章还介绍了使用函数strftime来格式化时间字符串的方法 xff0c 并列举了常
  • Java笔记(一):volatile、synchronized关键字

    volatile关键字 volatile字面意思为易变的 不稳定的 xff0c 事实上也正是如此 这个关键字的作用就是告诉编译器 xff0c 只要是被此关键字修饰的变量都是易变的 xff0c 不稳定的 主要是volatile所修饰的变量是直
  • 读取cv.VideoCapture(0)的frame帧转变为PIL.Image图片格式时遇到的坑

    在项目中遇到一个问题是想将VideoCapture 读到的frame图片转变成PIL的Image图片格式 坑1 xff1a BGR还是RGB模式 xff1f 兴冲冲地在在网上找到一段代码 xff0c 将opencv中的imread 图像转成
  • linux命令记录

    linux三剑客 xff1a grep xff0c awk xff0c sed 1 grep命令 2 awk命令 linux中的awk命令是一种处理文本的工具 AWK命名来源于三位创始人的家族名称首字母 可以分行对文本进行处理 其命令格式如
  • [joysticker]使用Ubuntu读取USB手柄/方向盘的输出控制

    摘要 xff1a 在淘宝上买到的游戏手柄 USB卖家只给了Windows下的驱动 xff0c 本来以为Ubuntu下没有驱动 xff0c 没想到网上早已经有人用cpp开发出了USB手柄的驱动 xff0c 搜索很多博客的方法终于从手柄拿到数据