|
GPIO中断如何传递到应用程序
发表于 2017-11-30 17:50:05
浏览:12565
|
回复:8
打印
只看该作者
[复制链接]
楼主
本帖最后由 Icefly 于 2017-12-15 18:01 编辑
朋友们好,我使用rk3399的板子学习GPIO驱动,跑了官网GPIO驱动的例子(http://wiki.t-firefly.com/index.php/Firefly-RK3399/GPIO),能够在内核log里看到相关的中断信息;
接着我想将该中断信息传递给上层应用程序,在应用程序里做出响应,不知道应该怎么做,新手上路请诸位多多指教。
从网上了解的的信息来看,有说用异步通信的,也有说使用input框架的,都看不太明白,如果能给个示例代码那最好啦。
参考网上的例子写了个用netlink实现用户空间和内核空间通信的例子,代码大致如下
gpio-firefly.c
- /* * Driver for pwm demo on Firefly board. * * Copyright (C) 2016, Zhongshan T-chip Intelligent Technology Co.,ltd. * Copyright 2006 JC.Lin * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. */
- #include <linux/module.h>
- #include <linux/kernel.h>
- #include <linux/init.h>
- #include <linux/err.h>
- #include <linux/gpio.h>
- #include <linux/io.h>
- #include <linux/of.h>
- #include <linux/of_gpio.h>
- #include <linux/interrupt.h>
- #include <linux/platform_device.h>
- #include <linux/workqueue.h>
- #include <linux/types.h>
- #include <net/sock.h>
- #include <linux/netlink.h>
- /*
- #define NETLINK_TEST 16
- struct sock *nl_sk = NULL;
- EXPORT_SYMBOL_GPL(nl_sk);
- */
- #define NETLINK_USER 22
- #define USER_MSG (NETLINK_USER+1)
- #define USER_PORT 50
- static struct sock *netlinkfd = NULL;
- static void *netlinkdata = NULL;
- static int netlinkdatalen = 0;
- static struct workqueue_struct *queue=NULL;
- static struct work_struct my_wq;
- static void my_wq_func(struct work_struct *data);
- struct firefly_gpio_info
- {
- //struct device *dev;
- //long firefly_param;
- int firefly_gpio;
- int gpio_enable_value;
- int firefly_irq_gpio;
- int firefly_irq;
- int firefly_irq_mode;
- };
- /*
- void nl_data_ready(struct sk_buff *__skb)
- {
- struct sk_buff *skb;
- struct nlmsghdr *nlh;
- u32 pid;
- int rc;
- int len = NLMSG_SPACE(1200);
- char str[100];
- printk("new_link: data is ready to read.\n");
- skb = skb_get(__skb);
- if(skb->len >= NLMSG_SPACE(0))
- {
- nlh = nlmsg_hdr(skb);
- printk("net_link: recv %s.\n", (char *)NLMSG_DATA(nlh));
- memcpy(str, NLMSG_DATA(nlh), sizeof(str));
- pid = nlh->nlmsg_pid; //pid of sending process
- printk("net_link: pid is %d\n", pid);
- kfree_skb(skb);
- skb = alloc_skb(len, GFP_ATOMIC);
- if(!skb)
- {
- printk(KERN_ERR "net_link: allocate failed.\n");
- return;
- }
- nlh = nlmsg_put(skb, 0, 0, 0, 1200, 0);
- NETLINK_CB(skb).pid = 0; //from kernel
- memcpy(NLMSG_DATA(nlh), str, sizeof(str));
- printk("net_link: going to send.\n");
- rc = netlink_unicast(nl_sk, skb, pid, MSG_DONTWAIT);
- if(rc < 0)
- {
- printk(KERN_ERR "net_link: can not unicast skb (%d)\n", rc);
- }
- printk("net_link: send is ok.\n");
- }
- return;
- }
- static int test_netlink(void)
- {
- nl_sk = netlink_kernel_create(&init_net, NETLINK_TEST, 0, nl_data_ready, NULL, THIS_MODULE);
- if(!nl_sk)
- {
- printk(KERN_ERR "net_link: Cannot create netlink socket.\n");
- return -EIO;
- }
- printk("net_link: create socket ok.\n");
- return 0;
- }
- */
- int send_msg(int8_t *pbuf, uint16_t len)
- {
- struct sk_buff *nl_skb;
- struct nlmsghdr *nlh;
- int ret;
- nl_skb = nlmsg_new(len, GFP_ATOMIC);
- if(!nl_skb)
- {
- printk("netlink: netlink_alloc_skb error\n");
- return -1;
- }
- nlh = nlmsg_put(nl_skb, 0, 0, USER_MSG, len, 0);
- if(nlh == NULL)
- {
- printk("netlink: nlmsg_put() error\n");
- nlmsg_free(nl_skb);
- return -1;
- }
- memcpy(nlmsg_data(nlh), pbuf, len);
- ret = netlink_unicast(netlinkfd, nl_skb, USER_PORT, MSG_DONTWAIT);
- return ret;
- }
- static void recv_cb(struct sk_buff *skb)
- {
- struct nlmsghdr *nlh = NULL;
- void *data = NULL;
- printk("netlink: skb->len = %u\n", skb->len);
- if(skb->len >= nlmsg_total_size(0))
- {
- nlh = nlmsg_hdr(skb);
- data = NLMSG_DATA(nlh);
- if(data)
- {
- printk("netlink: kernel receive data: %s\n", (int8_t *)data);
- netlinkdata = data;
- netlinkdatalen = nlmsg_len(nlh);
- //send_msg(data, nlmsg_len(nlh));
- }
- }
- }
- struct netlink_kernel_cfg cfg =
- {
- .input = recv_cb,
- };
- static int test_netlink(void)
- {
- netlinkfd = netlink_kernel_create(&init_net, USER_MSG, &cfg);
- if(!netlinkfd)
- {
- printk(KERN_ERR "netlink: can not create a netlink socket!\n");
- return -1;
- }
- printk("netlink: create socket ok.\n");
- return 0;
- }
- //static struct fasync_struct *gpio_irq_async;
- static void my_wq_func(struct work_struct *data)
- {
- printk("Enter firefly gpio irq my_wq_func!\n");
- //test_netlink();
- if (netlinkdatalen > 0)
- {
- send_msg(netlinkdata, netlinkdatalen);
- netlinkdatalen = 0;
- printk("firefly netlink send_msg\n");
- }
- printk("Exit firefly gpio irq my_wq_func!\n");
- }
-
- static irqreturn_t firefly_gpio_irq(int irq, void *dev_id)
- {
- printk("Enter firefly gpio irq test program!\n");
- //kill_fasync(&gpio_irq_async, SIGIO,POLL_IN);
- schedule_work(&my_wq);
- return IRQ_HANDLED;
- }
- /*
- static int firefly_gpio_fasync(int fd, struct file *filp, int mode)
- {
- //struct scull_pipe *dev = filp->private_data;
- return fasync_helper(fd, filp, mode, &gpio_irq_async);
- }*/
- /*
- static ssize_t gpio_firefly_attr_show(struct device *dev, struct device_attribute *attr, char *buf)
- {
- struct firefly_gpio_info *gpio_info = dev_get_drvdata(dev);
- int len;
- len = sprintf(buf, "%ld\n", gpio_info->firefly_param);
- if (len < 0)
- {
- dev_err(dev, "firefly_gpio_info gpio_firefly_attr_show: Invalid sprintf, len= %d\n", len);
- }
- return len;
- }
- static ssize_t gpio_firefly_attr_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
- {
- struct firefly_gpio_info *gpio_info = dev_get_drvdata(dev);
- int ret;
- ret = kstrtol(buf, 10, &gpio_info->firefly_param);
- if (ret != 0)
- {
- dev_err(dev, "firefly_gpio_info gpio_firefly_attr_store: kstrtol failed, ret= %d\n", ret);
- }
- return count;
- }
- static DEVICE_ATTR(firefly_param, S_IRUGO | S_IWUSR, gpio_firefly_attr_show, gpio_firefly_attr_store);
- static struct attribute *firefly_gpio_attrs[] =
- {
- &dev_attr_firefly_param.attr,
- NULL,
- };
- static struct attribute_group firefly_gpio_attr_group =
- {
- .name = "firefly_gpio_info",
- .attrs = firefly_gpio_attrs,
- };
- */
-
- static int firefly_gpio_probe(struct platform_device *pdev)
- {
- int ret;
- int gpio;
- //int error;
- enum of_gpio_flags flag;
- struct firefly_gpio_info *gpio_info;
- struct device_node *firefly_gpio_node = pdev->dev.of_node;
- printk("Firefly GPIO Test Program Probe\n");
-
- gpio_info = devm_kzalloc(&pdev->dev,sizeof(struct firefly_gpio_info *), GFP_KERNEL);
- if (!gpio_info)
- {
- dev_err(&pdev->dev, "devm_kzalloc failed!\n");
- return -ENOMEM;
- }
- /*
- gpio_info->dev = &pdev->dev;
- platform_set_drvdata(pdev, gpio_info);
- */
- gpio = of_get_named_gpio_flags(firefly_gpio_node, "firefly-gpio", 0, &flag);
- if (!gpio_is_valid(gpio))
- {
- dev_err(&pdev->dev, "firefly-gpio: %d is invalid\n", gpio);
- return -ENODEV;
- }
- if (gpio_request(gpio, "firefly-gpio"))
- {
- dev_err(&pdev->dev, "firefly-gpio: %d request failed!\n", gpio);
- gpio_free(gpio);
- return -ENODEV;
- }
- gpio_info->firefly_gpio = gpio;
- gpio_info->gpio_enable_value = (flag == OF_GPIO_ACTIVE_LOW) ? 0:1;
- gpio_direction_output(gpio_info->firefly_gpio, gpio_info->gpio_enable_value);
- printk("Firefly gpio putout\n");
- /*
- gpio = of_get_named_gpio_flags(firefly_gpio_node, "firefly-gpio1", 0, &flag);
- if (!gpio_is_valid(gpio))
- {
- dev_err(&pdev->dev, "firefly-gpio1: %d is invalid\n", gpio);
- return -ENODEV;
- }
- if (gpio_request(gpio, "firefly-gpio1"))
- {
- dev_err(&pdev->dev, "firefly-gpio1: %d request failed!\n", gpio);
- gpio_free(gpio);
- return -ENODEV;
- }
- gpio_info->firefly_gpio = gpio;
- gpio_info->gpio_enable_value = (flag == OF_GPIO_ACTIVE_LOW) ? 0:1;
- gpio_direction_output(gpio_info->firefly_gpio, gpio_info->gpio_enable_value);
- printk("Firefly gpio1 putout\n");
- */
- gpio = of_get_named_gpio_flags(firefly_gpio_node, "firefly-irq-gpio", 0, &flag);
- printk("firefly:the gpio:%d\n",gpio);
- if (!gpio_is_valid(gpio))
- {
- dev_err(&pdev->dev, "firefly-irq-gpio: %d is invalid\n", gpio);
- return -ENODEV;
- }
- gpio_info->firefly_irq_gpio = gpio;
- gpio_info->firefly_irq_mode = flag;
- gpio_info->firefly_irq = gpio_to_irq(gpio_info->firefly_irq_gpio);
- if (gpio_info->firefly_irq)
- {
- if (gpio_request(gpio, "firefly-irq-gpio"))
- {
- dev_err(&pdev->dev, "firefly-irq-gpio: %d request failed!\n", gpio);
- gpio_free(gpio);
- return IRQ_NONE;
- }
- ret = request_irq(gpio_info->firefly_irq, firefly_gpio_irq, flag, "firefly-gpio", gpio_info);
- if (ret != 0)
- {
- free_irq(gpio_info->firefly_irq, gpio_info);
- dev_err(&pdev->dev, "firefly-gpio Failed to request IRQ: %d\n", ret);
- }
- queue = create_singlethread_workqueue("firefly-irq-gpio");
- if (!queue)
- {
- return -1;
- }
- INIT_WORK(&my_wq, my_wq_func);
- }
- /*
- error = sysfs_create_group(&pdev->dev.kobj, &firefly_gpio_attr_group);
- if (error) {
- dev_err(&pdev->dev, "Unable to export firefly param, error: %d\n",
- error);
- return error;
- }
- */
- test_netlink();
- return 0;
- }
- static int firefly_gpio_remove(struct platform_device *pdev)
- {
- // sysfs_remove_group(&pdev->dev.kobj, &firefly_gpio_attr_group);
- if (netlinkfd != NULL)
- {
- sock_release(netlinkfd->sk_socket);
- printk(KERN_DEBUG "netlink exit\n");
- }
- return 0;
- }
- /*
- struct file_operations firefly_gpio_fops = {
- .owner = THIS_MODULE,
- .llseek = no_llseek,
- .fasync = firefly_gpio_fasync,
- };*/
- static struct of_device_id firefly_match_table[] =
- {
- { .compatible = "firefly,rk3399-gpio",}, {}, };
- static struct platform_driver firefly_gpio_driver =
- {
- .driver = {
- .name = "firefly-gpio",
- .owner = THIS_MODULE,
- .of_match_table = firefly_match_table,
- },
- .probe = firefly_gpio_probe,
- .remove = firefly_gpio_remove,
- };
-
- static int firefly_gpio_init(void)
- {
- return platform_driver_register(&firefly_gpio_driver);
- }
- module_init(firefly_gpio_init);
- static void firefly_gpio_exit(void)
- {
- platform_driver_unregister(&firefly_gpio_driver);
- }
-
- module_exit(firefly_gpio_exit);
- MODULE_AUTHOR("linjc <service@t-firefly.com>");
- MODULE_DESCRIPTION("Firefly GPIO driver");
- MODULE_ALIAS("platform:firefly-gpio");
- MODULE_LICENSE("GPL");
复制代码
用户空间代码:
- #include <stdio.h>
- #include <stdlib.h>
- #include <sys/socket.h>
- #include <string.h>
- #include <linux/netlink.h>
- #include <stdint.h>
- #include <unistd.h>
- #include <errno.h>
- #define NETLINK_USER 22
- #define USER_MSG (NETLINK_USER+1)
- #define MSG_LEN 100
- #define MAX_PLOAD 100
- struct _my_msg
- {
- struct nlmsghdr hdr;
- int8_t data[MSG_LEN];
- };
- int main(int argc, char **argv)
- {
- char *data = "hello kernel";
- struct sockaddr_nl local, dest_addr;
- int skfd;
- struct nlmsghdr *nlh = NULL;
- struct _my_msg info;
- int ret;
- int socklen;
- int recvcount = 0;
- skfd = socket(AF_NETLINK, SOCK_RAW, USER_MSG);
- if(skfd == -1)
- {
- printf("create socket error... %s\n", strerror(errno));
- return -1;
- }
- memset(&local, 0, sizeof(local));
- local.nl_family = AF_NETLINK;
- local.nl_pid = 50;
- local.nl_groups = 0;
- if(bind(skfd, (struct sockaddr *)&local, sizeof(local)) != 0)
- {
- printf("bind() error\n");
- close(skfd);
- return -1;
- }
- memset(&dest_addr, 0, sizeof(dest_addr));
- dest_addr.nl_family = AF_NETLINK;
- dest_addr.nl_pid = 0;
- dest_addr.nl_groups = 0;
- nlh = (struct nlmsghdr *)malloc(NLMSG_SPACE(MAX_PLOAD));
- memset(nlh, 0, sizeof(struct nlmsghdr));
- nlh->nlmsg_len = NLMSG_SPACE(MAX_PLOAD);
- nlh->nlmsg_flags = 0;
- nlh->nlmsg_type = 0;
- nlh->nlmsg_seq = 0;
- nlh->nlmsg_pid = local.nl_pid;
- memcpy(NLMSG_DATA(nlh), data, strlen(data));
- while(1)
- {
- ret = sendto(skfd, nlh, nlh->nlmsg_len, 0, (struct sockaddr *)&dest_addr, sizeof(struct sockaddr_nl));
- if(!ret)
- {
- perror("sendto error1\n");
- close(skfd);
- exit(-1);
- }
- printf("wait kernel msg!\n");
- // while(1)
- // {
- memset(&info, 0, sizeof(info));
- socklen = sizeof(dest_addr);
- ret = recvfrom(skfd, &info, sizeof(struct _my_msg), 0, (struct sockaddr *)&dest_addr, (socklen_t*)&socklen);
- if(!ret)
- {
- perror("recv from kernel error\n");
- close(skfd);
- exit(-1);
- }
- printf("msg receive from kernel: %s, %d\n", info.data, recvcount++);
- if (recvcount%2 == 0)
- {
- system("./light on");
- }
- else
- {
- system("./light off");
- }
- }
- close(skfd);
- free((void *)nlh);
- return 0;
- }
复制代码
|
|