446 lines
12 KiB
C
446 lines
12 KiB
C
/*****************************************************************************
|
|
*
|
|
* PidOp.c
|
|
*
|
|
* Copyright (c) 1999 Microsoft Corporation. All Rights Reserved.
|
|
*
|
|
* Abstract:
|
|
*
|
|
* PID device Operation .
|
|
*
|
|
*****************************************************************************/
|
|
#include "pidpr.h"
|
|
|
|
#define sqfl ( sqflOp )
|
|
|
|
#pragma BEGIN_CONST_DATA
|
|
|
|
static PIDUSAGE c_rgUsgGain[] =
|
|
{
|
|
MAKE_PIDUSAGE(DEVICE_GAIN, 0x0 )
|
|
};
|
|
|
|
static PIDREPORT DeviceGain =
|
|
{
|
|
HidP_Output,
|
|
HID_USAGE_PAGE_PID,
|
|
HID_USAGE_PID_DEVICE_GAIN_REPORT,
|
|
cbX(DWORD),
|
|
cA(c_rgUsgGain),
|
|
c_rgUsgGain
|
|
};
|
|
|
|
|
|
|
|
|
|
PIDUSAGE c_rgUsgOperationReport[] =
|
|
{
|
|
MAKE_PIDUSAGE(LOOP_COUNT, 0x0),
|
|
};
|
|
|
|
static PIDREPORT OperationReport =
|
|
{
|
|
HidP_Output,
|
|
HID_USAGE_PAGE_PID,
|
|
HID_USAGE_PID_EFFECT_OPERATION_REPORT,
|
|
cbX(DWORD),
|
|
cA(c_rgUsgOperationReport),
|
|
c_rgUsgOperationReport
|
|
};
|
|
|
|
|
|
static PIDREPORT DeviceControlReport =
|
|
{
|
|
HidP_Output,
|
|
HID_USAGE_PAGE_PID,
|
|
HID_USAGE_PID_DEVICE_CONTROL,
|
|
0x0,
|
|
0x0,
|
|
NULL
|
|
};
|
|
|
|
|
|
#pragma END_CONST_DATA
|
|
|
|
STDMETHODIMP
|
|
PID_EffectOperation
|
|
(
|
|
IDirectInputEffectDriver *ped,
|
|
DWORD dwId,
|
|
DWORD dwEffect,
|
|
DWORD dwMode,
|
|
DWORD dwCount,
|
|
BOOL bBlocking,
|
|
UINT blockNr,
|
|
UINT totalBlocks
|
|
)
|
|
{
|
|
CPidDrv *this = (CPidDrv *)ped;
|
|
HRESULT hres = S_OK;
|
|
|
|
EnterProcI( PID_EffectOperation, (_"xxxxx", ped, dwId, dwEffect, dwMode, dwCount ));
|
|
|
|
hres = PID_ValidateEffectIndex(ped, dwEffect);
|
|
// Allocate Memory for the report
|
|
if( SUCCEEDED(hres) )
|
|
{
|
|
USHORT cbReport;
|
|
PUCHAR pReport;
|
|
|
|
USHORT LinkCollection;
|
|
AssertF(OperationReport.HidP_Type == HidP_Output);
|
|
|
|
cbReport = this->cbReport[OperationReport.HidP_Type];
|
|
pReport = this->pReport[OperationReport.HidP_Type];
|
|
|
|
PID_GetLinkCollectionIndex(ped, OperationReport.UsagePage, OperationReport.Collection, 0x0, &LinkCollection );
|
|
// Set the Effect Structure
|
|
if( SUCCEEDED(hres) )
|
|
{
|
|
ZeroBuf(pReport, cbReport);
|
|
|
|
// Set Effect Operation
|
|
if( SUCCEEDED(hres) )
|
|
{
|
|
USAGE Usage;
|
|
USAGE UsagePage;
|
|
NTSTATUS ntStat;
|
|
UINT nUsages = 0x1;
|
|
USAGE LinkCollection0;
|
|
PEFFECTSTATE pEffectState = PeffectStateFromBlockIndex(this,dwEffect);
|
|
|
|
UsagePage = OperationReport.UsagePage;
|
|
|
|
PID_GetLinkCollectionIndex(ped, OperationReport.UsagePage, HID_USAGE_PID_EFFECT_OPERATION, 0x0, &LinkCollection0);
|
|
|
|
if( dwMode & DIES_SOLO )
|
|
{
|
|
Usage = HID_USAGE_PID_OP_EFFECT_START_SOLO;
|
|
pEffectState->lEfState |= PID_EFFECT_STARTED_SOLO;
|
|
} else if( dwMode & PID_DIES_START )
|
|
{
|
|
Usage = HID_USAGE_PID_OP_EFFECT_START;
|
|
pEffectState->lEfState |= PID_EFFECT_STARTED;
|
|
} else if(dwMode & PID_DIES_STOP )
|
|
{
|
|
Usage = HID_USAGE_PID_OP_EFFECT_STOP;
|
|
pEffectState->lEfState &= ~(PID_EFFECT_STARTED | PID_EFFECT_STARTED_SOLO);
|
|
} else
|
|
{
|
|
SquirtSqflPtszV(sqfl | sqflError,
|
|
TEXT("%s: FAIL Could not understand dwMode=0x%x"),
|
|
s_tszProc, dwMode );
|
|
|
|
hres = E_NOTIMPL;
|
|
}
|
|
|
|
ntStat = HidP_SetUsages
|
|
(
|
|
OperationReport.HidP_Type,
|
|
UsagePage,
|
|
LinkCollection0,
|
|
&Usage,
|
|
&nUsages,
|
|
this->ppd,
|
|
pReport,
|
|
cbReport);
|
|
|
|
if( FAILED(hres) )
|
|
{
|
|
SquirtSqflPtszV(sqfl | sqflBenign,
|
|
TEXT("%s: FAIL HidP_SetUsages:0x%x for(%x,%x,%x:%s)"),
|
|
s_tszProc, ntStat,
|
|
LinkCollection0, UsagePage, Usage,
|
|
PIDUSAGETXT(UsagePage,Usage) );
|
|
} else
|
|
{
|
|
SquirtSqflPtszV(sqfl | sqflVerbose,
|
|
TEXT("%s: HidP_SetUsages:0x%x for(%x,%x,%x:%s)"),
|
|
s_tszProc, ntStat,
|
|
LinkCollection0, UsagePage, Usage,
|
|
PIDUSAGETXT(UsagePage,Usage) );
|
|
}
|
|
}
|
|
|
|
// Set the Loop Count
|
|
if( SUCCEEDED(hres) )
|
|
{
|
|
PID_PackValue
|
|
(
|
|
ped,
|
|
&OperationReport,
|
|
LinkCollection,
|
|
&dwCount,
|
|
cbX(dwCount),
|
|
pReport,
|
|
cbReport
|
|
);
|
|
|
|
// Set the Block Index
|
|
PID_PackValue
|
|
(
|
|
ped,
|
|
&g_BlockIndex,
|
|
LinkCollection,
|
|
&dwEffect,
|
|
cbX(dwEffect),
|
|
pReport,
|
|
cbReport
|
|
);
|
|
}
|
|
|
|
if( SUCCEEDED(hres) )
|
|
{
|
|
hres = PID_SendReport(ped, pReport, cbReport, OperationReport.HidP_Type, bBlocking, blockNr, totalBlocks);
|
|
}
|
|
}
|
|
}
|
|
ExitOleProc();
|
|
return hres;
|
|
}
|
|
|
|
|
|
/*****************************************************************************
|
|
*
|
|
* PID_SetGain
|
|
*
|
|
* Set the overall device gain.
|
|
*
|
|
* dwId
|
|
*
|
|
* The joystick ID number being used.
|
|
*
|
|
* dwGain
|
|
*
|
|
* The new gain value.
|
|
*
|
|
* If the value is out of range for the device, the device
|
|
* should use the nearest supported value and return
|
|
* DI_TRUNCATED.
|
|
*
|
|
* Returns:
|
|
*
|
|
*
|
|
* S_OK if the operation completed successfully.
|
|
*
|
|
* DI_TRUNCATED if the value was out of range and was
|
|
* changed to the nearest supported value.
|
|
*
|
|
* Any DIERR_* error code may be returned.
|
|
*
|
|
* Private driver-specific error codes in the range
|
|
* DIERR_DRIVERFIRST through DIERR_DRIVERLAST
|
|
* may be returned.
|
|
*
|
|
*****************************************************************************/
|
|
STDMETHODIMP
|
|
PID_SetGain
|
|
(
|
|
IDirectInputEffectDriver *ped,
|
|
DWORD dwId,
|
|
DWORD dwGain
|
|
)
|
|
{
|
|
CPidDrv *this = (CPidDrv *)ped;
|
|
HRESULT hres = S_OK;
|
|
|
|
EnterProc( PID_SetGain, (_"xxx", ped, dwId, dwGain));
|
|
DllEnterCrit();
|
|
|
|
// Allocate Memory for the report
|
|
if( SUCCEEDED(hres) )
|
|
{
|
|
USHORT cbReport;
|
|
PUCHAR pReport;
|
|
|
|
USHORT LinkCollection;
|
|
|
|
AssertF(DeviceGain.HidP_Type == HidP_Output);
|
|
cbReport = this->cbReport[DeviceGain.HidP_Type];
|
|
pReport = this->pReport[DeviceGain.HidP_Type];
|
|
|
|
PID_GetLinkCollectionIndex(ped, DeviceGain.UsagePage, DeviceGain.Collection, 0x0, &LinkCollection );
|
|
// Set the Effect Structure
|
|
if( SUCCEEDED(hres) )
|
|
{
|
|
ZeroBuf(pReport, cbReport);
|
|
|
|
// Set the Loop Count
|
|
if( SUCCEEDED(hres) )
|
|
{
|
|
hres = PID_PackValue
|
|
(
|
|
ped,
|
|
&DeviceGain,
|
|
LinkCollection,
|
|
&dwGain,
|
|
cbX(dwGain),
|
|
pReport,
|
|
cbReport
|
|
);
|
|
}
|
|
|
|
if( SUCCEEDED(hres) )
|
|
{
|
|
hres = PID_SendReport(ped, pReport, cbReport, DeviceGain.HidP_Type, FALSE, 0, 1);
|
|
}
|
|
}
|
|
}
|
|
DllLeaveCrit();
|
|
|
|
ExitOleProc();
|
|
return hres;
|
|
}
|
|
|
|
|
|
/*****************************************************************************
|
|
*
|
|
* PID_SendForceFeedbackCommand
|
|
*
|
|
* Send a command to the device.
|
|
*
|
|
* dwId
|
|
*
|
|
* The external joystick number being addressed.
|
|
*
|
|
* dwCommand
|
|
*
|
|
* A DISFFC_* value specifying the command to send.
|
|
*
|
|
* Returns:
|
|
*
|
|
* S_OK on success.
|
|
*
|
|
* Any DIERR_* error code may be returned.
|
|
*
|
|
* Private driver-specific error codes in the range
|
|
* DIERR_DRIVERFIRST through DIERR_DRIVERLAST
|
|
* may be returned.
|
|
*
|
|
*****************************************************************************/
|
|
STDMETHODIMP
|
|
PID_SendForceFeedbackCommand
|
|
(
|
|
IDirectInputEffectDriver *ped,
|
|
DWORD dwId,
|
|
DWORD dwCommand
|
|
)
|
|
{
|
|
CPidDrv *this = (CPidDrv *)ped;
|
|
HRESULT hres = S_OK;
|
|
USAGE Usages[6];
|
|
PUSAGE pUsages = &Usages[0];
|
|
UINT nUsages;
|
|
|
|
EnterProcI( PID_SendForceFeedbackCommand, (_"xxx", ped, dwId, dwCommand));
|
|
|
|
DllEnterCrit();
|
|
|
|
if( dwCommand & DISFFC_RESET )
|
|
{
|
|
DWORD indx;
|
|
*pUsages++ = HID_USAGE_PID_DC_DEVICE_RESET;
|
|
for(indx = 1 ;
|
|
(indx <= this->cMaxEffects) && (((PUNITSTATE)(g_pshmem + this->iUnitStateOffset))->cEfDownloaded != 0x0 );
|
|
indx++ )
|
|
{
|
|
PID_DestroyEffect(ped, dwId, indx);
|
|
}
|
|
this->dwState = DIGFFS_STOPPED;
|
|
}
|
|
if( dwCommand & DISFFC_STOPALL )
|
|
{
|
|
*pUsages++ = HID_USAGE_PID_DC_STOP_ALL_EFFECTS;
|
|
this->dwState = DIGFFS_STOPPED;
|
|
}
|
|
if( dwCommand & DISFFC_PAUSE )
|
|
{
|
|
*pUsages++ = HID_USAGE_PID_DC_DEVICE_PAUSE;
|
|
}
|
|
if( dwCommand & DISFFC_CONTINUE )
|
|
{
|
|
*pUsages++ = HID_USAGE_PID_DC_DEVICE_CONTINUE;
|
|
}
|
|
if( dwCommand & DISFFC_SETACTUATORSON)
|
|
{
|
|
*pUsages++ = HID_USAGE_PID_DC_ENABLE_ACTUATORS;
|
|
}
|
|
if(dwCommand & DISFFC_SETACTUATORSOFF)
|
|
{
|
|
*pUsages++ = HID_USAGE_PID_DC_DISABLE_ACTUATORS;
|
|
}
|
|
|
|
nUsages = (UINT)(pUsages - &Usages[0]);
|
|
if(nUsages == 0x0 )
|
|
{
|
|
hres = E_NOTIMPL;
|
|
SquirtSqflPtszV(sqfl | sqflError,
|
|
TEXT("%s: FAIL Do not understand dwCommand(0x%x) "),
|
|
s_tszProc, dwCommand);
|
|
}
|
|
|
|
if( SUCCEEDED(hres) )
|
|
{
|
|
USHORT cbReport;
|
|
PUCHAR pReport;
|
|
USHORT LinkCollection;
|
|
|
|
AssertF(DeviceControlReport.HidP_Type == HidP_Output);
|
|
|
|
cbReport = this->cbReport[DeviceControlReport.HidP_Type];
|
|
pReport = this->pReport[DeviceControlReport.HidP_Type];
|
|
|
|
PID_GetLinkCollectionIndex(ped, DeviceControlReport.UsagePage, DeviceControlReport.Collection, 0x0, &LinkCollection );
|
|
// Set the Effect Structure
|
|
if( SUCCEEDED(hres) )
|
|
{
|
|
USHORT UsagePage;
|
|
NTSTATUS ntStat;
|
|
ZeroBuf(pReport, cbReport);
|
|
UsagePage = OperationReport.UsagePage;
|
|
|
|
ntStat = HidP_SetUsages
|
|
(
|
|
OperationReport.HidP_Type,
|
|
UsagePage,
|
|
LinkCollection,
|
|
&Usages[0],
|
|
&nUsages,
|
|
this->ppd,
|
|
pReport,
|
|
cbReport);
|
|
|
|
if( FAILED(ntStat) )
|
|
{
|
|
SquirtSqflPtszV(sqfl | sqflError,
|
|
TEXT("%s: FAIL HidP_SetUsages:0x%x for(%x,%x,%x:%s)"),
|
|
s_tszProc, ntStat,
|
|
LinkCollection, UsagePage, Usages[0],
|
|
PIDUSAGETXT(UsagePage,Usages[0]) );
|
|
hres = ntStat;
|
|
} else
|
|
{
|
|
SquirtSqflPtszV(sqfl | sqflVerbose,
|
|
TEXT("%s: HidP_SetUsages:0x%x for(%x,%x,%x:%s)"),
|
|
s_tszProc, ntStat,
|
|
LinkCollection,UsagePage, Usages[0],
|
|
PIDUSAGETXT(UsagePage,Usages[0]) );
|
|
}
|
|
|
|
if( SUCCEEDED(hres) )
|
|
{
|
|
hres = PID_SendReport(ped, pReport, cbReport, OperationReport.HidP_Type, TRUE, 0, 1); //we block on this call
|
|
}
|
|
}
|
|
}
|
|
|
|
DllLeaveCrit();
|
|
|
|
ExitOleProc();
|
|
return hres;
|
|
}
|
|
|
|
|
|
|
|
|