1/*
2 * @APPLE_LICENSE_HEADER_START@
3 *
4 * Copyright (c) 1999-2003 Apple Computer, Inc.  All Rights Reserved.
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
11 * file.
12 *
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
20 *
21 * @APPLE_LICENSE_HEADER_END@
22 */
23/*
24	File:		HIDHasUsage.c
25
26	Contains:	xxx put contents here xxx
27
28	Version:	xxx put version here xxx
29
30	Copyright:	� 1999-2000 by Apple Computer, Inc., all rights reserved.
31
32	File Ownership:
33
34		DRI:				xxx put dri here xxx
35
36		Other Contact:		xxx put other contact here xxx
37
38		Technology:			xxx put technology here xxx
39
40	Writers:
41
42		(KH)	Keithen Hayenga
43		(BWS)	Brent Schorsch
44
45	Change History (most recent first):
46
47	  <USB2>	12/12/00	KH		range count off by 1.
48	  <USB1>	  3/5/99	BWS		first checked in
49*/
50
51#include "HIDLib.h"
52
53/*
54 *------------------------------------------------------------------------------
55 *
56 * HidP_UsageFromIndex
57 *
58 *	 Input:
59 *			  ptPreparsedData		- The Preparsed Data
60 *			  ptReportItem			- The Report Item
61 *			  usagePage			   - The usage Page to find
62 *			  usage				   - The usage to find
63 *			  piIndex(optional)		- The usage Index pointer (Can be used to tell
64 *										which bits in an array correspond to that usage.)
65 *			  piCount(optional)		- The usage Count pointer (Can be used to tell
66 *										how many items will be in a report.)
67 *	 Output:
68 *			  piIndex				- The usage Index
69 *	 Returns:
70 *			  The usage
71 *
72 *------------------------------------------------------------------------------
73*/
74Boolean HIDHasUsage (HIDPreparsedDataRef preparsedDataRef,
75					   HIDReportItem *ptReportItem,
76					   HIDUsage usagePage, HIDUsage usage,
77					   UInt32 *piIndex, UInt32 *piCount)
78{
79	HIDPreparsedDataPtr ptPreparsedData = (HIDPreparsedDataPtr) preparsedDataRef;
80	int iUsageItem;
81	UInt32 iUsageIndex;
82	int iUsages;
83	int i;
84	SInt32 iCountsLeft;
85	HIDP_UsageItem *ptUsageItem;
86	Boolean bOnPage;
87/*
88 *	Disallow Null Pointers
89*/
90	if ((ptPreparsedData == NULL)
91	 || (ptReportItem == NULL))
92		return 0;
93	if (ptPreparsedData->hidTypeIfValid != kHIDOSType)
94		return 0;
95/*
96 *	Look through the usage Items for this usage
97*/
98	iUsageItem = ptReportItem->firstUsageItem;
99	iUsageIndex = 0;
100	for (i=0; i<ptReportItem->usageItemCount; i++)
101	{
102/*
103 *	   Each usage Item is either a usage or a usage range
104*/
105		ptUsageItem = &ptPreparsedData->usageItems[iUsageItem++];
106		bOnPage = ((usagePage == 0) || (usagePage == ptUsageItem->usagePage));
107		if (ptUsageItem->isRange)
108		{
109/*
110 *			For usage Ranges
111 *			  If the index is in the range
112 *				then return the usage
113 *			  Otherwise adjust the index by the size of the range
114*/
115			if ((usage >= ptUsageItem->usageMinimum)
116			 && (usage <= ptUsageItem->usageMaximum))
117			{
118				if (piIndex != NULL)
119					*piIndex = iUsageIndex + (ptUsageItem->usageMinimum - usage);
120/*
121 *				If this usage is the last one for this ReportItem
122 *				  then it gets all of the remaining reportCount
123*/
124				if (piCount != NULL)
125				{
126					// piCount is going to be used to find which element in a button array is
127					// the one that returns the value for that usage.
128					if (((i+1) == ptReportItem->usageItemCount)
129					 && (usage == ptUsageItem->usageMaximum))
130					{
131						// Hmm, the same logic in the non-range case below was wrong. But things
132						// seem to be working for finding buttons, so i am not changing it here.
133						// However, we have made some changes to range calculations that may no
134						// longer require that -1 here either. Heads up!
135						iCountsLeft = ptReportItem->globals.reportCount - iUsageIndex - 1;
136						if (iCountsLeft > 1)
137							*piCount = iCountsLeft;
138						else
139							*piCount = 1;
140					}
141					else
142						*piCount = 1;
143				}
144				if (bOnPage)
145					return true;
146			}
147			iUsages = ptUsageItem->usageMaximum - ptUsageItem->usageMinimum;
148			if (iUsages < 0)
149				iUsages = -iUsages;
150			iUsages++;		// Add off by one adjustment AFTER sign correction.
151			iUsageIndex += iUsages;
152		}
153		else
154		{
155/*
156 *			For Usages
157 *			If the index is zero
158 *			  then return this usage
159 *			Otherwise one less to index through
160*/
161			if (usage == ptUsageItem->usage)
162			{
163				if (piIndex != NULL)
164					*piIndex = iUsageIndex;
165				if (piCount != NULL)
166				{
167					if ((i+1) == ptReportItem->usageItemCount)
168					{
169						// Keithen does not understand the logic of iCountsLeft.
170						// In Radar #2579612 we come through here for HIDGetUsageValueArray
171						// and HIDGetSpecificValueCaps. In both cases piCount that is returned
172						// should be the reportCount without the -1.
173//						iCountsLeft = ptReportItem->globals.reportCount - iUsageIndex - 1;
174						iCountsLeft = ptReportItem->globals.reportCount - iUsageIndex;
175						if (iCountsLeft > 1)
176							*piCount = iCountsLeft;
177						else
178						   *piCount = 1;
179					}
180					else
181						*piCount = 1;
182				}
183				if (bOnPage)
184					return true;
185			}
186			iUsageIndex++;
187		}
188	}
189	return false;
190}
191