I used successfully under MacOS32 the following translation from Objective-c:
unit Macapi.IOKitExtension; uses MacApi.ObjectiveC, MacApi.Foundation, Macapi.CoreFoundation, Macapi.Mach, Macapi.IOKit; const kIOSerialBSDServiceValue = 'IOSerialBSDClient'; kIOSerialBSDTypeKey = 'IOSerialBSDClientType'; kIOSerialBSDModemType = 'IOModemSerialStream'; kIOUSBDeviceClassName = 'IOUSBDevice'; kIOCalloutDeviceKey = 'IOCalloutDevice'; kIOTTYDeviceKey = 'IOTTYDevice'; kIOServicePlane = 'IOService'; kUSBInterfaceNumber = 'bInterfaceNumber'; kUSBVendorID = 'idVendor'; kUSBProductID = 'idProduct'; kIORegistryIterateRecursively = $00000001; kIORegistryIterateParents = $00000002; type io_iterator_t = io_object_t; io_name_t = array[0..127] of AnsiChar; function IOServiceGetMatchingServices(masterPort: mach_port_t; matching: CFDictionaryRef; var existing: io_iterator_t): kern_return_t; cdecl; external libIOKit name _PU + 'IOServiceGetMatchingServices'; function IOIteratorNext(name: io_iterator_t): io_object_t; cdecl; external libIOKit name _PU + 'IOIteratorNext'; function IORegistryEntrySearchCFProperty(entry: io_registry_entry_t; plane: io_name_t; key: CFStringRef; allocator: CFAllocatorRef; options: IOOptionBits): CFTypeRef; cdecl; external libIOKit name _PU + 'IORegistryEntrySearchCFProperty';
I need this in the following function for searching an USB serial device for a given vendor ID and product ID:
function SearchUSBSerialDevice(const Service: string; VendorID, ProductID: cardinal): integer; var MatchingDictionary: CFMutableDictionaryRef; Iter: io_iterator_t; USBRef: io_service_t; ret: kern_return_t; ResAsCFString: CFTypeRef; aBsdPath: PAnsiChar; Bsd: array[0..1024] of AnsiChar; sBsd: string; VID, PID: Int32; begin result := 0; MatchingDictionary := IOServiceMatching(kIOSerialBSDServiceValue); ret := IOServiceGetMatchingServices(kIOMasterPortDefault, CFDictionaryRef(MatchingDictionary), Iter); if (ret = KERN_SUCCESS) and (Iter <> 0) then begin try repeat USBRef := IOIteratorNext(Iter); if USBRef <> 0 then begin // USB device found Bsd[0] := #0; VID := 0; PID := 0; ResAsCFString := IORegistryEntryCreateCFProperty(USBRef, CFSTR(kIOCalloutDeviceKey), kCFAllocatorDefault, 0); if assigned(ResAsCFString) then begin aBsdPath := CFStringGetCStringPtr(ResAsCFString, kCFStringEncodingASCII); if assigned(aBsdPath) then sBsd := string(aBsdPath) else if CFStringGetCString(ResAsCFString, @Bsd[0], sizeof(Bsd), kCFStringEncodingASCII) then sBsd := string(Bsd) else sBsd := ''; // Invalid device path end; ResAsCFString := IORegistryEntrySearchCFProperty(USBRef, kIOServicePlane, CFSTR(kUSBVendorID), kCFAllocatorDefault, kIORegistryIterateRecursively + kIORegistryIterateParents); if assigned(ResAsCFString) then if not CFNumberGetValue(ResAsCFString, kCFNumberIntType, @VID) then VID := 0; ResAsCFString := IORegistryEntrySearchCFProperty(USBRef, kIOServicePlane, CFSTR(kUSBProductID), kCFAllocatorDefault, kIORegistryIterateRecursively + kIORegistryIterateParents); if assigned(ResAsCFString) then if not CFNumberGetValue(ResAsCFString, kCFNumberIntType, @PID) then PID := 0; Log.d(name + ': USBDevice "' + sBsd + '" VID/PID: ' + IntToHex(VID) + '/' + IntToHex(PID)); end; until USBRef = 0; finally IOObjectRelease(Iter); end; end;
With Delphi 10.3.2, I need to migrate this code for using on MacOS64 too.
Unfortunately, I get a read access violation in IORegistryEntrySearchCFProperty which I do not understand.
From my point of view, there is no change in the parameters of IORegistryEntrySearchCFProperty from 32bit to 64bit.
I have implemented this code with XCode in C without any troubles.
Maybe someone can give me a tip, what I have to pay attention to here.
Well, that's an easy one. According to your declaration of IORegistryEntrySearchCFProperty, the second argument is a 128-byte array. Such long arguments are usually passed as pointers, you don't normally push 128 bytes as is. So... you should change your declaration to:function IORegistryEntrySearchCFProperty(entry: io_registry_entry_t; plane: pointer; ... And then your call becomes:var Plane: io_name_t;Plane := kIOServicePlane;ResAsCFString := IORegistryEntrySearchCFProperty(USBRef, @plane[0]....or even simply "PAnsiChar(ansistring(kIOServicePlane))", which should work as well. Magically, your function will start working just fine.