IOKIT Определение имени BSD (unix) для последовательного USB-устройства с PID и VID - PullRequest
0 голосов
/ 13 февраля 2019

Я работаю с последовательными USB-устройствами на macOS.

Как определить имя BSD (unix) для моего устройства USB Serial на macOS, используя IOKit?Я хочу получить имя устройства, например: "IODialinDevice" = "/dev/tty.usbmodemMyDeviceName"

Мое устройство USB - это последовательный порт USB COM.Также я хочу определить, когда устройство было подключено к машине.

Я могу определить, когда было подключено новое USB-устройство с моим VID и PID.Этот код позволяет мне сделать это

CFMutableDictionaryRef keywordDict = IOServiceMatching(kIOSerialBSDServiceValue);

kern_return_t result = IOServiceGetMatchingServices(kIOMasterPortDefault, keywordDict, &iterator);

while ((port = IOIteratorNext(iterator)))
{
        io_object_t parent = 0;                     
        io_object_t current_device = port;
        while (KERN_SUCCESS == IORegistryEntryGetParentEntry(current_device, kIOServicePlane, &parent))
        {
            CFTypeRef vendor_Id = IORegistryEntryCreateCFProperty(parent, CFSTR(kUSBVendorID), kCFAllocatorDefault, 0);
            CFTypeRef pr_Id = IORegistryEntryCreateCFProperty(parent, CFSTR(kUSBProductID), kCFAllocatorDefault, 0);

            if((vendor_id==MY_VENDOR_ID) && (pr_ID==MY_PRODUCT_ID))
            {
                // MY SERIAL DEVICE DETECTED !! 
                CFTypeRef deviceName = IORegistryEntryCreateCFProperty(device, key, CFSTR(kIOTTYDeviceKey), 0);
                CFTypeRef callOutDevice = IORegistryEntryCreateCFProperty(device, key, CFSTR(kIOCalloutDeviceKey), 0);
                CFTypeRef dialInDevice = IORegistryEntryCreateCFProperty(device, key, CFSTR(kIODialinDeviceKey), 0);

            }
        }
}

Но проблема в том, что этот код не позволяет мне обнаружить новое устройство.Я просто перечисляю существующие устройства kIOSerialBSDServiceValue здесь, а затем проверяю VID и PID родителей. Если у родителя есть MY_VID и MY_PID, я предполагаю, что нашел правильное последовательное устройство.

Другой код позволяет мне обнаружить новое USB-устройство

Это пример Apple LUSBPrivateDataSample.c Я могу обнаружить свое устройство, используя VID и PID, с помощью следующего кода

   int main()
   {
    ...
    ...
    ...

    // Create a CFNumber for the idVendor and set the value in the dictionary
    numberRef = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &usbVendor);
    CFDictionarySetValue(matchingDict, 
                         CFSTR(kUSBVendorID), 
                         numberRef);
    CFRelease(numberRef);

    // Create a CFNumber for the idProduct and set the value in the dictionary
    numberRef = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &usbProduct);
    CFDictionarySetValue(matchingDict, 
                         CFSTR(kUSBProductID), 
                         numberRef);
    CFRelease(numberRef);

    ...
    ...
    ...

        // Now set up a notification to be called when a device is first matched by I/O Kit.
    kr = IOServiceAddMatchingNotification(gNotifyPort,                  // notifyPort
                                          kIOFirstMatchNotification,    // notificationType
                                          matchingDict,                 // matching
                                          DeviceAdded,                  // callback
                                          NULL,                         // refCon
                                          &gAddedIter                   // notification
                                          );    

    }

    void DeviceAdded(void *refCon, io_iterator_t iterator)
    {
        io_service_t        usbDevice;
        while ((usbDevice = IOIteratorNext(iterator)))
        {
                // I have device here but I can't get IODialinDevice device name 
        }
    }

Проблема с этим кодом, из-за которой я не могу получить имя устройства IODialinDevice, я также проверил вседочерние узлы для этого usbDevice.Ни один из них не содержит свойство IODialinDevice, ни одно из них не является устройством kIOSerialBSDServiceValue.

Похоже, я делаю это неправильно.Похоже, последовательные устройства и USB живут в разных ветках реестра IOKit.Вопрос в том, как перейти от USB-устройства, идентифицированного VID и PID, к последовательному устройству (kIOSerialBSDServiceValue) со свойством IODialinDevice ("/dev/tty.usbmodemMyDeviceName").

Любая помощь приветствуется!

Обновление: Это дерево ioreg:
Я могу обнаружить устройство данных CDC ACM в моем приложении.(верхнее устройство в этом дереве) В ioreg я вижу эту картинкуИтак, есть дети AppleUSBACMData и IOSerialBSDClient, которые имеют свойство IODialinDevice.Но я не могу обнаружить AppleUSBACMData и IOSerialBSDClient в моем приложении.Возможно, потому что AppleUSBACMData и IOSerialBSDClient - это не устройства, а интерфейсы USB или конечные точки USB.Так что это моя проблема.

+-o CDC ACM Data@3  <class IOUSBHostInterface, id 0x100090fff, registered, matched, active, busy 0 (514 ms), retain 7>
  | {
  |   "USBPortType" = 0
  |   "IOCFPlugInTypes" = {"2d9786c6-9ef3-11d4-ad51-000a27052861"="IOUSBFamily.kext/Contents/PlugIns/IOUSBLib.bundle"}
  |   "Product Name" = "DevName"
  |   "bcdDevice" = 1044
  |   "USBSpeed" = 3
  |   "idProduct" = 260
  |   "bConfigurationValue" = 1
  |   "bInterfaceSubClass" = 0
  |   "locationID" = 338886656
  |   "IOGeneralInterest" = "IOCommand is not serializable"
  |   "IOServiceLegacyMatchingRegistryID" = 4295561221
  |   "IOClassNameOverride" = "IOUSBInterface"
  |   "AppleUSBAlternateServiceRegistryID" = 4295561221
  |   "idVendor" = 7777
  |   "bInterfaceProtocol" = 0
  |   "bAlternateSetting" = 0
  |   "bInterfaceNumber" = 3
  |   "bInterfaceClass" = 10
  | }
  | 
  +-o AppleUSBACMData  <class AppleUSBACMData, id 0x100091018, registered, matched, active, busy 0 (0 ms), retain 6>
    | {
    |   "IOClass" = "AppleUSBACMData"
    |   "CFBundleIdentifier" = "com.apple.driver.usb.cdc.acm"
    |   "IOProviderClass" = "IOUSBHostInterface"
    |   "IOTTYBaseName" = "usbmodem"
    |   "idProduct" = 260
    |   "IOProbeScore" = 49999
    |   "bInterfaceSubClass" = 0
    |   "HiddenPort" = Yes
    |   "IOMatchCategory" = "IODefaultMatchCategory"
    |   "idVendor" = 7777
    |   "IOTTYSuffix" = "DevName_B3"
    |   "bInterfaceClass" = 10
    | }
    | 
    +-o IOSerialBSDClient  <class IOSerialBSDClient, id 0x100091020, registered, matched, active, busy 0 (0 ms), retain 5>
    {
       "IOClass" = "IOSerialBSDClient" 
        "CFBundleIdentifier" = "com.apple.iokit.IOSerialFamily"
        "IOProviderClass" = "IOSerialStreamSync"
        "IOTTYBaseName" = "usbmodem"
        "IOSerialBSDClientType" = "IORS232SerialStream"
        "IOProbeScore" = 1000
        "IOCalloutDevice" = "/dev/cu.usbmodemDevName_B3"
        "IODialinDevice" = "/dev/tty.usbmodemDevName_B3"
        "IOMatchCategory" = "IODefaultMatchCategory"
        "IOTTYDevice" = "usbmodemDevName_B3"
        "IOResourceMatch" = "IOBSD"
        "IOTTYSuffix" = "DevName_B3"
    }

1 Ответ

0 голосов
/ 27 февраля 2019

Решение довольно простое.Это всегда было на моем столе.Вы должны подписаться на получение уведомлений о новых устройствах kIOSerialBSDServiceValue появляется в системе, как это.Этот код также основан на Apple USBPrivateDataSample.c

https://developer.apple.com/library/archive/samplecode/USBPrivateDataSample/Introduction/Intro.html#//apple_ref/doc/uid/DTS10000456

CFMutableDictionaryRef matchingDict = IOServiceMatching(kIOSerialBSDServiceValue);
....
    // Now set up a notification to be called when a device is first matched by I/O Kit.
kr = IOServiceAddMatchingNotification(gNotifyPort,                  // notifyPort
                                      kIOFirstMatchNotification,    // notificationType
                                      matchingDict,                 // matching
                                      DeviceAdded,                  // callback
                                      NULL,                         // refCon
                                      &gAddedIter                   // notification
                                      );

Когда вы получаете kIOSerialBSDServiceValue (в функции DeviceAdded ()) вверх (используя IORegistryEntryGetParentEntry) в дереве IOKit, пока вашнайдите свой VID и PID.(См. Мой первый фрагмент кода, о котором идет речь.) Если вы не можете найти и дерево устройств закончено, это не ваше устройство.

...