2 * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
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.
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
20 * @APPLE_LICENSE_HEADER_END@
23 File: HIDProcessReportItem.c
25 Contains: xxx put contents here xxx
27 Version: xxx put version here xxx
29 Copyright: © 1999-2000 by Apple Computer, Inc., all rights reserved.
33 DRI: xxx put dri here xxx
35 Other Contact: xxx put other contact here xxx
37 Technology: xxx put technology here xxx
45 Change History (most recent first):
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
71 *------------------------------------------------------------------------------
73 * HIDProcessReportItem - Process a Report Item MainItem
76 * ptDescriptor - The Descriptor Structure
77 * ptPreparsedData - The PreParsedData Structure
79 * ptDescriptor - The Descriptor Structure
80 * ptPreparsedData - The PreParsedData Structure
82 * kHIDSuccess - Success
83 * kHIDNullPointerErr - Argument, Pointer was Null
85 *------------------------------------------------------------------------------
87 OSStatus
HIDProcessReportItem(HIDReportDescriptor
*ptDescriptor
, HIDPreparsedDataPtr ptPreparsedData
)
89 OSStatus error
= noErr
;
90 HIDReportItem
*ptReportItem
;
91 HIDReportSizes
*ptReport
;
94 * Disallow NULL Pointers
97 if ((ptDescriptor
== NULL
) || (ptPreparsedData
== NULL
))
98 return kHIDNullPointerErr
;
100 * Begin to initialize the new Report Item structure
103 ptReportItem
= &ptPreparsedData
->reportItems
[ptPreparsedData
->reportItemCount
++];
104 ptReportItem
->dataModes
= ptDescriptor
->item
.unsignedValue
;
105 ptReportItem
->globals
= ptDescriptor
->globals
;
106 ptReportItem
->flags
= 0;
109 * Reality Check on the Report Main Item
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
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;
120 if (ptReportItem
->globals
.logicalMinimum
> realMax
)
122 error
= kHIDBadLogicalMinimumErr
;
123 ptReportItem
->globals
.logicalMinimum
= 0;
125 if (ptReportItem
->globals
.logicalMaximum
> realMax
)
128 error
= kHIDBadLogicalMaximumErr
;
129 ptReportItem
->globals
.logicalMaximum
= realMax
;
131 if (ptReportItem
->globals
.logicalMinimum
> ptReportItem
->globals
.logicalMaximum
)
135 error
= kHIDInvertedLogicalRangeErr
;
137 // mark as a 'reversed' item
138 ptReportItem
->flags
|= kHIDReportItemFlag_Reversed
;
140 temp
= ptReportItem
->globals
.logicalMaximum
;
141 ptReportItem
->globals
.logicalMaximum
= ptReportItem
->globals
.logicalMinimum
;
142 ptReportItem
->globals
.logicalMinimum
= temp
;
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
;
154 // if the physical min/max are out of wack, use the logical values
155 if (ptReportItem
->globals
.physicalMinimum
>= ptReportItem
->globals
.physicalMaximum
)
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
;
162 ptReportItem
->globals
.physicalMinimum
= ptReportItem
->globals
.logicalMinimum
;
163 ptReportItem
->globals
.physicalMaximum
= ptReportItem
->globals
.logicalMaximum
;
166 // if strict error checking is true, return any errors
167 if (error
!= noErr
&& ptPreparsedData
->flags
& kHIDFlag_StrictErrorChecking
)
171 * Continue to initialize the new Report Item structure
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
;
185 * Update the Report by the size of this item
188 ptReport
= &ptPreparsedData
->reports
[ptReportItem
->globals
.reportIndex
];
189 iBits
= ptReportItem
->globals
.reportSize
* ptReportItem
->globals
.reportCount
;
190 switch (ptDescriptor
->item
.tag
)
193 ptReportItem
->reportType
= kHIDFeatureReport
;
194 ptReportItem
->startBit
= ptReport
->featureBitCount
;
195 ptReport
->featureBitCount
+= iBits
;
198 ptReportItem
->reportType
= kHIDOutputReport
;
199 ptReportItem
->startBit
= ptReport
->outputBitCount
;
200 ptReport
->outputBitCount
+= iBits
;
203 ptReportItem
->reportType
= kHIDInputReport
;
204 ptReportItem
->startBit
= ptReport
->inputBitCount
;
205 ptReport
->inputBitCount
+= iBits
;
208 ptReportItem
->reportType
= kHIDUnknownReport
;
209 ptReportItem
->startBit
= 0;