/* * Copyright (c) 1999-2008 Apple Computer, Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. * * @APPLE_LICENSE_HEADER_END@ */ #include #include #include #include #include #include #include #ifndef min #define min(a,b) (aelement) CFRelease(event->element); } IOHIDValueRef _IOHIDValueCreateWithElementValuePtr(CFAllocatorRef allocator, IOHIDElementRef element, IOHIDElementValue * pElementValue) { IOHIDValueRef event = NULL; uint32_t length = 0; if ( !element || !pElementValue ) return NULL; length = _IOHIDElementGetLength(element); event = __IOHIDValueCreatePrivate(allocator, NULL, length); if (!event) return NULL; event->element = (IOHIDElementRef)CFRetain(element); event->timeStamp = *((uint64_t *)&(pElementValue->timestamp)); event->length = length; __IOHIDValueConvertWordToByte((const uint32_t *)&(pElementValue->value[0]), event->bytes, length); return event; } IOHIDValueRef _IOHIDValueCreateWithStruct(CFAllocatorRef allocator, IOHIDElementRef element, IOHIDEventStruct * pEventStruct) { IOHIDValueRef event = NULL; Boolean isLongValue = FALSE; uint32_t length = 0; if ( !element || !pEventStruct ) return NULL; isLongValue = (pEventStruct->longValue && pEventStruct->longValueSize); length = _IOHIDElementGetLength(element); event = __IOHIDValueCreatePrivate(allocator, NULL, isLongValue ? 0 : length); if (!event) return NULL; event->element = (IOHIDElementRef)CFRetain(element); event->timeStamp = *((uint64_t *)&(pEventStruct->timestamp)); event->length = length; if ( isLongValue ) { event->bytePtr = pEventStruct->longValue; } else __IOHIDValueConvertWordToByte((const uint32_t *)&(pEventStruct->value), event->bytes, min(sizeof(uint32_t), event->length)); return event; } IOHIDValueRef IOHIDValueCreateWithIntegerValue(CFAllocatorRef allocator, IOHIDElementRef element, uint64_t timeStamp, CFIndex value) { IOHIDValueRef event = NULL; uint32_t length = 0; uint64_t tempValue; if ( !element ) return NULL; length = _IOHIDElementGetLength(element); event = __IOHIDValueCreatePrivate(allocator, NULL, length); if (!event) return NULL; event->element = (IOHIDElementRef)CFRetain(element); event->timeStamp = timeStamp; event->length = length; tempValue = value; __IOHIDValueConvertLongWordToByte((const uint64_t *)&tempValue, event->bytes, min(length, sizeof(uint32_t))); return event; } IOHIDValueRef IOHIDValueCreateWithBytes(CFAllocatorRef allocator, IOHIDElementRef element, uint64_t timeStamp, const uint8_t * bytes, CFIndex byteLength) { IOHIDValueRef event = NULL; CFIndex length = 0; if ( !element || !bytes || !byteLength ) return NULL; length = _IOHIDElementGetLength(element); event = __IOHIDValueCreatePrivate(allocator, NULL, length); if (!event) return NULL; event->element = (IOHIDElementRef)CFRetain(element); event->timeStamp = timeStamp; event->length = length; bcopy(bytes, event->bytes, min(length, byteLength)); return event; } IOHIDValueRef IOHIDValueCreateWithBytesNoCopy(CFAllocatorRef allocator, IOHIDElementRef element, uint64_t timeStamp, const uint8_t * bytes, CFIndex length) { IOHIDValueRef event = NULL; if ( !element || !bytes || !length ) return NULL; event = __IOHIDValueCreatePrivate(allocator, NULL, 0); if (!event) return NULL; event->element = (IOHIDElementRef)CFRetain(element); event->timeStamp = timeStamp; event->length = min(length, _IOHIDElementGetLength(element)); event->bytePtr = (uint8_t *)bytes; return event; } IOHIDElementRef IOHIDValueGetElement(IOHIDValueRef event) { return event->element; } uint64_t IOHIDValueGetTimeStamp(IOHIDValueRef event) { return event->timeStamp; } CFIndex IOHIDValueGetIntegerValue(IOHIDValueRef event) { uint64_t value = 0; IOHIDElementRef element = event->element; __IOHIDValueConvertByteToLongWord(IOHIDValueGetBytePtr(event), &value, event->length, IOHIDElementGetLogicalMin(element) < 0 || IOHIDElementGetLogicalMax(element) < 0); return (CFIndex)value; } double_t IOHIDValueGetScaledValue(IOHIDValueRef event, IOHIDValueScaleType type) { IOHIDElementRef element = event->element; CFIndex logicalValue = IOHIDValueGetIntegerValue(event); CFIndex logicalMin = IOHIDElementGetLogicalMin(element); CFIndex logicalMax = IOHIDElementGetLogicalMax(element); CFIndex logicalRange = 0; CFIndex scaledMin = 0; CFIndex scaledMax = 0; CFIndex scaledRange = 0; double_t granularity = 0.0; double_t returnValue = 0.0; if ( type == kIOHIDValueScaleTypeCalibrated ){ IOHIDCalibrationInfo * calibrationInfo; calibrationInfo = _IOHIDElementGetCalibrationInfo(element); if ( calibrationInfo ) { if ( calibrationInfo->min != calibrationInfo->max ) { scaledMin = calibrationInfo->min; scaledMax = calibrationInfo->max; } else { scaledMin = -1; scaledMax = 1; } // check saturation first if ( calibrationInfo->satMin != calibrationInfo->satMax ) { if ( logicalValue <= calibrationInfo->satMin ) return scaledMin; if ( logicalValue >= calibrationInfo->satMax ) return scaledMax; logicalMin = calibrationInfo->satMin; logicalMax = calibrationInfo->satMax; } // now check the dead zone if (calibrationInfo->dzMin != calibrationInfo->dzMax) { double_t scaledMid = (scaledMin + scaledMax) / 2.0; if (logicalValue < calibrationInfo->dzMin) { logicalMax = calibrationInfo->dzMin; scaledMax = scaledMid; } else if ( logicalValue > calibrationInfo->dzMax) { logicalMin = calibrationInfo->dzMax; scaledMin = scaledMid; } else { return scaledMid; } } granularity = calibrationInfo->gran; } } else { // kIOHIDValueScaleTypePhysical scaledMin = IOHIDElementGetPhysicalMin(element); scaledMax = IOHIDElementGetPhysicalMax(element); } logicalRange = logicalMax - logicalMin; scaledRange = scaledMax - scaledMin; returnValue = ((double_t)(logicalValue - logicalMin) * (double_t)scaledRange / (double_t)logicalRange) + scaledMin; if ( granularity ) returnValue = granularity * llround(returnValue / granularity); return returnValue; } CFIndex IOHIDValueGetLength(IOHIDValueRef event) { return event->length; } const uint8_t * IOHIDValueGetBytePtr(IOHIDValueRef event) { return event->bytePtr ? event->bytePtr : event->bytes; } void _IOHIDValueCopyToElementValuePtr(IOHIDValueRef value, IOHIDElementValue * pElementValue) { IOHIDElementRef element = IOHIDValueGetElement(value); __IOHIDValueConvertByteToWord(IOHIDValueGetBytePtr(value), (uint32_t *)(pElementValue->value), value->length, IOHIDElementGetLogicalMin(element) < 0 || IOHIDElementGetLogicalMax(element) < 0); } #if defined (__LITTLE_ENDIAN__) #define ON_INTEL 1 #else #define ON_INTEL 0 #endif #define BIT_MASK(bits) (((uint64_t)1 << (bits)) - 1) void __IOHIDValueConvertByteToWord(const UInt8 * src, uint32_t * dst, uint32_t length, Boolean signExtend) { bcopy(src, dst, length); if ( signExtend && length ) { uint32_t lastOffset = length / sizeof(uint32_t); uint32_t wordBitsProcessed = length % sizeof(uint32_t); lastOffset += (wordBitsProcessed) ? 0:-1; wordBitsProcessed = wordBitsProcessed << 3; if (wordBitsProcessed && (dst[lastOffset] & (1<<(wordBitsProcessed-1)))) dst[lastOffset] |= ~(BIT_MASK(wordBitsProcessed)); } } void __IOHIDValueConvertWordToByte(const uint32_t * src, UInt8 * dst, uint32_t bytesToCopy) { bcopy(src, dst, bytesToCopy); } void __IOHIDValueConvertByteToLongWord(const UInt8 * src, uint64_t * dst, uint64_t length, Boolean signExtend) { bcopy(src, dst, length); if ( signExtend && length ) { uint32_t lastOffset = length / sizeof(uint64_t); uint32_t longWordBitsProcessed = length % sizeof(uint64_t); lastOffset += (longWordBitsProcessed) ? 0:-1; longWordBitsProcessed = longWordBitsProcessed << 3; if (longWordBitsProcessed && (dst[lastOffset] & (1<<(longWordBitsProcessed-1)))) dst[lastOffset] |= ~(BIT_MASK(longWordBitsProcessed)); } } void __IOHIDValueConvertLongWordToByte(const uint64_t * src, UInt8 * dst, uint64_t bytesToCopy) { bcopy(src, dst, bytesToCopy); }