我正在處理需要監視Thunderbolt端口連接變化的需求。 (當Thunderbolt電纜連接或斷開時)。監視Thunderbolt端口連接的變化
我試圖用IOServiceMatching(kIOUSBInterfaceClassName)從由於IOKit框架,但我無法監控Thunderbolt端口上的變化。
有什麼辦法可以實現它嗎?任何幫助表示讚賞。
我正在處理需要監視Thunderbolt端口連接變化的需求。 (當Thunderbolt電纜連接或斷開時)。監視Thunderbolt端口連接的變化
我試圖用IOServiceMatching(kIOUSBInterfaceClassName)從由於IOKit框架,但我無法監控Thunderbolt端口上的變化。
有什麼辦法可以實現它嗎?任何幫助表示讚賞。
Thunderbolt設備(除了使用Thunderbolt端口的DisplayPort部分的顯示器)是PCI設備,而不是USB,所以它們將在IOService註冊表中顯示爲IOPCIDevice
s。然而,它們也會在Thunderbolt子樹中顯示爲IOThunderboltPort
對象,其中「PCI Path」屬性將指示相關的012er的IOService路徑。通過監視IOThunderboltPort
服務的出現和消失,並檢查其PCI路徑屬性,可以避免匹配其他種類的PCI設備。
爲了說明我在說什麼,打開IORegistryExplorer或IOJones並熱插拔Thunderbolt設備;您應該看到IOThunderboltPort(以及一堆其他類型的相關對象,例如AppleThunderboltPCIUpAdapter等)以及IOPCIDevice(以及Thunderbolt總線工作的PCI2PCI網橋)。 (或者您可以使用ioreg
之前和熱插拔後報平安。)
因此,在總結,我會匹配IOThunderboltPort
服務,忽略任何不帶PCI path屬性,並查找對應的IOPCIDevice
在IO註冊表中那些有它到達實際設備的人。
最後,我想出了一種方法來監視Thunderbolt Connection。感謝蘋果科技人員指出我正確的方向。 監控IOEthernetInterface條目的I/O註冊表。過濾Thunderbolt網絡相對容易(我不確定最佳選擇是什麼,但一個簡單的選擇是在父IOEthernetController的「IOModel」屬性中查找「ThunderboltIP」)。這是蘋果論壇上來自Apple的技術人員的迴應。使用上面的信息,我寫了一段代碼,它將返回Thunderbolt端口的狀態。
#include <IOKit/network/IOEthernetController.h>
- (void) monitorThunderboltConnection
{
CFMutableDictionaryRef matchingDict;
io_iterator_t iter;
io_object_t controllerService;
kern_return_t kr;
UInt8 MACAddress[kIOEthernetAddressSize];
QNInterfaceModel *interfaceModel = [[QNInterfaceModel alloc] initWithInterfaceModel];
/* set up a matching dictionary for the class */
matchingDict = IOServiceMatching(kIOEthernetInterfaceClass);
if (matchingDict == NULL)
{
NSLog(@"Failed");
return;
}
/* Now we have a dictionary, get an iterator.*/
kr = IOServiceGetMatchingServices(kIOMasterPortDefault, matchingDict, &iter);
if (kr == kIOReturnSuccess)
{
// Actually iterate through the found devices.
io_registry_entry_t serviceObject;
while ((serviceObject = IOIteratorNext(iter)))
{
// Put this services object into a dictionary object.
kr = IORegistryEntryGetParentEntry(serviceObject,
kIOServicePlane,
&controllerService);
if (KERN_SUCCESS != kr)
{
printf("IORegistryEntryGetParentEntry returned 0x%08x\n", kr);
}
else
{
CFMutableDictionaryRef serviceDictionary;
CFTypeRef networkType;
CFTypeRef MACAddressAsCFData;
NSNumber *linkStatus;
if (IORegistryEntryCreateCFProperties(serviceObject,
&serviceDictionary,
kCFAllocatorDefault,
kNilOptions) == kIOReturnSuccess)
{
networkType = IORegistryEntryCreateCFProperty(controllerService,
CFSTR(kIOModel),
kCFAllocatorDefault,
0);
if(networkType)
{
if (CFGetTypeID(networkType) == CFStringGetTypeID())
{
CFStringRef networkName = networkType;
interfaceModel.interfaceName = (__bridge NSString *)networkName;
}
CFRelease(networkType);
}
if([interfaceModel.interfaceName isEqualToString:@"ThunderboltIP"])
{
MACAddressAsCFData = IORegistryEntryCreateCFProperty(controllerService,
CFSTR(kIOMACAddress),
kCFAllocatorDefault,
0);
if (MACAddressAsCFData)
{
CFShow(MACAddressAsCFData); // for display purposes only; output goes to stderr
// Get the raw bytes of the MAC address from the CFData
CFDataGetBytes(MACAddressAsCFData, CFRangeMake(0, kIOEthernetAddressSize), MACAddress);
if (KERN_SUCCESS != kr)
{
printf("GetMACAddress returned 0x%08x\n", kr);
}
else
{
interfaceModel.macAddress = [[NSString stringWithFormat:@"%02x:%02x:%02x:%02x:%02x:%02x",MACAddress[0], MACAddress[1], MACAddress[2], MACAddress[3], MACAddress[4], MACAddress[5]] uppercaseString];
}
CFRelease(MACAddressAsCFData);
}
linkStatus = (__bridge NSNumber *)(IORegistryEntryCreateCFProperty(controllerService,
CFSTR(kIOLinkStatus),
kCFAllocatorDefault,
0));
if (linkStatus)
{
NSLog(@"%@", [linkStatus stringValue]);
if([linkStatus integerValue] == 3) // Thunderbolt IP is Connnected
{
interfaceModel.connectedStatus = YES;
}
else
{
interfaceModel.connectedStatus = NO;
}
}
CFStringRef bsdName = (CFStringRef) IORegistryEntrySearchCFProperty (controllerService,
kIOServicePlane,
CFSTR (kIOBSDNameKey),
kCFAllocatorDefault,
kIORegistryIterateRecursively);
interfaceModel.interfaceName = (__bridge NSString *) bsdName;
if(interfaceModel.connectedStatus == YES)
{
NSLog(@"Connected");
}
else
{
NSLog(@"DisConnected");
}
}
// Failed to create a service dictionary, release and go on.
IOObjectRelease(serviceObject);
// Done with the parent Ethernet controller object so we release it.
(void) IOObjectRelease(controllerService);
continue;
}
}
}
}
/* Done, release the iterator */
IOObjectRelease(iter);
}
注:我使用的接口模式來收集像硬件地址,BSD名稱,連接狀態等所有霹靂信息您還需要添加I/O Kit框架到您的項目。
我試過這段代碼,當我連接新的Thunderbolt設備(例如外部顯示器)時,我沒有這麼做。 – Donny
感謝@pmdj爲您的答案,但我期待着一個更實用的答案,就像代碼等方面的問題一樣,但不用擔心,我想出了一個解決方案,並將其公佈在下面。 – Prashant