讲师博文
Linux下编写zlg7290驱动(2)--键盘驱动编写 来源 : 未知     2018-09-25

2.1. 驱动框架搭建

键盘驱动是典型的字符设备驱动,由于zlg7290使用的是I2C总线,所以这里首先搭建一个基于input子系统的驱动框架

static int zlg7290_probe(struct i2c_client *client, const struct i2c_device_id *id)

{

return 0;

}

static int zlg7290_remove(struct i2c_client *client)

{

return 0;

}

static const struct i2c_device_id zlg7290_id[] = {

{ZLG7290_NAME, 0 },

{ }

};

MODULE_DEVICE_TABLE(i2c, zlg7290_id);

static struct i2c_driver zlg7290_driver= {

.probe = zlg7290_probe,

.remove = zlg7290_remove,

.id_table = zlg7290_id,

.driver = {

.name = ZLG7290_NAME,

.owner = THIS_MODULE,

},

};

static int __init zlg7290_init(void)

{

return i2c_add_driver(&zlg7290_driver);

}

static void __exit zlg7290_exit(void)

{

i2c_del_driver(&zlg7290_driver);

}

MODULE_AUTHOR("farsight");

MODULE_DESCRIPTION("zlg7290 driver");

MODULE_LICENSE("GPL");

module_init(zlg7290_init);

module_exit(zlg7290_exit);

2.2. Input驱动框架搭建

键盘一般在内核中被注册为input设备,所以本例也需要将我们的键盘注册为一个input设备,input设备注册相关函数及结构体如下:

struct input_dev;

struct input_dev *input_allocate_device();

int input_register_device(struct input_dev *);

input_dev是linux内核中用来描述一个input设备的结构体,这个结构体用来描述一个input设备。

input_allocate_device内核中用来为input_dev分配空间的函数,这个函数不能被kmalloc等分配内存空间的函数替代,因为这个函数处理分配空间外还做了一些基本的初始化。

input_register_device内核中用来注册input_dev到linux内核中的函数,在调用这个函数前必须完成input_dev的初始化。

如下:

C++ Code

zlg7290->key = input_allocate_device();

if (zlg7290->key == NULL) {

kfree(zlg7290);

return -ENOMEM;

}

key_dev = zlg7290->key;

key_dev->name = "zlg7290";

key_dev->id.bustype = BUS_HOST;

key_dev->id.vendor = 0x0001;

key_dev->id.product = 0x0001;

key_dev->id.version = 0x0001;

key_dev->evbit[0] = BIT_MASK(EV_KEY);

for(i = 1; i <= 64; i++) {

key_dev->keybit[BIT_WORD(key_value[i])] |= BIT_MASK(key_value[i]);

}

ret = input_register_device(key_dev);

if (ret < 0) {

printk("Failed to register input device\n");

goto err1;

}

这部分代码input_allocate_device()和input_register_device()的使用比较好理解,需要注意的是input_dev初始化这部分内容

在这个input_dev一般需要初始化的主要有如下成员:

key_dev->name = "zlg7290";

key_dev->id.bustype = BUS_HOST;

key_dev->id.vendor = 0x0001;

key_dev->id.product = 0x0001;

key_dev->id.version = 0x0001;

这些成员主要是一些描述类信息。

key_dev->evbit[0] = BIT_MASK(EV_KEY);

for(i = 1; i <= 64; i++) {

key_dev->keybit[BIT_WORD(key_value[i])] |= BIT_MASK(key_value[i]);

}

key_dev->evbit[0] = BIT_MASK(EV_KEY);

evbit是设备所支持的事件类型,在这里我们使用EV_KEY作为我们的事件类型,有些设备支持多种事件类型。Linux内核时间类型很多,不同设备在注册时使用不同事件类型:

#define EV_SYN 0x00

#define EV_KEY 0x01

#define EV_REL 0x02

#define EV_ABS 0x03

#define EV_MSC 0x04

#define EV_SW 0x05

#define EV_LED 0x11

#define EV_SND 0x12

#define EV_REP 0x14

#define EV_FF 0x15

#define EV_PWR 0x16

key_dev->keybit[BIT_WORD(key_value[i])] |= BIT_MASK(key_value[i]);

keybit中每一位对应一个按键,初始化所有位都为0,当某一位被置1时,对应按键才能生效。按键需要初始化keybit,如果是其他的input设备则需要初始化其他成员,如下:

unsigned long evbit[BITS_TO_LONGS(EV_CNT)];

unsigned long keybit[BITS_TO_LONGS(KEY_CNT)];

unsigned long relbit[BITS_TO_LONGS(REL_CNT)];

unsigned long absbit[BITS_TO_LONGS(ABS_CNT)];

unsigned long mscbit[BITS_TO_LONGS(MSC_CNT)];

unsigned long ledbit[BITS_TO_LONGS(LED_CNT)];

unsigned long sndbit[BITS_TO_LONGS(SND_CNT)];

unsigned long ffbit[BITS_TO_LONGS(FF_CNT)];

unsigned long swbit[BITS_TO_LONGS(SW_CNT)];

扫码申领本地嵌入式教学实录全套视频及配套源码

上一篇:Linux下编写zlg7290驱动(1)

下一篇:Linux下编写zlg7290驱动(3)-键盘驱动编写

400-611-6270

Copyright © 2004-2024 华清远见教育科技集团 版权所有
京ICP备16055225号-5京公海网安备11010802025203号