On Wed, Oct 2, 2024, at 12:58, Alice Ryhl wrote: > On Wed, Oct 2, 2024 at 2:48 PM Arnd Bergmann <arnd@xxxxxxxx> wrote: > A quick sketch. > > One option is to do something along these lines: This does seem promising, at least if I read your sketch correctly. I'd probably need a more concrete example to understand better how this would be used in a driver. > struct IoctlParams { > pub cmd: u32, > pub arg: usize, > } > > impl IoctlParams { > fn user_slice(&self) -> IoctlUser { > let userslice = UserSlice::new(self.arg, _IOC_SIZE(self.cmd)); > match _IOC_DIR(self.cmd) { > _IOC_READ => IoctlParams::Read(userslice.reader()), > _IOC_WRITE => IoctlParams::Write(userslice.writer()), > _IOC_READ|_IOC_WRITE => IoctlParams::WriteRead(userslice), > _ => unreachable!(), Does the unreachable() here mean that something bad happens if userspace passes something other than one of the three, or are the 'cmd' values here in-kernel constants that are always valid? > enum IoctlUser { > Read(UserSliceReader), > Write(UserSliceWriter), > WriteRead(UserSlice), > } > > Then ioctl implementations can use a match statement like this: > > match ioc_params.user_slice() { > IoctlUser::Read(slice) => {}, > IoctlUser::Write(slice) => {}, > IoctlUser::WriteRead(slice) => {}, > } > > Where each branch of the match handles that case. This is where I fail to see how that would fit in. If there is a match statement in a driver, I would assume that it would always match on the entire cmd code, but never have a command that could with more than one _IOC_DIR type. Arnd