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.

1147 lines
32 KiB

  1. /****************************************************************************
  2. MODULE: VXDIOCTL.CPP
  3. Tab stops 5 9
  4. Copyright 1995-1997, Microsoft Corporation, All Rights Reserved.
  5. PURPOSE: Methods for communicating with VJoyD min-driver specific
  6. to Jolt Midi device
  7. FUNCTIONS:
  8. Author(s): Name:
  9. ---------- ----------------
  10. MEA Manolito E. Adan
  11. Revision History:
  12. -----------------
  13. Version Date Author Comments
  14. ------- ------ ----- -------------------------------------------
  15. 1.0 03-Jan-97 MEA Original
  16. 1.1 14-Apr-97 MEA Added SetMidiPort IOCTL
  17. 11-Jun-97 MEA Added JoltHWReset IOCTL
  18. 17-Jun-97 MEA Added MAX_RETRY_COUNT on IOCTLs
  19. 20-Mar-99 waltw Nuked VxDCommunicator, this is NT5 only!
  20. 20-Mar-99 waltw Nuked unused IsHandleValid
  21. ****************************************************************************/
  22. #include "vxdioctl.hpp"
  23. //#include <crtdbg.h> // For RPT macros
  24. #include <WINIOCTL.H> // For IOCTL definitions (CTL_CODE)
  25. #include "FFDevice.h" // For g_ForceFeedbackDevice
  26. #include "sw_error.hpp" // For Sidewinder HRESULT Error codes
  27. #include "hau_midi.hpp" // For MAX_RETRY_COUNT and others
  28. #include "midi_obj.hpp" // Global Jolt midi object and definition
  29. #include "JoyRegst.hpp" // The differnt types of ACK_NACK
  30. #include "DTrans.h" // For global Data Transmitter
  31. DriverCommunicator* g_pDriverCommunicator = NULL;
  32. extern DataTransmitter* g_pDataTransmitter;
  33. extern HINSTANCE g_MyInstance;
  34. // Bitmasks for FW Version
  35. #define FW_MAJOR_VERSION 0x40 // Bit 6
  36. #define FW_MINOR_VERSION 0x3F // Bit 5-0
  37. #define FW_PRODUCT_ID 0xff
  38. // Bitmasks for Get Status packet dwDeviceStatus member
  39. #define ERROR_STATUS_MASK 0x07 // only bits 0-2 valid
  40. /********************************** HIDFeatureCommunicator class ***********************************/
  41. /****************************************
  42. **
  43. ** HIDFeatureCommunicator::HIDFeatureCommunicator()
  44. **
  45. ** @mfunc Constructor for VxD Communications path
  46. **
  47. *****************************************/
  48. HIDFeatureCommunicator::HIDFeatureCommunicator() :
  49. DriverCommunicator(),
  50. m_ForceFeature()
  51. {
  52. }
  53. /****************************************
  54. **
  55. ** HIDFeatureCommunicator::~HIDFeatureCommunicator()
  56. **
  57. ** @mfunc Destructor for VxD communications path
  58. **
  59. *****************************************/
  60. HIDFeatureCommunicator::~HIDFeatureCommunicator()
  61. {
  62. }
  63. /****************************************
  64. **
  65. ** BOOL HIDFeatureCommunicator::Initialize(UINT uJoystickId)
  66. **
  67. ** @mfunc Opens the driver for communications via IOCTLs
  68. **
  69. ** @rdesc TRUE if driver opened, FALSE otherwise
  70. **
  71. *****************************************/
  72. BOOL HIDFeatureCommunicator::Initialize
  73. (
  74. UINT uJoystickId //@parm Joystick ID to use
  75. )
  76. {
  77. if (g_ForceFeedbackDevice.IsOSNT5() == FALSE)
  78. { // Only allowable on NT5
  79. return FALSE;
  80. }
  81. return (SUCCEEDED(m_ForceFeature.Initialize(uJoystickId, g_MyInstance)));
  82. }
  83. /****************************************
  84. **
  85. ** BOOL HIDFeatureCommunicator::ResetDevice()
  86. **
  87. ** @mfunc Sends the driver a device reset IOCTL
  88. **
  89. ** @rdesc S_OK if IOCTL suceeds,
  90. **
  91. *****************************************/
  92. HRESULT HIDFeatureCommunicator::ResetDevice()
  93. {
  94. return m_ForceFeature.DoReset();
  95. }
  96. /****************************************
  97. **
  98. ** HRESULT HIDFeatureCommunicator::GetDriverVersion(DWORD& rdwMajor, DWORD& rdwMinor)
  99. **
  100. ** @mfunc IOCTLs a version request
  101. **
  102. ** @rdesc S_OK on success E_FAIL if driver not initialized
  103. **
  104. *****************************************/
  105. HRESULT HIDFeatureCommunicator::GetDriverVersion
  106. (
  107. DWORD& rdwMajor, //@parm reference to returned major part of version
  108. DWORD& rdwMinor //@parm reference to returned minor part of version
  109. )
  110. {
  111. ULONG ulVersion = m_ForceFeature.GetVersion();
  112. rdwMajor = (ulVersion >> 16) & 0x0000FFFF;
  113. rdwMinor = ulVersion & 0x0000FFFF;
  114. return S_OK;
  115. }
  116. /****************************************
  117. **
  118. ** HRESULT HIDFeatureCommunicator::GetID(LOCAL_PRODUCT_ID& rProductID)
  119. **
  120. ** @mfunc IOCTLs a product id request
  121. **
  122. ** @rdesc S_OK on success E_FAIL if driver not initialized
  123. **
  124. *****************************************/
  125. HRESULT HIDFeatureCommunicator::GetID
  126. (
  127. LOCAL_PRODUCT_ID& rProductID //@parm reference to local product id structure for return value
  128. )
  129. {
  130. if (rProductID.cBytes != sizeof LOCAL_PRODUCT_ID)
  131. { // structure size is invalid
  132. return SFERR_INVALID_STRUCT_SIZE;
  133. }
  134. // Create report packet and request
  135. PRODUCT_ID_REPORT productIDReport;
  136. productIDReport.ProductId.cBytes = sizeof PRODUCT_ID;
  137. HRESULT hr = m_ForceFeature.GetId(productIDReport);
  138. if (FAILED(hr))
  139. { // There was a problem
  140. return hr;
  141. }
  142. // Decode to local packet
  143. rProductID.dwProductID = productIDReport.ProductId.dwProductID & FW_PRODUCT_ID;
  144. rProductID.dwFWMajVersion = 1;
  145. if (productIDReport.ProductId.dwFWVersion & FW_MAJOR_VERSION)
  146. {
  147. rProductID.dwFWMajVersion++;
  148. }
  149. rProductID.dwFWMinVersion = productIDReport.ProductId.dwFWVersion & FW_MINOR_VERSION;
  150. return S_OK;
  151. }
  152. /****************************************
  153. **
  154. ** HRESULT HIDFeatureCommunicator::GetStatus(JOYCHANNELSTATUS& rChannelStatus)
  155. **
  156. ** @mfunc IOCTLs a status request
  157. **
  158. ** @rdesc S_OK on success E_FAIL if driver not initialized
  159. **
  160. *****************************************/
  161. HRESULT HIDFeatureCommunicator::GetStatus
  162. (
  163. JOYCHANNELSTATUS& rChannelStatus //@parm reference to status packet for result
  164. )
  165. {
  166. if (rChannelStatus.cBytes != sizeof JOYCHANNELSTATUS)
  167. { // structure size is invalid
  168. return SFERR_INVALID_STRUCT_SIZE;
  169. }
  170. if (NULL == g_pJoltMidi) return (SFERR_DRIVER_ERROR);
  171. // Create report packet and perform request
  172. JOYCHANNELSTATUS_REPORT statusReport;
  173. statusReport.JoyChannelStatus.cBytes = sizeof JOYCHANNELSTATUS;
  174. HRESULT hr = S_OK;
  175. for (int i=0; i < MAX_GET_STATUS_PACKET_RETRY_COUNT; i++) {
  176. Sleep(g_pJoltMidi->DelayParamsPtrOf()->dwGetStatusPacketDelay);
  177. hr = m_ForceFeature.GetStatus(statusReport);
  178. if (FAILED(hr))
  179. { // There was a problem
  180. if (i > 5)
  181. {
  182. Sleep(1);
  183. }
  184. }
  185. else
  186. {
  187. break;
  188. }
  189. }
  190. if (SUCCEEDED(hr))
  191. { // Get the data from report packet
  192. ::memcpy(&rChannelStatus, &(statusReport.JoyChannelStatus), sizeof JOYCHANNELSTATUS);
  193. }
  194. return hr;
  195. }
  196. /****************************************
  197. **
  198. ** HRESULT HIDFeatureCommunicator::GetAckNack(ACKNACK& rAckNack, USHORT usRegIndex)
  199. **
  200. ** @mfunc IOCTLs a status request
  201. **
  202. ** @rdesc S_OK on success E_FAIL if driver not initialized
  203. **
  204. *****************************************/
  205. HRESULT HIDFeatureCommunicator::GetAckNack
  206. (
  207. ACKNACK& rAckNack, //@parm Structure for return of acking
  208. USHORT usRegIndex //@parm Index to what type of ack/nack to do
  209. )
  210. {
  211. if (rAckNack.cBytes != sizeof ACKNACK)
  212. { // Invalid structure size
  213. return SFERR_INVALID_STRUCT_SIZE;
  214. }
  215. // Determine how to get the result
  216. switch (g_ForceFeedbackDevice.GetAckNackMethod(usRegIndex))
  217. {
  218. case ACKNACK_NOTHING:
  219. { // This one is real easy - do nothing
  220. rAckNack.dwAckNack = ACK;
  221. rAckNack.dwErrorCode = 0;
  222. return S_OK;
  223. }
  224. case ACKNACK_BUTTONSTATUS:
  225. { // Look at the button status (status gate)
  226. ULONG_REPORT report;
  227. HRESULT hr = m_ForceFeature.GetAckNak(report);
  228. if (FAILED(hr))
  229. { // There was a problem
  230. return hr;
  231. }
  232. if (report.uLong & ACKNACK_MASK_200)
  233. { // NACK error, so get Error code
  234. rAckNack.dwAckNack = NACK;
  235. JOYCHANNELSTATUS statusPacket = { sizeof JOYCHANNELSTATUS };
  236. if (FAILED(hr = GetStatus(statusPacket)))
  237. { // Failed to get status error
  238. return hr;
  239. }
  240. rAckNack.dwErrorCode = (statusPacket.dwDeviceStatus & ERROR_STATUS_MASK);
  241. return S_OK;
  242. }
  243. // ACK success
  244. rAckNack.dwAckNack = ACK;
  245. rAckNack.dwErrorCode = 0;
  246. if (report.uLong & RUNNING_MASK_200)
  247. { // Current driver and effect running
  248. rAckNack.dwEffectStatus = SWDEV_STS_EFFECT_RUNNING;
  249. }
  250. else
  251. { // Effect not running
  252. rAckNack.dwEffectStatus = SWDEV_STS_EFFECT_STOPPED;
  253. }
  254. return S_OK;
  255. }
  256. case ACKNACK_STATUSPACKET:
  257. { // Use the Status Packet Error code field to determine ACK or NACK and Get Error code
  258. JOYCHANNELSTATUS statusPacket = { sizeof JOYCHANNELSTATUS };
  259. HRESULT hr = GetStatus(statusPacket);
  260. if (FAILED(hr))
  261. { // Failed (retried inside GetStatus)
  262. return SFERR_DRIVER_ERROR;
  263. }
  264. rAckNack.dwErrorCode = statusPacket.dwDeviceStatus & ERROR_STATUS_MASK;
  265. rAckNack.dwAckNack = (rAckNack.dwErrorCode) ? NACK : ACK;
  266. return S_OK;
  267. }
  268. default:
  269. { // Someone put garbage in the registry (do nothing)
  270. rAckNack.dwAckNack = ACK;
  271. rAckNack.dwErrorCode = 0;
  272. return S_OK;
  273. }
  274. }
  275. return S_OK;
  276. }
  277. /****************************************
  278. **
  279. ** HRESULT HIDFeatureCommunicator::GetStatusGateData(DWORD& rdwGateData)
  280. **
  281. ** @mfunc IOCTLs a status gate request
  282. **
  283. ** @rdesc S_OK on success E_FAIL if driver not initialized
  284. **
  285. *****************************************/
  286. HRESULT HIDFeatureCommunicator::GetStatusGateData
  287. (
  288. DWORD& rdwGateData //@parm reference to return gate data
  289. )
  290. {
  291. ULONG_REPORT report;
  292. HRESULT hr = m_ForceFeature.GetAckNak(report);
  293. rdwGateData = report.uLong;
  294. return hr;
  295. }
  296. /****************************************
  297. **
  298. ** HRESULT HIDFeatureCommunicator::SendBackdoorShortMidi(DWORD dwMidiMessage)
  299. **
  300. ** @mfunc IOCTLs a request sending a message through midi backdoor
  301. **
  302. ** @rdesc S_OK on success E_FAIL if driver not initialized
  303. **
  304. *****************************************/
  305. HRESULT HIDFeatureCommunicator::SendBackdoorShortMidi
  306. (
  307. DWORD dwMidiMessage //@parm Midi Channel Message to send via IOCTL
  308. )
  309. {
  310. // Byte count
  311. short int sByteCount = 3;
  312. BYTE bCmd = BYTE(dwMidiMessage & 0xF0);
  313. if ((bCmd == 0xC0 ) || (bCmd == 0xD0)) {
  314. sByteCount = 2;
  315. }
  316. // Send via data transmitter
  317. if (g_pDataTransmitter != NULL) {
  318. if (g_pDataTransmitter->Send((BYTE*)(&dwMidiMessage), sByteCount)) {
  319. return S_OK;
  320. }
  321. return SFERR_DRIVER_ERROR;
  322. }
  323. // Must use the data transmitter there is no backdoor in NT5
  324. return E_FAIL;
  325. }
  326. /****************************************
  327. **
  328. ** HRESULT HIDFeatureCommunicator::SendBackdoorLongMidi(BYTE* pMidiData)
  329. **
  330. ** @mfunc IOCTLs a request sending a message through midi backdoor
  331. **
  332. ** @rdesc S_OK on success E_FAIL if driver not initialized
  333. **
  334. *****************************************/
  335. HRESULT HIDFeatureCommunicator::SendBackdoorLongMidi
  336. (
  337. BYTE* pMidiData //@parm Array of bytes to send out
  338. )
  339. {
  340. // Count the bytes
  341. short int sByteCount = 1;
  342. while (!(pMidiData[sByteCount++] & 0x80));
  343. // Send via data transmitter?
  344. if (g_pDataTransmitter != NULL) {
  345. if (g_pDataTransmitter->Send(pMidiData, sByteCount)) {
  346. return (SUCCESS);
  347. }
  348. return (SFERR_DRIVER_ERROR);
  349. }
  350. // There is no real backdoor in NT
  351. return E_FAIL;
  352. }
  353. /********************************** Old dead code ***********************************/
  354. #if 0
  355. #include <windows.h>
  356. #include <WINIOCTL.H>
  357. #include "vxdioctl.hpp"
  358. #include "SW_error.hpp"
  359. #include "version.h"
  360. #include "hau_midi.hpp"
  361. #include "midi_obj.hpp"
  362. #include "DTrans.h"
  363. #include "FFDevice.h"
  364. #include "joyregst.hpp"
  365. #ifdef _DEBUG
  366. extern char g_cMsg[160];
  367. #endif
  368. #ifdef _DEBUG
  369. extern void DebugOut(LPCTSTR szDebug);
  370. #else !_DEBUG
  371. #define DebugOut(x)
  372. #endif _DEBUG
  373. extern DataTransmitter* g_pDataTransmitter;
  374. DWORD g_PreviousShortMidi = 0;
  375. class CJoltMidi;
  376. extern CJoltMidi *g_pJoltMidi;
  377. //
  378. // --- IOCTL Functions
  379. //
  380. /****************************************************************************
  381. FUNCTION: GetDevice
  382. PARAMETERS: IN const char* vxdName - Name of VxD
  383. RETURNS: valid HANDLE if successful or NULL
  384. COMMENTS:
  385. ****************************************************************************/
  386. HANDLE WINAPI GetDevice(
  387. IN const char* vxdName)
  388. {
  389. char fileName[64];
  390. HANDLE retVal;
  391. if (g_ForceFeedbackDevice.IsOSNT5()) { // Need to start MSGameIO
  392. try {
  393. // Open the Service Control Managere
  394. SC_HANDLE serviceControlManager = ::OpenSCManager(NULL, NULL, SC_MANAGER_CONNECT);
  395. if (serviceControlManager == NULL) {
  396. throw 0;
  397. }
  398. // Open the Service
  399. SC_HANDLE ring0DriverService = ::OpenService(serviceControlManager, vxdName, SERVICE_QUERY_STATUS | SERVICE_START);
  400. if (ring0DriverService == NULL) {
  401. throw 0;
  402. }
  403. // Start for service
  404. if (!::StartService(ring0DriverService, 0, NULL)) {
  405. throw 0;
  406. }
  407. // Did it start yet - Do some fancy waiting
  408. SERVICE_STATUS serviceStatus;
  409. DWORD lastCheckPoint = 0;
  410. do {
  411. if (!::QueryServiceStatus(ring0DriverService, &serviceStatus)) {
  412. throw 0;
  413. }
  414. if (serviceStatus.dwCurrentState == SERVICE_START_PENDING) {
  415. if (serviceStatus.dwCheckPoint <= lastCheckPoint) {
  416. DebugOut("Failed to start service\r\n");
  417. break;
  418. }
  419. lastCheckPoint = serviceStatus.dwCheckPoint;
  420. ::Sleep(serviceStatus.dwWaitHint);
  421. } else {
  422. DebugOut("Service Started (maybe), Yeah!\r\n");
  423. break;
  424. }
  425. } while (1);
  426. ::CloseServiceHandle(ring0DriverService); // Close the Ring0 Handle
  427. ::CloseServiceHandle(serviceControlManager); // Close the service control manager handle
  428. } catch(...) {
  429. DWORD errorCode = ::GetLastError();
  430. if (errorCode == ERROR_ACCESS_DENIED) { // We are screwed
  431. DebugOut("Access is denied\r\n");
  432. } else {
  433. DebugOut("Unable to start service\r\n");
  434. }
  435. }
  436. }
  437. wsprintf(fileName, "\\\\.\\%s", vxdName);
  438. retVal = CreateFile(fileName, GENERIC_READ | GENERIC_WRITE,
  439. 0, 0, OPEN_EXISTING, FILE_FLAG_DELETE_ON_CLOSE, 0);
  440. #ifdef _DEBUG
  441. wsprintf(g_cMsg, "GetDevice: %s -- Vxd Handle: 0x%X\r\n", vxdName, retVal);
  442. OutputDebugString(g_cMsg);
  443. #endif
  444. return retVal;
  445. }
  446. /****************************************************************************
  447. FUNCTION: CloseDevice
  448. PARAMETERS: IN HANDLE hVxD - valid VxD Handle
  449. RETURNS: BOOL TRUE if successful else FALSE
  450. COMMENTS:
  451. ****************************************************************************/
  452. BOOL WINAPI CloseDevice(
  453. IN HANDLE hVxD)
  454. {
  455. if (hVxD != INVALID_HANDLE_VALUE)
  456. return (CloseHandle(hVxD));
  457. return FALSE;
  458. }
  459. /****************************************************************************
  460. FUNCTION: QueryDriverVersion
  461. PARAMETERS: DWORD& major, DWORD& minor - Major and Minor parts of driver version
  462. RETURNS: BOOL TRUE if successful else FALSE
  463. COMMENTS:
  464. ****************************************************************************/
  465. HRESULT QueryDriverVersion(DWORD& major, DWORD& minor)
  466. {
  467. if ((g_pJoltMidi == NULL) || (g_pJoltMidi->VxDHandleOf() == INVALID_HANDLE_VALUE)) {
  468. return SFERR_DRIVER_ERROR;
  469. }
  470. DWORD version = 0x00000000;
  471. DWORD bytesReturned = 0;
  472. // HRESULT hr = DeviceIoControl(g_pJoltMidi->VxDHandleOf(), DIOC_GETVERSION, NULL, 0, &version, 4, &bytesReturned, NULL);
  473. if (::DeviceIoControl(g_pJoltMidi->VxDHandleOf(), IOCTL_GET_VERSION, NULL, 0, &version, 4, &bytesReturned, NULL)) {
  474. major = (version >> 16) & 0x0000FFFF;
  475. minor = version & 0x0000FFFF;
  476. }
  477. return S_OK;
  478. }
  479. /****************************************************************************
  480. FUNCTION: GetDataPacket
  481. PARAMETERS: IN HANDLE hVxD - valid VxD Handle
  482. IN OUT PJOYCHANNELDATA pDataPacket - Pointer to JOYCHANNELDATA
  483. structure
  484. RETURNS: SUCCESS or error code
  485. COMMENTS: No longer a valid IOCTL (mlc)
  486. ****************************************************************************/
  487. HRESULT WINAPI GetDataPacket(
  488. IN HANDLE hDevice,
  489. IN OUT PJOYCHANNELDATA pDataPacket)
  490. {
  491. return SFERR_DRIVER_ERROR;
  492. }
  493. /****************************************************************************
  494. FUNCTION: GetStatusPacket
  495. PARAMETERS: IN HANDLE hVxD - valid VxD Handle
  496. IN OUT PJOYCHANNELSTATUS pStatusPacket - Pointer to
  497. JOYCHANNELSTATUS structure
  498. RETURNS: SUCCESS or error code
  499. COMMENTS:
  500. ****************************************************************************/
  501. HRESULT WINAPI GetStatusPacket(
  502. IN HANDLE hDevice,
  503. IN OUT PJOYCHANNELSTATUS pStatusPacket)
  504. {
  505. DWORD dwBytesReturned;
  506. if (INVALID_HANDLE_VALUE == hDevice) {
  507. return SFERR_DRIVER_ERROR;
  508. }
  509. if (pStatusPacket->cBytes != sizeof(JOYCHANNELSTATUS)) {
  510. return (SFERR_INVALID_STRUCT_SIZE);
  511. }
  512. DWORD ioctlID = (g_ForceFeedbackDevice.GetDriverVersionMajor() > 1) ? IOCTL_SWFORCE_GETSTATUS : IOCTL_GET_STATUSPACKET;
  513. for (int i=0; i < MAX_GET_STATUS_PACKET_RETRY_COUNT; i++) {
  514. Sleep(g_pJoltMidi->DelayParamsPtrOf()->dwGetStatusPacketDelay);
  515. // Send the IOCTL
  516. BOOL bRetFlag = DeviceIoControl(hDevice,
  517. ioctlID,
  518. (LPVOID) pStatusPacket,
  519. (DWORD) sizeof(JOYCHANNELSTATUS),
  520. (LPVOID) pStatusPacket,
  521. (DWORD) sizeof(JOYCHANNELSTATUS),
  522. (LPDWORD) &dwBytesReturned,
  523. (LPOVERLAPPED) NULL);
  524. if (bRetFlag) {
  525. // Convert values to a signed LONG
  526. pStatusPacket->dwXVel = (LONG)((char)(pStatusPacket->dwXVel));
  527. pStatusPacket->dwYVel = (LONG)((char)(pStatusPacket->dwYVel));
  528. pStatusPacket->dwXAccel = (LONG)((char)(pStatusPacket->dwXAccel));
  529. pStatusPacket->dwXAccel = (LONG)((char)(pStatusPacket->dwYAccel));
  530. return SUCCESS;
  531. }
  532. if(i>5) {
  533. Sleep(1);
  534. }
  535. }
  536. return SFERR_DRIVER_ERROR;
  537. }
  538. /****************************************************************************
  539. FUNCTION: GetIDPacket
  540. PARAMETERS: IN HANDLE hVxD - valid VxD Handle
  541. IN OUT PPRODUCT_ID pID - Pointer to PRODUCT_ID structure
  542. RETURNS: SUCCESS or error code
  543. COMMENTS:
  544. ****************************************************************************/
  545. HRESULT WINAPI GetIDPacket(
  546. IN HANDLE hDevice,
  547. IN OUT PPRODUCT_ID pID)
  548. {
  549. DWORD dwBytesReturned;
  550. if (INVALID_HANDLE_VALUE == hDevice)
  551. return SFERR_DRIVER_ERROR;
  552. if (pID->cBytes != sizeof(PRODUCT_ID))
  553. return (SFERR_INVALID_STRUCT_SIZE);
  554. JOYCHANNELID IDPacket = {sizeof(JOYCHANNELID)};
  555. DWORD ioctlID = (g_ForceFeedbackDevice.GetDriverVersionMajor() > 1) ? IOCTL_SWFORCE_GETID : IOCTL_GET_IDPACKET;
  556. for (int i=0; i<MAX_RETRY_COUNT; i++)
  557. {
  558. // Send the IOCTL
  559. BOOL bRetFlag = DeviceIoControl(hDevice,
  560. ioctlID,
  561. (LPVOID) &IDPacket,
  562. (DWORD) sizeof(JOYCHANNELID),
  563. (LPVOID) &IDPacket,
  564. (DWORD) sizeof(JOYCHANNELID),
  565. (LPDWORD) &dwBytesReturned,
  566. (LPOVERLAPPED) NULL);
  567. Sleep(g_pJoltMidi->DelayParamsPtrOf()->dwGetIDPacketDelay);
  568. // Any error codes are returned in the first DWORD of the structure
  569. if (bRetFlag) {
  570. pID->dwProductID = IDPacket.dwProductID & FW_PRODUCT_ID;
  571. pID->dwFWMajVersion = 1;
  572. if (IDPacket.dwFWVersion & FW_MAJOR_VERSION)
  573. pID->dwFWMajVersion++;
  574. pID->dwFWMinVersion = IDPacket.dwFWVersion & FW_MINOR_VERSION;
  575. return SUCCESS;
  576. }
  577. }
  578. return SFERR_DRIVER_ERROR;
  579. }
  580. /****************************************************************************
  581. FUNCTION: GetDiagnostics
  582. PARAMETERS: IN HANDLE hVxD - valid VxD Handle
  583. IN OUT PDIAGNOSTIC_COUNTER pDiagnostics - Pointer to
  584. DIAGNOSTIC_COUNTER structure
  585. RETURNS: SUCCESS or error code
  586. COMMENTS:
  587. ****************************************************************************/
  588. HRESULT WINAPI GetDiagnostics(
  589. IN HANDLE hDevice,
  590. IN OUT PDIAGNOSTIC_COUNTER pDiagnostics)
  591. {
  592. DWORD dwBytesReturned;
  593. BOOL bRetFlag;
  594. if (INVALID_HANDLE_VALUE == hDevice)
  595. return (SFERR_DRIVER_ERROR);
  596. if (pDiagnostics->cBytes != sizeof(DIAGNOSTIC_COUNTER))
  597. return (SFERR_INVALID_STRUCT_SIZE);
  598. // Send the IOCTL
  599. bRetFlag = DeviceIoControl(hDevice,
  600. (DWORD) IOCTL_GET_DIAGNOSTICS,
  601. (LPVOID) pDiagnostics,
  602. (DWORD) sizeof(DIAGNOSTIC_COUNTER),
  603. (LPVOID) pDiagnostics,
  604. (DWORD) sizeof(DIAGNOSTIC_COUNTER),
  605. (LPDWORD) &dwBytesReturned,
  606. (LPOVERLAPPED) NULL);
  607. // Any error codes are returned in the first DWORD of the structure
  608. if (!bRetFlag || (dwBytesReturned != sizeof(DIAGNOSTIC_COUNTER)) )
  609. {
  610. return (SFERR_DRIVER_ERROR);
  611. }
  612. return (SUCCESS);
  613. }
  614. /****************************************************************************
  615. FUNCTION: GetAckNack
  616. PARAMETERS: IN HANDLE hVxD - valid VxD Handle
  617. IN OUT PACKNACK pAckNack - Pointer to ACKNACK structure
  618. RETURNS: SUCCESS or error code
  619. COMMENTS:
  620. typedef struct _ACKNACK {
  621. DWORD cBytes;
  622. DWORD dwAckNack; //ACK, NACK
  623. DWORD dwErrorCode;
  624. DWORD dwEffectStatus; //SWDEV_STS_EFFECT_RUNNING||SWDEV_STS_EFFECT_STOPPED
  625. } ACKNACK, *PACKNACK;
  626. ****************************************************************************/
  627. HRESULT WINAPI GetAckNack(
  628. IN HANDLE hDevice,
  629. IN OUT PACKNACK pAckNack,
  630. IN USHORT regindex)
  631. {
  632. if (INVALID_HANDLE_VALUE == hDevice) {
  633. return SFERR_DRIVER_ERROR;
  634. }
  635. if (pAckNack->cBytes != sizeof(ACKNACK)) {
  636. return SFERR_INVALID_STRUCT_SIZE;
  637. }
  638. switch (g_ForceFeedbackDevice.GetAckNackMethod(regindex)) {
  639. case ACKNACK_NOTHING: {
  640. pAckNack->dwAckNack = ACK;
  641. pAckNack->dwErrorCode = 0;
  642. return SUCCESS;
  643. }
  644. case ACKNACK_BUTTONSTATUS: {
  645. DWORD dwBytesReturned;
  646. BOOL bRetFlag;
  647. DWORD dwIn;
  648. DWORD ioctlID = (g_ForceFeedbackDevice.GetDriverVersionMajor() > 1) ? IOCTL_SWFORCE_GETACKNACK : IOCTL_GET_ACKNACK;
  649. // Send the IOCTL
  650. bRetFlag = DeviceIoControl(hDevice,
  651. ioctlID,
  652. (LPVOID) &dwIn,
  653. (DWORD) sizeof(DWORD),
  654. (LPVOID) &dwIn,
  655. (DWORD) sizeof(DWORD),
  656. (LPDWORD) &dwBytesReturned,
  657. (LPOVERLAPPED) NULL);
  658. if (!bRetFlag || (dwBytesReturned != sizeof(DWORD)) ) {
  659. return (SFERR_DRIVER_ERROR);
  660. }
  661. if (((g_ForceFeedbackDevice.GetDriverVersionMajor() == 1) && (dwIn & ACKNACK_MASK_1XX))
  662. || ((g_ForceFeedbackDevice.GetDriverVersionMajor() != 1) && (dwIn & ACKNACK_MASK_200))) { // NACK error, so get Error code
  663. pAckNack->dwAckNack = NACK;
  664. JOYCHANNELSTATUS StatusPacket = {sizeof(JOYCHANNELSTATUS)};
  665. if (FAILED(GetStatusPacket(hDevice, &StatusPacket))) {
  666. return (SFERR_DRIVER_ERROR);
  667. }
  668. pAckNack->dwErrorCode = (StatusPacket.dwDeviceStatus & ERROR_STATUS_MASK);
  669. return SUCCESS;
  670. }
  671. // ACK success
  672. pAckNack->dwAckNack = ACK;
  673. pAckNack->dwErrorCode = 0;
  674. if (((g_ForceFeedbackDevice.GetDriverVersionMajor() == 1) && (dwIn & RUNNING_MASK_1XX))
  675. || ((g_ForceFeedbackDevice.GetDriverVersionMajor() != 1) && (dwIn & RUNNING_MASK_200))) {
  676. pAckNack->dwEffectStatus = SWDEV_STS_EFFECT_RUNNING;
  677. } else {
  678. pAckNack->dwEffectStatus = SWDEV_STS_EFFECT_STOPPED;
  679. }
  680. return SUCCESS;
  681. }
  682. case ACKNACK_STATUSPACKET: {
  683. // Use the Status Packet Error code field to determine ACK or NACK
  684. // Get Error code
  685. JOYCHANNELSTATUS StatusPacket = {sizeof(JOYCHANNELSTATUS)};
  686. HRESULT hRet = GetStatusPacket(hDevice, &StatusPacket); // Retry count in GetStatusPacket function
  687. if (FAILED(hRet)) {
  688. DebugOut("GetStatusPacket Error\n");
  689. hRet = SFERR_DRIVER_ERROR;
  690. } else {
  691. pAckNack->dwErrorCode = StatusPacket.dwDeviceStatus & ERROR_STATUS_MASK;
  692. pAckNack->dwAckNack = (pAckNack->dwErrorCode) ? NACK : ACK;
  693. }
  694. return hRet;
  695. }
  696. default: { // Someone put garbage in the registry (do nothing)
  697. pAckNack->dwAckNack = ACK;
  698. pAckNack->dwErrorCode = 0;
  699. return SUCCESS;
  700. }
  701. }
  702. }
  703. /****************************************************************************
  704. FUNCTION: GetStatusGateData
  705. PARAMETERS: IN HANDLE hVxD - valid VxD Handle
  706. IN OUT DWORD *pdwStatusGateData - Pointer to Status Gate
  707. RETURNS: SUCCESS or error code
  708. COMMENTS:
  709. ****************************************************************************/
  710. HRESULT WINAPI GetStatusGateData(
  711. IN HANDLE hDevice,
  712. IN OUT DWORD *pdwStatusGateData)
  713. {
  714. DWORD dwBytesReturned;
  715. BOOL bRetFlag;
  716. DWORD dwIn;
  717. HRESULT hRet = SFERR_DRIVER_ERROR;
  718. if (INVALID_HANDLE_VALUE == hDevice)
  719. return (hRet);
  720. if (NULL == pdwStatusGateData)
  721. return (SFERR_INVALID_PARAM);
  722. DWORD ioctlID = (g_ForceFeedbackDevice.GetDriverVersionMajor() > 1) ? IOCTL_SWFORCE_GETACKNACK : IOCTL_GET_ACKNACK;
  723. for (int i=0; i<MAX_RETRY_COUNT; i++)
  724. {
  725. // Obtain Status Gate data
  726. // Send the IOCTL
  727. bRetFlag = DeviceIoControl(hDevice,
  728. ioctlID,
  729. (LPVOID) &dwIn,
  730. (DWORD) sizeof(DWORD),
  731. (LPVOID) &dwIn,
  732. (DWORD) sizeof(DWORD),
  733. (LPDWORD) &dwBytesReturned,
  734. (LPOVERLAPPED) NULL);
  735. Sleep(g_pJoltMidi->DelayParamsPtrOf()->dwGetStatusGateDataDelay);
  736. if (bRetFlag && (dwBytesReturned == sizeof(DWORD)))
  737. {
  738. hRet = SUCCESS;
  739. break;
  740. }
  741. }
  742. *pdwStatusGateData = dwIn;
  743. return (hRet);
  744. }
  745. /****************************************************************************
  746. FUNCTION: SendBackDoorShortMidi
  747. PARAMETERS: IN HANDLE hDevice - Handle to Vxd
  748. IN ULONG ulData - DWORD to send
  749. RETURNS:
  750. COMMENTS:
  751. ****************************************************************************/
  752. HRESULT WINAPI SendBackDoorShortMidi(
  753. IN HANDLE hDevice,
  754. IN ULONG ulData)
  755. {
  756. #ifdef _DEBUG
  757. // wsprintf(g_cMsg, "SendBackDoorShortMidi Data=%.8lx\r\n", ulData);
  758. // OutputDebugString(g_cMsg);
  759. #endif
  760. DWORD dwIn;
  761. DWORD bytesReturned;
  762. // Byte count
  763. int numBytes = 3;
  764. DWORD cmd = ulData & 0xF0;
  765. if ((cmd == 0xC0 ) || (cmd == 0xD0)) {
  766. numBytes = 2;
  767. }
  768. // Send via data transmitter
  769. if (g_pDataTransmitter != NULL) {
  770. g_PreviousShortMidi = ulData;
  771. if (g_pDataTransmitter->Send((BYTE*)(&ulData), numBytes)) {
  772. return (SUCCESS);
  773. }
  774. return (SFERR_DRIVER_ERROR);
  775. }
  776. // Is there a proper ring0 driver?
  777. if (INVALID_HANDLE_VALUE == hDevice) {
  778. return (SFERR_DRIVER_ERROR);
  779. }
  780. // Send via new single send IOCTL
  781. if (g_ForceFeedbackDevice.GetDriverVersionMajor() > 1) {
  782. if (DeviceIoControl(hDevice, IOCTL_SWFORCE_SENDDATA, (void*)&ulData, DWORD(numBytes),
  783. (void*)&dwIn, sizeof(DWORD), (DWORD*)&bytesReturned,
  784. (LPOVERLAPPED) NULL)) {
  785. if (bytesReturned == DWORD(numBytes)) {
  786. return SUCCESS;
  787. }
  788. }
  789. return SFERR_DRIVER_ERROR;
  790. }
  791. // Send the IOCTL the old way
  792. if (DeviceIoControl(hDevice, IOCTL_MIDISENDSHORTMSG, (void*)&ulData, sizeof(DWORD),
  793. (void*)&dwIn, sizeof(DWORD), &bytesReturned,
  794. (LPOVERLAPPED) NULL)) {
  795. if (bytesReturned == sizeof(DWORD)) {
  796. return (SUCCESS);
  797. }
  798. }
  799. return SFERR_DRIVER_ERROR;
  800. }
  801. /****************************************************************************
  802. FUNCTION: SendBackDoorLongMidi
  803. PARAMETERS: IN HANDLE hDevice - Handle to Vxd
  804. IN ULONG ulData - DWORD to send
  805. RETURNS:
  806. COMMENTS:
  807. ****************************************************************************/
  808. HRESULT WINAPI SendBackDoorLongMidi(
  809. IN HANDLE hDevice,
  810. IN PBYTE pData)
  811. {
  812. #ifdef _VERBOSE
  813. #pragma message("Compiling with VERBOSE mode")
  814. #ifdef _DEBUG
  815. wsprintf(g_cMsg, "SendBackDoorLongMidi pData\n%.2x ", pData[0]);
  816. OutputDebugString(g_cMsg);
  817. int i=1;
  818. while(TRUE)
  819. {
  820. wsprintf(g_cMsg,"%.2x ", pData[i]);
  821. OutputDebugString(g_cMsg);
  822. if (pData[i] & 0x80)
  823. break;
  824. else
  825. i++;
  826. }
  827. OutputDebugString("\n");
  828. #endif
  829. #endif
  830. DWORD dwIn;
  831. DWORD bytesReturned;
  832. // Count the bytes
  833. int numBytes = 1;
  834. while (!(pData[numBytes++] & 0x80));
  835. // Send via data transmitter?
  836. if (g_pDataTransmitter != NULL) {
  837. if (g_pDataTransmitter->Send(pData, numBytes)) {
  838. return (SUCCESS);
  839. }
  840. return (SFERR_DRIVER_ERROR);
  841. }
  842. // Is there a proper ring0 driver?
  843. if (INVALID_HANDLE_VALUE == hDevice) {
  844. return (SFERR_DRIVER_ERROR);
  845. }
  846. // Send via new single send IOCTL
  847. if (g_ForceFeedbackDevice.GetDriverVersionMajor() > 1) {
  848. if (DeviceIoControl(hDevice, IOCTL_SWFORCE_SENDDATA, (void*)pData, DWORD(numBytes),
  849. (void*)&dwIn, sizeof(DWORD), (DWORD*)&bytesReturned,
  850. (LPOVERLAPPED) NULL)) {
  851. if (bytesReturned == DWORD(numBytes)) {
  852. return SUCCESS;
  853. }
  854. }
  855. return SFERR_DRIVER_ERROR;
  856. }
  857. // Send the IOCTL the old way
  858. if (DeviceIoControl(hDevice, IOCTL_MIDISENDLONGMSG, (void*)pData, sizeof(DWORD),
  859. (void*)&dwIn, sizeof(DWORD), (DWORD*)&bytesReturned,
  860. (LPOVERLAPPED) NULL)) {
  861. if (bytesReturned == sizeof(DWORD)) {
  862. return SUCCESS;
  863. }
  864. }
  865. return SFERR_DRIVER_ERROR;
  866. }
  867. /****************************************************************************
  868. FUNCTION: SetMidiPort
  869. PARAMETERS: IN HANDLE hDevice - Handle to Vxd
  870. IN ULONG ulPort - Port #
  871. RETURNS:
  872. COMMENTS:
  873. 0 = DEFAULT MIDI UART 330
  874. 1 = COM1
  875. 2 = COM2
  876. 3 = COM3
  877. 4 = COM4
  878. or other MIDI port 340, etc...
  879. ****************************************************************************/
  880. HRESULT WINAPI SetMidiPort(
  881. IN HANDLE hDevice,
  882. IN ULONG ulPort)
  883. {
  884. if (g_ForceFeedbackDevice.IsOSNT5()) {
  885. return SUCCESS;
  886. }
  887. #ifdef _DEBUG
  888. wsprintf(g_cMsg, "SetMidiPort Port %lx\r\n", ulPort);
  889. OutputDebugString(g_cMsg);
  890. #endif
  891. DWORD dwBytesReturned;
  892. BOOL bRetFlag;
  893. DWORD dwIn;
  894. if (INVALID_HANDLE_VALUE == hDevice)
  895. return (SFERR_DRIVER_ERROR);
  896. DWORD ioctlID = (g_ForceFeedbackDevice.GetDriverVersionMajor() > 1) ? IOCTL_SWFORCE_SETPORT : IOCTL_SET_MIDIPORT;
  897. // Send the IOCTL
  898. bRetFlag = DeviceIoControl(hDevice,
  899. ioctlID,
  900. (LPVOID) &ulPort,
  901. (DWORD) sizeof(DWORD),
  902. (LPVOID) &dwIn,
  903. (DWORD) sizeof(DWORD),
  904. (LPDWORD) &dwBytesReturned,
  905. (LPOVERLAPPED) NULL);
  906. if (!bRetFlag || (dwBytesReturned != sizeof(DWORD)) )
  907. {
  908. return (SFERR_DRIVER_ERROR);
  909. }
  910. return (SUCCESS);
  911. }
  912. /****************************************************************************
  913. FUNCTION: JoltHWReset
  914. PARAMETERS: IN HANDLE hDevice - Handle to Vxd
  915. RETURNS:
  916. COMMENTS:
  917. Jolt is Reset (4 knocks)
  918. ****************************************************************************/
  919. HRESULT WINAPI JoltHWReset(
  920. IN HANDLE hDevice)
  921. {
  922. #ifdef _DEBUG
  923. wsprintf(g_cMsg, "JoltHWReset\r\n");
  924. OutputDebugString(g_cMsg);
  925. #endif
  926. DWORD dwBytesReturned;
  927. BOOL bRetFlag;
  928. DWORD dwIn;
  929. if (INVALID_HANDLE_VALUE == hDevice)
  930. return (SFERR_DRIVER_ERROR);
  931. DWORD ioctlID = (g_ForceFeedbackDevice.GetDriverVersionMajor() > 1) ? IOCTL_SWFORCE_RESET : IOCTL_HW_RESET;
  932. // Send the IOCTL
  933. bRetFlag = DeviceIoControl(hDevice,
  934. ioctlID,
  935. (LPVOID) NULL,
  936. (DWORD) sizeof(DWORD),
  937. (LPVOID) &dwIn,
  938. (DWORD) sizeof(DWORD),
  939. (LPDWORD) &dwBytesReturned,
  940. (LPOVERLAPPED) NULL);
  941. if (!bRetFlag || (dwBytesReturned != sizeof(DWORD)) )
  942. {
  943. return (SFERR_DRIVER_ERROR);
  944. }
  945. return (SUCCESS);
  946. }
  947. #endif