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