1/*
2 *
3 * @APPLE_LICENSE_HEADER_START@
4 *
5 * Copyright (c) 1999-2012 Apple Computer, Inc.  All Rights Reserved.
6 *
7 * This file contains Original Code and/or Modifications of Original Code
8 * as defined in and that are subject to the Apple Public Source License
9 * Version 2.0 (the 'License'). You may not use this file except in
10 * compliance with the License. Please obtain a copy of the License at
11 * http://www.opensource.apple.com/apsl/ and read it before using this
12 * file.
13 *
14 * The Original Code and all software distributed under the License are
15 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
16 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
17 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
19 * Please see the License for the specific language governing rights and
20 * limitations under the License.
21 *
22 * @APPLE_LICENSE_HEADER_END@
23 */
24/*
25	File:		HIDGetNextButtonInfo.c
26
27	Contains:	HIDGetNextButtonInfo call for HID Library
28
29	Version:	1.0d1
30
31	Copyright:	� 2000 by Apple Computer, Inc., all rights reserved.
32
33	File Ownership:
34
35		DRI:				David Ferguson
36
37		Other Contact:		Keithen Hayenga
38
39		Technology:			technologies, usb
40
41	Writers:
42
43		(KH)	Keithen Hayenga
44
45	Change History (most recent first):
46
47	  <USB1>	 2/14/00	KH		first checked in
48*/
49
50#include "HIDLib.h"
51
52/*
53 *------------------------------------------------------------------------------
54 *
55 * HIDGetNextButtonInfo - Get report id and collection for a button. In keeping
56 *								with USBGetNextInterface, we find the usage in the
57 *								next collection, so that you can find usages that
58 *								have the same usage and usage page.
59 *
60 *	 Input:
61 *			  reportType			- HIDP_Input, HIDP_Output, HIDP_Feature
62 *			  usagePage				- Page Criteria or zero
63 *			  usage					- The usage to get the information for
64 *			  collection			- Starting Collection Criteria or zero
65 *			  preparsedDataRef		- Pre-Parsed Data
66 *	 Output:
67 *			  collection			- Final Collection Criteria or no change
68 *			  reportID				- Report ID or no change
69 *	 Returns:
70 *
71 *------------------------------------------------------------------------------
72*/
73OSStatus HIDGetNextButtonInfo
74					   (HIDReportType			reportType,
75						HIDUsage				usagePage,
76						HIDUsage				usage,
77						UInt32 *				collection,
78						UInt8 *					reportID,
79						HIDPreparsedDataRef		preparsedDataRef)
80{
81	HIDPreparsedDataPtr ptPreparsedData = (HIDPreparsedDataPtr)preparsedDataRef;
82	HIDReportItem *ptReportItem;
83	UInt32 iCollection;
84	UInt32 newCollection = 0xFFFFFFFF;
85	int iR;
86	UInt8 newReportID = 0;
87	OSStatus iStatus = kHIDUsageNotFoundErr;
88
89	//Disallow Null Pointers
90
91	if ((ptPreparsedData == NULL) || (collection == NULL) || (reportID == NULL))
92		return kHIDNullPointerErr;
93	if (ptPreparsedData->hidTypeIfValid != kHIDOSType)
94		return kHIDInvalidPreparsedDataErr;
95
96	// The Collection must be in range
97
98	iCollection = *collection;
99	if (iCollection >= ptPreparsedData->collectionCount)
100		return kHIDBadParameterErr;
101
102	// HIDGetNextButtonInfo is different from HIDGetButton in how it treats
103	// the collection parameter. HIDGetButton will only look at report items that
104	// are within the collection and can therefore limit it's searches to starting at
105	// ptPreparsedData->collections[iCollection]->firstReportItem and only check
106	// ptPreparsedData->collections[iCollection]->reportItemCount. Since we want to
107	// find the NEXT collection as well, we need to cycle through all of the reports.
108
109	for (iR = 0; iR < ptPreparsedData->reportItemCount; iR++)
110	{
111		SInt32 minUsage;
112		SInt32 maxUsage;
113		HIDP_UsageItem thisUsage;
114
115		ptReportItem = &ptPreparsedData->reportItems[iR];
116
117		thisUsage = ptPreparsedData->usageItems[ptReportItem->firstUsageItem];
118
119		if (thisUsage.isRange)
120		{
121			minUsage = thisUsage.usageMinimum;
122			maxUsage = thisUsage.usageMaximum;
123		}
124		else
125		{
126			minUsage = thisUsage.usage;
127			maxUsage = thisUsage.usage;
128		}
129
130		if (ptReportItem->reportType == reportType &&
131			(usagePage == 0 || ptReportItem->globals.usagePage == usagePage) &&
132			(usage >= minUsage && usage <= maxUsage) &&
133			ptReportItem->parent > iCollection &&
134			HIDIsButton(ptReportItem, preparsedDataRef))
135		{
136			if (ptReportItem->parent < newCollection)
137			{
138				newCollection = ptReportItem->parent;
139				newReportID = iR;
140				iStatus = 0;
141			}
142		}
143	}
144
145	if (!iStatus)
146	{
147		*reportID = newReportID;
148		*collection = newCollection;
149	}
150
151	return iStatus;
152}
153