我们新项目的硬件设计使用了gpio口作为键,所以需要修复这个驱动。本来想自己写一个gpio口的关键驱动,然后看了kernel下面的代码,已经有了。Linux内核下游有很多很多现成的驱动程序。只要你想弄,基本都有现成的驱动。当然,一些异常的需求问题不包括在内。学习在Linux下查找驱动程序,查看驱动程序和内核代码。我认为这是一件值得享受和快乐的事情。但是,我在使用这个驱动程序时仍然遇到问题。1.ADC按键之前的文章先说一下adc按键的实现,无非就是省下一些GPIO口。RK使用SARADC制作多个按键2.GPIO按键硬件原理图3.驱动代码kernel-4.4/drivers/input/keyboard/gpio_keys.c完整代码可以查看https://gitee.com/weiqifa/gpio_key/blob/master/gpio_keys.c驱动代码流。我从probe开始的时候连dts文件都写不出来,因为之前没接触过这个驱动。然后看了gpio_keys_get_devtree_pdata函数,再看了内核代码下其他项目和平台的dts文件,才知道这个驱动的dts文件是怎么写的。说实话,这个驱动完成了很多我们需要的功能,比如防抖,比如中断,比如按键标签等等。3.1gpio_keys_get_devtree_pdata函数解析dts文件。这个文件的dts有两种解析方式,一种是直接传递给irq,另一种只传递给gpio口。在我们的项目中,只传入了gpio口。3.2gpio_keys_setup_key函数该函数用于设置gpio口的中断,直接看代码会更清楚。下面这个函数的作用我还没搞清楚。看了回调函数中的实现,就是停止打开的工作队列。但是我添加了打印,但没有打印出来。我猜是为了防止误触发,就是当按钮被按下的时间很短的时候,就会调用这个。/***devm_add_action()-addacustomactiontolistofmanagedresources*@dev:Devicethatownstheaction*@action:Functionthatshouldbecalled*@data:Pointertodatapassedto@actionimplementation**Thisaddsacustomactiontothelistofmanagedresourcessothat*itgetsexecutedaspartofstandardresourceunwinding.*/intdevm_add_action(structdevice*dev,void(*action)(void*),void*data){structaction_devres*devres;devres=devres_alloc(devm_action_release,sizeof(structaction_devres),GFP_KERNEL);if(!devres)return-ENOMEM;devres->datadata=data;devres->actionaction=action;devres_add(dev,devres);return0;}3.3驱动修改驱动修改代码如下---a/kernel-4.4/drivers/input/keyboard/gpio_keys.c+++b/kernel-4.4/drivers/input/keyboard/gpio_keys.c@@-32,6+32,11@@#include#include++#defineLOG_TAG[BUTTON]:%s()line:%d"+#definePRINTK_T(fmt,args...)printk(KERN_INFOLOG_TAGfmt,__FUNCTION__,__LINE__,##args)++structgpio_button_data{conststructgpio_keys_button*button;structinput_dev*input;@@-462,9+467,8@staticintgpio_keys_setup_key(structplatform_device*pdev,spin_lock_init(&bdata->lock);if(gpio_is_valid(button->gpio)){--error=devm_gpio_request_one(&pdev->dev,button->gpio,-GPIOF_IN,desc);+PRINTK_T("gpio:%d\n",button->gpio);+error=devm_gpio_request(&pdev->dev,button->gpio,desc);if(error<0){dev_err(dev,"FailedtorequestGPIO%d,error%d\n",button->gpio,error);@@-483,7+487,9@@staticintgpio_keys_setup_key(structplatform_device*pdev,if(button->irq){bdata->irq=button->irq;}else{+gpio_direction_input(button->gpio);irq=gpio_to_irq(button->gpio);+PRINTK_T("===weiqifa===irq:%d\n",irq);if(irq<0){error=irq;dev_err(dev,@@-540,8+546,10@@staticintgpio_keys_setup_key(structplatform_device*pdev,if(!button->can_disable)irqflags|=IRQF_SHARED;-error=devm_request_any_context_irq(&pdev->dev,bdata->irq,-isr,irqflags,desc,bdata);+PRINTK_T("===weiqifa===devm_request_threaded_irq()\n");+error=devm_request_threaded_irq(&pdev->dev,bdata->irq,NULL,+isr,irqflags|IRQF_ONESHOT,desc,bdata);if(error<0){dev_err(dev,"Unabletoclaimirq%d;error%d\n",bdata->irq,error);@@-709,6+717,8@@staticintgpio_keys_probe(structplatform_device*pdev)inti,error;intwakeup=0;+PRINTK_T("start.\n");+if(!pdata){pdata=gpio_keys_get_devtree_pdata(dev);if(IS_ERR(pdata))@@-779,6+789,8@@staticintgpio_keys_probe(structplatform_device*pdev)device_init_wakeup(&pdev->dev,wakeup);+PRINTK_T("end.\n");+return0;err_remove_group:可以肯定的是,不修改肯定会出错,你要知道这个驱动是2005年写的,中间经历了多少次系统升级,很多厂商主推ADC关键驱动,GPIO口驱动默认会被丢弃,厂商发布的SDK不会记得去完全修改它。这是驱动程序代码,所以不要认为其中没有错误您的手机是否正常运行。错误无处不在。只是我们有重启的方法。4.dts代码gpio-keys{compatible="gpio-keys";#address-cells=<1>;#size-cells=<0>;autorepeat;//pinctrl-names="default";//pinctrl-0=<&pwrbtn>;button@0{gpios=<&pio49IRQ_TYPE_EDGE_BOTH>;linux,code=;label="GPIOF13Power";linux,input-type=<1>;gpio-key,wakeup=<1>;debounce-interval=<100>;};button@1{gpios=<&pio48IRQ_TYPE_EDGE_BOTH>;linux,code=;label="GPIOF14Power";linux,input-type=<1>;gpio-key,wakeup=<1>;debounce-interval=<100>;};button@2{gpios=<&pio51IRQ_TYPE_EDGE_BOTH>;linux,code=;label="GPIOF15Power";linux,input-type=<1>;gpio-键,唤醒=<1>;去抖动间隔=<100>;};};5。烧录测试驱动后按下按钮,可以看到键值报告。