我正在处理需要监视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