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: HIDGetUsageValue.c
25 Contains: xxx put contents here xxx
27 Version: xxx put version here xxx
29 Copyright: © 1999-2001 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
44 Change History (most recent first):
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
60 *------------------------------------------------------------------------------
62 * HIDGetUsageValue - Get the value for a usage
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
74 * piValue - Pointer to usage Value
77 *------------------------------------------------------------------------------
79 OSStatus HIDGetUsageValue
80 (HIDReportType reportType
,
84 SInt32
* piUsageValue
,
85 HIDPreparsedDataRef preparsedDataRef
,
87 ByteCount iReportLength
)
89 HIDPreparsedDataPtr ptPreparsedData
= (HIDPreparsedDataPtr
) preparsedDataRef
;
90 HIDCollection
*ptCollection
;
91 HIDReportItem
*ptReportItem
;
98 Boolean bIncompatibleReport
= false;
100 * Disallow Null Pointers
102 if ((ptPreparsedData
== NULL
)
103 || (piUsageValue
== NULL
)
104 || (psReport
== NULL
))
105 return kHIDNullPointerErr
;
106 if (ptPreparsedData
->hidTypeIfValid
!= kHIDOSType
)
107 return kHIDInvalidPreparsedDataErr
;
109 * The Collection must be in range
111 if ((iCollection
< 0) || (iCollection
>= ptPreparsedData
->collectionCount
))
112 return kHIDBadParameterErr
;
114 * Search only the scope of the Collection specified
115 * Go through the ReportItems
116 * Filter on ReportType and usagePage
118 ptCollection
= &ptPreparsedData
->collections
[iCollection
];
119 for (iR
=0; iR
<ptCollection
->reportItemCount
; iR
++)
121 iReportItem
= ptCollection
->firstReportItem
+ iR
;
122 ptReportItem
= &ptPreparsedData
->reportItems
[iReportItem
];
123 if (HIDIsVariable(ptReportItem
, preparsedDataRef
)
124 && HIDHasUsage(preparsedDataRef
,ptReportItem
,usagePage
,usage
,&iUsageIndex
,NULL
))
127 * This may be the proper data to get
128 * Let's check for the proper Report ID, Type, and Length
130 iStatus
= HIDCheckReport(reportType
,preparsedDataRef
,ptReportItem
,
131 psReport
,iReportLength
);
133 * The Report ID or Type may not match.
134 * This may not be an error (yet)
136 if (iStatus
== kHIDIncompatibleReportErr
)
137 bIncompatibleReport
= true;
138 else if (iStatus
!= kHIDSuccess
)
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)));
152 iStatus
= HIDPostProcessRIValue (ptReportItem
, &iValue
);
153 *piUsageValue
= iValue
;
158 if (bIncompatibleReport
)
159 return kHIDIncompatibleReportErr
;
160 return kHIDUsageNotFoundErr
;
164 *------------------------------------------------------------------------------
166 * HIDGetScaledUsageValue - Get the value for a usage
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
178 * piValue - Pointer to usage Value
181 *------------------------------------------------------------------------------
183 OSStatus
HIDGetScaledUsageValue(HIDReportType reportType
,
187 SInt32
*piUsageValue
,
188 HIDPreparsedDataRef preparsedDataRef
,
190 ByteCount iReportLength
)
192 HIDPreparsedDataPtr ptPreparsedData
= (HIDPreparsedDataPtr
) preparsedDataRef
;
193 HIDCollection
*ptCollection
;
194 HIDReportItem
*ptReportItem
;
201 Boolean bIncompatibleReport
= false;
203 * Disallow Null Pointers
205 if ((ptPreparsedData
== NULL
)
206 || (piUsageValue
== NULL
)
207 || (psReport
== NULL
))
208 return kHIDNullPointerErr
;
209 if (ptPreparsedData
->hidTypeIfValid
!= kHIDOSType
)
210 return kHIDInvalidPreparsedDataErr
;
212 * The Collection must be in range
214 if ((iCollection
< 0) || (iCollection
>= ptPreparsedData
->collectionCount
))
215 return kHIDBadParameterErr
;
217 * Search only the scope of the Collection specified
218 * Go through the ReportItems
219 * Filter on ReportType and usagePage
221 ptCollection
= &ptPreparsedData
->collections
[iCollection
];
222 for (iR
=0; iR
<ptCollection
->reportItemCount
; iR
++)
224 iReportItem
= ptCollection
->firstReportItem
+ iR
;
225 ptReportItem
= &ptPreparsedData
->reportItems
[iReportItem
];
226 if (HIDIsVariable(ptReportItem
, preparsedDataRef
)
227 && HIDHasUsage(preparsedDataRef
,ptReportItem
,usagePage
,usage
,&iUsageIndex
,NULL
))
230 * This may be the proper data to get
231 * Let's check for the proper Report ID, Type, and Length
233 iStatus
= HIDCheckReport(reportType
,preparsedDataRef
,ptReportItem
,
234 psReport
,iReportLength
);
236 * The Report ID or Type may not match.
237 * This may not be an error (yet)
239 if (iStatus
== kHIDIncompatibleReportErr
)
240 bIncompatibleReport
= true;
241 else if (iStatus
!= kHIDSuccess
)
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)));
255 iStatus
= HIDPostProcessRIValue (ptReportItem
, &iValue
);
256 if (iStatus
!= kHIDSuccess
)
259 * Try to scale the data
261 iStatus
= HIDScaleUsageValueIn(ptReportItem
,iValue
,&iValue
);
262 *piUsageValue
= iValue
;
267 if (bIncompatibleReport
)
268 return kHIDIncompatibleReportErr
;
269 return kHIDUsageNotFoundErr
;