]> git.saurik.com Git - apple/xnu.git/blob - iokit/Families/IOHIDSystem/IOHIDDescriptorParser/HIDGetButtonsOnPage.c
xnu-124.13.tar.gz
[apple/xnu.git] / iokit / Families / IOHIDSystem / IOHIDDescriptorParser / HIDGetButtonsOnPage.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: HIDGetButtonsOnPage.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 (KH) Keithen Hayenga
42 (BWS) Brent Schorsch
43
44 Change History (most recent first):
45
46 <USB5> 3/24/00 KH Complex report descriptors could lead to reporting
47 kHIDUsageNotFoundErr's as kHIDIncompatibleReportErr's instead.
48 <USB4> 11/1/99 BWS [2405720] We need a better check for 'bit padding' items,
49 rather than just is constant. We will check to make sure the
50 item is constant, and has no usage, or zero usage. This means we
51 need to pass an additional parameter to some internal functions
52 <USB3> 5/26/99 BWS We are not checking the usage page for bitmapped buttons! This
53 caused the Wingman Extreme to get the tilt button on the user
54 page confused with the first button on the button page.
55 <USB2> 4/7/99 BWS Add support for reversed report items
56 <USB1> 3/5/99 BWS first checked in
57 */
58
59 #include "HIDLib.h"
60
61 /*
62 *------------------------------------------------------------------------------
63 *
64 * HIDGetButtonsOnPage - Get the state of the buttons for a Page
65 *
66 * Input:
67 * reportType - HIDP_Input, HIDP_Output, HIDP_Feature
68 * usagePage - Page Criteria or zero
69 * iCollection - Collection Criteria or zero
70 * piUsageList - Usages for pressed buttons
71 * piUsageListLength - Max entries in UsageList
72 * ptPreparsedData - Pre-Parsed Data
73 * psReport - An HID Report
74 * iReportLength - The length of the Report
75 * Output:
76 * piValue - Pointer to usage Value
77 * Returns:
78 *
79 *------------------------------------------------------------------------------
80 */
81 OSStatus HIDGetButtonsOnPage(HIDReportType reportType,
82 HIDUsage usagePage,
83 UInt32 iCollection,
84 HIDUsage *piUsageList,
85 UInt32 *piUsageListLength,
86 HIDPreparsedDataRef preparsedDataRef,
87 void *psReport,
88 UInt32 iReportLength)
89 {
90 HIDPreparsedDataPtr ptPreparsedData = (HIDPreparsedDataPtr) preparsedDataRef;
91 HIDUsageAndPage tUsageAndPage;
92 HIDCollection *ptCollection;
93 HIDReportItem *ptReportItem;
94 OSStatus iStatus;
95 int iR, iE;
96 long iValue;
97 int iStart;
98 int iMaxUsages;
99 int iReportItem;
100 Boolean bIncompatibleReport = false;
101 Boolean butNotReally = false;
102 /*
103 * Disallow Null Pointers
104 */
105 if ((ptPreparsedData == NULL)
106 || (piUsageList == NULL)
107 || (piUsageListLength == NULL)
108 || (psReport == NULL))
109 return kHIDNullPointerErr;
110 if (ptPreparsedData->hidTypeIfValid != kHIDOSType)
111 return kHIDInvalidPreparsedDataErr;
112 /*
113 * The Collection must be in range
114 */
115 if ((iCollection < 0) || (iCollection >= ptPreparsedData->collectionCount))
116 return kHIDBadParameterErr;
117 /*
118 * Save the size of the list
119 */
120 iMaxUsages = *piUsageListLength;
121 *piUsageListLength = 0;
122 /*
123 * Search only the scope of the Collection specified
124 * Go through the ReportItems
125 * Filter on ReportType and usagePage
126 */
127 ptCollection = &ptPreparsedData->collections[iCollection];
128 for (iR=0; iR<ptCollection->reportItemCount; iR++)
129 {
130 iReportItem = ptCollection->firstReportItem + iR;
131 ptReportItem = &ptPreparsedData->reportItems[iReportItem];
132 if (HIDIsButton(ptReportItem, preparsedDataRef))
133 {
134 /*
135 * This may be the proper data to get
136 * Let's check for the proper Report ID, Type, and Length
137 */
138 iStatus = HIDCheckReport(reportType,preparsedDataRef,ptReportItem,
139 psReport,iReportLength);
140 /*
141 * The Report ID or Type may not match.
142 * This may not be an error (yet)
143 */
144 if (iStatus == kHIDIncompatibleReportErr)
145 bIncompatibleReport = true;
146 else if (iStatus != kHIDSuccess)
147 return iStatus;
148 else
149 {
150 butNotReally = true;
151 /*
152 * Save Array Buttons
153 */
154 iStart = ptReportItem->startBit;
155 for (iE=0; iE<ptReportItem->globals.reportCount; iE++)
156 {
157 if ((ptReportItem->dataModes & kHIDDataArrayBit) == kHIDDataArray)
158 {
159 iStatus = HIDGetData(psReport, iReportLength, iStart,
160 ptReportItem->globals.reportSize,
161 &iValue, false);
162 if (!iStatus)
163 iStatus = HIDPostProcessRIValue (ptReportItem, &iValue);
164 HIDUsageAndPageFromIndex(preparsedDataRef,
165 ptReportItem,
166 iValue-ptReportItem->globals.logicalMinimum,
167 &tUsageAndPage);
168 iStart += ptReportItem->globals.reportSize;
169 if (usagePage == tUsageAndPage.usagePage)
170 {
171 if (*piUsageListLength >= iMaxUsages)
172 return kHIDBufferTooSmallErr;
173 piUsageList[(*piUsageListLength)++] = iValue;
174 }
175 }
176 /*
177 * Save Bitmapped Buttons
178 */
179 else
180 {
181 iStatus = HIDGetData(psReport, iReportLength, iStart, 1, &iValue, false);
182 if (!iStatus)
183 iStatus = HIDPostProcessRIValue (ptReportItem, &iValue);
184 iStart++;
185 if (!iStatus && iValue != 0)
186 {
187 HIDUsageAndPageFromIndex(preparsedDataRef,ptReportItem,iE,&tUsageAndPage);
188 if (usagePage == tUsageAndPage.usagePage)
189 {
190 if (*piUsageListLength >= iMaxUsages)
191 return kHIDBufferTooSmallErr;
192 piUsageList[(*piUsageListLength)++] = tUsageAndPage.usage;
193 }
194 }
195 }
196 }
197 }
198 }
199 }
200 /*
201 * If nothing was returned then change the status
202 */
203 if (*piUsageListLength == 0)
204 {
205 // If any of the report items were not the right type, we have set the bIncompatibleReport flag.
206 // However, if any of the report items really were the correct type, we have done our job of checking
207 // and really didn't find a usage. Don't let the bIncompatibleReport flag wipe out our valid test.
208 if (bIncompatibleReport && !butNotReally)
209 return kHIDIncompatibleReportErr;
210 return kHIDUsageNotFoundErr;
211 }
212 return kHIDSuccess;
213 }