A possible way (rude, for a more clean solution see below) is building an ioctl table by merging two different tables immediately before calling the drm-specific device allocator (e.g. drm_dev_alloc
). The two tables come from different driver's parts and contain different subset of services. The optional part may depend on a compiler macro to create a complete version or a "stub" (empty) version of the table. It's a quite tricky solution, and for sure error-prone. Basically, given the two tables, you have to
1) export each table as "extern" (or, at least, the "optional" one). Let's call them t1
and t2
. Note: for our purposes the tables can NOT be defined const
.
2) also export two size_t variables containing the two tables' "sizeof
"s (let's say s1
and s2
: size_t s1 = sizeof(t1)
and size_t s2 = sizeof(t2)
)
3) immediately before the driver's initialization, identify the biggest of the two tables ad assign its pointer to the ioctls
field of your struct drm_driver
. The table will be the "target" of your merge. Of course, the struct drm_driver
must also be non-const
.
Also you have to adjust the num_ioctls
field accordingly.
4) Merge the second table in the target by copying each element that have a non-NULL func
field. The number of elements to be tested is sX/sizeof(struct drm_ioctl_descr)
, where sX is the size of the second table (i.e. s1
if the target is t2
and s2
if the target is t1
).
5) Now you can register the driver as usual.
Ok, now a more clean and "standard" solution:
In the "reduced" version implement all your optional ioctls as functions always returning -EINVAL
or -EOPNOTSUPP
. The only disadvantage is that in your table you always must provide all the services (even the not yet implemented ones).