limitations of UserSendCDB in SCSIPeripheralsDriverKit?

I've made a dext and a user client that overrides IOUserSCSIPeripheralDeviceType00, with the object of writing device firmware to the driver. I can gain and relinquish exclusive access to the device, I can call UserReportMediumBlockSize and get back a sensible answer (512). I can build command parameters with the INQUIRY macro from IOUserSCSIPeripheralDeviceHelper.h and send that command successfully using UserSendCB, and I receive sensible-looking Inquiry data from the device.

However, what I really want to do is send a WriteBuffer command (opcode 0x3B), and that doesn't work. I have yet to put a bus analyzer on it, but I don't think the command goes out on the bus - there's no valid sense data, and the error returned is 0xe00002bc, or kIOReturnError, which isn't helpful.

This is the code I have which doesn't work.

kern_return_t driver::writeChunk(const char * buf, size_t atOffset, size_t length, bool lastOne)
{
    DebugMsg("writeChunk %p at %ld for %ld", buf, atOffset, length);
    SCSIType00OutParameters outParameters;
    SCSIType00InParameters response;
    
    memset(&outParameters, 0, sizeof(outParameters));
    memset(&response, 0, sizeof(response));
    
    SetCommandCDB(&outParameters.fCommandDescriptorBlock,
                  0x3B, // byte 0, opcode WriteBuffer command
                  lastOne ?   0x0E : 0x0F, // byte 1 mode: E=save deferred, F = download and defer save
                  0, // byte 2 bufferID
                  (atOffset >> 16), // byte 3
                  (atOffset >> 8),         // byte 4
                  atOffset,         // byte 5
                  (length >> 16),    // byte 6
                  (length >> 8),           // byte 7
                  length,              // byte 8
                  0, // control, byte 9
                  0, 0, 0, 0, 0, 0); // bytes 10..15
    
    outParameters.fLogicalUnitNumber = 0;
    outParameters.fBufferDirection = kIOMemoryDirectionOut;
    outParameters.fDataTransferDirection = kSCSIDataTransfer_FromInitiatorToTarget;

    outParameters.fTimeoutDuration = 1000; // milliseconds
    outParameters.fRequestedByteCountOfTransfer = length;
    outParameters.fDataBufferAddr = reinterpret_cast<uint64_t>(buf);
    
    uint8_t senseBuffer[255] = {0};
    outParameters.fSenseBufferAddr = reinterpret_cast<uint64_t>(senseBuffer);
    outParameters.fSenseLengthRequested = sizeof(senseBuffer);
    
    kern_return_t retVal = UserSendCDB(outParameters, &response);
                  
    return retVal;
}
limitations of UserSendCDB in SCSIPeripheralsDriverKit?
 
 
Q