分类: 嵌入式
2011-09-30 17:44:23
/*
* Mini-2440按键驱动
* Lzy 2011-9-30
*/
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define DEVICE_NAME "mybut"
static int led_major = 0;
static int led_minor = 0;
struct cdev *led_device;
static unsigned long led_table [] = {
S3C2410_GPB(5),
S3C2410_GPB(6),
S3C2410_GPB(7),
S3C2410_GPB(8),
};
static unsigned int led_cfg_table [] = {
S3C2410_GPIO_OUTPUT,
S3C2410_GPIO_OUTPUT,
S3C2410_GPIO_OUTPUT,
S3C2410_GPIO_OUTPUT,
};
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_GPG(0) , S3C2410_GPG0_EINT8 , 0, "KEY0"},
{IRQ_EINT11, S3C2410_GPG(3) , S3C2410_GPG3_EINT11 , 1, "KEY1"},
{IRQ_EINT13, S3C2410_GPG(5) , S3C2410_GPG5_EINT13 , 2, "KEY2"},
{IRQ_EINT14, S3C2410_GPG(6) , S3C2410_GPG6_EINT14 , 3, "KEY3"},
{IRQ_EINT15, S3C2410_GPG(7) , S3C2410_GPG7_EINT15 , 4, "KEY4"},
{IRQ_EINT19, S3C2410_GPG(11), S3C2410_GPG11_EINT19, 5, "KEY5"},
};
static irqreturn_t buttons_interrupt(int irq, void *dev_id)
{
int ret;
switch(irq)
{
case IRQ_EINT8:
ret = s3c2410_gpio_getpin(led_table[0]);
if(0 == ret)
{
s3c2410_gpio_setpin(led_table[0], 1);
}
else
{
s3c2410_gpio_setpin(led_table[0], 0);
}
break;
case IRQ_EINT11:
ret = s3c2410_gpio_getpin(led_table[1]);
if(0 == ret)
{
s3c2410_gpio_setpin(led_table[1], 1);
}
else
{
s3c2410_gpio_setpin(led_table[1], 0);
}
break;
case IRQ_EINT13:
ret = s3c2410_gpio_getpin(led_table[2]);
if(0 == ret)
{
s3c2410_gpio_setpin(led_table[2], 1);
}
else
{
s3c2410_gpio_setpin(led_table[2], 0);
}
break;
case IRQ_EINT14:
ret = s3c2410_gpio_getpin(led_table[3]);
if(0 == ret)
{
s3c2410_gpio_setpin(led_table[3], 1);
}
else
{
s3c2410_gpio_setpin(led_table[3], 0);
}
break;
default:
break;
}
return IRQ_RETVAL(IRQ_HANDLED);
}
static int but_set(void)
{
int i;
int err = 0;
for (i = 0; i < 4; i++)
{
s3c2410_gpio_cfgpin(led_table[i], led_cfg_table[i]);
s3c2410_gpio_setpin(led_table[i], 0);
}
for (i = 0; i < sizeof(button_irqs)/sizeof(button_irqs[0]); i++)
{
if (button_irqs[i].irq < 0)
{
continue;
}
err = request_irq(button_irqs[i].irq, buttons_interrupt, 1,
button_irqs[i].name, (void *)&button_irqs[i]);
if (err)
break;
}
if (err)
{
i--;
for (; i >= 0; i--)
{
if (button_irqs[i].irq < 0)
{
continue;
}
disable_irq(button_irqs[i].irq);
free_irq(button_irqs[i].irq, (void *)&button_irqs[i]);
}
return -EBUSY;
}
}
static int myled_release(struct inode *inode, struct file *filp)
{
int i;
for (i = 0; i < sizeof(button_irqs)/sizeof(button_irqs[0]); i++) {
if (button_irqs[i].irq < 0) {
continue;
}
free_irq(button_irqs[i].irq, (void *)&button_irqs[i]);
}
return 0;
}
struct file_operations led_fops =
{
.owner = THIS_MODULE,
.release = myled_release,
};
static int __init but_init(void)
{
int result = 0;
dev_t dev = 0;
result = alloc_chrdev_region(&dev, led_minor, 1, DEVICE_NAME);
led_major = MAJOR(dev);
if (result < 0) {
printk(KERN_WARNING "wfet_kb: can't get major %d\n", led_major);
return result;
}
led_device = kmalloc(sizeof(struct cdev), GFP_KERNEL);
if (!led_device) {
result = -ENOMEM;
unregister_chrdev_region(dev, 1);
return result;
}
memset(led_device, 0, sizeof(struct cdev));
cdev_init(led_device, &led_fops);
led_device->owner = THIS_MODULE;
result = cdev_add (led_device, dev, 1);
if (result) {
printk(KERN_NOTICE "Error %d adding LED device, major_%d", result, MAJOR(dev));
kfree(led_device);
unregister_chrdev_region(dev, 1);
return result;
}
but_set();
return 0;
}
static void but_exit(void)
{
dev_t devno = MKDEV(led_major, led_minor);
if (led_device){
/* Get rid of our char dev entries */
cdev_del(led_device);
kfree(led_device);
led_device = NULL;
}
/* cleanup_module is never called if registering failed */
unregister_chrdev_region(devno, 1);
return;
}
module_init(but_init);
module_exit(but_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Lzy");
源码文件: button.rar