SylixOS字符设备驱动开发(七)

gewenbin
gewenbin
gewenbin
188
文章
15
评论
2020年12月17日22:47:12 1 1,466

SylixOS驱动创建多个设备文件

在前面几节教程中我们在驱动中是直接定义一个设备实例的全局变量,但是实际项目中我们有时候需要定义自己的数据结构,用来将一些私有数据保存在其中,这时就可以按如下方式定义数据结构:

typedef struct _demo_dev {
    LW_DEV_HDR dev;
    void *priv;
} demo_dev_t;

这里将LW_DEV_HDR 设备实例作为第一个成员,后面我们会看到这样做带来的好处。

另外在实际项目中,有时候我们需要创建多个同类型的设备而使用同一个驱动。比如摄像头设备一般名为“/dev/video”,如果系统中有两个摄像头,我们希望创建两个设备文件分别为“/dev/video0”和“/dev/video1”,那么这种情况下驱动层该如何处理?

首先我们用上面的自定义数据结构定义一个有2个元素的数组:

demo_dev_t demo_dev[2];

然后创建设备文件的时候我们使用iosDevAdd 接口创建两个设备文件:

ret = iosDevAdd(&demo_dev[0].dev, "/dev/demo0", drv_index);
if (ret != ERROR_NONE) {
    printk("device add fail.\r\n");
    iosDrvRemove(drv_index, TRUE);
    return -1;
}

ret = iosDevAdd(&demo_dev[1].dev, "/dev/demo1", drv_index);
if (ret != ERROR_NONE) {
    printk("device1 add fail.\r\n");
    iosDevDelete(&demo_dev[0].dev);
    iosDrvRemove(drv_index, TRUE);
    return -1;
}

同样驱动卸载的时候我们需要删除这两个设备文件:

iosDevDelete(&demo_dev[0].dev);
iosDevDelete(&demo_dev[1].dev);

其次open函数原来返回的是设备实例变量的地址,现在要改成返回自定义数据的地址,由于我们是将设备实例变量放在自定义数据第一个成员,所以这两个地址值是一样的,这样我们直接将open函数的第一个参数转换成自定义数据类型指针即可:

static long demo_open(LW_DEV_HDR *dev, char *name, int flag, int mode)
{
    demo_dev_t *device = (demo_dev_t *)dev;
    device->priv = NULL;

    printk("%s %s.\r\n", __func__, name);

    if ((flag & O_ACCMODE) == O_RDONLY) {
        printk("open read only.\r\n");
    } else if ((flag & O_ACCMODE) == O_WRONLY) {
        printk("open write only.\r\n");
    } else {
        printk("open read/write.\r\n");
    }

    printk("file permission: %o.\r\n", mode);

    LW_DEV_INC_USE_COUNT(&device->dev);

    return (long)device;
}

如果自定义数据结构第一个成员不是LW_DEV_HDR 设备实例的话,就需要通过类似linux下的container_of  这类辅助宏获得自定义数据结构首地址。

注册驱动后,通过devs 查看驱动信息:

[root@sylixos:/root]# devs
device show (minor device) >>
drv dev open name
 37   1    0 /dev/demo1
 37   0    0 /dev/demo0
 36   1    0 /dev/input/xmse
 36   0    0 /dev/input/xkbd
 35   0    0 /dev/netbd
 34   0    0 /dev/netbr
 33   0    0 /dev/net/vnd
 32   0    0 /dev/socket
 31   0    0 /dev/netevent
 24   0    0 /ram
 29   0    1 /dev/input/touch0
 30   0    0 /dev/fb0
 23   0    0 /media/sdcard0
 10   0    0 /dev/blk/sdcard-0
 27   0    0 /yaffs2
 18   0    1 /dev/ttyS0
 15   1    0 /dev/urandom
 15   0    0 /dev/random
 14   0    0 /dev/shm
 13   0    0 /proc
 12   0    1 /dev/hotplug
 11   0    0 /dev/epollfd
  9   0    0 /dev/gpiofd
  8   0    0 /dev/signalfd
  7   0    0 /dev/hstimerfd
  6   0    0 /dev/timerfd
  5   0    0 /dev/semfd
  4   0    0 /dev/bmsg
  3   0    0 /dev/eventfd
  1   0    0 /dev/zero
  0   0    0 /dev/null
  2   0    0 /
[root@sylixos:/root]#

可以看到37号驱动下有两个设备文件。

附源码

driver_demo7源码:

#define  __SYLIXOS_KERNEL
#include <SylixOS.h>
#include <module.h>

typedef struct _demo_dev {
    LW_DEV_HDR dev;
    void *priv;
} demo_dev_t;

int drv_index;
demo_dev_t demo_dev[2];

static long demo_open(LW_DEV_HDR *dev, char *name, int flag, int mode)
{
    demo_dev_t *device = (demo_dev_t *)dev;
    device->priv = NULL;

    printk("%s %s.\r\n", __func__, name);

    if ((flag & O_ACCMODE) == O_RDONLY) {
        printk("open read only.\r\n");
    } else if ((flag & O_ACCMODE) == O_WRONLY) {
        printk("open write only.\r\n");
    } else {
        printk("open read/write.\r\n");
    }

    printk("file permission: %o.\r\n", mode);

    LW_DEV_INC_USE_COUNT(&device->dev);

    return (long)device;
}

static int demo_close(demo_dev_t *dev)
{
    printk("%s.\r\n", __func__);

    LW_DEV_DEC_USE_COUNT(&dev->dev);

    return ERROR_NONE;
}

static struct file_operations demo_fops = {
    .owner    = THIS_MODULE,
    .fo_open  = demo_open,
    .fo_close = demo_close,
};

int module_init (void)
{
    int ret = 0;

    drv_index = iosDrvInstallEx(&demo_fops);
    if (drv_index < 0) {
        printk("driver install fail.\r\n");
        return -1;
    }

    DRIVER_LICENSE(drv_index, "GPL->Ver 2.0");
    DRIVER_AUTHOR(drv_index, "GeWenBin");
    DRIVER_DESCRIPTION(drv_index, "demo driver.");

    ret = iosDevAdd(&demo_dev[0].dev, "/dev/demo0", drv_index);
    if (ret != ERROR_NONE) {
        printk("device add fail.\r\n");
        iosDrvRemove(drv_index, TRUE);
        return -1;
    }

    ret = iosDevAdd(&demo_dev[1].dev, "/dev/demo1", drv_index);
    if (ret != ERROR_NONE) {
        printk("device1 add fail.\r\n");
        iosDevDelete(&demo_dev[0].dev);
        iosDrvRemove(drv_index, TRUE);
        return -1;
    }

    return 0;
}

void module_exit (void)
{
    iosDevDelete(&demo_dev[0].dev);
    iosDevDelete(&demo_dev[1].dev);
    iosDrvRemove(drv_index, TRUE);
}

 

gewenbin
  • 本文由 发表于 2020年12月17日22:47:12
  • 转载请务必保留本文链接:http://www.databusworld.cn/8945.html
匿名

发表评论

匿名网友 填写信息

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

评论:1   其中:访客  1   博主  0
    • liqingquan liqingquan 3

      认真看到,感谢分享!