Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1201 lines
35 KiB

  1. //@doc
  2. /******************************************************
  3. **
  4. ** @module FFDEVICE.CPP | Implementation file for FFDevice class
  5. **
  6. ** Description:
  7. **
  8. ** History:
  9. ** Created 11/17/97 Matthew L. Coill (mlc)
  10. **
  11. ** 21-Mar-99 waltw Added dwDeviceID to SetFirmwareVersion,
  12. ** InitJoystickParams, StateChange, InitRTCSpring,
  13. ** InitRTCSpring200
  14. **
  15. ** (c) 1986-1997 Microsoft Corporation. All Rights Reserved.
  16. ******************************************************/
  17. #include "FFDevice.h"
  18. #include "Midi_obj.hpp"
  19. #include "DTrans.h"
  20. #include "DPack.h"
  21. #include "joyregst.hpp"
  22. #include "CritSec.h"
  23. #include <crt/io.h> // For file routines
  24. #include <FCNTL.h> // File _open flags
  25. #include <math.h> // for sin and cos
  26. extern CJoltMidi* g_pJoltMidi;
  27. //
  28. // --- VFX Force File defines
  29. //
  30. #define FCC_FORCE_EFFECT_RIFF mmioFOURCC('F','O','R','C')
  31. #define FCC_INFO_LIST mmioFOURCC('I','N','F','O')
  32. #define FCC_INFO_NAME_CHUNK mmioFOURCC('I','N','A','M')
  33. #define FCC_INFO_COMMENT_CHUNK mmioFOURCC('I','C','M','T')
  34. #define FCC_INFO_SOFTWARE_CHUNK mmioFOURCC('I','S','F','T')
  35. #define FCC_INFO_COPYRIGHT_CHUNK mmioFOURCC('I','C','O','P')
  36. #define FCC_TARGET_DEVICE_CHUNK mmioFOURCC('t','r','g','t')
  37. #define FCC_TRACK_LIST mmioFOURCC('t','r','a','k')
  38. #define FCC_EFFECT_LIST mmioFOURCC('e','f','c','t')
  39. #define FCC_ID_CHUNK mmioFOURCC('i','d',' ',' ')
  40. #define FCC_DATA_CHUNK mmioFOURCC('d','a','t','a')
  41. #define FCC_IMPLICIT_CHUNK mmioFOURCC('i','m','p','l')
  42. #define FCC_SPLINE_CHUNK mmioFOURCC('s','p','l','n')
  43. ForceFeedbackDevice g_ForceFeedbackDevice;
  44. #include <errno.h> // For open file errors
  45. HRESULT LoadBufferFromFile(const char* fileName, PBYTE& pBufferBytes, ULONG& numFileBytes)
  46. {
  47. if (pBufferBytes != NULL) {
  48. ASSUME_NOT_REACHED();
  49. numFileBytes = 0;
  50. return VFX_ERR_FILE_OUT_OF_MEMORY;
  51. }
  52. int fHandle = ::_open(fileName, _O_RDONLY | _O_BINARY);
  53. if (fHandle == -1) {
  54. numFileBytes = 0;
  55. switch (errno) {
  56. case EACCES : return VFX_ERR_FILE_ACCESS_DENIED;
  57. case EMFILE : return VFX_ERR_FILE_TOO_MANY_OPEN_FILES;
  58. case ENOENT : return VFX_ERR_FILE_NOT_FOUND;
  59. }
  60. return VFX_ERR_FILE_CANNOT_OPEN; // Who knows what went wrong
  61. }
  62. HRESULT hr = S_OK;
  63. numFileBytes = ::_lseek(fHandle, 0, SEEK_END);
  64. if (numFileBytes == -1) { // Seek failed
  65. hr = VFX_ERR_FILE_CANNOT_SEEK;
  66. } else if (numFileBytes == 0) { // Empty file
  67. hr = VFX_ERR_FILE_BAD_FORMAT;
  68. } else {
  69. pBufferBytes = new BYTE[numFileBytes];
  70. if (pBufferBytes == NULL) { // Could not allocate memory
  71. hr = VFX_ERR_FILE_OUT_OF_MEMORY;
  72. } else {
  73. if (::_lseek(fHandle, 0, SEEK_SET) == -1) { // Failed seek to begining
  74. hr = VFX_ERR_FILE_CANNOT_SEEK;
  75. } else if (::_read(fHandle, pBufferBytes, numFileBytes) == -1) { // Failed to read
  76. hr = VFX_ERR_FILE_CANNOT_READ;
  77. }
  78. if (hr != S_OK) { // Things didn't go well
  79. delete[] pBufferBytes;
  80. pBufferBytes = NULL;
  81. }
  82. }
  83. }
  84. ::_close(fHandle);
  85. return hr;
  86. }
  87. /******************************************************
  88. **
  89. ** ForceFeedbackDevice::ForceFeedbackDevice()
  90. **
  91. ** @mfunc Constructor.
  92. **
  93. ******************************************************/
  94. ForceFeedbackDevice::ForceFeedbackDevice() :
  95. m_FirmwareAckNackValues(0),
  96. m_FirmwareVersionMajor(0),
  97. m_FirmwareVersionMinor(0),
  98. m_DriverVersionMajor(0),
  99. m_DriverVersionMinor(0),
  100. m_SpringOffset(0),
  101. m_Mapping(0),
  102. m_DIStateFlags(0),
  103. m_RawForceX(0),
  104. m_RawForceY(0)
  105. {
  106. m_OSVersion.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
  107. ::GetVersionEx(&m_OSVersion);
  108. for (int index = 0; index < 14; index++) {
  109. m_PercentMappings[index] = 100; // Default is 100 percent till I'm told otherwise
  110. }
  111. for (index = 0; index < MAX_EFFECT_IDS; index++) {
  112. m_EffectList[index] = NULL;
  113. }
  114. m_SystemEffect = NULL;
  115. ::memset(&m_Version200State, 0, sizeof(m_Version200State));
  116. ::memset(&m_LastStatusPacket, 0, sizeof(m_LastStatusPacket));
  117. }
  118. /******************************************************
  119. **
  120. ** ForceFeedbackDevice::~ForceFeedbackDevice()
  121. **
  122. ** @mfunc Destructor.
  123. **
  124. ******************************************************/
  125. ForceFeedbackDevice::~ForceFeedbackDevice()
  126. {
  127. BOOL lingerer = FALSE;
  128. // Destroy the RTCSpring and SystemEffect if still hanging aroung
  129. if (m_EffectList[0] != NULL) {
  130. delete m_EffectList[0];
  131. m_EffectList[0] = NULL;
  132. }
  133. if (m_SystemEffect != NULL) {
  134. delete m_SystemEffect;
  135. m_SystemEffect = NULL;
  136. }
  137. // Destroy any lingering effects (of which there should be none)
  138. for (int index = 0; index < MAX_EFFECT_IDS; index++) {
  139. if (m_EffectList[index] != NULL) {
  140. lingerer = TRUE;
  141. delete m_EffectList[index];
  142. m_EffectList[index] = NULL;
  143. }
  144. }
  145. ASSUME(lingerer == FALSE); // Assuming programmer cleaned up thier own mess
  146. }
  147. /******************************************************
  148. **
  149. ** ForceFeedbackDevice::DetectHardware()
  150. **
  151. ** @mfunc DetectHardware.
  152. **
  153. ******************************************************/
  154. BOOL ForceFeedbackDevice::DetectHardware()
  155. {
  156. if (NULL == g_pJoltMidi)
  157. return (FALSE);
  158. else
  159. return g_pJoltMidi->QueryForJolt();
  160. }
  161. /******************************************************
  162. **
  163. ** ForceFeedbackDevice::SetFirmwareVersion(DWORD dwDeviceID, DWORD major, DWORD minor)
  164. **
  165. ** @mfunc SetFirmwareVersion.
  166. **
  167. ******************************************************/
  168. void ForceFeedbackDevice::SetFirmwareVersion(DWORD dwDeviceID, DWORD major, DWORD minor)
  169. {
  170. m_FirmwareVersionMajor = major;
  171. m_FirmwareVersionMinor = minor;
  172. if (g_pDataPackager != NULL) {
  173. delete g_pDataPackager;
  174. g_pDataPackager = NULL;
  175. }
  176. if (m_FirmwareVersionMajor == 1) {
  177. ASSUME_NOT_REACHED(); // Currently this code only supports wheel - this is a Jolt version
  178. // g_pDataPackager = new DataPackager100();
  179. } else { // Till version number is locked down
  180. g_pDataPackager = new DataPackager200();
  181. }
  182. ASSUME_NOT_NULL(g_pDataPackager);
  183. m_FirmwareAckNackValues = GetAckNackMethodFromRegistry(dwDeviceID);
  184. m_SpringOffset = GetSpringOffsetFromRegistry(dwDeviceID);
  185. }
  186. /******************************************************
  187. **
  188. ** ForceFeedbackDevice::SetDriverVersion(DWORD major, DWORD minor)
  189. **
  190. ** @mfunc SetDriverVersion.
  191. **
  192. ******************************************************/
  193. void ForceFeedbackDevice::SetDriverVersion(DWORD major, DWORD minor)
  194. {
  195. if ((major == 0xFFFFFFFF) && (minor == 0xFFFFFFFF)) { // Check for version 1.0 driver version error
  196. m_DriverVersionMajor = 1;
  197. m_DriverVersionMinor = 0;
  198. } else {
  199. m_DriverVersionMajor = major;
  200. m_DriverVersionMinor = minor;
  201. }
  202. }
  203. /******************************************************
  204. **
  205. ** ForceFeedbackDevice::GetYMappingPercent(UINT index)
  206. **
  207. ** @mfunc GetYMappingPercent.
  208. **
  209. ******************************************************/
  210. short ForceFeedbackDevice::GetYMappingPercent(UINT index) const
  211. {
  212. if (m_Mapping & Y_AXIS) {
  213. if (index < 14) {
  214. return m_PercentMappings[index];
  215. }
  216. }
  217. return 0;
  218. }
  219. /******************************************************
  220. **
  221. ** ForceFeedbackDevice::GetEffect(DWORD effectID) const
  222. **
  223. ** @mfunc GetEffect.
  224. **
  225. ******************************************************/
  226. InternalEffect* ForceFeedbackDevice::GetEffect(DWORD effectID) const
  227. {
  228. if (effectID == SYSTEM_EFFECT_ID) { // SystemEffect not stored in array
  229. return m_SystemEffect;
  230. }
  231. if (effectID == SYSTEM_RTCSPRING_ALIAS_ID) { // Remapping of RTC spring
  232. return m_EffectList[0];
  233. }
  234. if (effectID == RAW_FORCE_ALIAS) {
  235. return NULL;
  236. }
  237. // Parameter check
  238. if (effectID >= MAX_EFFECT_IDS) {
  239. ASSUME_NOT_REACHED();
  240. return NULL;
  241. }
  242. return m_EffectList[effectID];
  243. }
  244. /******************************************************
  245. **
  246. ** ForceFeedbackDevice::RemoveEffect(DWORD effectID) const
  247. **
  248. ** @mfunc GetEffect.
  249. **
  250. ******************************************************/
  251. InternalEffect* ForceFeedbackDevice::RemoveEffect(DWORD effectID)
  252. {
  253. // There really is no raw force effect
  254. if (effectID == RAW_FORCE_ALIAS) {
  255. return NULL;
  256. }
  257. // Cannot remove system effects
  258. if ((effectID == SYSTEM_EFFECT_ID) || (effectID == 0) || (effectID == SYSTEM_RTCSPRING_ALIAS_ID)) {
  259. ASSUME_NOT_REACHED();
  260. return NULL;
  261. }
  262. // Parameter check
  263. if (effectID >= MAX_EFFECT_IDS) {
  264. ASSUME_NOT_REACHED();
  265. return NULL;
  266. }
  267. InternalEffect* pEffect = m_EffectList[effectID];
  268. m_EffectList[effectID] = NULL;
  269. return pEffect;
  270. }
  271. /******************************************************
  272. **
  273. ** ForceFeedbackDevice::InitRTCSpring()
  274. **
  275. ** @mfunc InitRTCSpring.
  276. **
  277. ******************************************************/
  278. HRESULT ForceFeedbackDevice::InitRTCSpring(DWORD dwDeviceID)
  279. {
  280. if (g_pDataPackager == NULL) {
  281. ASSUME_NOT_REACHED();
  282. return SFERR_DRIVER_ERROR; // No global data packager
  283. }
  284. if (g_pDataTransmitter == NULL) {
  285. ASSUME_NOT_REACHED();
  286. return SFERR_DRIVER_ERROR; // No global data transmitter
  287. }
  288. if (GetFirmwareVersionMajor() == 1) {
  289. return InitRTCSpring1XX(dwDeviceID);
  290. }
  291. return InitRTCSpring200(dwDeviceID);
  292. }
  293. /******************************************************
  294. **
  295. ** ForceFeedbackDevice::InitRTCSpring1XX()
  296. **
  297. ** @mfunc InitRTCSpring.
  298. **
  299. ******************************************************/
  300. HRESULT ForceFeedbackDevice::InitRTCSpring1XX(DWORD dwDeviceID)
  301. {
  302. // Sanity Checks
  303. if (GetEffect(SYSTEM_RTCSPRING_ID) != NULL) {
  304. ASSUME_NOT_REACHED();
  305. return SUCCESS; // Already initialized
  306. }
  307. // DIEFFECT structure to fill
  308. DICONDITION cond[2];
  309. DIEFFECT rtc;
  310. rtc.dwSize = sizeof(DIEFFECT);
  311. rtc.cbTypeSpecificParams = sizeof(DICONDITION) * 2;
  312. rtc.lpvTypeSpecificParams = cond;
  313. // The default RTCSpring (the one on the stick)
  314. RTCSpring1XX rtcSpring1XX; // Def Parms filled by constructor
  315. // Default RTCSpring from the registry
  316. RTCSPRING_PARAM parms;
  317. GetSystemParams(dwDeviceID, (SYSTEM_PARAMS*)(&parms));
  318. cond[0].lPositiveCoefficient = parms.m_XKConstant;
  319. cond[1].lPositiveCoefficient = parms.m_YKConstant;
  320. cond[0].lOffset = parms.m_XAxisCenter;
  321. cond[1].lOffset = parms.m_YAxisCenter;
  322. cond[0].dwPositiveSaturation = parms.m_XSaturation;
  323. cond[1].dwPositiveSaturation = parms.m_YSaturation;
  324. cond[0].lDeadBand = parms.m_XDeadBand;
  325. cond[1].lDeadBand = parms.m_YDeadBand;
  326. // Allocate and create the RTCSpring
  327. InternalEffect* pNewRTCSpring = InternalEffect::CreateRTCSpring();
  328. if (pNewRTCSpring == NULL) {
  329. return SFERR_DRIVER_ERROR;
  330. }
  331. if (pNewRTCSpring->Create(rtc) != SUCCESS) {
  332. delete pNewRTCSpring; // Could not create system RTC Spring
  333. return SFERR_DRIVER_ERROR;
  334. }
  335. // Replace the stick default with the registry default
  336. SetEffect(SYSTEM_RTCSPRING_ALIAS_ID, &rtcSpring1XX); // Temporary pointer needed (but we only store temporarily)
  337. g_pDataPackager->ModifyEffect(rtcSpring1XX, *pNewRTCSpring, 0); // Package relative changes
  338. SetEffect(SYSTEM_RTCSPRING_ALIAS_ID, pNewRTCSpring); // Replace the old with the new
  339. pNewRTCSpring = NULL; // Forgotten, but not gone
  340. ACKNACK ackNack;
  341. return g_pDataTransmitter->Transmit(ackNack); // Send it off
  342. }
  343. /******************************************************
  344. **
  345. ** ForceFeedbackDevice::InitRTCSpring200()
  346. **
  347. ** @mfunc InitRTCSpring.
  348. **
  349. ******************************************************/
  350. HRESULT ForceFeedbackDevice::InitRTCSpring200(DWORD dwDeviceID)
  351. {
  352. // Sanity Checks
  353. if (GetEffect(ID_RTCSPRING_200) != NULL) {
  354. ASSUME_NOT_REACHED();
  355. return SUCCESS; // Already initialized
  356. }
  357. // The temporary spring and the allocated one
  358. InternalEffect* pNewRTCSpring = NULL;
  359. // DIEFFECT structure to fill
  360. DICONDITION cond[2];
  361. DIEFFECT rtc;
  362. rtc.dwSize = sizeof(DIEFFECT);
  363. rtc.cbTypeSpecificParams = sizeof(DICONDITION) * 2;
  364. rtc.lpvTypeSpecificParams = cond;
  365. // The default RTCSpring (the one on the stick)
  366. RTCSpring200 rtcSpring200; // Default values filled in by constructor
  367. // Default RTCSpring from the registry
  368. GetRTCSpringData(dwDeviceID, cond);
  369. // Allocate and create the RTCSpring
  370. pNewRTCSpring = InternalEffect::CreateRTCSpring();
  371. if (pNewRTCSpring == NULL) {
  372. return SFERR_DRIVER_ERROR;
  373. }
  374. HRESULT createResult = pNewRTCSpring->Create(rtc);
  375. if (FAILED(createResult)) {
  376. delete pNewRTCSpring; // Could not create system RTC Spring
  377. return SFERR_DRIVER_ERROR;
  378. }
  379. // Replace the stick default with the registry default
  380. SetEffect(SYSTEM_RTCSPRING_ALIAS_ID, &rtcSpring200); // Temporary pointer needed (but we only store temporarily)
  381. g_pDataPackager->ModifyEffect(rtcSpring200, *pNewRTCSpring, 0); // Package relative changes
  382. SetEffect(SYSTEM_RTCSPRING_ALIAS_ID, pNewRTCSpring); // Replace the old with the new
  383. pNewRTCSpring = NULL; // Forgotten, but not gone
  384. ACKNACK ackNack;
  385. HRESULT transmitResult = g_pDataTransmitter->Transmit(ackNack); // Send it off
  386. if (transmitResult != S_OK) {
  387. return transmitResult;
  388. }
  389. return createResult;
  390. }
  391. /******************************************************
  392. **
  393. ** ForceFeedbackDevice::InitJoystickParams()
  394. **
  395. ** @mfunc InitRTCSpring.
  396. **
  397. ******************************************************/
  398. HRESULT ForceFeedbackDevice::InitJoystickParams(DWORD dwDeviceID)
  399. {
  400. // Sanity Checks
  401. if (GetEffect(SYSTEM_EFFECT_ID) != NULL) {
  402. ASSUME_NOT_REACHED();
  403. return SUCCESS; // Already initialized
  404. }
  405. if (g_pDataPackager == NULL) {
  406. ASSUME_NOT_REACHED();
  407. return SFERR_DRIVER_ERROR; // No global data packager
  408. }
  409. if (g_pDataTransmitter == NULL) {
  410. ASSUME_NOT_REACHED();
  411. return SFERR_DRIVER_ERROR; // No global data transmitter
  412. }
  413. // Force Mapping
  414. m_Mapping = ::GetMapping(dwDeviceID);
  415. ::GetMappingPercents(dwDeviceID, m_PercentMappings, 14);
  416. if (GetFirmwareVersionMajor() == 1) {
  417. // The default System Effect (the one on the stick)
  418. SystemEffect1XX systemEffect;
  419. // Default System Effect from the registry
  420. SystemStickData1XX sysData;
  421. sysData.SetFromRegistry(dwDeviceID);
  422. // Put the registry system values into a DIEFFECT
  423. DIEFFECT systemDIEffect;
  424. systemDIEffect.dwSize = sizeof(DIEFFECT);
  425. systemDIEffect.cbTypeSpecificParams = sizeof(SystemStickData1XX);
  426. systemDIEffect.lpvTypeSpecificParams = &sysData;
  427. // Get a system effect (and fill it with our local DIEffect information
  428. SystemEffect1XX* pSystemEffect = (SystemEffect1XX*)(InternalEffect::CreateSystemEffect());
  429. if (pSystemEffect == NULL) {
  430. return SFERR_DRIVER_ERROR;
  431. }
  432. if (pSystemEffect->Create(systemDIEffect) != SUCCESS) {
  433. delete pSystemEffect; // Couldnot create SystemEffect
  434. return SFERR_DRIVER_ERROR;
  435. }
  436. // Replace the stick default with the registry default
  437. SetEffect(SYSTEM_EFFECT_ID, &systemEffect); // Temporary pointer (but we only store temporarily)
  438. g_pDataPackager->ModifyEffect(systemEffect, *pSystemEffect, 0); // Package relative changes
  439. SetEffect(SYSTEM_EFFECT_ID, pSystemEffect); // Replace the old with the new
  440. pSystemEffect = NULL; // Forgotten, but not gone
  441. ACKNACK ackNack;
  442. return g_pDataTransmitter->Transmit(ackNack); // Send it off
  443. }
  444. return SUCCESS;
  445. }
  446. /******************************************************
  447. **
  448. ** ForceFeedbackDevice::StateChange(DWORD newStateFlags)
  449. **
  450. ** @mfunc StateChange.
  451. **
  452. ******************************************************/
  453. void ForceFeedbackDevice::StateChange(DWORD dwDeviceID, DWORD newStateFlag)
  454. {
  455. if (newStateFlag == DISFFC_RESET) { // Stick is reset need to remove local copies of user commands
  456. // Remove all effect from our list
  457. for (int index = 2; index < MAX_EFFECT_IDS; index++) {
  458. if (m_EffectList[index] != NULL) {
  459. delete m_EffectList[index];
  460. m_EffectList[index] = NULL;
  461. }
  462. }
  463. // Remove individual axis raw effects
  464. m_RawForceX = 0;
  465. m_RawForceY = 0;
  466. // Look at the Y mapping, perhaps it changed
  467. m_Mapping = ::GetMapping(dwDeviceID);
  468. ::GetMappingPercents(dwDeviceID, m_PercentMappings, 14);
  469. } else if (newStateFlag == DISFFC_STOPALL) {
  470. m_RawForceX = 0;
  471. m_RawForceY = 0;
  472. }
  473. m_DIStateFlags = newStateFlag;
  474. }
  475. /******************************************************
  476. **
  477. ** ForceFeedbackDevice::CreateConditionEffect(DWORD subType, const DIEFFECT& diEffect, HRESULT& hr)
  478. **
  479. ** @mfunc CreateConditionEffect.
  480. **
  481. ******************************************************/
  482. InternalEffect* ForceFeedbackDevice::CreateConditionEffect(DWORD minorType, const DIEFFECT& diEffect, HRESULT& hr)
  483. {
  484. InternalEffect* pReturnEffect = NULL;
  485. switch (minorType) {
  486. case BE_SPRING:
  487. case BE_SPRING_2D: {
  488. pReturnEffect = InternalEffect::CreateSpring();
  489. break;
  490. }
  491. case BE_DAMPER:
  492. case BE_DAMPER_2D: {
  493. pReturnEffect = InternalEffect::CreateDamper();
  494. break;
  495. }
  496. case BE_INERTIA:
  497. case BE_INERTIA_2D: {
  498. pReturnEffect = InternalEffect::CreateInertia();
  499. break;
  500. }
  501. case BE_FRICTION:
  502. case BE_FRICTION_2D: {
  503. pReturnEffect = InternalEffect::CreateFriction();
  504. break;
  505. }
  506. case BE_WALL: {
  507. pReturnEffect = InternalEffect::CreateWall();
  508. break;
  509. }
  510. }
  511. if (pReturnEffect != NULL) {
  512. hr = pReturnEffect->Create(diEffect);
  513. if (FAILED(hr)) {
  514. delete pReturnEffect;
  515. }
  516. }
  517. return pReturnEffect;
  518. }
  519. /******************************************************
  520. **
  521. ** ForceFeedbackDevice::CreateRTCSpringEffect(DWORD subType, const DIEFFECT& diEffect)
  522. **
  523. ** @mfunc CreateRTCSpringEffect.
  524. **
  525. ******************************************************/
  526. InternalEffect* ForceFeedbackDevice::CreateRTCSpringEffect(DWORD minorType, const DIEFFECT& diEffect)
  527. {
  528. InternalEffect* pEffect = InternalEffect::CreateRTCSpring();
  529. if (pEffect != NULL) {
  530. if (pEffect->Create(diEffect) == SUCCESS) {
  531. return pEffect;
  532. }
  533. delete pEffect;
  534. }
  535. return NULL;
  536. }
  537. /******************************************************
  538. **
  539. ** ForceFeedbackDevice::CreateCustomForceEffect(DWORD subType, const DIEFFECT& diEffect, HRESULT& hr)
  540. **
  541. ** @mfunc CreateCustomForceEffect.
  542. **
  543. ******************************************************/
  544. InternalEffect* ForceFeedbackDevice::CreateCustomForceEffect(DWORD minorType, const DIEFFECT& diEffect, HRESULT& hr)
  545. {
  546. InternalEffect* pEffect = InternalEffect::CreateCustomForce();
  547. if (pEffect != NULL) {
  548. hr = pEffect->Create(diEffect);
  549. if (SUCCEEDED(hr)) {
  550. return pEffect;
  551. }
  552. delete pEffect;
  553. }
  554. return NULL;
  555. }
  556. /******************************************************
  557. **
  558. ** ForceFeedbackDevice::CreatePeriodicEffect(DWORD subType, const DIEFFECT& diEffect, HRESULT& hr)
  559. **
  560. ** @mfunc CreatePeriodicEffect.
  561. **
  562. ******************************************************/
  563. InternalEffect* ForceFeedbackDevice::CreatePeriodicEffect(DWORD minorType, const DIEFFECT& diEffect, HRESULT& hr)
  564. {
  565. InternalEffect* pReturnEffect = NULL;
  566. switch (minorType) {
  567. case SE_SINE: {
  568. pReturnEffect = InternalEffect::CreateSine();
  569. break;
  570. }
  571. case SE_SQUAREHIGH: {
  572. pReturnEffect = InternalEffect::CreateSquare();
  573. break;
  574. }
  575. case SE_TRIANGLEUP: {
  576. pReturnEffect = InternalEffect::CreateTriangle();
  577. break;
  578. }
  579. case SE_SAWTOOTHUP: {
  580. pReturnEffect = InternalEffect::CreateSawtoothUp();
  581. break;
  582. }
  583. case SE_SAWTOOTHDOWN: {
  584. pReturnEffect = InternalEffect::CreateSawtoothDown();
  585. break;
  586. }
  587. case SE_CONSTANT_FORCE: {
  588. return CreateConstantForceEffect(minorType, diEffect, hr);
  589. }
  590. case SE_RAMPUP: {
  591. return CreateRampForceEffect(minorType, diEffect, hr);
  592. }
  593. }
  594. if (pReturnEffect != NULL) {
  595. hr = pReturnEffect->Create(diEffect);
  596. if (FAILED(hr) == FALSE) {
  597. return pReturnEffect;
  598. }
  599. delete pReturnEffect;
  600. }
  601. return NULL;
  602. }
  603. /******************************************************
  604. **
  605. ** ForceFeedbackDevice::CreateConstantForceEffect(DWORD subType, const DIEFFECT& diEffect, HRESULT& hr)
  606. **
  607. ** @mfunc CreateConstantForceEffect.
  608. **
  609. ******************************************************/
  610. InternalEffect* ForceFeedbackDevice::CreateConstantForceEffect(DWORD minorType, const DIEFFECT& diEffect, HRESULT& hr)
  611. {
  612. InternalEffect* pEffect = InternalEffect::CreateConstantForce();
  613. if (pEffect != NULL) {
  614. hr = pEffect->Create(diEffect);
  615. if (FAILED(hr) == FALSE) {
  616. return pEffect;
  617. }
  618. delete pEffect;
  619. }
  620. return NULL;
  621. }
  622. /******************************************************
  623. **
  624. ** ForceFeedbackDevice::CreateRampForceEffect(DWORD subType, const DIEFFECT& diEffect, HRESULT& hr)
  625. **
  626. ** @mfunc CreateRampForceEffect.
  627. **
  628. ******************************************************/
  629. InternalEffect* ForceFeedbackDevice::CreateRampForceEffect(DWORD minorType, const DIEFFECT& diEffect, HRESULT& hr)
  630. {
  631. InternalEffect* pEffect = InternalEffect::CreateRamp();
  632. if (pEffect != NULL) {
  633. hr = pEffect->Create(diEffect);
  634. if (SUCCEEDED(hr)) {
  635. return pEffect;
  636. }
  637. delete pEffect;
  638. }
  639. return NULL;
  640. }
  641. /******************************************************
  642. **
  643. ** ForceFeedbackDevice::SendRawForce(const DIEFFECT& diEffect)
  644. **
  645. ** @mfunc SendRawForce.
  646. **
  647. ******************************************************/
  648. HRESULT ForceFeedbackDevice::SendRawForce(const DIEFFECT& diEffect, BOOL paramCheck)
  649. {
  650. if (diEffect.lpvTypeSpecificParams == NULL) {
  651. return SFERR_INVALID_PARAM;
  652. }
  653. if (diEffect.cbTypeSpecificParams != sizeof(DICONSTANTFORCE)) {
  654. return SFERR_INVALID_PARAM;
  655. }
  656. // We don't support more than 2 axes, and 0 is probably an error
  657. if ((diEffect.cAxes > 2) || (diEffect.cAxes == 0)) {
  658. return SFERR_NO_SUPPORT;
  659. }
  660. // Set up the axis mask
  661. DWORD axisMask = 0;
  662. for (unsigned int axisIndex = 0; axisIndex < diEffect.cAxes; axisIndex++) {
  663. DWORD axisNumber = DIDFT_GETINSTANCE(diEffect.rgdwAxes[axisIndex]);
  664. axisMask |= 1 << axisNumber;
  665. }
  666. BOOL axesReversed = (DIDFT_GETINSTANCE(diEffect.rgdwAxes[0]) == 1);
  667. double angle = 0.0;
  668. // Check coordinate sytems and change to rectangular
  669. if (diEffect.dwFlags & DIEFF_SPHERICAL) { // We don't support sperical (3 axis force)
  670. return SFERR_NO_SUPPORT; // .. since got by axis check, programmer goofed up
  671. }
  672. if (diEffect.dwFlags & DIEFF_POLAR) {
  673. if (diEffect.cAxes != 2) { // Polar coordinate must have two axes of data (because DX says so)
  674. return SFERR_INVALID_PARAM;
  675. }
  676. DWORD effectAngle = diEffect.rglDirection[0]; // in [0] even if reversed
  677. if (axesReversed) { // Indicates (-1, 0) as origin instead of (0, -1)
  678. effectAngle += 27000;
  679. }
  680. effectAngle %= 36000;
  681. angle = double(effectAngle)/18000 * 3.14159; // Convert to radians
  682. m_RawForceX = 0;
  683. m_RawForceY = 0;
  684. } else if (diEffect.dwFlags & DIEFF_CARTESIAN) { // Convert to polar (so we can convert to cartesian)
  685. if (diEffect.cAxes == 1) { // Fairly easy conversion
  686. if (X_AXIS & axisMask) {
  687. angle = 3.14159/2; // PI/2
  688. } else {
  689. angle = 0.0;
  690. }
  691. } else { // Multiple axis cartiesian
  692. m_RawForceX = 0;
  693. m_RawForceY = 0;
  694. int xDirection = DIDFT_GETINSTANCE(diEffect.rglDirection[0]);
  695. int yDirection = DIDFT_GETINSTANCE(diEffect.rglDirection[1]);
  696. if (axesReversed == TRUE) {
  697. yDirection = xDirection;
  698. xDirection = DIDFT_GETINSTANCE(diEffect.rglDirection[1]);
  699. }
  700. angle = atan2(double(yDirection), double(xDirection));
  701. }
  702. } else { // What, is there some other format?
  703. ASSUME_NOT_REACHED();
  704. return SFERR_INVALID_PARAM; // Untill someone says otherwise there was an error
  705. }
  706. // Sin^2(a) + Cos^2(a) = 1
  707. double xProj = ::sin(angle); // DI has 0 degs at (1, 0) not (0, 1)
  708. double yProj = ::cos(angle);
  709. xProj *= xProj;
  710. yProj *= yProj;
  711. DWORD percentX = DWORD(xProj * 100.0 + 0.05);
  712. DWORD percentY = DWORD(yProj * 100.0 + 0.05);
  713. BOOL truncated = FALSE;
  714. if (percentX != 0) {
  715. m_RawForceX = LONG(percentX * (((DICONSTANTFORCE*)(diEffect.lpvTypeSpecificParams))->lMagnitude/100));
  716. if (m_RawForceX > 10000) {
  717. m_RawForceX = 10000;
  718. truncated = TRUE;
  719. } else if (m_RawForceX < -10000) {
  720. m_RawForceX = -10000;
  721. truncated = TRUE;
  722. }
  723. }
  724. if (percentY != 0) {
  725. m_RawForceY = LONG(percentY * (((DICONSTANTFORCE*)(diEffect.lpvTypeSpecificParams))->lMagnitude/100));
  726. if (m_RawForceY > 10000) {
  727. m_RawForceY = 10000;
  728. truncated = TRUE;
  729. } else if (m_RawForceY < -10000) {
  730. m_RawForceY = -10000;
  731. truncated = TRUE;
  732. }
  733. }
  734. long int mag = m_RawForceX + m_RawForceY * GetYMappingPercent(ET_RAWFORCE_200)/100;
  735. if (mag > 10000) { // Check for overrun but don't return indication of truncation
  736. mag = 10000;
  737. } else if (mag < -10000) {
  738. mag = -10000;
  739. }
  740. if (angle > 3.14159) { // PI
  741. mag *= -1;
  742. }
  743. HRESULT hr = g_pDataPackager->ForceOut(mag, X_AXIS);
  744. if ((hr != SUCCESS) || (paramCheck == TRUE)) {
  745. return hr;
  746. }
  747. ACKNACK ackNack;
  748. g_pDataTransmitter->Transmit(ackNack);
  749. if (truncated == TRUE) {
  750. return DI_TRUNCATED;
  751. }
  752. return SUCCESS;
  753. }
  754. /******************************************************
  755. **
  756. ** ForceFeedbackDevice::CreateVFXEffect(const DIEFFECT& diEffect, HRESULT& hr)
  757. **
  758. ** @mfunc CreateVFXEffect.
  759. **
  760. ******************************************************/
  761. InternalEffect* ForceFeedbackDevice::CreateVFXEffect(const DIEFFECT& diEffect, HRESULT& hr)
  762. {
  763. /* ULONG m_Bytes; // Size of this structure
  764. ULONG m_PointerType; // VFX_FILENAME or VFX_BUFFER
  765. ULONG m_BufferSize; // number of bytes in buffer (if VFX_BUFFER)
  766. PVOID m_pFileNameOrBuffer; // file name to open
  767. */
  768. if (diEffect.lpvTypeSpecificParams == NULL) {
  769. return NULL;
  770. }
  771. if (diEffect.cbTypeSpecificParams != sizeof(VFX_PARAM)) {
  772. return NULL;
  773. }
  774. VFX_PARAM* pVFXParms = (VFX_PARAM*)diEffect.lpvTypeSpecificParams;
  775. BYTE* pEffectBuffer = NULL;
  776. ULONG numBufferBytes = 0;
  777. if (pVFXParms->m_PointerType == VFX_FILENAME) { // Create memory buffer from file
  778. hr = LoadBufferFromFile((const char*)(pVFXParms->m_pFileNameOrBuffer), pEffectBuffer, numBufferBytes);
  779. } else {
  780. pEffectBuffer = (BYTE*)(pVFXParms->m_pFileNameOrBuffer);
  781. numBufferBytes = pVFXParms->m_BufferSize;
  782. }
  783. if ((pEffectBuffer == NULL) || (numBufferBytes == 0)) {
  784. return NULL;
  785. }
  786. return CreateVFXEffectFromBuffer(diEffect, pEffectBuffer, numBufferBytes, hr);
  787. }
  788. /******************************************************
  789. **
  790. ** ForceFeedbackDevice::CreateVFXEffectFromBuffer(const DIEFFECT& diEffect, BYTE* pEffectBuffer, ULONG numBufferBytes, HRESULT& hr)
  791. **
  792. ** @mfunc CreateVFXEffect.
  793. **
  794. ******************************************************/
  795. InternalEffect* ForceFeedbackDevice::CreateVFXEffectFromBuffer(const DIEFFECT& diEffect, BYTE* pEffectBuffer, ULONG numBufferBytes, HRESULT& hr)
  796. {
  797. if ((pEffectBuffer == NULL) || (numBufferBytes == 0)) {
  798. ASSUME_NOT_REACHED();
  799. return NULL;
  800. }
  801. MMIOINFO mmioInfo;
  802. ::memset(&mmioInfo, 0, sizeof(MMIOINFO));
  803. mmioInfo.fccIOProc = FOURCC_MEM;
  804. mmioInfo.cchBuffer = numBufferBytes;
  805. mmioInfo.pchBuffer = (char*)pEffectBuffer;
  806. HMMIO hmmio = ::mmioOpen(NULL, &mmioInfo, MMIO_READ);
  807. if (hmmio == NULL) {
  808. return NULL;
  809. }
  810. BYTE* pEffectParms = NULL;
  811. DWORD paramSize;
  812. EFFECT effect; // SW EFFECT structure
  813. ENVELOPE envelope; // SW ENVELOPE structure
  814. try { // Try parsing the RIFF file
  815. MMRESULT mmResult;
  816. // Descend into FORC list
  817. MMCKINFO forceEffectRiffInfo;
  818. forceEffectRiffInfo.fccType = FCC_FORCE_EFFECT_RIFF;
  819. if ((mmResult = ::mmioDescend(hmmio, &forceEffectRiffInfo, NULL, MMIO_FINDRIFF)) != MMSYSERR_NOERROR) {
  820. throw mmResult;
  821. }
  822. // Descend into TRAK list
  823. MMCKINFO trakListInfo;
  824. trakListInfo.fccType = FCC_TRACK_LIST;
  825. if ((mmResult = ::mmioDescend(hmmio, &trakListInfo, &forceEffectRiffInfo, MMIO_FINDLIST)) != MMSYSERR_NOERROR) {
  826. throw mmResult;
  827. }
  828. // Descend into first EFCT list
  829. MMCKINFO effectListInfo;
  830. effectListInfo.fccType = FCC_EFFECT_LIST;
  831. if ((mmResult = ::mmioDescend(hmmio, &effectListInfo, &trakListInfo, MMIO_FINDLIST)) != MMSYSERR_NOERROR) {
  832. throw mmResult;
  833. }
  834. // Descend into the ID chunk (maybe someone has a clue what is in here)
  835. MMCKINFO idInfo;
  836. idInfo.ckid = FCC_ID_CHUNK;
  837. if ((mmResult = ::mmioDescend(hmmio, &idInfo, &effectListInfo, MMIO_FINDCHUNK)) != MMSYSERR_NOERROR) {
  838. throw mmResult;
  839. }
  840. // Find the number of IDs in here (should indicate the number of effect)
  841. DWORD numEffects = idInfo.cksize/sizeof(DWORD);
  842. if (numEffects != 1) {
  843. throw SFERR_NO_SUPPORT;
  844. }
  845. // Read the ID chunk
  846. DWORD id;
  847. DWORD bytesRead = ::mmioRead(hmmio, (char*)&id, sizeof(DWORD));
  848. if (bytesRead != sizeof(DWORD)) {
  849. throw (bytesRead == 0) ? VFX_ERR_FILE_END_OF_FILE : VFX_ERR_FILE_CANNOT_READ;
  850. }
  851. // Back out of the ID chunk
  852. if ((mmResult = ::mmioAscend(hmmio, &idInfo, 0)) != MMSYSERR_NOERROR) {
  853. throw HRESULT_FROM_WIN32(mmResult);
  854. }
  855. // Descend into the DATA chunk
  856. MMCKINFO dataInfo;
  857. dataInfo.ckid = FCC_DATA_CHUNK;
  858. if ((mmResult = ::mmioDescend(hmmio, &dataInfo, &effectListInfo, MMIO_FINDCHUNK)) != MMSYSERR_NOERROR) {
  859. throw HRESULT_FROM_WIN32(mmResult);
  860. }
  861. // Read the effect structure from this chunk
  862. bytesRead = ::mmioRead(hmmio, (char*)&effect, sizeof(EFFECT));
  863. if (bytesRead != sizeof(EFFECT)) {
  864. throw (bytesRead == 0) ? VFX_ERR_FILE_END_OF_FILE : VFX_ERR_FILE_CANNOT_READ;
  865. }
  866. // Read the envelope structure from this chunk
  867. bytesRead = ::mmioRead(hmmio, (char*)&envelope, sizeof(ENVELOPE));
  868. if (bytesRead != sizeof(ENVELOPE)) {
  869. throw (bytesRead == 0) ? VFX_ERR_FILE_END_OF_FILE : VFX_ERR_FILE_CANNOT_READ;
  870. }
  871. // Read the parameters in:
  872. // -- Figure out the paramter size
  873. DWORD currentFilePos = ::mmioSeek(hmmio, 0, SEEK_CUR);
  874. if (currentFilePos == -1) {
  875. throw VFX_ERR_FILE_CANNOT_SEEK;
  876. }
  877. paramSize = dataInfo.dwDataOffset + dataInfo.cksize - currentFilePos;
  878. // -- Allocate space for the parameter
  879. pEffectParms = new BYTE[paramSize];
  880. if (pEffectParms == NULL) {
  881. throw VFX_ERR_FILE_OUT_OF_MEMORY;
  882. }
  883. // -- Do the actual reading
  884. bytesRead = ::mmioRead(hmmio, (char*)pEffectParms, paramSize);
  885. if (bytesRead != paramSize) {
  886. throw (bytesRead == 0) ? VFX_ERR_FILE_END_OF_FILE : VFX_ERR_FILE_CANNOT_READ;
  887. }
  888. // -- The pointer must be fixed if this is User Defined
  889. if (effect.m_Type == EF_USER_DEFINED) {
  890. BYTE* pForceData = pEffectParms + sizeof(UD_PARAM);
  891. UD_PARAM* pUDParam = (UD_PARAM*)pEffectParms;
  892. pUDParam->m_pForceData = (LONG*)pForceData;
  893. }
  894. } catch (HRESULT thrownError) {
  895. hr = thrownError;
  896. ::mmioClose(hmmio, 0);
  897. if (pEffectParms == NULL) { // Did we get an effect?
  898. return NULL;
  899. }
  900. }
  901. ::mmioClose(hmmio, 0); // Close the file
  902. if (pEffectParms == NULL) {
  903. ASSUME_NOT_REACHED(); //Exception should have been thrown
  904. return NULL;
  905. }
  906. InternalEffect* pReturnEffect = InternalEffect::CreateFromVFX(diEffect, effect, envelope, pEffectParms, paramSize, hr);
  907. // Cleanup
  908. delete pEffectParms;
  909. pEffectParms = NULL;
  910. return pReturnEffect;
  911. }
  912. /******************************************************
  913. **
  914. ** ForceFeedbackDevice::CreateEffect(DWORD& effectID, const DIEFFECT& diEffect)
  915. **
  916. ** @mfunc CreateEffect.
  917. **
  918. ******************************************************/
  919. InternalEffect* ForceFeedbackDevice::CreateEffect(DWORD effectType, const DIEFFECT& diEffect, DWORD& dnloadID, HRESULT& hr, BOOL paramCheck)
  920. {
  921. WORD majorType = WORD((effectType >> 16) & 0x0000FFFF);
  922. WORD minorType = WORD(effectType & 0x0000FFFF);
  923. if (majorType == EF_RAW_FORCE) {
  924. hr = SendRawForce(diEffect, paramCheck);
  925. if (SUCCEEDED(hr)) {
  926. dnloadID = RAW_FORCE_ALIAS;
  927. }
  928. return NULL;
  929. }
  930. InternalEffect* pEffect = NULL;
  931. BOOL isNewEffect = (dnloadID == 0);
  932. if (isNewEffect) {
  933. dnloadID = g_ForceFeedbackDevice.GetNextCreationID();
  934. if (dnloadID == 0) {
  935. hr = SFERR_OUT_OF_FF_MEMORY;
  936. return NULL;
  937. }
  938. }
  939. hr = SUCCESS;
  940. switch (majorType) {
  941. case EF_BEHAVIOR: {
  942. pEffect = CreateConditionEffect(minorType, diEffect, hr);
  943. break;
  944. }
  945. case EF_USER_DEFINED: {
  946. pEffect = CreateCustomForceEffect(minorType, diEffect, hr);
  947. break;
  948. }
  949. case EF_SYNTHESIZED: {
  950. pEffect = CreatePeriodicEffect(minorType, diEffect, hr);
  951. break;
  952. }
  953. case EF_RTC_SPRING: {
  954. dnloadID = SYSTEM_RTCSPRING_ALIAS_ID;
  955. pEffect = CreateRTCSpringEffect(minorType, diEffect);
  956. break;
  957. }
  958. case EF_VFX_EFFECT: { // Visual force VFX Effect!!! Danger Will Robinson!
  959. pEffect = CreateVFXEffect(diEffect, hr);
  960. break;
  961. }
  962. }
  963. if (((pEffect == NULL) || (paramCheck == TRUE)) && (isNewEffect == TRUE)) {
  964. dnloadID = 0;
  965. }
  966. if (pEffect != NULL) {
  967. if ((isNewEffect == TRUE) && (paramCheck == FALSE)) {
  968. g_ForceFeedbackDevice.SetEffect(BYTE(dnloadID), pEffect);
  969. }
  970. } else if (!FAILED(hr)) {
  971. hr = SFERR_DRIVER_ERROR;
  972. }
  973. return pEffect;
  974. }
  975. /******************************************************
  976. **
  977. ** ForceFeedbackDevice::GetNextCreationID() const
  978. **
  979. ** @mfunc GetNextCreationID.
  980. **
  981. ******************************************************/
  982. BYTE ForceFeedbackDevice::GetNextCreationID() const
  983. {
  984. // Must search straight through (start at 2, 0 is spring, 1 is friction
  985. for (BYTE emptyID = 2; emptyID < MAX_EFFECT_IDS; emptyID++) {
  986. if (m_EffectList[emptyID] == NULL) {
  987. break;
  988. }
  989. }
  990. if (emptyID == MAX_EFFECT_IDS) {
  991. return 0;
  992. }
  993. return emptyID;
  994. }
  995. /******************************************************
  996. **
  997. ** ForceFeedbackDevice::SetEffect(BYTE globalID, BYTE deviceID, InternalEffect* pEffect)
  998. **
  999. ** @mfunc SetEffect.
  1000. **
  1001. ******************************************************/
  1002. void ForceFeedbackDevice::SetEffect(BYTE globalID, InternalEffect* pEffect)
  1003. {
  1004. if (pEffect == NULL) {
  1005. ASSUME_NOT_REACHED();
  1006. return;
  1007. }
  1008. if (globalID == SYSTEM_EFFECT_ID) {
  1009. m_SystemEffect = pEffect;
  1010. } else if (globalID == SYSTEM_RTCSPRING_ALIAS_ID) {
  1011. m_EffectList[0] = pEffect;
  1012. if (GetFirmwareVersionMajor() == 1) {
  1013. pEffect->SetGlobalID(SYSTEM_RTCSPRING_ID);
  1014. pEffect->SetDeviceID(SYSTEM_RTCSPRING_ID);
  1015. } else {
  1016. pEffect->SetGlobalID(ID_RTCSPRING_200);
  1017. pEffect->SetDeviceID(ID_RTCSPRING_200);
  1018. }
  1019. return;
  1020. } else if (globalID < MAX_EFFECT_IDS) {
  1021. m_EffectList[globalID] = pEffect;
  1022. } else {
  1023. ASSUME_NOT_REACHED(); // Out of range
  1024. }
  1025. pEffect->SetGlobalID(globalID);
  1026. }
  1027. /******************************************************
  1028. **
  1029. ** ForceFeedbackDevice::SetDeviceIDFromStatusPacket(DWORD globalID)
  1030. **
  1031. ** @mfunc SetDeviceIDFromStatusPacket.
  1032. **
  1033. ******************************************************/
  1034. void ForceFeedbackDevice::SetDeviceIDFromStatusPacket(DWORD globalID)
  1035. {
  1036. if (globalID == SYSTEM_EFFECT_ID) {
  1037. return;
  1038. }
  1039. if (globalID == SYSTEM_RTCSPRING_ALIAS_ID) {
  1040. return;
  1041. }
  1042. if (globalID < MAX_EFFECT_IDS) {
  1043. InternalEffect* pEffect = m_EffectList[globalID];
  1044. if (pEffect == NULL) {
  1045. ASSUME_NOT_REACHED(); // There should be an effect here
  1046. return;
  1047. }
  1048. pEffect->SetDeviceID(BYTE(m_LastStatusPacket.dwEffect));
  1049. #ifdef _DEBUG // Check to see if they coincide
  1050. if (pEffect->GetGlobalID() != pEffect->GetDeviceID()) {
  1051. TCHAR buff[256];
  1052. ::wsprintf(buff, TEXT("SW_WHEEL.DLL: Global ID (%d) != Download ID (%d)\r\n"), pEffect->GetGlobalID(), pEffect->GetDeviceID());
  1053. _RPT0(_CRT_WARN, buff);
  1054. }
  1055. #endif _DEBUG
  1056. } else {
  1057. ASSUME_NOT_REACHED(); // Out of range
  1058. }
  1059. }
  1060. /******************************************************
  1061. **
  1062. ** ForceFeedbackDevice::QueryStatus()
  1063. **
  1064. ** @mfunc QueryStatus.
  1065. **
  1066. ******************************************************/
  1067. HRESULT ForceFeedbackDevice::QueryStatus()
  1068. {
  1069. CriticalLock cl; // This is a critical section
  1070. // Use Digital Overdrive to get the status packet
  1071. JOYCHANNELSTATUS statusPacket = {sizeof(JOYCHANNELSTATUS)};
  1072. HRESULT hRet = g_pDriverCommunicator->GetStatus(statusPacket);
  1073. if (hRet == SUCCESS) {
  1074. if (GetFirmwareVersionMajor() == 1) {
  1075. // This is irrelevant till we support jolt
  1076. } else {
  1077. if (sizeof(statusPacket.dwDeviceStatus) == sizeof(m_Version200State)) {
  1078. ::memcpy(&m_Version200State, &(statusPacket.dwDeviceStatus), sizeof(statusPacket.dwDeviceStatus));
  1079. } else {
  1080. ASSUME_NOT_REACHED();
  1081. }
  1082. }
  1083. }
  1084. return hRet;
  1085. }