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.

556 lines
15 KiB

  1. /*++
  2. Copyright (c) 1998 - 1999 Microsoft Corporation
  3. Module Name:
  4. ioctl.c
  5. Abstract: Contains routines to support HIDCLASS internal
  6. ioctl queries for game devices.
  7. Environment:
  8. Kernel mode
  9. @@BEGIN_DDKSPLIT
  10. Author:
  11. Eliyas Yakub (Mar, 10, 1997)
  12. Revision History:
  13. Updated by Eliyas on Feb 5 1998
  14. MarcAnd 02-Jul-98 Quick tidy for DDK
  15. @@END_DDKSPLIT
  16. --*/
  17. #include "hidgame.h"
  18. #ifdef ALLOC_PRAGMA
  19. #pragma alloc_text (PAGE, HGM_GetDeviceDescriptor)
  20. #pragma alloc_text (PAGE, HGM_GetReportDescriptor)
  21. #pragma alloc_text (PAGE, HGM_GetAttributes )
  22. #endif
  23. /*****************************************************************************
  24. *
  25. * @doc EXTERNAL
  26. *
  27. * @func NTSTATUS | HGM_InternalIoctl |
  28. *
  29. * Process the Control IRPs sent to this device.
  30. * <nl>This function cannot be pageable because reads/writes
  31. * can be made at dispatch-level
  32. *
  33. * @parm IN PDRIVER_OBJECT | DeviceObject |
  34. *
  35. * Pointer to the driver object
  36. *
  37. * @parm IN PIRP | Irp |
  38. *
  39. * Pointer to an I/O Request Packet.
  40. *
  41. * @rvalue STATUS_SUCCESS | success
  42. * @rvalue STATUS_NOT_SUPPORT | Irp function not supported
  43. * @rvalue ??? | ???
  44. *
  45. *****************************************************************************/
  46. NTSTATUS EXTERNAL
  47. HGM_InternalIoctl
  48. (
  49. IN PDEVICE_OBJECT DeviceObject,
  50. IN PIRP Irp
  51. )
  52. {
  53. NTSTATUS ntStatus = STATUS_SUCCESS;
  54. PDEVICE_EXTENSION DeviceExtension;
  55. PIO_STACK_LOCATION IrpStack;
  56. HGM_DBGPRINT(FILE_IOCTL | HGM_FENTRY, \
  57. ("HGM_InternalIoctl(DeviceObject=0x%x,Irp=0x%x)", \
  58. DeviceObject, Irp));
  59. /*
  60. * Get a pointer to the current location in the Irp
  61. */
  62. IrpStack = IoGetCurrentIrpStackLocation(Irp);
  63. /*
  64. * Get a pointer to the device extension
  65. */
  66. DeviceExtension = GET_MINIDRIVER_DEVICE_EXTENSION (DeviceObject);
  67. ntStatus = HGM_IncRequestCount( DeviceExtension );
  68. if (!NT_SUCCESS (ntStatus))
  69. {
  70. /*
  71. * Someone sent us another plug and play IRP after removed
  72. */
  73. HGM_DBGPRINT(FILE_PNP | HGM_ERROR,\
  74. ("HGM_InternalIoctl: PnP IRP after device was removed\n"));
  75. Irp->IoStatus.Information = 0;
  76. Irp->IoStatus.Status = ntStatus;
  77. } else
  78. {
  79. switch(IrpStack->Parameters.DeviceIoControl.IoControlCode)
  80. {
  81. case IOCTL_HID_GET_DEVICE_DESCRIPTOR:
  82. HGM_DBGPRINT(FILE_IOCTL | HGM_BABBLE, \
  83. ("IOCTL_HID_GET_DEVICE_DESCRIPTOR"));
  84. ntStatus = HGM_GetDeviceDescriptor(DeviceObject, Irp);
  85. break;
  86. case IOCTL_HID_GET_REPORT_DESCRIPTOR:
  87. HGM_DBGPRINT(FILE_IOCTL | HGM_BABBLE, \
  88. ("IOCTL_HID_GET_REPORT_DESCRIPTOR"));
  89. ntStatus = HGM_GetReportDescriptor(DeviceObject, Irp);
  90. break;
  91. case IOCTL_HID_READ_REPORT:
  92. HGM_DBGPRINT(FILE_IOCTL | HGM_BABBLE,\
  93. ("IOCTL_HID_READ_REPORT"));
  94. ntStatus = HGM_ReadReport(DeviceObject, Irp);
  95. break;
  96. case IOCTL_HID_GET_DEVICE_ATTRIBUTES:
  97. HGM_DBGPRINT(FILE_IOCTL | HGM_BABBLE,\
  98. ("IOCTL_HID_GET_DEVICE_ATTRIBUTES"));
  99. ntStatus = HGM_GetAttributes(DeviceObject, Irp);
  100. break;
  101. default:
  102. HGM_DBGPRINT(FILE_IOCTL | HGM_WARN,\
  103. ("Unknown or unsupported IOCTL (%x)",
  104. IrpStack->Parameters.DeviceIoControl.IoControlCode));
  105. ntStatus = STATUS_NOT_SUPPORTED;
  106. break;
  107. }
  108. /*
  109. * Set real return status in Irp
  110. */
  111. Irp->IoStatus.Status = ntStatus;
  112. HGM_DecRequestCount( DeviceExtension );
  113. }
  114. if(ntStatus != STATUS_PENDING)
  115. {
  116. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  117. /*
  118. * NOTE: Real return status set in Irp->IoStatus.Status
  119. */
  120. ntStatus = STATUS_SUCCESS;
  121. } else
  122. {
  123. /*
  124. * No reason why there should be a status pending
  125. */
  126. HGM_DBGPRINT(FILE_IOCTL | HGM_ERROR, \
  127. ("HGM_InternalIoctl: Pending Status !"));
  128. IoMarkIrpPending( Irp );
  129. }
  130. HGM_EXITPROC(FILE_IOCTL | HGM_FEXIT_STATUSOK, "HGM_InternalIoctl", ntStatus);
  131. return ntStatus;
  132. } /* HGM_InternalIoctl */
  133. /*****************************************************************************
  134. *
  135. * @doc EXTERNAL
  136. *
  137. * @func NTSTATUS | HGM_GetDeviceDescriptor |
  138. *
  139. * Respond to HIDCLASS IOCTL_HID_GET_DEVICE_DESCRIPTOR
  140. * by returning a device descriptor
  141. *
  142. * @parm IN PDRIVER_OBJECT | DeviceObject |
  143. *
  144. * Pointer to the driver object
  145. *
  146. * @parm IN PIRP | Irp |
  147. *
  148. * Pointer to an I/O Request Packet.
  149. *
  150. * @rvalue STATUS_SUCCESS | success
  151. * @rvalue STATUS_BUFFER_TOO_SMALL | need more memory
  152. *
  153. *****************************************************************************/
  154. NTSTATUS INTERNAL
  155. HGM_GetDeviceDescriptor
  156. (
  157. IN PDEVICE_OBJECT DeviceObject,
  158. IN PIRP Irp
  159. )
  160. {
  161. PHID_DESCRIPTOR pHidDescriptor; /* Hid descriptor for this device */
  162. USHORT cbReport;
  163. UCHAR rgGameReport[MAXBYTES_GAME_REPORT] ;
  164. NTSTATUS ntStatus = STATUS_SUCCESS;
  165. PDEVICE_EXTENSION DeviceExtension;
  166. PIO_STACK_LOCATION IrpStack;
  167. PAGED_CODE ();
  168. HGM_DBGPRINT(FILE_IOCTL | HGM_FENTRY,\
  169. ("HGM_GetDeviceDescriptor(DeviceObject=0x%x,Irp=0x%x)",
  170. DeviceObject, Irp));
  171. /*
  172. * Get a pointer to the current location in the Irp
  173. */
  174. IrpStack = IoGetCurrentIrpStackLocation(Irp);
  175. /*
  176. * Get a pointer to the device extension
  177. */
  178. DeviceExtension = GET_MINIDRIVER_DEVICE_EXTENSION (DeviceObject);
  179. /*
  180. * Get a pointer to the HID_DESCRIPTOR
  181. */
  182. pHidDescriptor = (PHID_DESCRIPTOR) Irp->UserBuffer;
  183. if( IrpStack->Parameters.DeviceIoControl.OutputBufferLength < sizeof(*pHidDescriptor) )
  184. {
  185. HGM_DBGPRINT(FILE_IOCTL | HGM_ERROR,\
  186. ("HGM_GetDeviceDescriptor: OutBufferLength(0x%x) < sizeof(HID_DESCRIPTOR)(0x%x)", \
  187. IrpStack->Parameters.DeviceIoControl.OutputBufferLength, sizeof(*pHidDescriptor)));
  188. ntStatus = STATUS_BUFFER_TOO_SMALL;
  189. } else
  190. {
  191. /*
  192. * Generate the report
  193. */
  194. ntStatus = HGM_GenerateReport(DeviceObject, rgGameReport, &cbReport);
  195. if( NT_SUCCESS(ntStatus) )
  196. {
  197. RtlZeroMemory( pHidDescriptor, sizeof(*pHidDescriptor) );
  198. /*
  199. * Copy device descriptor to HIDCLASS buffer
  200. */
  201. pHidDescriptor->bLength = sizeof(*pHidDescriptor);
  202. pHidDescriptor->bDescriptorType = HID_HID_DESCRIPTOR_TYPE;
  203. pHidDescriptor->bcdHID = HID_REVISION;
  204. pHidDescriptor->bCountry = 0; /*not localized*/
  205. pHidDescriptor->bNumDescriptors = HGM_NUMBER_DESCRIPTORS;
  206. pHidDescriptor->DescriptorList[0].bReportType = HID_REPORT_DESCRIPTOR_TYPE ;
  207. pHidDescriptor->DescriptorList[0].wReportLength = cbReport;
  208. /*
  209. * Report how many bytes were copied
  210. */
  211. Irp->IoStatus.Information = sizeof(*pHidDescriptor);
  212. } else
  213. {
  214. Irp->IoStatus.Information = 0x0;
  215. }
  216. }
  217. HGM_EXITPROC(FILE_IOCTL |HGM_FEXIT_STATUSOK, "HGM_GetDeviceDescriptor", ntStatus);
  218. return ntStatus;
  219. } /* HGM_GetDeviceDescriptor */
  220. /*****************************************************************************
  221. *
  222. * @doc EXTERNAL
  223. *
  224. * @func NTSTATUS | HGM_GetReportDescriptor |
  225. *
  226. * Respond to HIDCLASS IOCTL_HID_GET_REPORT_DESCRIPTOR
  227. * by returning appropriate the report descriptor
  228. *
  229. * @parm IN PDRIVER_OBJECT | DeviceObject |
  230. *
  231. * Pointer to the driver object
  232. *
  233. * @parm IN PIRP | Irp |
  234. *
  235. * Pointer to an I/O Request Packet.
  236. *
  237. * @rvalue STATUS_SUCCESS | success
  238. * @rvalue ??? | ???
  239. *
  240. *****************************************************************************/
  241. NTSTATUS INTERNAL
  242. HGM_GetReportDescriptor
  243. (
  244. IN PDEVICE_OBJECT DeviceObject,
  245. IN PIRP Irp
  246. )
  247. {
  248. PDEVICE_EXTENSION DeviceExtension;
  249. PIO_STACK_LOCATION IrpStack;
  250. NTSTATUS ntStatus;
  251. UCHAR rgGameReport[MAXBYTES_GAME_REPORT] ;
  252. USHORT cbReport;
  253. PAGED_CODE ();
  254. HGM_DBGPRINT(FILE_IOCTL | HGM_FENTRY,\
  255. ("HGM_GetReportDescriptor(DeviceObject=0x%x,Irp=0x%x)",\
  256. DeviceObject, Irp));
  257. /*
  258. * Get a pointer to the current location in the Irp
  259. */
  260. IrpStack = IoGetCurrentIrpStackLocation(Irp);
  261. /*
  262. * Get a pointer to the device extension
  263. */
  264. DeviceExtension = GET_MINIDRIVER_DEVICE_EXTENSION (DeviceObject);
  265. /*
  266. * Generate the report
  267. */
  268. ntStatus = HGM_GenerateReport(DeviceObject, rgGameReport, &cbReport);
  269. if( NT_SUCCESS(ntStatus) )
  270. {
  271. if( cbReport > (USHORT) IrpStack->Parameters.DeviceIoControl.OutputBufferLength )
  272. {
  273. ntStatus = STATUS_BUFFER_TOO_SMALL;
  274. HGM_DBGPRINT(FILE_IOCTL | HGM_ERROR,\
  275. ("HGM_GetReportDescriptor: cbReport(0x%x) OutputBufferLength(0x%x)",\
  276. cbReport, IrpStack->Parameters.DeviceIoControl.OutputBufferLength));
  277. } else
  278. {
  279. RtlCopyMemory( Irp->UserBuffer, rgGameReport, cbReport );
  280. /*
  281. * Report how many bytes were copied
  282. */
  283. Irp->IoStatus.Information = cbReport;
  284. ntStatus = STATUS_SUCCESS;
  285. }
  286. }
  287. HGM_EXITPROC(FILE_IOCTL |HGM_FEXIT_STATUSOK, "HGM_GetReportDescriptor", ntStatus);
  288. return ntStatus;
  289. } /* HGM_GetReportDescriptor */
  290. /*****************************************************************************
  291. *
  292. * @doc EXTERNAL
  293. *
  294. * @func NTSTATUS | HGM_ReadReport |
  295. *
  296. * Poll the gameport, remap the axis and button data and package
  297. * into the defined HID report field.
  298. * <nl>This routine cannot be pageable as HID can make reads at
  299. * dispatch-level.
  300. *
  301. * @parm IN PDRIVER_OBJECT | DeviceObject |
  302. *
  303. * Pointer to the driver object
  304. *
  305. * @parm IN PIRP | Irp |
  306. *
  307. * Pointer to an I/O Request Packet.
  308. *
  309. * @rvalue STATUS_SUCCESS | success
  310. * @rvalue STATUS_DEVICE_NOT_CONNECTED | Device Failed to Quiesce
  311. * ( not connected )
  312. * @rvalue STATUS_TIMEOUT | Could not determine exact transition time for
  313. * one or more axis but not a failure.
  314. *
  315. *****************************************************************************/
  316. NTSTATUS INTERNAL
  317. HGM_ReadReport
  318. (
  319. IN PDEVICE_OBJECT DeviceObject,
  320. IN PIRP Irp
  321. )
  322. {
  323. NTSTATUS ntStatus = STATUS_SUCCESS;
  324. PDEVICE_EXTENSION DeviceExtension;
  325. PIO_STACK_LOCATION IrpStack;
  326. HGM_DBGPRINT(FILE_IOCTL | HGM_FENTRY,\
  327. ("HGM_ReadReport(DeviceObject=0x%x,Irp=0x%x)", \
  328. DeviceObject, Irp));
  329. /*
  330. * Get a pointer to the device extension.
  331. */
  332. DeviceExtension = GET_MINIDRIVER_DEVICE_EXTENSION (DeviceObject);
  333. /*
  334. * Get Stack location.
  335. */
  336. IrpStack = IoGetCurrentIrpStackLocation(Irp);
  337. /*
  338. * First check the size of the output buffer (there is no input buffer)
  339. */
  340. if( IrpStack->Parameters.DeviceIoControl.OutputBufferLength < sizeof(HIDGAME_INPUT_DATA) )
  341. {
  342. HGM_DBGPRINT(FILE_IOCTL | HGM_WARN,\
  343. ("HGM_ReadReport: Buffer too small, output=0x%x need=0x%x", \
  344. IrpStack->Parameters.DeviceIoControl.OutputBufferLength,
  345. sizeof(HIDGAME_INPUT_DATA) ) );
  346. ntStatus = STATUS_BUFFER_TOO_SMALL;
  347. }
  348. if( DeviceExtension->fStarted == FALSE )
  349. {
  350. ntStatus = STATUS_DEVICE_NOT_READY ;
  351. }
  352. /*
  353. * All the checking done so do device specific polling
  354. */
  355. if( NT_SUCCESS(ntStatus) )
  356. {
  357. ntStatus = HGM_UpdateLatestPollData( DeviceExtension );
  358. }
  359. /*
  360. * If all's well, translate device specific data to HID report
  361. */
  362. if( NT_SUCCESS(ntStatus) )
  363. {
  364. HGM_Game2HID( DeviceExtension, (PHIDGAME_INPUT_DATA)Irp->UserBuffer );
  365. Irp->IoStatus.Information = sizeof(HIDGAME_INPUT_DATA);
  366. }
  367. else
  368. {
  369. Irp->IoStatus.Information = 0x0;
  370. }
  371. Irp->IoStatus.Status = ntStatus;
  372. HGM_EXITPROC(FILE_IOCTL|HGM_FEXIT, "HGM_ReadReport", ntStatus);
  373. return ntStatus;
  374. } /* HGM_ReadReport */
  375. /*****************************************************************************
  376. *
  377. * @doc EXTERNAL
  378. *
  379. * @func NTSTATUS | HGM_GetAttributes |
  380. *
  381. * Respond to IOCTL_HID_GET_ATTRIBUTES, by filling
  382. * the HID_DEVICE_ATTRIBUTES struct
  383. *
  384. * @parm IN PDRIVER_OBJECT | DeviceObject |
  385. *
  386. * Pointer to the driver object
  387. *
  388. * @parm IN PIRP | Irp |
  389. *
  390. * Pointer to an I/O Request Packet.
  391. *
  392. * @rvalue STATUS_SUCCESS | success
  393. * @rvalue ??? | ???
  394. *
  395. *****************************************************************************/
  396. NTSTATUS INTERNAL
  397. HGM_GetAttributes
  398. (
  399. PDEVICE_OBJECT DeviceObject,
  400. PIRP Irp
  401. )
  402. {
  403. NTSTATUS ntStatus = STATUS_SUCCESS;
  404. PIO_STACK_LOCATION IrpStack;
  405. PAGED_CODE();
  406. HGM_DBGPRINT(FILE_IOCTL | HGM_FENTRY,\
  407. ("HGM_GetAttributes(DeviceObject=0x%x,Irp=0x%x)",\
  408. DeviceObject, Irp));
  409. /*
  410. * Get a pointer to the current location in the Irp
  411. */
  412. IrpStack = IoGetCurrentIrpStackLocation(Irp);
  413. if( IrpStack->Parameters.DeviceIoControl.OutputBufferLength < sizeof (HID_DEVICE_ATTRIBUTES) )
  414. {
  415. ntStatus = STATUS_BUFFER_TOO_SMALL;
  416. HGM_DBGPRINT(FILE_IOCTL | HGM_ERROR,\
  417. ("HGM_GetAttributes: cbReport(0x%x) OutputBufferLength(0x%x)",\
  418. sizeof (HID_DEVICE_ATTRIBUTES), IrpStack->Parameters.DeviceIoControl.OutputBufferLength));
  419. } else
  420. {
  421. PDEVICE_EXTENSION DeviceExtension;
  422. PHID_DEVICE_ATTRIBUTES DeviceAttributes;
  423. POEMDATA OemData;
  424. /*
  425. * Get a pointer to the device extension
  426. */
  427. DeviceExtension = GET_MINIDRIVER_DEVICE_EXTENSION(DeviceObject);
  428. DeviceAttributes = (PHID_DEVICE_ATTRIBUTES) Irp->UserBuffer;
  429. OemData = &DeviceExtension->HidGameOemData.OemData[0];
  430. if( DeviceExtension->fSiblingFound)
  431. {
  432. OemData = &DeviceExtension->HidGameOemData.OemData[1];
  433. }
  434. RtlZeroMemory( DeviceAttributes, sizeof(*DeviceAttributes));
  435. /*
  436. * Report how many bytes were copied
  437. */
  438. Irp->IoStatus.Information = sizeof(*DeviceAttributes);
  439. DeviceAttributes->Size = sizeof (*DeviceAttributes);
  440. DeviceAttributes->VendorID = OemData->VID;
  441. DeviceAttributes->ProductID = OemData->PID;
  442. DeviceAttributes->VersionNumber = HIDGAME_VERSION_NUMBER;
  443. }
  444. HGM_EXITPROC(FILE_IOCTL|HGM_FEXIT_STATUSOK, "HGM_GetAttributes", ntStatus);
  445. return ntStatus;
  446. } /* HGM_GetAttributes */