Chinaunix首页 | 论坛 | 博客
  • 博客访问: 73144
  • 博文数量: 13
  • 博客积分: 302
  • 博客等级: 二等列兵
  • 技术积分: 210
  • 用 户 组: 普通用户
  • 注册时间: 2010-07-27 18:51
文章分类

全部博文(13)

文章存档

2012年(1)

2011年(12)

我的朋友

分类: 嵌入式

2011-03-30 18:29:31

 
环境描述
kernel :linux 2.6.32
文件系统:yaffs,busybox1.13.1
硬件设备: TQ2440

一、一些基本理论

原理就不细说了,这里给一个连接,http://blog.csdn.net/ling1874/archive/2010/03/24/5410592.aspx

二 、code

 

  1. /*
  2. key_input.c
  3. @按键驱动程序,作为input子系统

  4. @针对S3C2440的驱动程序

  5. @2011.3.20,keytounix

  6. @hi.baidu.com/andio

  7. */

  8. //包含重要的和常用的头文件


  9. #include <linux/module.h>
  10. #include <linux/kernel.h>
  11. #include <linux/init.h>
  12. #include <linux/sched.h>
  13. #include <linux/poll.h>
  14. #include <linux/timer.h>
  15. #include <linux/irq.h>
  16. #include <linux/cdev.h>
  17. #include <linux/wait.h>//waitqueue

  18. #include <linux/errno.h>
  19. #include <linux/interrupt.h>//irq

  20. #include <linux/io.h>
  21. #include <linux/types.h>
  22. #include <linux/delay.h>
  23. #include <linux/semaphore.h>//sem

  24. #include <linux/fs.h>
  25. #include <linux/platform_device.h>//

  26. #include <linux/miscdevice.h>
  27. #include <linux/input.h>//input输入子系统


  28. #include <linux/device.h>
  29. #include <linux/workqueue.h>//workqueue


  30. #include <asm/uaccess.h>
  31. #include <asm/irq.h>

  32. //soc相关


  33. #include <mach/gpio.h>
  34. #include <mach/regs-clock.h>
  35. #include <mach/regs-gpio.h>
  36. #include <mach/hardware.h>
  37. #include <mach/irqs.h>





  38. //////////////////////////////


  39. #define u8 unsigned char

  40. #define u16 unsigned short

  41. #define uint unsigned int



  42. //这个 宏获得t[n]的n数目

  43. #define get_elem_num(t) (sizeof(t)/sizeof(t[0]))
  44. #define ARRAY_SIZE(T) (sizeof(t)/sizeof(t[0]))
  45. ////////////////////////////////////

  46. //这是一个debug宏,用于调试

  47. #define _DEBUG_ 1
  48. #if _DEBUG_
  49. #define debug(format,msg...) printk(format,##msg)
  50. #else
  51. #define debug(format,msg...) (void *)(0)
  52. #endif





  53. struct key_info
  54. {
  55. uint irq_no;//中断号

  56. uint pin;//管脚值

  57. uint pin_set;//管脚设置

  58. }key_info_tab[]=
  59. {
  60. [0]={

  61.     .irq_no=IRQ_EINT1,

  62.     .pin=S3C2410_GPF(1),
  63.         
  64.     .pin_set = S3C2410_GPF1_EINT1,


  65.     },

  66. [1]={

  67.     .irq_no=IRQ_EINT4,

  68.     .pin=S3C2410_GPF(4),
  69.     .pin_set = S3C2410_GPF4_EINT4,


  70.     },

  71. [2]={

  72.     .irq_no=IRQ_EINT2,

  73.     .pin=S3C2410_GPF(2),
  74.     .pin_set = S3C2410_GPF2_EINT2,


  75.     },

  76. [3]={

  77.     .irq_no=IRQ_EINT0,
  78.     .pin_set = S3C2410_GPF0_EINT0,

  79.     .pin=S3C2410_GPF(0),


  80.     }

  81. };

  82. u8 key_code[0x04]=
  83. {
  84. KEY_1,
  85. KEY_2,
  86. KEY_3,
  87. KEY_4
  88. };

  89. //这个宏直接获得 表x中的irq值

  90. #define irq(x) (key_info_tab[x].irq_no)
  91. //这个宏直接获得 表x中的pin值

  92. #define pin(x) (key_info_tab[x].pin)
  93. //这个宏直接获得 表x中的pin_set值

  94. #define set(x) (key_info_tab[x].pin_set)
  95. //这个宏直接获得 表x中的value值

  96. #define code(x) key_code[x]

  97. // 定义设备的相关信息


  98. #define DEV_NAME "usr_dev_key"
  99. #define VAR_KEY_DN 0x00
  100. #define TM1000MS 100
  101. #define METHOD_DELAYED_WORK 1
  102. static struct delayed_work delayed_work_wq;
  103. //工作队列的处理函数

  104. void my_work_proc(struct work_struct * my_work);
  105. static struct input_dev *dev_key;

  106. int volatile active_key;


  107. void my_delay_work_proc(struct work_struct * my_work)
  108. {
  109.      int id= active_key;
  110.         u8 key_real_var=s3c2410_gpio_getpin(pin(id));
  111.          if(key_real_var==VAR_KEY_DN)
  112.          {
  113.                 input_report_key(dev_key,code(id),code(id));
  114.                 input_sync(dev_key);            
  115.          }
  116.      return;
  117. }



  118. static irqreturn_t irq_proc(unsigned int irq,int _id)
  119. {    

  120.         active_key =_id;

  121.         #if METHOD_DELAYED_WORK
  122.         schedule_delayed_work(&delayed_work_wq,TM1000MS/10);
  123.         #endif

  124.      debug("extern from %s,active_key=%d\n",__func__,active_key);

  125.      return IRQ_RETVAL(IRQ_HANDLED);

  126.     };


  127. /*
  128. @dev_init,设备初始化函数,程式化的东西
  129. @
  130. */

  131. static int dev_init(void)
  132. {

  133.     int ret=0;

  134.     int i;

  135.     char * msg;


  136. //初始化作为input子系统的按键

  137.     dev_key=input_allocate_device();
  138.     dev_key->evbit[0]=BIT(EV_KEY);//支持按键

  139.     dev_key->keycode=key_code;//

  140.     dev_key->keycodesize=sizeof(u8);
  141.     dev_key->keycodemax=get_elem_num(key_code);
  142.     
  143.     for(i=0;i<get_elem_num(key_code);i++)
  144.         {
  145.             
  146.                 
  147.             set_bit(key_code[i],dev_key->keybit);
  148.                     
  149.             
  150.         }
  151.     
  152.     dev_key->name=DEV_NAME;
  153.     
  154.     
  155.     input_register_device(dev_key);

  156. ///中断

  157. for(i=0;i<get_elem_num(key_info_tab);i++)
  158. {
  159.     ret=request_irq(irq(i),irq_proc,IRQ_TYPE_EDGE_BOTH,DEV_NAME,i);
  160.     msg=(ret==0?"OK":"ERR");
  161.     debug("register %s.ext_irq[%d] -------[%s],using irq_no=%d\n",DEV_NAME,i,msg,key_info_tab[i].irq_no);
  162.     if(ret!=0)
  163.         goto unregister_irq_handle;
  164.     }
  165.      INIT_DELAYED_WORK(&delayed_work_wq,my_delay_work_proc);

  166.  out:
  167.     return ret;

  168. unregister_irq_handle:
  169.         for(i=i-1;i>=0;i--)
  170.         {
  171.             free_irq(irq(i),irq_proc);
  172.         }
  173.      return ret;
  174.     

  175. };



  176. static int dev_exit(void)
  177. {

  178.     int i;
  179.     for(i=0;i<get_elem_num(key_info_tab);i++)
  180.     {
  181.             free_irq(irq(i),irq_proc);
  182.     }
  183.        input_unregister_device(dev_key);
  184.          return 0;

  185. };
  186. MODULE_AUTHOR("keytounix");

  187. MODULE_LICENSE("Dual BSD/GPL");

  188. MODULE_DESCRIPTION("driver for TQ2440 key");

  189. module_init(dev_init);
  190. module_exit(dev_exit);

 

三、Makefile

 

  1. #TARGET=
  2. TARGET=key_input
  3. #KERNEL
  4. KERNEL=2.6.32
  5. #variable
  6. CC=arm-linux-gcc -w
  7. obj-m :=$(TARGET).o
  8. KERNELDIR :=kernel/linux-$(KERNEL)

  9. default:
  10.     make -C $(KERNELDIR) M=$(shell pwd) modules
  11. clean:
  12.     rm -rf module* *.symvers $(TARGET).o $(TARGET).mod.c $(TARGET).mod.o $(TARGET).ko $(TARGET).tmp_versions


 

四、测试程序

编译方法:#arm-linux-gcc -march=armv4t test.c -o test

#insmod key_input.ko

#./test /dev/event0 //或者

#./test /dev/input/event0 

  1. #include <stdio.h>

  2. #include <stdlib.h>

  3. #include <unistd.h>

  4. #include <fcntl.h>

  5. #include <string.h>

  6. #include <linux/input.h>


  7. int main(int argc, char ** argv)

  8. {

  9. int fd;
  10. int yalv;
  11. size_t rb;/* the events (up to 64 at once) */
  12. struct input_event ev[64];
  13. if ((fd = open(argv[1], O_RDONLY)) < 0) {

  14. perror("evdev open");

  15. exit(1);

  16. }

  17. rb=read(fd,ev,sizeof(struct input_event)*64);

  18. if (rb < (int) sizeof(struct input_event))
  19.      {
  20.          perror("evtest: short read");
  21.          exit (1);
  22.          }
  23. for (yalv = 0; yalv < (int) (rb / sizeof(struct input_event)); yalv++)
  24.      {
  25.          if (EV_KEY == ev[yalv].type)
  26.           printf("%ld.%06ld ", ev[yalv].time.tv_sec,ev[yalv].time.tv_usec);
  27.          printf("type %d code %d value %d\n", ev[yalv].type, ev[yalv].code, ev[yalv].value);
  28. }

  29. close(fd);
  30. return 0;
  31. }


 

五、问题

阅读(1666) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~