我正在尝试在 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 结构中定义额外的 ioctls,因为如果使用某个配置,它们可能会调用未定义的函数。有没有办法在其他地方定义它们并在这种情况下处理它们?
谢谢! (我对此有些陌生,我想我了解基础知识,但我可能会忽略一些东西。)
最佳答案
一种可能的方法(粗鲁,更干净的解决方案见下文)是通过在调用特定于 drm 的设备分配器(例如 drm_dev_alloc
)之前立即合并两个不同的表来构建一个 ioctl 表。这两个表来自不同的驱动程序部分并包含不同的服务子集。可选部分可能依赖编译器宏来创建表的完整版本或“ stub ”(空)版本。这是一个非常棘手的解决方案,而且肯定容易出错。基本上,鉴于这两个表,您必须
1) 将每个表导出为“外部”(或者至少是“可选”表)。我们称它们为 t1
和 t2
。注意:出于我们的目的,这些表不能定义为 const
。
2) 还导出两个 size_t 变量,其中包含两个表的“sizeof
”(比方说 s1
和 s2
): size_t s1 = sizeof(t1)
和 size_t s2 = sizeof(t2)
)
3) 在驱动程序初始化之前,确定两个表中最大的一个并将其指针分配给 struct drm_driver
的 ioctls
字段。该表将成为合并的“目标”。当然,struct drm_driver
也必须是非const
。
您还必须相应地调整 num_ioctls
字段。
4) 通过复制具有非 NULL func
字段的每个元素来合并目标中的第二个表。要测试的元素数量是 sX/sizeof(struct drm_ioctl_descr)
,其中 sX 是第二个表的大小(即 s1
如果目标是 t2
和 s2
如果目标是 t1
)。
5) 现在您可以照常注册驱动程序了。
好的,现在是一个更干净和“标准”的解决方案:
在“简化”版本中,将所有可选的 ioctls 实现为始终返回 -EINVAL
或 -EOPNOTSUPP
的函数。唯一的缺点是,在您的表中,您始终必须提供所有服务(即使是尚未实现的服务)。
关于c - 如何转发/多路复用 ioctl 组?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21466524/