Issues using DInput

Post questions, comments and feedback to our 3Dconnexion Windows Development Team.

Moderator: Moderators

Post Reply
simplyRubbish
Posts: 13
Joined: Fri Oct 02, 2009 7:25 am
Location: Daytona Beach, FL

Issues using DInput

Post by simplyRubbish »

I have already posted this topic in the general "Developer's Forum for Windows" but figured to post here as well. If I shouldn't have I apologize.

First off, I am using the SpaceExplorer and attempting to get this device to work with our software using DirectInput: http://www.3dconnexion.com/3dmouse/spaceexplorer.php

The problem that I'm getting stumped at is in EnumAxesCB function. *pDIDeviceInfo is NULL so my application crashes. Here's what my code looks like for there:

Code: Select all

BOOL CALLBACK EnumAxesCB( const DIDEVICEOBJECTINSTANCE* pdidoi, 
                         VOID* pContext ) 
                         /* 
                         Callback function for enumerating the axes on a UsbHidDevice 
                         -----------------------------------------------------------------------------*/ 
{ 
    HWND hDlg = (HWND)pContext; 
    DIDeviceInfo *pDIDeviceInfo = (DIDeviceInfo *)GetWindowLongPtr( hDlg, GWLP_HINSTANCE ); 

#if 0 // this has no effect 
    // Set the range for the axis 
    DIPROPRANGE diprg; 
    diprg.diph.dwSize       = sizeof(DIPROPRANGE); 
    diprg.diph.dwHeaderSize = sizeof(DIPROPHEADER); 
    diprg.diph.dwHow        = DIPH_BYID; 
    diprg.diph.dwObj        = pdidoi->dwType; // Specify the enumerated axis 
    diprg.lMin              = -512; // +/- 512 matches the hardware 1:1 
    diprg.lMax              =  511; 

    if( FAILED( pDIDeviceInfo->pUsbHidDevice->SetProperty( DIPROP_RANGE, &diprg.diph ) ) ) 
        return DIENUM_STOP; 
#endif 

    /* 
    * Recent 3Dx USB device descriptors indicate that the device axes return relative data 
    * even though the device is really an absolute device. 
    * HID ignores this, but apparently DI uses it. 
    * Changing the axis handling to return RELATIVE values gives us back what we want (displacement 
    * values rather than accumulated values).  If older USB devices were to be supported, this handling 
    * would have to be changed to DIPROPAXISMODE_ABS.  
    * 
    * In this mode, DI sets the notification event even though the values haven't changed. 
    */ 
    DIPROPDWORD dipdw; 
    dipdw.diph.dwSize       = sizeof(DIPROPDWORD); 
    dipdw.diph.dwHeaderSize = sizeof(DIPROPHEADER); 
    dipdw.diph.dwHow        = DIPH_DEVICE; 
    dipdw.diph.dwObj        = 0; // set for whole device not an axis (really only needs to be done once) 
    dipdw.dwData            = DIPROPAXISMODE_REL; 

    if( FAILED( pDIDeviceInfo->pUsbHidDevice->SetProperty( DIPROP_AXISMODE, &dipdw.diph ) ) ) 
        return DIENUM_STOP; 

    return DIENUM_CONTINUE; 
} 
The reason I'm using GLWP_HINSTANCE instead of GWLP_USERDATA is due to the fact I'm not actually creating the window the HWND is attached to in EnumDevicesCB function. Here's my code for EnumDevicesCB to show what I mean:

Code: Select all

BOOL CALLBACK EnumDevicesCB( const DIDEVICEINSTANCE* pdidInstance, 
                            VOID* pContext ) 
                            /* 
                            Called once for each enumerated UsbHidDevice. If we find one, create a 
                            device interface on it so we can play with it. 
                            -----------------------------------------------------------------------------*/ 
{ 
    int newIndex; 
    HRESULT hr; 
    GUID guid = pdidInstance->guidProduct; 
#   define LOGITECH_3DX_VID    0x046d  // Vendor ID for Logitech/3Dx 

    /* Check to see if this is a 3Dx device.  Look at the VendorID before stopping the enumeration. */ 
    if ( (guid.Data1 & 0x0000ffff) != LOGITECH_3DX_VID) 
        return DIENUM_CONTINUE; 

    /* Filter out LOGI mice and such */ 
    else if (pdidInstance->wUsagePage != 0x0001 || pdidInstance->wUsage != 0x0008) 
        return DIENUM_CONTINUE; 

    /* Make sure haven't found too many 3Dx devices for our array */ 
    if (g_nDevices >= MAX_DEVICES) 
        return DIENUM_CONTINUE; 


    newIndex = g_nDevices; 
    g_pDevices[g_nDevices++] = (DIDeviceInfo*)malloc( sizeof(DIDeviceInfo) ); 

    /* Set state variables to known values */ 
    ZeroMemory( &g_pDevices[newIndex]->lastJoyState, sizeof(DIJOYSTATE) ); 
    g_pDevices[newIndex]->lastVectorType = BothZeroVectors; 

    /* 
    * Save the DIDEVICEINSTANCE struct for later display. 
    * This isn't necessary.  The demo just does it to display the info in the dlg box. 
    */ 
    g_pDevices[newIndex]->DIDevInstance = *pdidInstance; 

    /* Obtain an interface to the enumerated device. */ 
    hr = g_pDI->CreateDevice( pdidInstance->guidInstance, &g_pDevices[newIndex]->pUsbHidDevice, NULL ); 

    /* 
    * If it failed, then we can't use this UsbHidDevice. (Maybe the user unplugged 
    * it while we were in the middle of enumerating it.) 
    */ 
    if( FAILED(hr) ) 
    { 
        free (g_pDevices[newIndex]); 
        g_nDevices--; 
        return DIENUM_CONTINUE; 
    } 

    /* Create a info dialog box for this device */ 
    //g_pDevices[newIndex]->hDlg = CreateDialogParam( hInst, MAKEINTRESOURCE(_APS_NEXT_RESOURCE_VALUE), NULL, DlgProc, 
    //    (LPARAM)g_pDevices[newIndex] ); 
    g_pDevices[newIndex]->hDlg = GetForegroundWindow(); 

    return DIENUM_CONTINUE; 
}
As you can see, the original "CreateDialogParam" is removed due to the fact this console application was already created so the code to handle that is done. I guess the question I'm trying to get at is, how can I handle the EnumAxesCB() function properly while getting the correct pDIDeviceInfo if I didn't do the creation of the window in EnumDevicesCB?

Any help on this issue is appreciated. Thank you.
simplyRubbish
Posts: 13
Joined: Fri Oct 02, 2009 7:25 am
Location: Daytona Beach, FL

Post by simplyRubbish »

Double thread, please ignore this one.
Post Reply