S5PV210(TQ210)学习笔记――按键驱动程序 (二)

2014-11-24 03:25:54 · 作者: · 浏览: 1
tk(KERN_ERR "The driver can not copy the data to user area!\n");
return -ENOMEM;
}

return 0;
}

static int buttons_close(struct inode *inode, struct file *file){
free_irq(IRQ_EINT(0), &key_descs[0]);
free_irq(IRQ_EINT(1), &key_descs[1]);
free_irq(IRQ_EINT(2), &key_descs[2]);
free_irq(IRQ_EINT(3), &key_descs[3]);
free_irq(IRQ_EINT(4), &key_descs[4]);
free_irq(IRQ_EINT(5), &key_descs[5]);
free_irq(IRQ_EINT(22), &key_descs[6]);
free_irq(IRQ_EINT(23), &key_descs[7]);
return 0;
}

struct file_operations buttons_ops = {
.open = buttons_open,
.read = buttons_read,
.release = buttons_close,
};

int buttons_init(void){
int ret;

cdev_init(&cdev, &buttons_ops);
cdev.owner = THIS_MODULE;

ret = alloc_chrdev_region(&devno, 0, 1, "buttons");
if(ret){
printk(KERN_ERR "alloc char device region faild!\n");
return ret;
}

ret = cdev_add(&cdev, devno, 1);
if(ret){
printk(KERN_ERR "add char device faild!\n");
goto add_error;
}

buttons_class = class_create(THIS_MODULE, "buttonsdrv");
if(IS_ERR(buttons_class)){
printk(KERN_ERR "create class error!\n");
goto class_error;
}

buttons_device = device_create(buttons_class, NULL, devno, NULL, "buttons");
if(IS_ERR(buttons_device)){
printk(KERN_ERR "create buttons device error!\n");
goto device_error;
}

init_waitqueue_head(&button_waitq);

return 0;

device_error:
class_destroy(buttons_class);
class_error:
cdev_del(&cdev);
add_error:
unregister_chrdev_region(devno,1);

return -ENODEV;
}

void buttons_exit(void){
device_destroy(buttons_class, devno);
class_destroy(buttons_class);
cdev_del(&cdev);
unregister_chrdev_region(devno, 1);
}

module_init(buttons_init);
module_exit(buttons_exit);
MODULE_LICENSE("GPL");

#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include

static dev_t devno;
static struct cdev cdev;
static struct class* buttons_class;
static struct device* buttons_device;

static wait_queue_head_t button_waitq;

static volatile int pressed = 0;
static unsigned char key_val;

struct key_desc{
unsigned int pin;
unsigned char value;
};

static struct key_desc key_descs[8] = {
[0] = {
.pin = S5PV210_GPH0(0),
.value = 0x00,
},

[1] = {
.pin = S5PV210_GPH0(1),
.value = 0x01,
},

[2] = {
.pin = S5PV210_GPH0(2),
.value = 0x02,
},

[3] = {
.pin = S5PV210_GPH0(3),
.value = 0x03,
},

[4] = {
.pin = S5PV210_GPH0(4),
.value = 0x04,
},

[5] = {
.pin = S5PV210_GPH0(5),
.value = 0x05,
},

[6] = {
.pin = S5PV210_GPH2(6),
.value = 0x06,
},

[7] = {
.pin = S5PV210_GPH2(7),
.value = 0x07,
},
};

static irqreturn_t buttons_irq(int irq, void *dev_id){
volatile struct key_desc *key = (volatile struct key_desc *)dev_id;

if(gpio_get_value(key->pin)){
key_val = key->value|0x80;
}
else{
key_val = key->value;
}

pressed = 1;
wake_up_interruptible(&button_waitq);

return IRQ_RETVAL(IRQ_HANDLED);
}

static int buttons_open(struct inode *inode, struct file *file){
int ret;

ret = request_irq(IRQ_EINT(0), buttons_irq, IRQ_TYPE_EDGE_BOTH, "key1", &key_descs[0]);
if(ret)
return ret;
ret = request_irq(IRQ_E