|
|
/*****************************************************************************
* * DIHid.c * * Copyright (c) 1996 Microsoft Corporation. All Rights Reserved. * * Abstract: * * WINNT implementation of JOYHID. * * Contents: * * DIWdm_JoyHidMapping * JoyReg_JoyIdToDeviceInterface * *****************************************************************************/
#include "dinputpr.h"
#undef sqfl
#define sqfl sqflWDM
#include "dijoyhid.h"
/*****************************************************************************
* * @doc INTERNAL * * @func HRESULT EXTERNAL | DIWdm_JoyHidMapping | * * Does the work done by JoyHid on Win9x. This function * maps the Joystick ID to a HID device and talks to the * HID device to obtain its capabilities. * * @parm IN int | idJoy | * * The Id of the joystick to be located. * * @parm OUT PVXDINITPARAMS | pvip | OPTIONAL * Address of a VXDINITPARAMS structure that is filled out * by this function. This is an optional parameter * and can be NULL * * @parm OUT LPDIJOYCONFIG | pcfg | * Address of a DIJOYCONFIG structure that is filled out * by this function. This is an optional parameter. * * @parm IN OUT LPDIJOYTYPEINFO | pdijti | * Address of a DIJOYTYPEINFO structure that is filled out * by this function. This is an optional parameter. * If passed in, the hws.dwFlags is used to initialize the * same flags in the DIJOYCONFIG structure. * * @returns HRESULT * Returns a COM error code * *****************************************************************************/ /*
* ISSUE-2001/03/29-timgill function uses too much stack space * This function uses over 4K of stack space! * This causes the Win9x build to choke looking for _chkstk. * Hack by forcing caller to pass pcfg and pdijti */ HRESULT EXTERNAL DIWdm_JoyHidMapping ( IN int idJoy, OUT PVXDINITPARMS pvip, OPTIONAL OUT LPDIJOYCONFIG pcfg, OPTIONAL IN OUT LPDIJOYTYPEINFO pdijti ) { HRESULT hres; PHIDDEVICEINFO phdi; VXDINITPARMS vip; DWORD wCaps = 0; DIPROPINFO propi; DIPROPSTRING dips; DIPROPDWORD dipd; BOOL fBadCalData = FALSE;
EnterProc(DIWdm_JoyHidMapping, (_ "uxx", idJoy, pvip, pcfg));
// AssertF(InCrit());
if( pvip == NULL ) { ZeroX(vip); vip.dwSize = cbX(vip); pvip = &vip; }
AssertF(pdijti != NULL );
/*
* Copy the type info because JOY_HWS_ISYOKE, JOY_HWS_ISCARCTRL and * JOY_HWS_ISHEADTRACKER have no simple equivalents in HID so would * otherwise get lost. No harm done if it's zero. * Note, the dwFlags is built in pvip then copied elsewhere. */ pvip->dwFlags = pdijti->hws.dwFlags;
phdi = phdiFindJoyId(idJoy); if( phdi != NULL ) { IDirectInputDeviceCallback *pdcb;
hres = CHid_New(0, &phdi->guid, &IID_IDirectInputDeviceCallback, (PPV)&pdcb); if( SUCCEEDED(hres) ) { DIDEVCAPS dc;
hres = pdcb->lpVtbl->GetCapabilities(pdcb, &dc ); if( SUCCEEDED(hres) ) { DIDEVICEINSTANCEW didi;
didi.dwSize = cbX(didi);
hres = pdcb->lpVtbl->GetDeviceInfo(pdcb, &didi); if( SUCCEEDED(hres) ) { LPDIDATAFORMAT pdf;
hres = pdcb->lpVtbl->GetDataFormat(pdcb, &pdf); if( SUCCEEDED(hres) ) { DIPROPCAL dipc; DWORD axis, pov = 0;
ZeroBuf(pvip->Usages, 6 * cbX(pvip->Usages[0]));
hres = pdcb->lpVtbl->MapUsage(pdcb, CheckHatswitch->dwUsage, &propi.iobj); if(SUCCEEDED(hres) ) { pvip->dwPOV1usage = CheckHatswitch->dwUsage; pvip->dwFlags |= CheckHatswitch->dwFlags; wCaps |= CheckHatswitch->dwCaps;
propi.pguid = DIPROP_GRANULARITY; propi.dwDevType = pdf->rgodf[propi.iobj].dwType; hres = pdcb->lpVtbl->GetProperty(pdcb, &propi, &dipd.diph); if( SUCCEEDED( hres ) ) { if( dipd.dwData >= 9000 ) // 4 directional POV
{ wCaps |= JOYCAPS_POV4DIR; if( pcfg != NULL ) { pcfg->hwc.hwv.dwPOVValues[JOY_POVVAL_FORWARD] = JOY_POVFORWARD; pcfg->hwc.hwv.dwPOVValues[JOY_POVVAL_BACKWARD] = JOY_POVBACKWARD; pcfg->hwc.hwv.dwPOVValues[JOY_POVVAL_LEFT] = JOY_POVLEFT; pcfg->hwc.hwv.dwPOVValues[JOY_POVVAL_RIGHT] = JOY_POVRIGHT; } } else // Continuous POV
{ wCaps |= JOYCAPS_POVCTS; } } }
for( axis = 0; axis < cA(AxesUsages)-1; axis++ ) { USAGES *pUse = &AxesUsages[axis]; DWORD dwCurAxisPos = pUse->dwAxisPos;
if( pvip->Usages[dwCurAxisPos] != 0) { continue; } else { int i; BOOL bHasUsed = FALSE; for( i = 0; i < (int)dwCurAxisPos; i++ ) { if( pvip->Usages[i] == pUse->dwUsage ) { bHasUsed = TRUE; break; } } if( bHasUsed ) { continue; } } hres = pdcb->lpVtbl->MapUsage(pdcb, pUse->dwUsage, &propi.iobj); if(SUCCEEDED(hres) ) { pvip->Usages[dwCurAxisPos] = pUse->dwUsage; pvip->dwFlags |= pUse->dwFlags; wCaps |= pUse->dwCaps;
propi.pguid = DIPROP_CALIBRATION; propi.dwDevType = pdf->rgodf[propi.iobj].dwType; hres = pdcb->lpVtbl->GetProperty(pdcb, &propi, &dipc.diph); if( SUCCEEDED(hres) && pcfg != NULL ) {
#ifdef WINNT
(&pcfg->hwc.hwv.jrvHardware.jpMin.dwX)[dwCurAxisPos] = dipc.lMin; (&pcfg->hwc.hwv.jrvHardware.jpMax.dwX)[dwCurAxisPos] = dipc.lMax; (&pcfg->hwc.hwv.jrvHardware.jpCenter.dwX)[dwCurAxisPos] = CCal_Midpoint(dipc.lMin, dipc.lMax); #else
DIPROPRANGE diprp; DIPROPRANGE diprl; propi.pguid = DIPROP_PHYSICALRANGE; propi.dwDevType = pdf->rgodf[propi.iobj].dwType; hres = pdcb->lpVtbl->GetProperty(pdcb, &propi, &diprp.diph); if( SUCCEEDED( hres ) ) { propi.pguid = DIPROP_LOGICALRANGE; propi.dwDevType = pdf->rgodf[propi.iobj].dwType; hres = pdcb->lpVtbl->GetProperty(pdcb, &propi, &diprl.diph); if( SUCCEEDED( hres ) ) { LONG lMin, lMax;
lMin = (&pcfg->hwc.hwv.jrvHardware.jpMin.dwX)[dwCurAxisPos] = CHid_CoordinateTransform( (PLMINMAX)&diprp.lMin, (PLMINMAX)&diprl.lMin, dipc.lMin ); lMax = (&pcfg->hwc.hwv.jrvHardware.jpMax.dwX)[dwCurAxisPos] = CHid_CoordinateTransform( (PLMINMAX)&diprp.lMin, (PLMINMAX)&diprl.lMin, dipc.lMax ); (&pcfg->hwc.hwv.jrvHardware.jpCenter.dwX)[dwCurAxisPos] = CCal_Midpoint(lMin, lMax);
if( lMin >= lMax ) { fBadCalData = TRUE; break; } }
} #endif
} } } //for (axis=0...
} //GetDataFormat
pvip->hres = S_OK; pvip->dwSize = cbX(*pvip); /* Which version of VJOYD are we? */ pvip->dwFlags |= JOY_HWS_AUTOLOAD; /* Describes the device */
if(didi.wUsage == HID_USAGE_GENERIC_GAMEPAD) { pvip->dwFlags |= JOY_HWS_ISGAMEPAD; }
pvip->dwId = idJoy; /* Internal joystick ID */ pvip->dwFirmwareRevision = dc.dwFirmwareRevision; pvip->dwHardwareRevision = dc.dwHardwareRevision; pvip->dwFFDriverVersion = dc.dwFFDriverVersion; pvip->dwFilenameLengths = lstrlen(phdi->pdidd->DevicePath); pvip->pFilenameBuffer = phdi->pdidd->DevicePath;
//pvip->Usages[6];
//pvip->dwPOV1usage = 0x0;
pvip->dwPOV2usage = 0x0; pvip->dwPOV3usage = 0x0;
/* Fill all fields of cfg */
if( pcfg != NULL ) { AssertF( pcfg->dwSize == sizeof(DIJOYCONFIG_DX5) || pcfg->dwSize == sizeof(DIJOYCONFIG_DX6) ); pcfg->guidInstance = phdi->guid; pcfg->hwc.hws.dwNumButtons = dc.dwButtons; pcfg->hwc.hws.dwFlags = pvip->dwFlags; //pcfg.hwc.hwv.jrvHardware
//pcfg.hwc.hwv.dwPOVValues
pcfg->hwc.hwv.dwCalFlags = 0x0; if( ( LOWORD(phdi->guidProduct.Data1) == MSFT_SYSTEM_VID ) &&( ( HIWORD(phdi->guidProduct.Data1) >= MSFT_SYSTEM_PID + JOY_HW_PREDEFMIN) &&( HIWORD(phdi->guidProduct.Data1) < MSFT_SYSTEM_PID + JOY_HW_PREDEFMAX ) ) ) { pcfg->hwc.dwType = HIWORD(phdi->guidProduct.Data1) - MSFT_SYSTEM_PID; pcfg->hwc.dwUsageSettings = JOY_US_PRESENT | JOY_US_VOLATILE; } else { /*
* This value really does not matter much but ideally * should be greater than or equal to JOY_HW_PREDEFMAX * Add idJoy for best compatiblity with the old CPLs. */ pcfg->hwc.dwType = idJoy + JOY_HW_PREDEFMAX; pcfg->hwc.dwUsageSettings = JOY_US_PRESENT | JOY_US_VOLATILE | JOY_US_ISOEM; } if(pcfg && pvip->Usages[ecRz]) { pcfg->hwc.dwUsageSettings |= JOY_US_HASRUDDER; } pcfg->hwc.dwReserved = 0x0; /*
* Default gain to nominal max so it does not get written * to the registry unless it has some other value. */ pcfg->dwGain = DI_FFNOMINALMAX; propi.pguid = DIPROP_FFGAIN; propi.dwDevType = DIPH_DEVICE; propi.iobj = 0xFFFFFFFF; hres = pdcb->lpVtbl->GetProperty(pdcb, &propi, &dipd.diph); if( SUCCEEDED(hres) ) { pcfg->dwGain = dipd.dwData; } else { // Failure to get gain is not crutial
hres = S_OK; } if( pcfg->hwc.dwType >= JOY_HW_PREDEFMAX ) { #ifndef UNICODE
char szType[20]; #endif
/*
* This should work, but it doesn't in Win98, bug! * * wsprintfW(pcfg->wszType, L"VID_%04X&PID_%04X", * LOWORD(didi.guidProduct.Data1), HIWORD(didi.guidProduct.Data1)); */ #ifdef UNICODE
wsprintf(pcfg->wszType, VID_PID_TEMPLATE, LOWORD(phdi->guidProduct.Data1), HIWORD(phdi->guidProduct.Data1)); #else
wsprintf(szType, VID_PID_TEMPLATE, LOWORD(phdi->guidProduct.Data1), HIWORD(phdi->guidProduct.Data1)); AToU(pcfg->wszType, cA(pcfg->wszType), szType); #endif
} else { /*
* Predefined types do not have type strings for the * uses the callers of this function need. */ ZeroX(pcfg->wszType); } #ifdef WINNT
// No callout on NT
ZeroX(pcfg->wszCallout); #else
lstrcpyW( pcfg->wszCallout, L"joyhid.vxd" ); #endif
} // end of filling pcfg's fields
pdijti->dwSize = cbX(*pdijti); pdijti->hws.dwNumButtons = dc.dwButtons; pdijti->hws.dwFlags = pvip->dwFlags; ZeroX(pdijti->clsidConfig);
propi.pguid = DIPROP_INSTANCENAME; propi.dwDevType = DIPH_DEVICE; propi.iobj = 0xFFFFFFFF; hres = pdcb->lpVtbl->GetProperty(pdcb, &propi, &dips.diph);
if( hres != S_OK && lstrlenW(pdijti->wszDisplayName) != 0x0 ) { // Failure to get friendly name
// We will try and use the OEM name from the registry
lstrcpyW(dips.wsz, pdijti->wszDisplayName); //pdcb->lpVtbl->SetProperty(pdcb, &propi, &dips.diph);
}else if( SUCCEEDED(hres) ) { // Use friendly name in the registry
lstrcpyW(pdijti->wszDisplayName, dips.wsz); hres = S_OK; } } // GetDeviceInfo FAILED
} // GetCapabilities FAILED
Invoke_Release(&pdcb); } } else // No HID device for JoyID
{ hres = E_FAIL; }
if( fBadCalData ) { hres = E_FAIL; }
ExitProcX(hres); return hres; }
/*****************************************************************************
* * @doc INTERNAL * * @func HRESULT | JoyReg_JoyIdToDeviceInterface | * * Given a joystick ID number, obtain the device interface * corresponding to it. * * @parm UINT | idJoy | * * Joystick ID number, zero-based. * * @parm PVXDINITPARMS | pvip | * * Receives init parameters from the driver. * * @parm LPTSTR | ptszBuf | * * A buffer of size <c MAX_PATH> in which the device interface * path is built. * * @returns * A pointer to the part of the <p ptszBuf> buffer that * contains the actual device interface path. * *****************************************************************************/
LPTSTR EXTERNAL JoyReg_JoyIdToDeviceInterface_NT ( IN UINT idJoy, OUT PVXDINITPARMS pvip, OUT LPTSTR ptszBuf ) { HRESULT hres; DIJOYCONFIG cfg; DIJOYTYPEINFO dijti;
DllEnterCrit();
ZeroX(cfg); ZeroX(dijti);
cfg.dwSize = cbX(cfg); dijti.dwSize = cbX(dijti);
hres = DIWdm_JoyHidMapping(idJoy, pvip, &cfg, &dijti );
if( SUCCEEDED(hres ) ) { AssertF( lstrlen(pvip->pFilenameBuffer) < MAX_PATH ); lstrcpy(ptszBuf, pvip->pFilenameBuffer); }
DllLeaveCrit();
return ptszBuf; }
|