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.

1011 lines
31 KiB

  1. //@doc
  2. /******************************************************
  3. **
  4. ** @module DTRANS.CPP | DataTransmitter implementation file
  5. **
  6. ** Description:
  7. **
  8. ** History:
  9. ** Created 11/13/97 Matthew L. Coill (mlc)
  10. **
  11. ** 21-Mar-99 waltw Removed unused ReportTransmission (Win9x only)
  12. ** 22-Mar-99 waltw Added DWORD dwDeviceID param to Initialize
  13. ** members of DataTransmitter and derived classes
  14. **
  15. ** (c) 1986-1999 Microsoft Corporation. All Rights Reserved.
  16. ******************************************************/
  17. #include "FFDevice.h"
  18. #include "DTrans.h"
  19. #include "DPack.h"
  20. #include "WinIOCTL.h" // For IOCTLs
  21. #include "VxDIOCTL.hpp"
  22. #include "SW_error.hpp"
  23. #include "midi_obj.hpp"
  24. #include "joyregst.hpp"
  25. #include "CritSec.h"
  26. DataTransmitter* g_pDataTransmitter = NULL;
  27. extern CJoltMidi *g_pJoltMidi;
  28. #ifdef _DEBUG
  29. extern void DebugOut(LPCTSTR szDebug);
  30. #else !_DEBUG
  31. #define DebugOut(x)
  32. #endif _DEBUG
  33. const char cCommPortNames[4][5] = { "COM1", "COM2", "COM3", "COM4" };
  34. const unsigned short c1_16_BytesPerShot = 3;
  35. const DWORD c1_16_SerialSleepTime = 1;
  36. /****************** DataTransmitter class ***************/
  37. HRESULT DataTransmitter::Transmit(ACKNACK& ackNack)
  38. {
  39. ackNack.cBytes = 0; // Indicated not valid (ack/nack not done)
  40. if (g_pDataPackager == NULL) {
  41. ASSUME_NOT_REACHED();
  42. return SFERR_DRIVER_ERROR;
  43. }
  44. if (NULL == g_pJoltMidi) return (SFERR_DRIVER_ERROR);
  45. BOOL forcedToggle = FALSE;
  46. if (m_NackToggle == 2) { // When Not yet sunk up == 2, probably initializing if 2 (synch up)
  47. ULONG portByte = 0;
  48. g_pDriverCommunicator->GetPortByte(portByte); // don't care about success, always fails on old driver
  49. if (portByte & STATUS_GATE_200) {
  50. SetNextNack(1);
  51. } else {
  52. SetNextNack(0);
  53. }
  54. forcedToggle = TRUE;
  55. }
  56. DataPacket* pNextPacket = NULL;
  57. for (USHORT packetIndex = 0; packetIndex < g_pDataPackager->GetNumDataPackets(); packetIndex++) {
  58. pNextPacket = g_pDataPackager->GetPacket(packetIndex);
  59. ASSUME_NOT_NULL(pNextPacket);
  60. if (pNextPacket == NULL) {
  61. return SFERR_DRIVER_ERROR;
  62. }
  63. BOOL success = FALSE;
  64. int retries = int(pNextPacket->m_NumberOfRetries);
  65. do {
  66. m_NackToggle = (m_NackToggle + 1) % 2; // Verions 2.0 switches button-line ack/nack methods each time
  67. ULONG portByte = 0;
  68. BOOL error = FALSE;
  69. if (g_pDriverCommunicator->GetPortByte(portByte) == SUCCESS) { // Will fail on old driver
  70. if (portByte & STATUS_GATE_200) { // Line is high
  71. if (m_NackToggle != 0) { // We should be expecting low
  72. m_NackToggle = 0; // Update it if wrong
  73. error = TRUE;
  74. DebugOut("SW_WHEEL.DLL: Status Gate is out of Synch (High - Expecting Low)!!!\r\n");
  75. }
  76. } else { // Line is low
  77. if (m_NackToggle != 1) { // We should be expecting high
  78. m_NackToggle = 1; // Update it if wrong
  79. error = TRUE;
  80. DebugOut("SW_WHEEL.DLL: Status Gate is out of Synch (Low - Expecting High)!!!\r\n");
  81. }
  82. }
  83. }
  84. Send(pNextPacket->m_pData, pNextPacket->m_BytesOfData);
  85. if (pNextPacket->m_AckNackDelay != 0) {
  86. Sleep(pNextPacket->m_AckNackDelay);
  87. }
  88. ackNack.cBytes = sizeof(ACKNACK);
  89. HRESULT hr = g_pJoltMidi->GetAckNackData(pNextPacket->m_AckNackTimeout, &ackNack, (USHORT)pNextPacket->m_AckNackMethod);
  90. if (forcedToggle == TRUE) {
  91. m_NackToggle = 2;
  92. }
  93. if (hr != SUCCESS) {
  94. return SFERR_DRIVER_ERROR;
  95. }
  96. success = (ackNack.dwAckNack == ACK);
  97. if (success == FALSE) { // We don't want to bother retrying on certian error codes, retrying is worthless
  98. success = ((ackNack.dwErrorCode == DEV_ERR_MEM_FULL_200) || (ackNack.dwErrorCode == DEV_ERR_PLAY_FULL_200) || (ackNack.dwErrorCode == DEV_ERR_INVALID_ID_200));
  99. }
  100. } while (!success && (--retries > 0));
  101. if (ackNack.dwAckNack == NACK) {
  102. return SFERR_DEVICE_NACK;
  103. }
  104. }
  105. g_pDataPackager->ClearPackets();
  106. return SUCCESS;
  107. }
  108. /****************** SerialDataTransmitter class ***************/
  109. /******************************************************
  110. **
  111. ** SerialDataTransmitter::SerialDataTransmitter()
  112. **
  113. ** @mfunc Constructor.
  114. **
  115. ******************************************************/
  116. SerialDataTransmitter::SerialDataTransmitter() : DataTransmitter(),
  117. m_SerialPort(INVALID_HANDLE_VALUE),
  118. m_SerialPortIDHack(0)
  119. {
  120. }
  121. /******************************************************
  122. **
  123. ** SerialDataTransmitter::~SerialDataTransmitter()
  124. **
  125. ** @mfunc Destructor.
  126. **
  127. ******************************************************/
  128. SerialDataTransmitter::~SerialDataTransmitter()
  129. {
  130. if (m_SerialPort != INVALID_HANDLE_VALUE) {
  131. if (::CloseHandle(m_SerialPort) == FALSE) {
  132. // ASSUME_NOT_REACHED();
  133. }
  134. m_SerialPort = INVALID_HANDLE_VALUE;
  135. }
  136. }
  137. /******************************************************
  138. **
  139. ** SerialDataTransmitter::Initialize()
  140. **
  141. ** returns: TRUE if initialized FALSE if not able to initialize
  142. ** @mfunc Initialize.
  143. **
  144. ******************************************************/
  145. BOOL SerialDataTransmitter::Initialize(DWORD dwDeviceID)
  146. {
  147. // If already open, close for reinitialization
  148. if (m_SerialPort != INVALID_HANDLE_VALUE) {
  149. if (CloseHandle(m_SerialPort) == FALSE) {
  150. // ASSUME_NOT_REACHED();
  151. }
  152. m_SerialPort = INVALID_HANDLE_VALUE;
  153. }
  154. for (unsigned int portNum = 0; portNum < 4; portNum++) {
  155. DebugOut(cCommPortNames[portNum]);
  156. DebugOut(":\r\n");
  157. m_SerialPort = ::CreateFile(cCommPortNames[portNum], GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
  158. if (m_SerialPort != INVALID_HANDLE_VALUE) {
  159. DCB CommDCB;
  160. if (::GetCommState(m_SerialPort, &CommDCB)) {
  161. #ifdef _DEBUG
  162. char dbgout[255];
  163. wsprintf(dbgout, "Baud Rate = 0x%08X (38400 = 0x%08X)\r\n", CommDCB.BaudRate, CBR_38400);
  164. _RPT0(_CRT_WARN, dbgout);
  165. #endif _DEBUG
  166. CommDCB.BaudRate = CBR_38400;
  167. CommDCB.StopBits = ONESTOPBIT;
  168. CommDCB.ByteSize = 8;
  169. CommDCB.Parity = NOPARITY;
  170. if (!::SetCommState(m_SerialPort, &CommDCB)) {
  171. DebugOut("Unabled to set baud rate\r\n");
  172. }
  173. }
  174. ::GetCommState(m_SerialPort, &CommDCB);
  175. if (g_ForceFeedbackDevice.DetectHardware()) {
  176. m_SerialPortIDHack = portNum + 1;
  177. // Write to shared file
  178. DebugOut(" Opened and FFDev Detected\r\n");
  179. break; // Exit from for loop
  180. }
  181. // Not found
  182. ::CloseHandle(m_SerialPort);
  183. DebugOut(" Opened but FFDev NOT detected\r\n");
  184. m_SerialPort = INVALID_HANDLE_VALUE;
  185. } else {
  186. DebugOut(" Not able to open\r\n");
  187. }
  188. }
  189. if (m_SerialPort != INVALID_HANDLE_VALUE) { // Found it
  190. DWORD oldPortID;
  191. DWORD oldAccessMethod;
  192. joyGetForceFeedbackCOMMInterface(dwDeviceID, &oldAccessMethod, &oldPortID);
  193. DWORD accessMethod = (oldAccessMethod & (MASK_OVERRIDE_MIDI_PATH | MASK_SERIAL_BACKDOOR)) | COMM_SERIAL_FILE;
  194. if ((accessMethod != oldAccessMethod) || (portNum != oldPortID)) {
  195. joySetForceFeedbackCOMMInterface(dwDeviceID, accessMethod, portNum);
  196. }
  197. return TRUE;
  198. }
  199. return FALSE;
  200. }
  201. /******************************************************
  202. **
  203. ** SerialDataTransmitter::Send()
  204. **
  205. ** returns: TRUE if all data was successfully sent
  206. ** @mfunc Send.
  207. **
  208. ******************************************************/
  209. BOOL SerialDataTransmitter::Send(BYTE* data, UINT numBytes) const
  210. {
  211. // Do we have a valid serial port (hopefully with MS FF device connected)
  212. if (m_SerialPort == NULL) {
  213. return FALSE;
  214. }
  215. if ((g_ForceFeedbackDevice.GetFirmwareVersionMajor() == 1) && (g_ForceFeedbackDevice.GetFirmwareVersionMinor() == 16)) {
  216. DWORD subTotalWritten;
  217. DWORD totalWritten = 0;
  218. DWORD numLeft = numBytes;
  219. while (numLeft > c1_16_BytesPerShot) {
  220. if (::WriteFile(m_SerialPort, (data + totalWritten), c1_16_BytesPerShot, &subTotalWritten, NULL) == FALSE) {
  221. return FALSE;
  222. }
  223. totalWritten += subTotalWritten;
  224. numLeft -= subTotalWritten;
  225. Sleep(c1_16_SerialSleepTime);
  226. }
  227. if (numLeft > 0) {
  228. if (::WriteFile(m_SerialPort, (data + totalWritten), numLeft, &subTotalWritten, NULL) == FALSE) {
  229. return FALSE;
  230. }
  231. totalWritten += subTotalWritten;
  232. }
  233. return (totalWritten == numBytes);
  234. }
  235. // Firmware other than 1.16
  236. DWORD numWritten;
  237. if (::WriteFile(m_SerialPort, data, numBytes, &numWritten, NULL) == FALSE) {
  238. return FALSE;
  239. }
  240. return (numWritten == numBytes);
  241. }
  242. /****************** WinMMDataTransmitter class ******************/
  243. /******************************************************
  244. **
  245. ** WinMMDataTransmitter::WinMMDataTransmitter()
  246. **
  247. ** @mfunc Constructor.
  248. **
  249. ******************************************************/
  250. WinMMDataTransmitter::WinMMDataTransmitter() : DataTransmitter(),
  251. m_MidiOutHandle(NULL)
  252. {
  253. // Check for callback event
  254. m_EventMidiOutputFinished = OpenEvent(EVENT_ALL_ACCESS, FALSE, SWFF_MIDIEVENT);
  255. if (m_EventMidiOutputFinished == NULL) { // Event not yet created
  256. m_EventMidiOutputFinished = CreateEvent(NULL, TRUE, FALSE, SWFF_MIDIEVENT);
  257. }
  258. }
  259. /******************************************************
  260. **
  261. ** WinMMDataTransmitter::~WinMMDataTransmitter()
  262. **
  263. ** @mfunc Destructor.
  264. **
  265. ******************************************************/
  266. WinMMDataTransmitter::~WinMMDataTransmitter()
  267. {
  268. // Kill MidiOutputEvent
  269. if (m_EventMidiOutputFinished != NULL) {
  270. CloseHandle(m_EventMidiOutputFinished);
  271. m_EventMidiOutputFinished = NULL;
  272. }
  273. // Close MidiHandle -- Check shared memory
  274. if (m_MidiOutHandle != NULL) {
  275. if ((NULL != g_pJoltMidi) && (g_pJoltMidi->GetSharedMemoryReferenceCount() == 0)) { // Just me (reference count has already been lowered for me)
  276. // Reset, close and release Midi Handles
  277. ::midiOutReset(m_MidiOutHandle);
  278. ::midiOutClose(m_MidiOutHandle);
  279. m_MidiOutHandle = NULL;
  280. } else {
  281. DebugOut("SW_WHEEL.DLL: Cannot close midi in use by another process\r\n");
  282. }
  283. }
  284. }
  285. /******************************************************
  286. **
  287. ** WinMMDataTransmitter::Initialize()
  288. **
  289. ** returns: TRUE if initialized FALSE if not able to initialize
  290. ** @mfunc Initialize.
  291. **
  292. ******************************************************/
  293. BOOL WinMMDataTransmitter::Initialize(DWORD dwDeviceID)
  294. {
  295. // Wouldn't want to people initializing at the same time
  296. g_CriticalSection.Enter();
  297. if (NULL == g_pJoltMidi)
  298. {
  299. g_CriticalSection.Leave();
  300. return (FALSE);
  301. }
  302. // Check to see if another task has already opened MidiPort
  303. if (g_pJoltMidi->MidiOutHandleOf() != NULL) {
  304. m_MidiOutHandle = g_pJoltMidi->MidiOutHandleOf();
  305. DebugOut("SW_WHEEL.DLL: Using winmm handle from another process\r\n");
  306. g_CriticalSection.Leave();
  307. return TRUE;
  308. }
  309. try {
  310. UINT numMidiDevices = ::midiOutGetNumDevs();
  311. if (numMidiDevices == 0) {
  312. throw 0; // No devices to check
  313. }
  314. MIDIOUTCAPS midiOutCaps;
  315. for (UINT midiDeviceID = 0; midiDeviceID < numMidiDevices; midiDeviceID++) {
  316. // Get dev-caps
  317. MMRESULT midiRet = ::midiOutGetDevCaps(midiDeviceID, &midiOutCaps, sizeof(midiOutCaps));
  318. if (midiRet != MMSYSERR_NOERROR) {
  319. throw 0; // Something went ugly - All ids should be valid upto numMidiDevs
  320. }
  321. // Midi hardware-port device (thats what we are looking for)
  322. if (midiOutCaps.wTechnology == MOD_MIDIPORT) {
  323. DebugOut("DetectMidiDevice: Opening WinMM Midi Output\n");
  324. // Try to open the thing
  325. UINT openRet = ::midiOutOpen(&m_MidiOutHandle, midiDeviceID, (DWORD) m_EventMidiOutputFinished, (DWORD) this, CALLBACK_EVENT);
  326. // UINT openRet = ::midiOutOpen(&m_MidiOutHandle, midiDeviceID, (DWORD) NULL, (DWORD) this, CALLBACK_EVENT);
  327. if ((openRet != MMSYSERR_NOERROR) || (m_MidiOutHandle == NULL)) {
  328. throw 0; // Unable to open midi handle for midi-device
  329. }
  330. DebugOut("Open Midi Output - Success.\r\n");
  331. if (g_ForceFeedbackDevice.DetectHardware()) {
  332. // Found Microsoft FF hardware - Set all the stuff and return happy
  333. g_pJoltMidi->SetMidiOutHandle(m_MidiOutHandle);
  334. // Tell the Registry WinMM was okay
  335. DWORD oldPortID;
  336. DWORD oldAccessMethod;
  337. joyGetForceFeedbackCOMMInterface(dwDeviceID, &oldAccessMethod, &oldPortID);
  338. DWORD accessMethod = (oldAccessMethod & (MASK_OVERRIDE_MIDI_PATH | MASK_SERIAL_BACKDOOR)) | COMM_WINMM;
  339. if ((accessMethod != oldAccessMethod) || (oldPortID != 0)) {
  340. joySetForceFeedbackCOMMInterface(dwDeviceID, accessMethod, 0);
  341. }
  342. g_CriticalSection.Leave();
  343. return TRUE;
  344. }
  345. // Not what we were looking for - close and continue
  346. ::midiOutClose(m_MidiOutHandle);
  347. m_MidiOutHandle = NULL;
  348. } // End of ModMidiPort found
  349. } // End of for loop
  350. throw 0; // Did not find MS FFDevice
  351. } catch (...) {
  352. m_MidiOutHandle = NULL;
  353. DebugOut("Failure to initlaize WinMMDataTransmitter\r\n");
  354. g_CriticalSection.Leave();
  355. return FALSE;
  356. }
  357. }
  358. /******************************************************
  359. **
  360. ** WinMMDataTransmitter::MakeShortMessage()
  361. **
  362. ** returns: DWORD WinMM MidiShort message
  363. ** @mfunc MakeShortMessage.
  364. **
  365. ******************************************************/
  366. DWORD WinMMDataTransmitter::MakeShortMessage(BYTE* data, UINT numBytes) const
  367. {
  368. DWORD shortMessage = data[0];
  369. if (numBytes > 1) {
  370. shortMessage |= (data[1] << 8);
  371. if (numBytes < 2) {
  372. shortMessage |= (data[2] << 16);
  373. }
  374. }
  375. return shortMessage;
  376. }
  377. /******************************************************
  378. **
  379. ** WinMMDataTransmitter::MakeLongMessageHeader()
  380. **
  381. ** returns: SUCCESS indication and WinMM MidiLong message header
  382. ** @mfunc MakeLongMessageHeader.
  383. **
  384. ******************************************************/
  385. BOOL WinMMDataTransmitter::MakeLongMessageHeader(MIDIHDR& longHeader, BYTE* data, UINT numBytes) const
  386. {
  387. longHeader.lpData = LPSTR(data);
  388. longHeader.dwBufferLength = numBytes;
  389. longHeader.dwBytesRecorded = numBytes;
  390. longHeader.dwFlags = 0;
  391. longHeader.dwUser = 0;
  392. longHeader.dwOffset = 0;
  393. return (::midiOutPrepareHeader(m_MidiOutHandle, &longHeader, sizeof(MIDIHDR)) == MMSYSERR_NOERROR);
  394. }
  395. /******************************************************
  396. **
  397. ** WinMMDataTransmitter::DestroyLongMessageHeader()
  398. **
  399. ** returns: TRUE if header was unprepared
  400. ** @mfunc DestroyLongMessageHeader.
  401. **
  402. ******************************************************/
  403. BOOL WinMMDataTransmitter::DestroyLongMessageHeader(MIDIHDR& longHeader) const
  404. {
  405. return (::midiOutUnprepareHeader(m_MidiOutHandle, &longHeader, sizeof(MIDIHDR)) == MMSYSERR_NOERROR);
  406. }
  407. /******************************************************
  408. **
  409. ** WinMMDataTransmitter::Send()
  410. **
  411. ** returns: TRUE if all data was successfully sent
  412. ** @mfunc Send.
  413. **
  414. ******************************************************/
  415. BOOL WinMMDataTransmitter::Send(BYTE* data, UINT numBytes) const
  416. {
  417. // Do we have a valid midi port (hopefully with MS FF device connected)
  418. if (m_MidiOutHandle == NULL) {
  419. return FALSE;
  420. }
  421. // Sanity check
  422. if ((data == NULL) || (numBytes == 0)) {
  423. return FALSE;
  424. }
  425. // Clear the Event Callback
  426. ::ResetEvent(m_EventMidiOutputFinished);
  427. // Short message
  428. if (data[0] < 0xF0) {
  429. DWORD shortMessage = MakeShortMessage(data, numBytes);
  430. return (::midiOutShortMsg(m_MidiOutHandle, shortMessage) == MMSYSERR_NOERROR);
  431. }
  432. // Long message
  433. BOOL retVal = FALSE;
  434. MIDIHDR midiHeader;
  435. if (MakeLongMessageHeader(midiHeader, data, numBytes)) {
  436. retVal = (::midiOutLongMsg(m_MidiOutHandle, &midiHeader, sizeof(MIDIHDR)) == MMSYSERR_NOERROR);
  437. DestroyLongMessageHeader(midiHeader);
  438. if (retVal == FALSE) { // Didn't work, kick it
  439. ::midiOutReset(m_MidiOutHandle);
  440. }
  441. }
  442. return retVal;
  443. }
  444. /******************************************************
  445. **
  446. ** WinMMDataTransmitter::WaitTillSendFinished()
  447. **
  448. ** returns: TRUE when all data is successfully sent or
  449. ** FALSE for timeOut
  450. ** @mfunc Send.
  451. **
  452. ******************************************************/
  453. BOOL WinMMDataTransmitter::WaitTillSendFinished(DWORD timeOut)
  454. {
  455. BOOL retVal = FALSE;
  456. if (m_EventMidiOutputFinished != NULL) {
  457. retVal = (::WaitForSingleObject(m_EventMidiOutputFinished, timeOut) == WAIT_OBJECT_0);
  458. ::ResetEvent(m_EventMidiOutputFinished);
  459. }
  460. return retVal;
  461. }
  462. /****************** BackdoorDataTransmitter class ***************/
  463. /******************************************************
  464. **
  465. ** BackdoorDataTransmitter::BackdoorDataTransmitter()
  466. **
  467. ** @mfunc Constructor.
  468. **
  469. ******************************************************/
  470. BackdoorDataTransmitter::BackdoorDataTransmitter() : DataTransmitter(),
  471. m_DataPort(INVALID_HANDLE_VALUE)
  472. {
  473. m_OldBackdoor = (g_ForceFeedbackDevice.GetDriverVersionMajor() == 1) && (g_ForceFeedbackDevice.GetDriverVersionMinor() == 0);
  474. }
  475. /******************************************************
  476. **
  477. ** BackdoorDataTransmitter::~BackdoorDataTransmitter()
  478. **
  479. ** @mfunc Destructor.
  480. **
  481. ******************************************************/
  482. BackdoorDataTransmitter::~BackdoorDataTransmitter()
  483. {
  484. if (m_DataPort != INVALID_HANDLE_VALUE) {
  485. if (::CloseHandle(m_DataPort) == FALSE) {
  486. // ASSUME_NOT_REACHED();
  487. }
  488. m_DataPort = INVALID_HANDLE_VALUE;
  489. }
  490. }
  491. /******************************************************
  492. **
  493. ** BackdoorDataTransmitter::Initialize()
  494. **
  495. ** returns: This base class only does error checking on preset values
  496. ** @mfunc Initialize.
  497. **
  498. ******************************************************/
  499. BOOL BackdoorDataTransmitter::Initialize(DWORD dwDeviceID)
  500. {
  501. if (g_ForceFeedbackDevice.IsOSNT5()) {
  502. return FALSE; // NT5 cannot use backdoor!
  503. }
  504. return TRUE;
  505. }
  506. /******************************************************
  507. **
  508. ** BackdoorDataTransmitter::Send()
  509. **
  510. ** returns: TRUE if all data was successfully sent
  511. ** @mfunc Send.
  512. **
  513. ******************************************************/
  514. BOOL BackdoorDataTransmitter::Send(BYTE* pData, UINT numBytes) const
  515. {
  516. // Do we have a valid serial port (hopefully with MS FF device connected)
  517. if (m_DataPort == NULL) {
  518. return FALSE;
  519. }
  520. return SUCCEEDED(g_pDriverCommunicator->SendBackdoor(pData, numBytes));
  521. }
  522. /****************** SerialBackdoorDataTransmitter class ***************/
  523. /******************************************************
  524. **
  525. ** SerialBackdoorDataTransmitter::SerialBackdoorDataTransmitter()
  526. **
  527. ** @mfunc Constructor.
  528. **
  529. ******************************************************/
  530. SerialBackdoorDataTransmitter::SerialBackdoorDataTransmitter() : BackdoorDataTransmitter()
  531. {
  532. }
  533. /******************************************************
  534. **
  535. ** SerialBackdoorDataTransmitter::Initialize()
  536. **
  537. ** returns: TRUE if initialized FALSE if not able to initialize
  538. ** @mfunc Initialize.
  539. **
  540. ******************************************************/
  541. BOOL SerialBackdoorDataTransmitter::Initialize(DWORD dwDeviceID)
  542. {
  543. if (!BackdoorDataTransmitter::Initialize(dwDeviceID)) {
  544. return FALSE;
  545. }
  546. SerialDataTransmitter serialFrontDoor;
  547. // This is funky
  548. if (g_pDataTransmitter == NULL) {
  549. ASSUME_NOT_REACHED();
  550. return FALSE;
  551. }
  552. g_pDataTransmitter = &serialFrontDoor;
  553. if (serialFrontDoor.Initialize(dwDeviceID)) {
  554. m_DataPort = HANDLE(serialFrontDoor.GetSerialPortHack());
  555. if (g_pDriverCommunicator->SetBackdoorPort(ULONG(m_DataPort)) == SUCCESS) {
  556. serialFrontDoor.StopAutoClose();
  557. DWORD oldPortID, oldAccessMethod;
  558. joyGetForceFeedbackCOMMInterface(dwDeviceID, &oldAccessMethod, &oldPortID);
  559. DWORD accessMethod = (oldAccessMethod & (MASK_OVERRIDE_MIDI_PATH | MASK_SERIAL_BACKDOOR)) | COMM_SERIAL_BACKDOOR;
  560. joySetForceFeedbackCOMMInterface(dwDeviceID, accessMethod, oldPortID);
  561. g_pDataTransmitter = this;
  562. return TRUE;
  563. }
  564. }
  565. g_pDataTransmitter = this;
  566. return FALSE;
  567. }
  568. /****************** MidiBackdoorDataTransmitter class ***************/
  569. /******************************************************
  570. **
  571. ** MidiBackdoorDataTransmitter::MidiBackdoorDataTransmitter()
  572. **
  573. ** @mfunc Constructor.
  574. **
  575. ******************************************************/
  576. MidiBackdoorDataTransmitter::MidiBackdoorDataTransmitter() : BackdoorDataTransmitter()
  577. {
  578. }
  579. /******************************************************
  580. **
  581. ** MidiBackdoorDataTransmitter::~MidiBackdoorDataTransmitter()
  582. **
  583. ** @mfunc Destructor.
  584. **
  585. ******************************************************/
  586. MidiBackdoorDataTransmitter::~MidiBackdoorDataTransmitter()
  587. {
  588. m_DataPort = NULL; // Prevent attempt to ::CloseHandle(m_DataPort)
  589. }
  590. /******************************************************
  591. **
  592. ** MidiBackdoorDataTransmitter::Initialize()
  593. **
  594. ** returns: TRUE if initialized FALSE if not able to initialize
  595. ** @mfunc Initialize.
  596. **
  597. ******************************************************/
  598. BOOL MidiBackdoorDataTransmitter::Initialize(DWORD dwDeviceID)
  599. {
  600. if (!BackdoorDataTransmitter::Initialize(dwDeviceID)) {
  601. return FALSE;
  602. }
  603. if (midiOutGetNumDevs() == 0) {
  604. return FALSE; // No midi-devices backdoor check is worthless
  605. }
  606. // Valid MIDI ports table for backdoor - ordered by probability of working
  607. DWORD midiPorts[] = {0x330, 0x300, 0x320, 0x340, 0x310, 0x350, 0x360, 0x370, 0x380, 0x390, 0x3a0, 0x3b0, 0x3c0, 0x3d0, 0x3e0, 0x3f0};
  608. int numMidiPorts = sizeof(midiPorts)/sizeof(DWORD);
  609. m_DataPort = NULL;
  610. for (int i=0; i < numMidiPorts; i++) {
  611. #ifdef _DEBUG
  612. char buff[256];
  613. wsprintf(buff, "MidiBackdoorDataTransmitter::Initialize(): Midi Port:%lx - ", midiPorts[i]);
  614. DebugOut(buff);
  615. #endif
  616. // We have the Port #, Let's see if Jolt is out there
  617. m_DataPort = HANDLE(midiPorts[i]);
  618. if (g_pDriverCommunicator->SetBackdoorPort(ULONG(m_DataPort)) == SUCCESS) {
  619. if (g_ForceFeedbackDevice.DetectHardware()) {
  620. DebugOut(" Success!\n");
  621. DWORD oldPortID;
  622. DWORD oldAccessMethod;
  623. joyGetForceFeedbackCOMMInterface(dwDeviceID, &oldAccessMethod, &oldPortID);
  624. DWORD accessMethod = (oldAccessMethod & (MASK_OVERRIDE_MIDI_PATH | MASK_SERIAL_BACKDOOR)) | COMM_MIDI_BACKDOOR;
  625. if ((accessMethod != oldAccessMethod) || (ULONG(m_DataPort) != oldPortID)) {
  626. joySetForceFeedbackCOMMInterface(dwDeviceID, accessMethod, ULONG(m_DataPort));
  627. }
  628. // joySetForceFeedbackCOMMInterface(0, COMM_MIDI_BACKDOOR, ULONG(m_DataPort));
  629. return TRUE;
  630. } else {
  631. m_DataPort = NULL;
  632. DebugOut(" No Answer\n");
  633. }
  634. }
  635. }
  636. // If we have fallen through we have failed
  637. return FALSE;
  638. }
  639. /******************************************************
  640. **
  641. ** MidiBackdoorDataTransmitter::InitializeSpecific(HANDLE specificHandle)
  642. **
  643. ** returns: TRUE if initialized FALSE if not able to initialize
  644. ** @mfunc Initialize.
  645. **
  646. ******************************************************/
  647. BOOL MidiBackdoorDataTransmitter::InitializeSpecific(DWORD dwDeviceID, HANDLE specificHandle)
  648. {
  649. if (!BackdoorDataTransmitter::Initialize(dwDeviceID)) {
  650. return FALSE;
  651. }
  652. if (midiOutGetNumDevs() == 0) {
  653. return FALSE; // No midi-devices backdoor check is worthless
  654. }
  655. m_DataPort = NULL;
  656. // We have the Port #, Let's see if Jolt is out there
  657. if (g_pDriverCommunicator->SetBackdoorPort(ULONG(specificHandle) == SUCCESS)) {
  658. if (g_ForceFeedbackDevice.DetectHardware()) {
  659. m_DataPort = specificHandle;
  660. // No need to set registry the registry is what brought us here
  661. return TRUE;
  662. }
  663. }
  664. // If we have fallen through we have failed
  665. return FALSE;
  666. }
  667. #if 0
  668. /************************** PinTransmitter Class ******************************/
  669. /******************************************************
  670. **
  671. ** PinTransmitter::PinTransmitter()
  672. **
  673. ** @mfunc Constructor.
  674. **
  675. ******************************************************/
  676. PinTransmitter::PinTransmitter() : DataTransmitter(),
  677. m_UartFilter(INVALID_HANDLE_VALUE),
  678. m_MidiPin(INVALID_HANDLE_VALUE),
  679. m_MidiOutEvent(INVALID_HANDLE_VALUE)
  680. {
  681. }
  682. /******************************************************
  683. **
  684. ** PinTransmitter::~PinTransmitter()
  685. **
  686. ** @mfunc Destructor.
  687. **
  688. ******************************************************/
  689. PinTransmitter::~PinTransmitter()
  690. {
  691. // Close the send event
  692. if (IsHandleValid(m_MidiOutEvent)) {
  693. ::CloseHandle(m_MidiOutEvent);
  694. m_MidiOutEvent = NULL;
  695. }
  696. // Close the pin
  697. if (IsHandleValid(m_MidiPin)) {
  698. ::CloseHandle(m_MidiPin);
  699. m_MidiPin = INVALID_HANDLE_VALUE;
  700. }
  701. // Close the Uart
  702. if (IsHandleValid(m_UartFilter)) {
  703. ::CloseHandle(m_UartFilter);
  704. m_UartFilter = INVALID_HANDLE_VALUE;
  705. }
  706. }
  707. /******************************************************
  708. **
  709. ** PinTransmitter::Initialize()
  710. **
  711. ** returns: TRUE if initialized FALSE if not able to initialize
  712. ** @mfunc Initialize.
  713. **
  714. ******************************************************/
  715. BOOL PinTransmitter::Initialize()
  716. {
  717. // Load the ksUserLibrary and grab the create pin function
  718. HINSTANCE ksUserLib = ::LoadLibrary(TEXT("KsUser.dll"));
  719. if (ksUserLib == NULL) {
  720. return FALSE;
  721. }
  722. KSCREATEPIN pfCreatePin = (KSCREATEPIN)::GetProcAddress(ksUserLib, TEXT("KsCreatePin"));
  723. if (pfCreatePin == NULL) {
  724. ::FreeLibrary(ksUserLib);
  725. return FALSE;
  726. }
  727. // Open the Uart
  728. m_UartFilter = ::CreateFile(UART_FILTER_NAME, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING,
  729. FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, NULL);
  730. if (m_UartFilter == INVALID_HANDLE_VALUE) {
  731. ::FreeLibrary(ksUserLib);
  732. return FALSE;
  733. }
  734. // Create Overlapped event
  735. OVERLAPPED overlapped;
  736. ::memset(&overlapped, 0, sizeof(overlapped));
  737. overlapped.hEvent = ::CreateEvent(NULL, FALSE, FALSE, NULL);
  738. // Get the number of pins
  739. KSP_PIN ksPinProp;
  740. ::memset(&ksPinProp, 0, sizeof(ksPinProp));
  741. ksPinProp.Property.Set = KSPROPSETID_Pin;
  742. ksPinProp.Property.Id = KSPROPERTY_PIN_CTYPES;
  743. ksPinProp.Property.Flags = KSPROPERTY_TYPE_GET;
  744. DWORD numPins = 0;
  745. OverLappedPinIOCTL(overlapped, ksPinProp, &numPins, sizeof(numPins));
  746. // Check each pin for proper type, then try to create
  747. BOOL wasCreated = FALSE;
  748. for (UINT pinNum = 0; (pinNum < numPins) && (wasCreated == FALSE); pinNum++) {
  749. ksPinProp.PinId = pinNum;
  750. ksPinProp.Property.Id = KSPROPERTY_PIN_DATAFLOW;
  751. KSPIN_DATAFLOW dataFlow = (KSPIN_DATAFLOW)0;
  752. if (OverLappedPinIOCTL(overlapped, ksPinProp, &dataFlow, sizeof(dataFlow)) == TRUE) {
  753. if (dataFlow == KSPIN_DATAFLOW_IN) {
  754. ksPinProp.Property.Id = KSPROPERTY_PIN_COMMUNICATION;
  755. KSPIN_COMMUNICATION communication = KSPIN_COMMUNICATION_NONE;
  756. if (OverLappedPinIOCTL(overlapped, ksPinProp, &communication, sizeof(communication)) == TRUE) {
  757. if ((communication == KSPIN_COMMUNICATION_SINK) || (communication == KSPIN_COMMUNICATION_BOTH)) {
  758. wasCreated = CreatePinInstance(pinNum, pfCreatePin);
  759. }
  760. }
  761. }
  762. }
  763. }
  764. ::FreeLibrary(ksUserLib);
  765. ::CloseHandle(overlapped.hEvent);
  766. if (wasCreated == FALSE) {
  767. ::CloseHandle(m_UartFilter);
  768. m_UartFilter = INVALID_HANDLE_VALUE;
  769. return FALSE;
  770. }
  771. return TRUE;
  772. }
  773. /******************************************************
  774. **
  775. ** PinTransmitter::OverLappedPinIOCTL()
  776. **
  777. ** returns: TRUE if able to proform Pin Property IOCTL
  778. ** @mfunc OverLappedPinIOCTL.
  779. ******************************************************/
  780. BOOL PinTransmitter::OverLappedPinIOCTL(OVERLAPPED overlapped, KSP_PIN ksPinProp, void* pData, DWORD dataSize)
  781. {
  782. // IOCTL the Property
  783. if (::DeviceIoControl(m_UartFilter, IOCTL_KS_PROPERTY, &ksPinProp, sizeof(ksPinProp), pData, dataSize, NULL, &overlapped) == TRUE) {
  784. return TRUE;
  785. }
  786. // Failed IOCTL check if more time is needed
  787. if (::GetLastError() != ERROR_IO_PENDING) {
  788. return FALSE;
  789. }
  790. // Do wait
  791. if (::WaitForSingleObject(overlapped.hEvent, 3000) == WAIT_OBJECT_0) {
  792. return TRUE; // Waiting paid off
  793. }
  794. return FALSE; // Grew tired of waiting
  795. }
  796. /******************************************************
  797. **
  798. ** PinTransmitter::CreatePinInstance()
  799. **
  800. ** returns: TRUE if able to create the requested pin instance
  801. ** @mfunc CreatePinInstance.
  802. ******************************************************/
  803. BOOL PinTransmitter::CreatePinInstance(UINT pinNumber, KSCREATEPIN pfCreatePin)
  804. {
  805. // Set the pin format
  806. KSDATAFORMAT ksDataFormat;
  807. ::memset(&ksDataFormat, 0, sizeof(ksDataFormat));
  808. ksDataFormat.FormatSize = sizeof(ksDataFormat);
  809. ksDataFormat.MajorFormat = KSDATAFORMAT_TYPE_MUSIC;
  810. ksDataFormat.SubFormat = KSDATAFORMAT_SUBTYPE_MIDI;
  811. ksDataFormat.Specifier = KSDATAFORMAT_SPECIFIER_NONE;
  812. // Set the pin connection information
  813. KSPIN_CONNECT* pConnectionInfo = (KSPIN_CONNECT*) new BYTE[sizeof(KSPIN_CONNECT) + sizeof(ksDataFormat)];
  814. ::memset(pConnectionInfo, 0, sizeof(KSPIN_CONNECT));
  815. pConnectionInfo->Interface.Set = KSINTERFACESETID_Standard;
  816. pConnectionInfo->Interface.Id = KSINTERFACE_STANDARD_STREAMING;
  817. pConnectionInfo->Medium.Set = KSMEDIUMSETID_Standard;
  818. pConnectionInfo->Medium.Id = KSMEDIUM_STANDARD_DEVIO;
  819. pConnectionInfo->PinId = pinNumber;
  820. pConnectionInfo->Priority.PriorityClass = KSPRIORITY_NORMAL;
  821. pConnectionInfo->Priority.PrioritySubClass = 1;
  822. ::memcpy(pConnectionInfo + 1, &ksDataFormat, sizeof(ksDataFormat));
  823. DWORD status = pfCreatePin(m_UartFilter, pConnectionInfo, FILE_WRITE_ACCESS, &m_MidiPin);
  824. delete[] pConnectionInfo;
  825. if (status != NO_ERROR) {
  826. #ifdef _DEBUG
  827. TCHAR buff[256];
  828. wsprintf(buff, TEXT("Error Creating Pin: 0x%08X\r\n"), status);
  829. _RPT0(_CRT_WARN, buff);
  830. #endif
  831. return FALSE;
  832. }
  833. SetPinState(KSSTATE_PAUSE);
  834. return TRUE;
  835. }
  836. /******************************************************
  837. **
  838. ** PinTransmitter::Send()
  839. **
  840. ** returns: TRUE if all data was successfully sent
  841. ** @mfunc Send.
  842. **
  843. ******************************************************/
  844. BOOL PinTransmitter::Send(BYTE* pData, UINT numBytes)
  845. {
  846. if (!IsHandleValid(m_MidiPin)) {
  847. return FALSE;
  848. }
  849. BYTE musicData[c_LongMsgMax + sizeof(KSMUSICFORMAT)];
  850. ::memset(musicData, 0, sizeof(musicData));
  851. ((KSMUSICFORMAT*)musicData)->ByteCount = numBytes;
  852. ::memcpy(((KSMUSICFORMAT*)musicData) + 1, pData, numBytes);
  853. KSSTREAM_HEADER ksStreamHeader;
  854. ::memset(&ksStreamHeader, 0, sizeof(ksStreamHeader));
  855. ksStreamHeader.Size = sizeof(ksStreamHeader);
  856. ksStreamHeader.PresentationTime.Numerator = 1;
  857. ksStreamHeader.PresentationTime.Denominator = 1;
  858. ksStreamHeader.FrameExtent = sizeof(musicData);
  859. ksStreamHeader.DataUsed = sizeof KSMUSICFORMAT + numBytes;
  860. ksStreamHeader.Data = (void*)musicData;
  861. if (!IsHandleValid(m_MidiOutEvent)) {
  862. m_MidiOutEvent = ::CreateEvent(NULL, FALSE, FALSE, NULL);
  863. }
  864. OVERLAPPED overlapped;
  865. ::memset(&overlapped, 0, sizeof(overlapped));
  866. overlapped.hEvent = m_MidiOutEvent;
  867. SetPinState(KSSTATE_RUN);
  868. if (!DeviceIoControl(m_MidiPin, IOCTL_KS_WRITE_STREAM, NULL, 0,
  869. &ksStreamHeader, sizeof(ksStreamHeader), NULL, &overlapped)) {
  870. if (GetLastError() == ERROR_IO_PENDING) {
  871. ::WaitForSingleObject(overlapped.hEvent, 3000);
  872. }
  873. }
  874. SetPinState(KSSTATE_PAUSE);
  875. return TRUE;
  876. }
  877. /******************************************************
  878. **
  879. ** PinTransmitter::SetPinState()
  880. **
  881. ** returns: Nothing
  882. ** @mfunc SetPinState.
  883. **
  884. ******************************************************/
  885. void PinTransmitter::SetPinState(KSSTATE state)
  886. {
  887. if (!IsHandleValid(m_MidiPin)) {
  888. return;
  889. }
  890. KSPROPERTY ksProperty;
  891. ::memset(&ksProperty, 0, sizeof(ksProperty));
  892. ksProperty.Set = KSPROPSETID_Connection;
  893. ksProperty.Id = KSPROPERTY_CONNECTION_STATE;
  894. ksProperty.Flags = KSPROPERTY_TYPE_SET;
  895. OVERLAPPED overlapped;
  896. ::memset(&overlapped, 0, sizeof(overlapped));
  897. overlapped.hEvent = ::CreateEvent(NULL, FALSE, FALSE, NULL);
  898. if (IsHandleValid(overlapped.hEvent)) {
  899. if( !DeviceIoControl(m_MidiPin, IOCTL_KS_PROPERTY, &ksProperty, sizeof ksProperty, &state, sizeof state, NULL, &overlapped )) {
  900. if (GetLastError() == ERROR_IO_PENDING) {
  901. WaitForSingleObject(overlapped.hEvent, 30000);
  902. }
  903. }
  904. ::CloseHandle(overlapped.hEvent);
  905. }
  906. }
  907. #endif