tiny6410按键驱动注释

  1 #include <linux/module.h>
  2 #include <linux/kernel.h>
  3 #include <linux/fs.h>
  4 #include <linux/init.h>
  5 #include <linux/delay.h>
  6 #include <linux/poll.h>
  7 #include <linux/irq.h>
  8 #include <asm/irq.h>
  9 #include <asm/io.h>
 10 #include <linux/interrupt.h>
 11 #include <asm/uaccess.h>
 12 #include <mach/hardware.h>
 13 #include <linux/platform_device.h>
 14 #include <linux/cdev.h>
 15 #include <linux/miscdevice.h>
 16 
 17 #include <mach/map.h>
 18 #include <mach/regs-clock.h>
 19 #include <mach/regs-gpio.h>
 20 
 21 #include <plat/gpio-cfg.h>
 22 #include <mach/gpio-bank-n.h>
 23 #include <mach/gpio-bank-l.h>
 24 
 25 #define DEVICE_NAME     "buttons"
 26 
 27 struct button_irq_desc {
 28     int irq;
 29     int number;
 30     char *name;    
 31 };
 32 
 33 static struct button_irq_desc button_irqs [] = {
 34     {IRQ_EINT( 0), 0, "KEY0"},
 35     {IRQ_EINT( 1), 1, "KEY1"},
 36     {IRQ_EINT( 2), 2, "KEY2"},
 37     {IRQ_EINT( 3), 3, "KEY3"},
 38     {IRQ_EINT( 4), 4, "KEY4"},
 39     {IRQ_EINT( 5), 5, "KEY5"},
 40     {IRQ_EINT(19), 6, "KEY6"},
 41     {IRQ_EINT(20), 7, "KEY7"},
 42 };
 43 static volatile char key_values [] = {'0', '0', '0', '0', '0', '0', '0', '0'}; //字符0表示没按下 字符1表示按下了 
 44 
 45 //此处声明并定义一个等待队列
 46 static DECLARE_WAIT_QUEUE_HEAD(button_waitq);
 47 
 48 static volatile int ev_press = 0;
 49 
 50 
 51 static irqreturn_t buttons_interrupt(int irq, void *dev_id)
 52 {
 53     struct button_irq_desc *button_irqs = (struct button_irq_desc *)dev_id;//传递给中断的信息
 54     int down;
 55     int number;
 56     unsigned tmp;
 57 
 58     udelay(0);
 59     number = button_irqs->number; //判断中断号
 60     switch(number) {
 61     case 0: case 1: case 2: case 3: case 4: case 5:
 62         tmp = readl(S3C64XX_GPNDAT);
 63         down = !(tmp & (1<<number)); //反向判断 低电平按下为1 高电平没按下为0
 64         break;
 65     case 6: case 7:
 66         tmp = readl(S3C64XX_GPLDAT);
 67         down = !(tmp & (1 << (number + 5)));//同理
 68         break;
 69     default:
 70         down = 0;
 71     }
 72 
 73     if (down != (key_values[number] & 1)) { //如果状态和上一次的不一样
 74         key_values[number] = '0' + down;
 75 
 76             ev_press = 1; //标记有按键按下
 77             wake_up_interruptible(&button_waitq);//唤醒等待队列
 78         }
 79 
 80     return IRQ_RETVAL(IRQ_HANDLED);
 81 }
 82 
 83 
 84 static int s3c64xx_buttons_open(struct inode *inode, struct file *file)
 85 {
 86     int i;
 87     int err = 0;
 88     
 89     for (i = 0; i < sizeof(button_irqs)/sizeof(button_irqs[0]); i++) {
 90     if (button_irqs[i].irq < 0) {
 91         continue;
 92     }
 93         err = request_irq(button_irqs[i].irq, buttons_interrupt, IRQ_TYPE_EDGE_BOTH, 
 94                           button_irqs[i].name, (void *)&button_irqs[i]);
 95         if (err)
 96             break;//出错即跳出
 97     }
 98 
 99     if (err) {
100         i--;
101         for (; i >= 0; i--) {
102         if (button_irqs[i].irq < 0) {
103         continue;
104         }
105         disable_irq(button_irqs[i].irq);
106             free_irq(button_irqs[i].irq, (void *)&button_irqs[i]);//解中断
107         }
108         return -EBUSY;
109     }
110 
111     ev_press = 1;
112     
113     return 0;
114 }
115 
116 
117 static int s3c64xx_buttons_close(struct inode *inode, struct file *file)
118 {
119     int i;
120     
121     for (i = 0; i < sizeof(button_irqs)/sizeof(button_irqs[0]); i++) {
122     if (button_irqs[i].irq < 0) {
123         continue;
124     }
125     free_irq(button_irqs[i].irq, (void *)&button_irqs[i]);
126     }
127 
128     return 0;
129 }
130 
131 //读取是哪个按键被按下
132 static int s3c64xx_buttons_read(struct file *filp, char __user *buff, size_t count, loff_t *offp)
133 {
134     unsigned long err;
135 
136     if (!ev_press) {
137     if (filp->f_flags & O_NONBLOCK) //如果是非阻塞的 就直接返回
138         return -EAGAIN;
139     else
140         wait_event_interruptible(button_waitq, ev_press);//如果是阻塞的 就添加到等待队列
141     }
142     
143     ev_press = 0; //重置状态
144 
145     err = copy_to_user((void *)buff, (const void *)(&key_values), min(sizeof(key_values), count));
146 
147     return err ? -EFAULT : min(sizeof(key_values), count);
148 }
149 
150 static unsigned int s3c64xx_buttons_poll( struct file *file, struct poll_table_struct *wait)
151 {
152     unsigned int mask = 0;
153     poll_wait(file, &button_waitq, wait);//添加到等待队列
154     if (ev_press)
155         mask |= POLLIN | POLLRDNORM; //标记数据可读 这边应该是标记有按键按下
156     return mask;
157 }
158 
159 
160 static struct file_operations dev_fops = {
161     .owner   =   THIS_MODULE,
162     .open    =   s3c64xx_buttons_open,
163     .release =   s3c64xx_buttons_close, 
164     .read    =   s3c64xx_buttons_read,
165     .poll    =   s3c64xx_buttons_poll,
166 };
167 
168 static struct miscdevice misc = {
169     .minor = MISC_DYNAMIC_MINOR,
170     .name = DEVICE_NAME,
171     .fops = &dev_fops,
172 };
173 
174 static int __init dev_init(void)
175 {
176     int ret;
177 
178     ret = misc_register(&misc);
179 
180     printk (DEVICE_NAME"\tinitialized\n");
181 
182     return ret;
183 }
184 
185 static void __exit dev_exit(void)
186 {
187     misc_deregister(&misc);
188 }
189 
190 module_init(dev_init);
191 module_exit(dev_exit);
192 MODULE_LICENSE("GPL");
193 MODULE_AUTHOR("FriendlyARM Inc.");

 

posted @ 2019-06-11 16:44  robinjr  阅读(133)  评论(0)    收藏  举报