447 lines
15 KiB
C
447 lines
15 KiB
C
/***************************************************************************/
|
|
/* Description: InitDI.c, part of CPA INO library */
|
|
/* Direct Input device low level init implementation */
|
|
/* */
|
|
/* Author: F. Jentey */
|
|
/* Creation date: 21/04/97 */
|
|
/* Last Update: 30/07/97 Direct input initialisation */
|
|
/***************************************************************************/
|
|
|
|
|
|
/*======== Direct Input header ========*/
|
|
#ifndef INITGUID
|
|
#define INITGUID
|
|
#include "DInput.h"
|
|
#undef INITGUID
|
|
#else
|
|
#include "DInput.h"
|
|
#endif
|
|
|
|
/*=======================================*/
|
|
|
|
#include "INO\errINO.h"
|
|
#include "INOInit.h"
|
|
#include "InitDI.h"
|
|
#include "INOJoy.h"
|
|
#include "INOKeyb.h"
|
|
#include "INOMouse.h"
|
|
#include "Joystick.h"
|
|
|
|
|
|
|
|
#define M_DInput() INO_g_p_stDInputInterface->lpVtbl
|
|
|
|
|
|
LPDIRECTINPUT INO_g_p_stDInputInterface = NULL;
|
|
HINSTANCE INO_g_hAppInstance;
|
|
HWND INO_g_hAppMainWindow;
|
|
unsigned long m_ulDITargetVersion = DIRECTINPUT_VERSION; /* Version of Direct Input the module was build for*/
|
|
unsigned long m_ulDIInstalledVersion; /* Version of Direct Input installed on the machine*/
|
|
DIDEVCAPS g_stDIDevCaps;
|
|
DIDEVCAPS_DX3 g_stDIDevCaps3;
|
|
|
|
|
|
|
|
|
|
|
|
INO_tdstDIDevice INO_g_a_stDIDevice[INO_C_wNbMaxDevice];
|
|
short INO_g_wNbDevices = 0;
|
|
|
|
|
|
|
|
|
|
/*********************************************************************************/
|
|
/* Joystick enumeration callback */
|
|
/* Device instance are stored in INO_g_a_stJoystickInstance */
|
|
/*********************************************************************************/
|
|
BOOL CALLBACK fn_bEnumDeviceCallback(LPCDIDEVICEINSTANCE p_stDeviceInstance, LPVOID p_vRef)
|
|
{
|
|
LPDIRECTINPUTDEVICE p_stDevice;
|
|
LPDIRECTINPUTDEVICE2 p_stDevice2;
|
|
LPCDIDATAFORMAT p_stDataFormat;
|
|
DWORD ulCooperativeLevel;
|
|
HRESULT DInputErr;
|
|
|
|
/* Create the DirectInput joystick device */
|
|
DInputErr = M_DInput()->CreateDevice(
|
|
INO_g_p_stDInputInterface,
|
|
&p_stDeviceInstance->guidInstance,
|
|
&p_stDevice,
|
|
NULL
|
|
);
|
|
if (DInputErr != DI_OK) return FALSE;
|
|
|
|
switch (GET_DIDEVICE_TYPE(p_stDeviceInstance->dwDevType))
|
|
{
|
|
case DIDEVTYPE_MOUSE:
|
|
p_stDataFormat = &c_dfDIMouse;
|
|
/* All these settings have been tried in NT 4 with Service Pack 3 installed*/
|
|
/* This is the option selected...*/
|
|
ulCooperativeLevel = DISCL_NONEXCLUSIVE | DISCL_FOREGROUND;
|
|
/* This one freezes the mouse...*/
|
|
/*ulCooperativeLevel = DISCL_EXCLUSIVE | DISCL_FOREGROUND;*/
|
|
/* Works similarly to DISCL_NONEXCLUSIVE | DISCL_FOREGROUND*/
|
|
/*ulCooperativeLevel = DISCL_NONEXCLUSIVE | DISCL_BACKGROUND;*/
|
|
/* This one causes unhandled exceptions...*/
|
|
/*ulCooperativeLevel = DISCL_EXCLUSIVE | DISCL_BACKGROUND;*/
|
|
break;
|
|
case DIDEVTYPE_KEYBOARD:
|
|
p_stDataFormat = &c_dfDIKeyboard;
|
|
ulCooperativeLevel = DISCL_NONEXCLUSIVE | DISCL_FOREGROUND;
|
|
/*ulCooperativeLevel = DISCL_EXCLUSIVE | DISCL_FOREGROUND;*/
|
|
break;
|
|
case DIDEVTYPE_JOYSTICK:
|
|
p_stDataFormat = &c_dfDIJoystick;
|
|
ulCooperativeLevel = DISCL_NONEXCLUSIVE | DISCL_FOREGROUND;
|
|
break;
|
|
default:
|
|
return FALSE;
|
|
}
|
|
|
|
/* Make sure the device is not acquired before calling setDataFormat */
|
|
/* and SetCooperativeLevel. */
|
|
DInputErr = p_stDevice->lpVtbl->Unacquire(p_stDevice);
|
|
/* Set joystick data format */
|
|
DInputErr = p_stDevice->lpVtbl->SetDataFormat(p_stDevice, p_stDataFormat);
|
|
if (DInputErr != DI_OK)
|
|
{
|
|
p_stDevice->lpVtbl->Release(p_stDevice);
|
|
return FALSE;
|
|
}
|
|
|
|
/* Set the cooperative level */
|
|
DInputErr = p_stDevice->lpVtbl->SetCooperativeLevel(
|
|
p_stDevice,
|
|
INO_g_hAppMainWindow,
|
|
ulCooperativeLevel
|
|
);
|
|
if (DInputErr != DI_OK)
|
|
{
|
|
p_stDevice->lpVtbl->Release(p_stDevice);
|
|
return FALSE;
|
|
}
|
|
|
|
/* Everything is OK, keep this joystick */
|
|
memcpy(
|
|
&INO_g_a_stDIDevice[INO_g_wNbDevices].m_stDevInstance,
|
|
p_stDeviceInstance,
|
|
sizeof(DIDEVICEINSTANCE)
|
|
);
|
|
INO_g_a_stDIDevice[INO_g_wNbDevices].m_p_stDevInterface = p_stDevice;
|
|
|
|
/* Find the IDirectInput2 interface, for using Poll method */
|
|
if (GET_DIDEVICE_TYPE(p_stDeviceInstance->dwDevType) == DIDEVTYPE_JOYSTICK)
|
|
{
|
|
DInputErr = p_stDevice->lpVtbl->QueryInterface(
|
|
p_stDevice,
|
|
&IID_IDirectInputDevice2,
|
|
(LPVOID*)&p_stDevice2
|
|
);
|
|
if (DInputErr == S_OK)
|
|
{
|
|
INO_g_a_stDIDevice[INO_g_wNbDevices].m_p_stDevInterface2 = p_stDevice2;
|
|
INO_g_a_stDIDevice[INO_g_wNbDevices].m_wExtendedInterfaceAvailable = 1;
|
|
}
|
|
else
|
|
{
|
|
INO_g_a_stDIDevice[INO_g_wNbDevices].m_p_stDevInterface2 = NULL;
|
|
INO_g_a_stDIDevice[INO_g_wNbDevices].m_wExtendedInterfaceAvailable = 0;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
INO_g_a_stDIDevice[INO_g_wNbDevices].m_p_stDevInterface2 = NULL;
|
|
INO_g_a_stDIDevice[INO_g_wNbDevices].m_wExtendedInterfaceAvailable = 0;
|
|
}
|
|
|
|
INO_g_wNbDevices++;
|
|
return DIENUM_CONTINUE;
|
|
}
|
|
|
|
|
|
|
|
/***********************************/
|
|
/* Init Direct Input */
|
|
/* Return 1 if OK, else 0 */
|
|
/***********************************/
|
|
short INO_fn_wInitAllDevices(HINSTANCE hInstance, HWND hWindow)
|
|
{
|
|
HRESULT DInputErr;
|
|
|
|
if (INO_g_p_stDInputInterface)
|
|
return(1);
|
|
|
|
INO_g_wNbDevices = 0;
|
|
DInputErr = DirectInputCreate(hInstance,DIRECTINPUT_VERSION,&INO_g_p_stDInputInterface,NULL);
|
|
if (DInputErr==DIERR_OLDDIRECTINPUTVERSION)
|
|
{
|
|
/* If compiled with Direct Input 5, and Direct Input 3 is installed */
|
|
DInputErr = DirectInputCreate(hInstance,DIRECTINPUT_VERSION_3,&INO_g_p_stDInputInterface,NULL);
|
|
if (DInputErr == DI_OK)
|
|
m_ulDIInstalledVersion = DIRECTINPUT_VERSION_3;
|
|
}
|
|
else
|
|
m_ulDIInstalledVersion = DIRECTINPUT_VERSION;
|
|
|
|
switch (DInputErr)
|
|
{
|
|
case DI_OK:
|
|
INO_g_hAppInstance = hInstance;
|
|
INO_g_hAppMainWindow = hWindow;
|
|
break;
|
|
|
|
case DIERR_INVALIDPARAM:
|
|
case DIERR_OUTOFMEMORY:
|
|
case DIERR_OLDDIRECTINPUTVERSION:
|
|
case DIERR_BETADIRECTINPUTVERSION:
|
|
default:
|
|
INO_g_p_stDInputInterface = NULL;
|
|
m_ulDIInstalledVersion = 0;
|
|
INO_fn_vUpdateLastError(E_uwINO_FatalDirectInpuNotFound);
|
|
return (0);
|
|
}
|
|
|
|
memset(INO_g_a_stDIDevice,0,sizeof(INO_tdstDIDevice)*INO_C_wNbMaxDevice);
|
|
|
|
DInputErr = M_DInput()->EnumDevices(
|
|
INO_g_p_stDInputInterface,
|
|
0,
|
|
fn_bEnumDeviceCallback,
|
|
NULL,
|
|
DIEDFL_ALLDEVICES
|
|
);
|
|
if( DInputErr == DI_OK )
|
|
{
|
|
return ( 1 );
|
|
}
|
|
|
|
return( 0 );
|
|
}
|
|
|
|
|
|
/***********************************/
|
|
/* Init one device */
|
|
/***********************************/
|
|
short INO_fn_wInitDevice(INO_tdhDevice hDev)
|
|
{
|
|
HRESULT DInputErr;
|
|
short i, wResult;
|
|
|
|
for (i=0; i<INO_C_wNbMaxDevice; i++)
|
|
{
|
|
if (!INO_g_a_stDIDevice[i].m_hDevice &&
|
|
(1 << GET_DIDEVICE_TYPE(INO_g_a_stDIDevice[i].m_stDevInstance.dwDevType) == INO_M_uwType(hDev))
|
|
)
|
|
{
|
|
INO_g_a_stDIDevice[i].m_hDevice = hDev;
|
|
switch (INO_M_uwType(hDev))
|
|
{
|
|
case INO_C_uwJoystick:
|
|
hDev->m_pfnRead = INO_fn_wReadJoystick;
|
|
wResult = INO_fn_wInitJoystickCaps(hDev);
|
|
break;
|
|
case INO_C_uwKeyboard:
|
|
hDev->m_pfnRead = INO_fn_wReadKeyboard;
|
|
wResult = INO_fn_wInitKeyboardCaps(hDev);
|
|
break;
|
|
case INO_C_uwMouse:
|
|
/* Initialize the mouse only if the application uses it*/
|
|
hDev->m_pfnRead = INO_fn_wReadMouse;
|
|
wResult = INO_fn_wInitMouseCaps(hDev);
|
|
break;
|
|
}
|
|
if (!wResult)
|
|
{
|
|
INO_fn_vUpdateLastError(E_uwINO_DeviceInitFailed);
|
|
return (-1);
|
|
}
|
|
|
|
DInputErr = M_DIAcquire(i);
|
|
switch (DInputErr)
|
|
{
|
|
case DI_OK:
|
|
case S_FALSE:
|
|
hDev->m_p_stState->m_ucStatus |= INO_C_ucAcquired;
|
|
break;
|
|
|
|
case DIERR_INPUTLOST:
|
|
hDev->m_p_stState->m_ucStatus &= ~INO_C_ucAcquired;
|
|
break;
|
|
|
|
case DIERR_INVALIDPARAM:
|
|
hDev->m_p_stState->m_ucStatus &= ~INO_C_ucAcquired;
|
|
INO_fn_vUpdateLastError(E_uwINO_DirectInputError);
|
|
return (-1);
|
|
|
|
default:
|
|
break;
|
|
}
|
|
return (i);
|
|
}
|
|
}
|
|
return (-1);
|
|
}
|
|
|
|
|
|
/***********************************/
|
|
/* Release one device */
|
|
/***********************************/
|
|
short INO_fn_wDestroyDevice(INO_tdhDevice hDev)
|
|
{
|
|
long i;
|
|
|
|
for (i=0; i<INO_C_wNbMaxDevice; i++)
|
|
{
|
|
if (INO_g_a_stDIDevice[i].m_hDevice == hDev)
|
|
{
|
|
M_DIUnacquire(i);
|
|
/* M_DIRelease(i);*/
|
|
memset(&INO_g_a_stDIDevice[i],0,sizeof(INO_tdstDIDevice));
|
|
return (1);
|
|
}
|
|
}
|
|
return (0);
|
|
}
|
|
|
|
|
|
/***********************************/
|
|
/* Release Direct Input */
|
|
/***********************************/
|
|
void INO_fn_vReleaseAllDevices()
|
|
{
|
|
long i;
|
|
|
|
if (!INO_g_p_stDInputInterface) return;
|
|
|
|
for (i=0; i<INO_C_wNbMaxDevice; i++)
|
|
if (INO_g_a_stDIDevice[i].m_hDevice)
|
|
{
|
|
M_DIRelease(i);
|
|
INO_fn_wDestroyDevice(INO_g_a_stDIDevice[i].m_hDevice);
|
|
}
|
|
|
|
M_DInput()->Release(INO_g_p_stDInputInterface);
|
|
INO_g_p_stDInputInterface = NULL;
|
|
}
|
|
|
|
|
|
/****************************************/
|
|
/* Free All */
|
|
/****************************************/
|
|
short INO_fn_wGetNbDevices(unsigned short uwType)
|
|
{
|
|
short i, lNb = 0;
|
|
|
|
if (!INO_g_p_stDInputInterface) return (0);
|
|
|
|
for (i=0; i<INO_C_wNbMaxDevice; i++)
|
|
if ((1 << GET_DIDEVICE_TYPE(INO_g_a_stDIDevice[i].m_stDevInstance.dwDevType)) == uwType) lNb++;
|
|
/*if (INO_g_a_stDIDevice[i].m_hDevice)*/
|
|
/* if (GET_DIDEVICE_TYPE(INO_g_a_stDIDevice[i].m_stDevInstance.dwDevType) == uwType) lNb++;*/
|
|
return (lNb);
|
|
}
|
|
|
|
|
|
/******************************************/
|
|
/* init the device capabilities */
|
|
/* and return the DInput sub-type */
|
|
/******************************************/
|
|
short INO_fn_wFillDeviceCaps(INO_tdhDevice hDev)
|
|
{
|
|
HRESULT DInputErr;
|
|
short wDev;
|
|
INO_tdstDevCaps *p_stCaps = (INO_tdstDevCaps*)(hDev->m_p_stCaps);
|
|
|
|
for (wDev=0; wDev<INO_C_wNbMaxDevice; wDev++)
|
|
if (INO_g_a_stDIDevice[wDev].m_hDevice == hDev) break;
|
|
if (wDev == INO_C_wNbMaxDevice) return (0);
|
|
|
|
M_DIAcquire(wDev);
|
|
|
|
if (m_ulDIInstalledVersion == DIRECTINPUT_VERSION_3)
|
|
{
|
|
memset(&g_stDIDevCaps3,0,sizeof(DIDEVCAPS_DX3));
|
|
g_stDIDevCaps3.dwSize = sizeof(DIDEVCAPS_DX3);
|
|
DInputErr = M_DIGetCaps(wDev,(DIDEVCAPS*)&g_stDIDevCaps3);
|
|
}
|
|
else
|
|
{
|
|
memset(&g_stDIDevCaps,0,sizeof(DIDEVCAPS));
|
|
g_stDIDevCaps.dwSize = sizeof(DIDEVCAPS);
|
|
DInputErr = M_DIGetCaps(wDev,&g_stDIDevCaps);
|
|
}
|
|
if (DInputErr == DI_OK)
|
|
{
|
|
if (m_ulDIInstalledVersion == DIRECTINPUT_VERSION_3)
|
|
{
|
|
if (g_stDIDevCaps3.dwFlags & DIDC_ATTACHED)
|
|
hDev->m_p_stState->m_ucStatus |= INO_C_ucConnected;
|
|
|
|
p_stCaps->m_ucNbButtons = (unsigned char)g_stDIDevCaps3.dwButtons;
|
|
switch (INO_M_uwType(hDev))
|
|
{
|
|
case INO_C_uwJoystick:
|
|
((INO_tdstJoystickCaps*)p_stCaps)->m_ucNbPOVs = (unsigned char)g_stDIDevCaps3.dwPOVs;
|
|
case INO_C_uwMouse:
|
|
((INO_tdstJoystickCaps*)p_stCaps)->m_ucNbAxes = (unsigned char)g_stDIDevCaps3.dwAxes;
|
|
break;
|
|
}
|
|
return (GET_DIDEVICE_SUBTYPE(g_stDIDevCaps3.dwDevType));
|
|
}
|
|
else
|
|
{
|
|
if (g_stDIDevCaps.dwFlags & DIDC_ATTACHED)
|
|
hDev->m_p_stState->m_ucStatus |= INO_C_ucConnected;
|
|
p_stCaps->m_ucNbButtons = (unsigned char)g_stDIDevCaps.dwButtons;
|
|
switch (INO_M_uwType(hDev))
|
|
{
|
|
case INO_C_uwJoystick:
|
|
((INO_tdstJoystickCaps*)p_stCaps)->m_ucNbAxes = (unsigned char)g_stDIDevCaps.dwAxes;
|
|
((INO_tdstJoystickCaps*)p_stCaps)->m_ucNbPOVs = (unsigned char)g_stDIDevCaps.dwPOVs;
|
|
break;
|
|
}
|
|
return (GET_DIDEVICE_SUBTYPE(g_stDIDevCaps.dwDevType));
|
|
}
|
|
}
|
|
else
|
|
{
|
|
hDev->m_p_stState->m_ucStatus &= ~INO_C_ucConnected;
|
|
hDev->m_p_stState->m_ucStatus &= ~INO_C_ucAcquired;
|
|
INO_fn_vUpdateLastError(E_uwINO_DeviceInitFailed);
|
|
return (0);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
short INO_fn_wIsConnected(INO_tdhDevice hDev)
|
|
{
|
|
HRESULT DInputErr;
|
|
short wDev;
|
|
|
|
/* JFP: what is this used for? Is it necessary?*/
|
|
for (wDev=0; wDev<INO_C_wNbMaxDevice; wDev++)
|
|
if (INO_g_a_stDIDevice[wDev].m_hDevice == hDev)
|
|
break;
|
|
if (wDev == INO_C_wNbMaxDevice)
|
|
return (0);
|
|
|
|
/* Use DI 3 structure to go faster */
|
|
memset(&g_stDIDevCaps3,0,sizeof(DIDEVCAPS_DX3));
|
|
g_stDIDevCaps3.dwSize = sizeof(DIDEVCAPS_DX3);
|
|
DInputErr = M_DIGetCaps(wDev,(DIDEVCAPS*)&g_stDIDevCaps3);
|
|
|
|
if (DInputErr == DI_OK)
|
|
{
|
|
if (g_stDIDevCaps3.dwFlags & DIDC_ATTACHED)
|
|
{
|
|
hDev->m_p_stState->m_ucStatus |= INO_C_ucConnected;
|
|
return (1);
|
|
}
|
|
else
|
|
hDev->m_p_stState->m_ucStatus &= ~INO_C_ucConnected;
|
|
}
|
|
|
|
return (0);
|
|
}
|