InputSprocketSimpleTest.cp

/*
    File:       InputSprocketSimpleTest.cp
 
    Contains:   xxx put contents here xxx
 
    Version:    xxx put version here xxx
 
    Copyright:  © 1998-1999 by Apple Computer, Inc., all rights reserved.
 
    File Ownership:
 
        DRI:                xxx put dri here xxx
 
        Other Contact:      xxx put other contact here xxx
 
        Technology:         xxx put technology here xxx
 
    Writers:
 
        (cjd)   Chris De Salvo
        (BWS)   Brent Schorsch
        (sjb)   Steve Bollinger
 
    Change History (most recent first):
 
      <SP63>     8/16/99    cjd     Fixing a type in the menus.  The event test said to hit Control
                                    to exit.  It should have said Command.
      <SP62>     12/1/98    BWS     Add test item: get element list for device, then count elements
                                    of certain type bassing null, then get the elements
      <SP61>     11/6/98    BWS     Add version in menutest
      <SP60>    10/20/98    BWS     Quit and pause now different
        <59>     7/17/98    BWS     fix come comments
        <58>     7/17/98    BWS     add sample code header
        <57>     7/17/98    BWS     fix needs list, other cleanup for GM SDK
        <56>     7/16/98    BWS     fix some constants so works with latest header
        <55>     6/18/98    sjb     InputSprocket.h comes from <> place
*/
 
/*************************************************************************************
 
File:      InputSprocketSimpleTest.cp
 
Copyright © 1996, 1997, 1998 Apple Computer, Inc., All Rights Reserved
 
 
You may incorporate this sample code into your applications without
restriction, though the sample code has been provided "AS IS" and the
responsibility for its operation is 100% yours.  However, what you are
not permitted to do is to redistribute the source as "DSC Sample Code"
after having made changes. If you're going to re-distribute the source,
we require that you make it clear in the source that the code was
descended from Apple Sample Code, but that you've made changes.
 
*************************************************************************************/
 
#ifndef DEBUG_DRIVER
    #define DEBUG_DRIVER 0
#endif
 
#include <stdio.h>
#include <stdlib.h>
 
#include <DeskBus.h>
 
#include <InputSprocket.h>
#include <SIOUX.h>
#include <CursorDevices.h>
#include <LowMem.h>
#include <FixMath.h>
 
// (default menu, if none defined) which test (AUTOTEST, DIALOGTEST or MENUTEST)
#ifndef AUTOTEST
#ifndef DIALOGTEST
#ifndef MENUTEST
#define MENUTEST        1
#endif
#endif
#endif
 
// set the other #defines to 0
#ifndef AUTOTEST
#define AUTOTEST        0
#endif
 
#ifndef DIALOGTEST
#define DIALOGTEST  0
#endif
 
#ifndef MENUTEST
#define MENUTEST        0
#endif
 
#if DEBUG_DRIVER
    #include "InputSprocketDriver.h"
#endif
 
const OSType kCreatorCode       = 'ISpT';
const OSType kSubCreatorCode    = '0015';
 
#define kResourceID_setl            128
 
enum
{
    kNeedIndex_XAxis = 1,
    kNeedIndex_YAxis = 2,
    kNeedIndex_DeltaAccelerationX = 11,
    kNeedIndex_DeltaAccelerationY = 12,
    kNeedCount = 13
};
 
enum
{
    kIconSuiteID_XThrust        = 129, 
    kIconSuiteID_YThrust        = 130,
    kIconSuiteID_ZThrust        = 131,
    kIconSuiteID_Look           = 159,
    kIconSuiteID_Fire           = 141,
    kIconSuiteID_SecondaryFire  = 142,
    kIconSuiteID_ThrustForward  = 147,
    kIconSuiteID_ThrustBackward = 148,
    kIconSuiteID_Pause          = 144,
    kIconSuiteID_Scroll         = 140,
    kIconSuiteID_DeltaX         = 256,
    kIconSuiteID_DeltaY         = 257
};
 
Boolean gIsSuspended = false;
Boolean gKeyboardEnabled = false;
ISpElementListReference gVirtualList = NULL;
ISpElementReference gVirtualElements[kNeedCount] = {nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil};
    
 
 
static ISpNeed gNeeds[kNeedCount] =
{
    { "\pForward Thrust",   kIconSuiteID_ZThrust,       0,  1, kISpElementKind_Axis,        kISpElementLabel_Axis_ZAxis,        kISpNeedFlag_Axis_AlreadyButton,    0, 0, 0 },
    { "\pSide Thrust",      kIconSuiteID_XThrust,       0,  0, kISpElementKind_Axis,        kISpElementLabel_Axis_XAxis,        0, 0, 0, 0  },
    { "\pVertical Thrust",  kIconSuiteID_YThrust,       0,  0, kISpElementKind_Axis,        kISpElementLabel_Axis_YAxis,        0, 0, 0, 0  },
    { "\pLook",             kIconSuiteID_Look,          0,  0, kISpElementKind_Movement,    kISpElementLabel_None,              0, 0, 0, 0  },
    { "\pFire",             kIconSuiteID_Fire,          0,  0, kISpElementKind_Button,      kISpElementLabel_Btn_Fire,          0, 0, 0, 0  },
    { "\pSecondary Fire",   kIconSuiteID_SecondaryFire, 0,  0, kISpElementKind_Button,      kISpElementLabel_Btn_SecondaryFire, 0, 0, 0, 0  },
    { "\pThrust Forward",   kIconSuiteID_ThrustForward, 0,  1, kISpElementKind_Button,      kISpElementLabel_Btn_MoveForward,   kISpNeedFlag_Button_AlreadyAxis,    0, 0, 0 },
    { "\pThrust Backward",  kIconSuiteID_ThrustBackward,0,  1, kISpElementKind_Button,      kISpElementLabel_Btn_MoveBackward,  kISpNeedFlag_Button_AlreadyAxis,    0, 0, 0 },
    { "\pPause",            kIconSuiteID_Pause,         0,  0, kISpElementKind_Button,      kISpElementLabel_Btn_StartPause,    kISpNeedFlag_NoMultiConfig,         0, 0, 0 },
    { "\pQuit",             kIconSuiteID_Pause,         0,  0, kISpElementKind_Button,      kISpElementLabel_Btn_Quit,          kISpNeedFlag_NoMultiConfig,         0, 0, 0 },
    { "\pScroll",           kIconSuiteID_Scroll,        0,  0, kISpElementKind_DPad,        kISpElementLabel_None,              0, 0, 0, 0                  },
    { "\pDelta X",          kIconSuiteID_DeltaX,        0,  0, kISpElementKind_Delta,       kISpElementLabel_Delta_Cursor_X,            0, 0, 0, 0                  },
    { "\pDelta Y",          kIconSuiteID_DeltaY,        0,  0, kISpElementKind_Delta,       kISpElementLabel_Delta_Cursor_Y,            0, 0, 0, 0                  }
};
 
SInt32 gStep;
char gStepId[255];
 
typedef Boolean (*ISpEventProcPtr) (EventRecord* inEvent);
 
Boolean ISpConfigureFilterProc(EventRecord *inEvent);
 
Boolean ISpConfigureFilterProc(EventRecord *inEvent)
{
    Boolean handled;
    
    handled = SIOUXHandleOneEvent(inEvent);
 
    return handled;
}
 
static Boolean Progress(UInt32 inItr, UInt32 inTotal, UInt32 inNumReports, char *string)
{
    UInt32 everyNTimes = inTotal / inNumReports;
    
    if (everyNTimes == 0) { everyNTimes = 1; }
    
    if (inItr == 0) { return false; }
    
    if ((inItr % everyNTimes) == 0)
    {
        UInt32 percent = (inItr * 100) / inTotal;
        sprintf(string, "%d%% [%d of %d]", percent, inItr, inTotal);
        return true;
    }
    
    return false;
}
 
static void InitStep(char *msg)
{
    gStep = 0;
    sprintf(gStepId, "%3d");
    
    if (msg == nil)
    {
        printf("step %s\n", gStepId);
    }
    else
    {
        printf("step %s %s\n",gStepId, msg);
    }
}
 
static void NextStep(char *msg)
{
    long this_app_memory;
    long this_sys_memory;
    static Boolean first_time = true;
    static long last_app_memory;
    static long last_sys_memory;
 
    gStep++;
    sprintf(gStepId, "%3d", gStep);
 
    this_app_memory = FreeMem();
    this_sys_memory = FreeMemSys();
 
    if (first_time) 
    {
        first_time = false;
    }
    else
    {
        long delta_app_memory = last_app_memory - this_app_memory;
        long delta_sys_memory = last_sys_memory - this_sys_memory;
        
        printf("step %s ending app mem = %d sys mem = %d\n", gStepId, this_app_memory, this_sys_memory);
        printf("step %s delta app mem = %d sys mem = %d\n", gStepId, delta_app_memory, delta_sys_memory);
    }
 
    if (msg == nil)
    {
        printf("step %s\n", gStepId);
    }
    else
    {
        printf("step %s %s\n",gStepId, msg);
    }
 
    printf("step %s starting app mem = %d sys mem = %d\n", gStepId, this_app_memory, this_sys_memory);
 
    last_app_memory = this_app_memory;
    last_sys_memory = this_sys_memory;
}
 
 
 
static void FailMsg(char *failure)
{
    printf("step %s FAILED reason = %s\n", gStepId, failure);
}
 
static void FailCode(OSStatus errorCode)
{
    printf("step %s FAILED errorCode = %d\n", gStepId, errorCode);
}
 
 
#define FAILMSG(x) { FailMsg(x); return; }
#define FAILCODE(x) { FailCode(x); return; }
 
#define FFAILMSG(x) { FailMsg(x); return false; }
#define FFAILCODE(x) { FailCode(x); return false; }
 
static void StatusMsg(char *msg)
{
    printf("step %s status msg = %s\n",gStepId, msg);
}
 
void ShowFourByte(OSType fourByte);
void ShowFourByte(OSType fourByte)
{
    putchar(((fourByte & 0xff000000) >> 24));
    putchar(((fourByte & 0x00ff0000) >> 16));
    putchar(((fourByte & 0x0000ff00) >> 8));
    putchar(((fourByte & 0x000000ff) >> 00));
}
 
void ShowStr63(const Str63 &theStr);
void ShowStr63(const Str63 &theStr)
{
    int i;
    int len = theStr[0];
    if (len > 63) { len = 63; }
    
    for(i=1; i <= len; i++)
    {
        putchar(theStr[i]);
    }
}
 
static void AppendStr63(char *string, const Str63 &theStr)
{
    char *c = string;
    int i;
    
    // find the end of the string
    while(*c != nil) { c++; }
    
    for(i = 1; i <= theStr[0]; i++)
    {
        *c = theStr[i];
        c++;
    }
    
    *c = 0;
}
 
void PrintEvent(ISpElementEventPtr theEvent);
void PrintEvent(ISpElementEventPtr theEvent)
{
    ISpElementInfo info;
    ISpElement_GetInfo(theEvent->element, &info);
    OSStatus status;
    const char* s = "¥UNKNOWN¥";
    
    printf("when = [%lu] [%lu]\n", theEvent->when.hi, theEvent->when.lo);
    
    switch (info.theKind)
    {
        case kISpElementKind_Delta:
            float inches = (Fixed) theEvent->data;
            inches /= 0xffff;
                
            printf("data = 0x%lx (%f inches) \n", theEvent->data, inches);
        break;
        case kISpElementKind_Button:
            switch (theEvent->data)
            {
                case 0:
                    s = "released";
                break;
                
                case 1:
                    s = "pressed";
                break;
            }
            
            printf("data = 0x%lx (%s)\n", theEvent->data, s);
        break;
        
        case kISpElementKind_DPad:
            switch (theEvent->data)
            {
                case kISpPadIdle:
                    s = "kISpPadIdle";
                break;
                
                case kISpPadLeft:
                    s = "kISpPadLeft";
                break;
                
                case kISpPadUpLeft:
                    s = "kISpPadUpLeft";
                break;
                
                case kISpPadUp:
                    s = "kISpPadUp";
                break;
                
                case kISpPadUpRight:
                    s = "kISpPadUpRight";
                break;
                
                case kISpPadRight:
                    s = "kISpPadRight";
                break;
                
                case kISpPadDownRight:
                    s = "kISpPadDownRight";
                break;
                
                case kISpPadDown:
                    s = "kISpPadDown";
                break;
                
                case kISpPadDownLeft:
                    s = "kISpPadDownLeft";
                break;
            }
            
            printf("data = 0x%lx (%s)\n", theEvent->data, s);
        break;
        
        case kISpElementKind_Axis:
            float temp1 = ((float) theEvent->data)/((float) 0xFFFFFFFFU);
            float temp2 = 2.0*temp1-1.0;
            
            printf("data = 0x%lx (%f%) (%f%)\n", theEvent->data, temp1, temp2);
        break;
        
        case kISpElementKind_Movement:
            printf("data = 0x%lx\n", theEvent->data);
            
            ISpMovementData movementData;
            if (ISpElement_GetComplexState(theEvent->element, sizeof(ISpMovementData), &movementData) == noErr)
            {
                switch (movementData.direction)
                {
                    case kISpPadIdle:
                        s = "kISpPadIdle";
                    break;
                    
                    case kISpPadLeft:
                        s = "kISpPadLeft";
                    break;
                    
                    case kISpPadUpLeft:
                        s = "kISpPadUpLeft";
                    break;
                    
                    case kISpPadUp:
                        s = "kISpPadUp";
                    break;
                    
                    case kISpPadUpRight:
                        s = "kISpPadUpRight";
                    break;
                    
                    case kISpPadRight:
                        s = "kISpPadRight";
                    break;
                    
                    case kISpPadDownRight:
                        s = "kISpPadDownRight";
                    break;
                    
                    case kISpPadDown:
                        s = "kISpPadDown";
                    break;
                    
                    case kISpPadDownLeft:
                        s = "kISpPadDownLeft";
                    break;
                }
                
                float horz = 2.0*(((float) movementData.xAxis)/((float) 0xFFFFFFFFU))-1.0;
                float vert = 2.0*(((float) movementData.yAxis)/((float) 0xFFFFFFFFU))-1.0;
                
                printf("state = (%f,%f) (%s)\n", horz, vert, s);
            }
        break;
    }
    
    printf("element = 0x%lx\n", theEvent->element);
    printf("refcon = %lx\n", theEvent->refCon);
    
    printf("label = ");
    ShowFourByte(info.theLabel);
    printf("\n");
    
    printf("kind = ");
    ShowFourByte(info.theKind);
    printf("\n");
    
    printf("string = ");
    ShowStr63(info.theString);
    printf("\n");
    
    {
        UInt32 data;
 
        status = ISpElement_GetSimpleState(theEvent->element, &data);
 
        if (status == noErr) { printf("polled = %x\n",data); }
    }
    
    printf("\n\n");
}
 
 
void PrintElementBlock(ISpElementReference *theElementReferences, UInt32 count);
void PrintElementBlock(ISpElementReference *theElementReferences, UInt32 count)
{
    printf("count = %d\n");
 
    int itr;
    
    for(itr = 0; itr < count; itr++)
    {
        printf("    element #%d\n",itr);
        
        ISpElementInfo info;
 
        ISpElement_GetInfo(theElementReferences[itr], &info);
 
        printf("        label = ");
        ShowFourByte(info.theLabel);
        printf("\n");
 
        printf("        kind = ");
        ShowFourByte(info.theKind);
        printf("\n");
 
        printf("        string = ");
        ShowStr63(info.theString);
        printf("\n\n");
    }
}
 
// if whichList is NULL then we use the global list
static void GetAndPrintEvents(ISpElementListReference whichList)
{
    OSErr err;
    
    if (whichList == NULL)
    {
        err = ISpGetGlobalElementList(&whichList);
        if (err)
        {
            printf("¥¥¥ ISpGetGlobalElementList returned error (%ld)\n",err);
            return;
        }
    }
 
    err = ISpElementList_Flush(whichList);
    if (err)
    {
        printf("¥¥¥ ISpElementList_Flush returned error (%ld)\n",err);
        return;
    }
 
    printf("getting events (press command to end)\n");
    
    while(1)
    {
        ISpElementEvent event;
        Boolean wasEvent;
 
        err = ISpElementList_GetNextEvent(whichList, sizeof(event), &event, &wasEvent);
        if (err)
        {
            printf("¥¥¥ ISpElementList_GetNextEvent returned error (%ld)\n",err);
            return;
        }
 
        if (wasEvent)
        {
            PrintEvent(&event);
        }
        
        KeyMap theKeys;
        GetKeys(theKeys);
 
        if ((theKeys[1] & 0x8000))
        {
            break;
        }
        
        SIOUXHandleOneEvent(nil);
    }
}
 
static void TestListOfDevices(void)
{
    ISpDeviceReference theDevices[100];
    UInt32 deviceCount;
    UInt32 deviceBufferSize = 100;
    UInt32 deviceItr;
    OSErr err;
    
    err = ISpDevices_Extract(deviceBufferSize, &deviceCount, theDevices);
    if (err)
    {
        printf("¥¥¥ ISpDevices_Extract returned error (%ld)\n",err);
        return;
    }
    
    printf("# of devices = %ld\n",deviceCount);
    for(deviceItr = 0; deviceItr < deviceCount; deviceItr++)
    {
        printf("    device #%ld\n",deviceItr);
        ISpDeviceDefinition theDfn;
        
        err = ISpDevice_GetDefinition(theDevices[deviceItr], sizeof(ISpDeviceDefinition), &theDfn);
        if (err)
        {
            printf("¥¥¥ ISpDevice_GetDefinition returned error (%ld)\n",err);
            return;
        }
        
        printf("        name = ");
        ShowStr63(theDfn.deviceName);
        printf("\n");
        
        printf("        class = ");
        ShowFourByte(theDfn.theDeviceClass);
        printf("\n");
 
        printf("        device identifier = ");
        ShowFourByte(theDfn.theDeviceIdentifier);
        printf("\n");
 
        printf("        permanent id = %ld\n",theDfn.permanentID);
        
        printf("\n\n");
    }
}
 
static void TestElementList_ExtractByKind(void)
{
    ISpDeviceReference theDevices[100];
    UInt32 deviceCount;
    UInt32 deviceBufferSize = 100;
    UInt32 deviceItr;
    OSErr err;
 
    err = ISpDevices_Extract(deviceBufferSize, &deviceCount, theDevices);
    if (err)
    {
        printf("¥¥¥ ISpDevices_Extract returned error (%ld)\n",err);
        return;
    }
    
    printf("\n\nChoose a device:\n");
    for(deviceItr = 0; deviceItr < deviceCount; deviceItr++)
    {
        printf("  %ld) ", deviceItr+1);
 
        ISpDeviceDefinition theDfn;
        err = ISpDevice_GetDefinition(theDevices[deviceItr], sizeof(ISpDeviceDefinition), &theDfn);
        if (err) 
            printf("¥¥¥ ISpDevice_GetDefinition returned error (%ld)", err);
        
        ShowStr63(theDfn.deviceName);
        printf("\n");
    }
 
    printf("Selection: ");
    char theString[32];
    gets (theString);
    UInt32 theChoice = atoi(theString);
    
    if (theChoice < 1 || theChoice > deviceCount)
    {
        printf("¥¥¥ Invalid choice (%ld)\n", theChoice);
        return;
    }
    
    ISpElementListReference deviceElementList = 0;
    err = ISpDevice_GetElementList(theDevices[theChoice-1], &deviceElementList);
    if (err)
    {
        printf("¥¥¥ ISpDevice_GetElementList returned error (%ld)\n",err);
        return;
    }
    printf("\nGot the element list for device %ld, (%lx)\n", theChoice, (UInt32) deviceElementList);
 
    printf("\nChoose a kind:\n");
    printf("1) Button ('butn')\n");
    printf("2) Direction Pad ('dpad')\n");
    printf("3) Axis ('axis')\n");
    printf("4) Delta ('dlta')\n");
    printf("5) Movement ('move')\n");
    printf("6) Virtual ('virt')\n");
    printf("Selection: ");
    
    gets (theString);
    theChoice = atoi(theString);
    
    ISpElementKind  theKind;
    switch (theChoice)
    {
        case 1: theKind = kISpElementKind_Button;   break;
        case 2: theKind = kISpElementKind_DPad;     break;
        case 3: theKind = kISpElementKind_Axis;     break;
        case 4: theKind = kISpElementKind_Delta;    break;
        case 5: theKind = kISpElementKind_Movement; break;
        case 6: theKind = kISpElementKind_Virtual;  break;
        
        default:
            printf("¥¥¥ Invalid choice (%ld)\n", theChoice);
            return;
    }
    
    UInt32 elementOfKindCount = 0;
    
    err = ISpElementList_ExtractByKind(deviceElementList, theKind, 0, &elementOfKindCount, nil);
    if (err)
    {
        printf("¥¥¥ ISpElementList_ExtractByKind returned error (%ld)\n",err);
        return;
    }
    printf("%ld elements counted (with zero count null buffer)\n", elementOfKindCount);
    
    err = ISpElementList_ExtractByKind(deviceElementList, theKind, 0, &elementOfKindCount, nil);
    if (err)
    {
        printf("¥¥¥ ISpElementList_ExtractByKind returned error (%ld)\n",err);
        return;
    }
    printf("%ld elements counted (with zero count null buffer)\n", elementOfKindCount);
    
    const UInt32    kElementListSize = 300;
    ISpElementReference elements[kElementListSize];
 
    err = ISpElementList_ExtractByKind(deviceElementList, theKind, 0, &elementOfKindCount, elements);
    if (err)
    {
        printf("¥¥¥ ISpElementList_ExtractByKind returned error (%ld)\n",err);
        return;
    }
    printf("%ld elements counted (with zero count)\n", elementOfKindCount);
 
    err = ISpElementList_ExtractByKind(deviceElementList, theKind, 1, &elementOfKindCount, elements);
    if (err)
    {
        printf("¥¥¥ ISpElementList_ExtractByKind returned error (%ld)\n",err);
        return;
    }
    printf("%ld elements counted (with one count)\n", elementOfKindCount);
 
    err = ISpElementList_ExtractByKind(deviceElementList, theKind, kElementListSize, &elementOfKindCount, elements);
    if (err)
    {
        printf("¥¥¥ ISpElementList_ExtractByKind returned error (%ld)\n",err);
        return;
    }
    printf("%ld elements counted (with %ld count)\n", elementOfKindCount, kElementListSize);
 
    err = ISpElementList_ExtractByKind(deviceElementList, theKind, kElementListSize, &elementOfKindCount, elements);
    if (err)
    {
        printf("¥¥¥ ISpElementList_ExtractByKind returned error (%ld)\n",err);
        return;
    }
    printf("%ld elements counted (with %ld count)\n", elementOfKindCount, kElementListSize);
    
    printf("\npress return key to continue\n");
    gets (theString);
}
 
static void TestListOfElements(void)
{
    ISpElementListReference globalList;
    OSErr err;
    
    err = ISpGetGlobalElementList(&globalList);
    if (err)
    {
        printf("¥¥¥ ISpGetGlobalElementList returned error (%ld)\n",err);
        return;
    }
    
    ISpElementReference theElementReferences[200];
    UInt32 bufferSize = 200;
    UInt32 count;
 
    err = ISpElementList_Extract(globalList, bufferSize, &count, theElementReferences);
    if (err)
    {
        printf("¥¥¥ ISpElementList_Extract returned error (%ld)\n",err);
        return;
    }
    
    PrintElementBlock(theElementReferences, count);
}
 
 
static void TestListOfButtons(void)
{
    ISpElementListReference globalList;
    OSErr err;
    
    err = ISpGetGlobalElementList(&globalList);
    if (err)
    {
        printf("¥¥¥ ISpGetGlobalElementList returned error (%ld)\n",err);
        return;
    }
    
    ISpElementReference theElementReferences[200];
    UInt32 bufferSize = 200;
    UInt32 count;
 
    err = ISpElementList_ExtractByKind(globalList, kISpElementKind_Button, bufferSize, &count, theElementReferences);
    if (err)
    {
        printf("¥¥¥ ISpElementList_Extract returned error (%ld)\n",err);
        return;
    }
    
    PrintElementBlock(theElementReferences, count);
}
 
 
static void TestListOfDPads(void)
{
    ISpElementListReference globalList;
    OSErr err;
    
    err = ISpGetGlobalElementList(&globalList);
    if (err)
    {
        printf("¥¥¥ ISpGetGlobalElementList returned error (%ld)\n",err);
        return;
    }
    
    ISpElementReference theElementReferences[200];
    UInt32 bufferSize = 200;
    UInt32 count;
 
    err = ISpElementList_ExtractByKind(globalList, kISpElementKind_DPad, bufferSize, &count, theElementReferences);
    if (err)
    {
        printf("¥¥¥ ISpElementList_Extract returned error (%ld)\n",err);
        return;
    }
    
    PrintElementBlock(theElementReferences, count);
}
 
 
static void TestListOfAxes(void)
{
    ISpElementListReference globalList;
    OSErr err;
    
    err = ISpGetGlobalElementList(&globalList);
    if (err)
    {
        printf("¥¥¥ ISpGetGlobalElementList returned error (%ld)\n",err);
        return;
    }
    
    ISpElementReference theElementReferences[200];
    UInt32 bufferSize = 200;
    UInt32 count;
 
    err = ISpElementList_ExtractByKind(globalList, kISpElementKind_Axis, bufferSize, &count, theElementReferences);
    if (err)
    {
        printf("¥¥¥ ISpElementList_Extract returned error (%ld)\n",err);
        return;
    }
    
    PrintElementBlock(theElementReferences, count);
}
 
 
static void TestListOfXAxes(void)
{
    ISpElementListReference globalList;
    OSErr err;
    
    err = ISpGetGlobalElementList(&globalList);
    if (err)
    {
        printf("¥¥¥ ISpGetGlobalElementList returned error (%ld)\n",err);
        return;
    }
    
    ISpElementReference theElementReferences[200];
    UInt32 bufferSize = 200;
    UInt32 count;
 
    err = ISpElementList_ExtractByLabel(globalList, kISpElementLabel_Axis_XAxis, bufferSize, &count, theElementReferences);
    if (err)
    {
        printf("¥¥¥ ISpElementList_Extract returned error (%ld)\n",err);
        return;
    }
    
    PrintElementBlock(theElementReferences, count);
}
 
 
static void TestSuspend(void)
{
    OSErr err;
    
    err = ISpSuspend();
    if (err)
    {
        printf("¥¥¥ ISpSuspend returned error (%ld)\n",err);
        return;
    }
    
    gIsSuspended = true;
}
 
 
static void TestResume(void)
{
    OSErr err;
    
    err = ISpResume();
    if (err)
    {
        printf("¥¥¥ ISpResume returned error (%ld)\n",err);
        return;
    }
    
    gIsSuspended = false;
}
 
 
static void TestCreateNeeds(void)
{
    OSErr err;
    
    if (gVirtualList == NULL)
    {
        printf("creating virtual elements\n");
        
        err = ISpElement_NewVirtualFromNeeds(kNeedCount, gNeeds, gVirtualElements, 0);
        if (err)
        {
            printf("¥¥¥ ISpElement_NewVirtualFromNeeds returned error (%ld)\n",err);
            return;
        }
        
        err = ISpElementList_New(
            kNeedCount,             // count
            gVirtualElements,       // needs
            &gVirtualList,          // virtual elements
            0);                     // flags
        if (err)
        {
            printf("¥¥¥ ISpElementList_New returned error (%ld)\n",err);
            return;
        }
            
        err = ISpInit(kNeedCount,   // count
                gNeeds,             // needs
                gVirtualElements,   // virtual elements
                kCreatorCode,       // app
                kSubCreatorCode,    // sub (we are using as a versioning)
                0,                  // flags
                kResourceID_setl,   // set list resource id
                0);                 // reserved
        if (err)
        {
            printf("¥¥¥ ISpInit returned error (%ld)\n",err);
            return;
        }
    }
}
 
 
static void TestDestroyNeeds(void)
{
    OSErr err;
    
    if (gVirtualList != NULL)
    {
        err = ISpElementList_Dispose(gVirtualList);
        gVirtualList = NULL;
        if (err)
        {
            printf("¥¥¥ ISpElementList_Dispose returned error (%ld)\n",err);
            return;
        }
        
        err = ISpStop();
        if (err)
        {
            printf("¥¥¥ ISpStop returned error (%ld)\n",err);
            return;
        }
        
        err = ISpElement_DisposeVirtual(kNeedCount, gVirtualElements);
        if (err)
        {
            printf("¥¥¥ ISpElement_DisposeVirtual returned error (%ld)\n",err);
            return;
        }
    }
}
 
 
static void TestNeedsEvents(void)
{
    TestCreateNeeds();
    
    if (gVirtualList != NULL)
    {
        GetAndPrintEvents(gVirtualList);
    }
}
 
 
static void TestConfiguration(void)
{
    OSErr err;
    
    TestCreateNeeds();
    
    err = ISpConfigure(nil);
    if (err)
    {
        printf("¥¥¥ ISpConfigure returned error (%ld)\n",err);
        return;
    }
}
 
 
static void EnableDeviceClass(OSType deviceClass, Boolean enable)
{
    enum {
        kDeviceList_COUNT = 100
    };
    
    OSStatus err;
    UInt32 count;
    ISpDeviceReference deviceList[kDeviceList_COUNT];
    
    // NOTE: This is not the correct way to handle the list count thing.  We
    // should actually call once with NULL for the device list, malloc a list of
    // that size, and call again.
    
    err = ISpDevices_ExtractByClass(
            deviceClass,
            kDeviceList_COUNT,
            &count,
            deviceList);
    
    if (err)
    {
        printf("¥¥¥ ISpDevices_ExtractByClass returned error (%ld)\n",err);
        return;
    }
    
    if (count > kDeviceList_COUNT)
    {
        count = kDeviceList_COUNT;
    }
    
    if (enable)
    {
        err = ISpDevices_Activate(
                count,
                deviceList);
        
        if (err)
        {
            printf("¥¥¥ ISpDevices_Activate returned error (%ld)\n",err);
            return;
        }
    }
    else
    {
        err = ISpDevices_Deactivate(
                count,
                deviceList);
        
        if (err)
        {
            printf("¥¥¥ ISpDevices_Deactivate returned error (%ld)\n",err);
            return;
        }
    }
    
    if (deviceClass == kISpDeviceClass_Keyboard)
    {
        gKeyboardEnabled = enable;
    }
}
 
static void TestAllocateDeallocate(void)
{
    OSErr err = noErr;
    UInt32 count = 0;
    char theString[32];
    UInt32 itr; 
    ISpElementReference virtuals[kNeedCount];
    Boolean done = false;
    
    printf("allocate/dellocate how many times>");
    
    gets( theString );
    count = atoi( theString );
 
    printf("allocating/deallocating %ld times\n",count);
    
    for(itr = 0; itr < count; itr++)
    {
        if ((itr % 100) == 0) { putchar('.'); fflush(stdout);  }
        if ((itr % 1000) == 0) 
        {
            long normal = FreeMem();
            long system = FreeMemSys();
            printf("%ld / %ld (app = %ld) (sys = %ld) \n",itr,count,normal,system);
        }
    
        SIOUXHandleOneEvent(nil);
        
        err = ISpElement_NewVirtualFromNeeds(kNeedCount, gNeeds, virtuals, 0);
        
        if (err)
        {
            printf("¥¥¥ itr = %d ISpElement_NewVirtualFromNeeds returned error (%ld)\n",itr, err);
            
            done = true;
        }
    
        err = ISpElement_DisposeVirtual(kNeedCount, virtuals);
    
        if (err)
        {
            printf("¥¥¥ ISpElementList_Dispose returned error (%ld)\n",err);
            return;
        }
        
        if (done) { return; }
    }
}
 
#define MAX_ELEMENTS    1000
#define MAX_DATASIZE    1000
 
 
#if DEBUG_DRIVER
static void TestAllocatePushData(void)
{
    char theString[32];
    OSErr err = noErr;
    UInt32 elementCount = 0;
    UInt32 dataSize;
    UInt32 count;
    UInt32 elemItr, itr;
    ISpElementReference elements[MAX_ELEMENTS];
    UInt8 state[MAX_DATASIZE];
    
    printf("how many elements>");
    gets( theString );
    elementCount = atoi( theString );
 
    printf("data size>");
    gets( theString );
    dataSize = atoi( theString );
 
    printf("count>");
    gets( theString );
    count = atoi( theString );
 
    printf("%ld elements, data size = %ld, count = %ld\n", elementCount, dataSize, count);
    
    
    if ((elementCount > MAX_ELEMENTS) || (dataSize > MAX_DATASIZE))
    {
        printf("¥¥¥ MAX_ELEMENTS = %d MAX_DATASIZE = %d\n",MAX_ELEMENTS,MAX_DATASIZE);
        return;
    }
 
    for(elemItr = 0; elemItr < elementCount; elemItr++)
    {
        err = ISpElement_NewVirtual(dataSize, &(elements[elemItr]), 0);
 
        if (err)
        {
            printf("¥¥¥ ISpElement_NewVirtual returned error (%d)\n",err);
            
            err = ISpElement_DisposeVirtual(elemItr, elements);
            if (err)
            {
                printf("¥¥¥ ISpElement_DisposeVirtual returned error (%d)\n",err);
            }
            
            return;
        }
    }
    
    for(itr = 0; itr < count; itr++)
    {
        AbsoluteTime time = {0, TickCount() };
        
        if ((itr % 100) == 0) { printf("."); }
        if ((itr % 1000) == 0) 
        {
            long normal = FreeMem();
            long system = FreeMemSys();
            Ptr temp = NewPtr(1000);
            DisposePtr(temp);
            printf("%ld / %ld (app = %ld) (sys = %ld) \n",itr,count,normal,system);
            
        }
        
        SIOUXHandleOneEvent(nil);
        
        for(elemItr = 0; elemItr < elementCount; elemItr++)
        {
            err = ISpElement_PushComplexData(elements[elemItr], dataSize, &state, &time);
            
            if (err)
            {
                printf("¥¥¥ ISpElement_PushComplexData returned error (%d)\n",err);
                return;
            }
        }
    }
 
    printf("\ndisposing elements\n");
    err = ISpElement_DisposeVirtual(elementCount, elements);
    if (err)
    {
        printf("¥¥¥ ISpElement_DisposeVirtual returned error (%d)\n",err);
    }
}
#endif /* DEBUG_DRIVER */
 
static void TestArbitraryAllocate(void)
{
    char theString[32];
    OSErr err = noErr;
    UInt32 elementCount = 0;
    UInt32 dataSize;
    UInt32 elemItr;
    ISpElementReference elements[MAX_ELEMENTS];
    
    printf("how many elements>");
    gets( theString );
    elementCount = atoi( theString );
 
    printf("data size>");
    gets( theString );
    dataSize = atoi( theString );
 
 
    printf("%ld elements, data size = %ld\n", elementCount, dataSize);  
    
    if ((elementCount > MAX_ELEMENTS) || (dataSize > MAX_DATASIZE))
    {
        printf("¥¥¥ MAX_ELEMENTS = %d MAX_DATASIZE = %d\n",MAX_ELEMENTS,MAX_DATASIZE);
        return;
    }
 
    printf("allocating elements\n");
    for(elemItr = 0; elemItr < elementCount; elemItr++)
    {
        err = ISpElement_NewVirtual(dataSize, &(elements[elemItr]), 0);
 
        if (err)
        {
            printf("¥¥¥ ISpElement_NewVirtual returned error (%d)\n",err);
            
            err = ISpElement_DisposeVirtual(elemItr, elements);
            if (err)
            {
                printf("¥¥¥ ISpElement_DisposeVirtual returned error (%d)\n",err);
            }
            
            return;
        }
    }
 
    printf("\ndisposing elements\n");
    err = ISpElement_DisposeVirtual(elementCount, elements);
    if (err)
    {
        printf("¥¥¥ ISpElement_DisposeVirtual returned error (%d)\n",err);
    }
}
 
#define MTemp 0x828
#define RawMouse 0x82c
#define CrsrNewCouple 0x8ce
 
static void TestAcceleration(void)
{
    TestCreateNeeds();
 
    ShowCursor();
    Point where =  * ( Point * ) RawMouse;
 
    float deltaX = 0;
    float deltaY = 0;
    
    while(1)
    {
        gVirtualElements[kNeedIndex_XAxis];
        gVirtualElements[kNeedIndex_YAxis];
        
        UInt32 forward;
        UInt32 side;
        OSStatus status;
        float temp;
        SInt8 amt;
        
        status = ISpElement_GetSimpleState(gVirtualElements[kNeedIndex_XAxis], &forward);
 
        if (status == noErr)
        {
            temp = forward;
            temp -= kISpAxisMiddle;
            temp /= kISpAxisMiddle;
            temp *= 25;
            
            deltaX += temp;
            
            if (deltaX >= 1) 
            {
                amt = deltaX;
                where.h += amt;
                deltaX -= amt;
            }
            else if (deltaX <= -1)
            {
                amt = -deltaX;
                where.h -= amt;
                deltaX += amt;
            }
        }
        
        status = ISpElement_GetSimpleState(gVirtualElements[kNeedIndex_YAxis], &side);
 
        if (status == noErr)
        {
            temp = side;
            temp -= kISpAxisMiddle;
            temp /= kISpAxisMiddle;
            temp *= -25;
            
            deltaY += temp;
 
            if (deltaY >= 1) 
            {
                amt = deltaY;
                where.v += amt;
                deltaY -= amt;
            }
            else if (deltaY <= -1)
            {
                amt = -deltaY;
                where.v -= amt;
                deltaY += amt;
            }
 
        }
                
        HideCursor();
        
        * ( Point * ) RawMouse = where ;
        * ( Point * ) MTemp = where ;
        * ( short * ) CrsrNewCouple = -1 ;
        
        ShowCursor();
    
        KeyMap theKeys;
        GetKeys(theKeys);
 
        if ((theKeys[1] & 0x8000))
        {
            break;
        }
        
        unsigned long aLong = ::TickCount();
        
        while (aLong == TickCount()) { ; }
    }
}
 
static void TestAcceleration2(void)
{
    TestCreateNeeds();
 
    ShowCursor();
    
    while(1)
    {
        Point where = * ( Point * ) RawMouse;
 
        Fixed horzPos = where.h * fixed1;
        Fixed vertPos = where.v * fixed1;
 
        Fixed horzDelta = 0;
        Fixed vertDelta = 0;
        OSStatus status;
        
        status = ISpElement_GetSimpleState(gVirtualElements[kNeedIndex_DeltaAccelerationX], (UInt32 *) &horzDelta);
        status = ISpElement_GetSimpleState(gVirtualElements[kNeedIndex_DeltaAccelerationY], (UInt32 *) &vertDelta);
        
        if ((horzDelta != 0) || (vertDelta != 0))
        {
            HideCursor();
            
            horzPos += 72 * horzDelta;
            vertPos -= 72 * vertDelta;
            
            where.h = horzPos / fixed1;
            where.v = vertPos / fixed1;
        
            * ( Point * ) RawMouse = where ;
            * ( Point * ) MTemp = where ;
            * ( short * ) CrsrNewCouple = -1 ;
            
            ShowCursor();
        }
    
        KeyMap theKeys;
        GetKeys(theKeys);
 
        if ((theKeys[1] & 0x8000))
        {
            break;
        }
    }
}
 
#define FVERIFY(x)  if (x) { FailCode(x); return false; }
#define FVERIFY2(x, y)  if (x) {    char VERIFY2_DEBUG_STATUS[512]; \
                                    sprintf(VERIFY2_DEBUG_STATUS,"%s got %d",y,x); \
                                     FailMsg(VERIFY2_DEBUG_STATUS); return false; }
 
// true if ExtractByClass works
// false otherwise
// 
static Boolean VerifyExtractByClass(void)
{
    ISpDeviceClass deviceClass;
    const UInt32 kNumDeviceClass = 8;
    ISpDeviceClass kDeviceClassArray[kNumDeviceClass] = { kISpDeviceClass_SpeechRecognition,
                                    kISpDeviceClass_Mouse,
                                    kISpDeviceClass_Keyboard,
                                    kISpDeviceClass_Joystick,
                                    kISpDeviceClass_Wheel,
                                    kISpDeviceClass_Pedals,
                                    kISpDeviceClass_Levers,
                                    'junk'
                                    };
    UInt32 deviceClassItr;
    OSStatus err;
    UInt32 result1, result2, result3;
    const UInt32 kFixedBufferSize = 100;
    ISpDeviceReference fixedBuffer[kFixedBufferSize] = { 0 } ;
    ISpDeviceReference *exactBuffer;
    UInt32 verifyItr;
    char debug_status[255];
    
    NextStep("broad band ISpDevices_ExtractByClass verification");
    
    for(deviceClassItr = 0; deviceClassItr < kNumDeviceClass; deviceClassItr++)
    {   
        deviceClass = kDeviceClassArray[deviceClassItr];
        
        sprintf(debug_status, "device class = %c%c%c%c", (deviceClass & 0xff000000) >> 24, (deviceClass & 0xff0000) >> 16, 
                (deviceClass & 0xff00) >> 8, (deviceClass & 0xff) >> 0);
        StatusMsg(debug_status);
        
        // result 1
        err = ISpDevices_ExtractByClass(deviceClass, 0, &result1, NULL);
        if (err) { FailMsg("ISpDevices_ExtractByClass failed with a null buffer"); return false; }
        
        sprintf(debug_status, "found %d devices of that type",result1);
        StatusMsg(debug_status);
        
        // result 2
        err = ISpDevices_ExtractByClass(deviceClass, kFixedBufferSize, &result2, fixedBuffer);
        if (err) { FailMsg("ISpDevices_ExtractByClass failed with a fixed buffer"); return false; }
        for(verifyItr = 0; ((verifyItr < result2) && (verifyItr < kFixedBufferSize)); verifyItr ++)
        {
            StatusMsg("verifying on list 2");
            if (fixedBuffer[verifyItr] == nil) 
            {
                FailMsg("ISpDevices_ExtractByClass failed to verify non nil with a fixed buffer");
                return false;
            }
        }
        
        // result 3
        exactBuffer = (ISpDeviceReference *) NewPtrClear(sizeof(ISpDeviceReference) * result1);
        if (exactBuffer == nil) { FailMsg("Problem with test program not the sprocket, test program needs more memory!"); return false; }
        err = ISpDevices_ExtractByClass(deviceClass, result1, &result3, exactBuffer);
        if (err) { FailMsg("ISpDevices_ExtractByClass failed with an exact buffer"); return false; }
        for(verifyItr = 0; verifyItr < result3; verifyItr ++)
        {
            StatusMsg("verifying on list 3");
            if (exactBuffer[verifyItr] == nil) 
            {
                FailMsg("ISpDevices_ExtractByClass failed to verify non nil with an exact buffer");
                return false;
            }
        }
        DisposePtr((Ptr) exactBuffer);
        
        if ((result1 != result2) || (result1 != result3))
        {
            FailMsg("the three results were not all the same!");
            return false;
        }
    }
    
    return true;
}
 
 
static Boolean VerifyActivateDeactive(void)
{
    const UInt32 kMaxDevices = 100;
    ISpDeviceReference devices[kMaxDevices];
    OSStatus err;
    UInt32 numDevices;
    char debug_status[512];
    NextStep("Running Enable/Disable test");
    UInt32 deviceItr;
    UInt32 enableDisableItr;
    const UInt32 kNumEnableDisableAttempts = 100;
    
    err = ISpDevices_Extract(kMaxDevices, &numDevices, devices);
    FVERIFY2(err,"ISpDevices_Extract")
        
    for(deviceItr = 0; deviceItr < numDevices; deviceItr++)
    {
        ISpDeviceReference thisDevice = devices[deviceItr];
        Boolean wasActive;
        ISpDeviceDefinition thisDefinition;
        
        err = ISpDevice_IsActive(thisDevice, &wasActive);
        FVERIFY2(err, "ISpDevice_IsActive");
        
        if (wasActive)
        {
            err = ISpDevices_Deactivate(1, &thisDevice);
            FVERIFY2(err, "ISpDevices_Deactivate")
        }
        
        err = ISpDevice_GetDefinition(thisDevice, sizeof(ISpDeviceDefinition), &thisDefinition);
        FVERIFY2(err, "ISpDevice_GetDefinition")
        
        sprintf(debug_status,"working on device ");
        AppendStr63(debug_status, thisDefinition.deviceName);
        StatusMsg(debug_status);
        
        for(enableDisableItr = 0; enableDisableItr < kNumEnableDisableAttempts; enableDisableItr++)
        {
            if (Progress(enableDisableItr, kNumEnableDisableAttempts, 10, debug_status))
            {
                StatusMsg(debug_status);
            }
            
            err = ISpDevices_Activate(1, &thisDevice);
            FVERIFY2(err, "ISpDevices_Activate")
 
            err = ISpDevices_Deactivate(1, &thisDevice);
            FVERIFY2(err, "ISpDevices_Deactivate")          
        }
        
        StatusMsg("100%");
        
        if (wasActive)
        {
            err = ISpDevices_Activate(1, &thisDevice);
            FVERIFY2(err, "ISpDevices_Activate")
        }
    }   
 
    return true;    
}
 
static void WaitForAnyKey(void)
{
    KeyMap theKeyMap;
    
    GetKeys(theKeyMap);
    
    while((theKeyMap[0] == 0) && (theKeyMap[1] == 0) && (theKeyMap[2] == 0) && (theKeyMap[3] == 0))
    {
        SIOUXHandleOneEvent(nil);
        GetKeys(theKeyMap);
    }
}
 
#define VERIFY(x)   if (x) { FailCode(x); return; }
 
 
 
static void AutoTest(void)
{
    OSStatus err;
    char debug_status[512];
    debug_status;
    Boolean success;
 
    InitStep("press any key to begin AutoTest");
    WaitForAnyKey();
 
    NextStep("getting the version of input sprocket");
    {
        NumVersion version = ISpGetVersion();
 
        sprintf(debug_status, "version = %x %x %x %x\n",version.majorRev, version.minorAndBugRev, version.stage, version.nonRelRev);
        StatusMsg(debug_status);
    }   
    
    NextStep("verifying that this is the first initialization");
    {
        if (gVirtualList != NULL)
        {
            FailMsg("this was not the first time a test was run for this launch of the application");
            return;
        }
    }
    
    NextStep("starting up");
    {
        err = ISpStartup();
        VERIFY(err);
    }
    
    NextStep("looping on startup / shutdown");
    {
        const UInt32 kStartShutAttempts = 20;
        UInt32 startShutItr;
                
        for(startShutItr = 0; startShutItr < kStartShutAttempts; startShutItr++)
        {
            err = ISpShutdown();
            VERIFY(err)
 
            err = ISpStartup();
            VERIFY(err);
 
            if (Progress(startShutItr, kStartShutAttempts, 10, debug_status))
            {
                StatusMsg(debug_status);
            }
        }
    }
        
    NextStep("single ISpSuspend (low level)");
    err = ISpSuspend();
    VERIFY(err);
 
    NextStep("single ISpResume (low level)");
    err = ISpResume();
    VERIFY(err);
 
    NextStep("testing suspend/resume repeatedly (low level)");
    {
        UInt32 kSuspendResumeLLCount = 1000;
        UInt32 suspendResumeLLItr;
                
        for(suspendResumeLLItr = 0; suspendResumeLLItr < kSuspendResumeLLCount;  suspendResumeLLItr++)
        {
            if (Progress(suspendResumeLLItr, kSuspendResumeLLCount, 5, debug_status))
            {
                StatusMsg(debug_status);
            }
            err = ISpSuspend();
            VERIFY(err);
            
            err = ISpResume();
            VERIFY(err);
        }       
    }
 
    NextStep("looping on startup / shutdown w/ a suspend in the middle");
    {
        const UInt32 kStartShutAttempts = 20;
        UInt32 startShutItr;
                
        for(startShutItr = 0; startShutItr < kStartShutAttempts; startShutItr++)
        {
            if (Progress(startShutItr, kStartShutAttempts, 10, debug_status))
            {
                StatusMsg(debug_status);
            }
 
            err = ISpSuspend();
            VERIFY(err);
 
            err = ISpShutdown();
            VERIFY(err)
 
            err = ISpStartup();
            VERIFY(err);
        }
    }
 
    NextStep("creating virtual elements");
    {
        err = ISpElement_NewVirtualFromNeeds(kNeedCount, gNeeds, gVirtualElements, 0);
        VERIFY(err)
    }
    
    NextStep("looping on disposing/recreating elements");
    {
        const UInt32 kDisposeCreateVirtualAttempts = 1000;
        UInt32 disposeCreateItr;
        
        for(disposeCreateItr = 0; disposeCreateItr < kDisposeCreateVirtualAttempts; disposeCreateItr++)
        {
        
            err = ISpElement_DisposeVirtual(kNeedCount, gVirtualElements);
            VERIFY(err)
 
            err = ISpElement_NewVirtualFromNeeds(kNeedCount, gNeeds, gVirtualElements, 0);
            VERIFY(err)
 
            if (Progress(disposeCreateItr, kDisposeCreateVirtualAttempts, 10, debug_status))
            {
                StatusMsg(debug_status);
            }
        }
    }
    
    NextStep("creating an element list");
    {
        err = ISpElementList_New(
            kNeedCount,             // count
            gVirtualElements,       // needs
            &gVirtualList,          // virtual elements
            0);                     // flags
    
        VERIFY(err)
    }
    
    NextStep("initializing input sprocket once");
    {
        err = ISpInit(kNeedCount,   // count
                gNeeds,             // needs
                gVirtualElements,   // virtual elements
                kCreatorCode,       // app
                kSubCreatorCode,    // sub
                0,                  // flags
                kResourceID_setl,   // set list resource id
                0);                 // version
 
        VERIFY(err)
    }
    
    NextStep("looping on ISpInit / ISpStop");
    {
        const UInt32 kStartStopAttempts = 20;
        UInt32 startStopItr;
                
        err = ISpStop();
        VERIFY(err)
 
        for(startStopItr = 0; startStopItr < kStartStopAttempts; startStopItr++)
        {
            if (Progress(startStopItr, kStartStopAttempts, 10, debug_status))
            {
                StatusMsg(debug_status);
            }
 
            err = ISpInit(kNeedCount, gNeeds, gVirtualElements, kCreatorCode, kSubCreatorCode, 0, kResourceID_setl, 0);
            VERIFY(err);
 
            err = ISpStop();
            VERIFY(err)
        }
    
        err = ISpInit(kNeedCount, gNeeds, gVirtualElements, kCreatorCode, kSubCreatorCode, 0, kResourceID_setl, 0);
        VERIFY(err);
    }
    
    NextStep("counting all the devices (verying size buffer) + isActive");
    {
        const UInt32 maxExtractBufferSize = 1000;
        ISpDeviceReference buffer[maxExtractBufferSize];
        UInt32 deviceCount;
        UInt32 bufferSizeItr;
        UInt32 bufferItr;
        Boolean isActive;
        
        for(bufferSizeItr = 0; bufferSizeItr < 1000; bufferSizeItr++)
        {
            if (Progress(bufferSizeItr, maxExtractBufferSize, 5, debug_status))
            {
                StatusMsg(debug_status);
            }
 
        
            // step 1 put the buffer into a known state
            for(bufferItr = 0; bufferItr < maxExtractBufferSize; bufferItr++)
            {
                buffer[bufferItr] = (ISpDeviceReference) 0xd0d0babe;
            }
            
            // step 2 call extract
            err = ISpDevices_Extract(bufferSizeItr, &deviceCount, buffer);
 
            if (!err)
            {
                for(bufferItr = 0; ((bufferItr < deviceCount) && (bufferItr < bufferSizeItr)); bufferItr++)
                {
                    if ((UInt32) buffer[bufferItr] == 0xd0d0babe)
                    {
                        sprintf(debug_status, "bufferSizeItr = %d deviceCount = %d, bufferItr = %d",bufferSizeItr, deviceCount, bufferItr);
                        StatusMsg(debug_status);
                    }
                    
                    err = ISpDevice_IsActive(buffer[bufferItr], &isActive);
                    if (err) { break; }
                }
            }
            VERIFY(err) 
 
            // step 3 verify the buffer contents
            for(; bufferItr < maxExtractBufferSize; bufferItr++)
            {
                if (((UInt32) buffer[bufferItr]) != 0xd0d0babe) 
                {
                    sprintf(debug_status,"spilled off the end loc = %d cnt = %d",bufferItr,deviceCount);
                    StatusMsg(debug_status);
                }
            }
        }
    }
            
    NextStep("verifying all the devices (100 size buffer) w/ ISpDevice_GetDefinition");
    {
        UInt32 deviceCount;
        ISpDeviceReference buffer[100];
        UInt32 itr;
        ISpDeviceDefinition outStruct;
        
        err = ISpDevices_Extract(100, &deviceCount, buffer);
        
        if (!err)
        {
            for(itr = 0; itr < deviceCount; itr++)
            {
                err = ISpDevice_GetDefinition(buffer[itr], sizeof(ISpDeviceDefinition), &outStruct);
                if (err) { break; }
            }
        }
                    
        VERIFY(err)
    }
    
    NextStep("searching for all the devices of class kISpDeviceClass_Mouse");
    {
        UInt32 deviceCount;
        ISpDeviceReference buffer[100];
        
        err = ISpDevices_ExtractByClass(kISpDeviceClass_Mouse, 100, &deviceCount, buffer);
        
        VERIFY(err)
    }
 
    NextStep("searching for all the devices of class kISpDeviceClass_Keyboard");
    {
        UInt32 deviceCount;
        ISpDeviceReference buffer[100];
        
        err = ISpDevices_ExtractByClass(kISpDeviceClass_Keyboard, 100, &deviceCount, buffer);
        
        VERIFY(err)
    }
 
    NextStep("searching for all the devices of class kISpDeviceClass_Joystick");
    {
        UInt32 deviceCount;
        ISpDeviceReference buffer[100];
        
        err = ISpDevices_ExtractByClass(kISpDeviceClass_Joystick, 100, &deviceCount, buffer);
        
        VERIFY(err)
    }
    
    success = VerifyExtractByClass();
    if (!success) { return; }
    
    success = VerifyActivateDeactive();
    if (!success) { return; }
    
    NextStep("bringing up the configuration screen (devices disabled, dialog warning you there are no devices is OK)");
    {
        err = ISpConfigure(nil);
        
        VERIFY(err)
    }
    
    NextStep("enabling all the devices of class kISpDeviceClass_Mouse");
    {
        UInt32 deviceCount;
        ISpDeviceReference buffer[100];
 
        err = ISpDevices_ExtractByClass(kISpDeviceClass_Mouse, 100, &deviceCount, buffer);
        
        if (!err)
        {
            err = ISpDevices_Activate(deviceCount, buffer);
        }
        
        VERIFY(err)
    }
 
    NextStep("enabling all the devices of class kISpDeviceClass_Keyboard");
    {
        UInt32 deviceCount;
        ISpDeviceReference buffer[100];
        
        err = ISpDevices_ExtractByClass(kISpDeviceClass_Keyboard, 100, &deviceCount, buffer);
        
        if (!err)
        {
            err = ISpDevices_Activate(deviceCount, buffer);
        }
 
        VERIFY(err)
    }
    
    NextStep("bringing up the configuration screen");
    {
        err = ISpConfigure(nil);
        
        VERIFY(err)
    }
    
    NextStep("bringing up the configuration screen w/ filter proc");
    {
        err = ISpConfigure(ISpConfigureFilterProc);
        
        VERIFY(err)
    }
    
    NextStep("getting the global list");
    {
        ISpElementListReference globalList;
        
        err = ISpGetGlobalElementList(&globalList);
 
        VERIFY(err)
    }
    
    NextStep("flushing the global list (and pausing)");
    {
        ISpElementListReference globalList;
        unsigned long ticks;
        const number_of_seconds_to_pause = 2;
        
        err = ISpGetGlobalElementList(&globalList);
 
        if (!err)
        {
            ticks = TickCount();
            ticks += number_of_seconds_to_pause * 60;
            
            while(ticks > TickCount())
            {
                err = ISpElementList_Flush(globalList);
                if (err) { break; }
            }
        }
 
        VERIFY(err)
    }
    
    NextStep("testing getting events, please press a button or move an axis");
    {
        ISpElementListReference globalList;
        ISpElementEvent event;
        Boolean wasEvent;
        
        err = ISpGetGlobalElementList(&globalList);
        
        if (!err)
        {
            wasEvent = false;
            
            while(!wasEvent)
            {
                err = ISpElementList_GetNextEvent(globalList, sizeof(ISpElementEvent), &event, &wasEvent);
                
                if (err == kISpBufferToSmallErr) { err = noErr; }
                
                if (err) { break; }
            }
        }
        
        VERIFY(err)
    }
 
 
    NextStep("flushing the need list (and pausing)");
    {
        unsigned long ticks;
        const number_of_seconds_to_pause = 2;
        
        ticks = TickCount();
        ticks += number_of_seconds_to_pause * 60;
        
        while(ticks > TickCount())
        {
            err = ISpElementList_Flush(gVirtualList);
            if (err) { break; }
        }
 
        VERIFY(err)
    }
    
    NextStep("testing getting need events, please press a configured button or move an axis (escape should always work)");
    {
        ISpElementEvent event;
        Boolean wasEvent;
        
        wasEvent = false;
        
        while(!wasEvent)
        {
            err = ISpElementList_GetNextEvent(gVirtualList, sizeof(ISpElementEvent), &event, &wasEvent);
            
            if (err) { break; }
        }
        
        VERIFY(err)
    }
    
    NextStep("single ISpSuspend");
    err = ISpSuspend();
    VERIFY(err);
 
    NextStep("single ISpResume");
    err = ISpResume();
    VERIFY(err);
 
    NextStep("testing suspend/resume repeatedly (high level)");
    {
        UInt32 kSuspendResumeCount = 1000;
        UInt32 suspendResumeItr;
                
        err = ISpSuspend();
        VERIFY(err);
            
        err = ISpResume();
        VERIFY(err);
 
 
        for(suspendResumeItr = 0; suspendResumeItr < kSuspendResumeCount;  suspendResumeItr++)
        {
            if (Progress(suspendResumeItr, kSuspendResumeCount, 5, debug_status))
            {
                StatusMsg(debug_status);
            }
            err = ISpSuspend();
            VERIFY(err);
            
            err = ISpResume();
            VERIFY(err);
        }       
    }
 
    NextStep("disabling all the devices of class kISpDeviceClass_Mouse");
    {
        UInt32 deviceCount;
        ISpDeviceReference buffer[100];
 
        err = ISpDevices_ExtractByClass(kISpDeviceClass_Mouse, 100, &deviceCount, buffer);
        
        if (!err)
        {
            err = ISpDevices_Deactivate(deviceCount, buffer);
        }
        
        VERIFY(err)
    }
 
    NextStep("disabling all the devices of class kISpDeviceClass_Keyboard");
    {
        UInt32 deviceCount;
        ISpDeviceReference buffer[100];
        
        err = ISpDevices_ExtractByClass(kISpDeviceClass_Keyboard, 100, &deviceCount, buffer);
        
        if (!err)
        {
            err = ISpDevices_Deactivate(deviceCount, buffer);
        }
 
        
        VERIFY(err)
    }
    
    NextStep("stopping input sprocket");
    {
        err = ISpStop();
        
        VERIFY(err)
    }
}
 
#if AUTOTEST
void main(void)
{
    // tell SIOUX to shut up
    SIOUXSettings.autocloseonquit = true;
    SIOUXSettings.asktosaveonclose = false;
 
    AutoTest();
    
    UInt32 who_cares;   
    scanf("%d",&who_cares);
}
#endif
 
#if DIALOGTEST
void main(void)
{
    OSErr err = noErr;
    
    NextStep("verifying that this is the first initialization");
    {
        if (gVirtualList != NULL)
        {
            FailMsg("this was not the first time a test was run for this launch of the application");
            return;
        }
    }
    
    NextStep("creating virtual elements");
    {
        err = ISpElement_NewVirtualFromNeeds(kNeedCount, gNeeds, gVirtualElements, 0);
    
        VERIFY(err)
    }
    
    NextStep("creating an element list");
    {
        err = ISpElementList_New(
            kNeedCount,             // count
            gVirtualElements,       // needs
            &gVirtualList,          // virtual elements
            0);                     // flags
    
        VERIFY(err)
    }
    
    NextStep("initializing input sprocket once");
    {
        err = ISpInit(kNeedCount,   // count
                gNeeds,             // needs
                gVirtualElements,   // virtual elements
                kCreatorCode,       // app
                kSubCreatorCode,    // sub
                0,                  // flags
                kResourceID_setl,   // set list resource id
                0);                 // version
 
        VERIFY(err)
    }
    
    NextStep("enabling all the devices of class kISpDeviceClass_Mouse");
    {
        UInt32 deviceCount;
        ISpDeviceReference buffer[100];
 
        err = ISpDevices_ExtractByClass(kISpDeviceClass_Mouse, 100, &deviceCount, buffer);
        
        if (!err)
        {
            err = ISpDevices_Activate(deviceCount, buffer);
        }
        
        VERIFY(err)
    }
 
    NextStep("enabling all the devices of class kISpDeviceClass_Keyboard");
    {
        UInt32 deviceCount;
        ISpDeviceReference buffer[100];
        
        err = ISpDevices_ExtractByClass(kISpDeviceClass_Keyboard, 100, &deviceCount, buffer);
        
        if (!err)
        {
            err = ISpDevices_Activate(deviceCount, buffer);
        }
 
        VERIFY(err)
    }
    
    NextStep("enabling all the devices of class kISpDeviceClass_SpeechRecognition");
    {
        UInt32 deviceCount;
        ISpDeviceReference buffer[100];
        
        err = ISpDevices_ExtractByClass(kISpDeviceClass_SpeechRecognition, 100, &deviceCount, buffer);
        
        if (!err)
        {
            err = ISpDevices_Activate(deviceCount, buffer);
        }
 
        VERIFY(err)
    }
 
    NextStep("bringing up the configuration screen");
    {
        err = ISpConfigure(nil);
        
        VERIFY(err)
    }
    
    NextStep("disabling all the devices of class kISpDeviceClass_Mouse");
    {
        UInt32 deviceCount;
        ISpDeviceReference buffer[100];
 
        err = ISpDevices_ExtractByClass(kISpDeviceClass_Mouse, 100, &deviceCount, buffer);
        
        if (!err)
        {
            err = ISpDevices_Deactivate(deviceCount, buffer);
        }
        
        VERIFY(err)
    }
 
    NextStep("disabling all the devices of class kISpDeviceClass_Keyboard");
    {
        UInt32 deviceCount;
        ISpDeviceReference buffer[100];
        
        err = ISpDevices_ExtractByClass(kISpDeviceClass_Keyboard, 100, &deviceCount, buffer);
        
        if (!err)
        {
            err = ISpDevices_Deactivate(deviceCount, buffer);
        }
 
        
        VERIFY(err)
    }
    NextStep("stopping input sprocket");
    {
        err = ISpStop();
        
        VERIFY(err)
    }
    
    NextStep("shutting down InputSprocket");
    err = ISpShutdown();
    VERIFY(err)
}
#endif
#if MENUTEST
void main(void)
{
    OSErr err = noErr;
    
    // tell SIOUX to shut up
    SIOUXSettings.autocloseonquit = true;
    SIOUXSettings.asktosaveonclose = false;
    
    printf("starting up...\n");
    
    NumVersion version = ISpGetVersion();
    printf("version = %x %x %x %x\n",version.majorRev, version.minorAndBugRev, version.stage, version.nonRelRev);
 
    NextStep("starting up InputSprocket");
    err = ISpStartup();
    VERIFY(err);
 
    Boolean theDoneFlag = false;
    
    EnableDeviceClass(kISpDeviceClass_SpeechRecognition, true);
    
    while( !theDoneFlag )
    {
        UInt32 theChoice;
        
        printf("\n\n\n############################################################\n");
        if (gIsSuspended)
        {
            printf("¥ SUSPENDED ¥\n");
        }
        
        if (gVirtualList != NULL)
        {
            printf("¥ NEEDS ARE ACTIVE ¥\n");
        }
        
        printf("Please select from the following tests:\n");        
        printf("\t 1. Exit\n");
        printf("\t 2. Run all tests automatically\n");
        printf("\t 3. Test ISpElementList_ExtractByKind\n");
        printf("\t 4. List all devices\n");
        printf("\t 5. List all elements\n");
        printf("\t 6. List all buttons\n");
        printf("\t 7. List all directional pads\n");
        printf("\t 8. List all axes\n");
        printf("\t 9. List all X-axes\n");
        printf("\t10. Get events (stop when Command key pressed)\n");
        printf("\t11. Suspend\n");
        printf("\t12. Resume\n");
        printf("\t13. Create needs\n");
        printf("\t14. Destroy needs\n");
        printf("\t15. Get needs events\n");
        printf("\t16. Configuration dialog\n");
        printf("\t17. Enable mouse and keyboard\n");
        printf("\t18. Disable mouse and keyboard\n");
        printf("\t19. Reinitialize ADB bus\n");
        printf("\t30. Allocate/Deallocate test\n");
        #if DEBUG_DRIVER
            printf("\t31. TestAllocatePushData test\n");
        #endif
        printf("\t32. TestArbitraryAllocate test\n");
        printf("\t33. TestAccelration\n");
        printf("\t34. Enable speech\n");
        printf("\t35. Disable speech\n");
        printf("\t36. Acceleration test # 2\n");
        
        printf("\n\tSelection: ");
        
        Boolean keyboardEnabled = gKeyboardEnabled;
        if (keyboardEnabled)
        {
            EnableDeviceClass(kISpDeviceClass_Keyboard, false);
        }
        
        char theString[32];
        gets( theString );
        theChoice = atoi( theString );
        
        if (keyboardEnabled)
        {
            EnableDeviceClass(kISpDeviceClass_Keyboard, true);
        }
        
        printf("\n\n");
        
        switch( theChoice )
        {
            case 1:
                theDoneFlag = true;
                break;
                
            case 2:
                AutoTest();
                break;
                
            case 3:
                TestElementList_ExtractByKind();
                break;
                
            case 4:
                TestListOfDevices();
                break;          
            
            case 5:
                TestListOfElements();
                break;          
            
            case 6:
                TestListOfButtons();
                break;          
            
            case 7:
                TestListOfDPads();
                break;          
            
            case 8:
                TestListOfAxes();
                break;          
            
            case 9:
                TestListOfXAxes();
                break;          
            
            case 10:
                GetAndPrintEvents(NULL);
                break;          
            
            case 11:
                TestSuspend();
                break;          
            
            case 12:
                TestResume();
                break;          
            
            case 13:
                TestCreateNeeds();
                break;          
            
            case 14:
                TestDestroyNeeds();
                break;          
            
            case 15:
                TestNeedsEvents();
                break;          
            
            case 16:
                TestConfiguration();
                break;          
            
            case 17:
                EnableDeviceClass(kISpDeviceClass_Mouse, true);
                EnableDeviceClass(kISpDeviceClass_Keyboard, true);
                break;          
            
            case 18:
                EnableDeviceClass(kISpDeviceClass_Mouse, false);
                EnableDeviceClass(kISpDeviceClass_Keyboard, false);
                break;
            
            case 19:
                ADBReInit();
                break;
                
            case 30:
                TestAllocateDeallocate();
                break;
        
        #if DEBUG_DRIVER
            case 31:
                TestAllocatePushData();
                break;
        #endif
            
            case 32:
                TestArbitraryAllocate();
                break;
            
            case 33:
                TestAcceleration();
                break;
                
            case 34:
                EnableDeviceClass(kISpDeviceClass_SpeechRecognition, true);
                break;          
            
            case 35:
                EnableDeviceClass(kISpDeviceClass_SpeechRecognition, false);
                break;
            
            case 36:
                TestAcceleration2();
                break;
 
            default:
                printf("\nhuh?\n");
                break;          
        }
        
        printf("\nThank you, please drive through.\n");
    }
}
#endif