2015-09-24 92 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