]> git.saurik.com Git - apple/xnu.git/blob - iokit/Families/IOHIDSystem/IOHIDDescriptorParser/HIDProcessLocalItem.c
c67f05a24b4d0c74bacc29473873a7e6b38252be
[apple/xnu.git] / iokit / Families / IOHIDSystem / IOHIDDescriptorParser / HIDProcessLocalItem.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: HIDProcessLocalItem.c
24
25 Contains: xxx put contents here xxx
26
27 Version: xxx put version here xxx
28
29 Copyright: © 1999 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 (BWS) Brent Schorsch
42
43 Change History (most recent first):
44
45 <USB1> 3/5/99 BWS first checked in
46 */
47
48 #include "HIDLib.h"
49
50 /*
51 *------------------------------------------------------------------------------
52 *
53 * HIDProcessLocalItem - Process a LocalItem
54 *
55 * Input:
56 * ptDescriptor - The Descriptor Structure
57 * ptPreparsedData - The PreParsedData Structure
58 * Output:
59 * ptPreparsedData - The PreParsedData Structure
60 * Returns:
61 * kHIDSuccess - Success
62 * kHIDNullPointerErr - Argument, Pointer was Null
63 *
64 *------------------------------------------------------------------------------
65 */
66 OSStatus HIDProcessLocalItem(HIDReportDescriptor *ptDescriptor,
67 HIDPreparsedDataPtr ptPreparsedData)
68 {
69 HIDDesignatorItem *ptDesignatorItem;
70 HIDStringItem *ptStringItem;
71 HIDP_UsageItem *ptUsageItem;
72 HIDItem *ptItem;
73 /*
74 * Disallow NULL Pointers
75 */
76 if ((ptDescriptor == NULL) || (ptPreparsedData == NULL))
77 return kHIDNullPointerErr;
78 /*
79 * Process the LocalItem by tag
80 */
81 ptItem = &ptDescriptor->item;
82 switch (ptItem->tag)
83 {
84 /*
85 * Note that Tag = usage Item may represent either
86 * a UsagePair with the usagePage implied, or
87 * a UsagePair defined by an extended usage
88 * If a Tag = usage Item has 1 or 2 bytes of data
89 * then the current usagePage is used
90 * If a Tag = usage Item has 4 bytes of data
91 * then the high order bytes are the usagePage
92 *
93 * Note that the Microsoft HID Parser uses the last
94 * usagePage defined before the MainItem with which
95 * the usage is associated rather than the current
96 * usagePage. The method used here is more generic
97 * although multiple UsagePages for a MainItem are
98 * unlikely due to the MS limitation.
99 */
100 case kHIDTagUsage:
101 ptUsageItem = &ptPreparsedData->usageItems[ptPreparsedData->usageItemCount++];
102 ptUsageItem->isRange = false;
103 if (ptItem->byteCount == 4)
104 {
105 ptUsageItem->usagePage = ptItem->unsignedValue>>16;
106 ptUsageItem->usage = ptItem->unsignedValue&0xFFFFL;
107 }
108 else
109 {
110 ptUsageItem->usagePage = ptDescriptor->globals.usagePage;
111 ptUsageItem->usage = ptItem->unsignedValue;
112 }
113 break;
114 /*
115 * Note that Tag = usage Minimum Item may represent either
116 * a UsagePair with the usagePage implied, or
117 * a UsagePair defined by an extended usage
118 * If a Tag = usage Item has 1 or 2 bytes of data
119 * then the current usagePage is used
120 * If a Tag = usage Item has 4 bytes of data
121 * then the high order bytes are the usagePage
122 */
123 case kHIDTagUsageMinimum:
124 if (ptDescriptor->haveUsageMax)
125 {
126 ptUsageItem = &ptPreparsedData->usageItems[ptPreparsedData->usageItemCount++];
127 ptUsageItem->isRange = true;
128 if (ptItem->byteCount == 4)
129 {
130 ptUsageItem->usagePage = ptItem->unsignedValue>>16;
131 ptUsageItem->usageMinimum = ptItem->unsignedValue&0xFFFFL;
132 }
133 else
134 {
135 ptUsageItem->usagePage = ptDescriptor->globals.usagePage;
136 ptUsageItem->usageMinimum = ptItem->unsignedValue;
137 }
138 if (ptUsageItem->usagePage != ptDescriptor->rangeUsagePage)
139 return kHIDInvalidRangePageErr;
140 ptUsageItem->usageMaximum = ptDescriptor->usageMaximum;
141 if (ptUsageItem->usageMaximum < ptUsageItem->usageMinimum)
142 return kHIDInvertedUsageRangeErr;
143 ptDescriptor->haveUsageMax = false;
144 ptDescriptor->haveUsageMin = false;
145 }
146 else
147 {
148 if (ptItem->byteCount == 4)
149 {
150 ptDescriptor->rangeUsagePage = ptItem->unsignedValue>>16;
151 ptDescriptor->usageMinimum = ptItem->unsignedValue&0xFFFFL;
152 }
153 else
154 {
155 ptDescriptor->rangeUsagePage = ptDescriptor->globals.usagePage;
156 ptDescriptor->usageMinimum = ptItem->unsignedValue;
157 }
158 ptDescriptor->haveUsageMin = true;
159 }
160 break;
161 /*
162 * Note that Tag = usage Maximum Item may represent either
163 * a UsagePair with the usagePage implied, or
164 * a UsagePair defined by an extended usage
165 * If a Tag = usage Item has 1 or 2 bytes of data
166 * then the current usagePage is used
167 * If a Tag = usage Item has 4 bytes of data
168 * then the high order bytes are the usagePage
169 */
170 case kHIDTagUsageMaximum:
171 if (ptDescriptor->haveUsageMin)
172 {
173 ptUsageItem = &ptPreparsedData->usageItems[ptPreparsedData->usageItemCount++];
174 ptUsageItem->isRange = true;
175 if (ptItem->byteCount == 4)
176 {
177 ptUsageItem->usagePage = ptItem->unsignedValue>>16;
178 ptUsageItem->usageMaximum = ptItem->unsignedValue&0xFFFFL;
179 }
180 else
181 {
182 ptUsageItem->usagePage = ptDescriptor->globals.usagePage;
183 ptUsageItem->usageMaximum = ptItem->unsignedValue;
184 }
185 if (ptUsageItem->usagePage != ptDescriptor->rangeUsagePage)
186 return kHIDInvalidRangePageErr;
187 ptUsageItem->usageMinimum = ptDescriptor->usageMinimum;
188 if (ptUsageItem->usageMaximum < ptUsageItem->usageMinimum)
189 return kHIDInvertedUsageRangeErr;
190 ptDescriptor->haveUsageMax = false;
191 ptDescriptor->haveUsageMin = false;
192 }
193 else
194 {
195 if (ptItem->byteCount == 4)
196 {
197 ptDescriptor->rangeUsagePage = ptItem->unsignedValue>>16;
198 ptDescriptor->usageMaximum = ptItem->unsignedValue&0xFFFFL;
199 }
200 else
201 {
202 ptDescriptor->rangeUsagePage = ptDescriptor->globals.usagePage;
203 ptDescriptor->usageMaximum = ptItem->unsignedValue;
204 }
205 ptDescriptor->haveUsageMax = true;
206 }
207 break;
208 /*
209 * Designators
210 */
211 case kHIDTagDesignatorIndex:
212 ptDesignatorItem = &ptPreparsedData->desigItems[ptPreparsedData->desigItemCount++];
213 ptDesignatorItem->isRange = false;
214 ptDesignatorItem->index = ptItem->unsignedValue;
215 break;
216 case kHIDTagDesignatorMinimum:
217 if (ptDescriptor->haveDesigMax)
218 {
219 ptDesignatorItem = &ptPreparsedData->desigItems[ptPreparsedData->desigItemCount++];
220 ptDesignatorItem->isRange = true;
221 ptDesignatorItem->minimum = ptItem->unsignedValue;
222 ptDesignatorItem->maximum = ptDescriptor->desigMaximum;
223 ptDescriptor->haveDesigMin = false;
224 ptDescriptor->haveDesigMax = false;
225 }
226 else
227 {
228 ptDescriptor->desigMinimum = ptItem->unsignedValue;
229 ptDescriptor->haveDesigMin = true;
230 }
231 break;
232 case kHIDTagDesignatorMaximum:
233 if (ptDescriptor->haveDesigMin)
234 {
235 ptDesignatorItem = &ptPreparsedData->desigItems[ptPreparsedData->desigItemCount++];
236 ptDesignatorItem->isRange = true;
237 ptDesignatorItem->maximum = ptItem->unsignedValue;
238 ptDesignatorItem->minimum = ptDescriptor->desigMinimum;
239 ptDescriptor->haveDesigMin = false;
240 ptDescriptor->haveDesigMax = false;
241 }
242 else
243 {
244 ptDescriptor->desigMaximum = ptItem->unsignedValue;
245 ptDescriptor->haveDesigMax = true;
246 }
247 break;
248 /*
249 * Strings
250 */
251 case kHIDTagStringIndex:
252 ptStringItem = &ptPreparsedData->stringItems[ptPreparsedData->stringItemCount++];
253 ptStringItem->isRange = false;
254 ptStringItem->index = ptItem->unsignedValue;
255 break;
256 case kHIDTagStringMinimum:
257 if (ptDescriptor->haveStringMax)
258 {
259 ptStringItem = &ptPreparsedData->stringItems[ptPreparsedData->stringItemCount++];
260 ptStringItem->isRange = true;
261 ptStringItem->minimum = ptItem->unsignedValue;
262 ptStringItem->maximum = ptDescriptor->stringMaximum;
263 ptDescriptor->haveStringMin = false;
264 ptDescriptor->haveStringMax = false;
265 }
266 else
267 {
268 ptDescriptor->stringMinimum = ptItem->unsignedValue;
269 ptDescriptor->haveStringMin = true;
270 }
271 break;
272 case kHIDTagStringMaximum:
273 if (ptDescriptor->haveStringMin)
274 {
275 ptStringItem = &ptPreparsedData->stringItems[ptPreparsedData->stringItemCount++];
276 ptStringItem->isRange = true;
277 ptStringItem->maximum = ptItem->unsignedValue;
278 ptStringItem->minimum = ptDescriptor->stringMinimum;
279 ptDescriptor->haveStringMin = false;
280 ptDescriptor->haveStringMax = false;
281 }
282 else
283 {
284 ptDescriptor->stringMaximum = ptItem->unsignedValue;
285 ptDescriptor->haveStringMax = true;
286 }
287 break;
288 /*
289 * Delimiters (are not processed)
290 */
291 case kHIDTagSetDelimiter:
292 break;
293 }
294 return kHIDSuccess;
295 }