Question

I'm trying to add my own ioctls in the drm kernel. I have the following already:

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

and then from there I have:

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),
}

But how would I multiplex a group of ioctl's and have them handled in another file/subfolder that may or may not be compiled in?

I.e. I don't want to define additional ioctls in the my_ioctls struct, because they might be calling functions that aren't defined if a certain config is used. Is there any way to define them somewhere else and handle them in that case?

Thanks! (I'm a bit new to some of this, and I think I understand the basics, but I might be overlooking something.)

Was it helpful?

Solution

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).

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top