Question

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.

Était-ce utile?

La solution

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.

Autres conseils

Perhaps things have changed in OS X 10.10? Your last code snippet doesn't seem to find the /dev/tty.usbmodem00054741 device on my system:

io_iterator_t devlisthndl = 0;
CFMutableDictionaryRef matchingDictionary = IOServiceMatching(kIOSerialBSDServiceValue);
CFIndex dict_count = CFDictionaryGetCount(matchingDictionary);
CFDictionarySetValue(matchingDictionary, CFSTR(kIOSerialBSDTypeKey), CFSTR(kIOSerialBSDModemType));
kern_return_t kernResult = IOServiceGetMatchingServices(kIOMasterPortDefault, matchingDictionary, &devlisthndl);

(lldb) p matchingDictionary
(CFMutableDictionaryRef) $3 = 0x0000610000267780 @"0 entries"

How did you end up obtaining the mount point string?

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top