home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1999 January: Mac OS SDK / Dev.CD Jan 99 SDK1.toast / Development Kits / Mac OS USB DDK_v1.0.1 / Examples / KeyboardModule / KeyboardModule.c < prev    next >
Encoding:
C/C++ Source or Header  |  1998-09-03  |  13.6 KB  |  372 lines  |  [TEXT/MPS ]

  1. /*
  2.     File:        KeyboardModule.c
  3.  
  4.     Contains:    HID Module for USB Keyboard
  5.  
  6.     Version:    xxx put version here xxx
  7.  
  8.     Copyright:    © 1997-1998 by Apple Computer, Inc., all rights reserved.
  9.  
  10. */
  11.  
  12. #include <Types.h>
  13. #include <Devices.h>
  14. #include <processes.h>
  15. #include <DriverServices.h>
  16. #include <USB.h>
  17.  
  18. #include "KeyboardModule.h"
  19.  
  20. usbKeyboardPBStruct myKeyboardPB;
  21. usbKeyboardPBStruct shimKeyboardPB;
  22.  
  23.  
  24. static void KeyboardModuleDelay1CompletionProc(USBPB *pb);
  25. void SetParamBlock(USBDeviceRef theDeviceRef, USBPB * paramblock);
  26.  
  27. void SetParamBlock(USBDeviceRef theDeviceRef, USBPB * paramblock)
  28. {
  29.     paramblock->usbReference = theDeviceRef;
  30.     paramblock->pbVersion = kUSBCurrentPBVersion;
  31.     paramblock->usbWIndex = 0;             
  32.     paramblock->usbBuffer = nil;        
  33.     paramblock->usbStatus = noErr;
  34.     paramblock->usbReqCount = 0;
  35.     paramblock->usbWValue = 0;
  36.     paramblock->usbFlags = 0;
  37. }
  38.  
  39. static Boolean immediateError(OSStatus err)
  40. {
  41.     return((err != kUSBPending) && (err != noErr) );
  42. }
  43.  
  44. void KeyboardModuleInitiateTransaction(USBPB *pb)
  45. {
  46. register usbKeyboardPBStruct *pKeyboardPB;
  47. OSStatus myErr;
  48.  
  49.     pKeyboardPB = (usbKeyboardPBStruct *)(pb);
  50.     pKeyboardPB->transDepth++;
  51.     if (pKeyboardPB->transDepth < 0)
  52.     {
  53.         USBExpertFatalError(pKeyboardPB->deviceRef, kUSBInternalErr, "\pUSBHIDKeyboardModule: transDepth < 0 (initiation)", pKeyboardPB->pb.usbRefcon );
  54.     }
  55.     
  56.     if (pKeyboardPB->transDepth > 1)
  57.     {
  58.         USBExpertFatalError(pKeyboardPB->deviceRef, kUSBInternalErr, "\pUSBHIDKeyboardModule: transDepth > 1 (initiation)", pKeyboardPB->pb.usbRefcon );
  59.     }
  60.     
  61.     switch(pKeyboardPB->pb.usbRefcon & ~kRetryTransaction)
  62.     {
  63.         case kSetKeyboardLEDs:
  64.             SetParamBlock(pKeyboardPB->deviceRef, &pKeyboardPB->pb);
  65.             
  66.             pKeyboardPB->pb.usbBMRequestType = USBMakeBMRequestType(kUSBOut, kUSBClass, kUSBInterface);            
  67.             
  68.             pKeyboardPB->pb.usbBRequest = kHIDRqSetReport;
  69.             pKeyboardPB->pb.usbWValue = (kHIDRtOutputReport << 8); 
  70.             pKeyboardPB->pb.usbWIndex = pKeyboardPB->pInterfaceDescriptor->interfaceNumber;
  71.             
  72.             pKeyboardPB->pb.usbBuffer = (Ptr)&pKeyboardPB->hidReport[0];
  73.             pKeyboardPB->pb.usbReqCount = 1;
  74.                 
  75.             pKeyboardPB->pb.usbCompletion = (USBCompletion)KeyboardCompletionProc;
  76.             pKeyboardPB->pb.usbRefcon |= kCompletionPending;
  77.             
  78.             myErr = USBDeviceRequest(&pKeyboardPB->pb);
  79.             if(immediateError(myErr))
  80.             {
  81.                 USBExpertFatalError(pKeyboardPB->deviceRef, kUSBInternalErr, "\pUSBHIDKeyboardModule: kSetKeyboardLEDs - immediate error", myErr);
  82.             }
  83.             break;
  84.  
  85.         case kGetFullConfiguration:
  86.             SetParamBlock(pKeyboardPB->deviceRef, &pKeyboardPB->pb);
  87.             
  88.             pKeyboardPB->pb.usbRefcon |= kCompletionPending;
  89.             pKeyboardPB->pb.usbCompletion = (USBCompletion)KeyboardCompletionProc;
  90.             myErr = USBGetFullConfigurationDescriptor(pb);
  91.             if(immediateError(myErr))
  92.             {
  93.                 USBExpertFatalError(pKeyboardPB->pb.usbReference, kUSBInternalErr, "\pUSBHIDKeyboardModule: kGetFullConfiguration (ImmediateError)", myErr);
  94.             }
  95.             break;
  96.             
  97.         case kFindInterfaceAndSetProtocol:
  98.             myErr = FindHIDInterfaceByNumber(pKeyboardPB->pFullConfigDescriptor, pKeyboardPB->interfaceDescriptor.interfaceNumber, &pKeyboardPB->pInterfaceDescriptor );    // find the HID interface
  99.             if ((pKeyboardPB->pInterfaceDescriptor == NULL) || 
  100.                 (myErr != noErr))
  101.             {
  102.                 USBExpertFatalError(pKeyboardPB->deviceRef, kUSBInternalErr, "\pUSBHIDKeyboardModule: Interface not found", myErr);
  103.                 pKeyboardPB->pb.usbRefcon = kReturnFromDriver;
  104.             }
  105.             
  106.             SetParamBlock(pKeyboardPB->deviceRef, &pKeyboardPB->pb);
  107.             
  108.             pKeyboardPB->pb.usbBMRequestType = USBMakeBMRequestType(kUSBOut, kUSBClass, kUSBInterface);            
  109.             pKeyboardPB->pb.usbBRequest = kHIDRqSetProtocol;
  110.             pKeyboardPB->pb.usbWValue = kHIDBootProtocolValue; 
  111.             pKeyboardPB->pb.usbWIndex = pKeyboardPB->pInterfaceDescriptor->interfaceNumber;
  112.             pKeyboardPB->pb.usbCompletion = (USBCompletion)KeyboardCompletionProc;
  113.             
  114.             pKeyboardPB->pb.usbRefcon |= kCompletionPending;
  115.             myErr = USBDeviceRequest(&pKeyboardPB->pb);
  116.             if (immediateError(myErr))
  117.             {
  118.                 USBExpertFatalError(pKeyboardPB->deviceRef, kUSBInternalErr, "\pUSBHIDKeyboardModule: kSetProtocol (ImmediateError)", myErr);
  119.             }
  120.             break;
  121.             
  122.         case kSetIdleRequest:
  123.             SetParamBlock(pKeyboardPB->deviceRef, &pKeyboardPB->pb);
  124.             
  125.             pKeyboardPB->pb.usbBMRequestType = USBMakeBMRequestType(kUSBOut, kUSBClass, kUSBInterface);            
  126.             
  127.             pKeyboardPB->pb.usbBRequest = kHIDRqSetIdle;
  128.             pKeyboardPB->pb.usbWValue = ((24/4)<<8);                 // force a read completion if idle for more than 24ms
  129.             pKeyboardPB->pb.usbWIndex = pKeyboardPB->pInterfaceDescriptor->interfaceNumber;
  130.             pKeyboardPB->pb.usbCompletion = (USBCompletion)KeyboardCompletionProc;
  131.             
  132.             pKeyboardPB->pb.usbRefcon |= kCompletionPending;
  133.  
  134.             myErr = USBDeviceRequest(&pKeyboardPB->pb);
  135.             if(immediateError(myErr))
  136.             {
  137.                 USBExpertFatalError(pKeyboardPB->deviceRef, kUSBInternalErr, "\pUSBHIDKeyboardModule: kSetIdleRequest - immediate error", myErr);
  138.             }
  139.             break;
  140.  
  141.         case kFindAndOpenInterruptPipe:
  142.             pKeyboardPB->pb.usbBMRequestType = USBMakeBMRequestType(kUSBIn, kUSBClass, kUSBInterface);
  143.             pKeyboardPB->pb.usbFlags = kUSBIn;
  144.             pKeyboardPB->pb.usbClassType = kUSBInterrupt;
  145.             pKeyboardPB->pb.usbOther = 0;            
  146.             pKeyboardPB->pb.usbBuffer = pKeyboardPB->pInterfaceDescriptor;
  147.             pKeyboardPB->pb.usbReqCount = (UInt8*)pKeyboardPB->pInterfaceDescriptor - (UInt8*)pKeyboardPB->pFullConfigDescriptor;
  148.             myErr = USBFindNextEndpointDescriptorImmediate( &pKeyboardPB->pb );
  149.             if((immediateError(myErr)) || (pKeyboardPB->pb.usbBuffer == nil))
  150.             {
  151.                 USBExpertFatalError(pKeyboardPB->deviceRef, kUSBInternalErr, "\pUSBHIDKeyboardModule: Endpoint not found", myErr);
  152.                 pKeyboardPB->pb.usbRefcon = kReturnFromDriver;
  153.             }
  154.             else
  155.             {
  156.                 pKeyboardPB->pEndpointDescriptor = (USBEndPointDescriptorPtr) pKeyboardPB->pb.usbBuffer;
  157.  
  158.                 SetParamBlock(pKeyboardPB->deviceRef, &pKeyboardPB->pb);
  159.                 
  160.                 pKeyboardPB->pb.usbFlags = kUSBIn;
  161.                 pKeyboardPB->pb.usbWValue = 0x08;
  162.                 pKeyboardPB->pb.usbClassType = kUSBInterrupt;
  163.                 pKeyboardPB->pb.usbOther = (pKeyboardPB->pEndpointDescriptor->endpointAddress & 0x0f);
  164.                 pKeyboardPB->pb.usbRefcon |= kCompletionPending;
  165.                 pKeyboardPB->pb.usbCompletion = (USBCompletion)KeyboardCompletionProc;
  166.         
  167.                 myErr = USBOpenPipe( &pKeyboardPB->pb );
  168.                 if(immediateError(myErr))
  169.                 {
  170.                     USBExpertFatalError(pKeyboardPB->deviceRef, kUSBInternalErr, "\pUSBHIDKeyboardModule: USBOpenPipe Failed (ImmediateError)", myErr);
  171.                 }
  172.             }
  173.             break;
  174.         
  175.         case kReadInterruptPipe:
  176.             SetParamBlock(pKeyboardPB->pipeRef, &pKeyboardPB->pb);
  177.  
  178.             pKeyboardPB->pb.usbBuffer = (Ptr)pKeyboardPB->hidReport;
  179.             pKeyboardPB->pb.usbReqCount = 0x08;
  180.             pKeyboardPB->pb.usbWIndex = pKeyboardPB->pInterfaceDescriptor->interfaceNumber;    
  181.             pKeyboardPB->pb.usbCompletion = (USBCompletion)KeyboardCompletionProc;
  182.             
  183.             pKeyboardPB->pb.usbRefcon |= kCompletionPending;
  184.         
  185.             myErr = USBIntRead(&pKeyboardPB->pb);
  186.             if(immediateError(myErr))
  187.             {
  188.                 USBExpertFatalError(pKeyboardPB->deviceRef, kUSBInternalErr, "\pUSBHIDKeyboardModule: Read Interrupt Pipe (ImmediateError)", myErr);
  189.             }
  190.             break;
  191.             
  192.         default:
  193.             USBExpertFatalError(pKeyboardPB->deviceRef, kUSBInternalErr, "\pUSBHIDKeyboardModule - Transaction completed with bad refcon value", pKeyboardPB->pb.usbRefcon );
  194.             pKeyboardPB->pb.usbRefcon = kUndefined + kReturnFromDriver;
  195.             break;
  196.     }
  197.     
  198. // At this point the control is returned to the system.  If a USB transaction
  199. // has been initiated, then it will call the Complete procs
  200. // (below) to handle the results of the transaction.
  201. }
  202.  
  203. void KeyboardCompletionProc(USBPB *pb)
  204. {
  205. unsigned char    * errstring;
  206. register usbKeyboardPBStruct *pKeyboardPB;
  207. USBPipeState pipeState;
  208.  
  209.     pKeyboardPB = (usbKeyboardPBStruct *)(pb);
  210.     pKeyboardPB->transDepth--;
  211.     if (pKeyboardPB->transDepth < 0)
  212.     {
  213.         USBExpertFatalError(pKeyboardPB->deviceRef, kUSBInternalErr, "\pUSBHIDKeyboardModule: transDepth < 0 (completion)", pKeyboardPB->pb.usbRefcon );
  214.     }
  215.     
  216.     if (pKeyboardPB->transDepth > 1)
  217.     {
  218.         USBExpertFatalError(pKeyboardPB->deviceRef, kUSBInternalErr, "\pUSBHIDKeyboardModule: transDepth > 1 (completion)", pKeyboardPB->pb.usbRefcon );
  219.     }
  220.     
  221.     if(pKeyboardPB->pb.usbStatus != noErr)                                                    // was there an error?
  222.     {
  223.         switch(pKeyboardPB->pb.usbRefcon & 0x0fff)                                            // yes, so show where the error occurred
  224.         {
  225.             case kGetFullConfiguration:          errstring = "\pUSBHIDKeyboardModule: Error during GetFullConfiguration"; break;
  226.             case kFindInterfaceAndSetProtocol:    errstring = "\pUSBHIDKeyboardModule: Error during FindInterfaceAndSetProtocol"; break;
  227.             case kFindAndOpenInterruptPipe:      errstring = "\pUSBHIDKeyboardModule: Error during FindAndOpenInterruptPipe"; break;
  228.             case kReadInterruptPipe:              errstring = "\pUSBHIDKeyboardModule: Error during ReadInterruptPipe"; break;
  229.             default:                              errstring = "\pUSBHIDKeyboardModule: Error occurred, but state is unknown"; break;
  230.         };
  231.         USBExpertFatalError(pKeyboardPB->deviceRef, pKeyboardPB->pb.usbStatus, errstring, (pKeyboardPB->pb.usbRefcon & 0x0fff));
  232.         
  233.         pKeyboardPB->pb.usbRefcon &= ~(kCompletionPending + kReturnFromDriver);                // set up to retry the transaction
  234.         pKeyboardPB->pb.usbRefcon |= kRetryTransaction;
  235.         pKeyboardPB->retryCount--;
  236.         
  237.         if ((!pKeyboardPB->retryCount)    || (pKeyboardPB->pb.usbStatus == kUSBAbortedError))    // have we exhausted the retries?
  238.         {                                                                                    // or received an abort?
  239.             USBExpertStatus(pKeyboardPB->deviceRef, "\pUSBHIDKeyboardModule: Pipe abort or unable to recover from error", pKeyboardPB->deviceRef);
  240.             pKeyboardPB->pb.usbRefcon = kReturnFromDriver;                                    // if so, just exit.
  241.         }
  242.         else                                                                                // if it didn't abort and there's retries left, then...
  243.         {
  244.             if (pKeyboardPB->pipeRef)                                                        // check if the pipe is open.
  245.             {
  246.                 USBGetPipeStatusByReference(pKeyboardPB->pipeRef, &pipeState);                // yes, so what it's state?
  247.                 if (pipeState != kUSBActive)                                                // if it's not active, try to clear it.  It might be stalled...
  248.                 {
  249.                     USBExpertStatus(pKeyboardPB->deviceRef, "\pUSBHIDKeyboardModule: Pipe is open and stalled, clearing stall...", pKeyboardPB->deviceRef);
  250.                     USBClearPipeStallByReference(pKeyboardPB->pipeRef);
  251.                 }
  252.             }
  253.         }
  254.     }
  255.     else
  256.     {
  257.         pKeyboardPB->pb.usbRefcon &= ~kRetryTransaction;
  258.         pKeyboardPB->retryCount = kKeyboardRetryCount;
  259.     }
  260.  
  261.     if (pKeyboardPB->pb.usbRefcon & kCompletionPending)             
  262.     {                                                
  263.         pKeyboardPB->pb.usbRefcon &= ~(kCompletionPending + kReturnFromDriver);
  264.         switch(pKeyboardPB->pb.usbRefcon)
  265.         {
  266.             case kSetKeyboardLEDs:
  267.                 pKeyboardPB->pb.usbRefcon = kReturnFromDriver;
  268.                 break;
  269.                 
  270.             case kGetFullConfiguration:
  271.                 pKeyboardPB->pFullConfigDescriptor = pKeyboardPB->pb.usbBuffer;
  272.                 if (pKeyboardPB->pFullConfigDescriptor == nil)
  273.                 {
  274.                     USBExpertFatalError(pKeyboardPB->pb.usbReference, kUSBInternalErr, "\pUSBHIDKeyboardModule: USBGetFullConfiguration - pointer is nil", pKeyboardPB->pb.usbRefcon);
  275.                     pKeyboardPB->pb.usbRefcon = kReturnFromDriver;
  276.                 }
  277.                 else
  278.                 {
  279.                     pKeyboardPB->pb.usbRefcon = kFindInterfaceAndSetProtocol;
  280.                 }
  281.                 break;
  282.                 
  283.             case kFindInterfaceAndSetProtocol:
  284.                 pKeyboardPB->pb.usbRefcon = kSetIdleRequest;
  285.                 break;
  286.                 
  287.             case kSetIdleRequest:
  288.                 pKeyboardPB->pb.usbRefcon = kFindAndOpenInterruptPipe;
  289.                 break;
  290.                 
  291.             case kFindAndOpenInterruptPipe:
  292.                 pKeyboardPB->pipeRef = pKeyboardPB->pb.usbReference;
  293.                 pKeyboardPB->pb.usbRefcon = kReadInterruptPipe;
  294.                 break;
  295.                 
  296.             case kReadInterruptPipe:
  297.                 NotifyRegisteredHIDUser(pKeyboardPB->hidDeviceType, pKeyboardPB->hidReport);
  298.                 pKeyboardPB->pb.usbRefcon = kReadInterruptPipe;
  299.                 break;
  300.                 
  301.             default:
  302.                 USBExpertFatalError(pKeyboardPB->deviceRef, kUSBInternalErr, "\pUSBHIDKeyboardModule - Transaction completed with bad refcon value", pKeyboardPB->pb.usbRefcon );
  303.                 pKeyboardPB->pb.usbRefcon = kUndefined + kReturnFromDriver;
  304.                 break;
  305.         }
  306.     }
  307.     if (!(pKeyboardPB->pb.usbRefcon & kReturnFromDriver))
  308.         KeyboardModuleInitiateTransaction(pb);
  309. }
  310.  
  311.  
  312. void InterfaceEntry(UInt32 interfacenum, USBInterfaceDescriptorPtr pInterfaceDescriptor, USBDeviceDescriptorPtr pDeviceDescriptor, USBDeviceRef device)
  313. {
  314. #pragma unused (interfacenum)
  315.  
  316. static Boolean beenThereDoneThat = false;
  317.  
  318.     if(beenThereDoneThat)
  319.     {
  320.         USBExpertFatalError(device, kUSBInternalErr, "\pUSBHIDKeyboardModule is not reentrant", 12);
  321.         return;
  322.     }
  323.     beenThereDoneThat = true;
  324.     
  325. //    DebugStr("\pIn Keyboard Module Interface entry routine");
  326.     shimKeyboardPB.deviceDescriptor = *pDeviceDescriptor;                
  327.     shimKeyboardPB.interfaceDescriptor = *pInterfaceDescriptor;                
  328.     shimKeyboardPB.transDepth = 0;                            
  329.     shimKeyboardPB.retryCount = kKeyboardRetryCount;
  330.     shimKeyboardPB.pSHIMInterruptRoutine = nil;
  331.     shimKeyboardPB.pSavedInterruptRoutine = nil;
  332.     shimKeyboardPB.deviceRef = device;
  333.     shimKeyboardPB.interfaceRef = 0;
  334.     shimKeyboardPB.pipeRef = 0;
  335.     
  336.     shimKeyboardPB.deviceRef = device;        
  337.     shimKeyboardPB.interfaceRef = nil;        
  338.     shimKeyboardPB.pipeRef = nil;        
  339.     
  340.     SetParamBlock(device, &shimKeyboardPB.pb);
  341.     shimKeyboardPB.pb.pbLength = sizeof(usbKeyboardPBStruct);
  342.     shimKeyboardPB.pb.usbRefcon = 0;                
  343.  
  344.     myKeyboardPB.deviceDescriptor = *pDeviceDescriptor;                
  345.     myKeyboardPB.interfaceDescriptor = *pInterfaceDescriptor;                
  346.     myKeyboardPB.transDepth = 0;                            
  347.     myKeyboardPB.retryCount = kKeyboardRetryCount;
  348.     myKeyboardPB.pSHIMInterruptRoutine = nil;
  349.     myKeyboardPB.pSavedInterruptRoutine = nil;
  350.     myKeyboardPB.deviceRef = device;
  351.     myKeyboardPB.interfaceRef = 0;
  352.     myKeyboardPB.pipeRef = 0;
  353.  
  354.     myKeyboardPB.deviceRef = device;        
  355.     myKeyboardPB.interfaceRef = nil;        
  356.     myKeyboardPB.pipeRef = nil;    
  357.     
  358.     myKeyboardPB.sendRawReportFlag = false;
  359.     myKeyboardPB.hidEmulationInit = false;
  360.     
  361.     SetParamBlock(device, &myKeyboardPB.pb);
  362.     myKeyboardPB.pb.pbLength = sizeof(usbKeyboardPBStruct);
  363.     myKeyboardPB.pb.usbRefcon = kGetFullConfiguration;        /* Start with setting the interface protocol */
  364.     
  365.     
  366.     USBHIDControlDevice(kHIDEnableDemoMode,0);
  367.     KeyboardModuleInitiateTransaction(&myKeyboardPB.pb);
  368. }
  369.  
  370.  
  371.  
  372.