I am trying to determine the BSD name of virtual serial port using IOKit under MacOS.
I have a USB CDC device that looks like a virtual serial port, and I want to get the BSD device path so that I can just do a fopen("/dev/tty.usbmodem123"). I have a program that takes the VID and PID and waits for the device to be plugged in, and then I want to use the BSD name write to the device. The device mounts differently on every system and I am trying to use this as a teaching tool, so I need to search for the device before I write to it without manually inspecting /dev/tty.* for where the device mounted.
I have 3 questions.
Firstly, can one get the BSD name of a virtual serial port using CFSTR(kIOBSDNameKey)
?
IORegistryEntrySearchCFProperty()
and FindProp()
always return "null". Does anyone know if the BSD name can be returned by a non-block device?
I am currently doing this:
bsdName = IORegistryEntrySearchCFProperty(p_usb_ref, kIOServicePlane, CFSTR(kIOBSDNameKey), kCFAllocatorDefault, kIORegistryIterateRecursively );
Secondly, I have been able to get service plane name: IOService:/AppleACPIPlatformExpert/PCI0@0/AppleACPIPCI/OHC1@4/AppleUSBOHCI/Intro to Electronics@4100000 and this corresponds to a mount point of: /dev/tty.usbmodem411 Does anyone know how to translate the service plane name to the dev tree name?
Thirdly, am I making this too complicated? I already know the device io handle, is there a way to use that to write data to the device? I just need to send a few ASCII bytes to flash some LEDs.
Any advice would be greatly appreciated.
EDIT:
After spending some more time looking at this, I found that my issue was that I was querying for the BSD name before the CDC driver was being loaded. I am currently getting the BSD name, and then sorting out for the VID and PID.
The code that solved my issue above is:
matchingDictionary = IOServiceMatching(kIOSerialBSDServiceValue);
CFDictionarySetValue(matchingDictionary, CFSTR(kIOSerialBSDTypeKey), CFSTR(kIOSerialBSDModemType));
kernResult = IOServiceGetMatchingServices(kIOMasterPortDefault, matchingDictionary, &iter);
And then you iterate through iter
to find the device with the correct ID.
This is what I use with a IONotification when adding a USB serial device: Under 10.11 it came up empty. After trying a lot of things, this was my solution:
while ((usbDevice = IOIteratorNext(iterator)))
{
//when hotplugging under OSX 10.11:
sleep(1);//otherwise the property will be empty.
CFStringRef deviceBSDName_cf = (CFStringRef) IORegistryEntrySearchCFProperty (usbDevice,
kIOServicePlane,
CFSTR (kIOCalloutDeviceKey),
kCFAllocatorDefault,
kIORegistryIterateRecursively );
NSLog(@"device path: %@", deviceBSDName_cf);
}
It should find something like: /dev/cu.xxxxx
Hope it helps someone.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With