按键驱动,应用程序

xiaoxiao2025-07-29  23

总结:int与char的混用导致错误(copy_to_user())。。。。。。。。。。。。。。。

#include <mach/regs-gpio.h> #include <mach/hardware.h> #include <linux/gpio.h> #include <linux/module.h> #include <linux/kernel.h> #include <linux/fs.h> #include <linux/init.h> #include <linux/delay.h> #include <asm/irq.h> #include <linux/interrupt.h> #include <asm/uaccess.h> //#include <asm/arch/regs-gpio.h> //#include <asm/hardware.h> #include <linux/device.h> #include <linux/poll.h> #define DEVICE_NAME "EmbedSky-buttons" #define BUTTON_MAJOR 232 struct button_irq_desc {   int irq;   int pin;   int pin_setting;   int number;   char *name; }; static struct button_irq_desc button_irqs [] = {     {IRQ_EINT1, S3C2410_GPF1,S3C2410_GPF1_EINT1,0, "KEY1"},    {IRQ_EINT4, S3C2410_GPF4,S3C2410_GPF4_EINT4,1, "KEY2"},    {IRQ_EINT2, S3C2410_GPF2,S3C2410_GPF2_EINT2,2, "KEY3"},    {IRQ_EINT0, S3C2410_GPF0,S3C2410_GPF0_EINT0,3, "KEY4"},   }; static volatile int key_values[] = {'0', '0', '0', '0'};

/* 等待队列: * 当没有按键被按下时,如果有进程调用 EmbedSky_buttons_read 函数, * 它将休眠 */ static DECLARE_WAIT_QUEUE_HEAD(button_waitq);

/* 中断事件标志, 中断服务程序将它置 1,EmbedSky_buttons_read 将它清 0 */ static volatile int ev_press = 0; static irqreturn_t buttons_interrupt(int irq, void *dev_id) {   struct button_irq_desc *button_irqs = (struct button_irq_desc *)dev_id;       printk("come in %d",button_irqs->number);          key_values[button_irqs->number] ='1';   ev_press = 1;  /* 表示中断发生了 */  wake_up_interruptible(&button_waitq);  /* 唤醒休眠的进程 */  return IRQ_RETVAL(IRQ_HANDLED); } static int EmbedSky_buttons_open(struct inode *inode, struct file *file) {   int i;   int err;   for (i = 0; i < sizeof(button_irqs)/sizeof(button_irqs[0]); i++)      {      // 注册中断处理函数      s3c2410_gpio_cfgpin(button_irqs[i].pin,button_irqs[i].pin_setting);      err=request_irq(button_irqs[i].irq,buttons_interrupt,NULL,button_irqs[i].name,(void*)&button_irqs[i]);      if (err)              break;       } if (err)      {        // 释放已经注册的中断        i--;        for (; i >= 0; i--)           {    disable_irq(button_irqs[i].irq);                free_irq(button_irqs[i].irq, (void *)&button_irqs[i]);            }        return -EBUSY;       } return 0; } static int EmbedSky_buttons_close(struct inode *inode, struct file *file) {     int i;     for (i = 0; i < sizeof(button_irqs)/sizeof(button_irqs[0]); i++)      {       // 释放已经注册的中断       disable_irq(button_irqs[i].irq);       free_irq(button_irqs[i].irq, (void *)&button_irqs[i]);       }     return 0; } static int EmbedSky_buttons_read(struct file *filp, char __user *buff, size_t count, loff_t *offp) { int ii;    unsigned long err;        /* 如果 ev_press 等于 0,休眠 */        wait_event_interruptible(button_waitq, ev_press);               /* 执行到这里时,ev_press 等于 1,将它清 0 */        ev_press = 0;        /* 将按键状态复制给用户,并清 0 */   for(ii=0;ii<4;ii++)       { printk("%c",key_values[ii]);         printk("\n");}        err = copy_to_user(buff, key_values, min(sizeof(key_values), count));        memset((void *)key_values, '0', sizeof(key_values));     return err ? -EFAULT : min(sizeof(key_values), count); } /************************************************** * 当用户程序调用 select 函数时,本函数被调用 * 如果有按键数据,则 select 函数会立刻返回 * 如果没有按键数据,本函数使用 poll_wait 等待 **************************************************/ static unsigned int EmbedSky_buttons_poll( struct file *file, struct poll_table_struct *wait) {   unsigned int mask = 0;   poll_wait(file, &button_waitq, wait);   if (ev_press)         mask |= POLLIN | POLLRDNORM;   return mask; }

static struct file_operations EmbedSky_buttons_fops = {  .owner=THIS_MODULE,  .open    = EmbedSky_buttons_open,  .release = EmbedSky_buttons_close,  .read    = EmbedSky_buttons_read,  .poll    = EmbedSky_buttons_poll,  }; static char __initdata banner[] = "TQ2440/SKY2440 LEDS, (c) 2008,2009 www.embedsky.net\n"; static struct class *button_class; static int __init EmbedSky_buttons_init(void) {   int ret;   printk(banner);   ret = register_chrdev(BUTTON_MAJOR, DEVICE_NAME, &EmbedSky_buttons_fops);   if (ret < 0)       {         printk(DEVICE_NAME " can't register major number\n");         return ret;        }

  button_class = class_create(THIS_MODULE, DEVICE_NAME);   if(IS_ERR(button_class))     {       printk("Err: failed in EmbedSky-leds class. \n");       return -1;     }   device_create(button_class, NULL, MKDEV(BUTTON_MAJOR, 0), NULL, DEVICE_NAME);   printk(DEVICE_NAME " initialized\n");   return 0; } static void __exit EmbedSky_buttons_exit(void) {   unregister_chrdev(BUTTON_MAJOR, DEVICE_NAME);   device_destroy(button_class, MKDEV(BUTTON_MAJOR, 0));   class_destroy(button_class);  } module_init(EmbedSky_buttons_init); module_exit(EmbedSky_buttons_exit); MODULE_AUTHOR("http://www.embedsky.net"); MODULE_DESCRIPTION("TQ2440/SKY2440 LED Driver"); MODULE_LICENSE("GPL");

对应应用程序。。。。。。。。。。。。。。。。

#include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <sys/ioctl.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <sys/select.h> #include <sys/time.h> #include <errno.h>

int main(void) {  int i;  int buttons_fd;             int  key_value_temp[4];

 /*打开键盘设备文件*/  buttons_fd = open("/dev/EmbedSky-buttons", 0);  if (buttons_fd < 0)  {   perror("open device buttons");   exit(1);  }

 for (;;)  {

  int ret;

  /*开始读取键盘驱动发出的数据,注意key_value和键盘驱动中定义为一致的类型*/   ret = read(buttons_fd, key_value_temp, sizeof(key_value_temp));           printf("hello\n");           for(i=0;i<4;i++)  {printf("%c",key_value_temp[i]);}          printf("\n");          for(i=0;i<4;i++)               {key_value_temp[i]='0';}  }

 /*关闭设备文件句柄*/  close(buttons_fd);  return 0; }

转载请注明原文地址: https://www.6miu.com/read-5033940.html

最新回复(0)