介绍三种linux驱动生成文件节点的方法

您所在的位置:网站首页 linux驱动在哪个文件夹 介绍三种linux驱动生成文件节点的方法

介绍三种linux驱动生成文件节点的方法

2023-10-18 04:27| 来源: 网络整理| 查看: 265

linux用户空间和kernel空间是分开,所以上层需要和某个模块驱动交流的时候,就需要驱动来创建一个文件节点,当然input设备除外,已有非常成熟的上报流程。现在介绍3种驱动生成文件节点的方法:

1、在/dev下面创建节点

2、在/proc下面创建节点

上图中建的节点是/proc/onekey_recovery/last_pressed,如果不用proc_mkdir而只用proc_create的话,则生成的节点是/proc/last_pressed

3、在/sys下面创建节点

重点参考md_gpiox_write,md_gpiox_read,DEVICE_ATTR,device_create_file,这里生成的节点在/sys/devices/...

#include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef CONFIG_OF #include #include #endif #include //#include //#include #define USE_INTERRUPT 1 #define D1_RST_PIN 84 struct md_gpio_eint_data { struct switch_dev sdev84; unsigned gpio84; //alarm输入 const char *state_on; const char *state_off; int irq84; struct work_struct work84; #ifdef CONFIG_OF struct device_node *irq_node84; #endif }; static char last_pressed =0; #ifdef USE_INTERRUPT static void md_gpio_eint_work84(struct work_struct *work) { int state; struct md_gpio_eint_data *data = container_of(work, struct md_gpio_eint_data, work84); msleep(3000); //3s state = gpio_get_value(data->gpio84); pr_err("%s: state=%d\n", __FUNCTION__, state); switch_set_state(&data->sdev84, state); /* if(state) irq_set_irq_type(data->irq84, IRQF_TRIGGER_LOW); else irq_set_irq_type(data->irq84, IRQF_TRIGGER_HIGH); */ enable_irq(data->irq84); } static irqreturn_t gpio_irq_handler84(int irq, void *dev_id) { struct md_gpio_eint_data *switch_data = (struct md_gpio_eint_data *)dev_id; disable_irq_nosync(switch_data->irq84); printk(KERN_ERR "vision_d:RST-KEY work84 irq handler \n"); last_pressed =1; schedule_work(&switch_data->work84); return IRQ_HANDLED; } #endif /* static int d1_reset_thread(void *x) { int gpio84; msleep(2000); //2s do{ //printk("vision_d:%s \n",__func__); gpio84 = gpio_get_value(D1_RST_PIN); if(gpio84 ==0){ msleep(2000); //2s gpio84 = gpio_get_value(D1_RST_PIN); if(gpio84 ==0) kernel_restart(NULL); }else msleep(100); //100ms }while (!kthread_should_stop()); return 0; } */ static int rgpio = -1; static ssize_t md_gpiox_write(struct device *dev, struct device_attribute *attr, char *buffer, size_t count) { int ret; int gpio_num = -1; int gpio_val = -1; int value; int n =0; ret = sscanf(buffer, "%d", &value); if(!ret) { pr_err("%s: intput error!\n", __FUNCTION__); return -1; } gpio_num = value; //printk(KERN_ERR "vision_d %s: gpio num %d\n", __FUNCTION__, gpio_num); while(value) { value = value / 10; n++; } buffer +=n; if(*buffer ==32){ ret = sscanf(buffer, "%d", &value); if(!ret) { pr_err("%s: intput error!\n", __FUNCTION__); return -1; } gpio_val = value; //printk(KERN_ERR "vision_d %s: gpio set value %d\n", __FUNCTION__, gpio_val); } printk(KERN_ERR "vision_d %s:set gpio%d %d\n", __FUNCTION__, gpio_num,gpio_val); if(gpio_val ==0) gpio_set_value(gpio_num, 0); else if(gpio_val ==1) gpio_set_value(gpio_num, 1); else rgpio = gpio_num; //gpio_free(gpio); return count; } static ssize_t md_gpiox_read(struct device *dev, struct device_attribute *attr, char *buffer) { if(rgpio > 0) return snprintf(buffer,PAGE_SIZE,"gpio%d=%d\n",rgpio,gpio_get_value(rgpio)); else return -1; } static DEVICE_ATTR(pinctl, S_IWUSR | S_IRUGO, md_gpiox_read, md_gpiox_write); static ssize_t rst_key_status_r(struct device *dev, struct device_attribute *attr, char *buff) { return snprintf(buff,PAGE_SIZE,"%d\n",last_pressed); } static ssize_t rst_key_status_w(struct device *dev, struct device_attribute *attr, char *buf, size_t count) { last_pressed =0; return count; } static DEVICE_ATTR(RstKeyStatus, S_IWUSR | S_IRUGO, rst_key_status_r, rst_key_status_w); static int md_gpio_eint_probe(struct platform_device *pdev) { struct md_gpio_eint_data *switch_data; int ret = 0; #if defined(CONFIG_OF) u32 ints[2] = { 0, 0 }; #endif ret = device_create_file(&pdev->dev,&dev_attr_RstKeyStatus); if(ret) printk(KERN_ERR "vision_d:create attr failed \n"); ret = device_create_file(&pdev->dev,&dev_attr_pinctl); if(ret) printk(KERN_ERR "vision_d:create attr failed \n"); pr_err("%s: start!\n", __FUNCTION__); switch_data = kzalloc(sizeof(struct md_gpio_eint_data), GFP_KERNEL); if (!switch_data) { pr_err("%s: kzalloc error!\n", __FUNCTION__); return -ENOMEM; } platform_set_drvdata(pdev, switch_data); switch_data->sdev84.name = "onekey_recovery"; //gpio84 switch_data->sdev84.index = 0; switch_data->sdev84.state = 0; switch_data->gpio84 = D1_RST_PIN; switch_data->state_on = "on"; switch_data->state_off = "off"; ret = switch_dev_register(&switch_data->sdev84); if (ret < 0) { pr_err("%s: fail to register sdev84!\n", __FUNCTION__); goto err_switch_dev_register; } ret = gpio_request(switch_data->gpio84, "gpio84"); if (ret < 0) { pr_err("%s: fail gpio_request 84!\n", __FUNCTION__); goto err_request_gpio; } /* ret = gpio_request(D1_RST_PIN, "gpio84"); if (ret < 0) { pr_err("%s: fail gpio_request 84!\n", __FUNCTION__); goto err_request_gpio; } */ ret = gpio_direction_input(switch_data->gpio84); if (ret < 0) { pr_err("%s: fail gpio_direction_input 84!\n", __FUNCTION__); goto err_set_gpio_input; } gpio_set_debounce(switch_data->gpio84, 100); /* ret = gpio_direction_input(D1_RST_PIN); if (ret < 0) { pr_err("%s: fail gpio_direction_input 84!\n", __FUNCTION__); goto err_set_gpio_input; } gpio_set_debounce(D1_RST_PIN, 100); */ #ifdef USE_INTERRUPT INIT_WORK(&switch_data->work84, md_gpio_eint_work84); #ifdef CONFIG_OF printk(KERN_ERR "vision_d:md_gpio_eint find node from dts \n"); switch_data->irq_node84 = of_find_compatible_node(NULL, NULL, "mediatek, gpio84-eint"); if(switch_data->irq_node84) switch_data->irq84 = irq_of_parse_and_map(switch_data->irq_node84, 0); #else switch_data->irq84 = gpio_to_irq(switch_data->gpio84); if (switch_data->irq84 < 0) { pr_err("%s: fail gpio_to_irq 84!\n", __FUNCTION__); ret = switch_data->irq84; goto err_detect_irq_num_failed; } #endif ret = request_irq(switch_data->irq84, gpio_irq_handler84, IRQF_TRIGGER_LOW |IRQF_ONESHOT, "gpio84_eint", switch_data); if (ret < 0) { pr_err("%s: fail request_irq 84!\n", __FUNCTION__); goto err_request_irq; } //irq_set_irq_type(switch_data->irq84, IRQF_TRIGGER_LOW |IRQF_ONESHOT); #endif //#ifndef USE_INTERRUPT // kthread_run(d1_reset_thread, NULL, "d1_reset_thread"); //#endif switch_set_state(&switch_data->sdev84, 1); //init state status pr_err("%s: ok\n", __FUNCTION__); return 0; err_request_irq: err_detect_irq_num_failed: err_set_gpio_input: gpio_free(switch_data->gpio84); //gpio_free(D1_RST_PIN); err_request_gpio: switch_dev_unregister(&switch_data->sdev84); err_switch_dev_register: kfree(switch_data); pr_err("%s: fail, ret=%d\n", __FUNCTION__, ret); return ret; } static int md_gpio_eint_remove(struct platform_device *pdev) { struct md_gpio_eint_data *switch_data = platform_get_drvdata(pdev); //cancel_work_sync(&switch_data->work84); gpio_free(switch_data->gpio84); switch_dev_unregister(&switch_data->sdev84); kfree(switch_data); return 0; } static const struct of_device_id md_gpio_eint_ids[] = { {.compatible = "mediatek,md_gpio_eint",}, {}, }; static struct platform_driver md_gpio_eint_driver = { .probe = md_gpio_eint_probe, .remove = md_gpio_eint_remove, .driver = { .name = "md-gpio-eint", .owner = THIS_MODULE, #ifdef CONFIG_OF .of_match_table = md_gpio_eint_ids, #endif }, }; static int __init md_gpio_eint_init(void) { pr_err("%s: start!\n", __FUNCTION__); return platform_driver_register(&md_gpio_eint_driver); } static void __exit md_gpio_eint_exit(void) { platform_driver_unregister(&md_gpio_eint_driver); } module_init(md_gpio_eint_init); module_exit(md_gpio_eint_exit); MODULE_AUTHOR("deli.sun "); MODULE_DESCRIPTION("md gpio eint driver"); MODULE_LICENSE("GPL");

上述三种方法,第一种和第二种方法使用时一般流程就是open、read/write、ioctl等,第三种方法则可以通过echo/cat命令来读写。另外以上方法具体实现时可以在kernel目录下grep相关关键字,看看手中原代码是如何实现的,必须能搜到大量的使用例程的。



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3