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.

347 lines
9.6 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. 21-Mar-99 waltw Nuked VxDCommunicator, this is NT5 only!
  20. 21-Mar-99 waltw Nuked unused IsHandleValid
  21. 23-Mar-99 waltw Nuked GetStatusGateData (old Jolt code)
  22. ****************************************************************************/
  23. #include "vxdioctl.hpp"
  24. //#include <crtdbg.h> // For RPT macros
  25. #include <WINIOCTL.H> // For IOCTL definitions (CTL_CODE)
  26. #include "FFDevice.h" // For g_ForceFeedbackDevice
  27. #include "sw_error.hpp" // For Sidewinder HRESULT Error codes
  28. #include "hau_midi.hpp" // For MAX_RETRY_COUNT and others
  29. #include "midi_obj.hpp" // Global Jolt midi object and definition
  30. #include "JoyRegst.hpp" // The differnt types of ACK_NACK
  31. #include "DTrans.h" // For global Data Transmitter
  32. DriverCommunicator* g_pDriverCommunicator = NULL;
  33. extern DataTransmitter* g_pDataTransmitter;
  34. extern HINSTANCE g_MyInstance;
  35. extern CJoltMidi* g_pJoltMidi;
  36. // Bitmasks for FW Version
  37. #define FW_MAJOR_VERSION 0xFF00 // wheel
  38. #define FW_MINOR_VERSION 0x00FF // wheel
  39. //#define FW_MAJOR_VERSION 0x40 // Bit 6 Jolt
  40. //#define FW_MINOR_VERSION 0x3F // Bit 5-0 Jolt
  41. #define FW_PRODUCT_ID 0xff
  42. /********************************** HIDFeatureCommunicator class ***********************************/
  43. /****************************************
  44. **
  45. ** HIDFeatureCommunicator::HIDFeatureCommunicator()
  46. **
  47. ** @mfunc Constructor for VxD Communications path
  48. **
  49. *****************************************/
  50. HIDFeatureCommunicator::HIDFeatureCommunicator() :
  51. DriverCommunicator(),
  52. m_ForceFeature()
  53. {
  54. }
  55. /****************************************
  56. **
  57. ** HIDFeatureCommunicator::~HIDFeatureCommunicator()
  58. **
  59. ** @mfunc Destructor for VxD communications path
  60. **
  61. *****************************************/
  62. HIDFeatureCommunicator::~HIDFeatureCommunicator()
  63. {
  64. }
  65. /****************************************
  66. **
  67. ** BOOL HIDFeatureCommunicator::Initialize(UINT uJoystickId)
  68. **
  69. ** @mfunc Opens the driver for communications via IOCTLs
  70. **
  71. ** @rdesc TRUE if driver opened, FALSE otherwise
  72. **
  73. *****************************************/
  74. BOOL HIDFeatureCommunicator::Initialize
  75. (
  76. UINT uJoystickId //@parm Joystick ID to use
  77. )
  78. {
  79. if (g_ForceFeedbackDevice.IsOSNT5() == FALSE)
  80. { // Only allowable on NT5
  81. return FALSE;
  82. }
  83. return (SUCCEEDED(m_ForceFeature.Initialize(uJoystickId, g_MyInstance)));
  84. }
  85. /****************************************
  86. **
  87. ** BOOL HIDFeatureCommunicator::ResetDevice()
  88. **
  89. ** @mfunc Sends the driver a device reset IOCTL
  90. **
  91. ** @rdesc S_OK if IOCTL suceeds,
  92. **
  93. *****************************************/
  94. HRESULT HIDFeatureCommunicator::ResetDevice()
  95. {
  96. return m_ForceFeature.DoReset();
  97. }
  98. /****************************************
  99. **
  100. ** HRESULT HIDFeatureCommunicator::GetDriverVersion(DWORD& rdwMajor, DWORD& rdwMinor)
  101. **
  102. ** @mfunc IOCTLs a version request
  103. **
  104. ** @rdesc S_OK on success E_FAIL if driver not initialized
  105. **
  106. *****************************************/
  107. HRESULT HIDFeatureCommunicator::GetDriverVersion
  108. (
  109. DWORD& rdwMajor, //@parm reference to returned major part of version
  110. DWORD& rdwMinor //@parm reference to returned minor part of version
  111. )
  112. {
  113. ULONG ulVersion = m_ForceFeature.GetVersion();
  114. rdwMajor = (ulVersion >> 16) & 0x0000FFFF;
  115. rdwMinor = ulVersion & 0x0000FFFF;
  116. return S_OK;
  117. }
  118. /****************************************
  119. **
  120. ** HRESULT HIDFeatureCommunicator::GetID(LOCAL_PRODUCT_ID& rProductID)
  121. **
  122. ** @mfunc IOCTLs a product id request
  123. **
  124. ** @rdesc S_OK on success E_FAIL if driver not initialized
  125. **
  126. *****************************************/
  127. HRESULT HIDFeatureCommunicator::GetID
  128. (
  129. LOCAL_PRODUCT_ID& rProductID //@parm reference to local product id structure for return value
  130. )
  131. {
  132. if (rProductID.cBytes != sizeof LOCAL_PRODUCT_ID)
  133. { // structure size is invalid
  134. return SFERR_INVALID_STRUCT_SIZE;
  135. }
  136. // Create report packet and request
  137. PRODUCT_ID_REPORT productIDReport;
  138. productIDReport.ProductId.cBytes = sizeof PRODUCT_ID;
  139. HRESULT hr = m_ForceFeature.GetId(productIDReport);
  140. if (FAILED(hr))
  141. { // There was a problem
  142. return hr;
  143. }
  144. // Decode to local packet
  145. rProductID.dwProductID = productIDReport.ProductId.dwProductID & FW_PRODUCT_ID;
  146. rProductID.dwFWMajVersion = 1;
  147. if (productIDReport.ProductId.dwFWVersion & FW_MAJOR_VERSION)
  148. {
  149. rProductID.dwFWMajVersion++;
  150. }
  151. rProductID.dwFWMinVersion = productIDReport.ProductId.dwFWVersion & FW_MINOR_VERSION;
  152. return S_OK;
  153. }
  154. /****************************************
  155. **
  156. ** HRESULT HIDFeatureCommunicator::GetPortByte(ULONG& portByte)
  157. **
  158. ** @mfunc IOCTLs a request for the port byte
  159. **
  160. ** @rdesc S_OK on success E_FAIL if driver not initialized
  161. **
  162. *****************************************/
  163. HRESULT HIDFeatureCommunicator::GetPortByte
  164. (
  165. ULONG& portByte //@parm reference to byte return value for port data
  166. )
  167. {
  168. ULONG_REPORT report;
  169. HRESULT hr = m_ForceFeature.GetSync(report);
  170. portByte = report.uLong;
  171. return hr;
  172. }
  173. /****************************************
  174. **
  175. ** HRESULT HIDFeatureCommunicator::GetStatus(JOYCHANNELSTATUS& rChannelStatus)
  176. **
  177. ** @mfunc IOCTLs a status request
  178. **
  179. ** @rdesc S_OK on success E_FAIL if driver not initialized
  180. **
  181. *****************************************/
  182. HRESULT HIDFeatureCommunicator::GetStatus
  183. (
  184. JOYCHANNELSTATUS& rChannelStatus //@parm reference to status packet for result
  185. )
  186. {
  187. if (rChannelStatus.cBytes != sizeof JOYCHANNELSTATUS)
  188. { // structure size is invalid
  189. return SFERR_INVALID_STRUCT_SIZE;
  190. }
  191. if (NULL == g_pJoltMidi) return (SFERR_DRIVER_ERROR);
  192. // Create report packet and perform request
  193. JOYCHANNELSTATUS_REPORT statusReport;
  194. statusReport.JoyChannelStatus.cBytes = sizeof JOYCHANNELSTATUS;
  195. HRESULT hr = S_OK;
  196. for (int i=0; i < MAX_GET_STATUS_PACKET_RETRY_COUNT; i++) {
  197. Sleep(g_pJoltMidi->DelayParamsPtrOf()->dwGetStatusPacketDelay);
  198. hr = m_ForceFeature.GetStatus(statusReport);
  199. if (FAILED(hr))
  200. { // There was a problem
  201. if (i > 5)
  202. {
  203. Sleep(1);
  204. }
  205. }
  206. else
  207. {
  208. break;
  209. }
  210. }
  211. if (SUCCEEDED(hr))
  212. { // Get the data from report packet
  213. ::memcpy(g_ForceFeedbackDevice.GetLastStatusPacket(), &(statusReport.JoyChannelStatus), sizeof(JOYCHANNELSTATUS));
  214. ::memcpy(&rChannelStatus, &(statusReport.JoyChannelStatus), sizeof JOYCHANNELSTATUS);
  215. }
  216. return hr;
  217. }
  218. /****************************************
  219. **
  220. ** HRESULT HIDFeatureCommunicator::GetAckNack(ACKNACK& rAckNack, USHORT usRegIndex)
  221. **
  222. ** @mfunc IOCTLs a status request
  223. **
  224. ** @rdesc S_OK on success E_FAIL if driver not initialized
  225. **
  226. *****************************************/
  227. HRESULT HIDFeatureCommunicator::GetAckNack
  228. (
  229. ACKNACK& rAckNack, //@parm Structure for return of acking
  230. USHORT usRegIndex //@parm Index to what type of ack/nack to do
  231. )
  232. {
  233. if (rAckNack.cBytes != sizeof ACKNACK)
  234. { // Invalid structure size
  235. return SFERR_INVALID_STRUCT_SIZE;
  236. }
  237. // Determine how to get the result
  238. switch (g_ForceFeedbackDevice.GetAckNackMethod(usRegIndex))
  239. {
  240. case ACKNACK_NOTHING:
  241. { // This one is real easy - do nothing
  242. rAckNack.dwAckNack = ACK;
  243. rAckNack.dwErrorCode = 0;
  244. return S_OK;
  245. }
  246. case ACKNACK_BUTTONSTATUS:
  247. { // Look at the button status (status gate)
  248. ULONG_REPORT report;
  249. report.uLong = 0L;
  250. HRESULT hr = S_OK;
  251. if (g_pDataTransmitter && g_pDataTransmitter->NackToggle())
  252. {
  253. hr = m_ForceFeature.GetNakAck(report);
  254. }
  255. else
  256. {
  257. hr = m_ForceFeature.GetAckNak(report);
  258. }
  259. if (FAILED(hr))
  260. { // There was a problem
  261. return hr;
  262. }
  263. #if 0
  264. // NT5 driver doesn't touch report.uLong on failure (returns above)
  265. if (report.uLong & ACKNACK_MASK_200)
  266. { // NACK error, so get Error code
  267. rAckNack.dwAckNack = NACK;
  268. JOYCHANNELSTATUS statusPacket = { sizeof JOYCHANNELSTATUS };
  269. if (FAILED(hr = GetStatus(statusPacket)))
  270. { // Failed to get status error
  271. return hr;
  272. }
  273. rAckNack.dwErrorCode = (statusPacket.dwDeviceStatus & ERROR_STATUS_MASK);
  274. return S_OK;
  275. }
  276. #endif
  277. // ACK success
  278. rAckNack.dwAckNack = ACK;
  279. rAckNack.dwErrorCode = 0;
  280. if (report.uLong & RUNNING_MASK_200)
  281. { // Current driver and effect running
  282. rAckNack.dwEffectStatus = SWDEV_STS_EFFECT_RUNNING;
  283. }
  284. else
  285. { // Effect not running
  286. rAckNack.dwEffectStatus = SWDEV_STS_EFFECT_STOPPED;
  287. }
  288. return S_OK;
  289. }
  290. case ACKNACK_STATUSPACKET:
  291. { // Use the Status Packet Error code field to determine ACK or NACK and Get Error code
  292. JOYCHANNELSTATUS statusPacket = { sizeof JOYCHANNELSTATUS };
  293. HRESULT hr = GetStatus(statusPacket);
  294. if (FAILED(hr))
  295. { // Failed (retried inside GetStatus)
  296. return SFERR_DRIVER_ERROR;
  297. }
  298. rAckNack.dwErrorCode = statusPacket.dwDeviceStatus & ERROR_STATUS_MASK;
  299. rAckNack.dwAckNack = (rAckNack.dwErrorCode) ? NACK : ACK;
  300. return S_OK;
  301. }
  302. default:
  303. { // Someone put garbage in the registry (do nothing)
  304. rAckNack.dwAckNack = ACK;
  305. rAckNack.dwErrorCode = 0;
  306. return S_OK;
  307. }
  308. }
  309. return S_OK;
  310. }