创客神器NanoPi
直播中

左宗棠

8年用户 31经验值
擅长:可编程逻辑
私信 关注
[经验]

【NanoPi M2试用体验】字符类按键源码

在上一贴成功点灯以后,笔者果断决定对代码进行修改,使其成为读取按键的程序。采用的是最笨的while循环查询的方法,希望对一起学习的新手们提供一定的借鉴,献丑了。
key.c:
  1. /*包含初始化宏定义的头文件,代码中的module_init和module_exit在此文件中*/
  2. #include
  3. /*包含初始化加载模块的头文件,代码中的MODULE_LICENSE在此头文件中*/
  4. #include
  5. /*三个字符设备函数*/
  6. #include
  7. /*MKDEV转换设备号数据类型的宏定义*/
  8. #include
  9. /*定义字符设备的结构体*/
  10. #include
  11. /*分配内存空间函数头文件*/
  12. #include
  13. /*包含函数device_create 结构体class等头文件*/
  14. #include

  15. #include //copy_to_user要包含这个
  16. #include
  17. #include //包含prink等函数
  18. #include //与c++相关的东西
  19. #include //Linux中申请GPIO的头文件
  20. /*自定义头文件*/
  21. #include "key.h"

  22. #include //不同平台使用的文件
  23. #include


  24. MODULE_LICENSE("Dual BSD/GPL");
  25. /*声明是开源的,没有内核版本限制*/
  26. MODULE_AUTHOR("XIE");
  27. /*声明作者*/

  28. static int key_gpios[] = {
  29.         PAD_GPIO_C + 11,
  30. };
  31. #define KEY_NUM                ARRAY_SIZE(key_gpios)


  32. int numdev_major = DEV_MAJOR;
  33. int numdev_minor = DEV_MINOR;

  34. static struct class *myclass;
  35. struct reg_dev *my_devices;

  36. /*打开操作*/
  37. static int chardevnode_open(struct inode *inode, struct file *file){
  38.         printk(KERN_EMERG "chardevnode_open is success!n");
  39.        
  40.         return 0;
  41. }
  42. /*关闭操作*/
  43. static int chardevnode_release(struct inode *inode, struct file *file){
  44.         printk(KERN_EMERG "chardevnode_release is success!n");
  45.        
  46.         return 0;
  47. }
  48. /*IO操作*/
  49. static long chardevnode_ioctl(struct file *file, unsigned int cmd, unsigned long arg){
  50.         return 0;
  51. }

  52. ssize_t chardevnode_read(struct file *file, char __user *buf, size_t count, loff_t *f_ops){
  53.         unsigned long key_val[KEY_NUM];
  54.         int i;
  55.         for(i = 0; i < KEY_NUM; i++){
  56.                 key_val[i] = gpio_get_value(key_gpios[i]);
  57.         }
  58.         /* 读出值后,将数据传给应用程序 */
  59.         copy_to_user(buf, key_val, sizeof(key_val));

  60.         return sizeof(key_val);
  61. }

  62. ssize_t chardevnode_write(struct file *file, const char __user *buf, size_t count, loff_t *f_ops){
  63.         return 0;
  64. }

  65. loff_t chardevnode_llseek(struct file *file, loff_t offset, int ence){
  66.         return 0;
  67. }
  68. struct file_operations my_fops = {
  69.         .owner = THIS_MODULE,
  70.         .open = chardevnode_open,
  71.         .release = chardevnode_release,
  72.         .unlocked_ioctl = chardevnode_ioctl,
  73.         .read = chardevnode_read,
  74.         .write = chardevnode_write,
  75.         .llseek = chardevnode_llseek,
  76. };


  77. /*设备注册到系统*/
  78. static void reg_init_cdev(struct reg_dev *dev,int index){
  79.         int err;
  80.         int devno = MKDEV(numdev_major,numdev_minor+index);

  81.         /*数据初始化*/
  82.         cdev_init(&dev->cdev,&my_fops);
  83.         dev->cdev.owner = THIS_MODULE;
  84.        
  85.        
  86.         /*注册到系统*/
  87.         err = cdev_add(&dev->cdev,devno,1);
  88.         if(err){
  89.                 printk(KERN_EMERG "cdev_add %d is fail! %dn",index,err);
  90.         }
  91.         else{
  92.                 printk(KERN_EMERG "cdev_add %d is success!n",numdev_minor+index);
  93.         }
  94. }

  95. static int gpio_init(void){
  96.         int i=0,ret;
  97.        
  98.         for(i=0;i
  99.                 ret = gpio_request(key_gpios[i], "KEY");
  100.                 if (ret) {
  101.                         printk("%s: request GPIO %d for KEY failed, ret = %dn", DEVICE_NAME,i,ret);
  102.                         return -1;
  103.                 }
  104.                 else{
  105.                         gpio_direction_output(key_gpios[i], 1);                       
  106.                 }
  107.         }
  108.        
  109.         return 0;
  110. }


  111. static int scdev_init(void)
  112. {
  113.         int ret = 0,i;
  114.         dev_t num_dev;
  115.        
  116.        
  117.         printk(KERN_EMERG "numdev_major is %d!n",numdev_major);//主设备号
  118.         printk(KERN_EMERG "numdev_minor is %d!n",numdev_minor);//次设备号
  119.        
  120.         if(numdev_major){
  121.                 num_dev = MKDEV(numdev_major,numdev_minor);//生成设备号
  122.                 ret = register_chrdev_region(num_dev,DEVICE_MINOR_NUM,DEVICE_NAME);//向系统申请设备号(已知设备号)
  123.         }
  124.         else{
  125.                 /*动态注册设备号*/
  126.                 ret = alloc_chrdev_region(&num_dev,numdev_minor,DEVICE_MINOR_NUM,DEVICE_NAME);//向系统申请设备号(动态申请)
  127.                 /*获得主设备号*/
  128.                 numdev_major = MAJOR(num_dev);
  129.                 printk(KERN_EMERG "adev_region req %d !n",numdev_major);
  130.         }
  131.         if(ret<0){
  132.                 printk(KERN_EMERG "register_chrdev_region req %d is failed!n",numdev_major);               
  133.         }
  134.         myclass = class_create(THIS_MODULE,DEVICE_NAME);//创建设备类别文件
  135.        
  136.        
  137.         my_devices = kmalloc(DEVICE_MINOR_NUM * sizeof(struct reg_dev),GFP_KERNEL);//分配内存
  138.         if(!my_devices){
  139.                 ret = -ENOMEM;
  140.                 goto fail;
  141.         }
  142.         memset(my_devices,0,DEVICE_MINOR_NUM * sizeof(struct reg_dev));//将s中前n个字节用 ch 替换并返回 s 。
  143.        
  144.         /*设备初始化*/
  145.         for(i=0;i
  146.                 my_devices[i].data = kmalloc(REGDEV_SIZE,GFP_KERNEL);//GFP_KERNEL是一个宏,分配内核空间
  147.                 memset(my_devices[i].data,0,REGDEV_SIZE);
  148.                 /*设备注册到系统*/
  149.                 reg_init_cdev(&my_devices[i],i);
  150.                
  151.                 /*创建设备节点*/
  152.                 device_create(myclass,NULL,MKDEV(numdev_major,numdev_minor+i),NULL,DEVICE_NAME"%d",i);
  153.         }
  154.        
  155.         ret = gpio_init();
  156.         if(ret){
  157.                 printk(KERN_EMERG "gpio_init failed!n");
  158.         }       
  159.                
  160.         printk(KERN_EMERG "scdev_init!n");
  161.         /*打印信息,KERN_EMERG表示紧急信息*/
  162.         return 0;

  163. fail:
  164.         /*注销设备号*/
  165.         unregister_chrdev_region(MKDEV(numdev_major,numdev_minor),DEVICE_MINOR_NUM);
  166.         printk(KERN_EMERG "kmalloc is fail!n");
  167.        
  168.         return ret;
  169. }

  170. static void scdev_exit(void)
  171. {
  172.         int i;
  173.         printk(KERN_EMERG "scdev_exit!n");
  174.        
  175.         /*除去字符设备*/
  176.         for(i=0;i
  177.                 cdev_del(&(my_devices[i].cdev));//这个函数会干掉cdev_map 散列表及dev本身
  178.                 /*摧毁设备节点函数d*/
  179.                 device_destroy(myclass,MKDEV(numdev_major,numdev_minor+i));
  180.         }
  181.         /*释放设备class*/
  182.         class_destroy(myclass);
  183.         /*释放内存*/
  184.         kfree(my_devices);
  185.        
  186.         /*释放GPIO*/
  187.         for(i=0;i
  188.                 gpio_free(key_gpios[i]);
  189.         }
  190.         //释放设备号       
  191.         unregister_chrdev_region(MKDEV(numdev_major,numdev_minor),DEVICE_MINOR_NUM);
  192. }


  193. module_init(scdev_init);
  194. /*初始化函数*/
  195. module_exit(scdev_exit);
  196. /*卸载函数*/
key.h:
  1. #ifndef _CHAR_DRIVER_LEDS_H_
  2. #define _CHAR_DRIVER_LEDS_H_

  3. #ifndef DEVICE_NAME
  4. #define DEVICE_NAME "charGPIO"
  5. #endif

  6. #ifndef DEVICE_MINOR_NUM
  7. #define DEVICE_MINOR_NUM 1
  8. #endif

  9. #ifndef DEV_MAJOR
  10. #define DEV_MAJOR 0
  11. #endif

  12. #ifndef DEV_MINOR
  13. #define DEV_MINOR 0
  14. #endif

  15. #ifndef REGDEV_SIZE
  16. #define REGDEV_SIZE 3000
  17. #endif

  18. struct reg_dev
  19. {
  20.         char *data;
  21.         // unsigned long size;
  22.         struct cdev cdev;
  23. };
  24. #endif
key_test.c:
  1. #include
  2. #include
  3. #include //各种系统api如read,write,sleep
  4. #include

  5. int main()
  6. {
  7.         int fd,i;
  8.         unsigned long key_val[1];
  9.         char *lednode = "/dev/charGPIO0";

  10.         /*O_RDWR只读打开,O_NDELAY非阻塞方式*/       
  11.         if((fd = open(lednode,O_RDWR|O_NDELAY))<0){
  12.                 printf("APP open %s failed!n",lednode);
  13.         }
  14.         else
  15.                 printf("APP open %s success!n",lednode);
  16.         while(1)
  17.         {
  18.                 read(fd,key_val,sizeof(key_val));
  19.                 if(key_val[0] == 0)
  20.                         printf("button0 is setn");
  21.                 else
  22.                         printf("waiting button0n");
  23.                 sleep(1);
  24.         }
  25.        
  26.        
  27.         close(fd);
  28.         return 0;
  29. }
以上,由于是笔者是新手所以难免有疏漏或者不足,敬请各路大神指教咯

更多回帖

发帖
×
20
完善资料,
赚取积分