I'm struggling with IOKit at the moment as well, and it's not a very well covered topic (either with Mr. Google or in this forum).
Would you be able to post some example code on how to use these functions?
It would be very much appreciated :)
{$linkframework IOKit}
//IOKit = '/System/Library/Frameworks/IOKit.framework/IOKit';
type
io_name_t = array[0..128] of Char;
io_object_t = mach_port_t;
io_iterator_t = io_object_t;
io_service_t = io_object_t;
io_registry_entry_t = io_object_t;
IOOptionBits = UInt32;
const
kIOSerialBSDServiceValue = 'IOSerialBSDClient';
kIOSerialBSDTypeKey = 'IOSerialBSDClientType';
kIOSerialBSDModemType = 'IOModemSerialStream';
kIOUSBDeviceClassName = 'IOUSBDevice';
kUSBVendorID = 'idVendor';
kUSBProductID = 'idProduct';
kIOTTYDeviceKey = 'IOTTYDevice';
kIOCalloutDeviceKey = 'IOCalloutDevice';
kIOServicePlane = 'IOService';
kUSBInterfaceNumber = 'bInterfaceNumber';
function IOServiceMatching(name: PChar): CFMutableDictionaryRef; cdecl; external;
function IOServiceGetMatchingServices(masterPort: mach_port_t; matching: CFDictionaryRef;
var existing: io_iterator_t): kern_return_t; cdecl; external;
function IOIteratorNext(name: io_iterator_t): io_object_t; cdecl; external;
function IORegistryEntryCreateCFProperty(entry: io_registry_entry_t; key: CFStringRef;
allocator: CFAllocatorRef; options: IOOptionBits): CFTypeRef; cdecl; external;
function IORegistryEntryGetName(entry: io_registry_entry_t; var name: io_name_t): kern_return_t; cdecl; external;
function IORegistryEntryGetParentEntry(entry: io_registry_entry_t; plane: io_name_t;
var parent: io_registry_entry_t): kern_return_t; cdecl; external;
function IORegistryEntrySearchCFProperty(entry: io_registry_entry_t; plane: io_name_t;
key: CFStringRef; allocator: CFAllocatorRef; options: IOOptionBits): CFTypeRef; cdecl; external;
function IOObjectRelease(object_: io_object_t): kern_return_t; cdecl; external;
function RegName(FEntry: io_registry_entry_t): string;
var
FName: io_name_t;
begin
FillChar(FName, SizeOf(FName), 0);
IORegistryEntryGetName(FEntry, FName);
RegName := StrPas(PChar(@FName));
end;
function RegStr(FEntry: io_registry_entry_t; FKey: PChar): string;
var
FBuf: array[0..255] of Char;
FCFStr: CFTypeRef;
FStr: string;
begin
FCFStr := IORegistryEntryCreateCFProperty(FEntry, CFSTR(FKey), kCFAllocatorDefault, 0);
FillChar(FBuf, SizeOf(FBuf), 0);
CFStringGetPascalString(FCFStr, @FBuf[0], 256, CFStringGetSystemEncoding);
FStr := StrPas(PChar(@FBuf));
FStr := RightStr(FStr, Length(FStr) - 1);
RegStr := FStr;
end;
function RegNum(FEntry: io_registry_entry_t; FKey: PChar; var FRes: Int): Boolean;
var
FCFNumber: CFTypeRef;
FNum: SInt32;
begin
RegNum := False;
FCFNumber := IORegistryEntrySearchCFProperty(FEntry, kIOServicePlane, CFSTR(FKey), kCFAllocatorDefault, 0);
if FCFNumber <> nil then
begin
CFNumberGetValue(FCFNumber, kCFNumberSInt32Type, @FNum);
FRes := FNum;
RegNum := True;
end;
end;
function CdcPort: Boolean;
var
FMatchDic: CFMutableDictionaryRef;
FIterator: io_iterator_t;
FDevice, FDeviceOld: io_registry_entry_t;
FGetParentRes: kern_return_t;
FVid, FPid, FIntNum: Int;
FPortName, FPortPath: string;
begin
CdcPort := False;
FMatchDic := IOServiceMatching(kIOSerialBSDServiceValue);
CFDictionarySetValue(FMatchDic, CFSTR(kIOSerialBSDTypeKey), CFSTR(kIOSerialBSDModemType));
//if IOServiceGetMatchingServices(kIOMasterPortDefault, FMatchDic, FIterator) = kIOReturnSuccess then
if IOServiceGetMatchingServices(0, FMatchDic, FIterator) = kIOReturnSuccess then
while True do
begin
FDevice := IOIteratorNext(FIterator);
if FDevice = 0 then break;
FPortName := RegStr(FDevice, kIOTTYDeviceKey);
if LeftStr(FPortName, 8) = 'usbmodem' then
begin
FPortPath := RegStr(FDevice, kIOCalloutDeviceKey);
//WriteLn(FPortName + ':' + FPortPath);
//WriteLn(RegName(FDevice));
FVid := -1;
FGetParentRes := kIOReturnSuccess;
while (FVid < 0) and (FGetParentRes = kIOReturnSuccess) do
begin
//WriteLn(RegName(FDevice));
FDeviceOld := FDevice;
FGetParentRes := IORegistryEntryGetParentEntry(FDevice, kIOServicePlane, FDevice);
if IOObjectRelease(FDeviceOld) = kIOReturnSuccess then ; //WriteLn('*')
if FGetParentRes = kIOReturnSuccess then
begin
RegNum(FDevice, kUSBVendorID, FVid);
RegNum(FDevice, kUSBProductID, FPid);
RegNum(FDevice, kUSBInterfaceNumber, FIntNum);
end;
end;
//WriteLn(IntToHex(FVid, 4) + ' ' + IntToHex(FPid, 4) + ' ' + IntToHex(FIntNum, 4));
if (FVid = $XXXX) and ((FPid = $YYYY) or (FPid = $ZZZZ)) and (FIntNum = 1) then
begin
GPortLen := GPortLen + 1;
GPortName[GPortLen] := FPortName;
GPortPath[GPortLen] := FPortPath;
if AnsiCompareText(GPortName[0], GPortName[GPortLen]) = 0 then CdcPort := True;
end;
end;
end;
end;