Hi,
This is the code snippet in my driver for an usb uart device. I am trying to call standard cdc-acm command to set the Line Coding in the device, but fails with this error:
"USBSendSetLineCoding - Failed : 0xe0005000, bytes transferred: 0"
I guess the USB device is returning this error due to incorrect buffer or format. There is no proper documentation on how to use IOMemoryDescriptor when the data has to be passed down in a buffer to the usb stack. (IOUSBHostInterface->DeviceRequest())
Can anyone please point out what is wrong with this code and suggest a right method?
void MyDriver::USBSendSetLineCoding(uint32_t BaudRate, uint8_t StopBits, uint8_t TX_Parity, uint8_t CharLength)
{
kern_return_t ret = kIOReturnSuccess;
LineCoding *lineParms;
uint16_t lcLen = sizeof(LineCoding)-1;
lineParms = (LineCoding *)IOMalloc(lcLen);
if (!lineParms)
{
MyDebugLog("USBSendSetLineCoding - allocate lineParms failed");
return;
}
bzero(lineParms, lcLen);
lineParms->bCharFormat = StopBits - 2;
lineParms->bParityType = TX_Parity - 1;
lineParms->bDataBits = CharLength;
OSSwapBigToHostInt32(BaudRate);
lineParms->dwDTERate = BaudRate;
IOBufferMemoryDescriptor* bufferDescriptor = nullptr;
_controlInterface->CreateIOBuffer(kIOMemoryDirectionOut, lcLen, &bufferDescriptor);
IOMemoryMap *map = nullptr;
bufferDescriptor->CreateMapping(kIOMemoryMapReadOnly, 0, 0, 0, 0, &map);
if(map == nullptr)
{
MyDebugLog("USBSendSetLineCoding - Failed to map memory in CreateMapping\n");
IOFree(lineParms, lcLen);
bufferDescriptor->release();
return;
}
uint64_t ptr = map->GetAddress();
if(!ptr)
{
MyDebugLog("USBSendSetLineCoding - Failed to get Memory Address\n");
IOFree(lineParms, lcLen);
bufferDescriptor->release();
map->release();
return;
}
memcpy(&ptr, lineParms, lcLen);
uint8_t bmRequestType = kIOUSBDeviceRequestDirectionOut | kIOUSBDeviceRequestTypeClass | kIOUSBDeviceRequestRecipientInterface;
uint16_t wValue = 0;
uint16_t wIndex = _bControlInterfaceNumber;
uint16_t bytesTransferred = 0;
ret = _controlInterface->DeviceRequest(bmRequestType, kUSBSET_LINE_CODING, wValue, wIndex, lcLen, bufferDescriptor, &bytesTransferred, 1000);
IOFree(lineParms, lcLen);
map->release();
bufferDescriptor->release();
if (ret != kIOReturnSuccess) {
MyDebugLog("USBSendSetLineCoding - Failed : 0x%x, bytes transferred: %d\n", ret, bytesTransferred);
return;
}
return;
}
I am able to call DeviceRequest() successfully on the same interface for any other setting that requires no data buffer, such as,
"ret = _controlInterface->DeviceRequest(bmRequestType, kUSBSEND_BREAK, wValue, wIndex, 0, NULL, &bytesTransferred, 1000);"
So I think the "bufferDescriptor" is not properly created or the data is not copied correctly in this function for the failure.
"ret = _controlInterface->DeviceRequest(bmRequestType, kUSBSET_LINE_CODING, wValue, wIndex, lcLen, bufferDescriptor, &bytesTransferred, 1000);"
Any help is very much appreciated. Thanks in advance.