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); }
2021年9月16日 17:49 1F
认真看到,感谢分享!