IOCTL in MacOS drivers (DriverKit/DEXT)

Hi,

In Linux we have this driver structure where the handlers are defined as below:

static struct file_operations fops = { .owner = THIS_MODULE, .read = etx_read, .write = etx_write, .open = etx_open, .unlocked_ioctl = etx_ioctl, .release = etx_release, };

So when the user app calls open() with the appropriate file/device handle "etx_open" in the driver is acalled, etc. However, the Apple driver structure that is exposed to developers is different and it has changed drastically with the DriverKit architecture.

I have some custom requests from the user app where I need to call this ioctl() type requests on my serial port "tty.myusbserial1234". My driver is derived from IOUserUSBSerial and is working fine for all other practical purposes except for such custom requirements.

Has anyone encountered such a problem in MacOS DriverKit and what is the solution or an alternative?

https://developer.apple.com/documentation/driverkit/communicating-between-a-driverkit-extension-and-a-client-app This gives a different approach, but the serial ports are accessed via open/read/write/close system calls and tcsetattr and other termios functions to set baud-rate and such. So, the above approcah is not suitable for my purpose.

Any ideas/help is very much appreciated.

Thanks.

Has anyone encountered such a problem in MacOS DriverKit and what is the solution or an alternative?

You've actually already identified the solution, which is to use IOUserClient. There isn't really any alternative for sending custom commands to a DEXT.

This gives a different approach, but the serial ports are accessed via open/read/write/close system calls and tcsetattr and other termios functions to set baud-rate and such. So, the above approcah is not suitable for my purpose.

Why? I don't have an example at hand to confirm the details with, but it shouldn't be difficult to find the IOKit object that's publishing the BSD object you're opening, then "walk" back from that IOKit object to your own driver. At that point, you can open your own UserClient and do whatever you want. It's different than other Unix system and a bit more work, but I don't see any reason why it wouldn't work fine.

__
Kevin Elliott
DTS Engineer, CoreOS/Hardware

Hi Kevin,

I think I am not able to convey the issue properly. I am accessing the serial ports from the client/user application which is developed using C/C++. I am not using SwiftUI.

So I am using open/read/write/ioctl/close() system calls and accessing the the serial port handle specifying the TTY name of the port (such as open("/dev/cu.usbserial123", O_RDWR | O_NOCTTY | O_SYNC) ).

https://developer.apple.com/documentation/driverkit/communicating-between-a-driverkit-extension-and-a-client-app

The above sample does not work for me as I have to use tcsetattr() function to set the uart parameters after getting the handle to the serial port using open() system function and the IOUserSerial class of DriverKit supports this architecture.

If I have to use IOServiceOpen method then I have to get handles for two sets in the user/client app (one to the port using open() and another for custom calls using IOServiceOpen) which is not preferred or appropriate solution in our case.

I know this is quite an unusual request or complicated, but this is a necessary requirement for me.

Any suggestions/help is very much appreciated.

Thanks.

I think I am not able to convey the issue properly. I am accessing the serial ports from the client/user application which is developed using C/C++. I am not using SwiftUI. So I am using open/read/write/ioctl/close() system calls and accessing the serial port handle specifying the TTY name of the port (such as open("/dev/cu.usbserial123", O_RDWR | O_NOCTTY | O_SYNC) ).

Yes, that's basically what I expected you to be doing.

Moving to here:

The above sample does not work for me as I have to use tcsetattr() function to set the uart parameters after getting the handle to the serial port using open() system function and the IOUserSerial class of DriverKit supports this architecture.

I don't think you've understood what I'm saying here. The basic issue here is that the in-kernel driver that supports your DEXT already implements ioctl support and doesn't expose any of that support to your DEXT. There simply isn't any way for your DEXT to receive ioctl commands from a user space app, nor is there any other "side channel" within the BSD API set.

The only option that leaves open is to use IOKit and an IOUserClient to directly communicate with your DEXT, at which point you can send/do whatever you want.

If I have to use IOServiceOpen method then I have to get handles for two sets in the user/client app (one to the port using open() and another for custom calls using IOServiceOpen)

Yes, that is in fact what you'll need to do to make an IOUserClient work.

which is not a preferred or appropriate solution in our case.

OK. In that case, your only option is to file an enhancement request asking for us to add what you want to the system. If you post the bug number back here then I'll make sure it gets to the right team.

However, you should be aware that:

  1. This kind of feature work is generally only shipped in major system releases ("macOS 26") not system updates ("macOS 26.x").

  2. Given the choices that were already made in SerialDriverKit, I'm not confident that this functionality will ever be provided.

I know this is quite an unusual request or complicated, but this is a necessary requirement for me.

As I described above, the only option I can see here is IOUserClient.

__
Kevin Elliott
DTS Engineer, CoreOS/Hardware

IOCTL in MacOS drivers (DriverKit/DEXT)
 
 
Q