OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 4879|回复: 10

设置私有数据的作用!!!!

[复制链接]

57

主题

90

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
279
金钱
279
注册时间
2019-11-13
在线时间
40 小时
发表于 2020-3-30 13:19:45 | 显示全部楼层 |阅读模式
设置私有的数据的作用是什么啊?这里定义了一个全局变量的结构体 newchrled,我可以在整个驱动直接使用 newchrled 就行了啊!这里设置私有数据也是将 newchrled 结构体的地址指向 dev 位置,即 dev 等于 newchrled!!
Image [2].png

正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

13

主题

109

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
351
金钱
351
注册时间
2016-4-20
在线时间
162 小时
发表于 2020-3-30 14:02:53 来自手机 | 显示全部楼层
如果你想多个设备用同一个驱动,就会发现驱动私有数据的好处了
回复 支持 1 反对 0

使用道具 举报

13

主题

109

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
351
金钱
351
注册时间
2016-4-20
在线时间
162 小时
发表于 2020-3-30 14:06:08 来自手机 | 显示全部楼层
比如,有三个led灯的设备,不用写三套驱动,也不用在每个操作函数里面做判断。而是使用私有数据,即内个设备都有自己的私有数据,操作这个私有数据就行。这样同一个驱动,支持了多个设备。
回复 支持 反对

使用道具 举报

57

主题

90

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
279
金钱
279
注册时间
2019-11-13
在线时间
40 小时
 楼主| 发表于 2020-3-30 14:29:09 | 显示全部楼层
hannuaa 发表于 2020-3-30 14:06
比如,有三个led灯的设备,不用写三套驱动,也不用在每个操作函数里面做判断。而是使用私有数据,即内个设 ...

好的,谢谢!
回复 支持 反对

使用道具 举报

57

主题

90

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
279
金钱
279
注册时间
2019-11-13
在线时间
40 小时
 楼主| 发表于 2020-3-30 14:42:12 | 显示全部楼层
hannuaa 发表于 2020-3-30 14:06
比如,有三个led灯的设备,不用写三套驱动,也不用在每个操作函数里面做判断。而是使用私有数据,即内个设 ...

这里定义了 struct  newchrled_dev *dev = filp->private_data ,意思是我可以通过 dev->xxx来修改结构体成员的值,但是它不影响原来的 newchrled->xxx 的值??
回复 支持 反对

使用道具 举报

2

主题

712

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
2178
金钱
2178
注册时间
2018-8-27
在线时间
258 小时
发表于 2020-3-30 15:33:51 | 显示全部楼层
uestczcl 发表于 2020-3-30 14:42
这里定义了 struct  newchrled_dev *dev = filp->private_data ,意思是我可以通过 dev->xxx来修改结构体 ...

怎么可能不影响,肯定会修改newchrled->xxx的值啊
森罗万象
回复 支持 反对

使用道具 举报

13

主题

109

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
351
金钱
351
注册时间
2016-4-20
在线时间
162 小时
发表于 2020-3-30 17:02:20 来自手机 | 显示全部楼层
uestczcl 发表于 2020-3-30 14:42
这里定义了 struct  newchrled_dev *dev = filp->private_data ,意思是我可以通过 dev->xxx来修改结构体 ...

晚上回去,我给您发一个样板,供您参考!写的不完善,错误处理,参数检查这些都没做。仅供讨论。
回复 支持 反对

使用道具 举报

13

主题

109

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
351
金钱
351
注册时间
2016-4-20
在线时间
162 小时
发表于 2020-3-30 18:34:54 | 显示全部楼层
uestczcl 发表于 2020-3-30 14:42
这里定义了 struct  newchrled_dev *dev = filp->private_data ,意思是我可以通过 dev->xxx来修改结构体 ...

#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/fs.h>
#include <linux/device.h>
#include <linux/cdev.h>
#include <linux/slab.h>
#include <linux/uaccess.h>
#include <linux/of.h>
#include <linux/mutex.h>

#include <linux/of_gpio.h>

#define LED_DEVS_NUM 3
#define LED_DEV_NAME "led"

typedef struct
{
    dev_t devid;
    struct cdev cdev;
    struct class *class;
    struct device *dev;
    struct device_node *node;
    int gpio;
    unsigned char value;
    struct mutex lock;
} led_dev_t;

static led_dev_t *led_dev;

static void led_off(led_dev_t *dev)
{
    if (gpio_direction_output(dev->gpio, 1))
    {
        printk("%s: gpio_direction_output fail!\r\n", __func__);
    }
}

static void led_on(led_dev_t *dev)
{
    if (gpio_direction_output(dev->gpio, 0))
    {
        printk("%s: gpio_direction_output fail!\r\n", __func__);
    }
}

static int led_open(struct inode *inode, struct file *file)
{
    led_dev_t *dev = container_of(inode->i_cdev, led_dev_t, cdev);
    file->private_data = dev;
    return 0;
}

static int led_release(struct inode *inode, struct file *file)
{
    //led_dev_t *dev = file->private_data;
    //led_off(dev);
    return 0;
}

static ssize_t led_read(struct file *file, char __user *buf, size_t count, loff_t *ppos)
{
    led_dev_t *dev = file->private_data;

    mutex_lock(&dev->lock);
    if (copy_to_user(buf, &(dev->value), sizeof(unsigned char)))
    {
        return -EFAULT;
    }
    mutex_unlock(&dev->lock);

    return sizeof(unsigned char);
}

static ssize_t led_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos)
{
    led_dev_t *dev = file->private_data;

    mutex_lock(&dev->lock);
    if (copy_from_user(&(dev->value), buf, sizeof(unsigned char)))
    {
        return -EFAULT;
    }
    mutex_unlock(&dev->lock);

    switch (dev->value)
    {
    case 1:
        led_on(dev);
        break;
    case 0:
        led_off(dev);
        break;
    default:
        return -ENOTTY;
    }

    return sizeof(unsigned char);
}

static long led_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
    led_dev_t *dev = file->private_data;
    switch (cmd)
    {
    case 1:
        led_on(dev);
        break;
    case 0:
        led_off(dev);
        break;
    default:
        return -ENOTTY;
    }
    return 0;
}

static const struct file_operations led_fops = {
    .owner = THIS_MODULE,
    .open = led_open,
    .release = led_release,
    .read = led_read,
    .write = led_write,
    .unlocked_ioctl = led_ioctl,
};

static int __init led_init(void)
{
    int ret = 0;
    dev_t devid;
    int major;
    unsigned int i;
    char dev_name[20];

    //  为驱动数据分配内存
    led_dev = kmalloc(LED_DEVS_NUM * sizeof(led_dev_t), GFP_KERNEL);
    if (led_dev == NULL)
    {
        printk("%s: kmalloc fail!\r\n", __func__);
        return -EFAULT;
    }
    memset(led_dev, 0, LED_DEVS_NUM * sizeof(led_dev_t));

    //  申请自动分配的设备号
    ret = alloc_chrdev_region(&devid, 0, LED_DEVS_NUM, LED_DEV_NAME);
    if (ret)
    {
        printk("%s: alloc_chrdev_region fail!\r\n", __func__);
        return ret;
    }
    else
    {
        major = MAJOR(devid);
    }

    for (i = 0; i != LED_DEVS_NUM; ++i)
    {
        led_dev_t *dev = led_dev + i;

        //  设备ID
        dev->devid = MKDEV(major, i);

        //  初始化互斥体
        mutex_init(&dev->lock);

        //  添加字符设备并添加至内核
        dev->cdev.owner = led_fops.owner;
        cdev_init(&dev->cdev, &led_fops);
        ret = cdev_add(&dev->cdev, dev->devid, 1);
        if (ret)
        {
            printk("%s: cdev_add fail!\r\n", __func__);
            return -ret;
        }

        //  创建类
        sprintf(dev_name, "%s%d", LED_DEV_NAME, i);
        dev->class = class_create(THIS_MODULE, dev_name);
        if (IS_ERR(dev->class))
        {
            printk("%s: class_create fail!\r\n", __func__);
            return PTR_ERR(dev->class);
        }

        //  创建设备
        dev->dev = device_create(dev->class, NULL, dev->devid, NULL, dev_name);
        if (IS_ERR(dev->dev))
        {
            return PTR_ERR(dev->dev);
        }

        // 获取设备树节点
        dev->node = of_find_node_by_path("/led");
        if (dev->node == NULL)
        {
            printk("%s: of_find_node_by_path fail!\r\n", __func__);
            return -EFAULT;
        }

        //  获取GPIO属性
        dev->gpio = of_get_named_gpio(dev->node, "led-gpio", i);
        if (!gpio_is_valid(dev->gpio))
        {
            printk("%s: of_get_named_gpio fail!\r\n", __func__);
            return -ENODEV;
        }

        //  默认关闭LED
        led_off(dev);
    }

    printk("%s : sucess!\r\n", __func__);
    return 0;
}

static void __exit led_exit(void)
{
    unsigned int i;
    for (i = 0; i != LED_DEVS_NUM; ++i)
    {
        led_dev_t *dev = led_dev + i;

        led_off(dev);
        device_destroy(dev->class, dev->devid);
        class_destroy(dev->class);
        cdev_del(&dev->cdev);
        unregister_chrdev_region(dev->devid, 1);
    }

    kfree(led_dev);

    printk("%s : sucess!\r\n", __func__);
}

module_init(led_init);
module_exit(led_exit);

MODULE_DESCRIPTION("led driver");
MODULE_LICENSE("GPL");
MODULE_AUTHOR("hannuaa");


回复 支持 反对

使用道具 举报

13

主题

109

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
351
金钱
351
注册时间
2016-4-20
在线时间
162 小时
发表于 2020-3-30 18:35:52 | 显示全部楼层
uestczcl 发表于 2020-3-30 14:42
这里定义了 struct  newchrled_dev *dev = filp->private_data ,意思是我可以通过 dev->xxx来修改结构体 ...

不知道怎么挂.c的附件,直接给您贴出来了,做的不完善,私有数据的作用体现了,仅供参考!
回复 支持 反对

使用道具 举报

57

主题

90

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
279
金钱
279
注册时间
2019-11-13
在线时间
40 小时
 楼主| 发表于 2020-3-31 23:01:49 | 显示全部楼层
hannuaa 发表于 2020-3-30 18:35
不知道怎么挂.c的附件,直接给您贴出来了,做的不完善,私有数据的作用体现了,仅供参考!

谢谢您!
回复 支持 反对

使用道具 举报

13

主题

109

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
351
金钱
351
注册时间
2016-4-20
在线时间
162 小时
发表于 2020-4-1 17:14:50 来自手机 | 显示全部楼层
uestczcl 发表于 2020-3-31 23:01
谢谢您!

客气,多交流!
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2024-11-25 09:37

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表