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.
Selecting any option will automatically load the page
Post
Replies
Boosts
Views
Activity
Hi,
In Linux we have this driver structure where the handlers are defined as below:
static struct file_operations fops =
{
.owner = THIS_MODULE,
.read = etx_read,
.write = etx_write,
.open = etx_open,
.unlocked_ioctl = etx_ioctl,
.release = etx_release,
};
So when the user app calls open() with the appropriate file/device handle "etx_open" in the driver is acalled, etc. However, the Apple driver structure that is exposed to developers is different and it has changed drastically with the DriverKit architecture.
I have some custom requests from the user app where I need to call this ioctl() type requests on my serial port "tty.myusbserial1234". My driver is derived from IOUserUSBSerial and is working fine for all other practical purposes except for such custom requirements.
Has anyone encountered such a problem in MacOS DriverKit and what is the solution or an alternative?
https://developer.apple.com/documentation/driverkit/communicating-between-a-driverkit-extension-and-a-client-app
This gives a different approach, but the serial ports are accessed via open/read/write/close system calls and tcsetattr and other termios functions to set baud-rate and such. So, the above approcah is not suitable for my purpose.
Any ideas/help is very much appreciated.
Thanks.
Topic:
App & System Services
SubTopic:
Drivers
Hi,
I have a usb composite device with multiple interfaces that support cdc-acm UARTs.
My custom driver (.dext) loads and works for single channel usb-cdcccm device with these entries in the info.plist:
bInterfaceNumber
1
But there is no option to define multiple "bInterfaceNumber" key.
I tried bInterfaceClass also, as given below, but no success.
Option-1:
bInterfaceClass
10
bInterfaceSubClass
0
bInterfaceProtocol
0
Option-2:
bInterfaceClass
10
bInterfaceSubClass
0
bInterfaceProtocol
0
Both the above options yield no result.
But as I said in the beginning:
<key>IOProviderClass</key>
<string>IOUSBHostInterface</string>
<key>IOClass</key>
<string>IOUserSerial</string>
<key>IOResourceMatch</key>
<string>IOKit</string>
<key>IOUserClass</key>
<string>MyDriver</string>
<key>IOUserServerName</key>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>idVendor</key>
<integer>VENDORID</integer>
<key>idProduct</key>
<integer>PRODUCTID</integer>
<key>bInterfaceNumber</key>
<integer>1</integer>
<key>bConfigurationValue</key>
<integer>1</integer>
"MyDriver" loads for interface-1 and works fine. The default AppleCDCACM driver loads for the 2nd channel. I want the same driver load for both the channels.
Any help/suggestions \is very much appreciated.
Thank you.
Topic:
App & System Services
SubTopic:
Drivers