Source code of Windows XP (NT5)
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.

271 lines
7.6 KiB

  1. /*****************************************************************************
  2. *
  3. * diqdevg.c
  4. *
  5. * Acquire an IDirectInputDevice8 as a generic device.
  6. *
  7. * We build a private data format with all the axes first, then
  8. * all the buttons.
  9. *
  10. * We display the axes parenthesized, followed by a space-separated
  11. * list of buttons.
  12. *
  13. *****************************************************************************/
  14. #include "diquick.h"
  15. /*****************************************************************************
  16. *
  17. * DEVGINFO
  18. *
  19. * Structure used to track generic device state.
  20. *
  21. *****************************************************************************/
  22. typedef struct DEVGINFO {
  23. DWORD cbState; /* Size of state buffer */
  24. LPVOID pvState; /* State buffer */
  25. int cAxes; /* Number of axes (start at offset 0) */
  26. int cButtons; /* Number of buttons (start after axes) */
  27. } DEVGINFO, *PDEVGINFO;
  28. /*****************************************************************************
  29. *
  30. * Devg_UpdateStatus
  31. *
  32. * Warning! ptszBuf is only 256 characters long!
  33. *
  34. *****************************************************************************/
  35. STDMETHODIMP
  36. Devg_UpdateStatus(PDEVDLGINFO pddi, LPTSTR ptszBuf)
  37. {
  38. HRESULT hres;
  39. PDEVGINFO pdevg = pddi->pvAcq;
  40. IDirectInputDevice8 *pdev = pddi->pdid;
  41. hres = IDirectInputDevice8_GetDeviceState(pdev, pdevg->cbState,
  42. pdevg->pvState);
  43. if (SUCCEEDED(hres)) {
  44. LPVOID pvData = pdevg->pvState;
  45. int iButton;
  46. if (pdevg->cAxes) {
  47. int iAxis;
  48. for (iAxis = 0; iAxis < pdevg->cAxes; iAxis++) {
  49. LPLONG pl = pvData;
  50. pvData = pvAddPvCb(pvData, sizeof(LONG));
  51. ptszBuf += wsprintf(ptszBuf, iAxis == 0 ? TEXT("\050%d") :
  52. TEXT(", %d"), *pl);
  53. }
  54. ptszBuf += wsprintf(ptszBuf, TEXT("\051"));
  55. }
  56. for (iButton = 0; iButton < pdevg->cButtons; iButton++) {
  57. LPBYTE pb = pvData;
  58. pvData = pvAddPvCb(pvData, sizeof(BYTE));
  59. if (*pb & 0x80) {
  60. ptszBuf += wsprintf(ptszBuf, TEXT(" %d"), iButton);
  61. }
  62. }
  63. }
  64. *ptszBuf = TEXT('\0');
  65. return hres;
  66. }
  67. /*****************************************************************************
  68. *
  69. * Devg_Destroy
  70. *
  71. *****************************************************************************/
  72. STDMETHODIMP_(void)
  73. Devg_Destroy(PDEVDLGINFO pddi)
  74. {
  75. PDEVGINFO pdevg = pddi->pvAcq;
  76. if (pdevg) {
  77. if (pdevg->pvState) {
  78. LocalFree(pdevg->pvState);
  79. }
  80. LocalFree(pdevg);
  81. }
  82. }
  83. /*****************************************************************************
  84. *
  85. * Devg_DataFormatEnumProc
  86. *
  87. * Callback function for each object. If it's a button or axis,
  88. * we put it in the data format. But only if it generates data!
  89. *
  90. *****************************************************************************/
  91. typedef struct DEVGENUM {
  92. DWORD dwNumObjs;
  93. DIDATAFORMAT df;
  94. PDEVGINFO pdevg;
  95. PDEVDLGINFO pddi;
  96. } DEVGENUM, *PDEVGENUM;
  97. BOOL CALLBACK
  98. Devg_DataFormatEnumProc(LPCDIDEVICEOBJECTINSTANCE pinst, LPVOID pv)
  99. {
  100. PDEVGENUM pge = pv;
  101. LPDIOBJECTDATAFORMAT podf;
  102. DIDEVICEOBJECTINSTANCE doi;
  103. DWORD cbObj;
  104. if( pge->df.dwNumObjs == pge->dwNumObjs -1 )
  105. {
  106. HLOCAL hloc;
  107. pge->dwNumObjs *=2;
  108. hloc = LocalReAlloc((HLOCAL)pge->df.rgodf, pge->dwNumObjs * pge->df.dwObjSize , LMEM_MOVEABLE+LMEM_ZEROINIT);
  109. if(hloc)
  110. {
  111. pge->df.rgodf = hloc;
  112. }else
  113. {
  114. goto done;
  115. }
  116. }
  117. ConvertDoi(pge->pddi, &doi, pinst);
  118. /*
  119. * Ignore no-data elements.
  120. */
  121. if (doi.dwType & DIDFT_NODATA) {
  122. } else {
  123. if (doi.dwType & (DIDFT_AXIS | DIDFT_POV)) {
  124. pge->pdevg->cAxes++;
  125. cbObj = cbX(LONG);
  126. } else if (doi.dwType & DIDFT_BUTTON) {
  127. pge->pdevg->cButtons++;
  128. cbObj = cbX(BYTE);
  129. } else {
  130. /*
  131. * Theoretical impossibility!
  132. */
  133. goto done;
  134. }
  135. podf = &pge->df.rgodf[pge->df.dwNumObjs];
  136. podf->dwOfs = pge->df.dwDataSize;
  137. #ifdef USE_HID_USAGE_DATA_FORMATS
  138. if (doi.wUsagePage) {
  139. podf->dwType = (doi.dwType &
  140. (DIDFT_AXIS | DIDFT_BUTTON | DIDFT_POV)) |
  141. DIDFT_ANYINSTANCE;
  142. podf->pguid = (PV)DIMAKEUSAGEDWORD(doi.wUsagePage, doi.wUsage);
  143. podf->dwFlags |= DIDOI_GUIDISUSAGE;
  144. } else {
  145. podf->dwType = doi.dwType;
  146. }
  147. #else
  148. podf->dwType = doi.dwType;
  149. #endif
  150. pge->df.dwDataSize += cbObj;
  151. pge->df.dwNumObjs++;
  152. }
  153. done:;
  154. return DIENUM_CONTINUE;
  155. }
  156. /*****************************************************************************
  157. *
  158. * Devg_SetDataFormat
  159. *
  160. * Build a custom data format for the device.
  161. *
  162. *****************************************************************************/
  163. STDMETHODIMP
  164. Devg_SetDataFormat(PDEVDLGINFO pddi)
  165. {
  166. HRESULT hres;
  167. DEVGENUM ge;
  168. ge.pddi = pddi;
  169. ge.pdevg = LocalAlloc(LPTR, cbX(DEVGINFO));
  170. if (ge.pdevg) {
  171. DIDEVCAPS_DX3 caps;
  172. pddi->pvAcq = ge.pdevg;
  173. /*
  174. * Get worst-case axis and button count.
  175. */
  176. caps.dwSize = cbX(caps);
  177. hres = IDirectInputDevice8_GetCapabilities(pddi->pdid,
  178. (PV)&caps);
  179. if (SUCCEEDED(hres)) {
  180. ge.df.dwSize = cbX(ge.df);
  181. ge.df.dwObjSize = cbX(DIOBJECTDATAFORMAT);
  182. ge.df.dwFlags = 0;
  183. ge.df.dwNumObjs = 0;
  184. ge.df.dwDataSize = 0;
  185. ge.dwNumObjs = caps.dwAxes + caps.dwPOVs + caps.dwButtons;
  186. ge.df.rgodf = LocalAlloc(LPTR,
  187. (caps.dwAxes + caps.dwPOVs + caps.dwButtons) *
  188. ge.df.dwObjSize);
  189. if (ge.df.rgodf) {
  190. if (SUCCEEDED(hres =
  191. IDirectInputDevice8_EnumObjects(pddi->pdid,
  192. Devg_DataFormatEnumProc, &ge,
  193. DIDFT_AXIS | DIDFT_POV | DIDFT_ALIAS | DIDFT_VENDORDEFINED )) &&
  194. SUCCEEDED(hres =
  195. IDirectInputDevice8_EnumObjects(pddi->pdid,
  196. Devg_DataFormatEnumProc, &ge, DIDFT_BUTTON| DIDFT_ALIAS | DIDFT_VENDORDEFINED))) {
  197. ge.df.dwDataSize = (ge.df.dwDataSize + 3) & ~3;
  198. ge.pdevg->cbState = ge.df.dwDataSize;
  199. ge.pdevg->pvState = LocalAlloc(LPTR, ge.pdevg->cbState);
  200. if (ge.pdevg->pvState) {
  201. hres = IDirectInputDevice8_SetDataFormat(
  202. pddi->pdid, &ge.df);
  203. } else {
  204. hres = E_OUTOFMEMORY;
  205. }
  206. }
  207. LocalFree(ge.df.rgodf);
  208. } else {
  209. hres = E_OUTOFMEMORY;
  210. }
  211. }
  212. } else {
  213. hres = E_OUTOFMEMORY;
  214. }
  215. return hres;
  216. }
  217. /*****************************************************************************
  218. *
  219. * c_acqvtblDev
  220. *
  221. *****************************************************************************/
  222. #pragma BEGIN_CONST_DATA
  223. ACQVTBL c_acqvtblDev = {
  224. Devg_UpdateStatus,
  225. Devg_SetDataFormat,
  226. Devg_Destroy,
  227. 0,
  228. };
  229. #pragma END_CONST_DATA