KEXT to DEXT:Unable to getInterface of my IOUSBHostDevice

Hi all ,
I have been trying to communicate with my device in my Big Sur, I am able to open IOUSBHostDevice in start function , But not getting Interface(IOUSBHostInterface),
IOUSBHostDevice ::CreateInterfaceIterator();
is returning Null value, Unable to use getchildIterator().

Any Help is appreciated
Answered by in 667784022
Interfaces are created when the device is configured. If you're matching on an IOUSBHostDevice you'll likely need to configure the device from your driver which will, in turn, create the interfaces. If you only require working with interfaces and you have a composite device (class/sub-class = 0) or interface association device (class = 239, sub-class = 2, protocol = 1) consider matching on the IOUSBHostInterface instead and allowing the Apple provided (AppleUSBHostCompositeDevice) driver to configure the device.
Are your interfaces visible in the IORegistry?
What error code does CreateInterfaceIterator() return?
Does your device have a set configuration? It won't have any interfaces unless you set a configuration.
Accepted Answer
Interfaces are created when the device is configured. If you're matching on an IOUSBHostDevice you'll likely need to configure the device from your driver which will, in turn, create the interfaces. If you only require working with interfaces and you have a composite device (class/sub-class = 0) or interface association device (class = 239, sub-class = 2, protocol = 1) consider matching on the IOUSBHostInterface instead and allowing the Apple provided (AppleUSBHostCompositeDevice) driver to configure the device.
thank you for your replies ,

Now i am able to get the interface, But stumbled on another issue, I am inheriting IOUserSerial and overriding "TxDataAvailable()" and RxDataAvailable(), I am getting control in TxAvailable, Not getting how to read data from here , tried overriding connectQueues(), which is leading to error "ERROR occurred while attempting to open port,, 100:Access denied"
In "CoolTerm" Application On "Connect" Button Click

In log stream I can see as below 
IOUserSerial::<private>: ConnectQueues 0x6000028f4058
IOUserSerial::<private>:DisconnectQueues 0x6000028f4058

getting very similar Error when i just Inherit ioUserUSBSerial
"ERROR occurred while attempting to open port,, 100:Access denied"
In "CoolTerm" Application On "Connect" Button Click

In log stream I can see as below 
IOUserSerial::<private>: 522 0x6000028f4058
IOUserSerial::<private>:523 0x6000028f4058
IOUserSerial::<private>:110 0x6000028f4058


Please help me with this,

If you are using USBDriverKit and trying to communicate with a serial device, you should stick to IOUserUSBSerial and use USBSerialDriverKit. The error you are seeing looks like an application error with CoolTerm. Is there any error in your dext? Is it successfully sending data? If you are overriding ConnectQueues, are you successfully creating the buffers to be used in communication with the serial device? Do TxDataAvailable and RxDataAvailable transmit and receive without error?
Using IOUserUSBSerial we got the serial node as /dev/cu.serial-100068x(update). is the node enumeration is correct or it should be cu.usbserial?

And when opening the node from any application (coolterm and Screen commandline tool) Access denied error is seen
we feel that IO calls from IOUserSerial is returning error for some reason, how to debug this
Hi  Drewbadour
As your suggestion i am using IOUserUSBSerial , i am not overriding Connectqueues, DisconnectQueues,(According to apple document "At activation time, IOUserUSBSerial object automatically creates memory buffers for managing data moving to and from the USB device") TxAvailable, RxAvailable, (Since TxAvailable and TxAvailable are Final functions)

Here are some logs i am able to see when i try to connect in application(coolterm or Screen commandline tool)

.615828+0530 0x216d Activity 0x57a7 731 0 CoolTerm: (AppKit) sendActionFrom:
.616360+0530 0x216d Default 0x0 0 0 kernel: (IOUserSerial) IOUserSerial::call0(allocResources) ==>
.616376+0530 0x216d Default 0x0 0 0 kernel: (IOUserSerial) IOUserSerial::call0() locklevel = 1
.616481+0530 0x1fcb Default 0x0 0 0 kernel: (sc.knight.MyUserUSBInterfaceDriver.dext) IOUserSerial::<private>: 522 0x6000034bc058
.616517+0530 0x216d Default 0x0 0 0 kernel: (IOUserSerial) IOUserSerial::call0() <== e00002c7
.616524+0530 0x216d Default 0x0 0 0 kernel: (IOUserSerial) IOUserSerial::call0(freeResources) ==>
.616528+0530 0x216d Default 0x0 0 0 kernel: (IOUserSerial) IOUserSerial::call0() locklevel = 1
.616599+0530 0x1fcb Default 0x0 0 0 kernel: (sc.knight.MyUserUSBInterfaceDriver.dext) IOUserSerial::<private>: 533 0x6000034bc058
.616606+0530 0x1fcb Default 0x0 0 0 kernel: (sc.knight.MyUserUSBInterfaceDriver.dext) IOUserSerial::<private>: 110 0x6000034bc058
.616633+0530 0x216d Default 0x0 0 0 kernel: (IOUserSerial) IOUserSerial::call0() <== e00002c7
Since the function names in your logs are getting redacted, what methods are being called here? And what do these printouts afterwards mean? These logs from "sc.knight.MyUserUSBInterfaceDriver.dext" look like they are from your dext, but I have no idea what they mean, or what part of your dext is getting called. Have you overridden methods like "HwProgramBaudRate" to properly configure your device? Are those methods succeeding? Are they being called? It looks like there's one particular method that is being called in your dext that may be failing to transmit data.
Hi ,

From our dext hwactivate itself not getting called, We suspect after ConnectQueues() we getting some unknown function error. DisconnectQueue is being called just after Connectqueues().
I have overridden HwProgramBaudRate(), But Controll not reaching till that point.
You've previously said that you're not overriding ConnectQueues. And now you're saying that HwActivate is not getting called. So I assume your dext is having its Start method called. So this means that you're calling ConnectQueues from Start, correct? What does ConnectQueues return? Does it not return and instead call DisconnectQueue? If it does return successfully, are you calling RegisterService in your Start implementation? If you don't call ConnectQueues at all, does your dext start and run a normal lifecycle?
Hi Drewbadour,
Parallelly I am trying both ways of inheriting IOUserUSBSerial and IOUserSerial

Below is my sequence with IOUserSerial class,
In start function I have "
opened device
SetConfiguration
registerService
Opened Interface
copyPipe
ConnectQueues
pipe->IO() ,
  • -- IO function returning device "2d8: not ready Error".

I have also tried pipe->IO in Tx Available() function ,
  • -- IO function returning device "2d8: not ready Error".

As suggested by you I have inherited "HwProgramBaudRate" and setting baud rate and etc , which is successfull,

All function calls returning Success exept IO function

any help is appriciated,
It's likely the reason you are seeing "not ready" errors is because your device hasn't been set up yet. If you need to send data to initialize your device, you should probably override HwActivate and do it there. Generally, wouldn't these be provider->DeviceRequest messages though? And if your device is a USB device, you should stick to IOUserUSBSerial and report what you see there.
Drewbadour, Happy to see your reply ,

please give me some light on my doubt please
with IOUserUSBSerial ,
  • -- i am able to read Firmware versions using device request ,(in start function)
  • On Clicking Connect in USB application(coolterm/screen)" Permission denied " error is coming,

  • i see after UserSerial::connectqueue() , Disconnect sequence is initiated,

  • How Tx and Rx data is managed ?

with IOUserSerial ,
I am able to get TxAvalable function
trying to write tx value to device using
pip->IO(),-->Success but not recieving RxAvailable Function
  • can u give me correct sequence of RxAvailable,TxAvailable, RxfreeSpaceAvailable,TxFreeSpaceAvailable,

which function to override which to call ,
where to read the data from and write data to ,


can u give me correct sequence of RxAvailable,TxAvailable, RxfreeSpaceAvailable,TxFreeSpaceAvailable
which function to override which to call , 
where to read the data from and write data to ,

You should be using IOUserUSBSerial. Like I've said, and I'm going to keep saying, if you are connecting to a USB device, you should be using IOUserUSBSerial. The results you are seeing with IOUserSerial are misleading and are going to continue to confuse you if what you are connecting to is a standard USB serial device.

  • - i am able to read Firmware versions using device request ,(in start function)

Good. That means you've correctly matched to your device. That's a good first step.

On Clicking Connect in USB application(coolterm/screen)" Permission denied " error is coming,

That's because your driver doesn't work. It doesn't tell us anything helpful.

i see after UserSerial::connectqueue() , Disconnect sequence is initiated,

What does your USB serial device look like? Does it have a bulk in and bulk out pipe? If so, ConnectQueues should automatically set up your device. In fact, if you do, the correct way to implement this device would likely be to make a dext that matches to the IOUSBHostDevice, sets a configuration to expose the interface (as the original question was answered) and allow the generic Apple serial driver to handle this device. If you still want to write a driver, all you should need to have a working driver on a device that has bulk in and out pipes is a Start implementation that looks like this:
Code Block C++
IMPL(MyDriver, Start)
{
kern_return_t status = Start(SUPERDISPATCH);
if (status != kIOReturnSuccess)
{
return status;
}
return RegisterService();
}

No other code is required. If your device is different in some way, you will need to refer to the documentation of IOUserUSBSerial and override each part as you see need.

If your device doesn't have just these two pipes, then things get significantly more complicated. What does your interface look like? How many pipes does it have? What types of pipes? Etc.

Hi Drewbadour,
Thank you for such detailed explanation, I will focus on IOUserUSBserial as my device is USB,My device has bulk in and out pipes, it's working fine in windows.

I will reply more about my device soon, as for now I want to ask you is there any quicker way to contact you over mail or any other way would be help full.
My mail id is : revancse2@gmail.com
Hi Drewbadour,

We are inheriting "IOUserUSBSerial" and using IOUSBHostDevice as a provider class to match our device, In start function we are getting the device, able to configure the device. below is the Start function
Code Block
kern_return_t
IMPL(MyUserUSBInterfaceDriver, Start){
    kern_return_t                    ret;
    ivars->ioDevice = OSDynamicCast(IOUSBHostDevice, provider);
    ret = ivars->ioDevice->Open(this, 0, NULL);
    ivars->ioDevice->SetConfiguration(2, false);
/* code logic to open the interface and device request is successful, Able to communicate with device Firmware*/
    ret = Start(provider, SUPERDISPATCH);
    return  RegisterService();
}

After DEXT is loaded IOReg is as attached

In Cool Term Or any Serial application when we try to open the serial node its giving
"An Error Occured while attempting to open the port,
100:Access denied"

And I can see the below logs -- e00002c7 ="unsupported function"
Code Block
kernel: (IOUserSerial) IOUserSerial::call0(allocResources) ==>
kernel: (IOUserSerial) IOUserSerial::call0() locklevel = 1
kernel: (sc.knight.MyUserUSBInterfaceDriver.dext) IOUserSerial::<private>: 522 0x600002984058
kernel: (IOUserSerial) IOUserSerial::call0() <== e00002c7
kernel: (IOUserSerial) IOUserSerial::call0(freeResources) ==>
kernel: (IOUserSerial) IOUserSerial::call0() locklevel = 1
kernel: (sc.knight.MyUserUSBInterfaceDriver.dext) IOUserSerial::<private>: 533 0x600002984058
kernel: (sc.knight.MyUserUSBInterfaceDriver.dext) IOUserSerial::<private>: 110 0x600002984058
kernel: (IOUserSerial) IOUserSerial::call0() <== e00002c7

Our Device has Bulk in and out pipes, Connectqueues function is not automatically setting up, Please let us know how we can debug this

On Another method we have tried is Adding "AppleUSBHostCompositeDevice" as provider, We got the interface But IOHostInterface is not loading to match (init() and start() are not called)
KEXT to DEXT:Unable to getInterface of my IOUSBHostDevice
 
 
Q