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: HIDProcessLocalItem.c 25 26 Contains: xxx put contents here xxx 27 28 Version: xxx put version here xxx 29 30 Copyright: � 1999 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 (BWS) Brent Schorsch 43 44 Change History (most recent first): 45 46 <USB1> 3/5/99 BWS first checked in 47*/ 48 49#include "HIDLib.h" 50 51/* 52 *------------------------------------------------------------------------------ 53 * 54 * HIDProcessLocalItem - Process a LocalItem 55 * 56 * Input: 57 * ptDescriptor - The Descriptor Structure 58 * ptPreparsedData - The PreParsedData Structure 59 * Output: 60 * ptPreparsedData - The PreParsedData Structure 61 * Returns: 62 * kHIDSuccess - Success 63 * kHIDNullPointerErr - Argument, Pointer was Null 64 * 65 *------------------------------------------------------------------------------ 66*/ 67OSStatus HIDProcessLocalItem(HIDReportDescriptor *ptDescriptor, 68 HIDPreparsedDataPtr ptPreparsedData) 69{ 70 HIDDesignatorItem *ptDesignatorItem; 71 HIDStringItem *ptStringItem; 72 HIDP_UsageItem *ptUsageItem; 73 HIDItem *ptItem; 74/* 75 * Disallow NULL Pointers 76*/ 77 if ((ptDescriptor == NULL) || (ptPreparsedData == NULL)) 78 return kHIDNullPointerErr; 79/* 80 * Process the LocalItem by tag 81*/ 82 ptItem = &ptDescriptor->item; 83 switch (ptItem->tag) 84 { 85/* 86 * Note that Tag = usage Item may represent either 87 * a UsagePair with the usagePage implied, or 88 * a UsagePair defined by an extended usage 89 * If a Tag = usage Item has 1 or 2 bytes of data 90 * then the current usagePage is used 91 * If a Tag = usage Item has 4 bytes of data 92 * then the high order bytes are the usagePage 93 * 94 * Note that the Microsoft HID Parser uses the last 95 * usagePage defined before the MainItem with which 96 * the usage is associated rather than the current 97 * usagePage. The method used here is more generic 98 * although multiple UsagePages for a MainItem are 99 * unlikely due to the MS limitation. 100*/ 101 case kHIDTagUsage: 102 ptUsageItem = &ptPreparsedData->usageItems[ptPreparsedData->usageItemCount++]; 103 ptUsageItem->isRange = false; 104 if (ptItem->byteCount == 4) 105 { 106 ptUsageItem->usagePage = ptItem->unsignedValue>>16; 107 ptUsageItem->usage = ptItem->unsignedValue&0xFFFFL; 108 } 109 else 110 { 111 ptUsageItem->usagePage = ptDescriptor->globals.usagePage; 112 ptUsageItem->usage = ptItem->unsignedValue; 113 } 114 break; 115/* 116 * Note that Tag = usage Minimum Item may represent either 117 * a UsagePair with the usagePage implied, or 118 * a UsagePair defined by an extended usage 119 * If a Tag = usage Item has 1 or 2 bytes of data 120 * then the current usagePage is used 121 * If a Tag = usage Item has 4 bytes of data 122 * then the high order bytes are the usagePage 123*/ 124 case kHIDTagUsageMinimum: 125 if (ptDescriptor->haveUsageMax) 126 { 127 ptUsageItem = &ptPreparsedData->usageItems[ptPreparsedData->usageItemCount++]; 128 ptUsageItem->isRange = true; 129 if (ptItem->byteCount == 4) 130 { 131 ptUsageItem->usagePage = ptItem->unsignedValue>>16; 132 ptUsageItem->usageMinimum = ptItem->unsignedValue&0xFFFFL; 133 } 134 else 135 { 136 ptUsageItem->usagePage = ptDescriptor->globals.usagePage; 137 ptUsageItem->usageMinimum = ptItem->unsignedValue; 138 } 139 if (ptUsageItem->usagePage != ptDescriptor->rangeUsagePage) 140 return kHIDInvalidRangePageErr; 141 ptUsageItem->usageMaximum = ptDescriptor->usageMaximum; 142 if (ptUsageItem->usageMaximum < ptUsageItem->usageMinimum) 143 return kHIDInvertedUsageRangeErr; 144 ptDescriptor->haveUsageMax = false; 145 ptDescriptor->haveUsageMin = false; 146 } 147 else 148 { 149 if (ptItem->byteCount == 4) 150 { 151 ptDescriptor->rangeUsagePage = ptItem->unsignedValue>>16; 152 ptDescriptor->usageMinimum = ptItem->unsignedValue&0xFFFFL; 153 } 154 else 155 { 156 ptDescriptor->rangeUsagePage = ptDescriptor->globals.usagePage; 157 ptDescriptor->usageMinimum = ptItem->unsignedValue; 158 } 159 ptDescriptor->haveUsageMin = true; 160 } 161 break; 162/* 163 * Note that Tag = usage Maximum Item may represent either 164 * a UsagePair with the usagePage implied, or 165 * a UsagePair defined by an extended usage 166 * If a Tag = usage Item has 1 or 2 bytes of data 167 * then the current usagePage is used 168 * If a Tag = usage Item has 4 bytes of data 169 * then the high order bytes are the usagePage 170*/ 171 case kHIDTagUsageMaximum: 172 if (ptDescriptor->haveUsageMin) 173 { 174 ptUsageItem = &ptPreparsedData->usageItems[ptPreparsedData->usageItemCount++]; 175 ptUsageItem->isRange = true; 176 if (ptItem->byteCount == 4) 177 { 178 ptUsageItem->usagePage = ptItem->unsignedValue>>16; 179 ptUsageItem->usageMaximum = ptItem->unsignedValue&0xFFFFL; 180 } 181 else 182 { 183 ptUsageItem->usagePage = ptDescriptor->globals.usagePage; 184 ptUsageItem->usageMaximum = ptItem->unsignedValue; 185 } 186 if (ptUsageItem->usagePage != ptDescriptor->rangeUsagePage) 187 return kHIDInvalidRangePageErr; 188 ptUsageItem->usageMinimum = ptDescriptor->usageMinimum; 189 if (ptUsageItem->usageMaximum < ptUsageItem->usageMinimum) 190 return kHIDInvertedUsageRangeErr; 191 ptDescriptor->haveUsageMax = false; 192 ptDescriptor->haveUsageMin = false; 193 } 194 else 195 { 196 if (ptItem->byteCount == 4) 197 { 198 ptDescriptor->rangeUsagePage = ptItem->unsignedValue>>16; 199 ptDescriptor->usageMaximum = ptItem->unsignedValue&0xFFFFL; 200 } 201 else 202 { 203 ptDescriptor->rangeUsagePage = ptDescriptor->globals.usagePage; 204 ptDescriptor->usageMaximum = ptItem->unsignedValue; 205 } 206 ptDescriptor->haveUsageMax = true; 207 } 208 break; 209/* 210 * Designators 211*/ 212 case kHIDTagDesignatorIndex: 213 ptDesignatorItem = &ptPreparsedData->desigItems[ptPreparsedData->desigItemCount++]; 214 ptDesignatorItem->isRange = false; 215 ptDesignatorItem->index = ptItem->unsignedValue; 216 break; 217 case kHIDTagDesignatorMinimum: 218 if (ptDescriptor->haveDesigMax) 219 { 220 ptDesignatorItem = &ptPreparsedData->desigItems[ptPreparsedData->desigItemCount++]; 221 ptDesignatorItem->isRange = true; 222 ptDesignatorItem->minimum = ptItem->unsignedValue; 223 ptDesignatorItem->maximum = ptDescriptor->desigMaximum; 224 ptDescriptor->haveDesigMin = false; 225 ptDescriptor->haveDesigMax = false; 226 } 227 else 228 { 229 ptDescriptor->desigMinimum = ptItem->unsignedValue; 230 ptDescriptor->haveDesigMin = true; 231 } 232 break; 233 case kHIDTagDesignatorMaximum: 234 if (ptDescriptor->haveDesigMin) 235 { 236 ptDesignatorItem = &ptPreparsedData->desigItems[ptPreparsedData->desigItemCount++]; 237 ptDesignatorItem->isRange = true; 238 ptDesignatorItem->maximum = ptItem->unsignedValue; 239 ptDesignatorItem->minimum = ptDescriptor->desigMinimum; 240 ptDescriptor->haveDesigMin = false; 241 ptDescriptor->haveDesigMax = false; 242 } 243 else 244 { 245 ptDescriptor->desigMaximum = ptItem->unsignedValue; 246 ptDescriptor->haveDesigMax = true; 247 } 248 break; 249/* 250 * Strings 251*/ 252 case kHIDTagStringIndex: 253 ptStringItem = &ptPreparsedData->stringItems[ptPreparsedData->stringItemCount++]; 254 ptStringItem->isRange = false; 255 ptStringItem->index = ptItem->unsignedValue; 256 break; 257 case kHIDTagStringMinimum: 258 if (ptDescriptor->haveStringMax) 259 { 260 ptStringItem = &ptPreparsedData->stringItems[ptPreparsedData->stringItemCount++]; 261 ptStringItem->isRange = true; 262 ptStringItem->minimum = ptItem->unsignedValue; 263 ptStringItem->maximum = ptDescriptor->stringMaximum; 264 ptDescriptor->haveStringMin = false; 265 ptDescriptor->haveStringMax = false; 266 } 267 else 268 { 269 ptDescriptor->stringMinimum = ptItem->unsignedValue; 270 ptDescriptor->haveStringMin = true; 271 } 272 break; 273 case kHIDTagStringMaximum: 274 if (ptDescriptor->haveStringMin) 275 { 276 ptStringItem = &ptPreparsedData->stringItems[ptPreparsedData->stringItemCount++]; 277 ptStringItem->isRange = true; 278 ptStringItem->maximum = ptItem->unsignedValue; 279 ptStringItem->minimum = ptDescriptor->stringMinimum; 280 ptDescriptor->haveStringMin = false; 281 ptDescriptor->haveStringMax = false; 282 } 283 else 284 { 285 ptDescriptor->stringMaximum = ptItem->unsignedValue; 286 ptDescriptor->haveStringMax = true; 287 } 288 break; 289/* 290 * Delimiters (are not processed) 291*/ 292 case kHIDTagSetDelimiter: 293 break; 294 } 295 return kHIDSuccess; 296} 297