如何转发/复用ioctls组?

时间:2014-01-30 20:10:49

标签: c linux kernel ioctl

我试图在drm内核中添加自己的ioctl。我已经有了以下内容:

static struct drm_driver my_driver = {
//stuff
.ioctls = my_ioctls,
};

然后从那里我有:

struct drm_ioctl_desc my_ioctls[] = {
// other stuff
DRM_IOCTL_DEF_DRV(MYIOCTL1, myfuncptr, myflags),
DRM_IOCTL_DEF_DRV(MYIOCTL2, myfuncptr2, myflags),
DRM_IOCTL_DEF_DRV(MYIOCTL3, myfuncptr3, myflags),
DRM_IOCTL_DEF_DRV(MYIOCTL4, myfuncptr4, myflags),
}

但是我如何复用一组ioctl并将它们处理在另一个可能编译或不编译的文件/子文件夹中?

即。我不想在my_ioctls结构中定义其他ioctl,因为如果使用某个配置,它们可能会调用未定义的函数。有没有办法在其他地方定义它们并在那种情况下处理它们?

谢谢! (我对其中一些有点新鲜,我认为我理解基础知识,但我可能会忽略一些东西。)

1 个答案:

答案 0 :(得分:0)

一种可能的方法(粗鲁,对于更清洁的解决方案,见下文)是通过在调用特定于drm的设备分配器(例如drm_dev_alloc)之前立即合并两个不同的表来构建ioctl表。这两个表来自不同的驱动程序部分,包含不同的服务子集。可选部分可能依赖于编译器宏来创建表的完整版本或“存根”(空)版本。这是一个非常棘手的解决方案,并且肯定容易出错。基本上,给定两个表,你必须

1)将每个表导出为“extern”(或者至少是“可选”表)。我们称他们为t1t2。注意:出于我们的目的,无法定义表格const

2)还导出两个包含两个表“sizeof”的size_t变量(假设为s1s2size_t s1 = sizeof(t1)size_t s2 = sizeof(t2)

3)在驱动程序初始化之前,确定两个表中最大的一个,并将其指针指向ioctls的{​​{1}}字段。该表将是您合并的“目标”。当然,struct drm_driver也必须是非struct drm_driver。 此外,您还必须相应地调整const字段。

4)通过复制具有非NULL num_ioctls字段的每个元素来合并目标中的第二个表。要测试的元素数量为func,其中sX是第二个表的大小(如果目标是sX/sizeof(struct drm_ioctl_descr),则为s1;如果目标为{t2,则为s2 {1}})。

5)现在你可以像往常一样注册驱动程序。

好的,现在是一个更干净,更“标准”的解决方案

在“简化”版本中,将所有可选ioctl作为函数始终返回t1-EINVAL。唯一的缺点是,在您的表中,您始终必须提供所有服务(即使尚未实现的服务)。