How to do async IO using IOUSBHostPipe?

We followed WWDC Session: System Extensions and DriverKit and recreated a code to do USB device communication via IOUSBHostPipe:

struct MyDriver_IVars {
    IOUSBHostInterface       *interface;
    IOUSBHostPipe            *inPipe;
    OSAction                 *ioCompleteCallback;
    IOBufferMemoryDescriptor *inData;
    uint16_t                  maxPacketSize;
};

kern_return_t
IMPL(MyDriver, Start)
{
...
    ivars->maxPacketSize = 64;
    ret = ivars->interface->CreateIOBuffer(
                                          kIOMemoryDirectionInOut,
                                           ivars->maxPacketSize,
                                           &ivars->inData);

    ret = CreateActionReadComplete(0, &ivars->ioCompleteCallback);

    ret = ivars->inPipe->AsyncIO(ivars->inData,
                                 ivars->maxPacketSize,
                                 ivars->ioCompleteCallback,
                                 0);
...
}

Our Driver is started by OS when device is connected. We see that ReadComplete callback is called:

void IMPL(MyDriver, ReadComplete)
{
      Log("ReadComplete() - status - %d; bytes count - %d", status, actualByteCount);
}

However it's not obvious how to read data received in this callback. I suspect that we should use IOBufferMemoryDescriptor *inData but we didn't find any good example/sample and documentation is poor.

Our callback is called only once. It's not clear how to read a series of data from device? Should we create some loop and call inPipe->AsyncIO from callback?

Also it would be helpful to see how to pass data to device. I hope we should fill IOBufferMemoryDescriptor *inData.

Post not yet marked as solved Up vote post of myurik2 Down vote post of myurik2
86 views
  • I think it is more or less your implementation of the ioCompleteCallback function that is missing. Any async callback data is passed to this function.

  • I think it is more or less your implementation of the ioCompleteCallback function that is missing.

    It's because we don't know how to read data. Here is method declaration in MyDriver.iig:

        virtual void ReadComplete(OSAction *action,                               IOReturn  status,                               uint32_t  actualByteCount,                               uint64_t  completionTimestamp) TYPE(IOUSBHostPipe::CompleteAsyncIO);

    No data is passed