2015-09-24 61 views
2

我正在处理需要监视Thunderbolt端口连接变化的需求。 (当Thunderbolt电缆连接或断开时)。监视Thunderbolt端口连接的变化

我试图用IOServiceMatching(kIOUSBInterfaceClassName)由于IOKit框架,但我无法监控Thunderbolt端口上的变化。

有什么办法可以实现它吗?任何帮助表示赞赏。

回答

1

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注册表中那些有它到达实际设备的人。

+0

感谢@pmdj为您的答案,但我期待着一个更实用的答案,就像代码等方面的问题一样,但不用担心,我想出了一个解决方案,并将其公布在下面。 – Prashant

0

最后,我想出了一种方法来监视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框架到您的项目。

+0

我试过这段代码,当我连接新的Thunderbolt设备(例如外部显示器)时,我没有这么做。 – Donny