linux窗口旋转代码,让linux支持EC11等旋转编码器

最近,产品基本定型了,所以开始着手升级版。说是升级版,只是在操作上面有所修改。产品需要使用旋钮进行人机交互。对linux驱动十窍通了九窍,一窍不通,所以从最低级的开始看起,然后把gpio_key.c这个东西,看了一遍又一遍。都快看吐了

0818b9ca8b590ca3270a3433284dd417.png

首先修改设备树文件,这个东西是linux3.0的新东西,弄的我无限糊涂,到现在依然糊涂。我只能稍微修改一点需要的东西,让我写肯定写不出来。以后再慢慢研究。在这个文件的KEY_X0里面,把对应的

0818b9ca8b590ca3270a3433284dd417.png,改成

0818b9ca8b590ca3270a3433284dd417.png。因为是使用设备树这种方式,所以需要修改对应的gpio_keys_get_devtree_pdata这个函数,

0818b9ca8b590ca3270a3433284dd417.png

0818b9ca8b590ca3270a3433284dd417.png

修改以上两处,这个函数的改动就结束了。这样改完编译会发现有错误,因为button里面没有ckgpio这些东西。所以修改对应linux目录中include/linux/gpio_key.h

struct gpio_keys_button {

/* Configuration parameters */

unsigned int code;/* input event code (KEY_*, SW_*) */

int gpio;/* -1 if this key does not support gpio */

int active_low;

const char *desc;

unsigned int type;/* input event type (EV_KEY, EV_SW, EV_ABS) */

int wakeup;/* configure the button as a wake-up source */

int debounce_interval;/* debounce ticks interval in msecs */

bool can_disable;

int value;/* axis value for EV_ABS */

unsigned int irq;/* Irq number in case of interrupt keys */

};改成:

struct gpio_keys_button {

/* Configuration parameters */

unsigned int code;/* input event code (KEY_*, SW_*) */

int gpio;/* -1 if this key does not support gpio */

int active_low;

const char *desc;

unsigned int type;/* input event type (EV_KEY, EV_SW, EV_ABS) */

int wakeup;/* configure the button as a wake-up source */

int debounce_interval;/* debounce ticks interval in msecs */

bool can_disable;

int value;/* axis value for EV_ABS */

unsigned int irq;/* Irq number in case of interrupt keys */

int ckgpio; /*zxf*/ 保存旋转编码器的另外一个引脚

unsigned int oldcode; 记录原始键值

unsigned int ckcode; /*zxf*/ 记录新键值

};这样设备树就修改完了。

接下来修改中断触发方式,我只需下降沿,就可以判断是正转还是反转了,所以:

if (button->ckgpio != button->gpio)

irqflags = IRQF_TRIGGER_FALLING;对应旋钮部分

else

irqflags = IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING;对应按键部分

因为ec11这种东西有旋钮部分,也有按钮部分,所以把对应的中断响应函数进行了区分,按钮部分不动,旋钮部分改成:

static irqreturn_t gpio_knob_gpio_isr(int irq, void *dev_id)

{

struct gpio_button_data *bdata = dev_id;

BUG_ON(irq != bdata->irq);

if(gpio_get_value(bdata->button->ckgpio) )判断对应的另外一个引脚电平状态。

bdata->button->code = bdata->button->oldcode;

else

bdata->button->code = bdata->button->ckcode;

//printk(KERN_ALERT"gpio:%d, ckgpio:%d, check=%d", bdata->button->gpio, bdata->button->ckgpio,bdata->button->check);

if (bdata->timer_debounce)

mod_timer(&bdata->timer,

jiffies + msecs_to_jiffies(bdata->timer_debounce));

else

schedule_work(&bdata->work);

return IRQ_HANDLED;

}中断分为上半部分,和下半部分,上述代码是中断的上半部分。功能就是检测另外一个引脚的点评状态,并给code赋不同的键值。

中断的下半部分,事件上报函数改成:

static void gpio_knob_gpio_report_event(struct gpio_button_data *bdata)

{

struct gpio_keys_button *button = bdata->button;

struct input_dev *input = bdata->input;

unsigned int type = button->type ?: EV_KEY;

input_event(input, type, button->code, 1);

//printk(KERN_ALERT"type:%d,code:%d\n", type,button->code);

input_sync(input);

input_event(input, type, button->code, 0);

//printk(KERN_ALERT"type:%d,code:%d\n", type,button->code);

input_sync(input);

}可以看到这里面有两条重复的语句,原因是按键有按下和放开两个状态,而我的旋钮,我值捕捉到了下降沿,所以上升沿部分我自己编造一个,反正内核不知道我是认为编造的。红色部分很重要,如果只有蓝色部分,那就相当于按键一直按下,而没有弹起。cat event*会发现一直不停的输出。我在这就卡了两天,因为没有好好理解什么是key。

中断部分修改完了以后,修改gpio_keys_setup_key()函数。

if (gpio_is_valid(button->gpio)) {

error = gpio_request(button->gpio, desc);

if (error < 0) {

dev_err(dev, "Failed to request GPIO %d, error %d\n",

button->gpio, error);

return error;

}

if (button->ckgpio != button->gpio){

error = gpio_request(button->ckgpio, desc);

if (error < 0) {

dev_err(dev, "Failed to request GPIO %d, error %d\n",

button->ckgpio, error);

return error;

}

}

error = gpio_direction_input(button->gpio);

if (error < 0) {

dev_err(dev,

"Failed to configure direction for GPIO %d, error %d\n",

button->gpio, error);

goto fail;

}

if (button->ckgpio != button->gpio){

error = gpio_direction_input(button->ckgpio);

if (error < 0) {

dev_err(dev,

"Failed to configure direction for GPIO %d, error %d\n",

button->ckgpio, error);

goto fail;

}

}就是增加了对旋钮部分按键的配置操作。

现在编译应该可以通过,使用hexdump测试event会发现,只有一个方向的旋转才有输出。另一个方向是没有反映的,通过跟踪代码发现,是在input_handle_event()函数出现的问题:

case EV_KEY:

if (is_event_supported(code, dev->keybit, KEY_MAX) &&

!!test_bit(code, dev->key) != value) {

if (value != 2) {

__change_bit(code, dev->key);

if (value)

input_start_autorepeat(dev, code);

else

input_stop_autorepeat(dev);

}

disposition = INPUT_PASS_TO_HANDLERS;

}

break;红色部分就是跟踪后发现问题的地方,另一个方向旋转并不能进入到这个if语句中,再继续跟踪发现:

static inline int is_event_supported(unsigned int code, unsigned long *bm, unsigned int max)

{

return code <= max && test_bit(code, bm);

}这个函数的test_bit函数出的问题,它会测试input_dev是否支持这个键值。这个地方卡了我两周的时间,因为不了解linux的输入子系统。我现在还不知道,可以上报的那个键值是在哪设置的,有知道的前辈请不吝告诉我。为了让input_dev支持另外一个键值,在gpio_keys_setup_key()函数增加如下代码:

set_bit(button->ckcode, input->keybit);这样就可以了。 这个事情进行到一半的时候,想过自己重新写。可是真的没有信心能写出来,这个事情我还欠缺很多。把原文件也是弄得面目全非。以后再继续学习把。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值