Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Getting the BSD name of a USB device using IOKit to write to the device?

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.

like image 352
b degnan Avatar asked Feb 12 '13 20:02

b degnan


1 Answers

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.

like image 159
Johan Velthuis Avatar answered Oct 21 '22 12:10

Johan Velthuis