Доступ к устройству HID

Версия 10.5 OS X («Leopard») представляет новый APIs, абстрагирующий текущие сложности использования Набора I/O для передачи с менеджером по HID. Этот APIs позволяет Вам перечислять устройства HID и элементы, получать доступ к их свойствам, регистру для уведомления об обнаружении устройств HID и удалении (замена в горячем режиме и отключение), отправить и получить отчеты устройства, использовать очереди, чтобы заставить уведомление об изменениях значения элемента HID и транзакции использования говорить с устройствами HID. Разработчики приложений, которые должны связаться с устройствами HID, должны считать эту главу сначала.

Эта документация принимает основное понимание материала, содержавшегося в Доступе к Аппаратным средствам Из Приложений. Для определений терминов Набора I/O, использованных в этой документации (таких как соответствие словарей), см. обзор условий Набора I/O и понятий в Доступе к устройствам и главе Набора I/O. Подробное описание спецификации класса HID выходит за рамки этого документа. Для получения дополнительной информации, включая полный список таблиц использования HID, посетите веб-сайт USB в http://www .usb.org/developers/hidpage/.

Устройство, соответствующее и доступ

Менеджер по HID ссылки используется для связи с Набором I/O подсистемы HID. Они создаются при помощи IOHIDManagerCreate функция:

 
// Create HID Manager reference
IOHIDManagerRef IOHIDManagerCreate(
                    CFAllocatorRef  inCFAllocatorRef,   // Allocator to be used during creation
                    IOOptionBits    inOptions);         // options Reserved for future use
 

Первый параметр (allocator) CFAllocator, который будет использоваться при выделении возвращенного IOHIDManagerRef. Последний параметр (options) в настоящее время резервируется для будущего использования. Разработчики должны передать kIOHIDOptionsTypeNone (zero) для этого параметра.

Существует нет IOHIDManagerDestroy (или выпуск, свободный, и т.д.); потому что менеджер по HID ссылка является Базовой ссылкой на объект Основы, CFRelease должен использоваться для избавления от него.

A CFTypeRef может быть проверен, чтобы быть менеджером по HID ссылка путем сравнения ее Базового типа Основы с IOHIDManagerGetTypeID:

Перечисление 2-1  , Проверяющее менеджера по HID ссылка

 
    if (CFGetTypeID(tCFTypeRef) == IOHIDManagerGetTypeID()) {
        // this is a HID Manager reference!
    }
 

Соответствие устройств HID

Один раз менеджер по HID ссылка была создана, она должна быть открыта, прежде чем она сможет использоваться для доступа к устройствам HID, связанным с ним. Для ограничения устройств HID, с которыми менеджер по HID связана ссылка, устанавливает соответствующий словарь (единственные критерии) или массив соответствия словарей (многократные критерии). Функции:

 
// Sets single matching criteria (dictionary) for device enumeration.
void IOHIDManagerSetDeviceMatching(
        IOHIDManagerRef inIOHIDManagerRef,  // HID Manager reference
        CFDictionaryRef inMatchingDictRef); // single dictionary containing device matching criteria.
 
// Sets multiple matching criteria (array of dictionaries) for device enumeration.
void IOHIDManagerSetDeviceMatchingMultiple(
        IOHIDManagerRef inIOHIDManagerRef,  // HID Manager reference
        CFArrayRef      inCFArrayRef);      // array of dictionaries containing device matching criteria.
 

Соответствующие ключи, используемые в словарных статьях, объявляются в <IOKit/hid/IOHIDKeys.h>:

Перечисление 2-2  ключи свойства устройства HID

 
#include <IOKit/hid/IOHIDKeys.h>
 
#define kIOHIDTransportKey                  "Transport"
#define kIOHIDVendorIDKey                   "VendorID"
#define kIOHIDVendorIDSourceKey             "VendorIDSource"
#define kIOHIDProductIDKey                  "ProductID"
#define kIOHIDVersionNumberKey              "VersionNumber"
#define kIOHIDManufacturerKey               "Manufacturer"
#define kIOHIDProductKey                    "Product"
#define kIOHIDSerialNumberKey               "SerialNumber"
#define kIOHIDCountryCodeKey                "CountryCode"
#define kIOHIDLocationIDKey                 "LocationID"
#define kIOHIDDeviceUsageKey                "DeviceUsage"
#define kIOHIDDeviceUsagePageKey            "DeviceUsagePage"
#define kIOHIDDeviceUsagePairsKey           "DeviceUsagePairs"
#define kIOHIDPrimaryUsageKey               "PrimaryUsage"
#define kIOHIDPrimaryUsagePageKey           "PrimaryUsagePage"
#define kIOHIDMaxInputReportSizeKey         "MaxInputReportSize"
#define kIOHIDMaxOutputReportSizeKey        "MaxOutputReportSize"
#define kIOHIDMaxFeatureReportSizeKey       "MaxFeatureReportSize"
#define kIOHIDReportIntervalKey             "ReportInterval"
 

kIOHIDDeviceUsagePairsKey ключ используется для представления массива словарей, содержащих пары ключ/значение, на которые ссылаются kIOHIDDeviceUsageKey и kIOHIDDeviceUsagePageKey. Эти пары использования описывают все наборы типа приложения (способы поведения), определенные устройством HID.

Приложение, заинтересованное только соответствием на критериях, только добавило бы kIOHIDDeviceUsageKey и kIOHIDDeviceUsagePageKey ключи к соответствующему словарю. Если это интересуется устройством HID, имеющим многократные способы поведения, приложение вместо этого добавило бы массив словарей, на которые ссылаются kIOHIDDeviceUsagePairsKey к их соответствию словаря.

Это эквивалентно передаче массива словарей каждый содержащий две записи с ключами kIOHIDDeviceUsagePageKey и kIOHIDDeviceUsageKey к IOHIDManagerSetDeviceMatchingMultiple.

Передача a NULL словарь приведет ко всем перечисляемым устройствам. Любые последующие вызовы заставят менеджера по HID выпускать ранее перечисленные устройства и перезапускать процесс перечисления с помощью пересмотренных критериев.

Перечисление 2-3  , Соответствующее против единственного набора (словарь) свойств

 
// function to create matching dictionary
static CFMutableDictionaryRef hu_CreateDeviceMatchingDictionary(UInt32 inUsagePage, UInt32 inUsage)
{
    // create a dictionary to add usage page/usages to
    CFMutableDictionaryRef result = CFDictionaryCreateMutable(
        kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
    if (result) {
        if (inUsagePage) {
            // Add key for device type to refine the matching dictionary.
            CFNumberRef pageCFNumberRef = CFNumberCreate(
                            kCFAllocatorDefault, kCFNumberIntType, &inUsagePage);
            if (pageCFNumberRef) {
                CFDictionarySetValue(result,
                        CFSTR(kIOHIDDeviceUsagePageKey), pageCFNumberRef);
                CFRelease(pageCFNumberRef);
 
                // note: the usage is only valid if the usage page is also defined
                if (inUsage) {
                    CFNumberRef usageCFNumberRef = CFNumberCreate(
                                    kCFAllocatorDefault, kCFNumberIntType, &inUsage);
                    if (usageCFNumberRef) {
                        CFDictionarySetValue(result,
                            CFSTR(kIOHIDDeviceUsageKey), usageCFNumberRef);
                        CFRelease(usageCFNumberRef);
                    } else {
                        fprintf(stderr, "%s: CFNumberCreate(usage) failed.", __PRETTY_FUNCTION__);
                    }
                }
            } else {
                fprintf(stderr, "%s: CFNumberCreate(usage page) failed.", __PRETTY_FUNCTION__);
            }
        }
    } else {
        fprintf(stderr, "%s: CFDictionaryCreateMutable failed.", __PRETTY_FUNCTION__);
    }
    return result;
}   // hu_CreateDeviceMatchingDictionary
 
// Create a matching dictionary
CFDictionaryRef matchingCFDictRef =
                    hu_CreateDeviceMatchingDictionary(kHIDPage_GenericDesktop, kHIDUsage_GD_Keyboard);
if (matchingCFDictRef) {
    // set the HID device matching dictionary
    IOHIDManagerSetDeviceMatching(managerRef, matchingCFDictRef);
} else {
    fprintf(stderr, "%s: hu_CreateDeviceMatchingDictionary failed.", __PRETTY_FUNCTION__);
}
 

Перечисление 2-4  , Соответствующее против многократных наборов (массивы словарей) свойств

 
// create an array of matching dictionaries
CFArrayRef matchingCFArrayRef = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks);
if (matchingCFArrayRef) {
    // create a device matching dictionary for joysticks
    CFDictionaryRef matchingCFDictRef =
                        hu_CreateDeviceMatchingDictionary(kHIDPage_GenericDesktop, kHIDUsage_GD_Joystick);
    if (matchingCFDictRef) {
        // add it to the matching array
        CFArrayAppendValue(matchingCFArrayRef, matchingCFDictRef);
        CFRelease(matchingCFDictRef); // and release it
    } else {
        fprintf(stderr, "%s: hu_CreateDeviceMatchingDictionary(joystick) failed.", __PRETTY_FUNCTION__);
    }
 
    // create a device matching dictionary for game pads
    matchingCFDictRef = hu_CreateDeviceMatchingDictionary(kHIDPage_GenericDesktop, kHIDUsage_GD_GamePad);
    if (matchingCFDictRef) {
        // add it to the matching array
        CFArrayAppendValue(matchingCFArrayRef, matchingCFDictRef);
        CFRelease(matchingCFDictRef); // and release it
    } else {
        fprintf(stderr, "%s: hu_CreateDeviceMatchingDictionary(game pad) failed.", __PRETTY_FUNCTION__);
    }
} else {
    fprintf(stderr, "%s: CFArrayCreateMutable failed.", __PRETTY_FUNCTION__);
}
 
-- EITHER --
 
// create a dictionary for the kIOHIDDeviceUsagePairsKey entry
matchingCFDictRef = CFDictionaryCreateMutable(
    kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
 
// add the matching array to it
CFDictionarySetValue(matchingCFDictRef, CFSTR(kIOHIDDeviceUsagePairsKey), matchingCFArrayRef);
// release the matching array
CFRelease(matchingCFArrayRef);
 
// set the HID device matching dictionary
IOHIDManagerSetDeviceMatching(managerRef, matchingCFDictRef);
 
// and then release it
CFRelease(matchingCFDictRef);
 
-- OR --
 
// set the HID device matching array
IOHIDManagerSetDeviceMatchingMultiple(managerRef, matchingCFArrayRef);
 
// and then release it
CFRelease(matchingCFArrayRef);
 

Прежде, чем открыть менеджера по HID ссылка может быть желательно зарегистрировать подпрограммы, которые вызовут, когда (соответствующие) устройства подключены или отключены.

 
// Register device matching callback routine
// This routine will be called when a new (matching) device is connected.
void IOHIDManagerRegisterDeviceMatchingCallback(
        IOHIDManagerRef     inIOHIDManagerRef,      // HID Manager reference
        IOHIDDeviceCallback inIOHIDDeviceCallback,  // Pointer to the callback routine
        void *              inContext);             // Pointer to be passed to the callback
 
// Registers a routine to be called when any currently enumerated device is removed.
// This routine will be called when a (matching) device is disconnected.
void IOHIDManagerRegisterDeviceRemovalCallback(
        IOHIDManagerRef     inIOHIDManagerRef,      // HID Manager reference
        IOHIDDeviceCallback inIOHIDDeviceCallback,  // Pointer to the callback routine
        void *              inContext);             // Pointer to be passed to the callback
 

  Примеры перечисления 2-5 устройства HID, соответствующего и подпрограмм обратного вызова удаления

 
// this will be called when the HID Manager matches a new (hot plugged) HID device
static void Handle_DeviceMatchingCallback(
            void *          inContext,       // context from IOHIDManagerRegisterDeviceMatchingCallback
            IOReturn        inResult,        // the result of the matching operation
            void *          inSender,        // the IOHIDManagerRef for the new device
            IOHIDDeviceRef  inIOHIDDeviceRef // the new HID device
) {
    printf("%s(context: %p, result: %p, sender: %p, device: %p).\n",
        __PRETTY_FUNCTION__, inContext, (void *) inResult, inSender, (void*) inIOHIDDeviceRef);
}   // Handle_DeviceMatchingCallback
 
// this will be called when a HID device is removed (unplugged)
static void Handle_RemovalCallback(
                void *         inContext,       // context from IOHIDManagerRegisterDeviceMatchingCallback
                IOReturn       inResult,        // the result of the removing operation
                void *         inSender,        // the IOHIDManagerRef for the device being removed
                IOHIDDeviceRef inIOHIDDeviceRef // the removed HID device
) {
    printf("%s(context: %p, result: %p, sender: %p, device: %p).\n",
        __PRETTY_FUNCTION__, inContext, (void *) inResult, inSender, (void*) inIOHIDDeviceRef);
}   // Handle_RemovalCallback
 

inResult параметр обратного вызова содержит ошибочный результат работы, вызывающей обратный вызов. Необходимо проверить возвращаемое значение, и если это является ненулевым, обработайте отказ соответственно.

Планирование менеджера по HID на цикле выполнения

Перед менеджером по HID подпрограммы обратного вызова могут быть диспетчеризированы менеджер по HID, ссылка должна сначала быть запланирована с циклом выполнения:

 
// Schedule HID Manager with run loop
void IOHIDManagerScheduleWithRunLoop(
        IOHIDManagerRef inIOHIDManagerRef,  // HID Manager reference
        CFRunLoopRef    inRunLoop,          // Run loop to be used when scheduling asynchronous activity
        CFStringRef     inRunLoopMode);     // Run loop mode to be used when scheduling
 

Это формально связывает менеджера по HID с циклом выполнения клиента. Это расписание распространит ко всем устройствам HID, в настоящее время перечисляющимся и к новым устройствам HID, поскольку они являются соответствующими менеджером по HID.

Перечисление 2-6  Планируя менеджера по HID с текущим циклом выполнения

 
        IOHIDManagerScheduleWithRunLoop(inIOHIDManagerRef, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode);
 

Существует соответствующая функция, чтобы не запланировать менеджера по HID ссылка от цикла выполнения:

 
void IOHIDManagerUnscheduleFromRunLoop(
        IOHIDManagerRef inIOHIDManagerRef,  // HID Manager reference
        CFRunLoopRef    inRunLoop,          // Run loop to be used when unscheduling asynchronous activity
        CFStringRef     inRunLoopMode);     // Run loop mode to be used when unscheduling
 

Перечисление 2-7  Не планируя менеджера по HID от цикла выполнения

 
IOHIDManagerUnscheduleFromRunLoop(managerRef, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode);
 

Теперь мы готовы открыть менеджера по HID ссылка.

 
// Open a HID Manager reference
IOReturn IOHIDManagerOpen(
            IOHIDManagerRef inIOHIDManagerRef,  // HID Manager reference
            IOOptionBits    inOptions);         // Option bits
 

Это откроет все соответствие устройства HID. Это возвращается kIOReturnSuccess в случае успеха. В настоящее время единственные допустимые опции (второй параметр) kIOHIDOptionsTypeNone или kIOHIDOptionsTypeSeizeDevice (который вызывает эксклюзивный доступ для всех согласующих устройств).

Если будет устройство, соответствующее подпрограмму обратного вызова, зарегистрированную, когда IOHIDManagerOpen вызовут тогда, то эту подпрограмму вызовут, как только для каждого устройства HID в настоящее время соединялся, который соответствует текущие критерии соответствия. Эту подпрограмму также вызовут, когда новые устройства, соответствующие текущие критерии соответствия, будут подключены к компьютеру (но только если менеджер по HID ссылка все еще открыт).

Перечисление 2-8  , Открытие ссылку HID Manager

 
// open it
IOReturn tIOReturn = IOHIDManagerOpen(managerRef, kIOHIDOptionsTypeNone);
 

Один раз менеджер по HID ссылка была открыта, она может быть закрыта при помощи функции IOHIDManagerClose:

 
// Closes the IOHIDManager
IOReturn IOHIDManagerClose(IOHIDManagerRef inIOHIDManagerRef,  // HID Manager reference
                            IOOptionBits    inOptions);        // Option bits
 

Это также закроет все в настоящее время перечисляющиеся устройства. Опции распространены к устройству HID близкая функция.

Регистрация обратных вызовов значения

Как только соединение с менеджером по HID открыто, разработчики могут зарегистрировать подпрограмму, которую вызовут, когда изменяются входные значения:

 
// Register a routine to be called when an input value changes
void IOHIDManagerRegisterInputValueCallback(
        IOHIDManagerRef     inIOHIDManagerRef,  // HID Manager reference
        IOHIDValueCallback  inCallback,         // Pointer to the callback routine
        void *              inContext);         // Pointer to be passed to the callback
 

Когда значение HID любого элемента типа kIOHIDElementTypeInput изменит для всего соответствия устройства HID, зарегистрированную подпрограмму обратного вызова вызовут.

См. Перечисление 2-6 для получения дополнительной информации.

Перечисление 2-9  , Регистрирующееся для обратного вызова входного значения

 
IOHIDManagerRegisterInputValueCallback(managerRef, Handle_IOHIDInputValueCallback, context);
 

Когда входное значение изменится для любого входного элемента для всех согласующих устройств, эту подпрограмму вызовут.

  Подпрограмма обратного вызова входного значения перечисления 2-10 В качестве примера

 
static void Handle_IOHIDInputValueCallback(
                void *          inContext,      // context from IOHIDManagerRegisterInputValueCallback
                IOReturn        inResult,       // completion result for the input value operation
                void *          inSender,       // the IOHIDManagerRef
                IOHIDValueRef   inIOHIDValueRef // the new element value
) {
    printf("%s(context: %p, result: %p, sender: %p, value: %p).\n",
        __PRETTY_FUNCTION__, inContext, (void *) inResult, inSender, (void*) inIOHIDValueRef);
}   // Handle_IOHIDInputValueCallback
 

inResult параметр обратного вызова содержит ошибочный результат работы, вызывающей обратный вызов. Необходимо проверить возвращаемое значение, и если это является ненулевым, обработайте отказ соответственно.

void IOHIDManagerSetInputValueMatching(
        IOHIDManagerRef inIOHIDManagerRef,  // HID Manager reference
        CFDictionaryRef inMatchingDictRef); // single dictionary containing
                                            // element matching criteria.
 
// Sets multiple matching criteria (array of dictionaries)
// for the input value callback.
void IOHIDManagerSetInputValueMatchingMultiple(
        IOHIDManagerRef inIOHIDManagerRef,  // HID Manager reference
        CFArrayRef      inCFArrayRef);      // array of dictionaries containing
                                            // element matching criteria.

Соответствующие ключи для элементов HID снабжаются префиксом kIOHIDElement. Они объявляются в <IOKit/hid/IOHIDKeys.h>. См. Перечисление 2-31 для получения дополнительной информации.

IOHIDManagerGetProperty и IOHIDManagerSetProperty функции доступны для доступа к свойствам менеджера по HID:

 
// Obtains a property of a HIDManagerRef
CFTypeRef IOHIDManagerGetProperty(
            IOHIDManagerRef inIOHIDManagerRef,  // HID Manager reference
            CFStringRef     inKeyCFStringRef);  // CFStringRef for the key
 
// Sets a property for a HIDManagerRef
void IOHIDManagerSetProperty(
            IOHIDManagerRef inIOHIDManagerRef,  // HID Manager reference
            CFStringRef     inKeyCFStringRef,   // CFStringRef for the key
            CFTypeRef       inValueCFTypeRef);  // the HID value for the property
 

В настоящее время нет никаких свойств HID Manager по умолчанию, установленных системой. Однако, так как свойства HID Manager распространены ко всем устройствам HID, поскольку они перечисляются (соответствовал), это могло бы быть convient способом установить значения свойства устройства HID по умолчанию.

  Свойства Listing 2-11 Accessing HID Manager

 
CFTypeRef tCFTypeRef = IOHIDManagerGetProperty(managerRef, key);
IOHIDManagerSetProperty(managerRef, key, tCFTypeRef);
 

Для определения, что устройства соответствуют текущим критериям соответствия, используют IOHIDManagerCopyDevices:

 
CFSetRef IOHIDManagerCopyDevices(IOHIDManagerRef inIOHIDManagerRef);    // HID Manager reference
 

Параметр является менеджером по HID ссылка. Этот вызов возвращает Базовый набор Основы (CFSetRef) из IOHIDDeviceRef объекты.

Перечисление 2-12  , Получающее набор соответствия ссылок устройства HID

 
CFSetRef tCFSetRef = IOHIDManagerCopyDevices(managerRef);
 

Ссылки устройства HID в возвращенном наборе могут быть получены при помощи CFSetGetValues функционируйте или выполненный с помощью итераций при помощи CFSetApplyFunction функция.

Функции устройства HID

A CFTypeRef объект может быть проверен, чтобы быть ссылкой устройства HID путем сравнения ее Базового типа Основы с IOHIDDeviceGetTypeID:

Перечисление 2-13  , Проверяющее ссылку устройства HID

 
    if (CFGetTypeID(tCFTypeRef) == IOHIDDeviceGetTypeID()) {
        // this is a valid HID device reference
    }
 

Как только у Вас есть допустимое устройство HID, ссылаются IOHIDDeviceGetProperty функция может использоваться для доступа к ее свойствам (производитель, поставщик, идентификаторы продукта, и т.д.) использование ключей устройства HID, определенных в <IOKit/HID/IOHIDKeys.h>. См. Перечисление 2-2 для получения дополнительной информации.

  Примеры перечисления 2-14 получения свойств устройства HID

 
// Get a HID device's transport (string)
CFStringRef IOHIDDevice_GetTransport(IOHIDDeviceRef inIOHIDDeviceRef)
{
    return IOHIDDeviceGetProperty(inIOHIDDeviceRef, CFSTR(kIOHIDTransportKey));
}
 
// function to get a long device property
// returns FALSE if the property isn't found or can't be converted to a long
static Boolean IOHIDDevice_GetLongProperty(
    IOHIDDeviceRef inDeviceRef,     // the HID device reference
    CFStringRef inKey,              // the kIOHIDDevice key (as a CFString)
    long * outValue)                // address where to return the output value
{
    Boolean result = FALSE;
 
    CFTypeRef tCFTypeRef = IOHIDDeviceGetProperty(inDeviceRef, inKey);
    if (tCFTypeRef) {
        // if this is a number
        if (CFNumberGetTypeID() == CFGetTypeID(tCFTypeRef)) {
            // get its value
            result = CFNumberGetValue((CFNumberRef) tCFTypeRef, kCFNumberSInt32Type, outValue);
        }
    }
    return result;
}   // IOHIDDevice_GetLongProperty
 
// Get a HID device's vendor ID (long)
long IOHIDDevice_GetVendorID(IOHIDDeviceRef inIOHIDDeviceRef)
{
    long result = 0;
    (void) IOHIDDevice_GetLongProperty(inIOHIDDeviceRef, CFSTR(kIOHIDVendorIDKey), &result);
    return result;
} // IOHIDDevice_GetVendorID
 
// Get a HID device's product ID (long)
long IOHIDDevice_GetProductID(IOHIDDeviceRef inIOHIDDeviceRef)
{
    long result = 0;
    (void) IOHIDDevice_GetLongProperty(inIOHIDDeviceRef, CFSTR(kIOHIDProductIDKey), &result);
    return result;
} // IOHIDDevice_GetProductID
 

Определение пригодности

Существует функция удобства, которая отсканирует элементы набора приложения устройства, чтобы определить, соответствует ли устройство указанной странице использования и использованию:

 
Boolean IOHIDDeviceConformsTo(IOHIDDeviceRef   inIOHIDDeviceRef,  // IOHIDDeviceRef for the HID device
                                uint32_t        inUsagePage,      // the usage page to test conformance with
                                uint32_t        inUsage);         // the usage to test conformance with
 

Некоторые примеры пар использования набора приложения:

  • usagePage = kHIDPage_GenericDesktop, использование = kHIDUsage_GD_Mouse

  • usagePage = kHIDPage_GenericDesktop, использование = kHIDUsage_GD_Keyboard

Прежде чем можно будет связаться с устройством HID, оно должно быть открыто; Открыл ссылки устройства HID должны быть закрыты, когда связь завершена. Вот функции, чтобы открыть и закрыть ссылку устройства HID:

 
IOReturn IOHIDDeviceOpen(IOHIDDeviceRef  inIOHIDDeviceRef, // IOHIDDeviceRef for the HID device
                          IOOptionBits    inOptions);      // Option bits to be sent down to the HID device
IOReturn IOHIDDeviceClose(IOHIDDeviceRef  IOHIDDeviceRef,  // IOHIDDeviceRef for the HID device
                          IOOptionBits    inOptions);      // Option bits to be sent down to the HID device
 

На IOHIDDeviceOpen разработчики вызова могут передать kIOHIDOptionsTypeNone или kIOHIDOptionsTypeSeizeDevice опция запросить эксклюзивный доступ к устройству HID. Оба возврата функций kIOReturnSuccess в случае успеха.

Получение элементов для устройства

Для получения элементов HID, связанных с определенным устройством, используют IOHIDDeviceCopyMatchingElements функция:

 
// return the HID elements that match the criteria contained in the matching dictionary
CFArrayRef IOHIDDeviceCopyMatchingElements(
                IOHIDDeviceRef  inIOHIDDeviceRef,       // IOHIDDeviceRef for the HID device
                CFDictionaryRef inMatchingCFDictRef,    // the matching dictionary
                IOOptionBits    inOptions);             // Option bits
 

Первый параметр является менеджером по HID ссылка. Второй параметр является соответствующим словарем (который может быть NULL возвратить все элементы). Третий параметр содержит любые биты опции (в настоящее время неиспользованный, передача kIOHIDOptionsTypeNone). Этот API возвращает a CFArrayRef объектный содержащий IOHIDElementRef объекты. Разработчики могут тогда использовать CFArrayGetValueAtIndex функция для получения определенного IOHIDElementRef объект, CFArrayGetValues получать все IOHIDElementRef объекты или CFSetApplyFunction выполнить итерации всех IOHIDElementRef объекты в этом массиве.

Соответствующие ключи для элементов HID снабжаются префиксом kIOHIDElement. Они объявляются в <IOKit/hid/IOHIDKeys.h>. См. Перечисление 2-31 для получения дополнительной информации.

Перечисление 2-15  примеры IOHIDDeviceCopyMatchingElements

 
// to return all elements for a device
CFArrayRef elementCFArrayRef = IOHIDDeviceCopyMatchingElements(deviceRef, NULL, kIOHIDOptionsTypeNone);
 
// to return all elements with usage page keyboard
 
// create a dictionary to add element properties to
CFMutableDictionaryRef tCFDictRef = CFDictionaryCreateMutable(
    kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
if (tCFDictRef) {
    // Add key for element usage page to matching dictionary
    int usagePage = kHIDUsage_GD_Keyboard;
    CFNumberRef pageCFNumberRef = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &usagePage);
    if (pageCFNumberRef) {
        CFDictionarySetValue(tCFDictRef, CFSTR(kIOHIDElementUsagePageKey), pageCFNumberRef);
        CFRelease(pageCFNumberRef);
    } else {
        fprintf(stderr, "%s: CFNumberCreate(usage page) failed.", __PRETTY_FUNCTION__);
    }
} else {
    fprintf(stderr, "%s: CFDictionaryCreateMutable failed.", __PRETTY_FUNCTION__);
}
 
if (tCFDictRef) {
    CFArrayRef elementCFArrayRef = IOHIDDeviceCopyMatchingElements(
        deviceRef, tCFDictRef, kIOHIDOptionsTypeNone);
    CFRelease(tCFDictRef);
}
 

Регистрация для отключает уведомления

Обратные вызовы могут быть зарегистрированы, который вызовут, когда устройство HID будет отключено, когда входные значения изменяются, когда введенные отчеты получены, или, когда асинхронный получают и устанавливают значение и завершенные функции отчета. (Эти обратные вызовы документируются ниже.), Прежде чем эти обратные вызовы устройства HID диспетчеризируются, однако, устройство HID должно быть запланировано с циклом выполнения.

Перечисление 2-16  Планируя устройство HID с циклом выполнения

 
    IOHIDDeviceScheduleWithRunLoop(inIOHIDDeviceRef, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode);
 

Существует соответствующая функция, чтобы не запланировать устройство HID от цикла выполнения:

Перечисление 2-17  Не планируя устройство HID от цикла выполнения

 
IOHIDDeviceUnscheduleFromRunLoop(deviceRef, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode);
 

Зарегистрировать подпрограмму, которую вызовут, когда демонтировано устройство HID:

Перечисление 2-18  , Регистрирующее подпрограмму обратного вызова удаления устройства HID

 
IOHIDDeviceRegisterRemovalCallback(deviceRef, Handle_IOHIDDeviceRemovalCallback, context);
 

Перечисление 2-19  подпрограмма обратного вызова удаления устройства HID

 
static void Handle_IOHIDDeviceRemovalCallback(
                void *      inContext,  // context from IOHIDDeviceRegisterRemovalCallback
                IOReturn    inResult,   // the result of the removal
                void *      inSender    // IOHIDDeviceRef for the HID device being removed
) {
    printf("%s(context: %p, result: %p, sender: %p).\n",
        __PRETTY_FUNCTION__, inContext, (void *) inResult, inSender);
}   // Handle_IOHIDDeviceRemovalCallback
 

inResult параметр обратного вызова содержит ошибочный результат работы, вызывающей обратный вызов. Необходимо проверить возвращаемое значение, и если это является ненулевым, обработайте отказ соответственно.

Регистрация для уведомлений изменения значения

Зарегистрировать подпрограмму, которую вызовут, когда входное значение изменяется устройством HID:

Перечисление 2-20  , Регистрирующее подпрограмму обратного вызова входного значения устройства HID

 
IOHIDDeviceRegisterInputValueCallback(deviceRef, Handle_IOHIDDeviceInputValueCallback, context);
 

Первый параметр является ссылкой устройства HID. Второй параметр является подпрограммой обратного вызова. Третий параметр является пользовательским параметром контекста, передающимся той подпрограмме обратного вызова.

Перечисление 2-21  подпрограмма обратного вызова входного значения устройства HID

 
static void Handle_IOHIDDeviceInputValueCallback(
                void *          inContext,      // context from IOHIDDeviceRegisterInputValueCallback
                IOReturn        inResult,       // completion result for the input value operation
                void *          inSender,       // IOHIDDeviceRef of the device this element is from
                IOHIDValueRef   inIOHIDValueRef // the new element value
) {
    printf("%s(context: %p, result: %p, sender: %p, value: %p).\n",
        __PRETTY_FUNCTION__, inContext, (void *) inResult, inSender, (void*) inIOHIDValueRef);
}   // Handle_IOHIDDeviceInputValueCallback
 

inResult параметр обратного вызова содержит ошибочный результат работы, вызывающей обратный вызов. Необходимо проверить возвращаемое значение, и если это является ненулевым, обработайте отказ соответственно.

Для ограничения изменений значения элемента, о которых сообщает этот обратный вызов определенным элементам HID, словарь соответствия элемента (единственные критерии) или массив соответствия словарей (многократные критерии) может быть установлен с помощью IOHIDDeviceSetInputValueMatching или IOHIDDeviceSetInputValueMatchingMultiple функции.

// Sets single element matching criteria (dictionary) for the
// input value callback.
void IOHIDDeviceSetInputValueMatching(
        IOHIDDeviceRef  inIOHIDDeviceRef,    // IOHIDDeviceRef for the HID device
        CFDictionaryRef inMatchingDictRef);  // single dictionary containing
                                             // element matching criteria.
 
// Sets multiple matching criteria (array of dictionaries) for the
// input value callback.
void IOHIDDeviceSetInputValueMatchingMultiple(
        IOHIDDeviceRef  inIOHIDDeviceRef,   // IOHIDDeviceRef for the HID device
        CFArrayRef      inCFArrayRef);      // array of dictionaries containing
                                            // element matching criteria.

Соответствующие ключи для элементов HID снабжаются префиксом kIOHIDElement. Они объявляются в <IOKit/hid/IOHIDKeys.h>. См. Перечисление 2-31 для получения дополнительной информации.

Регистрация для входных уведомлений отчета

Зарегистрировать подпрограмму, которую вызовут, когда входной отчет выпущен устройством HID:

Перечисление 2-22  , Регистрирующее ввод устройства HID, сообщает о подпрограмме обратного вызова

 
CFIndex reportSize = 64;    // note: this should be greater than or equal to the size of the report
uint8_t report = malloc(reportSize);
IOHIDDeviceRegisterInputReportCallback(deviceRef,           // IOHIDDeviceRef for the HID device
                                        report,             // pointer to the report data (uint8_t's)
                                        reportSize,         // number of bytes in the report (CFIndex)
                                        Handle_IOHIDDeviceIOHIDReportCallback,   // the callback routine
                                        context);           // context passed to callback
 

Первый параметр является ссылкой устройства HID. Вторым является адрес, где сохранить входной отчет. Третий параметр является адресом подпрограммы обратного вызова. Последний параметр является пользовательским параметром контекста, передающимся той подпрограмме обратного вызова.

Буфер отчета должен быть достаточно большим для хранения самого большого отчета, который, как могут ожидать, будет получен от устройства HID. Этот размер может быть получен путем передачи kIOHIDMaxInputReportSizeKey как ключ к IOHIDDeviceGetProperty.

Перечисление 2-23  входная подпрограмма обратного вызова отчета устройства HID

 
static void Handle_IOHIDDeviceIOHIDReportCallback(
                void *          inContext,          // context from IOHIDDeviceRegisterInputReportCallback
                IOReturn        inResult,           // completion result for the input report operation
                void *          inSender,           // IOHIDDeviceRef of the device this report is from
                IOHIDReportType inType,             // the report type
                uint32_t        inReportID,         // the report ID
                uint8_t *       inReport,           // pointer to the report data
                CFIndex         InReportLength)     // the actual size of the input report
{
    printf("%s(context: %p, result: %p, sender: %p," \
            "type: %d, id: %p, report: %p, length: %d).\n",
        __PRETTY_FUNCTION__, inContext, (void *) inResult, inSender,
        (long) inType, inReportID, inReport, inReportLength);
}   // Handle_IOHIDDeviceIOHIDReportCallback
 

inResult параметр обратного вызова содержит ошибочный результат работы, вызывающей обратный вызов. Необходимо проверить возвращаемое значение, и если это является ненулевым, обработайте отказ соответственно.

Получение и установка значений вывода или функции

Для установки значения HID единственного вывода или функции вводят элемент IOHIDDeviceSetValue (синхронный) или IOHIDDeviceSetValueWithCallback могут использоваться (асинхронные) функции. (для установки многократных значений рассматривают использование отчетов или транзакций):

 
// synchronous
IOReturn  tIOReturn = IOHIDDeviceSetValue(
                            deviceRef,      // IOHIDDeviceRef for the HID device
                            elementRef,     // IOHIDElementRef for the HID element
                            valueRef);      // IOHIDValueRef for the HID element's new value
 
// asynchronous
IOReturn  tIOReturn = IOHIDDeviceSetValueWithCallback(
                            deviceRef,          // IOHIDDeviceRef for the HID device
                            elementRef,         // IOHIDElementRef for the HID element
                            valueRef,           // IOHIDValueRef for the HID element's new value
                            tCFTimeInterval,    // timeout duration
                            Handle_IOHIDDeviceSetValueCallback,  // the callback routine
                            context);           // context passed to callback
 

Первый параметр является ссылкой устройства HID. Второй является ссылка на элемент HID. Третий параметр является ссылкой значения HID. Для асинхронной версии четвертый параметр является тайм-аутом, пятый параметр является подпрограммой обратного вызова, и последний параметр является указателем контекста, передающимся той подпрограмме обратного вызова.

Перечисление 2-24  подпрограмма обратного вызова значения набора устройства HID

 
static void Handle_IOHIDDeviceSetValueCallback(
                void *          inContext,          // context from IOHIDDeviceSetValueWithCallback
                IOReturn        inResult,           // completion result for the set value operation
                void *          inSender,           // IOHIDDeviceRef of the device
                IOHIDValueRef   inIOHIDValueRef)    // the HID element value
{
    printf("%s(context: %p, result: %p, sender: %p, value: %p).\n",
        __PRETTY_FUNCTION__, inContext, (void *) inResult, inSender, inIOHIDValueRef);
}   // Handle_IOHIDDeviceSetValueCallback
 

inResult параметр обратного вызова содержит ошибочный результат работы, вызывающей обратный вызов. Необходимо проверить возвращаемое значение, и если это является ненулевым, обработайте отказ соответственно.

Получить значение HID единственного элемента IOHIDDeviceGetValue (синхронный) или IOHIDDeviceGetValueWithCallback могут использоваться (асинхронные) функции. (Для получения многократных значений рассматривают использование отчетов или транзакций.) Для входных элементов типа синхронная функция сразу возвращается; поскольку функция вводит элементы, которые она блокирует, пока получить отчет значения не был выпущен к устройству HID.

 
// synchronous
IOReturn  tIOReturn = IOHIDDeviceGetValue(
                            deviceRef,  // IOHIDDeviceRef for the HID device
                            elementRef, // IOHIDElementRef for the HID element
                            valueRef);  // IOHIDValueRef for the HID element's new value
 
// asynchronous
IOReturn  tIOReturn = IOHIDDeviceGetValueWithCallback(
                            deviceRef,          // IOHIDDeviceRef for the HID device
                            elementRef,         // IOHIDElementRef for the HID element
                            valueRef,           // IOHIDValueRef for the HID element's new value
                            tCFTimeInterval,    // timeout duration
                            Handle_IOHIDDeviceGetValueCallback,  // the callback routine
                            context);           // context passed to callback
 

Для обеих из этих функций первый параметр является ссылкой устройства HID. Второй является ссылка на элемент HID. Третий параметр является ссылкой значения HID. Для асинхронной версии четвертый параметр является тайм-аутом, пятый параметр является подпрограммой обратного вызова, и последний параметр является указателем контекста, передающимся той подпрограмме обратного вызова.

Перечисление 2-25  устройство HID получает подпрограмму обратного вызова значения

 
static void Handle_IOHIDDeviceGetValueCallback(
                void *          inContext,          // context from IOHIDDeviceGetValueWithCallback
                IOReturn        inResult,           // completion result for the get value operation
                void *          inSender,           // IOHIDDeviceRef of the device
                IOHIDValueRef   inIOHIDValueRef)    // the HID element value
{
    printf("%s(context: %p, result: %p, sender: %p, value: %p).\n",
        __PRETTY_FUNCTION__, inContext, (void *) inResult, inSender, inIOHIDValueRef);
}   // Handle_IOHIDDeviceGetValueCallback
 

inResult параметр обратного вызова содержит ошибочный результат работы, вызывающей обратный вызов. Необходимо проверить возвращаемое значение, и если это является ненулевым, обработайте отказ соответственно.

Получение и установка отчетов HID

Данные USB передаются и от устройств HID packetized в отчеты. Эти отчеты состоят из одного или более полей элемента, обычно содержавшихся в иерархии наборов. Разработчики, понимающие, как элементы упаковываются в отчеты, могут использовать IOHIDDeviceGetReport, IOHIDDeviceGetReportWithCallback, IOHIDDeviceSetReport, и IOHIDDeviceSetReportWithCallback функции для разговора непосредственно с устройствами HID. Разработчики, незнакомые с тем, как отчеты HID создаются, могут использовать функции транзакции HID. Посмотрите Функции Транзакции HID для получения дополнительной информации.

Для отправки отчета в устройство HID (синхронный) IOHIDDeviceSetReport или IOHIDDeviceSetReportWithCallback (асинхронные) функции должны использоваться:

Перечисление 2-26  , отправляющее отчет HID

 
CFIndex reportSize = 64;
uint8_t report = malloc(reportSize);
 
// synchronous
IOReturn  tIOReturn = IOHIDDeviceSetReport(
                            deviceRef,          // IOHIDDeviceRef for the HID device
                            tIOHIDReportType,   // IOHIDReportType for the report
                            reportID,           // CFIndex for the report ID
                            report,             // address of report buffer
                            reportLength);      // length of the report
 
// asynchronous
IOReturn  tIOReturn = IOHIDDeviceSetReportWithCallback(
                            deviceRef,          // IOHIDDeviceRef for the HID device
                            tIOHIDReportType,   // IOHIDReportType for the report
                            reportID,           // CFIndex for the report ID
                            report,             // address of report buffer
                            reportLength,       // length of the report
                            tCFTimeInterval,    // timeout duration
                            Handle_IOHIDDeviceSetReportCallback,  // the callback routine
                            context);           // context passed to callback
 

Для обеих из этих функций первый параметр является ссылкой устройства HID. Второй параметр IOHIDReportType объект для отчета. Третий параметр является идентификатором отчета. Четвертый параметр является адресом буфера отчета. Пятый параметр является размером отправляемого отчета. Для асинхронной версии шестой параметр является тайм-аутом, седьмой параметр является подпрограммой обратного вызова, и последний параметр является указателем контекста, передающимся той подпрограмме обратного вызова:

Перечисление 2-27  подпрограмма обратного вызова отчета набора устройства HID

 
static void Handle_IOHIDDeviceSetReportCallback(
                void *          inContext,          // context from IOHIDDeviceSetReportWithCallback
                IOReturn        inResult,           // completion result for the set value operation
                void *          inSender,           // IOHIDDeviceRef of the device this report is from
                IOHIDReportType inIOHIDReportType,  // the report type
                uint32_t        inReportID,         // the report ID
                uint8_t*        inReport,           // the address of the report
                CFIndex         inReportLength)     // the length of the report
{
    printf("%s(context: %p, result: %p, sender: %p, "  \
            "type: %d, id: %d, report: %p, length: %p).\n",
        __PRETTY_FUNCTION__, inContext, (void *) inResult, inSender,
        inIOHIDReportType, inReportID, inReport, inReportLength);
}   // Handle_IOHIDDeviceSetReportCallback
 

inResult параметр обратного вызова содержит ошибочный результат работы, вызывающей обратный вызов. Необходимо проверить возвращаемое значение, и если это является ненулевым, обработайте отказ соответственно.

Для запроса отчета от устройства HID необходимо использовать IOHIDDeviceGetReport (синхронный) или IOHIDDeviceGetReportWithCallback (асинхронные) функции как показано ниже:

Перечисление 2-28  IOHIDDeviceGetReport и IOHIDDeviceGetReportWithCallback

 
// synchronous
IOReturn  tIOReturn = IOHIDDeviceGetReport(
                            deviceRef,          // IOHIDDeviceRef for the HID device
                            tIOHIDReportType,   // IOHIDReportType for the report
                            reportID,           // CFIndex for the report ID
                            report,             // address of report buffer
                            &reportSize);       // address of length of the report
 
// asynchronous
IOReturn  tIOReturn = IOHIDDeviceGetReportWithCallback(
                            deviceRef,          // IOHIDDeviceRef for the HID device
                            tIOHIDReportType,   // IOHIDReportType for the report
                            reportID,           // CFIndex for the report ID
                            report,             // address of report buffer
                            &reportSize,        // address of length of the report
                            tCFTimeInterval,    // timeout duration
                            Handle_IOHIDDeviceGetReportCallback,  // the callback routine
                            context);           // context passed to callback
 

Для обеих из этих функций первый параметр является ссылкой устройства HID. Второе IOHIDReportType для отчета. Третий параметр является идентификатором отчета. Четвертый параметр является адресом буфера отчета. Пятый параметр должен быть адресом a CFIndex переменная. Первоначально, необходимо установить значение этого CFIndex переменная, чтобы быть размером отчета Вы запрашиваете. По возврату новое значение в той переменной является размером возвращенного отчета. Для асинхронной версии шестой параметр является тайм-аутом, седьмой параметр является подпрограммой обратного вызова, и последний параметр является указателем контекста, передающимся подпрограмме обратного вызова.

Перечисление 2-29  устройство HID получает подпрограмму обратного вызова отчета

 
static void Handle_IOHIDDeviceGetReportCallback(
                void *          inContext,          // context from IOHIDDeviceGetReportWithCallback
                IOReturn        inResult,           // completion result for the get report operation
                void *          inSender,           // IOHIDDeviceRef of the device this report is from
                IOHIDReportType inIOHIDReportType,  // the report type
                uint32_t        inReportID,         // the report ID
                uint8_t*        inReport,           // the address of the report
                CFIndex         inReportLength)     // the length of the report
{
    printf("%s(context: %p, result: %p, sender: %p, "  \
            "type: %d, id: %d, report: %p, length: %p).\n",
        __PRETTY_FUNCTION__, inContext, (void *) inResult, inSender,
        inIOHIDReportType, inReportID, inReport, inReportLength);
}   // Handle_IOHIDDeviceGetReportCallback
 

inResult параметр обратного вызова содержит ошибочный результат работы, вызывающей обратный вызов. Необходимо проверить возвращаемое значение, и если это является ненулевым, обработайте отказ соответственно.

Работа с элементами HID

CFTypeRef может быть проверен, чтобы быть ссылкой на элемент HID путем сравнения ее Базового типа Основы с IOHIDElementGetTypeID:

Перечисление 2-30  , Проверяющее ссылку на элемент HID

 
    if (CFGetTypeID(tCFTypeRef) == IOHIDElementGetTypeID()) {
        // this is a valid HID element reference
    }
 

Как только допустимая ссылка на элемент HID доступна, IOHIDElementGetProperty функция может использоваться для доступа к ее свойствам (тип, страница использования и использование, и т.д.) использование ключей элемента HID, определенных в <IOKit/HID/IOHIDKeys.h>:

Перечисление 2-31  ключи элемента HID

 
From <IOKit/hid/IOHIDKeys.h>:
 
#define kIOHIDElementCookieKey                      "ElementCookie"
#define kIOHIDElementTypeKey                        "Type"
#define kIOHIDElementCollectionTypeKey              "CollectionType"
#define kIOHIDElementUsageKey                       "Usage"
#define kIOHIDElementUsagePageKey                   "UsagePage"
#define kIOHIDElementMinKey                         "Min"
#define kIOHIDElementMaxKey                         "Max"
#define kIOHIDElementScaledMinKey                   "ScaledMin"
#define kIOHIDElementScaledMaxKey                   "ScaledMax"
#define kIOHIDElementSizeKey                        "Size"
#define kIOHIDElementReportSizeKey                  "ReportSize"
#define kIOHIDElementReportCountKey                 "ReportCount"
#define kIOHIDElementReportIDKey                    "ReportID"
#define kIOHIDElementIsArrayKey                     "IsArray"
#define kIOHIDElementIsRelativeKey                  "IsRelative"
#define kIOHIDElementIsWrappingKey                  "IsWrapping"
#define kIOHIDElementIsNonLinearKey                 "IsNonLinear"
#define kIOHIDElementHasPreferredStateKey           "HasPreferredState"
#define kIOHIDElementHasNullStateKey                "HasNullState"
#define kIOHIDElementFlagsKey                       "Flags"
#define kIOHIDElementUnitKey                        "Unit"
#define kIOHIDElementUnitExponentKey                "UnitExponent"
#define kIOHIDElementNameKey                        "Name"
#define kIOHIDElementValueLocationKey               "ValueLocation"
#define kIOHIDElementDuplicateIndexKey              "DuplicateIndex"
#define kIOHIDElementParentCollectionKey            "ParentCollection"
#define kIOHIDElementVendorSpecificKey              "VendorSpecific"
 
#define kIOHIDElementCalibrationMinKey              "CalibrationMin"
#define kIOHIDElementCalibrationMaxKey              "CalibrationMax"
#define kIOHIDElementCalibrationSaturationMinKey    "CalibrationSaturationMin"
#define kIOHIDElementCalibrationSaturationMaxKey    "CalibrationSaturationMax"
#define kIOHIDElementCalibrationDeadZoneMinKey      "CalibrationDeadZoneMin"
#define kIOHIDElementCalibrationDeadZoneMaxKey      "CalibrationDeadZoneMax"
#define kIOHIDElementCalibrationGranularityKey      "CalibrationGranularity"
 

Весь kIOHIDElementCalibration***Key свойства доступны через IOHIDElementGetProperty и IOHIDElementSetProperty функции.

Перечисление 2-32  Передающие ключи элемента HID к Получить/Установить функциям Свойства

 
IOHIDElementGetProperty(element, CFSTR(kIOHIDElementTypeKey), &tCFNumberRef);
 

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

  Примеры перечисления 2-33 того, как получить или установить долгие свойства элемента HID

 
static Boolean IOHIDElement_GetLongProperty(
    IOHIDElementRef inElementRef,   // the HID element
    CFStringRef inKey,              // the kIOHIDElement key (as a CFString)
    long * outValue)                // address where to return the output value
{
    Boolean result = FALSE;
 
    CFTypeRef tCFTypeRef = IOHIDElementGetProperty(inElementRef, inKey);
    if (tCFTypeRef) {
        // if this is a number
        if (CFNumberGetTypeID() == CFGetTypeID(tCFTypeRef)) {
            // get its value
            result = CFNumberGetValue((CFNumberRef) tCFTypeRef, kCFNumberSInt32Type, outValue);
        }
    }
    return result;
}
 
static void IOHIDElement_SetLongProperty(
    IOHIDElementRef inElementRef,   // the HID element
    CFStringRef inKey,              // the kIOHIDElement key (as a CFString)
    long inValue)                   // the long value to be set
{
    CFNumberRef tCFNumberRef = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &inValue);
    if (tCFNumberRef) {
        IOHIDElementSetProperty(inElementRef, inKey, tCFNumberRef);
        CFRelease(tCFNumberRef);
    }
}
 
// access the kIOHIDElementVendorSpecificKey if it exists:
long longValue;
if (IOHIDElement_GetLongProperty(elementRef, CFSTR(kIOHIDElementVendorSpecificKey), &longValue)) {
    printf("Element 0x%08lX has a vendor specific key of value 0x%08lX.\n", elementRef, longValue);
}
 
 

Существуют функции удобства для получения многих из этих свойств элемента непосредственно:

Перечисление 2-34  функции свойства элемента HID

 
// IOHIDElementCookie represent a unique identifier for a HID element within a HID device.
IOHIDElementCookie cookie = IOHIDElementGetCookie(elementRef);
 
// return the collection type:
//  kIOHIDElementTypeInput_Misc         = 1,
//  kIOHIDElementTypeInput_Button       = 2,
//  kIOHIDElementTypeInput_Axis         = 3,
//  kIOHIDElementTypeInput_ScanCodes    = 4,
//  kIOHIDElementTypeOutput             = 129,
//  kIOHIDElementTypeFeature            = 257,
//  kIOHIDElementTypeCollection         = 513
IOHIDElementType tType = IOHIDElementGetType(elementRef);
 
// If the HID element type is of type kIOHIDElementTypeCollection then
// the collection type is one of:
//  kIOHIDElementCollectionTypePhysical         = 0x00,
//  kIOHIDElementCollectionTypeApplication      = 0x01,
//  kIOHIDElementCollectionTypeLogical          = 0x02,
//  kIOHIDElementCollectionTypeReport           = 0x03,
//  kIOHIDElementCollectionTypeNamedArray       = 0x04,
//  kIOHIDElementCollectionTypeUsageSwitch      = 0x05,
//  kIOHIDElementCollectionTypeUsageModifier    = 0x06
IOHIDElementCollectionType collectionType = IOHIDElementGetCollectionType(elementRef);
 
// usage and usage pages are defined on the USB website at: <http://www.usb.org>
uint32_t page = IOHIDElementGetUsagePage(elementRef);
uint32_t usage = IOHIDElementGetUsage(elementRef);
 
// Boolean properties
Boolean isVirtual = IOHIDElementIsVirtual(elementRef);
Boolean isRelative = IOHIDElementIsRelative(elementRef);
Boolean isWrapping = IOHIDElementIsWrapping(elementRef);
Boolean isArray = IOHIDElementIsArray(elementRef);
Boolean isNonLinear = IOHIDElementIsNonLinear(elementRef);
Boolean hasPreferred = IOHIDElementHasPreferredState(elementRef);
Boolean hasNullState = IOHIDElementHasNullState(elementRef);
 
// the HID element name
CFStringRef name = IOHIDElementGetName(elementRef);
 
// element report information
uint32_t reportID = IOHIDElementGetReportID(elementRef);
uint32_t reportSize = IOHIDElementGetReportSize(elementRef);
uint32_t reportCount = IOHIDElementGetReportCount(elementRef);
 
// element unit & exponent
uint32_t unit = IOHIDElementGetUnit(elementRef);
uint32_t unitExp = IOHIDElementGetUnitExponent(elementRef);
 
// logical & physical minimums & maximums
CFIndex logicalMin = IOHIDElementGetLogicalMin(elementRef);
CFIndex logicalMax = IOHIDElementGetLogicalMax(elementRef);
CFIndex physicalMin = IOHIDElementGetPhysicalMin(elementRef);
CFIndex physicalMax = IOHIDElementGetPhysicalMax(elementRef);
 

Существуют также функции для определения устройства, родителя и дочернего элемента указанного элемента HID:

Перечисление 2-35  функции иерархии элемента HID

 
// return the HID device that a element belongs to
IOHIDDeviceRef deviceRef = IOHIDElementGetDevice(elementRef);
 
// return the collection element that a HID element belongs to (if any)
IOHIDElementRef elementRef = IOHIDElementGetParent(elementRef);
 
// return the child elements of a collection element (if any)
CFArrayRef tCFArrayRef = IOHIDElementGetChildren(elementRef);
 

Функции очереди HID

В то время как разработчики могут использовать IOHIDDeviceGetValue для получения нового значения элемента HID для некоторых элементов, это не достаточно. Если необходимо отслеживать все изменения значения элемента HID, а не просто новое, разработчики могут создать очередь и добавить элементы HID интереса для него. После выполнения так, все события изменения значения, включающие те элементы, получены очередью HID (до глубины очереди HID).

Ссылки очереди HID (IOHIDQueueRef объекты), используются для передачи с очередями HID. Они создаются при помощи IOHIDQueueCreate функция:

 
// Create HID queue reference
IOHIDQueueRef IOHIDQueueCreate(
                    CFAllocatorRef  inCFAllocatorRef,   // Allocator to be used during creation
                    IOHIDDeviceRef  inIOHIDDeviceRef,   // the HID device to be associated with this queue
                    CFIndex         inDepth,            // the maximum number of values to queue
                    IOOptionBits    inOptions)          // options (currently reserved)
 

Первый параметр является a CFAllocatorRef объект, который будет использоваться при выделении возвращенного IOHIDQueueRef. Второй параметр является устройством HID, которое будет связано с этой очередью. Третий параметр является максимальной глубиной очереди HID. Последний параметр (options) в настоящее время резервируется для будущего использования. Разработчики должны передать kIOHIDOptionsTypeNone (нуль) для этого параметра.

Существует нет IOHIDQueueDestroy (или выпуск, свободный, и т.д.). Поскольку ссылка очереди HID является Базовой ссылкой на объект Основы, CFRelease должен использоваться для избавления от него.

A CFTypeRef может быть проверен, чтобы быть ссылкой очереди HID путем сравнения ее Базового типа Основы с IOHIDQueueGetTypeID:

Перечисление 2-36  , Проверяющее ссылку очереди HID

 
    if (CFGetTypeID(tCFTypeRef) == IOHIDQueueGetTypeID()) {
        // this is a valid HID queue reference!
    }
 

Как только ссылка очереди HID была создана, она должна быть запущена, прежде чем она сможет использоваться для доступа к устройствам HID, связанным с ним.

 
void IOHIDQueueStart(IOHIDQueueRef inIOHIDQueueRef);
 

Соответствующая функция для остановки очереди HID:

 
void IOHIDQueueStop(IOHIDQueueRef inIOHIDQueueRef);
 

Для определения устройства HID, связанного с определенной очередью HID, используют IOHIDQueueGetDevice функция:

 
IOHIDDeviceRef IOHIDQueueGetDevice(IOHIDQueueRef inIOHIDQueueRef);
 

Существует функция средства доступа, чтобы получить и установить глубину очереди HID:

 
CFIndex IOHIDQueueGetDepth(IOHIDQueueRef inIOHIDQueueRef);
void IOHIDQueueSetDepth(IOHIDQueueRef inIOHIDQueueRef, CFIndex inDepth);
 

Элементы HID могут быть добавлены и удалены при помощи этих функций:

 
void IOHIDQueueAddElement(IOHIDQueueRef inIOHIDQueueRef, IOHIDElementRef inIOHIDElementRef);
void IOHIDQueueRemoveElement(IOHIDQueueRef inIOHIDQueueRef, IOHIDElementRef inIOHIDElementRef);
 

Чтобы определить, был ли элемент HID добавлен к очереди HID, используют эту функцию:

 
Boolean IOHIDQueueContainsElement(IOHIDQueueRef inIOHIDQueueRef, IOHIDElementRef inIOHIDElementRef);
 

Как только очередь HID была создана, элементы HID были добавлены, и очередь была запущена, значения HID могут тогда быть исключены из очереди с одной из этих функций:

 
IOHIDValueRef IOHIDQueueCopyNextValue(IOHIDQueueRef inIOHIDQueueRef);
IOHIDValueRef IOHIDQueueCopyNextValueWithTimeout(IOHIDQueueRef inIOHIDQueueRef, CFTimeInterval inTimeout);
 

Избегать опрашивать очередь HID относительно значения HID изменяется, разработчики могут вместо этого зарегистрировать подпрограмму обратного вызова:

 
void IOHIDQueueRegisterValueAvailableCallback(
                                IOHIDQueueRef inIOHIDQueueRef,   // reference to the HID queue
                                IOHIDCallback inCallback,        // address of the callback routine
                                void *        inContext);        // context passed to callback
 

Функции, чтобы запланировать и не запланировать очередь HID от цикла выполнения:

 
// Schedule a HID queue with a runloop
void IOHIDQueueScheduleWithRunLoop(IOHIDQueueRef       inIOHIDQueueRef,     // reference to the HID queue
                                    CFRunLoopRef        inRunLoop,          // Run loop to be scheduled with
                                    CFStringRef         inRunLoopMode);     // Run loop mode for scheduling
 
// Unschedule a HID queue from a runloop
void IOHIDQueueUnscheduleFromRunLoop(
                        IOHIDQueueRef   inIOHIDQueueRef,    // reference to the HID queue
                        CFRunLoopRef    inRunLoop,          // Run loop to be unscheduling from
                        CFStringRef     inRunLoopMode);     // Run loop mode for unscheduling
 

Перечисление 2-37  Планируя очередь HID с циклом выполнения

 
IOHIDQueueScheduleWithRunLoop(inIOHIDQueueRef, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode);
 

Перечисление 2-38  значение очереди HID доступная подпрограмма обратного вызова

 
static void Handle_ValueAvailableCallback(
                void *   inContext, // context from IOHIDQueueRegisterValueAvailableCallback
                IOReturn inResult,  // the inResult
                void *   inSender,  // IOHIDQueueRef of the queue
) {
    printf("%s(context: %p, result: %p, sender: %p).\n",
        __PRETTY_FUNCTION__, inContext, (void *) inResult, inSender);
    do {
        IOHIDValueRef valueRef = IOHIDQueueCopyNextValueWithTimeout((IOHIDQueueRef) inSender, 0.);
        if (!valueRef) break;
        // process the HID value reference
        .
        .
        .
        CFRelease(valueRef);    // Don't forget to release our HID value reference
    } while (1) ;
}   // Handle_ValueAvailableCallback
 

inResult параметр обратного вызова содержит ошибочный результат работы, вызывающей обратный вызов. Необходимо проверить возвращаемое значение, и если это является ненулевым, обработайте отказ соответственно.

Функции транзакции HID

APIs низшего уровня такой как IOHIDDeviceGetReport, IOHIDDeviceGetReportWithCallback, IOHIDDeviceSetReport, и IOHIDDeviceSetReportWithCallback потребуйте, чтобы Вы знали, как дескрипторы устройства HID используются для определения отчетов, отправленных в и полученный от устройств HID. См. Перечисление 2-28 и Перечисление 2-26 для получения дополнительной информации об этих функциях.

Транзакции HID являются абстракцией, разделенной на уровни поверх этого APIs низшего уровня. Транзакции HID позволяют Вам собирать транзакцию, добавлять соответствующие значения, устанавливать значения по умолчанию и фиксировать транзакцию (который вынуждает отчет быть отправленным через Шину USB).

Для создания транзакции сначала необходимо создать ссылку транзакции HID путем вызова IOHIDTransactionCreate функция:

IOHIDTransactionRef IOHIDTransactionCreate(
                        CFAllocatorRef  inCFAllocatorRef,   // Allocator to be used during creation
                        IOHIDDeviceRef  inIOHIDDeviceRef,   // the HID device for this transaction
                        IOHIDTransactionDirectionType   inDirection,  // The direction: in or out
                        IOOptionBits    inOptions);         // options (currently reserved)

Первый параметр является a CFAllocatorRef средство выделения, которое будет использоваться при выделении возвращенного IOHIDTransactionRef объект. Второй параметр является устройством HID, которое будет связано с этой транзакцией. Третий параметр является направлением для передачи (kIOHIDTransactionDirectionTypeInput или kIOHIDTransactionDirectionTypeOutput). Последний параметр (options) в настоящее время резервируется для будущего использования. Разработчики должны передать kIOHIDOptionsTypeNone (нуль) для этого параметра.

Существует нет IOHIDTransactionDestroy (или выпуск, свободный, и т.д.). Поскольку ссылка транзакции HID является Базовой ссылкой на объект Основы, необходимо вызвать CFRelease избавляться от него.

A CFTypeRef объект может быть проверен, чтобы быть ссылкой транзакции HID путем сравнения ее Базового типа Основы с возвращаемым значением IOHIDTransactionGetTypeID функция:

Перечисление 2-39  , Проверяющее ссылку транзакции HID

 
    if (CFGetTypeID(tCFTypeRef) == IOHIDTransactionGetTypeID()) {
        // this is a valid HID transaction reference!
    }
 

Существуют функции удобства, чтобы связать устройство HID с транзакцией HID и получить или установить направление для транзакции HID:

 
// Obtain the HID device associated with a transaction
IOHIDDeviceRef IOHIDTransactionGetDevice(
                                    IOHIDTransactionRef inIOHIDTransactionRef); // HID transaction reference
 
// Obtain the direction of the transaction.
IOHIDTransactionDirectionType IOHIDTransactionGetDirection(
                                    IOHIDTransactionRef IOHIDTransactionRef);   // HID transaction reference
 
// Sets the direction of the transaction
void IOHIDTransactionSetDirection(IOHIDTransactionRef IOHIDTransactionRef,      // HID transaction reference
                                   IOHIDTransactionDirectionType direction);    // The direction: in or out
 

Как только транзакция HID была создана тогда, элементы HID, связанные с нею, могут быть добавлены при помощи IOHIDTransactionAddElement функция:

 
void IOHIDTransactionAddElement(
            IOHIDTransactionRef inIOHIDTransactionRef,  // HID transaction reference
            IOHIDElementRef     inIOHIDElementRef);     // the HID element to associate with this transaction
 

Элементы HID могут быть удалены из транзакции HID при помощи функции IOHIDTransactionRemoveElement:

 
void IOHIDTransactionRemoveElement(
            IOHIDTransactionRef inIOHIDTransactionRef,  // HID transaction reference
            IOHIDElementRef     inIOHIDElementRef);     // the HID element to associate with this transaction
 

Чтобы определить, связывается ли элемент HID в настоящее время с транзакцией HID, функция IOHIDTransactionContainsElement может использоваться:

 
// Queries the transaction to determine if elemement has been added.
Boolean IOHIDTransactionContainsElement(
                    IOHIDTransactionRef inIOHIDTransactionRef, // HID transaction reference
                    IOHIDElementRef     inIOHIDElementRef);    // the HID element to test for
 

Для установки значений HID, связанных с элементами HID в транзакции HID, используют функции IOHIDTransactionSetValue:

 
void IOHIDTransactionSetValue(IOHIDTransactionRef  inIOHIDTransactionRef,   // HID transaction reference
                                IOHIDElementRef     inIOHIDElementRef,      // the HID element
                                IOHIDValueRef       inIOHIDValueRef,        // the HID element value
                                IOOptionBits        inOptions);             // options
 

Набор значений HID ожидается, пока транзакция не фиксируется. Если направление транзакции, это значение только используется kIOHIDTransactionDirectionTypeOutput. Используйте kIOHIDTransactionOptionDefaultOutputValue опция установить значения элемента по умолчанию для транзакций.

Для получения значений HID, связанных с элементами HID в транзакции HID, разработчики могут использовать функцию IOHIDTransactionGetValue:

 
// Obtains the HID value for a transaction element.
IOHIDValueRef IOHIDTransactionGetValue(
                                IOHIDTransactionRef inIOHIDTransactionRef,  // HID transaction reference
                                IOHIDElementRef     inIOHIDElementRef,      // the HID element
                                IOOptionBits        inOptions);             // options
 
 

Если направление транзакции HID является kIOHIDTransactionDirectionTypeInput, значение HID представляет то, что было получено из устройства HID от транзакции HID. Иначе, если направление транзакции является kIOHIDTransactionDirectionTypeOutput, значение HID представляет незаконченное значение, которое будет отправлено в устройство HID. Используйте kIOHIDTransactionOptionDefaultOutputValue опцию получить значение HID по умолчанию, связанное с элементами HID транзакции HID.

Значения для элементов HID, связанных с транзакцией HID, могут быть сброшены к их значениям по умолчанию при помощи функции IOHIDTransactionClear:

 
// Clears element transaction values.
void IOHIDTransactionClear(IOHIDTransactionRef inIOHIDTransactionRef);  // HID transaction reference
 

Как только все надлежащие элементы HID были добавлены к транзакции HID (и набор значений для выходных транзакций) тогда, чтобы заставить фактическую транзакцию шины происходить, они должны фиксироваться при помощи одного из двух после функций:

 
// Synchronously commits element transaction to the HID device.
IOReturn IOHIDTransactionCommit(IOHIDTransactionRef inIOHIDTransactionRef); // HID transaction reference
 
// Asynchronously commits element transaction to the HID device.
IOReturn IOHIDTransactionCommitWithCallback(
                        IOHIDTransactionRef inIOHIDTransactionRef,  // HID transaction reference
                        CFTimeInterval      inTimeout,              // timeout duration
                        IOHIDCallback       inCallback,             // address of the callback routine
                        void *              inContext);             // Pointer to be passed to the callback
 

Для обеих функций первый параметр является ссылкой транзакции HID, которая будет фиксироваться. Для асинхронной функции второй параметр является тайм-аутом, третий параметр является подпрограммой обратного вызова (передача NULL если Вы хотите синхронное поведение с тайм-аутом), и последний параметр является указателем контекста, передающимся подпрограмме обратного вызова.

Функции, чтобы запланировать и не запланировать транзакцию HID от цикла выполнения:

 
// Schedule a HID transaction with a runloop
void IOHIDTransactionScheduleWithRunLoop(
        IOHIDTransactionRef inIOHIDTransactionRef,  // reference to the HID transaction
        CFRunLoopRef        inRunLoop,              // Run loop to be scheduled with
        CFStringRef         inRunLoopMode);         // Run loop mode for scheduling
 
// Unschedule a HID transaction from a runloop
void IOHIDTransactionUnscheduleFromRunLoop(
        IOHIDTransactionRef inIOHIDTransactionRef,  // reference to the HID transaction
        CFRunLoopRef        inRunLoop,              // Run loop to be unscheduling from
        CFStringRef         inRunLoopMode);         // Run loop mode for unscheduling
 

Перечисление 2-40  Планируя транзакцию HID с циклом выполнения

 
IOHIDTransactionScheduleWithRunLoop(inIOHIDTransactionRef, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode);
 

Функции значения HID

Ссылки значения HID используются менеджером по HID, и обратные вызовы входного значения устройства HID, устройство HID получает и установило функции значения и обратные вызовы и функции значения копии очереди HID (с или без тайм-аута). Три функции доступны для создания ссылок значения HID:

 
IOHIDValueRef IOHIDValueCreateWithIntegerValue(
            CFAllocatorRef  inCFAllocatorRef,   // Allocator to be used during creation
            IOHIDElementRef inIOHIDElementRef,  // the HID element to be associated with this value
            uint64_t        inTimeStamp,        // OS AbsoluteTime
            CFIndex         inValue);           // the integer (32-bit) value used to create this HID value
 
IOHIDValueRef IOHIDValueCreateWithBytes(
            CFAllocatorRef  inCFAllocatorRef,   // Allocator to be used during creation
            IOHIDElementRef inIOHIDElementRef,  // the HID element to be associated with this value
            uint64_t        inTimeStamp,        // OS AbsoluteTime
            const uint8_t * inBytes,            // a pointer to the data used to create this HID value
            CFIndex         inLength);          // the length of the data used to create this HID value
 
IOHIDValueRef IOHIDValueCreateWithBytesNoCopy(
            CFAllocatorRef  inCFAllocatorRef,   // Allocator to be used during creation
            IOHIDElementRef inIOHIDElementRef,  // the HID element to be associated with this value
            uint64_t        inTimeStamp,        // OS AbsoluteTime
            const uint8_t * inBytes,            // a pointer to the data used to create this HID value
            CFIndex         inLength);          // the length of the data used to create this HID value
 

Для всех трех из этих функций первый параметр является a CFAllocatorRef объект, который будет использоваться при выделении возвращенного IOHIDValueRef. Второй параметр является элементом HID, который будет связан с этим значением. Третий параметр является меткой времени. Для IOHIDValueCreateWithIntegerValue функция, последний параметр является a CFIndex значение. Для последних двух функций четвертый параметр является указателем на данные, и последний параметр является длиной данных.

A CFTypeRef может быть проверен, чтобы быть ссылкой значения HID путем сравнения ее Базового типа Основы с IOHIDValueGetTypeID:

Перечисление 2-41  , Проверяющее HID, оценивает ссылку

 
    if (CFGetTypeID(tCFTypeRef) == IOHIDValueGetTypeID()) {
        // this is a valid HID value reference!
    }
 

Функции удобства предоставлены для доступа к элементу HID, метке времени и целочисленным значениям, связанным с объектами значения HID:

 
// Returns the HID element value associated with this HID value reference.
IOHIDElementRef IOHIDValueGetElement(IOHIDValueRef inIOHIDValueRef);
 
// Returns the timestamp value associated with this HID value reference.
uint64_t IOHIDValueGetTimeStamp(IOHIDValueRef inIOHIDValueRef);
 
// Returns an integer representation for this HID value reference.
CFIndex IOHIDValueGetIntegerValue(IOHIDValueRef inIOHIDValueRef);
 

Дополнительные функции предоставлены для доступа к данным и длине данных, связанных с объектом значения HID:

 
// Returns the size, in bytes, of the data associated with this HID value reference.
CFIndex IOHIDValueGetLength(IOHIDValueRef inIOHIDValueRef);
 
// Returns a byte pointer to the data associated with this HID value reference.
const uint8_t * IOHIDValueGetBytePtr(IOHIDValueRef inIOHIDValueRef)
 

Одна дополнительная функция существует для возврата масштабированного представления объекта значения HID:

 
// return the scaled value of a HID value reference
double_t IOHIDValueGetScaledValue(IOHIDValueRef inIOHIDValueRef, IOHIDValueScaleType inType);
 

В настоящее время существует два типа масштабирования, которое может быть применено:

Первые два калибровочных свойства элемента HID определяют желаемый диапазон возвращенного масштабированного значения:

kIOHIDElementCalibrationMinKey

Минимум ограничивает для калиброванного значения (значение по умолчанию =-1).

kIOHIDElementCalibrationMaxKey

Максимум ограничивает для калиброванного значения (значение по умолчанию = +1).

Например, фактический необработанный диапазон элемента HID мог бы пойти от 0-255, но разработчик мог бы хотеть, чтобы масштабированное значение было возвращено с диапазоном-32.0 к +32.0. В этом примере минута и макс. калибровочные значения были бы установлены в-32.0 и +32.0, соответственно.

Следующие два калибровочных свойства элемента HID определяют диапазон математических ожиданий:

kIOHIDElementCalibrationSaturationMinKey

Минимальное значение, которое будет использоваться при калибровке значения HID.

kIOHIDElementCalibrationSaturationMaxKey

Максимальное значение, которое будет использоваться при калибровке значения HID.

Некоторые устройства HID могут иметь элементы, которые не могут возвратить полный спектр значений, определенных к их логической минуте, и макс. оценить пределы. Например, логические значения для элемента могли бы быть определены как в пределах от от 0 до 255, но существующее устройство может фактически только быть в состоянии к возвращаемым значениям в диапазоне 5 - 250. Это может быть вызвано ошибками оцифровки, механическими пределами на кодере, и т.д. Если эти калибровочные свойства установлены, то логические значения в этом диапазоне масштабируются к полному логическому диапазону для устройства HID. В этом примере минута и макс. степени насыщения были бы установлены в 5 и 250, соответственно.

Следующие два калибровочных свойства элемента HID определяют диапазон мертвой зоны (если он существует):

kIOHIDElementCalibrationDeadZoneMinKey

Минимум ограничивает около средней точки, где проигнорированы значения.

kIOHIDElementCalibrationDeadZoneMaxKey

Максимум ограничивает около средней точки, где проигнорированы значения.

Некоторые устройства HID (такие как джойстики) имеют элементы, имеющие механическую функцию возврата к центру. Когда элемент HID возвращается к центральной позиции, из-за механических помоев, смещения, или шума оцифровки, эти элементы могут не всегда возвращать те же самые значения. Например, элемент с логическим диапазоном от 0 до 255 мог бы возвратить центральные значения в пределах от 124 - 130. Если эти свойства мертвой зоны установлены (к 124 и 130, в этом случае), то любое значение между этими двумя числами возвращается как центр масштабируемое значение (127 в этом случае).

Последнее калибровочное свойство элемента HID определяет гранулярность:

kIOHIDElementCalibrationGranularityKey

Масштаб или уровень детализации возвратились в калиброванном значении элемента.

Например, если свойство гранулярности установлено в 0,1, возвращенные значения после того, как калибровка будет точной сетью магазинов 0,1: {0.0, 0.1, 0.2, 0.3, 0.4, и т.д.}.

Перечисление 2-42  , Устанавливающее калибровочные свойства элемента HID

 
static void IOHIDElement_SetDoubleProperty(
                                IOHIDElementRef inElementRef,   // the HID element
                                CFStringRef     inKey,          // the kIOHIDElement key (as a CFString)
                                double          inValue)        // the double value to be set
{
    CFNumberRef tCFNumberRef = CFNumberCreate(kCFAllocatorDefault, kCFNumberDoubleType, &inValue);
    if (tCFNumberRef) {
        IOHIDElementSetProperty(inElementRef, inKey, tCFNumberRef);
        CFRelease(tCFNumberRef);
    }
}
 
// These define the range of the returned scaled values
IOHIDElement_SetDoubleProperty(elementRef, CFSTR(kIOHIDElementCalibrationMinKey), -32.);
IOHIDElement_SetDoubleProperty(elementRef, CFSTR(kIOHIDElementCalibrationMaxKey), +32.);
 
// these define the range of values expected from the device (logical values)
IOHIDElement_SetDoubleProperty(elementRef, CFSTR(kIOHIDElementCalibrationSaturationMinKey), 5.);
IOHIDElement_SetDoubleProperty(elementRef, CFSTR(kIOHIDElementCalibrationSaturationMaxKey), 250.);
 
// these define the range of the dead zone (logical values)
IOHIDElement_SetDoubleProperty(elementRef, CFSTR(kIOHIDElementCalibrationDeadZoneMinKey), 124.);
IOHIDElement_SetDoubleProperty(elementRef, CFSTR(kIOHIDElementCalibrationDeadZoneMaxKey), 130.);
 
// this defines the granularity of the returned scaled values
IOHIDElement_SetDoubleProperty(elementRef, CFSTR(kIOHIDElementCalibrationGranularityKey), 0.1);
 

Перечисление 2-43  Псевдо код для функции IOHIDValueGetScaledValue

 
// first a convenience function to access HID element properties stored as doubles:
static Boolean IOHIDElement_GetDoubleProperty(
    IOHIDElementRef inElementRef,   // the HID element
    CFStringRef inKey,              // the kIOHIDElement key (as a CFString)
    double * outValue)              // address where to return the output value
{
    Boolean result = FALSE;
 
    CFTypeRef tCFTypeRef = IOHIDElementGetProperty(inElementRef, inKey);
    if (tCFTypeRef) {
        // if this is a number
        if (CFNumberGetTypeID() == CFGetTypeID(tCFTypeRef)) {
            // get its value
            result = CFNumberGetValue((CFNumberRef) tCFTypeRef, kCFNumberDoubleType, outValue);
        }
    }
    return result;
}
 
double_t IOHIDValueGetScaledValue(IOHIDValueRef inValue, IOHIDValueScaleType inType)
{
    IOHIDElementRef element = IOHIDValueGetElement(inValue);
 
    double_t logicalValue = IOHIDValueGetIntegerValue(inValue);
 
    double_t logicalMin = IOHIDElementGetLogicalMin(element);
    double_t logicalMax = IOHIDElementGetLogicalMax(element);
 
    double_t scaledMin = 0;
    double_t scaledMax = 0;
 
    double_t granularity = 0.;
 
    double_t returnValue = 0.;
 
    switch (inType) {
        case kIOHIDValueScaleTypeCalibrated: {
 
            double_t calibrateMin = 0.;
            (void) IOHIDElement_GetDoubleProperty(element,
                        CFSTR(kIOHIDElementCalibrationMinKey), &calibrateMin);
            double_t calibrateMax = 0.;
            (void) IOHIDElement_GetDoubleProperty(element,
                        CFSTR(kIOHIDElementCalibrationMaxKey), &calibrateMax);
 
            // if there are calibration min/max values...
            if (calibrateMin != calibrateMax) {
                // ...use them...
                scaledMin = calibrateMin;
                scaledMax = calibrateMax;
            } else {
                // ...otherwise use +/- 1.0
                scaledMin = -1.;
                scaledMax = +1.;
            }
 
            double_t saturationMin = 0.;
            (void) IOHIDElement_GetDoubleProperty(element,
                        CFSTR(kIOHIDElementCalibrationSaturationMinKey), &saturationMin);
            double_t saturationMax = 0.;
            (void) IOHIDElement_GetDoubleProperty(element,
                        CFSTR(kIOHIDElementCalibrationSaturationMaxKey), &saturationMax);
 
            // if there are saturation min/max values...
            if (saturationMin != saturationMax) {
                // .. and the logical value is less than the minimum saturated value...
                if (logicalValue <= saturationMin) {
                    // ...then return the minimum scaled value
                    return scaledMin;
                } else
                // otherwise if the logical value is greater than the maximum saturated value...
                if (logicalValue >= saturationMax) {
                    // ...return the maximum scaled value.
                    return scaledMax;
                } else
                // otherwise use the min/max saturated values for the logical min/max
                {
                    logicalMin = saturationMin;
                    logicalMax = saturationMax;
                }
            }
 
            double_t deadzoneMin = 0.;
            (void) IOHIDElement_GetDoubleProperty(element,
                        CFSTR(kIOHIDElementCalibrationDeadZoneMinKey), &deadzoneMin);
            double_t deadzoneMax = 0.;
            (void) IOHIDElement_GetDoubleProperty(element,
                        CFSTR(kIOHIDElementCalibrationDeadZoneMaxKey), &deadzoneMax);
 
            // if there are deadzone min/max values...
            if (deadzoneMin != deadzoneMax) {
                    double_t scaledMid = (scaledMin + scaledMax) / 2.;
 
                // if the logical value is less than the deadzone min...
                if (logicalValue < deadzoneMin) {
                    // ...then use the deadzone min as our logical max...
                    logicalMax = deadzoneMin;
                    // ...and the middle of our scaled range as our scaled max.
                    scaledMax = scaledMid;
                } // otherwise if the logical value is greater than the deadzone max...
                else if (logicalValue > deadzoneMax) {
                    // ...then use the deadzone max as our logical min...
                    logicalMin = deadzoneMax;
                    // ...and the middle of our scaled range as our scaled min.
                    scaledMin = scaledMid;
                } else {
                    // otherwise return the middle of our scaled range
                    return scaledMid;
                }
            }
 
            (void) IOHIDElement_GetDoubleProperty(element,
                        CFSTR(kIOHIDElementCalibrationGranularityKey), &granularity);
            break;
        }
        case kIOHIDValueScaleTypePhysical: {
            scaledMin = IOHIDElementGetPhysicalMin(element);
            scaledMax = IOHIDElementGetPhysicalMax(element);
            break;
        }
        default: {
            return returnValue; // should be 0.0
        }
    }
 
    double_t logicalRange = logicalMax - logicalMin;
    double_t scaledRange = scaledMax - scaledMin;
 
    returnValue = ((logicalValue - logicalMin) * scaledRange / logicalRange) + scaledMin;
 
    if (granularity) {
        returnValue = round(returnValue / granularity) * granularity;
    }
    return returnValue;
}