windows-nt/Source/XPSP1/NT/multimedia/directx/dinput/dx7/diquick/diqdevg.c
2020-09-26 16:20:57 +08:00

272 lines
7.6 KiB
C

/*****************************************************************************
*
* diqdevg.c
*
* Acquire an IDirectInputDevice as a generic device.
*
* We build a private data format with all the axes first, then
* all the buttons.
*
* We display the axes parenthesized, followed by a space-separated
* list of buttons.
*
*****************************************************************************/
#include "diquick.h"
/*****************************************************************************
*
* DEVGINFO
*
* Structure used to track generic device state.
*
*****************************************************************************/
typedef struct DEVGINFO {
DWORD cbState; /* Size of state buffer */
LPVOID pvState; /* State buffer */
int cAxes; /* Number of axes (start at offset 0) */
int cButtons; /* Number of buttons (start after axes) */
} DEVGINFO, *PDEVGINFO;
/*****************************************************************************
*
* Devg_UpdateStatus
*
* Warning! ptszBuf is only 256 characters long!
*
*****************************************************************************/
STDMETHODIMP
Devg_UpdateStatus(PDEVDLGINFO pddi, LPTSTR ptszBuf)
{
HRESULT hres;
PDEVGINFO pdevg = pddi->pvAcq;
IDirectInputDevice *pdev = pddi->pdid;
hres = IDirectInputDevice_GetDeviceState(pdev, pdevg->cbState,
pdevg->pvState);
if (SUCCEEDED(hres)) {
LPVOID pvData = pdevg->pvState;
int iButton;
if (pdevg->cAxes) {
int iAxis;
for (iAxis = 0; iAxis < pdevg->cAxes; iAxis++) {
LPLONG pl = pvData;
pvData = pvAddPvCb(pvData, sizeof(LONG));
ptszBuf += wsprintf(ptszBuf, iAxis == 0 ? TEXT("\050%d") :
TEXT(", %d"), *pl);
}
ptszBuf += wsprintf(ptszBuf, TEXT("\051"));
}
for (iButton = 0; iButton < pdevg->cButtons; iButton++) {
LPBYTE pb = pvData;
pvData = pvAddPvCb(pvData, sizeof(BYTE));
if (*pb & 0x80) {
ptszBuf += wsprintf(ptszBuf, TEXT(" %d"), iButton);
}
}
}
*ptszBuf = TEXT('\0');
return hres;
}
/*****************************************************************************
*
* Devg_Destroy
*
*****************************************************************************/
STDMETHODIMP_(void)
Devg_Destroy(PDEVDLGINFO pddi)
{
PDEVGINFO pdevg = pddi->pvAcq;
if (pdevg) {
if (pdevg->pvState) {
LocalFree(pdevg->pvState);
}
LocalFree(pdevg);
}
}
/*****************************************************************************
*
* Devg_DataFormatEnumProc
*
* Callback function for each object. If it's a button or axis,
* we put it in the data format. But only if it generates data!
*
*****************************************************************************/
typedef struct DEVGENUM {
DWORD dwNumObjs;
DIDATAFORMAT df;
PDEVGINFO pdevg;
PDEVDLGINFO pddi;
} DEVGENUM, *PDEVGENUM;
BOOL CALLBACK
Devg_DataFormatEnumProc(LPCDIDEVICEOBJECTINSTANCE pinst, LPVOID pv)
{
PDEVGENUM pge = pv;
LPDIOBJECTDATAFORMAT podf;
DIDEVICEOBJECTINSTANCE doi;
DWORD cbObj;
if( pge->df.dwNumObjs == pge->dwNumObjs -1 )
{
HLOCAL hloc;
pge->dwNumObjs *=2;
hloc = LocalReAlloc((HLOCAL)pge->df.rgodf, pge->dwNumObjs * pge->df.dwObjSize , LMEM_MOVEABLE+LMEM_ZEROINIT);
if(hloc)
{
pge->df.rgodf = hloc;
}else
{
goto done;
}
}
ConvertDoi(pge->pddi, &doi, pinst);
/*
* Ignore no-data elements.
*/
if (doi.dwType & DIDFT_NODATA) {
} else {
if (doi.dwType & (DIDFT_AXIS | DIDFT_POV)) {
pge->pdevg->cAxes++;
cbObj = cbX(LONG);
} else if (doi.dwType & DIDFT_BUTTON) {
pge->pdevg->cButtons++;
cbObj = cbX(BYTE);
} else {
/*
* Theoretical impossibility!
*/
goto done;
}
podf = &pge->df.rgodf[pge->df.dwNumObjs];
podf->dwOfs = pge->df.dwDataSize;
#ifdef USE_HID_USAGE_DATA_FORMATS
if (doi.wUsagePage) {
podf->dwType = (doi.dwType &
(DIDFT_AXIS | DIDFT_BUTTON | DIDFT_POV)) |
DIDFT_ANYINSTANCE;
podf->pguid = (PV)DIMAKEUSAGEDWORD(doi.wUsagePage, doi.wUsage);
podf->dwFlags |= DIDOI_GUIDISUSAGE;
} else {
podf->dwType = doi.dwType;
}
#else
podf->dwType = doi.dwType;
#endif
pge->df.dwDataSize += cbObj;
pge->df.dwNumObjs++;
}
done:;
return DIENUM_CONTINUE;
}
/*****************************************************************************
*
* Devg_SetDataFormat
*
* Build a custom data format for the device.
*
*****************************************************************************/
STDMETHODIMP
Devg_SetDataFormat(PDEVDLGINFO pddi)
{
HRESULT hres;
DEVGENUM ge;
ge.pddi = pddi;
ge.pdevg = LocalAlloc(LPTR, cbX(DEVGINFO));
if (ge.pdevg) {
DIDEVCAPS_DX3 caps;
pddi->pvAcq = ge.pdevg;
/*
* Get worst-case axis and button count.
*/
caps.dwSize = cbX(caps);
hres = IDirectInputDevice_GetCapabilities(pddi->pdid,
(PV)&caps);
if (SUCCEEDED(hres)) {
ge.df.dwSize = cbX(ge.df);
ge.df.dwObjSize = cbX(DIOBJECTDATAFORMAT);
ge.df.dwFlags = 0;
ge.df.dwNumObjs = 0;
ge.df.dwDataSize = 0;
ge.dwNumObjs = caps.dwAxes + caps.dwPOVs + caps.dwButtons;
ge.df.rgodf = LocalAlloc(LPTR,
(caps.dwAxes + caps.dwPOVs + caps.dwButtons) *
ge.df.dwObjSize);
if (ge.df.rgodf) {
if (SUCCEEDED(hres =
IDirectInputDevice_EnumObjects(pddi->pdid,
Devg_DataFormatEnumProc, &ge,
DIDFT_AXIS | DIDFT_POV | DIDFT_ALIAS | DIDFT_VENDORDEFINED )) &&
SUCCEEDED(hres =
IDirectInputDevice_EnumObjects(pddi->pdid,
Devg_DataFormatEnumProc, &ge, DIDFT_BUTTON| DIDFT_ALIAS | DIDFT_VENDORDEFINED))) {
ge.df.dwDataSize = (ge.df.dwDataSize + 3) & ~3;
ge.pdevg->cbState = ge.df.dwDataSize;
ge.pdevg->pvState = LocalAlloc(LPTR, ge.pdevg->cbState);
if (ge.pdevg->pvState) {
hres = IDirectInputDevice_SetDataFormat(
pddi->pdid, &ge.df);
} else {
hres = E_OUTOFMEMORY;
}
}
LocalFree(ge.df.rgodf);
} else {
hres = E_OUTOFMEMORY;
}
}
} else {
hres = E_OUTOFMEMORY;
}
return hres;
}
/*****************************************************************************
*
* c_acqvtblDev
*
*****************************************************************************/
#pragma BEGIN_CONST_DATA
ACQVTBL c_acqvtblDev = {
Devg_UpdateStatus,
Devg_SetDataFormat,
Devg_Destroy,
0,
};
#pragma END_CONST_DATA