⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 hidjoystick.cpp

📁 Wxpython Implemented on Windows CE, Source code
💻 CPP
📖 第 1 页 / 共 2 页
字号:
}

bool wxJoystick::HasU() const
{
    return m_hid->HasElement(wxJS_AXIS_U);
}

bool wxJoystick::HasV() const
{
    return m_hid->HasElement(wxJS_AXIS_V);
}

//---------------------------------------------------------------------------
// UNSUPPORTED
//---------------------------------------------------------------------------
int wxJoystick::GetPOVPosition() const
{
    return -1;
}

int wxJoystick::GetPOVCTSPosition() const
{
    return -1;
}

int wxJoystick::GetMovementThreshold() const
{
    return 0;
}

void wxJoystick::SetMovementThreshold(int threshold)
{
}

bool wxJoystick::HasPOV() const
{
    return false;
}

bool wxJoystick::HasPOV4Dir() const
{
    return false;
}

bool wxJoystick::HasPOVCTS() const
{
    return false;
}

//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//
// wxHIDJoystick
//
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

//---------------------------------------------------------------------------
// wxHIDJoystick ctor
//
// Initializes the min/max members
//---------------------------------------------------------------------------
wxHIDJoystick::wxHIDJoystick() :
 m_nXMax(0), m_nYMax(0), m_nZMax(0), m_nRudderMax(0), m_nUMax(0), m_nVMax(0),
 m_nXMin(0), m_nYMin(0), m_nZMin(0), m_nRudderMin(0), m_nUMin(0), m_nVMin(0)
{
}

//---------------------------------------------------------------------------
// wxHIDJoystick dtor
//
// Nothing...
//---------------------------------------------------------------------------
wxHIDJoystick::~wxHIDJoystick()
{
}

//---------------------------------------------------------------------------
// wxHIDJoystick::Create
//
// Creates the native HID device (joysticks are of either
// kHIDUsage_GD_Joystick or kHIDUsage_GD_GamePad)
//---------------------------------------------------------------------------
bool wxHIDJoystick::Create(int nWhich)
{
    int nJoysticks = GetCount(kHIDPage_GenericDesktop, kHIDUsage_GD_Joystick);

    if (nWhich <= nJoysticks)
        return wxHIDDevice::Create(kHIDPage_GenericDesktop,
                                   kHIDUsage_GD_Joystick,
                                   nWhich);
    else
        nWhich -= nJoysticks;

    int nGamePads = GetCount(kHIDPage_GenericDesktop, kHIDUsage_GD_GamePad);

    if (nWhich <= nGamePads)
        return wxHIDDevice::Create(kHIDPage_GenericDesktop,
                                   kHIDUsage_GD_GamePad,
                                   nWhich);
    else
    return false;
}

//---------------------------------------------------------------------------
// wxHIDJoystick::BuildCookies
// wxHIDJoystick::MakeCookies
//
// Sets up the cookies for the HID device (called from Create) - as
// mentioned 0-40 are the buttons and 40-50 are the axes.
//
// MakeCookies is just a recursive function for each array within
// BuildCookies.
//---------------------------------------------------------------------------
void wxHIDJoystick::BuildCookies(CFArrayRef Array)
{
    InitCookies(50, true);

    //
    // I wasted two hours of my life on this line :(
    // accidently removed it during some source cleaning...
    //
    MakeCookies(Array);

    //paranoid debugging stuff
#if 0
    for(int i = 0; i < 50; ++i)
        wxPrintf(wxT("\nVAL #%i:[%i]"), i, m_pCookies[i]);
#endif
}//end buildcookies

void wxHIDJoystick::MakeCookies(CFArrayRef Array)
{
    int i, nUsage, nPage;

    for (i = 0; i < CFArrayGetCount(Array); ++i)
    {
        const void* ref = CFDictionaryGetValue(
                (CFDictionaryRef)CFArrayGetValueAtIndex(Array, i),
                CFSTR(kIOHIDElementKey)
                                              );

        if (ref != NULL)
        {
            MakeCookies((CFArrayRef) ref);
    }
        else
        {
            CFNumberGetValue(
                (CFNumberRef)
                    CFDictionaryGetValue(
                        (CFDictionaryRef) CFArrayGetValueAtIndex(Array, i),
                        CFSTR(kIOHIDElementUsageKey)
                                        ),
                kCFNumberIntType,
                &nUsage    );

            CFNumberGetValue(
                (CFNumberRef)
                    CFDictionaryGetValue(
                        (CFDictionaryRef) CFArrayGetValueAtIndex(Array, i),
                        CFSTR(kIOHIDElementUsagePageKey)
                                        ),
                kCFNumberIntType,
                &nPage     );

#if 0
            wxLogSysError(wxT("[%i][%i]"), nUsage, nPage);
#endif
            if (nPage == kHIDPage_Button && nUsage <= 40)
                AddCookieInQueue(CFArrayGetValueAtIndex(Array, i), nUsage-1 );
            else if (nPage == kHIDPage_GenericDesktop)
            {
                //axis...
                switch(nUsage)
                {
                    case kHIDUsage_GD_X:
                        AddCookieInQueue(CFArrayGetValueAtIndex(Array, i), wxJS_AXIS_X);
                        wxGetIntFromCFDictionary(CFArrayGetValueAtIndex(Array, i),
                                                 CFSTR(kIOHIDElementMaxKey),
                                                 &m_nXMax);
                        wxGetIntFromCFDictionary(CFArrayGetValueAtIndex(Array, i),
                                                 CFSTR(kIOHIDElementMinKey),
                                                 &m_nXMin);
                        break;
                    case kHIDUsage_GD_Y:
                        AddCookieInQueue(CFArrayGetValueAtIndex(Array, i), wxJS_AXIS_Y);
                        wxGetIntFromCFDictionary(CFArrayGetValueAtIndex(Array, i),
                                                 CFSTR(kIOHIDElementMaxKey),
                                                 &m_nYMax);
                        wxGetIntFromCFDictionary(CFArrayGetValueAtIndex(Array, i),
                                                 CFSTR(kIOHIDElementMinKey),
                                                 &m_nYMin);
                        break;
                    case kHIDUsage_GD_Z:
                        AddCookieInQueue(CFArrayGetValueAtIndex(Array, i), wxJS_AXIS_Z);
                        wxGetIntFromCFDictionary(CFArrayGetValueAtIndex(Array, i),
                                                 CFSTR(kIOHIDElementMaxKey),
                                                 &m_nZMax);
                        wxGetIntFromCFDictionary(CFArrayGetValueAtIndex(Array, i),
                                                 CFSTR(kIOHIDElementMinKey),
                                                 &m_nZMin);
                        break;
                    default:
                        break;
                }
            }
            else if (nPage == kHIDPage_Simulation && nUsage == kHIDUsage_Sim_Rudder)
            {
                //rudder...
                AddCookieInQueue(CFArrayGetValueAtIndex(Array, i), wxJS_AXIS_RUDDER );
                wxGetIntFromCFDictionary(CFArrayGetValueAtIndex(Array, i),
                                         CFSTR(kIOHIDElementMaxKey),
                                         &m_nRudderMax);
                wxGetIntFromCFDictionary(CFArrayGetValueAtIndex(Array, i),
                                         CFSTR(kIOHIDElementMinKey),
                                         &m_nRudderMin);
            }
        }
    }
}

//---------------------------------------------------------------------------
// wxHIDJoystick::Get[XXX]
//
// Simple accessors so that the HID callback and the thread procedure
// can access members from wxHIDDevice (our parent here).
//---------------------------------------------------------------------------
IOHIDElementCookie* wxHIDJoystick::GetCookies()
{   return m_pCookies;  }
IOHIDQueueInterface** wxHIDJoystick::GetQueue()
{   return m_ppQueue;   }

//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//
// wxJoystickThread
//
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

//---------------------------------------------------------------------------
// wxJoystickThread Constructor
//
// Just initializes members
//---------------------------------------------------------------------------
wxJoystickThread::wxJoystickThread(wxHIDJoystick* hid, int joystick)
    : m_hid(hid),
      m_joystick(joystick),
      m_lastposition(127,127),
      m_buttons(0),
      m_catchwin(NULL),
      m_polling(0)
{
    memset(m_axe, 0, sizeof(int) * wxJS_MAX_AXES);
}

//---------------------------------------------------------------------------
// wxJoystickThread::Entry
//
// Thread procedure
//
// Runs a CFRunLoop for polling. Basically, it sets the HID queue to
// call wxJoystickThread::HIDCallback in the context of this thread
// when something changes on the device. It polls as long as the user
// wants, or a certain amount if the user wants to "block". Note that
// we don't actually block here since this is in a secondary thread.
//---------------------------------------------------------------------------
void* wxJoystickThread::Entry()
{
    CFRunLoopSourceRef pRLSource = NULL;

    if ((*m_hid->GetQueue())->createAsyncEventSource(
                    m_hid->GetQueue(), &pRLSource) != kIOReturnSuccess )
    {
        wxLogSysError(wxT("Couldn't create async event source"));
        return NULL;
    }

    wxASSERT(pRLSource != NULL);

    //attach runloop source to main run loop in thread
    CFRunLoopRef pRL = CFRunLoopGetCurrent();
    CFRunLoopAddSource(pRL, pRLSource, kCFRunLoopDefaultMode);
    wxASSERT( CFRunLoopContainsSource(pRL, pRLSource, kCFRunLoopDefaultMode) );


    if( (*m_hid->GetQueue())->setEventCallout(m_hid->GetQueue(),
          wxJoystickThread::HIDCallback, this, this) != kIOReturnSuccess )
    {
        wxLogSysError(wxT("Could not set event callout for queue"));
        return NULL;
    }

    if( (*m_hid->GetQueue())->start(m_hid->GetQueue()) != kIOReturnSuccess )
    {
        wxLogSysError(wxT("Could not start queue"));
        return NULL;
    }

    double dTime;

    while(true)
    {
        if (TestDestroy())
            break;

        if (m_polling)
            dTime = 0.0001 * m_polling;
        else
            dTime = 0.0001 * 10;  // check at least every 10 msec in "blocking" case

        //true just "handles and returns" - false forces it to stay the time
        //amount
#if 1
        CFRunLoopRunInMode(kCFRunLoopDefaultMode, dTime, true);
#else
        IOReturn ret = NULL;
        HIDCallback(this, ret, this, this);
        Sleep(3000);
#endif
    }

    wxASSERT( CFRunLoopContainsSource(pRL, pRLSource, kCFRunLoopDefaultMode) );

    CFRunLoopRemoveSource(pRL, pRLSource, kCFRunLoopDefaultMode);
    CFRelease(pRLSource);

    return NULL;
}

//---------------------------------------------------------------------------
// wxJoystickThread::HIDCallback (static)
//
// Callback for the native HID device when it recieves input.
//
// This is where the REAL dirty work gets done.
//
// 1) Loops through each event the queue has recieved
// 2) First, checks if the thread that is running the loop for
//    the polling has ended - if so it breaks out
// 3) Next, it checks if there was an error getting this event from
//    the HID queue, if there was, it logs an error and returns
// 4) Now it does the real dirty work by getting the button states
//    from cookies 0-40 and axes positions/states from cookies 40-50
//    in the native HID device by quering cookie values.
// 5) Sends the event to the polling window (if any)
// 6) Gets the next event and goes back to (1)
//---------------------------------------------------------------------------
/*static*/ void wxJoystickThread::HIDCallback(void* target, IOReturn res,
                                              void* context, void* sender)
{
    IOHIDEventStruct hidevent;
    AbsoluteTime bogustime = {0,0};
    IOReturn ret;
    wxJoystickThread* pThis = (wxJoystickThread*) context;
    wxHIDJoystick* m_hid = pThis->m_hid;

    //Get the "first" event from the queue
    //bogustime tells it we don't care at what time to start
    //where it gets the next from
    ret = (*m_hid->GetQueue())->getNextEvent(m_hid->GetQueue(),
                    &hidevent, bogustime, 0);

    while (ret != kIOReturnUnderrun)
    {
        if (pThis->TestDestroy())
            break;

        if(ret != kIOReturnSuccess)
        {
            wxLogSysError(wxString::Format(wxT("wxJoystick Error:[%i]"), ret));
            return;
        }

        wxJoystickEvent wxevent;

        //Find the cookie that changed
        int nIndex = 0;
        IOHIDElementCookie* pCookies = m_hid->GetCookies();
        while(nIndex < 50)
        {
            if(hidevent.elementCookie == pCookies[nIndex])
                break;

            ++nIndex;
        }

        //debugging stuff
#if 0
        if(nIndex == 50)
        {
            wxLogSysError(wxString::Format(wxT("wxJoystick Out Of Bounds Error")));
            break;
        }
#endif

        //is the cookie a button?
        if (nIndex < 40)
        {
            if (hidevent.value)
            {
                pThis->m_buttons |= (1 << nIndex);
                wxevent.SetEventType(wxEVT_JOY_BUTTON_DOWN);
            }
            else
            {
                pThis->m_buttons &= ~(1 << nIndex);
                wxevent.SetEventType(wxEVT_JOY_BUTTON_UP);
            }

            wxevent.SetButtonChange(nIndex+1);
        }
        else if (nIndex == wxJS_AXIS_X)
        {
            pThis->m_lastposition.x = hidevent.value;
            wxevent.SetEventType(wxEVT_JOY_MOVE);
            pThis->m_axe[0] = hidevent.value;
        }
        else if (nIndex == wxJS_AXIS_Y)
        {
            pThis->m_lastposition.y = hidevent.value;
            wxevent.SetEventType(wxEVT_JOY_MOVE);
            pThis->m_axe[1] = hidevent.value;
        }
        else if (nIndex == wxJS_AXIS_Z)
        {
            wxevent.SetEventType(wxEVT_JOY_ZMOVE);
            pThis->m_axe[2] = hidevent.value;
        }
        else
            wxevent.SetEventType(wxEVT_JOY_MOVE);

        Nanoseconds timestamp = AbsoluteToNanoseconds(hidevent.timestamp);

        wxULongLong llTime(timestamp.hi, timestamp.lo);

        llTime /= 1000000;

        wxevent.SetTimestamp(llTime.GetValue());
        wxevent.SetJoystick(pThis->m_joystick);
        wxevent.SetButtonState(pThis->m_buttons);
        wxevent.SetPosition(pThis->m_lastposition);
        wxevent.SetZPosition(pThis->m_axe[2]);
        wxevent.SetEventObject(pThis->m_catchwin);

        if (pThis->m_catchwin)
            pThis->m_catchwin->AddPendingEvent(wxevent);

        ret = (*m_hid->GetQueue())->getNextEvent(m_hid->GetQueue(),
                    &hidevent, bogustime, 0);
    }
}

#endif // wxUSE_JOYSTICK && defined(__DARWIN__)

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -