1/* 2 * @APPLE_LICENSE_HEADER_START@ 3 * 4 * Copyright (c) 1999-2012 Apple Computer, Inc. All Rights Reserved. 5 * 6 * This file contains Original Code and/or Modifications of Original Code 7 * as defined in and that are subject to the Apple Public Source License 8 * Version 2.0 (the 'License'). You may not use this file except in 9 * compliance with the License. Please obtain a copy of the License at 10 * http://www.opensource.apple.com/apsl/ and read it before using this 11 * file. 12 * 13 * The Original Code and all software distributed under the License are 14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 18 * Please see the License for the specific language governing rights and 19 * limitations under the License. 20 * 21 * @APPLE_LICENSE_HEADER_END@ 22 */ 23/* 24 File: HIDGetUsageValue.c 25 26 Contains: xxx put contents here xxx 27 28 Version: xxx put version here xxx 29 30 Copyright: � 1999-2001 by Apple Computer, Inc., all rights reserved. 31 32 File Ownership: 33 34 DRI: xxx put dri here xxx 35 36 Other Contact: xxx put other contact here xxx 37 38 Technology: xxx put technology here xxx 39 40 Writers: 41 42 (KH) Keithen Hayenga 43 (BWS) Brent Schorsch 44 45 Change History (most recent first): 46 47 <USB5> 1/18/01 KH Fix for complex descriptors only needed for buttons. 48 <USB4> 3/24/00 KH Complex report descriptors could lead to reporting 49 kHIDUsageNotFoundErr's as kHIDIncompatibleReportErr's instead. 50 <USB3> 11/1/99 BWS [2405720] We need a better check for 'bit padding' items, 51 rather than just is constant. We will check to make sure the 52 item is constant, and has no usage, or zero usage. This means we 53 need to pass an additional parameter to some internal functions 54 <USB2> 4/7/99 BWS Add support for reversed report items 55 <USB1> 3/5/99 BWS first checked in 56*/ 57 58#include "HIDLib.h" 59 60/* 61 *------------------------------------------------------------------------------ 62 * 63 * HIDGetUsageValue - Get the value for a usage 64 * 65 * Input: 66 * reportType - HIDP_Input, HIDP_Output, HIDP_Feature 67 * usagePage - Page Criteria or zero 68 * iCollection - Collection Criteria or zero 69 * usage - The usage to get the value for 70 * piUsageValue - User-supplied place to put value 71 * ptPreparsedData - Pre-Parsed Data 72 * psReport - An HID Report 73 * iReportLength - The length of the Report 74 * Output: 75 * piValue - Pointer to usage Value 76 * Returns: 77 * 78 *------------------------------------------------------------------------------ 79*/ 80OSStatus HIDGetUsageValue 81 (HIDReportType reportType, 82 HIDUsage usagePage, 83 UInt32 iCollection, 84 HIDUsage usage, 85 SInt32 * piUsageValue, 86 HIDPreparsedDataRef preparsedDataRef, 87 void * psReport, 88 IOByteCount iReportLength) 89{ 90 HIDPreparsedDataPtr ptPreparsedData = (HIDPreparsedDataPtr) preparsedDataRef; 91 HIDCollection *ptCollection; 92 HIDReportItem *ptReportItem; 93 OSStatus iStatus; 94 int iR; 95 SInt32 iValue; 96 int iStart; 97 int iReportItem; 98 UInt32 iUsageIndex; 99 Boolean bIncompatibleReport = false; 100/* 101 * Disallow Null Pointers 102*/ 103 if ((ptPreparsedData == NULL) 104 || (piUsageValue == NULL) 105 || (psReport == NULL)) 106 return kHIDNullPointerErr; 107 if (ptPreparsedData->hidTypeIfValid != kHIDOSType) 108 return kHIDInvalidPreparsedDataErr; 109/* 110 * The Collection must be in range 111*/ 112 if (iCollection >= ptPreparsedData->collectionCount) 113 return kHIDBadParameterErr; 114/* 115 * Search only the scope of the Collection specified 116 * Go through the ReportItems 117 * Filter on ReportType and usagePage 118*/ 119 ptCollection = &ptPreparsedData->collections[iCollection]; 120 for (iR=0; iR<ptCollection->reportItemCount; iR++) 121 { 122 iReportItem = ptCollection->firstReportItem + iR; 123 ptReportItem = &ptPreparsedData->reportItems[iReportItem]; 124 if (HIDIsVariable(ptReportItem, preparsedDataRef) 125 && HIDHasUsage(preparsedDataRef,ptReportItem,usagePage,usage,&iUsageIndex,NULL)) 126 { 127/* 128 * This may be the proper data to get 129 * Let's check for the proper Report ID, Type, and Length 130*/ 131 iStatus = HIDCheckReport(reportType,preparsedDataRef,ptReportItem, 132 psReport,iReportLength); 133/* 134 * The Report ID or Type may not match. 135 * This may not be an error (yet) 136*/ 137 if (iStatus == kHIDIncompatibleReportErr) 138 bIncompatibleReport = true; 139 else if (iStatus != kHIDSuccess) 140 return iStatus; 141 else 142 { 143/* 144 * Pick up the data 145*/ 146 iStart = ptReportItem->startBit 147 + (ptReportItem->globals.reportSize * iUsageIndex); 148 iStatus = HIDGetData(psReport, iReportLength, iStart, 149 ptReportItem->globals.reportSize, &iValue, 150 ((ptReportItem->globals.logicalMinimum < 0) 151 ||(ptReportItem->globals.logicalMaximum < 0))); 152 if (!iStatus) 153 iStatus = HIDPostProcessRIValue (ptReportItem, &iValue); 154 *piUsageValue = iValue; 155 return iStatus; 156 } 157 } 158 } 159 if (bIncompatibleReport) 160 return kHIDIncompatibleReportErr; 161 return kHIDUsageNotFoundErr; 162} 163 164/* 165 *------------------------------------------------------------------------------ 166 * 167 * HIDGetScaledUsageValue - Get the value for a usage 168 * 169 * Input: 170 * reportType - HIDP_Input, HIDP_Output, HIDP_Feature 171 * usagePage - Page Criteria or zero 172 * iCollection - Collection Criteria or zero 173 * usage - usage Criteria or zero 174 * piValue - Pointer to usage Value 175 * ptPreparsedData - Pre-Parsed Data 176 * psReport - An HID Report 177 * iReportLength - The length of the Report 178 * Output: 179 * piValue - Pointer to usage Value 180 * Returns: 181 * 182 *------------------------------------------------------------------------------ 183*/ 184OSStatus HIDGetScaledUsageValue(HIDReportType reportType, 185 HIDUsage usagePage, 186 UInt32 iCollection, 187 HIDUsage usage, 188 SInt32 *piUsageValue, 189 HIDPreparsedDataRef preparsedDataRef, 190 void *psReport, 191 IOByteCount iReportLength) 192{ 193 HIDPreparsedDataPtr ptPreparsedData = (HIDPreparsedDataPtr) preparsedDataRef; 194 HIDCollection *ptCollection; 195 HIDReportItem *ptReportItem; 196 OSStatus iStatus; 197 int iR; 198 SInt32 iValue; 199 int iStart; 200 int iReportItem; 201 UInt32 iUsageIndex; 202 Boolean bIncompatibleReport = false; 203/* 204 * Disallow Null Pointers 205*/ 206 if ((ptPreparsedData == NULL) 207 || (piUsageValue == NULL) 208 || (psReport == NULL)) 209 return kHIDNullPointerErr; 210 if (ptPreparsedData->hidTypeIfValid != kHIDOSType) 211 return kHIDInvalidPreparsedDataErr; 212/* 213 * The Collection must be in range 214*/ 215 if (iCollection >= ptPreparsedData->collectionCount) 216 return kHIDBadParameterErr; 217/* 218 * Search only the scope of the Collection specified 219 * Go through the ReportItems 220 * Filter on ReportType and usagePage 221*/ 222 ptCollection = &ptPreparsedData->collections[iCollection]; 223 for (iR=0; iR<ptCollection->reportItemCount; iR++) 224 { 225 iReportItem = ptCollection->firstReportItem + iR; 226 ptReportItem = &ptPreparsedData->reportItems[iReportItem]; 227 if (HIDIsVariable(ptReportItem, preparsedDataRef) 228 && HIDHasUsage(preparsedDataRef,ptReportItem,usagePage,usage,&iUsageIndex,NULL)) 229 { 230/* 231 * This may be the proper data to get 232 * Let's check for the proper Report ID, Type, and Length 233*/ 234 iStatus = HIDCheckReport(reportType,preparsedDataRef,ptReportItem, 235 psReport,iReportLength); 236/* 237 * The Report ID or Type may not match. 238 * This may not be an error (yet) 239*/ 240 if (iStatus == kHIDIncompatibleReportErr) 241 bIncompatibleReport = true; 242 else if (iStatus != kHIDSuccess) 243 return iStatus; 244 else 245 { 246/* 247 * Pick up the data 248*/ 249 iStart = ptReportItem->startBit 250 + (ptReportItem->globals.reportSize * iUsageIndex); 251 iStatus = HIDGetData(psReport, iReportLength, iStart, 252 ptReportItem->globals.reportSize, &iValue, 253 ((ptReportItem->globals.logicalMinimum < 0) 254 ||(ptReportItem->globals.logicalMaximum < 0))); 255 if (!iStatus) 256 iStatus = HIDPostProcessRIValue (ptReportItem, &iValue); 257 if (iStatus != kHIDSuccess) 258 return iStatus; 259/* 260 * Try to scale the data 261*/ 262 iStatus = HIDScaleUsageValueIn(ptReportItem,iValue,&iValue); 263 *piUsageValue = iValue; 264 return iStatus; 265 } 266 } 267 } 268 if (bIncompatibleReport) 269 return kHIDIncompatibleReportErr; 270 return kHIDUsageNotFoundErr; 271} 272