6.Linux按键驱动-阻塞与非阻塞

[复制链接]
发表于 2024-10-27 10:30:11 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

×
默认打开文件时间是阻塞的
  1. 当设置打开方式为非阻塞时,无数据时会返回。
  2. 当设置打开方式为阻塞时,无数据的时候会等待
复制代码
1.设置打开方式为非阻塞

立即返回,无法读出,返回-1

2.设置为阻塞

焦点在于驱动程序中的.read函数的支持

3.代码实现
应用程序:
  1. #include <stdio.h>
  2. #include <sys/types.h>
  3. #include <sys/stat.h>
  4. #include <fcntl.h>
  5. #include <unistd.h>
  6. #include <poll.h>
  7. #include <signal.h>
  8. static int fd;
  9. /* 信号处理函数 */
  10. /*static void sig_func(int sig)
  11. {
  12.         int val;
  13.         int num;
  14.         read(fd,&val,4);
  15.         num  = val >>8;
  16.         printf("get button: %d val = %d\n", num, val - num *(1 << 8));
  17. }*/
  18. int main(int argc, char** argv)
  19. {
  20.        
  21.         int val;
  22.         int num;
  23.         struct pollfd fds[1];
  24.         int timeout_ms = 5000;
  25.         int ret;
  26.         int flags;
  27.         int i;
  28.         /* 判断输入值是否合法 */
  29.         if(argc != 2)
  30.         {
  31.                 printf("Usage ./button_app /dev/devname\n");
  32.                 return -1;
  33.         }
  34.         fd = open(argv[1], O_RDONLY);
  35.         if (fd == -1)
  36.         {
  37.                 printf("open err\n");
  38.         }
  39.         else
  40.         {
  41.                 printf("open success\n");
  42.         }
  43.         /* 初始化文件监听描述符 */
  44.         /*fds[0].fd     = fd;
  45.         fds[0].events = POLLIN;*/
  46.         /*绑定SIGIO和sig_func */
  47.         //signal(SIGIO, sig_func);
  48.        
  49.         /* APP把自己的pid告诉驱动 */
  50.         //fcntl(fd, F_SETOWN, getpid());/* APP把自己的pid告诉驱动程序 */
  51.         //flags = fcntl(fd,F_GETFL);/* 获得标志位 */
  52.         //fcntl(fd, F_SETFL, flags | FASYNC);/* 使能异步通知 */
  53.         //printf("设置了FASYNC\n");
  54.         /*while(1)
  55.         {
  56.                 printf("www.100ask.net \n");
  57.                 sleep(2);
  58.         }*/
  59.        
  60.        
  61.         /*while(1)
  62.         {
  63.                 ret = poll(fds, 1, timeout_ms);
  64.                 if((ret == 1) && (fds[0].revents == POLLIN))
  65.                 {
  66.                         read(fd, &val, 4);
  67.                         num  = val >>8;
  68.                         printf("get button: %d val = %d\n", num, val - num *(1 << 8));
  69.                 }
  70.                 else
  71.                 {
  72.                         printf("timeout\n");
  73.                 }
  74.         }*/
  75.         /* 设置打开方式为非阻塞 */
  76.         fcntl(fd,F_SETFL,O_NONBLOCK);
  77.         for (i = 0; i < 10; i++)
  78.         {
  79.                 if (read(fd, &val, 4) == 4)
  80.                         printf("get button: 0x%x\n", val);
  81.                 else
  82.                         printf("get button: -1\n");
  83.         }
  84.         /* 设置打开方式为阻塞 */
  85.         flags = fcntl(fd,F_GETFL);
  86.         fcntl(fd,F_SETFL,flags & ~O_NONBLOCK);
  87.         while(1)
  88.         {
  89.                 if (read(fd, &val, 4) == 4)
  90.                 {
  91.                         num  = val >>8;
  92.                         printf("get button: %d val = %d\n", num, val - num *(1 << 8));
  93.                 }
  94.                 else
  95.                         printf("get button: -1\n");
  96.         }
  97.        
  98.         close(fd);
  99.         return 0;
  100. }
复制代码
驱动程序:
  1. #include <linux/module.h>
  2. #include <linux/fs.h>
  3. #include <linux/errno.h>
  4. #include <linux/miscdevice.h>
  5. #include <linux/kernel.h>
  6. #include <linux/major.h>
  7. #include <linux/mutex.h>
  8. #include <linux/proc_fs.h>
  9. #include <linux/seq_file.h>
  10. #include <linux/stat.h>
  11. #include <linux/init.h>
  12. #include <linux/device.h>
  13. #include <linux/tty.h>
  14. #include <linux/kmod.h>
  15. #include <linux/gfp.h>
  16. #include <linux/gpio/consumer.h>
  17. #include <linux/platform_device.h>
  18. #include <linux/of_gpio.h>
  19. #include <linux/of_irq.h>
  20. #include <linux/interrupt.h>
  21. #include <linux/irq.h>
  22. #include <linux/slab.h>
  23. #include <linux/poll.h>
  24. #include <linux/fcntl.h>
  25. /* 定义结构体来描述gpio */
  26. struct gpio_key{
  27.         int gpio;
  28.         struct gpio_desc* gpiod;
  29.         int flag;
  30.         int irq;
  31. };
  32. /* 定义全局变量来存储设备树中的所有gpio节点信息 */
  33. static struct gpio_key* gpio_keys_100ask;
  34. /* 字符设备的主设备号 */
  35. static unsigned int major = 0;
  36. static struct class *gpio_class;
  37. //static int g_key = 0;
  38. /* 定义等待队列 */
  39. static DECLARE_WAIT_QUEUE_HEAD(gpio_key_wait);
  40. struct fasync_struct * button_fasync;
  41. /* 环形缓冲区 */
  42. #define BUF_LEN 128
  43. static int g_keys[BUF_LEN];
  44. static int r, w;
  45. #define NEXT_POS(x) ((x+1) % BUF_LEN)
  46. int is_key_buf_empty(void)
  47. {
  48.         return (r == w);
  49. }
  50. int is_key_buf_full(void)
  51. {
  52.         return (r == NEXT_POS(w));
  53. }
  54. void put_key(int key)
  55. {
  56.         if (!is_key_buf_full())
  57.         {
  58.                 g_keys[w] = key;
  59.                 w = NEXT_POS(w);
  60.         }
  61. }
  62. int get_key(void)
  63. {
  64.         int key = 0;
  65.         if (!is_key_buf_empty())
  66.         {
  67.                 key = g_keys[r];
  68.                 r = NEXT_POS(r);
  69.         }
  70.         return key;
  71. }
  72. static ssize_t gpio_read(struct file *fp, char __user *buf, size_t size, loff_t * offset)
  73. {
  74.         int err;
  75.         int key;
  76.         if(is_key_buf_empty() && (fp->f_flags & O_NONBLOCK))
  77.         {
  78.                 return -EAGAIN;
  79.         }
  80.         //wait_event_interruptible(gpio_key_wait, !is_key_buf_empty());
  81.         key = get_key();
  82.         //err = copy_to_user(buf, &g_key, 4);
  83.         err = copy_to_user(buf, &key, 4);
  84.         //g_key = 0;
  85.         //printk("%s %s line %d\n", __FILE__, __FUNCTION__, __LINE__);
  86.         return 4;
  87. }
  88. static unsigned int gpio_poll(struct file *fp, struct poll_table_struct *wait)
  89. {
  90.         //printk("%s %s line %d\n", __FILE__, __FUNCTION__, __LINE__);
  91.         poll_wait(fp, &gpio_key_wait, wait);
  92.         return is_key_buf_empty() ? 0 : POLLIN | POLLRDNORM;
  93. }
  94. static int gpio_fasync(int fd , struct file *file, int on)
  95. {
  96.         //printk("%s %s line %d\n", __FILE__, __FUNCTION__, __LINE__);
  97.         if (fasync_helper(fd, file, on, &button_fasync) >= 0)
  98.         {
  99.                 return 0;
  100.         }
  101.         else
  102.         {
  103.                 return -EIO;
  104.         }
  105. }
  106. static const struct file_operations gpio_fops = {
  107.         .owner = THIS_MODULE,
  108.         .read  = gpio_read,
  109.         .poll  = gpio_poll,
  110.         .fasync = gpio_fasync,
  111. };
  112. static irqreturn_t gpio_key_isr(int irq, void *dev_id)
  113. {
  114.         struct gpio_key* gpio_key = dev_id;
  115.         int val;
  116.         int key;
  117.         val = gpio_get_value(gpio_key->gpio);
  118.         //printk("key %d %d\n", gpio_key->gpio, val);
  119.         //g_key = (gpio_key->gpio << 8) | val;
  120.         key = (gpio_key->gpio << 8) | val;
  121.        
  122.         put_key(key);
  123.         wake_up_interruptible(&gpio_key_wait);
  124.         /* 发信号 */
  125.         kill_fasync(&button_fasync, SIGIO, POLL_IN);
  126.         //printk("%s %s line %d\n", __FILE__, __FUNCTION__, __LINE__);
  127.         return IRQ_HANDLED;
  128. }
  129. static int gpio_probe(struct platform_device *pdev)
  130. {
  131.         int count, i;
  132.         struct device_node *node;
  133.         int err;
  134.         node = pdev->dev.of_node;
  135.         count = of_gpio_count(node);
  136.         if (!count)
  137.         {
  138.                 printk("%s %s line %d, there isn't any gpio available\n", __FILE__, __FUNCTION__, __LINE__);
  139.                 return -1;
  140.         }
  141.        
  142.         /* 申请资源 */
  143.         gpio_keys_100ask = kzalloc(sizeof(struct gpio_key) * count, GFP_KERNEL);
  144.         if (!gpio_keys_100ask)
  145.         {
  146.                 printk("kzalloc error\n");
  147.                 return -1;
  148.         }
  149.         /* 获得资源 */
  150.         for (i = 0; i < count; i++)
  151.         {
  152.                 gpio_keys_100ask[i].gpio = of_get_gpio(node, i);
  153.                 if (gpio_keys_100ask[i].gpio < 0)
  154.                 {
  155.                         printk("%s %s line %d, of_get_gpio_flags fail\n", __FILE__, __FUNCTION__, __LINE__);
  156.                         return -1;
  157.                 }
  158.                 gpio_keys_100ask[i].gpiod = gpio_to_desc(gpio_keys_100ask[i].gpio);
  159.                 gpio_keys_100ask[i].irq   = gpio_to_irq(gpio_keys_100ask[i].gpio);
  160.                 /* 申请中断 */
  161.                 err = request_irq(gpio_keys_100ask[i].irq, gpio_key_isr, IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, "test1_gpio_keys_100ask", &gpio_keys_100ask[i]);
  162.                 if (err)
  163.                 {
  164.                         printk("request_irq err\n");
  165.                 }
  166.         }
  167.         /* 注册字符设备 */
  168.         major = register_chrdev(major, "100ask_key", &gpio_fops);
  169.         if(major < 0)
  170.         {
  171.                 printk("register_chrdev err'\n");
  172.                 return -1;
  173.         }
  174.         /* 注册类 */
  175.         gpio_class = class_create(THIS_MODULE, "100ask_key_class");
  176.         /* 注册设备 */
  177.         device_create(gpio_class, NULL, MKDEV(major,0), NULL, "100ask_key_button");
  178.         printk("%s %s line %d\n", __FILE__, __FUNCTION__, __LINE__);
  179.         return 0;
  180. }
  181. static int gpio_remove(struct platform_device *pdev)
  182. {
  183.         int count, i;
  184.         struct device_node *node;
  185.         node = pdev->dev.of_node;
  186.         count = of_gpio_count(node);
  187.         device_destroy(gpio_class, MKDEV(major,0));
  188.         class_destroy(gpio_class);
  189.         unregister_chrdev(major, "100ask_key");
  190.         for (i = 0; i < count; i++)
  191.         {
  192.                 free_irq(gpio_keys_100ask[i].irq, &gpio_keys_100ask[i]);
  193.         }
  194.         kfree(gpio_keys_100ask);
  195.         printk("%s %s line %d\n", __FILE__, __FUNCTION__, __LINE__);
  196.         return 0;
  197. }
  198. /*
  199. * 在设备树中添加的节点的compatible属性为:"test1_100ask,test1_gpio_key"
  200. */
  201. static const struct of_device_id gpio_key_of_match[] = {
  202.         {.compatible = "test1_100ask,test1_gpio_key"},
  203.         {/* 这里必须要有一个空项,表示结束 */}
  204. };
  205. static struct platform_driver gpio_driver = {
  206.         .driver = {
  207.                 .name        = "test1_gpio_keys_100ask",
  208.                 .of_match_table = gpio_key_of_match,
  209.         },
  210.         .probe        = gpio_probe,
  211.         .remove = gpio_remove,
  212. };
  213. /* 基于platform总线来实现这个程序 */
  214. static int gpio_init(void)  
  215. {
  216.         int ret;
  217.         ret = platform_driver_register(&gpio_driver);
  218.         if (ret != 0)
  219.         {
  220.                 printk("platform_driver_register err\n");
  221.                 return -1;
  222.         }
  223.         else
  224.         {
  225.                 printk("%s %s line %d\n", __FILE__, __FUNCTION__, __LINE__);
  226.         }
  227.         return ret;
  228. }
  229. static void gpio_exit(void)
  230. {
  231.         platform_driver_unregister(&gpio_driver);
  232.         printk("%s %s line %d\n", __FILE__, __FUNCTION__, __LINE__);
  233. }
  234. module_init(gpio_init);
  235. module_exit(gpio_exit);
  236. MODULE_LICENSE("GPL");
复制代码
4.代码路径:
  1. /home/book/nfs_rootfs/CSDN/01_gpio_irq/06_read_key_irq_poll_fasync_block
复制代码
回复

使用道具 举报

登录后关闭弹窗

登录参与点评抽奖  加入IT实名职场社区
去登录
快速回复 返回顶部 返回列表