|  | 
 
| #include <linux/device.h> #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/fs.h>
 #include <linux/init.h>
 #include <linux/interrupt.h>
 #include <linux/irq.h>
 #include <linux/delay.h>
 #include <asm/uaccess.h>
 #include <asm/irq.h>
 #include <asm/io.h>
 #include <mach/regs-gpio.h>
 #include <mach/hardware.h>
 
 static struct class *button_class;
 static struct class_device        *button_class_dev;
 /* 定义变量*/
 static DECLARE_WAIT_QUEUE_HEAD(button_waitq);/*等待队列头,为休眠和唤醒做准备*/
 
 /*中断事件标志,中断服务程序将其置1,read函数将它请0*/
 static volatile int ev_press = 0;
 
 static unsigned long gpio_table [] =
 {
 S3C2410_GPF0,
 S3C2410_GPF1,
 S3C2410_GPF2,
 S3C2410_GPF4,
 };
 
 /* 用来指定GPIO引脚的功能:输出 */
 static unsigned int gpio_cfg_table [] =
 {
 S3C2410_GPF0_INP,
 S3C2410_GPF1_INP,
 S3C2410_GPF2_INP,
 S3C2410_GPF4_INP,
 
 };
 /*结构体类型的声明*/
 struct pin_desc  {
 unsigned int pin;
 unsigned int pin_val;
 };
 unsigned int key_val;
 /*当按下按键显示 0X01 0X02 0X04 0X08
 当松开按键时,显示0X81 0X82 0X84 0X88
 */
 struct pin_desc pins_desc[4] = {  //结构体数组初始化
 {S3C2410_GPF0, 0x01},
 {S3C2410_GPF1, 0x02},
 {S3C2410_GPF2, 0x03},
 {S3C2410_GPF4, 0x04},
 };
 /*
 *确定按键值
 */
 static  irqreturn_t button_irq(int irq,void *dev_id)
 {
 
 struct pin_desc * pindesc = (struct pin_desc *)dev_id;//(struct pin_desc *)强制类型转换
 unsigned int pin_value;
 pin_value=s3c2410_gpio_getpin(pindesc ->pin);
 
 if(pin_value )
 {
 /*按下按键*/
 key_val = 0x80 |pindesc->pin_val;
 }
 else
 {
 /*松开按键?/
 key_val = pindesc ->pin_val;
 }
 ev_press = 1;      //表示中断发生
 wake_up_interruptible(&button_waitq);  //  唤醒休眠
 //printk(" button_irq  occured\n");
 return IRQ_HANDLED;   /*return应该在函数的最后,不然return之后的代码不起作用的澹垮*/
 
 }
 
 static int button_openNNN(struct inode *inode, struct file *file)  //此处的函数名可以随便热″?只要在fopsd的对应
 //正确即可???????????
 {
 /* 配置GPF0,2为输入引脚 */
 request_irq(IRQ_EINT0,button_irq,IRQ_TYPE_EDGE_BOTH,"KEY4",&pins_desc[0]);
 request_irq(IRQ_EINT1,button_irq,IRQ_TYPE_EDGE_BOTH,"KEY1",&pins_desc[1]);
 request_irq(IRQ_EINT2,button_irq,IRQ_TYPE_EDGE_BOTH,"KEY3",&pins_desc[2]);
 request_irq(IRQ_EINT4,button_irq,IRQ_TYPE_EDGE_BOTH,"KEY2",&pins_desc[3]);
 
 // printk("button_open\n");
 return 0;
 }
 
 ssize_t button_read(struct file *file, char __user *buf, size_t size, loff_t *ppos)
 {
 /* 如果没有按键动作发生,休眠 */
 wait_event_interruptible(button_waitq,ev_press);////当有按键按下时,中断当前运行(终止当前休眠)
 //跳转到button_irq处继续运行,当button_irq运行完毕,再从此处继续向下运行
 /* 如果有按键动作发生,返回按键值 */
 if (size != 1)
 return -EINVAL;
 copy_to_user(buf,&key_val,1);
 
 ev_press = 0;
 //printk("button_read\n");
 return 1;
 }
 /*释放中断函数*/
 int button_release(struct inode * inode, struct file * file)
 {
 free_irq(IRQ_EINT0,&pins_desc[0]);
 free_irq(IRQ_EINT1,&pins_desc[1]);
 free_irq(IRQ_EINT2,&pins_desc[2]);
 free_irq(IRQ_EINT4,&pins_desc[3]);
 // printk("button_release\n");
 }
 
 static struct file_operations button_fops = {
 .owner  =   THIS_MODULE,    /* 这是一个宏,推向编译模块时自动创建的__this_module变量 */
 .open   =   button_openNNN,
 .read        =        button_read,
 .release = button_release,
 };
 
 
 int major;
 static int button_init(void)
 {
 major = register_chrdev(0, "button_drv", &button_fops);
 
 button_class = class_create(THIS_MODULE, "buttons_irq");
 
 button_class_dev = device_create(button_class, NULL, MKDEV(major, 0), NULL, "Buttons_irq"); /* /dev/buttons */
 
 printk("button_init\n");
 return 0;
 }
 
 static void button_exit(void)
 {
 unregister_chrdev(major, "button");
 device_unregister(button_class_dev);
 class_destroy(button_class);
 printk("button_exit\n");
 return 0;
 }
 
 
 module_init(button_init);
 
 module_exit(button_exit);
 
 MODULE_LICENSE("GPL");
 
 这是我参考一个例程写的中断程序,但中断处理函数static  irqreturn_t button_irq(int irq,void *dev_id)
 中的
 struct pin_desc * pindesc = (struct pin_desc *)dev_id;怎么理解,
 
 我的理解是:(struct pin_desc *)dev_id把void *dev_id强制转换成struct pin_desc 类型,但问题它怎么又能指向pin_val (key_val = 0x80 |pindesc->pin_val;)就能输出
 struct pin_desc pins_desc[4] = {  //结构体数组初始化
 {S3C2410_GPF0, 0x01},
 {S3C2410_GPF1, 0x02},
 {S3C2410_GPF2, 0x03},
 {S3C2410_GPF4, 0x04},
 };0X01,0X02,0X03,0X04呢?我认为只有pins_desc才能指向它们的,请解释一下
 | 
 |