1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
| #include <linux/module.h>
#include <linux/fs.h>
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/device.h>
#include <linux/interrupt.h>
#include <linux/cdev.h>
#define IR_GPIO GPIOH(8)
#define USE_STATIC_MAJOR 1
#define KEY_MAJOR 260
struct s5pv210_key {
dev_t devno;
int dev_major;
int irqno;
struct cdev *cdev;
struct class *cls;
struct device *dev;
};
struct s5pv210_key *key_dev;
static int key_drv_open(struct inode *inode, struct file *filp)
{
return 0;
}
static int key_drv_close(struct inode *inode, struct file *filp)
{
printk("-------^_^ %s-------\n", __FUNCTION__);
return 0;
}
struct file_operations key_fops = {
.open = key_drv_open,
.release = key_drv_close,
};
irqreturn_t key_irq_svc(int irqno, void *dev_id)
{
printk(" --------- ^-^ ---------%s \n", __FUNCTION__);
return IRQ_HANDLED;
}
static int __init key_drv_init(void)
{
int ret;
key_dev = kzalloc(sizeof(struct s5pv210_key), GFP_KERNEL);
if (key_dev == NULL) {
printk(KERN_ERR"kzalloc error\n");
return -ENOMEM;
}
#ifdef USE_STATIC_MAJOR
key_dev->devno = MKDEV(KEY_MAJOR, 32);
ret = register_chrdev_region(key_dev->devno, 1, "key"); /*申请设备号*/
if (ret < 0) {
printk(KERN_ERR"register chrdev failed\n");
goto err_free;
}
#else
ret = alloc_chrdev_region(&key_dev->devno, 32, 1, "key");
if (ret != 0) {
/* 出错 */
printk(KERN_ERR"register chrdev failed\n");
goto err_free;
}
#endif
key_dev->cdev = cdev_alloc(); /*动态分配一个struct cdev对象*/
cdev_init(key_dev->cdev, &key_fops); /*初始化cdev的fops*/
cdev_add(key_dev->cdev, key_dev->devno, 1); /*将cdev注册到系统中*/
/* 自动创建设备节点 */
key_dev->cls = class_create(THIS_MODULE, "key_cls");
if (IS_ERR(key_dev->cls)) {
printk(KERN_ERR"class create error\n");
ret = PTR_ERR(key_dev->cls);
goto err_unregister;
}
key_dev->dev = device_create(key_dev->cls, NULL, MKDEV(key_dev->dev_major, 0), NULL, "key%d", 0);
if (IS_ERR(key_dev->dev)) {
printk(KERN_ERR"device create error\n");
ret = PTR_ERR(key_dev->dev);
goto err_class_destory;
}
/* 初始化硬件 */
// 中断号获取 IRQ_EINT(x); irqs.h
//key_dev->irqno = IRQ_EINT(1);
key_dev->irqno = gpio_to_irq(IR_GPIO);
ret = request_irq(key_dev->irqno, key_irq_svc, IRQF_TRIGGER_FALLING|IRQF_TRIGGER_RISING, "KEY", NULL);
if (ret != 0) {
printk(KERN_ERR"request irq error\n");
ret = -EBUSY;
goto err_device_destory;
}
err_device_destory:
device_destroy(key_dev->cls, key_dev->devno);
err_class_destory:
class_destroy(key_dev->cls);
err_unregister:
cdev_del(key_dev->cdev);
unregister_chrdev_region(key_dev->devno, 1);
err_free:
kfree(key_dev);
return ret;
}
static void __exit key_drv_exit(void)
{
class_destroy(key_dev->cls);
cdev_del(key_dev->cdev);
unregister_chrdev_region(key_dev->devno, 1);
kfree(key_dev);
}
module_init(key_drv_init);
module_exit(key_drv_exit);
MODULE_LICENSE("GPL");
|