|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. ! 3: * ! 4: * @APPLE_LICENSE_HEADER_START@ ! 5: * ! 6: * Portions Copyright (c) 1999 Apple Computer, Inc. All Rights ! 7: * Reserved. This file contains Original Code and/or Modifications of ! 8: * Original Code as defined in and that are subject to the Apple Public ! 9: * Source License Version 1.1 (the "License"). You may not use this file ! 10: * except in compliance with the License. Please obtain a copy of the ! 11: * License at http://www.apple.com/publicsource and read it before using ! 12: * this 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 OR NON-INFRINGEMENT. Please see the ! 19: * License for the specific language governing rights and limitations ! 20: * under the License. ! 21: * ! 22: * @APPLE_LICENSE_HEADER_END@ ! 23: */ ! 24: ! 25: /* ! 26: File: CompositeClassDriver.c ! 27: ! 28: Contains: Core functionality to Composite Class Driver ! 29: ! 30: Version: xxx put version here xxx ! 31: ! 32: Copyright: � 1997-1998 by Apple Computer, Inc., all rights reserved. ! 33: ! 34: File Ownership: ! 35: ! 36: DRI: Craig Keithley ! 37: ! 38: Other Contact: xxx put other contact here xxx ! 39: ! 40: Technology: xxx put technology here xxx ! 41: ! 42: Writers: ! 43: ! 44: (DF) David Ferguson ! 45: (BT) Barry Twycross ! 46: (CJK) Craig Keithley ! 47: ! 48: Change History (most recent first): ! 49: ! 50: <USB12> 8/25/98 BT Isoc name changes ! 51: <USB11> 8/11/98 CJK add error checking to GetInterfaceDescriptor. If ! 52: GetInterfaceDescriptor has a problem then the Composite class ! 53: driver won't try to load an interface driver for the device. ! 54: <USB10> 6/11/98 CJK add reserved params to USBExpertSetDevicePowerStatus. Wanted to ! 55: get it into the USB.i before freezing C1. pass 0 for right now. ! 56: <USB9> 6/8/98 CJK add check of power required against power available ! 57: <USB8> 6/6/98 DF Increment the InterfaceIndex before checking to see if it's ! 58: valid, pass the deviceRef to InstallInterfaceDriver ! 59: <USB7> 6/5/98 CJK implement finalize routine (which disposes of the interface refs ! 60: and removes the interface drivers) ! 61: <USB6> 5/20/98 BT Set pbVersion correctly ! 62: <USB5> 5/12/98 BT New name for add interface ! 63: <USB4> 5/2/98 DF use pascal strings for errors ! 64: <USB3> 4/9/98 CJK change to use USB.h ! 65: <USB2> 4/9/98 DF Massaged to work with MasterInterfaces ! 66: <1> 4/7/98 CJK first checked in ! 67: <36> 3/31/98 CJK start out at config 0 ! 68: <35> 3/27/98 CJK set default config to be 1, then step back to 0, if that doesn't ! 69: work. ! 70: <34> 3/26/98 CJK check for config #0 & config #1 when setting up the Composite ! 71: device. Some devices respond to 1, others to 0. ! 72: <33> 3/17/98 CJK Replace "};" with just "}". Used ExtractPrototypes to create ! 73: function prototypes for this file (placed the in the header ! 74: files). ! 75: <32> 2/26/98 CJK change to use USL's GetFullConfiguration function. ! 76: <31> 2/17/98 CJK replace debugstrs with notify expert calls. ! 77: <30> 2/17/98 CJK Change get configuration to byte swap the length ! 78: <29> 2/10/98 CJK Change call to USBExpertNewDevice to use the USL's add interface ! 79: call. ! 80: <28> 2/9/98 CJK add back in set configuration ! 81: <27> 2/9/98 CJK remove HID Emulation related items (no more include of ! 82: HIDEmulation.h, etc.) ! 83: <26> 2/9/98 CJK remove unneeded HID support. Now in mouse & keyboard modules. ! 84: The add new interface call now properly loads the HID Modules ! 85: for mouse & keyboard. ! 86: <25> 2/8/98 BT Power allocation stuff ! 87: <24> 2/6/98 CJK add call to InitUSBKeyboard. (Disabled for now) ! 88: <23> 2/6/98 CJK Crank delay back down to 10ms. ! 89: <22> 2/4/98 BT Add ref/port info to expert notify] ! 90: <21> 2/3/98 CJK Change set configuration USB Direction to "USBOut". Changed ! 91: sequence of states to be "get configuration, set configuration, ! 92: set protocol, get HID descriptor" ! 93: <20> 2/2/98 CJK change retry to simply abort if limit is reached. Also changed ! 94: sequence of getting the configuration data & then setting the ! 95: selected configuration. Used to do a set configuration before ! 96: reading the first one. ! 97: <19> 2/2/98 CJK change readhidreport state to only copy the new hid data to the ! 98: old hid data *after* doing a hid notification. ! 99: <18> 1/30/98 CJK rework test for mouse/keyboard device types ! 100: <17> 1/27/98 CJK Fixed change history... Previously said something about ! 101: commenting out code ! 102: <16> 1/27/98 CJK Work on interface set protocol & get report handling. Wasn't ! 103: setting the direction or target properly. ! 104: <15> 1/26/98 CJK Add call to USBExpertNewDevice routine ! 105: <14> 1/26/98 BT Mangle names after design review ! 106: <13> 1/23/98 CJK Change to use USBServicesLib USBDelay function. ! 107: <12> 1/23/98 CJK Implement HID data change detection ! 108: <11> 1/23/98 CJK Add call to configuration parser. ! 109: <10> 1/22/98 CJK Work on get configuration code. ! 110: <9> 1/22/98 CJK Change state tag to async operation ! 111: <8> 1/20/98 CJK Add states to handle reading the configuration (both the base ! 112: size and full size). ! 113: <7> 1/15/98 CJK Change ClassDrivers.h to USBClassDrivers.h ! 114: <6> 1/14/98 BT Remove superceded expert stuff ! 115: <5> 1/14/98 CJK Add setup of version field ! 116: <4> 1/8/98 CJK Moved initialize & finalize routines over to ! 117: CompositeClassDescription.c ! 118: <3> 1/6/98 CJK Add tasktime and expert entry procs ! 119: <2> 12/17/97 CJK Add basic functionality for mouse and keyboard. ! 120: <1> 12/17/97 CJK First time checkin ! 121: */ ! 122: ! 123: //naga#include "../types.h" ! 124: //naga#include "../devices.h" ! 125: //naga#include "../processes.h" ! 126: #include "../driverservices.h" ! 127: #include "../USB.h" ! 128: ! 129: #include "CompositeClassDriver.h" ! 130: extern usbCompositePBStruct myCompositePBRecord; ! 131: ! 132: ! 133: void InitParamBlock(USBDeviceRef theDeviceRef, USBPB * paramblock) ! 134: { ! 135: paramblock->usbReference = theDeviceRef; ! 136: paramblock->usbCompletion = (USBCompletion)CompositeDeviceCompletionProc; ! 137: paramblock->pbLength = sizeof(usbCompositePBStruct); ! 138: paramblock->pbVersion = kUSBCurrentPBVersion; ! 139: paramblock->usb.cntl.WIndex = 0; ! 140: paramblock->usbBuffer = nil; ! 141: paramblock->usbStatus = kUSBNoErr; ! 142: paramblock->usbReqCount = 0; ! 143: paramblock->usbActCount = 0; ! 144: paramblock->usb.cntl.WValue = 0; ! 145: paramblock->usbFlags = 0; ! 146: } ! 147: ! 148: ! 149: static Boolean immediateError(OSStatus err) ! 150: { ! 151: return((err != kUSBPending) && (err != kUSBNoErr) ); ! 152: } ! 153: ! 154: void CompositeDeviceInitiateTransaction(USBPB *pb) ! 155: { ! 156: register usbCompositePBStruct *pCompositePB; ! 157: OSStatus myErr; ! 158: ! 159: pCompositePB = (usbCompositePBStruct *)(pb); ! 160: pCompositePB->transDepth++; ! 161: if ((pCompositePB->transDepth < 0) || (pCompositePB->transDepth > 1)) ! 162: { ! 163: ! 164: USBExpertFatalError(pCompositePB->pb.usbReference, kUSBInternalErr, "Composite Driver: Illegal Transaction Depth", pCompositePB->pb.usbRefcon); ! 165: } ! 166: do ! 167: { ! 168: switch(pCompositePB->pb.usbRefcon & ~kRetryTransaction) ! 169: { ! 170: case kGetFullConfiguration0: ! 171: InitParamBlock(pCompositePB->deviceRef, &pCompositePB->pb); ! 172: pCompositePB->pb.usb.cntl.WIndex = 0; /* First try configuration 0, if it doesn't succeed, then try config 1*/ ! 173: ! 174: pCompositePB->pb.usbRefcon |= kCompletionPending; ! 175: pCompositePB->pb.usbCompletion = (USBCompletion)CompositeDeviceCompletionProc; ! 176: myErr = USBGetFullConfigurationDescriptor(pb); ! 177: if(immediateError(myErr)) ! 178: { ! 179: USBExpertFatalError(pCompositePB->pb.usbReference, kUSBInternalErr, "Composite Driver: USBGetFullConfiguration (#0) - immediate error", myErr); ! 180: } ! 181: break; ! 182: ! 183: case kGetFullConfiguration1: ! 184: InitParamBlock(pCompositePB->deviceRef, &pCompositePB->pb); ! 185: pCompositePB->pb.usb.cntl.WIndex = 1; /* Try configuration 1 (some devices seem to expect config 0, others config 1 */ ! 186: pCompositePB->pb.usbRefcon |= kCompletionPending; ! 187: ! 188: pCompositePB->pb.usbCompletion = (USBCompletion)CompositeDeviceCompletionProc; ! 189: myErr = USBGetFullConfigurationDescriptor(pb); ! 190: if(immediateError(myErr)) ! 191: { ! 192: USBExpertFatalError(pCompositePB->pb.usbReference, kUSBInternalErr, "Composite Driver: USBGetFullConfiguration (#1) - immediate error", myErr); ! 193: } ! 194: break; ! 195: ! 196: case kSetConfig: ! 197: InitParamBlock(pCompositePB->deviceRef, &pCompositePB->pb); ! 198: pCompositePB->pb.usb.cntl.BMRequestType = USBMakeBMRequestType(kUSBOut, kUSBStandard, kUSBDevice); ! 199: ! 200: pCompositePB->pb.usb.cntl.BRequest = kUSBRqSetConfig; ! 201: pCompositePB->pb.usb.cntl.WValue = pCompositePB->pFullConfigDescriptor->configValue; /* Use configuration ID value from descriptor */ ! 202: ! 203: pCompositePB->pb.usbRefcon |= kCompletionPending; ! 204: ! 205: pCompositePB->pb.usbCompletion = (USBCompletion)CompositeDeviceCompletionProc; ! 206: myErr = USBDeviceRequest(pb); ! 207: if(immediateError(myErr)) ! 208: { ! 209: USBExpertFatalError(pCompositePB->pb.usbReference, kUSBInternalErr, "Composite Driver: kSetConfig - immediate error", myErr); ! 210: } ! 211: break; ! 212: ! 213: case kNewInterfaceRef: ! 214: InitParamBlock(pCompositePB->deviceRef, &pCompositePB->pb); ! 215: // Note: pCompositePB->usb.cntl.WIndex will be set to zero by InitParamBlock ! 216: // so set it again to pCompositePB->interfaceIndex before calling USBNewInterfaceRef ! 217: pCompositePB->pb.usb.cntl.WIndex = pCompositePB->interfaceIndex; ! 218: pCompositePB->pb.usbRefcon |= kCompletionPending; ! 219: pCompositePB->pb.usbCompletion = (USBCompletion)CompositeDeviceCompletionProc; ! 220: ! 221: myErr = USBNewInterfaceRef(pb); ! 222: if(immediateError(myErr)) ! 223: { ! 224: USBExpertFatalError(pCompositePB->pb.usbReference, kUSBInternalErr, "Composite Driver: kNewInterfaceRef - immediate error", myErr); ! 225: } ! 226: break; ! 227: ! 228: default: ! 229: USBExpertFatalError(pCompositePB->pb.usbReference, kUSBInternalErr, "Composite Driver - Transaction initiated with bad refcon value", pCompositePB->pb.usbRefcon); ! 230: pCompositePB->pb.usbRefcon = kUndefined + kExitDriver; ! 231: break; ! 232: } ! 233: } while (false); ! 234: ! 235: // At this point the control is returned to the system. If a USB transaction ! 236: // has been initiated, then it will call the Complete procs ! 237: // (below) to handle the results of the transaction. ! 238: } ! 239: ! 240: void CompositeDeviceCompletionProc(USBPB *pb) ! 241: { ! 242: OSStatus myErr; ! 243: register usbCompositePBStruct *pCompositePB; ! 244: USBInterfaceDescriptorPtr pInterfaceDescriptor; ! 245: UInt32 i; ! 246: ! 247: pCompositePB = (usbCompositePBStruct *)(pb); ! 248: pCompositePB->transDepth--; ! 249: if ((pCompositePB->transDepth < 0) || (pCompositePB->transDepth > 1)) ! 250: { ! 251: USBExpertFatalError(pCompositePB->pb.usbReference, kUSBInternalErr, "Composite Driver - Illegal Transaction Depth", pCompositePB->transDepth); ! 252: } ! 253: ! 254: if((pCompositePB->pb.usbStatus != kUSBNoErr) && (pCompositePB->pb.usbStatus != kUSBPending)) ! 255: { ! 256: USBExpertStatus(pCompositePB->pb.usbReference, "Composite Driver: Completion Error", pCompositePB->pb.usbStatus); ! 257: pCompositePB->pb.usbRefcon &= ~(kCompletionPending + kExitDriver); ! 258: pCompositePB->pb.usbRefcon |= kRetryTransaction; ! 259: pCompositePB->retryCount--; ! 260: if (!pCompositePB->retryCount) ! 261: { ! 262: if (pCompositePB->pb.usbRefcon == kGetFullConfiguration1) ! 263: { ! 264: pCompositePB->pb.usbRefcon = kGetFullConfiguration0; ! 265: } ! 266: else ! 267: { ! 268: USBExpertFatalError(pCompositePB->pb.usbReference, kUSBInternalErr, "Composite Driver: Too many retries", pCompositePB->pb.usbRefcon); ! 269: pCompositePB->pb.usbRefcon = kExitDriver; ! 270: return; ! 271: } ! 272: } ! 273: } ! 274: else ! 275: { ! 276: pCompositePB->pb.usbRefcon &= ~kRetryTransaction; ! 277: pCompositePB->retryCount = kCompositeRetryCount; ! 278: } ! 279: ! 280: if (pCompositePB->pb.usbRefcon & kCompletionPending) ! 281: { ! 282: pCompositePB->pb.usbRefcon &= ~(kCompletionPending + kExitDriver); ! 283: switch(pCompositePB->pb.usbRefcon) ! 284: { ! 285: case kGetFullConfiguration0: ! 286: case kGetFullConfiguration1: ! 287: // DebugStr("Check power"); ! 288: pCompositePB->pFullConfigDescriptor = pCompositePB->pb.usbBuffer; ! 289: if (pCompositePB->pFullConfigDescriptor == nil) ! 290: { ! 291: USBExpertFatalError(pCompositePB->pb.usbReference, kUSBInternalErr, "Composite Driver: USBGetFullConfiguration - pointer is nil", pCompositePB->pb.usbRefcon); ! 292: pCompositePB->pb.usbRefcon = kExitDriver; ! 293: break; ! 294: } ! 295: ! 296: BlockCopy( (void *)pCompositePB->pFullConfigDescriptor, (void *)(&(pCompositePB->partialConfigDescriptor)), (Size)(sizeof(USBConfigurationDescriptor) ) ); ! 297: if (pCompositePB->pFullConfigDescriptor->maxPower <= pCompositePB->busPowerAvailable) ! 298: { ! 299: pCompositePB->pb.usbRefcon = kSetConfig; ! 300: } ! 301: else ! 302: { ! 303: USBExpertSetDevicePowerStatus(pCompositePB->pb.usbReference, 0, 0, kUSBDevicePower_BusPowerInsufficient, pCompositePB->busPowerAvailable, pCompositePB->pFullConfigDescriptor->maxPower); ! 304: USBExpertFatalError(pCompositePB->pb.usbReference, kUSBDevicePowerProblem, "Composite Driver - Insufficient power for device", pCompositePB->pb.usbRefcon); ! 305: pCompositePB->pb.usbRefcon = kExitDriver; ! 306: } ! 307: break; ! 308: ! 309: case kSetConfig: /* get all the interface descriptors and save them */ ! 310: for (i=0; i < pCompositePB->partialConfigDescriptor.numInterfaces; i++) ! 311: { ! 312: pCompositePB->interfaceRefArray[i] = 0; ! 313: myErr = GetInterfaceDescriptor(pCompositePB->pFullConfigDescriptor, (UInt32)i, &pInterfaceDescriptor); ! 314: if (kUSBNoErr == myErr) ! 315: { ! 316: BlockCopy((void *)pInterfaceDescriptor, (void *)(&(pCompositePB->interfaceDescriptors[i])), (Size)(pInterfaceDescriptor->length)); ! 317: } ! 318: else /* if GetInterfaceDescriptor returned an error, then set the length to zero (so we know later) */ ! 319: { ! 320: pCompositePB->interfaceDescriptors[i].length = 0; ! 321: } ! 322: } ! 323: pCompositePB->interfaceIndex = 0; ! 324: pCompositePB->interfaceCount = pCompositePB->partialConfigDescriptor.numInterfaces; ! 325: pCompositePB->pb.usbRefcon = kNewInterfaceRef; ! 326: break; ! 327: ! 328: case kNewInterfaceRef: ! 329: /* save the new interface ref for this interface */ ! 330: pCompositePB->interfaceRefArray[pCompositePB->interfaceIndex] = pCompositePB->pb.usbReference; ! 331: ! 332: /* only install the interface driver if we had a valid interface descriptor */ ! 333: if (pCompositePB->interfaceDescriptors[pCompositePB->interfaceIndex].length != 0) ! 334: { ! 335: USBExpertInstallInterfaceDriver(pCompositePB->interfaceRefArray[pCompositePB->interfaceIndex], &pCompositePB->deviceDescriptor, &pCompositePB->interfaceDescriptors[pCompositePB->interfaceIndex], pCompositePB->deviceRef, 0); ! 336: } ! 337: ! 338: /* advance to the next interface */ ! 339: pCompositePB->interfaceIndex++; ! 340: ! 341: /* if there's more interfaces, then just keep cycling through kNewInterfaceRef */ ! 342: if (pCompositePB->interfaceIndex < pCompositePB->interfaceCount) ! 343: { ! 344: pCompositePB->pb.usbRefcon = kNewInterfaceRef; ! 345: } ! 346: else ! 347: { ! 348: pCompositePB->pb.usbRefcon = kExitDriver; ! 349: } ! 350: break; ! 351: ! 352: default: ! 353: USBExpertFatalError(pCompositePB->pb.usbReference, kUSBInternalErr, "Composite Driver - Transaction completed with a bad refcon value", pCompositePB->pb.usbRefcon); ! 354: pCompositePB->pb.usbRefcon = kExitDriver; ! 355: break; ! 356: } ! 357: } ! 358: if (!(pCompositePB->pb.usbRefcon & kExitDriver)) ! 359: CompositeDeviceInitiateTransaction(pb); ! 360: ! 361: pCompositePB->okayToFinalizeFlag = true; ! 362: pCompositePB->disposeCompletedFlag = true; ! 363: } ! 364: ! 365:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.