#include"drv_key_int.h"
#define DRV_KEY_INT_N_MINORS 1 #define DRV_KEY_INT_FIRST_MINOR 0 #define DRV_KEY_INT_NODE_NAME "key_int"
MODULE_LICENSE("GPL"); MODULE_AUTHOR("DRAAPHO");
int drv_key_int_major=0;
dev_t drv_key_int_device_num;
struct class *drv_key_int_class;
typedef struct privatedata { int nMinor; struct cdev cdev; struct device *drv_key_int_device; } drv_key_int_private;
drv_key_int_private devices[DRV_KEY_INT_N_MINORS];
static DECLARE_WAIT_QUEUE_HEAD(key_waitq); static volatile int ev_press = 0; static unsigned char keys_val;
struct pin_desc { unsigned int pin; unsigned int key_val; };
struct pin_desc pins_desc[3] = { {S3C2410_GPF0, 0x01}, {S3C2410_GPF2, 0x02}, {S3C2410_GPG3, 0x04}, };
static irqreturn_t keys_irq(int irq, void *dev_id) { struct pin_desc * pindesc = (struct pin_desc *)dev_id; unsigned int pinval;
PINFO("keys_irq, irq=%d\n", irq); pinval = s3c2410_gpio_getpin(pindesc->pin);
if (pinval) { keys_val &= ~pindesc->key_val; } else { keys_val |= pindesc->key_val; }
ev_press = 1; wake_up_interruptible(&key_waitq); return IRQ_RETVAL(IRQ_HANDLED); }
static int drv_key_int_open(struct inode *inode,struct file *filp) { int ret; drv_key_int_private *priv = container_of(inode->i_cdev , drv_key_int_private ,cdev); filp->private_data = priv; PINFO("In char driver open() function\n");
ret = request_irq(IRQ_EINT0, keys_irq, IRQT_BOTHEDGE, "S2", &pins_desc[0]); ret |= request_irq(IRQ_EINT2, keys_irq, IRQT_BOTHEDGE, "S3", &pins_desc[1]); ret |= request_irq(IRQ_EINT11, keys_irq, IRQT_BOTHEDGE, "S4", &pins_desc[2]);
if (ret) return -EINVAL; else return 0; }
static int drv_key_int_release(struct inode *inode,struct file *filp) { drv_key_int_private *priv; priv=filp->private_data; PINFO("In char driver release() function\n");
free_irq(IRQ_EINT11, &pins_desc[2]); free_irq(IRQ_EINT2, &pins_desc[1]); free_irq(IRQ_EINT0, &pins_desc[0]); return 0; }
static ssize_t drv_key_int_read(struct file *filp, char __user *ubuff,size_t count,loff_t *offp) { drv_key_int_private *priv; priv = filp->private_data; PINFO("In char driver read() function\n");
if (count != 1) return -EINVAL;
wait_event_interruptible(key_waitq, ev_press); ev_press = 0;
if (copy_to_user(ubuff, &keys_val, 1)) { return -EFAULT; } return 1; }
static const struct file_operations drv_key_int_fops= { .owner = THIS_MODULE, .open = drv_key_int_open, .release = drv_key_int_release, .read = drv_key_int_read, };
static int __init drv_key_int_init(void) { int i; int res;
res = alloc_chrdev_region(&drv_key_int_device_num,DRV_KEY_INT_FIRST_MINOR,DRV_KEY_INT_N_MINORS ,DRIVER_NAME); if(res) { PERR("register device no failed\n"); return -1; } drv_key_int_major = MAJOR(drv_key_int_device_num);
drv_key_int_class = class_create(THIS_MODULE , DRIVER_NAME); if(!drv_key_int_class) { PERR("class creation failed\n"); return -1; }
for(i=0;i<DRV_KEY_INT_N_MINORS;i++) { drv_key_int_device_num= MKDEV(drv_key_int_major ,DRV_KEY_INT_FIRST_MINOR+i); cdev_init(&devices[i].cdev , &drv_key_int_fops); cdev_add(&devices[i].cdev,drv_key_int_device_num,1);
devices[i].drv_key_int_device = device_create(drv_key_int_class , NULL ,drv_key_int_device_num , DRV_KEY_INT_NODE_NAME"%d",DRV_KEY_INT_FIRST_MINOR+i); if(!devices[i].drv_key_int_device) { class_destroy(drv_key_int_class); PERR("device creation failed\n"); return -1; }
devices[i].nMinor = DRV_KEY_INT_FIRST_MINOR+i; }
PINFO("INIT\n");
return 0; }
static void __exit drv_key_int_exit(void) {
int i;
PINFO("EXIT\n");
for(i=0;i<DRV_KEY_INT_N_MINORS;i++) { drv_key_int_device_num= MKDEV(drv_key_int_major ,DRV_KEY_INT_FIRST_MINOR+i);
cdev_del(&devices[i].cdev);
device_destroy(drv_key_int_class ,drv_key_int_device_num);
}
class_destroy(drv_key_int_class);
unregister_chrdev_region(drv_key_int_device_num ,DRV_KEY_INT_N_MINORS);
}
module_init(drv_key_int_init); module_exit(drv_key_int_exit);
|