#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/cdev.h>
#include <linux/fs.h>
#include <linux/device.h>
#include <linux/syscalls.h>
#include <linux/interrupt.h>
#include <linux/gpio.h>
#include <linux/of_gpio.h>
#include <linux/of_platform.h>
#include <linux/uaccess.h>
#include <linux/string.h>
#include <mach/gpio.h>
#include <mach/irqs.h>
#define GPIO_TO_PIN(bank, gpio) (32 * (bank) + (gpio))
struct handle_sw_key_dev
{
struct cdev cdev;
dev_t devno;
char test[20];
struct class *handle_sw_key_class;
struct fasync_struct *async_queue;
int message_cdev_open;
};
struct handle_sw_key_dev handle_sw_key_dev;
irqreturn_t irq_handler(int irqno, void *dev_id)
{
struct handle_sw_key_dev *dev = &handle_sw_key_dev;
static int count = 0;
//printk("handle_sw key down = %d\n", count);
if (dev->async_queue)
kill_fasync(&dev->async_queue, SIGIO, POLL_IN);
return IRQ_HANDLED;
}
static int handle_sw_key_open(struct inode *node, struct file *fd)
{
struct handle_sw_key_dev *dev;
#ifdef HANDEL_SW_DEBUG
printk("handle_sw_key_open()++\n");
printk("node->i_cdev = %x\n", (unsigned int)node->i_cdev);
#endif
dev = container_of(node->i_cdev, struct handle_sw_key_dev, cdev);
#ifdef HANDEL_SW_DEBUG
printk("dev->cdev = %x\n", (unsigned int)&dev->cdev);
printk("dev = %x\n", (unsigned int)dev);
#endif
if (!dev->message_cdev_open) {
dev->message_cdev_open = 1;
fd->private_data = dev;
}
else{
return -EFAULT;
}
#ifdef HANDEL_SW_DEBUG
printk("handle_sw_key_open()--\n");
#endif
return 0;
}
static ssize_t handle_sw_key_write(struct file *fd, const char __user *buf, size_t len, loff_t *ptr)
{
return 0;
}
static ssize_t handle_sw_key_read(struct file *fd, char __user *buf, size_t len, loff_t *ptr)
{
return 0;
}
static int handle_sw_key_fasync(int fd, struct file *filp, int mode)
{
struct handle_sw_key_dev *dev = filp->private_data;
#ifdef HANDEL_SW_DEBUG
printk("handle_sw_key_fasync()++\n");
#endif
fasync_helper(fd, filp, mode, &dev->async_queue);
#ifdef HANDEL_SW_DEBUG
printk("handle_sw_key_fasync()--\n");
#endif
return 0;
}
static int handle_sw_key_release(struct inode *node, struct file *fd)
{
struct handle_sw_key_dev *dev = fd->private_data;
#ifdef HANDEL_SW_DEBUG
printk("handle_sw_key_release()++\n");
#endif
dev->message_cdev_open = 0;
handle_sw_key_fasync(-1, fd, 0);
#ifdef HANDEL_SW_DEBUG
printk("handle_sw_key_release()--\n");
#endif
return 0;
}
struct file_operations meassage_operatons =
{
.owner = THIS_MODULE,
.open = handle_sw_key_open,
.write = handle_sw_key_write,
.read = handle_sw_key_read,
.fasync = handle_sw_key_fasync,
.release = handle_sw_key_release,
};
static int __init handle_sw_key_init(void)
{
struct handle_sw_key_dev * dev;
int ret = 0;
int irq = 0;
printk("handle_sw_key_init()\n");
dev = &handle_sw_key_dev;
alloc_chrdev_region(&dev->devno, 0, 1, "handle_sw_key");
cdev_init(&dev->cdev, &meassage_operatons);
cdev_add(&dev->cdev, dev->devno, 1);
dev->handle_sw_key_class = class_create(THIS_MODULE, "handle_sw_key_class");
if(IS_ERR(dev->handle_sw_key_class)) {
printk("Err: failed in creating class./n");
goto fail1;
}
device_create(dev->handle_sw_key_class, NULL, dev->devno, NULL, "handle_sw_key");
//init irq
ret = gpio_request(GPIO_TO_PIN(0, 21), "handle_sw_key_inter");
if(ret){
printk("gpio_request() failed !\n");
goto fail1;
}
ret = gpio_direction_input(GPIO_TO_PIN(0, 21));
if(ret){
printk("gpio_direction_input() failed !\n");
goto fail2;
}
irq = gpio_to_irq(GPIO_TO_PIN(0, 21));
if(irq < 0){
printk("gpio_to_irq() failed !\n");
ret = irq;
goto fail2;
}
printk("irq = %d\n", irq);
ret = request_irq(irq,
irq_handler,
IRQF_TRIGGER_FALLING | IRQF_SHARED,
"handle_sw_key_inter",
&dev->devno);
if(ret){
printk("request_irq() failed ! %d\n", ret);
goto fail2;
}
printk("handle_sw_key_init() Successful\n");
return 0;
fail2:
gpio_free(GPIO_TO_PIN(0, 21));
fail1:
device_destroy(dev->handle_sw_key_class, dev->devno);
class_destroy(dev->handle_sw_key_class);
cdev_del(&dev->cdev);
unregister_chrdev_region(dev->devno, 1);
return ret;
}
static void __exit handle_sw_key_exit(void)
{
struct handle_sw_key_dev *dev = &handle_sw_key_dev;
int irq = 0;
#ifdef HANDEL_SW_DEBUG
printk("handle_sw_key_exit()++\n");
#endif
irq = gpio_to_irq(GPIO_TO_PIN(0, 21));
#ifdef HANDEL_SW_DEBUG
printk("irq = %d\n", irq);
#endif
free_irq(irq, &dev->devno);
gpio_free(GPIO_TO_PIN(0, 21));
device_destroy(dev->handle_sw_key_class, dev->devno);
class_destroy(dev->handle_sw_key_class);
cdev_del(&dev->cdev);
unregister_chrdev_region(dev->devno, 1);
#ifdef HANDEL_SW_DEBUG
printk("handle_sw_key_exit()--\n");
#endif
}
module_init(handle_sw_key_init);
module_exit(handle_sw_key_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Austin Huang");
MODULE_DESCRIPTION("handle_sw_key");