Доступ к устройствам FireWire из приложений

Устройство взаимодействует через интерфейс, семья FireWire обеспечивает, плагины, предоставляющие функции, которые Ваше приложение может вызвать, чтобы связаться с или управлять устройством. В этой главе описываются, как найти устройство FireWire и заставить один или несколько интерфейсов устройства связываться с ним.

Устройство, соответствующее для устройств FireWire

Весь доступ пользовательского уровня устройства начинается с порта Маха для передачи с Набором I/O. Вы получаете порт Маха путем вызывания функции Набора I/O IOMasterPort, как в следующем примере:

kern_return_t   result;
mach_port_t     masterPort;
 
result = IOMasterPort( MACH_PORT_NULL, &masterPort );

Для нахождения устройства Вы создаете соответствующий словарь, описывающий тип устройства или тип устройства, которым Вы интересуетесь. Функция Набора I/O IOServiceMatching создает словарь, соответствующий на данном имени класса, как в этом примере:

CFMutableDictionaryRef  matchingDictionary = IOServiceMatching
                                                ( “IOFireWireDevice” );

В этом примере можно использовать matchingDictionary для нахождения всех устройств в настоящее время представляемыми IOFireWireDevice возражают в Реестре I/O. Таблица 2-1 перечисляет имена классов FireWire, которые можно использовать для создания соответствующего словаря.

Таблица 2-1  имена классов FireWire

Имя класса

Определение

IOFireWireSBP2Target

Модуль в устройстве, которое является целью SBP-2

IOFireWireSBP2LUN

ЛУН в цели SBP-2

IOFireWireAVCUnit

Модуль AV/C в устройстве

IOFireWireUnit

Модуль в устройстве

IOFireWireDevice

Устройство на Шине FireWire

IOFireWireLocalNode

Сам Macintosh

Если Вы не должны выполнять более определенный поиск, словарь IOServiceMatching создает будет достаточно для нахождения всех устройств определенного класса в настоящее время в Реестре I/O.

Если Вы хотите совершенствовать свой поиск, можно добавить свойства к словарю для описания уникального устройства. Как описано в Поддержке Устройства FireWire В ядре, семья IOFireWire помещает свойства, описывающие каждое устройство и модуль в объекты, представляющие их в Реестре I/O. Можно использовать любое из этих свойств для сужения поиска определенного устройства или модуля. Таблица 2-2 показывает свойства, доступные в каждом объекте.

Таблица 2-2  свойства класса FireWire

Имя класса

Ключ Property

Определение

Ввести

IOFireWireDevice

FireWire Node ID

Текущий узел ID

CFNumber

Vendor_ID

Идентификатор поставщика устройства

CFNumber

FireWire Device ROM

В настоящее время читайте, содержание конфигурации ROM (может не содержать все содержание ROM),

CFData

FireWire Vendor Name

Имя поставщика устройства

CFString

FireWire Self IDs

Сам IDs получен от устройства

CFData

FireWire Speed

Текущая рабочая скорость устройства

CFNumber

GUID

Глобально уникальный идентификатор устройства

CFNumber

IOFireWireUnit

Vendor_ID

Идентификатор поставщика устройства

CFNumber

FireWire Vendor Name

Имя поставщика устройства

CFString

GUID

Глобально уникальный идентификатор модуля

CFNumber

Unit_Spec_ID

Спецификация модуля ID для этого модуля

CFNumber

Unit_SW_Version

Версия программного обеспечения Unit модуля

CFNumber

FireWire Product Name

Название продукта устройства

CFString

IOFireWireSBP2Target

Command_Set

Набор команд SBP2

CFNumber

Command_Set_Revision

Версия набора команд SBP2

CFNumber

Unit_Spec_ID

Спецификация модуля ID для провайдера модуля FireWire этой цели SBP-2

CFNumber

Command_Set_Spec_ID

Спецификация набора команд SBP-2 ID

CFNumber

GUID

Глобально уникальный идентификатор для этого устройства

CFNumber

Vendor_ID

Идентификатор поставщика устройства

CFNumber

Device_Type

Тип устройства SBP-2

CFNumber

Firmware_Revision

Версия встроенного микропрограммного обеспечения SBP-2

CFNumber

Unit_SW_Version

Версия программного обеспечения Unit для этого модуля

CFNumber

IOFireWireSBP2LUN

Vendor_ID

Идентификатор поставщика устройства

CFNumber

Command_Set

Набор команд SBP-2

CFNumber

Command_Set_Spec_ID

Спецификация набора команд SBP-2 ID

CFNumber

GUID

Глобально уникальный идентификатор для этого устройства

CFNumber

Device_Type

Тип устройства SBP-2

CFNumber

Firmware_Revision

Версия встроенного микропрограммного обеспечения SBP-2

CFNumber

IOUnit

SBP-2 число ЛУНА

CFNumber

IOFireWireAVCUnit

Unit_Spec_ID

Спецификация модуля ID для этого модуля

CFNumber

Unit_Type

Тип модуля AV/C

CFNumber

Vendor_ID

Идентификатор поставщика устройства

CFNumber

GUID

Глобально уникальный идентификатор для этого устройства

CFNumber

Unit_SW_Version

Версия программного обеспечения Unit для этого модуля

CFNumber

FireWire Product Name

Имя этого продукта

CFString

Для использования этих свойств для соответствия запустите со словаря от IOServiceMatching и используйте Базовые функции Основы для добавления пар ключ/значение свойства к нему. Перечисление 2-1 показывает словарь, соответствующий на объекте IOFireWireUnit с определенным Unit_Spec_ID и Unit_SW_Version значения:

Перечисление 2-1  соответствующий словарь для объекта IOFireWireUnit

CFMutableDictionaryRef  matchingDictionary =
                                    IOServiceMatching(“IOFireWireUnit” );
 
UInt32      value;
CFNumberRef cfValue;
 
value = myFireWireUnitSpecID;
cfValue = CFNumberCreate( kCFAllocatorDefault, kCFNumberSInt32Type, &value );
CFDictionaryAddValue( matchingDictionary, CFSTR( “Unit_Spec_ID” ), cfValue );
CFRelease( cfValue );
 
value = myFireWireUnitSwVersionID;
cfValue = CFNumberCreate( kCFAllocatorDefault, kCFNumberSInt32Type, &value );
CFDictionaryAddValue( matchingDictionary, CFSTR( “Unit_SW_Version” ),
                        cfValue);
CFRelease( cfValue );

Нахождение устройств FireWire

После установки соответствующего словаря, описывающего тип устройства или тип устройства, который Вы ищете, Вы передаете его функции Набора I/O IOServiceGetMatchingServices. Эта функция ищет Реестр I/O объекты, соответствующие свойства в данном словаре, и возвращает итератор, который можно использовать для доступа к каждому:

kern_return_t   result;
io_iterator_t   iterator;
 
result = IOServiceGetMatchingServices( masterPort, matchingDictionary,
    &iterator );

Затем, передайте итератор функции Набора I/O IOIteratorNext, который возвращает ссылку на первый соответствующий объект. Каждый вызов к IOIteratorNext возвращает следующий доступный объект:

io_object_t aDevice;
 
while ( (aDevice = IOIteratorNext( iterator ) ) != 0 ) {
    //get a device interface for the device
}

Можно также использовать функции Набора I/O, чтобы получить замену в горячем режиме устройства и отключить уведомления. Чтобы сделать это, Вы сначала устанавливаете порт уведомлений и добавляете его источник события цикла выполнения к циклу выполнения Вашей программы. Затем вместо вызова IOServiceGetMatchingServices, Вы отправляете соответствующий словарь, который Вы создали ранее к функции Набора I/O IOServiceAddMatchingNotification получить итератор для объектов согласующего устройства и установить запрос уведомления на новое устройство возражают тому соответствию. Функция myServiceMatchingCallback функция, которую Вы предоставляете для итерации по согласующим устройствам и доступу каждого. Перечисление 2-2 показывает, как установить уведомление.

Перечисление 2-2  , Настраивающее устройство, заменяет уведомление в горячем режиме

//global variables
IONotificationPortRef   gNotifyPort;
CFRunLoopSourceRef      gNotifySource;
 
//local variables
io_iterator_t   iterator;
kern_return_t   result;
mach_port_t     masterPort;
CFMutableDictionaryRef  matchingDictionary;
 
//The acquisition of the Mach port and the creation of the matching
//dictionary are not shown here.
gNotifyPort = IONotificationPortCreate( masterPort );
gNotifySource = IONotificationPortGetRunLoopSource( gNotifyPort );
CFRunLoopAddSource( CFRunLoopGetCurrent(), gNotifySource,
    kCFRunLoopDefaultMode );
 
result = IOServiceAddMatchingNotification( gNotifyPort,
    kIOMatchedNotification, matchingDictionary,
    myServiceMatchingCallback, NULL, &iterator );
 
//IOServiceAddMatchingNotification consumes a reference to the
//matching dictionary so if you need to use the dictionary again
//after this call, you must first call CFRetain on it.
 
//Execute your callback function to iterate over the set of matching
//devices already present and to arm the notification for future devices.
myServiceMatchingCallback( NULL, iterator );

Получение интерфейсов устройства FireWire

После того, как Вы получили итератор и использовали его для получения ссылки на каждое согласующее устройство, необходимо получить интерфейс устройства для него. Независимо от которого устройства FireWire соединяют интерфейсом библиотекой, которой Вы хотите пользоваться, Вы сначала получаете сменный интерфейс типа IOCFPlugInInterface. Вы используете устройство io_object_t ссылка Вы добрались от IOIteratorNext и константа kIOFireWireLibTypeID, как в этом примере:

IOCFPlugInInterface**   cfPlugInInterface = 0;
IOReturn                result;
SInt32                  theScore;
 
result = IOCreatePlugInInterfaceForService( aDevice, kIOFireWireLibTypeID,
    kIOCFPlugInInterfaceID, &cfPlugInInterface, &theScore );

Затем Вы используете IOCFPlugInInterface QueryInterface функция для получения определенного устройства соединяет интерфейсом с Вами потребность. Вы передаете его идентификатор интерфейса основного устройства, который Вы хотите использовать, например, kIOFireWireDeviceInterfaceID или kIOFireWireSBP2LibLUNInterfaceID:

IOFireWireLibDeviceRef  fwDeviceInterface = 0;
 
(*cfPlugInInterface)->QueryInterface( cfPlugInInterface, CFUUIDGetUUIDBytes(
    kIOFireWireDeviceInterfaceID ), (void **) fwDeviceInterface );

Существует три версии IOFireWireDeviceInterface, который можно использовать. Каждая версия добавляет новые службы к функциональности предыдущей версии. Обязательно проверьте заголовочные файлы, чтобы удостовериться, что Вы выполняете версию OS X, соответствующего версии IOFireWireDeviceInterface, которую Вы хотите. При попытке получить более позднюю версию IOFireWireDeviceInterface, чем Ваша версия поддержек OS X, QueryInterface функция перестанет работать. Можно, однако, получить более раннюю версию интерфейса, чем в настоящее время поддерживается версией OS X, который Вы выполняете.

Можно также получить экземпляры IOFireWireUnitInterface и IOFireWireNubInterface. Они синонимичны с IOFireWireDeviceInterface и относятся к тому же объекту. Их единственная функция должна предоставить Вам более описательное имя для IOFireWireDeviceInterface при открытии его на модуле или локальном узле.

Когда у Вас есть интерфейс основного устройства в библиотеке, Вы хотите использовать, Вы не должны использовать IOCreatePlugInForService и QueryInterface функции для получения дополнительных интерфейсов, которые обеспечивает библиотека. Каждая библиотека обеспечивает свои собственные функции для получения ее других интерфейсов.

Получение многократных интерфейсов устройства FireWire

Когда Вы открываете устройство или модуль с помощью одного из интерфейса устройства open функции, у Вас есть монопольное соединение с объектом, представляющим то устройство или модуль в ядре. Поскольку open функция открывает не только объект, Вы обращаетесь к нему, но также и объекты, предшествующие ему в штабеле, никакое другое приложение не может тогда открыть то устройство или модуль. Например, если Вы открываете модуль AV/C с IOFireWireAVCLibUnitInterface open функция, Вы автоматически открытие IOFireWireUnit и объекты IOFireWireDevice, а также объект IOFireWireAVCUnit.

Таким образом, если Вы хотите использовать или IOFireWireSBP2Lib или IOFireWireAVCLib в сотрудничестве с IOFireWireLib, необходимо, в действительности, открыть устройство или объект модуля, который уже открыт. Для разрешения этого семья IOFireWire использует понятие ссылки сеанса для обращения к определенному соединению с объектом модуля или устройством.

Ссылка сеанса походит на ключ, позволяющий Вам переопределять эксклюзивность open функция. Если Ваше приложение использовало интерфейс устройства open функция для открытия SBP-2 или модуля AV/C можно использовать GetSessionRef функция (доступный и в IOFireWireAVCLib и в IOFireWireSBP2Lib) для получения IOFireWireSessionRef открыть объекты IOFireWireDevice или IOFireWireUnit. GetSessionRef функция требует указателя на текущий интерфейс устройства, который Вы содержите поэтому, только Ваше приложение может успешно использовать его.

Вы передаете IOFireWireSessionRef к функции IOFireWireDeviceInterface openWithSessionRef, открытие устройства в ядре или объекта модуля. Можно тогда использовать интерфейсы и функции обеих библиотек для передачи с устройством или модулем. Перечисление 2-3 показывает, как использовать экземпляр IOFireWireAVCLibUnitInterface, чтобы открыть модуль AV/C и затем заставить ссылку сеанса открывать устройство для экземпляра IOFireWireDeviceInterface.

Перечисление 2-3  , Добирающееся и использующее ссылку сеанса

IOFireWireSessionRef    session;
 
result = (*avcInterface)->open( avcInterface );
session = (*avcInterface)->getSessionRef( avcInterface );
result = (*fwInterface)->openWithSessionRef( fwInterface, session );

Прежде чем можно будет использовать эти интерфейсы устройства, однако, необходимо сначала найти устройство, которым Вы интересуетесь. Устройство, соответствующее, является процессом использования функций Набора I/O для поиска Реестра I/O определенные устройства (или модули) или типы устройства. Этот раздел предоставляет общую информацию относительно этого процесса, поскольку это применяется к устройствам FireWire. Это предоставляет фрагменты кода для общих задач, таких как поиск Реестра I/O, уведомлений установки для новых устройств и получения интерфейсов основного устройства в каждой библиотеке интерфейса устройства FireWire. Кроме того, в Получении Многократных Интерфейсов Устройства FireWire, это описывает, как использовать IOFireWireDeviceInterface или в сочетании с IOFireWireSBP2LibLUNInterface или в сочетании с IOFireWireAVCLibUnitInterface.