###OS Xでシリアルポートアクセス
Mac OS Xで Arduinoなどをコントロールする場合、USB経由での Serial通信を行う事が多々あります。
あくまでも実験段階であれば /dev/tty.cu.usbmodem*
など、デバイスファイル名を直接指定して open()
すれば良いのですが、この手のデバイス名は仮想的なものなので接続する度に名前が変わったりとかして、実に面倒臭いです。
やっぱり、自動的にシリアルデバイス名を見つけて自動的にオープンする。こんな流れに持っていきたいですよね。
そこで、OS X流のデバイスファイルの見つけ方。
IOKit Frameworkを使いましょう。
#import <IOKit/IOKitLib.h>
#import <IOKit/serial/IOSerialKeys.h>
#import <IOKit/IOBSD.h>
#import <sys/ioctl.h>
static io_iterator_t findServiceDevices(void) {
kern_return_t result;
mach_port_t mach_port;
if ((result = IOMasterPort(MACH_PORT_NULL, &mach_port)) != KERN_SUCCESS)
return 0;
CFMutableDictionaryRef classesToMatch = IOServiceMatching(kIOSerialBSDServiceValue);
if (classesToMatch == NULL)
return 0;
CFDictionarySetValue(classesToMatch, CFSTR(kIOSerialBSDTypeKey), CFSTR(kIOSerialBSDAllTypes));
if ((result = IOServiceMatchingServices(mach_port, classesToMatch, &matchingServices)) != KERN_SUCCESS)
return 0;
return matchingServices;
}
static NSString * resolveServiceDeviceName(io_iterator_t iterator) {
io_object_t modemDevice;
CFTypeRef deviceFilePathAsCFString = NULL;
NSString *deviceFilePath = nil;
if (iterator == 0)
return nil;
while ((modemDevice = IOIteratorNext(iterator)) != 0) {
deviceFilePathAsCFString = IORegistryEntryCreateCFProperty(modemDevice, CFSTR(kIOCalloutDeviceKey), kCFAllocatorDefault, 0);
IOObjectRelease(modemDevice);
deviceFilePath = CFBridgingRelease(deviceFilePathAsCFString);
if ([deviceFilePath isGreaterThanOrEqualTo:@"/dev/cu.usbmodem"])
break;
deviceFilePath = nil;
}
return deviceFilePath;
}
io_iterator_t iterator = findSerialDevices();
NSString *devName = resolveSerialDeviceName(iterator);
int devFD = open(devName.UTF8String, O_RDWR|O_NOTTY|O_NONBLOCK);
iotcl(devFD, TIOCEXCL);
: