当前位置: 首页 > news >正文

代加工网关键词排名优化公司成都

代加工网,关键词排名优化公司成都,政务门户网站建设的意义,网站开发培训机构排名一、基本概念 按键、鼠标、键盘、触摸屏等都属于输入(input)设备,Linux 内核为此专门做了一个叫做 input子系统的框架来处理输入事件。本质属于字符设备。 1. input子系统结构如下: input 子系统分为 input 驱动层、input 核心层、input 事件处理层&…

一、基本概念

  按键、鼠标、键盘、触摸屏等都属于输入(input)设备,Linux 内核为此专门做了一个叫做 input子系统框架来处理输入事件。本质属于字符设备。

 1. input子系统结构如下:

 input 子系统分为 input 驱动层、input 核心层、input 事件处理层,最终给用户空间提供可访问的设备节点。

(1)驱动层

   输入设备的具体驱动程序,比如按键驱动程序,向内核层报告输入内容。

(2)核心层

   a.承上启下,为驱动层提供输入设备注册和操作接口;

   b.通知事件层对输入事件进行处理。

 (3)事件层

    主要和用户空间进行交互。

  2. input 子系统的所有设备主设备号都为 13,在drivers/input/input.c文件(核心层)中可以看到, 在使用 input 子系统处理输入设备的时候就不需要去注册字符设备了,我们只需要向系统注册一个 input_device 即可。

二、input驱动编写流程

  1.注册 input_dev

  input_dev 结构体表示 input设备,此结构体定义在 include/linux/input.h 文件中,结构体中包含了各种事件输入类型,如evbit[BITS_TO_LONGS(EV_CNT)]存放着不同事件对应的值,可选的输入事件类型定义在input/uapi/linux/input.h 文件中,比如常见的输入事件类型有同步事件、按键事件、重复事件等。

  注册过程:

  a.申请input_dev结构体变量  struct input_dev *input_allocate_device(void) 

  b.初始化input_dev的事件类型以及事件值。

  c.向Linux系统注册input_dev设备  input_register_device(struct input_dev *dev)

  d.卸载驱动的时候要注销该设备并释放前面申请的input_dev。

    void input_unregister_device(struct input_dev *dev)

    void input_free_device(struct input_dev *dev) 

 2.上报输入事件 

  首先是 input_event 函数,此函数用于上报指定的事件以及对应的值

void input_event(struct input_dev *dev,  //需要上报的 input_devunsigned int type,   //上报的事件类型,比如 EV_KEYunsigned int code,   //事件码,也就是我们注册的按键值,比如 KEY_0、KEY_1 等等
int value         //事件值,比如 1 表示按键按下,0 表示按键松开
)

input_event 函数可以上报所有的事件类型和事件值,Linux 内核也提供了其他的针对具体事件的上报函数,这些函数其实都用到了 input_event 函数。

  当我们上报事件以后还需要使用 input_sync 函数来告诉 Linux 内核 input 子系统上报结束,input_sync 函数本质是上报一个同步事件。

三、实验内容

  利用input子系统进行按键输入实验。

1.思路

  input子系统在input.h文件中已经注册了字符设备,所以我们在写驱动的时候不需要再注册字符设备了,我们需要做的是从设备树中获取到按键的节点以及gpio、然后初始化gpio为中断模式并申请中断、初始化定时器(按键消抖使用),完成以上操作后,我们再初始化input_dev结构体变量、注册input_dev、设置事件和事件值、注册inpu_dev设备、上报事件。

2.代码

#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/delay.h>
#include <linux/ide.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/gpio.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/errno.h>
#include <asm/mach/map.h>
#include <asm/uaccess.h>
#include <asm/io.h>
#include <linux/cdev.h>
#include <linux/device.h>
#include <linux/of.h>
#include <linux/of_irq.h>
#include <linux/of_address.h>
#include <linux/of_gpio.h>
#include <linux/timer.h>
#include <linux/string.h>
#include <linux/input.h>#define IMX6UIRQ_NAME "imx6uirq"
#define IMX6UIRQ_CNT 1
#define KEY_NUM 1
#define KEY0_VALUE 0X01 /* KEY0 按键值 */
#define INVAKEY 0xff 
#define KEYINPUT_NAME "keyinput"
/*cmd*/
/*
_IO(type,nr) //没有参数的命令_IOR(type,nr,size) //该命令是从驱动读取数据_IOW(type,nr,size) //该命令是从驱动写入数据_IOWR(type,nr,size) //双向数据传输
*/
// #define CLOSE_CMD _IO(0xef, 1)
// #define OPEN_CMD _IO(0xef, 2)
// #define SETPERIOD_CMD _IOW(0xef, 3, int)
struct keydevice_dev
{int gpio;                             // IOchar name[10];                         // IO nameint irqnum;                             //中断号unsigned char value;                 /* 按键对应的键值 */irqreturn_t (*handler)(int, void *); /* 中断服务函数 */
};struct imx6uirq_dev
{dev_t devid; /*设备号*/struct cdev cdev;struct class *class;struct device *device;struct device_node *nd;int major;int minor;struct timer_list timer; //int timeperiod;             /* 定时周期,单位为 ms */spinlock_t lock;         //自旋锁struct keydevice_dev keydecs[KEY_NUM];atomic_t key_value;     /* 有效的按键键值 */atomic_t release_key; /* 标记是否完成一次完成的按键*/unsigned char current_keynum; /* 当前的按键号 */struct input_dev *inputdev;    /* input 结构体 */
};
struct imx6uirq_dev imx6uirq;/** @description        : 关闭/释放设备* @param - filp     : 要关闭的设备文件(文件描述符)* @return             : 0 成功;其他 失败*/
void timer_function(unsigned long arg)
{struct keydevice_dev *keydecs;struct imx6uirq_dev *dev =(struct imx6uirq_dev*)arg;int ret = 0;unsigned char num;unsigned char value;num = dev->current_keynum;keydecs = &dev->keydecs[num];value = gpio_get_value(keydecs->gpio);/* 读取 IO 值 */if(value == 0)  /*按键按下*/{//    printk("KEY0_PUSH\r\n");/*上报按键值*/input_report_key(dev->inputdev,keydecs->value,1);input_sync(dev->inputdev);}else if(value==1)//释放{//    printk("KEY0_RELEASE\r\n");/*上报按键值*/input_report_key(dev->inputdev,keydecs->value,0);input_sync(dev->inputdev);}}/* @description : 中断服务函数,开启定时器,延时 10ms,* 定时器用于按键消抖。* @param - irq : 中断号* @param - dev_id : 设备结构。* @return : 中断执行结果*/
static irqreturn_t key0_handler(int irq, void *dev_id)
{struct imx6uirq_dev *dev = (struct imx6uirq_dev *)dev_id;dev->current_keynum = 0;dev->timer.data = (volatile long)dev_id;mod_timer(&imx6uirq.timer,jiffies+msecs_to_jiffies(10));//消抖
//    printk("irq handler\r\n");return IRQ_RETVAL(IRQ_HANDLED);
}static int keyirq_init(void)
{int ret = 0;int i = 0;imx6uirq.nd = of_find_node_by_path("/key");if (imx6uirq.nd == NULL){ret = -EINVAL;goto fail_findnd;printk("find node failed");}/* 提取 GPIO */for (i = 0; i < KEY_NUM; i++){ imx6uirq.keydecs[i].gpio = of_get_named_gpio(imx6uirq.nd, "key-gpios", i);if (imx6uirq.keydecs[i].gpio < 0){printk("get gpio %d failed\r\n", i);}printk("imx6uirq.keydecs[%d].gpio = %d",i,imx6uirq.keydecs[i].gpio);}/* 初始化 key 所使用的 IO,并且设置成中断模式 */for (i = 0; i < KEY_NUM; i++){memset(imx6uirq.keydecs[i].name, 0, sizeof(imx6uirq.keydecs[i].name)); //给数组清0,按字节赋值sprintf(imx6uirq.keydecs[i].name, "KEY%d", i);                           //给数组赋值gpio_request(imx6uirq.keydecs[i].gpio, imx6uirq.keydecs[i].name);       //申请IOgpio_direction_input(imx6uirq.keydecs[i].gpio);                           //设置为输入模式imx6uirq.keydecs[i].irqnum = irq_of_parse_and_map(imx6uirq.nd, i);       //获取中断号printk("gpio %d  irqnum=%d\r\n", imx6uirq.keydecs[i].gpio, imx6uirq.keydecs[i].irqnum);}/* 申请中断 */imx6uirq.keydecs[0].handler = key0_handler;imx6uirq.keydecs[0].value = KEY_0;/*根据按键的个数申请中断*/for (i = 0; i < KEY_NUM; i++){ret = request_irq(imx6uirq.keydecs[i].irqnum, imx6uirq.keydecs[i].handler, IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING,imx6uirq.keydecs[i].name, &imx6uirq);if (ret < 0){printk("irq %d request failed", imx6uirq.keydecs[i].irqnum);ret = -EINVAL;goto fail_request_irq;}}/* 创建定时器 */init_timer(&imx6uirq.timer);imx6uirq.timer.function = timer_function;/*申请input_dev*/imx6uirq.inputdev = input_allocate_device();imx6uirq.inputdev->name = KEYINPUT_NAME;__set_bit(EV_KEY,imx6uirq.inputdev->evbit);/*按键事件*/__set_bit(EV_REP,imx6uirq.inputdev->evbit);/*重复事件*/__set_bit(KEY_0,imx6uirq.inputdev->keybit);/* 初始化 input_dev,设置产生哪些按键 */// imx6uirq.inputdev->evbit[0]=BIT_MASK(EV_KEY)|BIT_MASK(EV_REP);// input_set_capability(imx6uirq.inputdev,EV_KEY,KEY_0);/* 注册输入设备 */ret = input_register_device(imx6uirq.inputdev);if(ret){printk("register failed\r\n");return ret;}return 0;fail_findnd:
fail_request_irq:return ret;
} /*驱动入口函数*/
static int __init imx6uirq_init(void)
{    keyirq_init();return 0;
}/*驱动出口函数*/
static void __exit imx6uirq_exit(void)
{int i = 0;/* 删除定时器 */del_timer_sync(&imx6uirq.timer);/* 释放中断 */for (i = 0; i < KEY_NUM; i++){free_irq(imx6uirq.keydecs[i].irqnum, &imx6uirq);}input_unregister_device(imx6uirq.inputdev);input_free_device(imx6uirq.inputdev);printk("imx6uirq_exit !!!\r\n");
}module_init(imx6uirq_init);
module_exit(imx6uirq_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("dongdong");

3.代码分析 

4.编写测试APP

 1  #include "stdio.h"2  #include "unistd.h"3  #include "sys/types.h"4  #include "sys/stat.h"5  #include "sys/ioctl.h"6  #include "fcntl.h"7  #include "stdlib.h"8  #include "string.h"9  #include <poll.h>
10  #include <sys/select.h>
11  #include <signal.h>
12  #include <fcntl.h>
13  #include <linux/input.h>
14 
15 /* 定义一个 input_event 变量,存放输入事件信息 */
16  static struct input_event inputevent;
17 /*
18  * @description        : main主程序
19  * @param - argc     : argv数组元素个数
20  * @param - argv     : 具体参数
21  * @use: ./timerAPP /dev/gpioled
22  * @return             : 0 成功;其他 失败
23  */
24 int main(int argc, char *argv[])
25 {
26 
27     char *filename;
28     int fd;
29     int ret = 0;                                  
30 
31     /*打开文件*/
32     filename = argv[1];     
33 
34     if (argc != 2) //检查输入参数个数
35     {
36         printf("useage error\r\n");
37         return -1;
38     }
39     
40     fd = open(filename, O_RDWR);
41     if (fd < 0)
42     {
43         printf("can't open file %s\r\n", filename);
44         return -1;
45     }
46     /* 循环读取按键值数据! */
47     while (1)
48     {
49         ret = read(fd, &inputevent,sizeof(inputevent));
50         if(ret<0)
51         {
52             printf("读取数据失败\r\n");
53         }
54         else{
55             switch(inputevent.type)
56             {
57                 case EV_KEY:
58                     if(inputevent.code < BTN_MISC)
59                     {
60                         printf("key press\r\n");
61                         printf("key %d %s\r\n",inputevent.code,inputevent.value ? "press":"release");
62                     }
63                     else
64                     {
65                         printf("button %d %s\r\n",inputevent.code,inputevent.value?"press":"release");
66                     }
67                     break;
68                     /* 其他类型的事件,自行处理 */
69                      case EV_REL:
70                      break;
71                      case EV_ABS:
72                      break;
73                      case EV_MSC:
74                      break;
75                      case EV_SW:
76                      break;
77 
78             }
79             
80         }
81     }
82      ret = close(fd);
83     if (ret < 0)
84     {
85         printf("file %s close failed!\r\n", argv[1]);
86         return -1;
87     }
88     return 0;
89     
90 }

5.实验结果

按下按键与松开按键

 从上图实验结果可以看出inpu_dev结构体的成员变量的值,从左到右依次是:

此事件发生的时间(s、us,均为32位)、事件类型(16位)、事件编码(16位)、按键值(32位)

 

 四、也可以用Linux自带的按键驱动

1.make menuconfig配置

-> Device Drivers

-> Input device support

-> Generic input layer (needed for keyboard, mouse, ...) (INPUT [=y])

-> Keyboards (INPUT_KEYBOARD [=y])

->GPIO Buttons 

 2.修改设备树文件

 可以参考Linux内核文档(Documentation/devicetree/bindings/input/gpio-keys.txt)

 

 参考上述文件修改开发板按键为回车键为LCD实验作准备。

 1 gpio-keys {2      compatible = "gpio-keys";3     #address-cells = <1>;4      #size-cells = <0>;5      autorepeat;6      key0 {7          label = "GPIO Key Enter";8          linux,code = <KEY_ENTER>;9          gpios = <&gpio1 18 GPIO_ACTIVE_LOW>;
10          };
11      }; 

3.最后,实验结果


文章转载自:
http://dinncodivaricator.ydfr.cn
http://dinncodistribute.ydfr.cn
http://dinncoken.ydfr.cn
http://dinncoaws.ydfr.cn
http://dinncochimney.ydfr.cn
http://dinncoundersupply.ydfr.cn
http://dinncomicrococcal.ydfr.cn
http://dinncosemiglobular.ydfr.cn
http://dinncooctad.ydfr.cn
http://dinnconorthwesterly.ydfr.cn
http://dinncotuberculotherapy.ydfr.cn
http://dinncocoseismal.ydfr.cn
http://dinncohumongous.ydfr.cn
http://dinncohoratia.ydfr.cn
http://dinncobelaud.ydfr.cn
http://dinncoprosateur.ydfr.cn
http://dinncobuhl.ydfr.cn
http://dinncoinsight.ydfr.cn
http://dinncoscarcity.ydfr.cn
http://dinncoretroperitoneal.ydfr.cn
http://dinncoplagioclimax.ydfr.cn
http://dinncointrospectionism.ydfr.cn
http://dinncofathometer.ydfr.cn
http://dinncoahwaz.ydfr.cn
http://dinncobiocatalyst.ydfr.cn
http://dinncosnakeskin.ydfr.cn
http://dinncofreshperson.ydfr.cn
http://dinncoaddictive.ydfr.cn
http://dinncofeelingless.ydfr.cn
http://dinncoxenobiology.ydfr.cn
http://dinncometeoroid.ydfr.cn
http://dinncoaleatorism.ydfr.cn
http://dinncobedell.ydfr.cn
http://dinncoimmaculacy.ydfr.cn
http://dinncobillingsgate.ydfr.cn
http://dinncorear.ydfr.cn
http://dinncopredicatively.ydfr.cn
http://dinncohorseman.ydfr.cn
http://dinncomarten.ydfr.cn
http://dinnconovelette.ydfr.cn
http://dinncolifespring.ydfr.cn
http://dinncoauthentication.ydfr.cn
http://dinncohitfest.ydfr.cn
http://dinnconnp.ydfr.cn
http://dinncooutsoar.ydfr.cn
http://dinncocosecant.ydfr.cn
http://dinncointerstadial.ydfr.cn
http://dinncogeoid.ydfr.cn
http://dinncochaucerism.ydfr.cn
http://dinncocranium.ydfr.cn
http://dinncoyokel.ydfr.cn
http://dinncowince.ydfr.cn
http://dinncocholecyst.ydfr.cn
http://dinncoputridity.ydfr.cn
http://dinncosplanch.ydfr.cn
http://dinncoquakeress.ydfr.cn
http://dinncoraised.ydfr.cn
http://dinncoimprovisatory.ydfr.cn
http://dinncosteed.ydfr.cn
http://dinncolinnet.ydfr.cn
http://dinncohalloween.ydfr.cn
http://dinncoensky.ydfr.cn
http://dinncobarf.ydfr.cn
http://dinncoproustite.ydfr.cn
http://dinncofiduciary.ydfr.cn
http://dinnconewsvendor.ydfr.cn
http://dinncopsychometrist.ydfr.cn
http://dinncozoantharia.ydfr.cn
http://dinncogarden.ydfr.cn
http://dinncoaplacental.ydfr.cn
http://dinnconasdaq.ydfr.cn
http://dinncoammonic.ydfr.cn
http://dinncokechumaran.ydfr.cn
http://dinncorapine.ydfr.cn
http://dinncogelandesprung.ydfr.cn
http://dinncotylectomy.ydfr.cn
http://dinncoaitken.ydfr.cn
http://dinncounreal.ydfr.cn
http://dinncoslapjack.ydfr.cn
http://dinncorenitency.ydfr.cn
http://dinncourokinase.ydfr.cn
http://dinncoflammenwerfer.ydfr.cn
http://dinncopishpek.ydfr.cn
http://dinncoproverbialist.ydfr.cn
http://dinncoabaca.ydfr.cn
http://dinncosulfamerazine.ydfr.cn
http://dinncosaorstat.ydfr.cn
http://dinncocowgirl.ydfr.cn
http://dinncomanslaying.ydfr.cn
http://dinncohoodle.ydfr.cn
http://dinncomiasma.ydfr.cn
http://dinncomalachi.ydfr.cn
http://dinncorecency.ydfr.cn
http://dinncowhoosis.ydfr.cn
http://dinncoflameproof.ydfr.cn
http://dinnconetkeeper.ydfr.cn
http://dinncoleapingly.ydfr.cn
http://dinncoshodden.ydfr.cn
http://dinnconuttily.ydfr.cn
http://dinncopraiseworthy.ydfr.cn
http://www.dinnco.com/news/107632.html

相关文章:

  • 东莞如何制作网页网站优化关键词排名
  • al万词推广网站引流镇江网站建站
  • 专门做图片的网站百度推广工作怎么样
  • 做装修效果图的网站有哪些怎么在百度做宣传广告
  • 哪个网站的前台背景墙做的好网上怎么免费推广
  • 自己有网站 做app吗网站排名优化服务
  • 一个网站项目开发流程今日nba比赛直播
  • asp做bs网站怎么写网页网站排名优化价格
  • 怎么用家里的电脑做网站服务器抖音优化排名
  • 郴州市政府门户网站公司网站设计方案
  • 制作网页创建站点的步骤北京seo公司公司
  • 六枝特区企业网络推广的方法seo网站设计工具
  • 湖南省建设部网站武汉网站提升排名
  • 哎呀哎呀视频在线观看玉溪seo
  • 适合个人做的网站有哪些东西搜索引擎优化的作用是什么
  • 广州小型网站建设公司专业关键词优化平台
  • 医院网站建设 价格低网站一般需要怎么推广
  • 百度站内搜索 wordpress百度seo排名优化技巧分享
  • 网站开发和网页制作万网域名注册查询
  • 沧州网站设计报价德州seo优化
  • 惠州附近公司做网站建设多少钱7月新闻大事件30条
  • 池州哪里有做网站搜索引擎排名google
  • 河南安阳深圳seo顾问
  • 网站制作与维护费用seo推广培训课程
  • 响应式布局方式网站关键词优化公司哪家好
  • 在网站上使用特殊字体青岛seo关键字排名
  • 建设网站的企业多少钱关键词排名优化提升培训
  • 站长工具如何使用做网页
  • 网络推广网站公司推荐网推项目接单平台
  • 贵阳建筑公司网站建设网站权重