您的位置 首页 国产IC

根据S3C2440的linux驱动

MINI2440_BUTTON.C#includelinux/module.h>#includelinux/kernel.h>#includelinux/fs.h>#includel

MINI2440_BUTTON.C

#include

#include

#include

#include

#include

#include

#include

#include interrupt.h>

#include

#include

#include

#define DEVICE_NAME “buttons”

#define BUTTON_MAJOR 232

struct button_irq_desc {

int irq;

int pin;

int pin_setting;

int number;

char *name;

};

static struct button_irq_desc button_irqs [] = {

{IRQ_EINT8, S3C2410_GPG0, S3C2410_GPG0_EINT8, 0, “KEY1”},

{IRQ_EINT11, S3C2410_GPG3, S3C2410_GPG3_EINT11, 1, “KEY2”},

{IRQ_EINT13, S3C2410_GPG5, S3C2410_GPG5_EINT13, 2, “KEY3”},

{IRQ_EINT14, S3C2410_GPG6, S3C2410_GPG6_EINT14, 3, “KEY4”},

{IRQ_EINT15, S3C2410_GPG7, S3C2410_GPG7_EINT15, 4, “KEY5”},

{IRQ_EINT19, S3C2410_GPG11, S3C2410_GPG11_EINT19, 5, “KEY6”},

};

static volatile int key_values [] = {0, 0, 0, 0, 0, 0};

static DECLARE_WAIT_QUEUE_HEAD(button_waitq);

static volatile int ev_press = 0;

static irqreturn_t buttons_interrupt(int irq, void *dev_id)

{

struct button_irq_desc *button_irqs = (struct button_irq_desc *)dev_id;

int up = s3c2410_gpio_getpin(button_irqs->pin);

if (up)

key_values[button_irqs->number] = (button_irqs->number + 1) + 0x80;

else

key_values[button_irqs->number] = (button_irqs->number + 1);

ev_press = 1;

wake_up_interruptible(&button_waitq);

return IRQ_RETVAL(IRQ_HANDLED);

}

static int mini2440_buttons_open(struct inode *inode, struct file *file)

{

int i;

int err;

for (i = 0; i < sizeof(button_irqs)/sizeof(button_irqs[0]); i++) {

// 注册中止处理函数

s3c2410_gpio_cfgpin(button_irqs[i].pin,button_irqs[i].pin_setting);

err = request_irq(button_irqs[i].irq, buttons_interrupt, NULL,

button_irqs[i].name, (void *)&button_irqs[i]);

set_irq_type(button_irqs[i].irq, IRQT_BOTHEDGE);

if (err)

break;

}

if (err) {

// 开释现已注册的中止

i–;

for (; i >= 0; i–) {

disable_irq(button_irqs[i].irq);

free_irq(button_irqs[i].irq, (void *)&button_irqs[i]);

}

return -EBUSY;

}

return 0;

}

static int mini2440_buttons_close(struct inode *inode, struct file *file)

{

int i;

for (i = 0; i < sizeof(button_irqs)/sizeof(button_irqs[0]); i++) {

// 开释现已注册的中止

disable_irq(button_irqs[i].irq);

free_irq(button_irqs[i].irq, (void *)&button_irqs[i]);

}

return 0;

}

static int mini2440_buttons_read(struct file *filp, char __user *buff,

size_t count, loff_t *offp)

{

unsigned long err;

if (!ev_press) {

if (filp->f_flags & O_NONBLOCK)

return -EAGAIN;

else

wait_event_interruptible(button_waitq, ev_press);

}

ev_press = 0;

err = copy_to_user(buff, (const void *)key_values, min(sizeof(key_values), count));

memset((void *)key_values, 0, sizeof(key_values));

return err ? -EFAULT : min(sizeof(key_values), count);

}

static unsigned int mini2440_buttons_poll(

struct file *file,

struct poll_table_struct *wait)

{

unsigned int mask = 0;

poll_wait(file, &button_waitq, wait);

if (ev_press)

mask |= POLLIN | POLLRDNORM;

return mask;

}

static struct file_operations mini2440_buttons_fops = {

.owner = THIS_MODULE,

.open = mini2440_buttons_open,

.release = mini2440_buttons_close,

.read = mini2440_buttons_read,

.poll = mini2440_buttons_poll,

};

static int __init mini2440_buttons_init(void)

{

int ret;

ret = register_chrdev(BUTTON_MAJOR, DEVICE_NAME, &mini2440_buttons_fops);

if (ret < 0) {

printk(DEVICE_NAME ” cant register major number\n”);

return ret;

}

devfs_mk_cdev(MKDEV(BUTTON_MAJOR, 0), S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP, DEVICE_NAME);

printk(DEVICE_NAME ” initialized\n”);

return 0;

}

static void __exit mini2440_buttons_exit(void)

{

devfs_remove(DEVICE_NAME);

unregister_chrdev(BUTTON_MAJOR, DEVICE_NAME);

}

module_init(mini2440_buttons_init);

module_exit(mini2440_buttons_exit);

MODULE_AUTHOR(“http://www.arm9.net”); // 驱动程序的作者

MODULE_DESCRIPTION(“S3C2410/S3C2440 BUTTON Driver”); // 一些描绘信息

MODULE_LICENSE(“GPL”); // 遵从的协议

总结一下,程序结构。

按键的驱动首要是多了中止的处理,关于中止首要的处理函数是

request_irq(button_irqs[i].irq, buttons_interrupt, NULL,

button_irqs[i].name, (void *)&button_irqs[i]);

第二个参数是首要的中止处理函数。

static irqreturn_t buttons_interrupt(int irq, void *dev_id)

{

struct button_irq_desc *button_irqs = (struct button_irq_desc *)dev_id;

int up = s3c2410_gpio_getpin(button_irqs->pin);

if (up)

key_values[button_irqs->number] = (button_irqs->number + 1) + 0x80;

else

key_values[button_irqs->number] = (button_irqs->number + 1);

ev_press = 1;

wake_up_interruptible(&button_waitq);

return IRQ_RETVAL(IRQ_HANDLED);

}

别的还用到了两个重要的结构体:

static struct button_irq_desc button_irqs [] = {

{IRQ_EINT8, S3C2410_GPG0, S3C2410_GPG0_EINT8, 0, “KEY1”},

{IRQ_EINT11, S3C2410_GPG3, S3C2410_GPG3_EINT11, 1, “KEY2”},

{IRQ_EINT13, S3C2410_GPG5, S3C2410_GPG5_EINT13, 2, “KEY3”},

{IRQ_EINT14, S3C2410_GPG6, S3C2410_GPG6_EINT14, 3, “KEY4”},

{IRQ_EINT15, S3C2410_GPG7, S3C2410_GPG7_EINT15, 4, “KEY5”},

{IRQ_EINT19, S3C2410_GPG11, S3C2410_GPG11_EINT19, 5, “KEY6”},

};

struct button_irq_desc {

int irq;

int pin;

int pin_setting;

int number;

char *name;

};

而驱动程序中的最重要的部分,file_operations为

static struct file_operations mini2440_buttons_fops = {

.owner = THIS_MODULE,

.open = mini2440_buttons_open,

.release = mini2440_buttons_close,

.read = mini2440_buttons_read,

.poll = mini2440_buttons_poll,

};

程序中其他的使命便是饱满这个组织体,使得应用程序在调用open,close等的时分能够在

驱动中找到对应的项。

这儿的request_irq在open函数里调用的。

至于注册的部分跟LEDS那些是相同的,就不多说啦。

再附个应用程序供参阅:

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

int main(void)

{

int i;

int buttons_fd;

int key_value[4];

buttons_fd = open(“/dev/buttons”, 0);

if (buttons_fd < 0) {

perror(“open device buttons”);

exit(1);

}

for (;;) {

fd_set rds;

int ret;

FD_ZERO(&rds);

FD_SET(buttons_fd, &rds);

ret = select(buttons_fd + 1, &rds, NULL, NULL, NULL);

if (ret < 0) {

perror(“select”);

exit(1);

}

if (ret == 0) {

printf(“Timeout.\n”);

}

else if (FD_ISSET(buttons_fd, &rds)) {

int ret = read(buttons_fd, key_value, sizeof key_value);

if (ret != sizeof key_value) {

if (errno != EAGAIN)

perror(“read buttons\n”);

continue;

} else {

for (i = 0;i < sizeof(key_value)/sizeof(key_value[0]); i++)

printf(“K%d %s, key value = 0x%02x\n”, i+1, (key_value[i] & 0x80) ? “released” : \

key_value[i] ? “pressed down” : “”, \

key_value[i]);

}

}

}

close(buttons_fd);

return 0;

}

声明:本文内容来自网络转载或用户投稿,文章版权归原作者和原出处所有。文中观点,不代表本站立场。若有侵权请联系本站删除(kf@86ic.com)https://www.86ic.net/bandaoti/ic/264260.html

为您推荐

联系我们

联系我们

在线咨询: QQ交谈

邮箱: kf@86ic.com

关注微信
微信扫一扫关注我们

微信扫一扫关注我们

返回顶部