马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。
您需要 登录 才可以下载或查看,没有账号?立即注册
×
默认打开文件时间是阻塞的
- 当设置打开方式为非阻塞时,无数据时会返回。
- 当设置打开方式为阻塞时,无数据的时候会等待
复制代码 1.设置打开方式为非阻塞
立即返回,无法读出,返回-1
2.设置为阻塞
焦点在于驱动程序中的.read函数的支持
3.代码实现
应用程序:
- #include <stdio.h>
- #include <sys/types.h>
- #include <sys/stat.h>
- #include <fcntl.h>
- #include <unistd.h>
- #include <poll.h>
- #include <signal.h>
- static int fd;
- /* 信号处理函数 */
- /*static void sig_func(int sig)
- {
- int val;
- int num;
- read(fd,&val,4);
- num = val >>8;
- printf("get button: %d val = %d\n", num, val - num *(1 << 8));
- }*/
- int main(int argc, char** argv)
- {
-
- int val;
- int num;
- struct pollfd fds[1];
- int timeout_ms = 5000;
- int ret;
- int flags;
- int i;
- /* 判断输入值是否合法 */
- if(argc != 2)
- {
- printf("Usage ./button_app /dev/devname\n");
- return -1;
- }
- fd = open(argv[1], O_RDONLY);
- if (fd == -1)
- {
- printf("open err\n");
- }
- else
- {
- printf("open success\n");
- }
- /* 初始化文件监听描述符 */
- /*fds[0].fd = fd;
- fds[0].events = POLLIN;*/
- /*绑定SIGIO和sig_func */
- //signal(SIGIO, sig_func);
-
- /* APP把自己的pid告诉驱动 */
- //fcntl(fd, F_SETOWN, getpid());/* APP把自己的pid告诉驱动程序 */
- //flags = fcntl(fd,F_GETFL);/* 获得标志位 */
- //fcntl(fd, F_SETFL, flags | FASYNC);/* 使能异步通知 */
- //printf("设置了FASYNC\n");
- /*while(1)
- {
- printf("www.100ask.net \n");
- sleep(2);
- }*/
-
-
- /*while(1)
- {
- ret = poll(fds, 1, timeout_ms);
- if((ret == 1) && (fds[0].revents == POLLIN))
- {
- read(fd, &val, 4);
- num = val >>8;
- printf("get button: %d val = %d\n", num, val - num *(1 << 8));
- }
- else
- {
- printf("timeout\n");
- }
- }*/
- /* 设置打开方式为非阻塞 */
- fcntl(fd,F_SETFL,O_NONBLOCK);
- for (i = 0; i < 10; i++)
- {
- if (read(fd, &val, 4) == 4)
- printf("get button: 0x%x\n", val);
- else
- printf("get button: -1\n");
- }
- /* 设置打开方式为阻塞 */
- flags = fcntl(fd,F_GETFL);
- fcntl(fd,F_SETFL,flags & ~O_NONBLOCK);
- while(1)
- {
- if (read(fd, &val, 4) == 4)
- {
- num = val >>8;
- printf("get button: %d val = %d\n", num, val - num *(1 << 8));
- }
- else
- printf("get button: -1\n");
- }
-
- close(fd);
- return 0;
- }
复制代码 驱动程序:
- #include <linux/module.h>
- #include <linux/fs.h>
- #include <linux/errno.h>
- #include <linux/miscdevice.h>
- #include <linux/kernel.h>
- #include <linux/major.h>
- #include <linux/mutex.h>
- #include <linux/proc_fs.h>
- #include <linux/seq_file.h>
- #include <linux/stat.h>
- #include <linux/init.h>
- #include <linux/device.h>
- #include <linux/tty.h>
- #include <linux/kmod.h>
- #include <linux/gfp.h>
- #include <linux/gpio/consumer.h>
- #include <linux/platform_device.h>
- #include <linux/of_gpio.h>
- #include <linux/of_irq.h>
- #include <linux/interrupt.h>
- #include <linux/irq.h>
- #include <linux/slab.h>
- #include <linux/poll.h>
- #include <linux/fcntl.h>
- /* 定义结构体来描述gpio */
- struct gpio_key{
- int gpio;
- struct gpio_desc* gpiod;
- int flag;
- int irq;
- };
- /* 定义全局变量来存储设备树中的所有gpio节点信息 */
- static struct gpio_key* gpio_keys_100ask;
- /* 字符设备的主设备号 */
- static unsigned int major = 0;
- static struct class *gpio_class;
- //static int g_key = 0;
- /* 定义等待队列 */
- static DECLARE_WAIT_QUEUE_HEAD(gpio_key_wait);
- struct fasync_struct * button_fasync;
- /* 环形缓冲区 */
- #define BUF_LEN 128
- static int g_keys[BUF_LEN];
- static int r, w;
- #define NEXT_POS(x) ((x+1) % BUF_LEN)
- int is_key_buf_empty(void)
- {
- return (r == w);
- }
- int is_key_buf_full(void)
- {
- return (r == NEXT_POS(w));
- }
- void put_key(int key)
- {
- if (!is_key_buf_full())
- {
- g_keys[w] = key;
- w = NEXT_POS(w);
- }
- }
- int get_key(void)
- {
- int key = 0;
- if (!is_key_buf_empty())
- {
- key = g_keys[r];
- r = NEXT_POS(r);
- }
- return key;
- }
- static ssize_t gpio_read(struct file *fp, char __user *buf, size_t size, loff_t * offset)
- {
- int err;
- int key;
- if(is_key_buf_empty() && (fp->f_flags & O_NONBLOCK))
- {
- return -EAGAIN;
- }
- //wait_event_interruptible(gpio_key_wait, !is_key_buf_empty());
- key = get_key();
- //err = copy_to_user(buf, &g_key, 4);
- err = copy_to_user(buf, &key, 4);
- //g_key = 0;
- //printk("%s %s line %d\n", __FILE__, __FUNCTION__, __LINE__);
- return 4;
- }
- static unsigned int gpio_poll(struct file *fp, struct poll_table_struct *wait)
- {
- //printk("%s %s line %d\n", __FILE__, __FUNCTION__, __LINE__);
- poll_wait(fp, &gpio_key_wait, wait);
- return is_key_buf_empty() ? 0 : POLLIN | POLLRDNORM;
- }
- static int gpio_fasync(int fd , struct file *file, int on)
- {
- //printk("%s %s line %d\n", __FILE__, __FUNCTION__, __LINE__);
- if (fasync_helper(fd, file, on, &button_fasync) >= 0)
- {
- return 0;
- }
- else
- {
- return -EIO;
- }
- }
- static const struct file_operations gpio_fops = {
- .owner = THIS_MODULE,
- .read = gpio_read,
- .poll = gpio_poll,
- .fasync = gpio_fasync,
- };
- static irqreturn_t gpio_key_isr(int irq, void *dev_id)
- {
- struct gpio_key* gpio_key = dev_id;
- int val;
- int key;
- val = gpio_get_value(gpio_key->gpio);
- //printk("key %d %d\n", gpio_key->gpio, val);
- //g_key = (gpio_key->gpio << 8) | val;
- key = (gpio_key->gpio << 8) | val;
-
- put_key(key);
- wake_up_interruptible(&gpio_key_wait);
- /* 发信号 */
- kill_fasync(&button_fasync, SIGIO, POLL_IN);
- //printk("%s %s line %d\n", __FILE__, __FUNCTION__, __LINE__);
- return IRQ_HANDLED;
- }
- static int gpio_probe(struct platform_device *pdev)
- {
- int count, i;
- struct device_node *node;
- int err;
- node = pdev->dev.of_node;
- count = of_gpio_count(node);
- if (!count)
- {
- printk("%s %s line %d, there isn't any gpio available\n", __FILE__, __FUNCTION__, __LINE__);
- return -1;
- }
-
- /* 申请资源 */
- gpio_keys_100ask = kzalloc(sizeof(struct gpio_key) * count, GFP_KERNEL);
- if (!gpio_keys_100ask)
- {
- printk("kzalloc error\n");
- return -1;
- }
- /* 获得资源 */
- for (i = 0; i < count; i++)
- {
- gpio_keys_100ask[i].gpio = of_get_gpio(node, i);
- if (gpio_keys_100ask[i].gpio < 0)
- {
- printk("%s %s line %d, of_get_gpio_flags fail\n", __FILE__, __FUNCTION__, __LINE__);
- return -1;
- }
- gpio_keys_100ask[i].gpiod = gpio_to_desc(gpio_keys_100ask[i].gpio);
- gpio_keys_100ask[i].irq = gpio_to_irq(gpio_keys_100ask[i].gpio);
- /* 申请中断 */
- 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]);
- if (err)
- {
- printk("request_irq err\n");
- }
- }
- /* 注册字符设备 */
- major = register_chrdev(major, "100ask_key", &gpio_fops);
- if(major < 0)
- {
- printk("register_chrdev err'\n");
- return -1;
- }
- /* 注册类 */
- gpio_class = class_create(THIS_MODULE, "100ask_key_class");
- /* 注册设备 */
- device_create(gpio_class, NULL, MKDEV(major,0), NULL, "100ask_key_button");
- printk("%s %s line %d\n", __FILE__, __FUNCTION__, __LINE__);
- return 0;
- }
- static int gpio_remove(struct platform_device *pdev)
- {
- int count, i;
- struct device_node *node;
- node = pdev->dev.of_node;
- count = of_gpio_count(node);
- device_destroy(gpio_class, MKDEV(major,0));
- class_destroy(gpio_class);
- unregister_chrdev(major, "100ask_key");
- for (i = 0; i < count; i++)
- {
- free_irq(gpio_keys_100ask[i].irq, &gpio_keys_100ask[i]);
- }
- kfree(gpio_keys_100ask);
- printk("%s %s line %d\n", __FILE__, __FUNCTION__, __LINE__);
- return 0;
- }
- /*
- * 在设备树中添加的节点的compatible属性为:"test1_100ask,test1_gpio_key"
- */
- static const struct of_device_id gpio_key_of_match[] = {
- {.compatible = "test1_100ask,test1_gpio_key"},
- {/* 这里必须要有一个空项,表示结束 */}
- };
- static struct platform_driver gpio_driver = {
- .driver = {
- .name = "test1_gpio_keys_100ask",
- .of_match_table = gpio_key_of_match,
- },
- .probe = gpio_probe,
- .remove = gpio_remove,
- };
- /* 基于platform总线来实现这个程序 */
- static int gpio_init(void)
- {
- int ret;
- ret = platform_driver_register(&gpio_driver);
- if (ret != 0)
- {
- printk("platform_driver_register err\n");
- return -1;
- }
- else
- {
- printk("%s %s line %d\n", __FILE__, __FUNCTION__, __LINE__);
- }
- return ret;
- }
- static void gpio_exit(void)
- {
- platform_driver_unregister(&gpio_driver);
- printk("%s %s line %d\n", __FILE__, __FUNCTION__, __LINE__);
- }
- module_init(gpio_init);
- module_exit(gpio_exit);
- MODULE_LICENSE("GPL");
复制代码 4.代码路径:
- /home/book/nfs_rootfs/CSDN/01_gpio_irq/06_read_key_irq_poll_fasync_block
复制代码 |