]> git.saurik.com Git - apple/xnu.git/blob - iokit/Families/IOHIDSystem/IOHIDDescriptorParser/HIDProcessReportItem.c
xnu-123.5.tar.gz
[apple/xnu.git] / iokit / Families / IOHIDSystem / IOHIDDescriptorParser / HIDProcessReportItem.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: HIDProcessReportItem.c
24
25 Contains: xxx put contents here xxx
26
27 Version: xxx put version here xxx
28
29 Copyright: © 1999-2000 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 (DF) David Ferguson
43 (BWS) Brent Schorsch
44
45 Change History (most recent first):
46
47 <USB10> 1/11/00 KH Tweaking last fix. For logical maximum, limit shifting into the
48 sign bit only for report sizes of 32 bits or greater.
49 <USB9> 1/10/00 DF re-do last change (better fix).
50 <USB8> 1/10/00 DF do proper logical range test for 32-bit report items.
51 <USB7> 4/7/99 BWS Add support for reversed report items
52 <USB6> 3/20/99 BWS Oops, strict error checking does not work if there is no error.
53 We should only return error if it is not noErr
54 <USB5> 3/17/99 BWS [2314839] Added flags field to HIDPreparsedData which is set in
55 new parameter to HIDOpenReportDescriptor. We check the
56 StrictErrorCheck bit to determine whether we return errors or
57 just try to work around problems we find
58 <USB4> 3/7/99 BWS [2311413] Do not error check min/max ranges for constants
59 <USB3> 3/7/99 BWS [2311412] We need to handle the cases where physical min/max is
60 either (0/0) which is valid according to the spec, and means to
61 use the logical min/max, and the invalid case, that some devices
62 exibit, which has (0/-1) which we will treat the same,
63 <USB2> 3/5/99 BWS [2311359] HIDProcessReportItem does not initialize startBit
64 field of HIDReportItem!
65 <USB1> 3/5/99 BWS first checked in
66 */
67
68 #include "HIDLib.h"
69
70 /*
71 *------------------------------------------------------------------------------
72 *
73 * HIDProcessReportItem - Process a Report Item MainItem
74 *
75 * Input:
76 * ptDescriptor - The Descriptor Structure
77 * ptPreparsedData - The PreParsedData Structure
78 * Output:
79 * ptDescriptor - The Descriptor Structure
80 * ptPreparsedData - The PreParsedData Structure
81 * Returns:
82 * kHIDSuccess - Success
83 * kHIDNullPointerErr - Argument, Pointer was Null
84 *
85 *------------------------------------------------------------------------------
86 */
87 OSStatus HIDProcessReportItem(HIDReportDescriptor *ptDescriptor, HIDPreparsedDataPtr ptPreparsedData)
88 {
89 OSStatus error = noErr;
90 HIDReportItem *ptReportItem;
91 HIDReportSizes *ptReport;
92 int iBits;
93 /*
94 * Disallow NULL Pointers
95 */
96
97 if ((ptDescriptor == NULL) || (ptPreparsedData == NULL))
98 return kHIDNullPointerErr;
99 /*
100 * Begin to initialize the new Report Item structure
101 */
102
103 ptReportItem = &ptPreparsedData->reportItems[ptPreparsedData->reportItemCount++];
104 ptReportItem->dataModes = ptDescriptor->item.unsignedValue;
105 ptReportItem->globals = ptDescriptor->globals;
106 ptReportItem->flags = 0;
107
108 /*
109 * Reality Check on the Report Main Item
110 */
111 // Don't check ranges for constants (MS Sidewinder, for one, does not reset)
112 //if (!(ptReportItem->dataModes & kHIDDataConstantBit)) // don't think we need this anymore
113 {
114 // Determine the maximum signed value for a given report size.
115 // (Don't allow shifting into sign bit.)
116 SInt32 posSize = (ptReportItem->globals.reportSize >= 32) ?
117 31 : ptReportItem->globals.reportSize;
118 SInt32 realMax = (1<<posSize) - 1;
119
120 if (ptReportItem->globals.logicalMinimum > realMax)
121 {
122 error = kHIDBadLogicalMinimumErr;
123 ptReportItem->globals.logicalMinimum = 0;
124 }
125 if (ptReportItem->globals.logicalMaximum > realMax)
126 {
127 if (error == noErr)
128 error = kHIDBadLogicalMaximumErr;
129 ptReportItem->globals.logicalMaximum = realMax;
130 }
131 if (ptReportItem->globals.logicalMinimum > ptReportItem->globals.logicalMaximum)
132 {
133 SInt32 temp;
134 if (error == noErr)
135 error = kHIDInvertedLogicalRangeErr;
136
137 // mark as a 'reversed' item
138 ptReportItem->flags |= kHIDReportItemFlag_Reversed;
139
140 temp = ptReportItem->globals.logicalMaximum;
141 ptReportItem->globals.logicalMaximum = ptReportItem->globals.logicalMinimum;
142 ptReportItem->globals.logicalMinimum = temp;
143 }
144 }
145
146 // check to see if we got half a range (we don't need to fix this, since 'isRange' will be false
147 if ((error == noErr) && (ptDescriptor->haveUsageMin || ptDescriptor->haveUsageMax))
148 error = kHIDUnmatchedUsageRangeErr;
149 if ((error == noErr) && (ptDescriptor->haveStringMin || ptDescriptor->haveStringMax))
150 error = kHIDUnmatchedStringRangeErr;
151 if ((error == noErr) && (ptDescriptor->haveDesigMin || ptDescriptor->haveDesigMax))
152 error = kHIDUnmatchedDesignatorRangeErr;
153
154 // if the physical min/max are out of wack, use the logical values
155 if (ptReportItem->globals.physicalMinimum >= ptReportItem->globals.physicalMaximum)
156 {
157 // equal to each other is not an error, just means to use the logical values
158 if ((error == noErr) &&
159 (ptReportItem->globals.physicalMinimum > ptReportItem->globals.physicalMaximum))
160 error = kHIDInvertedPhysicalRangeErr;
161
162 ptReportItem->globals.physicalMinimum = ptReportItem->globals.logicalMinimum;
163 ptReportItem->globals.physicalMaximum = ptReportItem->globals.logicalMaximum;
164 }
165
166 // if strict error checking is true, return any errors
167 if (error != noErr && ptPreparsedData->flags & kHIDFlag_StrictErrorChecking)
168 return error;
169
170 /*
171 * Continue to initialize the new Report Item structure
172 */
173
174 ptReportItem->parent = ptDescriptor->parent;
175 ptReportItem->firstUsageItem = ptDescriptor->firstUsageItem;
176 ptDescriptor->firstUsageItem = ptPreparsedData->usageItemCount;
177 ptReportItem->usageItemCount = ptPreparsedData->usageItemCount - ptReportItem->firstUsageItem;
178 ptReportItem->firstStringItem = ptDescriptor->firstStringItem;
179 ptDescriptor->firstStringItem = ptPreparsedData->stringItemCount;
180 ptReportItem->stringItemCount = ptPreparsedData->stringItemCount - ptReportItem->firstStringItem;
181 ptReportItem->firstDesigItem = ptDescriptor->firstDesigItem;
182 ptDescriptor->firstDesigItem = ptPreparsedData->desigItemCount;
183 ptReportItem->desigItemCount = ptPreparsedData->desigItemCount - ptReportItem->firstDesigItem;
184 /*
185 * Update the Report by the size of this item
186 */
187
188 ptReport = &ptPreparsedData->reports[ptReportItem->globals.reportIndex];
189 iBits = ptReportItem->globals.reportSize * ptReportItem->globals.reportCount;
190 switch (ptDescriptor->item.tag)
191 {
192 case kHIDTagFeature:
193 ptReportItem->reportType = kHIDFeatureReport;
194 ptReportItem->startBit = ptReport->featureBitCount;
195 ptReport->featureBitCount += iBits;
196 break;
197 case kHIDTagOutput:
198 ptReportItem->reportType = kHIDOutputReport;
199 ptReportItem->startBit = ptReport->outputBitCount;
200 ptReport->outputBitCount += iBits;
201 break;
202 case kHIDTagInput:
203 ptReportItem->reportType = kHIDInputReport;
204 ptReportItem->startBit = ptReport->inputBitCount;
205 ptReport->inputBitCount += iBits;
206 break;
207 default:
208 ptReportItem->reportType = kHIDUnknownReport;
209 ptReportItem->startBit = 0;
210 break;
211 }
212 return kHIDSuccess;
213 }