home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1998 August: Tool Chest / Dev.CD Aug 98 TC.toast / What's New? / Software Development Kits / Mac OS USB DDK / MacOS USB DDK 1.0b4 / NeptuneDDK / Examples / KeyboardModule / KeyboardModule.c < prev    next >
Encoding:
C/C++ Source or Header  |  1998-06-26  |  13.2 KB  |  383 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->transDepth );
  54.     }
  55.     
  56.     if (pKeyboardPB->transDepth > 1)
  57.     {
  58.         USBExpertFatalError(pKeyboardPB->deviceRef, kUSBInternalErr, "\pUSBHIDKeyboardModule: transDepth > 1 (initiation)", pKeyboardPB->transDepth );
  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 = FindHIDInterfaceByProtocol(pKeyboardPB->pFullConfigDescriptor, kHIDKeyboardInterfaceProtocol, &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 = USBFindNextEndpointDescriptor( &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.  
  208.     pKeyboardPB = (usbKeyboardPBStruct *)(pb);
  209.     pKeyboardPB->transDepth--;
  210.     if (pKeyboardPB->transDepth < 0)
  211.     {
  212.         USBExpertFatalError(pKeyboardPB->deviceRef, kUSBInternalErr, "\pUSBHIDKeyboardModule: transDepth < 0 (completion)", pKeyboardPB->transDepth );
  213.     }
  214.     
  215.     if (pKeyboardPB->transDepth > 1)
  216.     {
  217.         USBExpertFatalError(pKeyboardPB->deviceRef, kUSBInternalErr, "\pUSBHIDKeyboardModule: transDepth > 1 (completion)", pKeyboardPB->transDepth );
  218.     }
  219.     
  220.     if((pKeyboardPB->pb.usbStatus != noErr) && (pKeyboardPB->pb.usbStatus != kUSBPending))
  221.     {
  222.         USBExpertFatalError(pKeyboardPB->deviceRef, pKeyboardPB->pb.usbStatus, "\pUSBHIDKeyboardModule: USL Reported an error", pKeyboardPB->deviceRef);
  223.         if (pKeyboardPB->pipeRef)
  224.         {
  225.             USBExpertStatus(pKeyboardPB->deviceRef, "\pUSBHIDKeyboardModule: Attempting to clear the pipe stall", pKeyboardPB->deviceRef);
  226.             USBClearPipeStallByReference(pKeyboardPB->pipeRef);
  227.         }
  228.         
  229.         pKeyboardPB->pb.usbRefcon &= ~(kCompletionPending + kReturnFromDriver);
  230.         pKeyboardPB->pb.usbRefcon |= kRetryTransaction;
  231.         pKeyboardPB->retryCount--;
  232.         if (!pKeyboardPB->retryCount)
  233.         {
  234.             switch(pKeyboardPB->pb.usbRefcon & 0x0fff)
  235.             {
  236.                 case kGetFullConfiguration:     
  237.                     errstring = "\pUSBHIDKeyboardModule: kGetFullConfiguration retry failed"; break;
  238.                     
  239.                 case kFindInterfaceAndSetProtocol:     
  240.                     errstring = "\pUSBHIDKeyboardModule: kFindInterfaceAndSetProtocol retry failed"; break;
  241.                     
  242.                 case kFindAndOpenInterruptPipe:     
  243.                     errstring = "\pUSBHIDKeyboardModule: kFindAndOpenInterruptPipe retry failed"; break;
  244.                     
  245.                 case kReadInterruptPipe:     
  246.                     errstring = "\pUSBHIDKeyboardModule: kReadInterruptPipe retry failed"; break;
  247.                     
  248.                 default:     
  249.                     errstring = "\pUSBHIDKeyboardModule: retry failed (unknown state)"; break;
  250.             };
  251.             USBExpertFatalError(pKeyboardPB->deviceRef, pKeyboardPB->pb.usbStatus, errstring, pKeyboardPB->deviceRef);
  252.             pKeyboardPB->pb.usbRefcon = kReturnFromDriver;
  253.             return;
  254.         }
  255.     }
  256.     else
  257.     {
  258.         pKeyboardPB->pb.usbRefcon &= ~kRetryTransaction;
  259.         pKeyboardPB->retryCount = kKeyboardRetryCount;
  260.     }
  261.  
  262.     if (pKeyboardPB->pb.usbRefcon & kCompletionPending)             
  263.     {                                                
  264.         pKeyboardPB->pb.usbRefcon &= ~(kCompletionPending + kReturnFromDriver);
  265.         switch(pKeyboardPB->pb.usbRefcon)
  266.         {
  267.             case kSetKeyboardLEDs:
  268.                 pKeyboardPB->pb.usbRefcon = kReturnFromDriver;
  269.                 break;
  270.                 
  271.             case kGetFullConfiguration:
  272.                 pKeyboardPB->pFullConfigDescriptor = pKeyboardPB->pb.usbBuffer;
  273.                 if (pKeyboardPB->pFullConfigDescriptor == nil)
  274.                 {
  275.                     USBExpertFatalError(pKeyboardPB->pb.usbReference, kUSBInternalErr, "\pUSBHIDKeyboardModule: USBGetFullConfiguration - pointer is nil", pKeyboardPB->pb.usbRefcon);
  276.                     pKeyboardPB->pb.usbRefcon = kReturnFromDriver;
  277.                 }
  278.                 else
  279.                 {
  280.                     pKeyboardPB->pb.usbRefcon = kFindInterfaceAndSetProtocol;
  281.                 }
  282.                 break;
  283.                 
  284.             case kFindInterfaceAndSetProtocol:
  285.                 pKeyboardPB->pb.usbRefcon = kSetIdleRequest;
  286.                 break;
  287.                 
  288.             case kSetIdleRequest:
  289.                 pKeyboardPB->pb.usbRefcon = kFindAndOpenInterruptPipe;
  290.                 break;
  291.                 
  292.             case kFindAndOpenInterruptPipe:
  293.                 pKeyboardPB->pipeRef = pKeyboardPB->pb.usbReference;
  294.                 pKeyboardPB->pb.usbRefcon = kReadInterruptPipe;
  295.                 break;
  296.                 
  297.             case kReadInterruptPipe:
  298.                 NotifyRegisteredHIDUser(pKeyboardPB->hidDeviceType, pKeyboardPB->hidReport);
  299.                 pKeyboardPB->pb.usbRefcon = kReadInterruptPipe;
  300.                 break;
  301.                 
  302.             default:
  303.                 USBExpertFatalError(pKeyboardPB->deviceRef, kUSBInternalErr, "\pUSBHIDKeyboardModule - Transaction completed with bad refcon value", pKeyboardPB->pb.usbRefcon );
  304.                 pKeyboardPB->pb.usbRefcon = kUndefined + kReturnFromDriver;
  305.                 break;
  306.         }
  307.     }
  308.     if (!(pKeyboardPB->pb.usbRefcon & kReturnFromDriver))
  309.         KeyboardModuleInitiateTransaction(pb);
  310. }
  311.  
  312.  
  313. void DriverEntry(USBDeviceRef device, USBDeviceDescriptorPtr pDeviceDescriptor)
  314. {
  315. #pragma unused (device)
  316. #pragma unused (pDeviceDescriptor)
  317.  
  318. static Boolean beenThereDoneThat = false;
  319.  
  320.     return;
  321. }
  322.  
  323. void InterfaceEntry(UInt32 interfacenum, USBInterfaceDescriptorPtr pInterfaceDescriptor, USBDeviceDescriptorPtr pDeviceDescriptor, USBDeviceRef device)
  324. {
  325. #pragma unused (interfacenum)
  326.  
  327. static Boolean beenThereDoneThat = false;
  328.  
  329.     if(beenThereDoneThat)
  330.     {
  331.         USBExpertFatalError(device, kUSBInternalErr, "\pUSBHIDKeyboardModule is not reentrant", 12);
  332.         return;
  333.     }
  334.     beenThereDoneThat = true;
  335.     
  336. //    DebugStr("\pIn Keyboard Module Interface entry routine");
  337.     shimKeyboardPB.deviceDescriptor = *pDeviceDescriptor;                
  338.     shimKeyboardPB.interfaceDescriptor = *pInterfaceDescriptor;                
  339.     shimKeyboardPB.transDepth = 0;                            
  340.     shimKeyboardPB.retryCount = kKeyboardRetryCount;
  341.     shimKeyboardPB.pSHIMInterruptRoutine = nil;
  342.     shimKeyboardPB.pSavedInterruptRoutine = nil;
  343.     shimKeyboardPB.deviceRef = device;
  344.     shimKeyboardPB.interfaceRef = 0;
  345.     shimKeyboardPB.pipeRef = 0;
  346.     
  347.     shimKeyboardPB.deviceRef = device;        
  348.     shimKeyboardPB.interfaceRef = nil;        
  349.     shimKeyboardPB.pipeRef = nil;        
  350.     
  351.     SetParamBlock(device, &shimKeyboardPB.pb);
  352.     shimKeyboardPB.pb.pbLength = sizeof(usbKeyboardPBStruct);
  353.     shimKeyboardPB.pb.usbRefcon = 0;                
  354.  
  355.     myKeyboardPB.deviceDescriptor = *pDeviceDescriptor;                
  356.     myKeyboardPB.interfaceDescriptor = *pInterfaceDescriptor;                
  357.     myKeyboardPB.transDepth = 0;                            
  358.     myKeyboardPB.retryCount = kKeyboardRetryCount;
  359.     myKeyboardPB.pSHIMInterruptRoutine = nil;
  360.     myKeyboardPB.pSavedInterruptRoutine = nil;
  361.     myKeyboardPB.deviceRef = device;
  362.     myKeyboardPB.interfaceRef = 0;
  363.     myKeyboardPB.pipeRef = 0;
  364.  
  365.     myKeyboardPB.deviceRef = device;        
  366.     myKeyboardPB.interfaceRef = nil;        
  367.     myKeyboardPB.pipeRef = nil;    
  368.     
  369.     myKeyboardPB.sendRawReportFlag = false;
  370.     myKeyboardPB.hidEmulationInit = false;
  371.     
  372.     SetParamBlock(device, &myKeyboardPB.pb);
  373.     myKeyboardPB.pb.pbLength = sizeof(usbKeyboardPBStruct);
  374.     myKeyboardPB.pb.usbRefcon = kGetFullConfiguration;        /* Start with setting the interface protocol */
  375.     
  376.     
  377.     USBHIDControlDevice(kHIDEnableDemoMode,0);
  378.     KeyboardModuleInitiateTransaction(&myKeyboardPB.pb);
  379. }
  380.  
  381.  
  382.  
  383.