1/*
2 * @APPLE_LICENSE_HEADER_START@
3 *
4 * Copyright (c) 1999-2012 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:		HIDGetUsageValueArray.c
25
26	Contains:	xxx put contents here xxx
27
28	Version:	xxx put version here xxx
29
30	Copyright:	� 1999-2001 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	  <USB5>	 1/18/01	KH		Fix for complex descriptors only needed for buttons.
48	  <USB4>	 3/24/00	KH		Complex report descriptors could lead to reporting
49									kHIDUsageNotFoundErr's as kHIDIncompatibleReportErr's instead.
50	  <USB3>	 11/1/99	BWS		[2405720]  We need a better check for 'bit padding' items,
51									rather than just is constant. We will check to make sure the
52									item is constant, and has no usage, or zero usage. This means we
53									need to pass an additional parameter to some internal functions
54	  <USB2>	  4/7/99	BWS		Add support for reversed report items
55	  <USB1>	  3/5/99	BWS		first checked in
56*/
57
58#include "HIDLib.h"
59
60/*
61 *------------------------------------------------------------------------------
62 *
63 * HIDP_GetUsageValueArray - Get the values for a usage
64 *
65 *	 Input:
66 *			  reportType		   - HIDP_Input, HIDP_Output, HIDP_Feature
67 *			  usagePage			   - Page Criteria
68 *			  iCollection			- Collection Criteria or zero
69 *			  usage				   - usage Criteria
70 *			  psBuffer				- Pointer to usage Buffer
71 *			  iByteLength			- Length of usage Buffer
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*/
81OSStatus HIDGetUsageValueArray(HIDReportType reportType,
82									HIDUsage usagePage,
83									UInt32 iCollection,
84									HIDUsage usage,
85									UInt8 *psUsageBuffer,
86									IOByteCount iByteLength,
87									HIDPreparsedDataRef preparsedDataRef,
88									void *psReport,
89									IOByteCount iReportLength)
90{
91	HIDPreparsedDataPtr ptPreparsedData = (HIDPreparsedDataPtr) preparsedDataRef;
92	HIDCollection *ptCollection;
93	HIDReportItem *ptReportItem;
94	OSStatus iStatus;
95	int i;
96	int iR;
97	SInt32 iValue;
98	int iStart;
99	int iReportItem;
100	UInt32 iUsageIndex;
101	UInt32 iCount;
102	int byteCount;
103	Boolean bIncompatibleReport = false;
104/*
105 *	Disallow Null Pointers
106*/
107	if ((ptPreparsedData == NULL)
108	 || (psUsageBuffer == NULL)
109	 || (psReport == NULL))
110		return kHIDNullPointerErr;
111	if (ptPreparsedData->hidTypeIfValid != kHIDOSType)
112		return kHIDInvalidPreparsedDataErr;
113/*
114 *	The Collection must be in range
115*/
116	if (iCollection >= ptPreparsedData->collectionCount)
117		return kHIDBadParameterErr;
118/*
119 *	Search only the scope of the Collection specified
120 *	Go through the ReportItems
121 *	Filter on ReportType and usagePage
122*/
123	ptCollection = &ptPreparsedData->collections[iCollection];
124	for (iR=0; iR<ptCollection->reportItemCount; iR++)
125	{
126		iReportItem = ptCollection->firstReportItem + iR;
127		ptReportItem = &ptPreparsedData->reportItems[iReportItem];
128		if (HIDIsVariable(ptReportItem, preparsedDataRef)
129		 && HIDHasUsage(preparsedDataRef,ptReportItem,usagePage,usage,&iUsageIndex,&iCount))
130		{
131/*
132 *			This may be the proper data to get
133 *			Let's check for the proper Report ID, Type, and Length
134*/
135			iStatus = HIDCheckReport(reportType,preparsedDataRef,ptReportItem,
136									   psReport,iReportLength);
137/*
138 *			The Report ID or Type may not match.
139 *			This may not be an error (yet)
140*/
141			if (iStatus == kHIDIncompatibleReportErr)
142				bIncompatibleReport = true;
143			else if (iStatus != kHIDSuccess)
144				return iStatus;
145			else
146			{
147/*
148 *				Disallow single count variables
149 *				Count is set by HasUsage
150*/
151				if (iCount <= 1)
152					return kHIDNotValueArrayErr;
153/*
154 *				Get the data
155*/
156				iStart = ptReportItem->startBit + (ptReportItem->globals.reportSize * iUsageIndex);
157				byteCount = (ptReportItem->globals.reportSize * iCount + 7)/8;
158				if (byteCount > iByteLength)
159					byteCount = iByteLength;
160				for (i=0; i<byteCount; i++)
161				{
162					iStatus = HIDGetData(psReport, iReportLength, iStart, 8, &iValue,
163									   ((ptReportItem->globals.logicalMinimum < 0)
164									  ||(ptReportItem->globals.logicalMaximum < 0)));
165					if (!iStatus)
166						iStatus = HIDPostProcessRIValue (ptReportItem, &iValue);
167					if (iStatus != kHIDSuccess)
168						return iStatus;
169					*psUsageBuffer++ = (char) iValue;
170					iStart += 8;
171				}
172				return kHIDSuccess;
173			}
174		}
175	}
176	if (bIncompatibleReport)
177		return kHIDIncompatibleReportErr;
178	return kHIDUsageNotFoundErr;
179}
180