HID_Queue_Utilities.c
// File: HID_Queue_Utilities.c |
// Abstract: HID Queue Utilities. |
// Version: 2.0 |
// |
// Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple |
// Inc. ("Apple") in consideration of your agreement to the following |
// terms, and your use, installation, modification or redistribution of |
// this Apple software constitutes acceptance of these terms. If you do |
// not agree with these terms, please do not use, install, modify or |
// redistribute this Apple software. |
// |
// In consideration of your agreement to abide by the following terms, and |
// subject to these terms, Apple grants you a personal, non-exclusive |
// license, under Apple's copyrights in this original Apple software (the |
// "Apple Software"), to use, reproduce, modify and redistribute the Apple |
// Software, with or without modifications, in source and/or binary forms; |
// provided that if you redistribute the Apple Software in its entirety and |
// without modifications, you must retain this notice and the following |
// text and disclaimers in all such redistributions of the Apple Software. |
// Neither the name, trademarks, service marks or logos of Apple Inc. may |
// be used to endorse or promote products derived from the Apple Software |
// without specific prior written permission from Apple. Except as |
// expressly stated in this notice, no other rights or licenses, express or |
// implied, are granted by Apple herein, including but not limited to any |
// patent rights that may be infringed by your derivative works or by other |
// works in which the Apple Software may be incorporated. |
// |
// The Apple Software is provided by Apple on an "AS IS" basis. APPLE |
// MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION |
// THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS |
// FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND |
// OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS. |
// |
// IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL |
// OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
// INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, |
// MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED |
// AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE), |
// STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE |
// POSSIBILITY OF SUCH DAMAGE. |
// |
// Copyright (C) 2009 Apple Inc. All Rights Reserved. |
// |
//***************************************************** |
#include "HID_Utilities_External.h" |
// ================================== |
// private functions |
// creates a queue for a device, creates and opens device interface if required |
static IOReturn HIDCreateQueue(IOHIDDeviceRef inIOHIDDeviceRef) { |
IOReturn result = kIOReturnSuccess; |
if ( inIOHIDDeviceRef ) { |
assert( IOHIDDeviceGetTypeID() == CFGetTypeID(inIOHIDDeviceRef) ); |
// do we already have a queue? |
IOHIDQueueRef tIOHIDQueueRef = IOHIDDevice_GetQueue(inIOHIDDeviceRef); |
if ( tIOHIDQueueRef ) { // (yes) |
assert( IOHIDQueueGetTypeID() == CFGetTypeID(tIOHIDQueueRef) ); |
} else { |
tIOHIDQueueRef = IOHIDQueueCreate(kCFAllocatorDefault, inIOHIDDeviceRef, kDeviceQueueSize, kIOHIDOptionsTypeNone); |
if ( tIOHIDQueueRef ) { // did that work |
HIDReportErrorNum("Failed to create queue via create", result); |
} else { |
result = kIOReturnSuccess; |
} |
} |
} else { |
HIDReportErrorNum("HID device ref does not exist for queue creation", result); |
} |
return (result); |
} /* HIDCreateQueue */ |
// --------------------------------- |
// returns true if queue is empty false otherwise |
// error if no device, empty if no queue |
static unsigned char HIDIsDeviceQueueEmpty(IOHIDDeviceRef inIOHIDDeviceRef) { |
if ( inIOHIDDeviceRef ) { // need device and queue |
assert( IOHIDDeviceGetTypeID() == CFGetTypeID(inIOHIDDeviceRef) ); |
IOHIDQueueRef tIOHIDQueueRef = IOHIDDevice_GetQueue(inIOHIDDeviceRef); |
if ( tIOHIDQueueRef ) { |
IOHIDElementRef tIOHIDElementRef = HIDGetFirstDeviceElement(inIOHIDDeviceRef, kHIDElementTypeIO); |
while ( tIOHIDElementRef ) { |
if ( IOHIDQueueContainsElement(tIOHIDQueueRef, tIOHIDElementRef) ) { |
return (false); |
} |
tIOHIDElementRef = HIDGetNextDeviceElement(tIOHIDElementRef, kHIDElementTypeIO); |
} |
} else { |
HIDReportError("NULL device passed to HIDIsDeviceQueueEmpty."); |
} |
} else { |
HIDReportError("NULL device passed to HIDIsDeviceQueueEmpty."); |
} |
return (true); |
} /* HIDIsDeviceQueueEmpty */ |
// --------------------------------- |
// disposes and releases queue, sets queue to NULL,. |
// Note: will have no effect if device or queue do not exist |
static IOReturn HIDDisposeReleaseQueue(IOHIDDeviceRef inIOHIDDeviceRef) { |
IOReturn result = kIOReturnSuccess; |
if ( inIOHIDDeviceRef ) { |
IOHIDQueueRef tIOHIDQueueRef = IOHIDDevice_GetQueue(inIOHIDDeviceRef); |
if ( tIOHIDQueueRef ) { |
// stop queue |
IOHIDQueueStop(tIOHIDQueueRef); |
// release the queue |
CFRelease(tIOHIDQueueRef); |
} |
} else { |
HIDReportError("NULL device passed to HIDDisposeReleaseQueue."); |
} |
return (result); |
} /* HIDDisposeReleaseQueue */ |
// ================================== |
// public functions |
// ---------------------------------- |
// queues specific element, performing any device queue set up required |
// queue is started and ready to return events on exit from this function |
int HIDQueueElement(IOHIDDeviceRef inIOHIDDeviceRef, IOHIDElementRef inIOHIDElementRef) { |
IOReturn result = kIOReturnSuccess; |
if ( inIOHIDDeviceRef ) { |
assert( IOHIDDeviceGetTypeID() == CFGetTypeID(inIOHIDDeviceRef) ); |
if ( inIOHIDElementRef ) { |
assert( IOHIDElementGetTypeID() == CFGetTypeID(inIOHIDElementRef) ); |
IOHIDQueueRef tIOHIDQueueRef = IOHIDDevice_GetQueue(inIOHIDDeviceRef); |
if ( !tIOHIDQueueRef ) { // if no queue create queue |
result = HIDCreateQueue(inIOHIDDeviceRef); |
if ( kIOReturnSuccess == result ) { |
tIOHIDQueueRef = IOHIDDevice_GetQueue(inIOHIDDeviceRef); |
} |
} |
if ( tIOHIDQueueRef ) { |
// stop queue |
IOHIDQueueStop(tIOHIDQueueRef); |
// queue element |
if ( !IOHIDQueueContainsElement(tIOHIDQueueRef, inIOHIDElementRef) ) { |
IOHIDQueueAddElement(tIOHIDQueueRef, inIOHIDElementRef); |
} |
// restart queue |
IOHIDQueueStart(tIOHIDQueueRef); |
} else { |
HIDReportError("No queue for device passed to HIDQueueElement."); |
if ( kIOReturnSuccess == result ) { |
result = kIOReturnError; |
} |
} |
} else { |
HIDReportError("NULL element passed to HIDQueueElement."); |
result = kIOReturnBadArgument; |
} |
} else { |
HIDReportError("NULL device passed to HIDQueueElement."); |
result = kIOReturnBadArgument; |
} |
return (result); |
} /* HIDQueueElement */ |
// --------------------------------- |
// adds all elements to queue, performing any device queue set up required |
// queue is started and ready to return events on exit from this function |
int HIDQueueDevice(IOHIDDeviceRef inIOHIDDeviceRef) { |
IOReturn result = kIOReturnSuccess; |
// error checking |
if ( !inIOHIDDeviceRef ) { |
HIDReportError("Device does not exist, cannot queue device."); |
return (kIOReturnBadArgument); |
} |
if ( !inIOHIDDeviceRef ) { // must have interface |
HIDReportError("Device does not have hid device ref, cannot queue device."); |
return (kIOReturnError); |
} |
IOHIDQueueRef tIOHIDQueueRef = IOHIDDevice_GetQueue(inIOHIDDeviceRef); |
if ( !tIOHIDQueueRef ) { // if no queue create queue |
result = HIDCreateQueue(inIOHIDDeviceRef); |
if ( kIOReturnSuccess == result ) { |
tIOHIDQueueRef = IOHIDDevice_GetQueue(inIOHIDDeviceRef); |
} |
} |
if ( (kIOReturnSuccess != result) || (!tIOHIDQueueRef) ) { |
HIDReportErrorNum("Could not queue device due to problem creating queue.", result); |
if ( kIOReturnSuccess != result ) { |
return (result); |
} else { |
return (kIOReturnError); |
} |
} |
// stop queue |
IOHIDQueueStop(tIOHIDQueueRef); |
// queue element |
IOHIDElementRef tIOHIDElementRef = HIDGetFirstDeviceElement(inIOHIDDeviceRef, kHIDElementTypeIO); |
while ( tIOHIDElementRef ) { |
if ( !IOHIDQueueContainsElement(tIOHIDQueueRef, tIOHIDElementRef) ) { |
IOHIDQueueAddElement(tIOHIDQueueRef, tIOHIDElementRef); |
} |
tIOHIDElementRef = HIDGetNextDeviceElement(tIOHIDElementRef, kHIDElementTypeIO); |
} |
// restart queue |
IOHIDQueueStart(tIOHIDQueueRef); |
return (result); |
} /* HIDQueueDevice */ |
// --------------------------------- |
// removes element for queue, if last element in queue will release queue and closes device interface |
int HIDDequeueElement(IOHIDDeviceRef inIOHIDDeviceRef, IOHIDElementRef inIOHIDElementRef) { |
IOReturn result = kIOReturnSuccess; |
if ( inIOHIDDeviceRef ) { |
assert( IOHIDDeviceGetTypeID() == CFGetTypeID(inIOHIDDeviceRef) ); |
if ( inIOHIDElementRef ) { |
assert( IOHIDElementGetTypeID() == CFGetTypeID(inIOHIDElementRef) ); |
IOHIDQueueRef tIOHIDQueueRef = IOHIDDevice_GetQueue(inIOHIDDeviceRef); |
if ( tIOHIDQueueRef ) { |
// stop queue |
IOHIDQueueStop(tIOHIDQueueRef); |
// de-queue element |
if ( IOHIDQueueContainsElement(tIOHIDQueueRef, inIOHIDElementRef) ) { |
IOHIDQueueRemoveElement(tIOHIDQueueRef, inIOHIDElementRef); |
} |
// release device queue and close interface if queue empty |
if ( HIDIsDeviceQueueEmpty(inIOHIDDeviceRef) ) { |
result = HIDDisposeReleaseQueue(inIOHIDDeviceRef); |
if ( kIOReturnSuccess != result ) { |
HIDReportErrorNum("Failed to dispose and release queue.", result); |
} |
} else { // not empty so restart queue |
IOHIDQueueStart(tIOHIDQueueRef); |
} |
} else { |
HIDReportError("No queue for device passed to HIDDequeueElement."); |
if ( kIOReturnSuccess == result ) { |
result = kIOReturnError; |
} |
} |
} else { |
HIDReportError("NULL element passed to HIDDequeueElement."); |
result = kIOReturnBadArgument; |
} |
} else { |
HIDReportError("NULL device passed to HIDDequeueElement."); |
result = kIOReturnBadArgument; |
} |
return (result); |
} /* HIDDequeueElement */ |
// --------------------------------- |
// completely removes all elements from queue and releases queue and closes device interface |
// does not release device interfaces, application must call ReleaseHIDDeviceList on exit |
int HIDDequeueDevice(IOHIDDeviceRef inIOHIDDeviceRef) { |
IOReturn result = kIOReturnSuccess; |
// error checking |
if ( !inIOHIDDeviceRef ) { |
HIDReportError("Device does not exist, cannot queue device."); |
return (kIOReturnBadArgument); |
} |
if ( !inIOHIDDeviceRef ) { // must have interface |
HIDReportError("Device does not have hid device ref, cannot queue device."); |
return (kIOReturnError); |
} |
IOHIDQueueRef tIOHIDQueueRef = IOHIDDevice_GetQueue(inIOHIDDeviceRef); |
if ( tIOHIDQueueRef ) { |
// iterate through elements and if queued, remove |
IOHIDElementRef tIOHIDElementRef = HIDGetFirstDeviceElement(inIOHIDDeviceRef, kHIDElementTypeIO); |
while ( tIOHIDElementRef ) { |
// de-queue element |
if ( IOHIDQueueContainsElement(tIOHIDQueueRef, tIOHIDElementRef) ) { |
IOHIDQueueRemoveElement(tIOHIDQueueRef, tIOHIDElementRef); |
} |
tIOHIDElementRef = HIDGetNextDeviceElement(tIOHIDElementRef, kHIDElementTypeIO); |
} |
// ensure queue is disposed and released |
result = HIDDisposeReleaseQueue(inIOHIDDeviceRef); |
if ( kIOReturnSuccess != result ) { |
HIDReportErrorNum("Failed to dispose and release queue.", result); |
} |
} else { |
HIDReportError("No queue for device passed to HIDDequeueElement."); |
if ( kIOReturnSuccess == result ) { |
result = kIOReturnError; |
} |
} |
return (result); |
} /* HIDDequeueDevice */ |
// --------------------------------- |
// releases all device queues for quit or rebuild (must be called) |
// does not release device interfaces, application must call ReleaseHIDDeviceList on exit |
IOReturn HIDReleaseAllDeviceQueues(void) { |
IOReturn result = kIOReturnSuccess; |
IOHIDDeviceRef tIOHIDDeviceRef = HIDGetFirstDevice(); |
while ( tIOHIDDeviceRef ) { |
result = HIDDequeueDevice(tIOHIDDeviceRef); |
if ( kIOReturnSuccess != result ) { |
HIDReportErrorNum("Could not dequeue device.", result); |
} |
tIOHIDDeviceRef = HIDGetNextDevice(tIOHIDDeviceRef); |
} |
return (result); |
} /* HIDReleaseAllDeviceQueues */ |
// --------------------------------- |
// Get the next event in the queue for a device |
// elements or entire device should be queued prior to calling this with HIDQueueElement or HIDQueueDevice |
// returns true if an event is avialable for the element and fills out *pHIDEvent structure, returns false otherwise |
// Note: kIOReturnUnderrun returned from getNextEvent indicates an empty queue not an error condition |
// Note: application should pass in a pointer to a IOHIDEventStruct cast to a void (for CFM compatibility) |
unsigned char HIDGetEvent(IOHIDDeviceRef inIOHIDDeviceRef, IOHIDValueRef *pIOHIDValueRef) { |
if ( inIOHIDDeviceRef ) { |
IOHIDQueueRef tIOHIDQueueRef = IOHIDDevice_GetQueue(inIOHIDDeviceRef); |
if ( tIOHIDQueueRef ) { |
if ( pIOHIDValueRef ) { |
*pIOHIDValueRef = IOHIDQueueCopyNextValueWithTimeout(tIOHIDQueueRef, 0.0); |
if ( *pIOHIDValueRef ) { |
return (true); |
} |
} |
} else { |
HIDReportError("Could not get HID event, hid queue reference does not exist."); |
} |
} else { |
HIDReportError("Could not get HID event, device does not exist."); |
} |
return (false); // did not get event |
} /* HIDGetEvent */ |
Copyright © 2009 Apple Inc. All Rights Reserved. Terms of Use | Privacy Policy | Updated: 2009-10-01