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

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;
}