1. 找到键盘设备

linux的键盘设备在 /dev/input/eventX 中,通过 ls /dev/input 通常会看到很多个eventX

那么哪个才是键盘?继续使用指令 cat /proc/bus/input/devices 查看各个设备的描述,通过关键字 keyboard 可以定位到 event1

2. 读取按键

按照linux “一切皆文件” 的特点,读取按键只需三步,open、read和解析,特别注意的是读取的数据为 struct input_event 结构

#include <linux/input.h>
... ...
struct input_event key_info;
... ...
if (read(fd, &key_info, sizeof(struct input_event)) > 0)
{//这是按键事件if (key_info.type == EV_KEY)//是哪个按键 及 按键状态printf("按键: %d 状态: %d \r\n", key_info.code, key_info.value);
}
  • key_info.code 是按键对应的标号,比如数字键1对应标号为2,具体对应可以在 linux/input.h 中查看(下面给出一段截图),或者把要用的按键都按一遍打印出来就知道了;
  • key_info.value 是按键状态,只有三种数值,0/松开 1/按下 2/按住(按住不放会连续触发这个事件);特别注意的是,当已经有按键(假设按键a)处于 2/按住 状态时,再去按别的按键(假设按键b),会先读到按键b的 1/按下 事件,而按键a的 2/按住 事件将不再触发,如果继续按住b不放会连续触发按键b的 2/按住 事件,而按键a只会在松开时触发 0/松开 事件;如果有更多的按键同时操作,逻辑同上。

3. 代码示例

鉴于前面提到的多按键同时按下会掩盖掉前面按键的 2/按住 事件问题,以下代码对 2/按住 事件进行了自行管理,可自行定义最大同时按下按键数和连续触发间隔。

  • key.h
#ifndef _KEY_H_
#define _KEY_H_/**  如何确认键盘在"/dev/input/event"几号?*  通过"cat /proc/bus/input/devices"可以看到"keyboard"所在的event号*/
#define INPUT_DEV_PATH "/dev/input/event1"/**  按键回调注册*  参数:*      obj: 用户私有指针,会在互调的时候传回给用户*      callback: 回调函数原型 void callback(void *obj, int key, int type)*  回调函数参数:*      obj: 前面传入的用户私有指针*      key: 键位,可以看头文件<linux/input.h>中的定义,或者先测试打印一遍就知道哪个按键对哪个值了*      type: 按键状态,0/松开时,1/按下时,2/一直按住(会反复触发回调,间隔多久我也忘了)*  返回: 0/成功 -1/失败,找不到设备或者没有sudo运行*/
int key_register(void *obj, void (*callback)(void *, int, int));#endif
  • key.c
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <linux/input.h>#include "key.h"//支持最大同按下的按键数量
#define KEY_COMBINATION 10//长按按键时会反复触发事件,这里设置时间间隔ms,为0时不触发长按事件
#define KEY_HOLD_EVENT_INTERVALMS 50//本地主结构体
typedef struct
{int fd;void *obj;void (*callback)(void *, int, int);
} Key_Struct;//回调线程传入参数结构体(就是把一堆参数打包成一个好传递)
typedef struct
{void *obj;int key;int type;void (*callback)(void *, int, int);//数组指针int *combin;
} Key_Param;//延时工具
#include <sys/time.h>
void key_delayms(unsigned int ms)
{struct timeval tv;tv.tv_sec = ms / 1000;tv.tv_usec = ms % 1000 * 1000;select(0, NULL, NULL, NULL, &tv);
}//抛线程工具
static void throwOut_thread(void *obj, void (*callback)(void *))
{pthread_t th;pthread_attr_t attr;//attr initpthread_attr_init(&attr);pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); //禁用线程同步, 线程运行结束后自动释放//抛出线程pthread_create(&th, &attr, (void *)callback, (void *)obj);//attr destroypthread_attr_destroy(&attr);
}//回调线程,在这里回调用户传入的callback函数
static void key_callback(void *argv)
{Key_Param *kp = (Key_Param *)argv;do {//按键事件回调if (kp->callback)kp->callback(kp->obj, kp->key, kp->type);//该值为0时,不触发长按事件if (KEY_HOLD_EVENT_INTERVALMS > 0) {//按下事件,经过2倍延时后切换为长按事件if (kp->type == 1) {key_delayms(KEY_HOLD_EVENT_INTERVALMS * 2);kp->type = 2;}//长按事件else if (kp->type == 2)key_delayms(KEY_HOLD_EVENT_INTERVALMS);}//周期触发长按事件} while (kp->type == 2 && kp->combin[0] == kp->key);free(kp);
}//数组元素的设置和清除,返回位置
static int _arrayAdd(int *array, int len, int value)
{int i;for (i = 0; i < len; i++) {if (array[i] == 0) {array[i] = value;return i;}}return 0;
}
static int _arrayClear(int *array, int len, int value)
{int i;for (i = 0; i < len; i++) {if (array[i] == value) {array[i] = 0;return i;}}return 0;
}static void key_thread(void *argv)
{Key_Struct *ks = (Key_Struct *)argv;Key_Param *kp;struct input_event key_info;int order;int combin[KEY_COMBINATION] = {0};while (1){//阻塞读if (read(ks->fd, &key_info, sizeof(struct input_event)) > 0){//这是按键类事件(触屏类事件也是这样读的)if (key_info.type == EV_KEY){if (!ks->callback || key_info.value > 1)continue;//按键按下时注册到数组,释放时清除order = 0;if (key_info.value == 1)order = _arrayAdd(combin, KEY_COMBINATION, key_info.code);else_arrayClear(combin, KEY_COMBINATION, key_info.code);//参数准备kp = (Key_Param *)calloc(1, sizeof(Key_Param));kp->obj = ks->obj;kp->key = key_info.code;   //键位kp->type = key_info.value; //键值kp->callback = ks->callback;kp->combin = &combin[order];//抛线程,在异步线程中触发用户回调函数throwOut_thread(kp, &key_callback);}}}
}/**  按键回调注册*  参数:*      obj: 用户私有指针,会在互调的时候传回给用户*      callback: 回调函数原型 void callback(void *obj, int key, int type)*  回调函数参数:*      obj: 前面传入的用户私有指针*      key: 键位值,可以看<linux/input.h>中的定义,或者先测试打印一遍就知道哪个按键对哪个值了*      type: 按键状态,0/松开时,1/按下时,2/一直按住(会反复触发回调)*  返回: 0/成功 -1/失败,找不到设备或者没有sudo运行*/
int key_register(void *obj, void (*callback)(void *, int, int))
{Key_Struct *ks;//关键参数检查if (!callback)return -1;//只读打开键盘所在input设备int fd = open(INPUT_DEV_PATH, O_RDONLY);if (fd < 1){printf("key_register: open %s failed\r\n", INPUT_DEV_PATH);return -1;}//参数备份,抛线程检测按键ks = (Key_Struct *)calloc(1, sizeof(Key_Struct));ks->fd = fd;ks->obj = obj;ks->callback = callback;throwOut_thread(ks, &key_thread);return 0;
}
  • main.c
#include <stdio.h>
#include <unistd.h>
#include "key.h"void key_callback(void *obj, int key, int type)
{printf("key/%d type/%d\r\n", key, type);
}int main(void)
{key_register(NULL, &key_callback);while(1)sleep(1);return 0;
}
  • 编译: gcc -o out main.c key.c -lpthread
  • 运行: sudo ./out (由于打开 /dev/input/event1 需要管理员权限)

推荐文章

https://blog.csdn.net/lanmanck/article/details/8423669

Linux键盘输入读取相关推荐

  1. qt 调用linux键盘输入,嵌入式linux上QT标准键盘输入的实现

    1.嵌入式linux上QT标准键盘输入的实现 在嵌入式平台上运行QTE时,使用的键盘通常不是标准键盘,而是嵌入式设备外扩的普通按键.那么实现QTE键盘输入的方法大体上可以分为两类: (1)编写一个普通 ...

  2. linux键盘输入重复,关于修改键盘输入

    该楼层疑似违规已被系统折叠 隐藏此楼查看此楼 #include #include #include #include #define KBD_IRQ 1 /* IRQ number for keybo ...

  3. python获取键盘输入_python之判断数据异常Python读取键盘输入

    Python提供了两个内置函数从标准输入读入一行文本,默认的标准输入是键盘.如下: <python之判断数据异常Python读取键盘输入>总结了关于python网站教程,对于我们来www. ...

  4. python键盘输入数组_python 二维数组切割Python读取键盘输入的2种方法

    Python提供了两个内置函数从标准输入读入一行文本,默认的标准输入是键盘.如下: 1.raw_input 2.input raw_input函数raw_input() 函数从标准输入读取一个行,并返 ...

  5. python二维数组换行输出_python 二维数组切割Python读取键盘输入的2种方法

    Python提供了两个内置函数从标准输入读入一行文本,默认的标准输入是键盘.如下: 1.raw_input 2.input raw_input函数raw_input() 函数从标准输入读取一个行,并返 ...

  6. QT接收Linux内核,嵌入式linux上QT标准键盘输入的实现

    在嵌入式平台上运行QTE时,使用的键盘通常不是标准键盘,而是嵌入式设备外扩的普通按键.那么实现QTE键盘输入的方法大体上可以分为两类: (1)编写一个普通按键驱动,然后开辟一个QT线程读取按键值,在通 ...

  7. 【shell】实现交互|read读取键盘输入

    目录 一.SHELL 1.1 输入单个指令 1.2 输入多行指令 限制输入内容的个数 控制输入内容的可见性 二.Expect 简介 for 中嵌套 expect 在expect中使用shell的环境变 ...

  8. linux shell 键盘输入 $,linuxshell在while中用read从键盘输入的实现

    系统是ubuntu 14.04 64bit,之前曾想安装Stream来玩dota2,但最终没成功.由于Stream只有32bit,安装Stream时也安装了大量32bit的库.删除Stream后,这些 ...

  9. linux中用参数代替键盘输入,linux shell在while中用read从键盘输入的实现

    系统是ubuntu 14.04 64bit,之前曾想安装stream来玩dota2,但最终没成功.由于stream只有32bit,安装stream时也安装了大量32bit的库.删除stream后,这些 ...

  10. qt linux软键盘拼音,嵌入式linux上Qt键盘输入实现拼音输入法

    作者:刘洪涛, 在嵌入式平台上运行QTE时,使用的键盘通常不是标准键盘,而是嵌入式设备外扩的普通按键.那么实现QTE键盘输入的方法大体上可以分为两类: (1)编写一个普通按键驱动,然后开辟一个QT线程 ...

最新文章

  1. ORA-00904 的解决
  2. centos6下的mysql的安装
  3. Python 函数参数传递
  4. java双链表基本方法_Java数据结构之双端链表原理与实现方法
  5. java让对象分配在栈上_java – Hotspot何时可以在堆栈上分配对象?
  6. Open-Falcon 监控系统监控 MySQL/Redis/MongoDB 状态监控
  7. Android中ProgressDialog的应用
  8. DIV CSS BackGround属性研究
  9. 论文 计算机网络技术的功能,计算机网络技术在有线电视网络中的作用论文
  10. linux为mysql创建gpower_系统运维|RHEL/CentOS 7中安装并配置 PowerDNS 和 PowerAdmin
  11. python入口文件_python常用模块:项目目录规范、定制程序入口、自定义模块、引用变量、time和datetime模块...
  12. 扫锚工具:xscan.exe
  13. windows 控制台cmd乱码的解决办法 chcp 65001
  14. Golang 信息采集
  15. 大学生面试20个经典问题及回答思路!
  16. c#winform利用opencvsharp的Floodfill实现类似PS魔棒功能
  17. 用计算机怎么打出箭头,电脑左箭头怎么打出来(电脑键盘怎么打符号)
  18. 河北工业大学城市学院2019级 Java企业级系统管理期末复习资料
  19. python支付程序源码_Python提取支付宝和微信支付二维码的示例代码
  20. 2 pygraphviz在windows10 64位下的安装问题(反斜杠的血案)

热门文章

  1. Milet谷仓:区块链电商先行者
  2. VSCode Python运行环境配置
  3. 愿与岁月共白头,且以深情寄余生
  4. python 滚动字幕_python – 在PyQt中滚动文本?
  5. C#操作excel的打印分页符问题
  6. VUE解决路由里的参数改变页面却没有跳转的问题
  7. 优矿量化如何完成Alpha对冲模型测试?
  8. 从安防监控走进手机VR 红外线LED翻身
  9. python中base函数_详细的python basemap中各函数的所有参量注释
  10. iapp教程从入门到精通全部,iapp怎么做软件教程