Transfer large data using IOUserClient AsyncCompletion

I'm trying to make an asynchronous bulk data read using IOUSBHostPipe AsyncIO/CompleteAsyncIO and send the data back to the user-space application using AsyncCompletion.

virtual void AsyncCompletion(OSAction *action, IOReturn status, const IOUserClientAsyncArgumentsArray asyncData, uint32_t asyncDataCount);

My understanding is that the IOUserClientAsyncArgumentsArray asyncData in AsyncCompletion method has a limited size of 128 bytes, and the data I need to send back is over 10k bytes.

Would it be possible to send such large data from the driver to the user-space application using async callback?

Thanks

Answered by DTS Engineer in 793294022

My understanding is that the IOUserClientAsyncArgumentsArray asyncData in AsyncCompletion method has a limited size of 128 bytes, and the data I need to send back is over 10k bytes.

The limitation here is driven by general efficiency, not any technical limitation. For very small transfers it's faster to copy each byte between the kernel and user space but as the transfer size grows that becomes cumbersome and the VM system should be used instead.

How exactly you do that depends on what you want to do. Two approaches:

-IOConnectMapMemory64 in IOKitLib is the corresponds to IOUserClient.CopyClientMemoryForType. Depending on how the memory descriptor is configured, that can then be used to share memory in any way that you choose.

-You can do larger transfer through the UserClient by passing memory descriptor's through the interface. This is shown in "Communicating between a DriverKit extension and a client app", though it's easy to overlook. In the sample, look for "structureOutputDescriptor" in the function "NullDriverUserClient::HandleExternalStruct".

__
Kevin Elliott
DTS Engineer, CoreOS/Hardware

Accepted Answer

My understanding is that the IOUserClientAsyncArgumentsArray asyncData in AsyncCompletion method has a limited size of 128 bytes, and the data I need to send back is over 10k bytes.

The limitation here is driven by general efficiency, not any technical limitation. For very small transfers it's faster to copy each byte between the kernel and user space but as the transfer size grows that becomes cumbersome and the VM system should be used instead.

How exactly you do that depends on what you want to do. Two approaches:

-IOConnectMapMemory64 in IOKitLib is the corresponds to IOUserClient.CopyClientMemoryForType. Depending on how the memory descriptor is configured, that can then be used to share memory in any way that you choose.

-You can do larger transfer through the UserClient by passing memory descriptor's through the interface. This is shown in "Communicating between a DriverKit extension and a client app", though it's easy to overlook. In the sample, look for "structureOutputDescriptor" in the function "NullDriverUserClient::HandleExternalStruct".

__
Kevin Elliott
DTS Engineer, CoreOS/Hardware

Transfer large data using IOUserClient AsyncCompletion
 
 
Q