home *** CD-ROM | disk | FTP | other *** search
- /*
- File: MouseModule.c
-
- Contains: HID Module for USB Mouse
-
- Version: xxx put version here xxx
-
- Copyright: © 1997-1999 by Apple Computer, Inc., all rights reserved.
-
- */
-
- #include <Types.h>
- #include <Devices.h>
- #include <processes.h>
- #include <DriverServices.h>
- #include <USB.h>
- #include <LowMem.h>
-
- #include "MouseModule.h"
-
- usbMousePBStruct myMousePB;
-
- void InitParamBlock(USBReference theInterfaceRef, USBPB * paramblock)
- {
- paramblock->usbReference = theInterfaceRef;
- paramblock->pbVersion = kUSBCurrentPBVersion;
-
- paramblock->usb.cntl.WIndex = 0;
- paramblock->usb.cntl.WValue = 0;
-
- paramblock->usbBuffer = nil;
- paramblock->usbActCount = 0;
- paramblock->usbReqCount = 0;
- paramblock->usbFlags = 0;
- paramblock->usbOther = 0;
-
- paramblock->usbStatus = noErr;
- }
-
-
-
- Boolean immediateError(OSStatus err)
- {
- return((err != kUSBPending) && (err != noErr) );
- }
-
- void MouseInitiateTransaction(USBPB *pb)
- {
- register usbMousePBStruct *pMousePB;
- OSStatus myErr;
-
- pMousePB = (usbMousePBStruct *)(pb);
- pMousePB->transDepth++;
- if (pMousePB->transDepth < 0)
- {
- USBExpertFatalError(pMousePB->interfaceRef, kUSBInternalErr, kMouseModuleName": transDepth < 0 (initiation)", pMousePB->pb.usbRefcon );
- }
-
- if (pMousePB->transDepth > 1)
- {
- USBExpertFatalError(pMousePB->interfaceRef, kUSBInternalErr, kMouseModuleName": transDepth > 1 (initiation)", pMousePB->pb.usbRefcon );
- }
-
- if (pMousePB->driverRemovalPending)
- {
- pMousePB->pb.usbRefcon = kReturnFromDriver;
- return;
- }
-
- switch(pMousePB->pb.usbRefcon & ~kRetryTransaction)
- {
- case kConfigureInterface:
- InitParamBlock(pMousePB->interfaceRef, &pMousePB->pb);
-
- pMousePB->pb.usbCompletion = (USBCompletion)MouseCompletionProc;
- pMousePB->pb.usbRefcon |= kCompletionPending;
-
- myErr = USBConfigureInterface( &pMousePB->pb );
- if(immediateError(myErr))
- {
- USBExpertFatalError(pMousePB->interfaceRef, kUSBInternalErr, kMouseModuleName": kConfigureInterface - immediate error", myErr);
- pMousePB->pb.usbRefcon = kReturnFromDriver;
- }
- break;
-
- case kSetProtocol:
- InitParamBlock(pMousePB->interfaceRef, &pMousePB->pb);
-
- pMousePB->pb.usb.cntl.BMRequestType = USBMakeBMRequestType(kUSBOut, kUSBClass, kUSBInterface);
- pMousePB->pb.usb.cntl.BRequest = kHIDRqSetProtocol;
- pMousePB->pb.usb.cntl.WValue = kHIDBootProtocolValue;
- pMousePB->pb.usb.cntl.WIndex = pMousePB->interfaceDescriptor.interfaceNumber;
-
- pMousePB->pb.usbCompletion = (USBCompletion)MouseCompletionProc;
- pMousePB->pb.usbRefcon |= kCompletionPending;
-
- myErr = USBDeviceRequest(&pMousePB->pb);
- if (immediateError(myErr))
- {
- USBExpertFatalError(pMousePB->interfaceRef, kUSBInternalErr, kMouseModuleName": kSetProtocol - immediate error", myErr);
- }
- break;
-
- case kSetIdleRequest:
- InitParamBlock(pMousePB->interfaceRef, &pMousePB->pb);
-
- pMousePB->pb.usb.cntl.BMRequestType = USBMakeBMRequestType(kUSBOut, kUSBClass, kUSBInterface);
-
- pMousePB->pb.usb.cntl.BRequest = kHIDRqSetIdle;
- pMousePB->pb.usb.cntl.WValue = ((24/4)<<8); // force a read completion if idle for more than 24ms
- pMousePB->pb.usb.cntl.WIndex = pMousePB->interfaceDescriptor.interfaceNumber;
-
- pMousePB->pb.usbCompletion = (USBCompletion)MouseCompletionProc;
- pMousePB->pb.usbRefcon |= kCompletionPending;
-
- myErr = USBDeviceRequest(&pMousePB->pb);
- if(immediateError(myErr))
- {
- USBExpertFatalError(pMousePB->interfaceRef, kUSBInternalErr, kMouseModuleName": kSetIdleRequest - immediate error", myErr);
- }
- break;
-
- case kFindPipe:
- InitParamBlock(pMousePB->interfaceRef, &pMousePB->pb);
-
- pMousePB->pb.usbFlags = kUSBIn;
- pMousePB->pb.usbClassType = kUSBInterrupt;
-
- pMousePB->pb.usbCompletion = (USBCompletion)MouseCompletionProc;
- pMousePB->pb.usbRefcon |= kCompletionPending;
-
- myErr = USBFindNextPipe( &pMousePB->pb );
- if((immediateError(myErr)) || (pMousePB->pb.usbBuffer == nil))
- {
- USBExpertFatalError(pMousePB->interfaceRef, kUSBInternalErr, kMouseModuleName": kFindPipe - immediate error", myErr);
- pMousePB->pb.usbRefcon = kReturnFromDriver;
- }
- break;
-
- case kClearFeature:
- USBExpertStatus(pMousePB->interfaceRef, kMouseModuleName": Do a clear feature on the interrupt endpoint", pMousePB->pipeRef);
- InitParamBlock(pMousePB->pipeRef, &pMousePB->pb);
- pMousePB->pb.usb.cntl.BMRequestType = USBMakeBMRequestType(kUSBOut, kUSBStandard, kUSBEndpoint);
-
- pMousePB->pb.usb.cntl.BRequest = kUSBRqClearFeature;
- pMousePB->pb.usb.cntl.WValue = kUSBFeatureEndpointStall;
-
- pMousePB->pb.usbFlags = kUSBAddressRequest; /* kUSBAddressRequest asks the USL to do a translation of piperef to endpoint number */
-
- pMousePB->pb.usbCompletion = (USBCompletion)MouseCompletionProc;
- pMousePB->pb.usbRefcon |= kCompletionPending;
-
- myErr = USBDeviceRequest(pb);
- if(immediateError(myErr))
- {
- USBExpertFatalError(pMousePB->pb.usbReference, kUSBInternalErr, kMouseModuleName": kClearFeature - immediate error", myErr);
- }
- break;
-
- case kReadInterruptPipe:
- InitParamBlock(pMousePB->pipeRef, &pMousePB->pb);
-
- pMousePB->pb.usbBuffer = (Ptr)pMousePB->hidReport;
- pMousePB->pb.usbReqCount = pMousePB->maxPacketSize;
- pMousePB->pb.usb.cntl.WIndex = pMousePB->interfaceDescriptor.interfaceNumber;
-
- pMousePB->pb.usbCompletion = (USBCompletion)MouseCompletionProc;
- pMousePB->pb.usbRefcon |= kCompletionPending;
-
- myErr = USBIntRead(&pMousePB->pb);
- if(immediateError(myErr))
- {
- USBExpertFatalError(pMousePB->interfaceRef, kUSBInternalErr, kMouseModuleName": Read Interrupt Pipe (ImmediateError)", myErr);
- }
- break;
-
- default:
- USBExpertFatalError(pMousePB->interfaceRef, kUSBInternalErr, kMouseModuleName": Transaction initiated with bad refcon value", pMousePB->pb.usbRefcon);
- pMousePB->pb.usbRefcon = kUndefined + kReturnFromDriver;
- break;
- }
-
- // At this point the control is returned to the system. If a USB transaction
- // has been initiated, then it will call the Complete procs
- // (below) to handle the results of the transaction.
- }
-
-
- void MouseCompletionProc(USBPB *pb)
- {
- register usbMousePBStruct *pMousePB;
- unsigned char * errstring;
- USBPipeState pipeState;
-
- pMousePB = (usbMousePBStruct *)(pb);
- pMousePB->transDepth--;
- if (pMousePB->transDepth < 0)
- {
- USBExpertFatalError(pMousePB->interfaceRef, kUSBInternalErr, kMouseModuleName": transDepth < 0 (completion)", pMousePB->pb.usbRefcon );
- }
-
- if (pMousePB->transDepth > 1)
- {
- USBExpertFatalError(pMousePB->interfaceRef, kUSBInternalErr, kMouseModuleName": transDepth > 1 (completion)", pMousePB->pb.usbRefcon );
- }
-
- if(pMousePB->pb.usbStatus != noErr) // was there an error?
- {
- switch(pMousePB->pb.usbRefcon & 0x0fff) // yes, so show where the error occurred
- {
- case kSetProtocol: errstring = kMouseModuleName": Error during kSetProtocol"; break;
- case kSetIdleRequest: errstring = kMouseModuleName": Error during kSetIdleRequest"; break;
- case kConfigureInterface: errstring = kMouseModuleName": Error during kConfigureInterface"; break;
- case kFindPipe: errstring = kMouseModuleName": Error during kFindPipe"; break;
- case kClearFeature: errstring = kMouseModuleName": Error during kClearFeature"; break;
- case kReadInterruptPipe:
- {
- errstring = kMouseModuleName": Error during ReadInterruptPipe";
- LMSetMouseButtonState(0x80); // release any possibly held-down mouse button
- break;
- }
- default: errstring = kMouseModuleName": Error occurred, but state is unknown"; break;
- };
- USBExpertFatalError(pMousePB->interfaceRef, pMousePB->pb.usbStatus, errstring, (pMousePB->pb.usbRefcon & 0x0fff));
-
- pMousePB->pb.usbRefcon &= ~(kCompletionPending + kReturnFromDriver); // set up to retry the transaction
- pMousePB->pb.usbRefcon |= kRetryTransaction;
- pMousePB->retryCount--;
-
- if ((pMousePB->retryCount == 1) && ((pMousePB->pb.usbRefcon&pMousePB->pb.usbRefcon & 0x0fff) == kSetIdleRequest))
- {
- USBExpertStatus(pMousePB->interfaceRef, kMouseModuleName": Device doesn't accept SetIdle", pMousePB->interfaceRef);
- pMousePB->pb.usbRefcon = kFindPipe;
- pMousePB->pb.usbStatus = noErr;
- }
- else
- {
- if ((!pMousePB->retryCount) || (pMousePB->pb.usbStatus == kUSBAbortedError)) // have we exhausted the retries?
- { // or received an abort?
- USBExpertStatus(pMousePB->interfaceRef, kMouseModuleName": Pipe abort or unable to recover from error", pMousePB->interfaceRef);
- pMousePB->pb.usbRefcon = kReturnFromDriver; // if so, just exit.
- pMousePB->intPipeAborted = true;
- }
- else // if it didn't abort and there's retries left, then...
- {
- if (pMousePB->pipeRef) // check if the pipe is open.
- {
- USBGetPipeStatusByReference(pMousePB->pipeRef, &pipeState); // yes, so what it's state?
- if (pipeState != kUSBActive) // if it's not active, try to clear it. It might be stalled...
- {
- USBExpertStatus(pMousePB->interfaceRef, kMouseModuleName": Pipe is open and stalled, clearing stall...", pMousePB->interfaceRef);
- USBClearPipeStallByReference(pMousePB->pipeRef);
- }
- }
- }
- }
- }
- else
- {
- pMousePB->pb.usbRefcon &= ~kRetryTransaction;
- pMousePB->retryCount = kMouseRetryCount;
- }
-
- if (pMousePB->pb.usbRefcon & kCompletionPending)
- {
- pMousePB->pb.usbRefcon &= ~(kCompletionPending + kReturnFromDriver);
- switch(pMousePB->pb.usbRefcon)
- {
- case kConfigureInterface:
- pMousePB->pb.usbRefcon = kSetProtocol;
- break;
-
- case kSetProtocol:
- pMousePB->pb.usbRefcon = kFindPipe;
- break;
-
- case kSetIdleRequest:
- pMousePB->pb.usbRefcon = kFindPipe;
- break;
-
- case kFindPipe:
- pMousePB->maxPacketSize = pMousePB->pb.usb.cntl.WValue;
- pMousePB->pipeRef = pMousePB->pb.usbReference;
- pMousePB->pb.usbRefcon = kReadInterruptPipe;
- break;
-
- case kReadInterruptPipe:
- NotifyRegisteredHIDUser(pMousePB->hidDeviceType, pMousePB->hidReport);
- pMousePB->pb.usbRefcon = kReadInterruptPipe;
- break;
-
- default:
- USBExpertFatalError(pMousePB->interfaceRef, kUSBInternalErr, kMouseModuleName": Transaction completed with bad refcon value", pMousePB->pb.usbRefcon );
- pMousePB->pb.usbRefcon = kUndefined + kReturnFromDriver;
- break;
- }
- }
- if (!(pMousePB->pb.usbRefcon & kReturnFromDriver) && (!pMousePB->driverRemovalPending))
- MouseInitiateTransaction(pb);
- }
-
-
- void InterfaceEntry(UInt32 interfacenum, USBInterfaceDescriptorPtr pInterfaceDescriptor, USBDeviceDescriptorPtr pDeviceDescriptor, USBReference theInterfaceRef)
- {
- #pragma unused (interfacenum)
-
- static Boolean beenThereDoneThat = false;
-
- if(beenThereDoneThat)
- {
- USBExpertFatalError(theInterfaceRef, kUSBInternalErr, kMouseModuleName" is not reentrant", 0);
- return;
- }
- beenThereDoneThat = true;
-
- // DebugStr("\pIn Mouse Interface Entry routine");
-
- myMousePB.driverRemovalPending = false;
- myMousePB.intPipeAborted = false;
-
- myMousePB.deviceDescriptor = *pDeviceDescriptor;
- myMousePB.interfaceDescriptor = *pInterfaceDescriptor;
-
- myMousePB.transDepth = 0;
- myMousePB.retryCount = kMouseRetryCount;
-
- myMousePB.pSHIMInterruptRoutine = nil;
- myMousePB.pSavedInterruptRoutine = nil;
-
- myMousePB.interfaceRef = theInterfaceRef;
- myMousePB.pipeRef = nil;
-
- InitParamBlock(theInterfaceRef, &myMousePB.pb);
-
- myMousePB.pb.usbReference = theInterfaceRef;
- myMousePB.pb.pbLength = sizeof(usbMousePBStruct);
- myMousePB.pb.usbRefcon = kConfigureInterface;
-
- if ((myMousePB.deviceDescriptor.vendor == USB_CONSTANT16(0x046e)) &&
- (myMousePB.deviceDescriptor.product == USB_CONSTANT16(0x6782)))
- {
- myMousePB.unitsPerInch = (Fixed)(100<<16);
- }
- else
- {
- myMousePB.unitsPerInch = (Fixed)(400<<16);
- }
-
- myMousePB.pCursorDeviceInfo = 0;
- USBHIDControlDevice(kHIDEnableDemoMode,0);
-
- MouseInitiateTransaction(&myMousePB.pb);
- }
-
-
-
-