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.

561 lines
16 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. if( IrpStack->Parameters.DeviceIoControl.OutputBufferLength < sizeof(*pHidDescriptor) )
  180. {
  181. HGM_DBGPRINT(FILE_IOCTL | HGM_ERROR,\
  182. ("HGM_GetDeviceDescriptor: OutBufferLength(0x%x) < sizeof(HID_DESCRIPTOR)(0x%x)", \
  183. IrpStack->Parameters.DeviceIoControl.OutputBufferLength, sizeof(*pHidDescriptor)));
  184. ntStatus = STATUS_BUFFER_TOO_SMALL;
  185. } else
  186. {
  187. /*
  188. * Generate the report
  189. */
  190. ntStatus = HGM_GenerateReport(DeviceObject, rgGameReport, &cbReport);
  191. if( NT_SUCCESS(ntStatus) )
  192. {
  193. /*
  194. * Get a pointer to the HID_DESCRIPTOR
  195. * HIDCLASS is trusted to pass a valid pointer.
  196. */
  197. pHidDescriptor = (PHID_DESCRIPTOR) Irp->UserBuffer;
  198. RtlZeroMemory( pHidDescriptor, sizeof(*pHidDescriptor) );
  199. /*
  200. * Copy device descriptor to HIDCLASS buffer
  201. */
  202. pHidDescriptor->bLength = sizeof(*pHidDescriptor);
  203. pHidDescriptor->bDescriptorType = HID_HID_DESCRIPTOR_TYPE;
  204. pHidDescriptor->bcdHID = HID_REVISION;
  205. pHidDescriptor->bCountry = 0; /*not localized*/
  206. pHidDescriptor->bNumDescriptors = HGM_NUMBER_DESCRIPTORS;
  207. pHidDescriptor->DescriptorList[0].bReportType = HID_REPORT_DESCRIPTOR_TYPE ;
  208. pHidDescriptor->DescriptorList[0].wReportLength = cbReport;
  209. /*
  210. * Report how many bytes were copied
  211. */
  212. Irp->IoStatus.Information = sizeof(*pHidDescriptor);
  213. } else
  214. {
  215. Irp->IoStatus.Information = 0x0;
  216. }
  217. }
  218. HGM_EXITPROC(FILE_IOCTL |HGM_FEXIT_STATUSOK, "HGM_GetDeviceDescriptor", ntStatus);
  219. return ntStatus;
  220. } /* HGM_GetDeviceDescriptor */
  221. /*****************************************************************************
  222. *
  223. * @doc EXTERNAL
  224. *
  225. * @func NTSTATUS | HGM_GetReportDescriptor |
  226. *
  227. * Respond to HIDCLASS IOCTL_HID_GET_REPORT_DESCRIPTOR
  228. * by returning appropriate the report descriptor
  229. *
  230. * @parm IN PDRIVER_OBJECT | DeviceObject |
  231. *
  232. * Pointer to the driver object
  233. *
  234. * @parm IN PIRP | Irp |
  235. *
  236. * Pointer to an I/O Request Packet.
  237. *
  238. * @rvalue STATUS_SUCCESS | success
  239. * @rvalue ??? | ???
  240. *
  241. *****************************************************************************/
  242. NTSTATUS INTERNAL
  243. HGM_GetReportDescriptor
  244. (
  245. IN PDEVICE_OBJECT DeviceObject,
  246. IN PIRP Irp
  247. )
  248. {
  249. PDEVICE_EXTENSION DeviceExtension;
  250. PIO_STACK_LOCATION IrpStack;
  251. NTSTATUS ntStatus;
  252. UCHAR rgGameReport[MAXBYTES_GAME_REPORT] ;
  253. USHORT cbReport;
  254. PAGED_CODE ();
  255. HGM_DBGPRINT(FILE_IOCTL | HGM_FENTRY,\
  256. ("HGM_GetReportDescriptor(DeviceObject=0x%x,Irp=0x%x)",\
  257. DeviceObject, Irp));
  258. /*
  259. * Get a pointer to the current location in the Irp
  260. */
  261. IrpStack = IoGetCurrentIrpStackLocation(Irp);
  262. /*
  263. * Get a pointer to the device extension
  264. */
  265. DeviceExtension = GET_MINIDRIVER_DEVICE_EXTENSION (DeviceObject);
  266. /*
  267. * Generate the report
  268. */
  269. ntStatus = HGM_GenerateReport(DeviceObject, rgGameReport, &cbReport);
  270. if( NT_SUCCESS(ntStatus) )
  271. {
  272. if( cbReport > (USHORT) IrpStack->Parameters.DeviceIoControl.OutputBufferLength )
  273. {
  274. ntStatus = STATUS_BUFFER_TOO_SMALL;
  275. HGM_DBGPRINT(FILE_IOCTL | HGM_ERROR,\
  276. ("HGM_GetReportDescriptor: cbReport(0x%x) OutputBufferLength(0x%x)",\
  277. cbReport, IrpStack->Parameters.DeviceIoControl.OutputBufferLength));
  278. } else
  279. {
  280. RtlCopyMemory( Irp->UserBuffer, rgGameReport, cbReport );
  281. /*
  282. * Report how many bytes were copied
  283. */
  284. Irp->IoStatus.Information = cbReport;
  285. ntStatus = STATUS_SUCCESS;
  286. }
  287. }
  288. HGM_EXITPROC(FILE_IOCTL |HGM_FEXIT_STATUSOK, "HGM_GetReportDescriptor", ntStatus);
  289. return ntStatus;
  290. } /* HGM_GetReportDescriptor */
  291. /*****************************************************************************
  292. *
  293. * @doc EXTERNAL
  294. *
  295. * @func NTSTATUS | HGM_ReadReport |
  296. *
  297. * Poll the gameport, remap the axis and button data and package
  298. * into the defined HID report field.
  299. * <nl>This routine cannot be pageable as HID can make reads at
  300. * dispatch-level.
  301. *
  302. * @parm IN PDRIVER_OBJECT | DeviceObject |
  303. *
  304. * Pointer to the driver object
  305. *
  306. * @parm IN PIRP | Irp |
  307. *
  308. * Pointer to an I/O Request Packet.
  309. *
  310. * @rvalue STATUS_SUCCESS | success
  311. * @rvalue STATUS_DEVICE_NOT_CONNECTED | Device Failed to Quiesce
  312. * ( not connected )
  313. * @rvalue STATUS_TIMEOUT | Could not determine exact transition time for
  314. * one or more axis but not a failure.
  315. *
  316. *****************************************************************************/
  317. NTSTATUS INTERNAL
  318. HGM_ReadReport
  319. (
  320. IN PDEVICE_OBJECT DeviceObject,
  321. IN PIRP Irp
  322. )
  323. {
  324. NTSTATUS ntStatus = STATUS_SUCCESS;
  325. PDEVICE_EXTENSION DeviceExtension;
  326. PIO_STACK_LOCATION IrpStack;
  327. HGM_DBGPRINT(FILE_IOCTL | HGM_FENTRY,\
  328. ("HGM_ReadReport(DeviceObject=0x%x,Irp=0x%x)", \
  329. DeviceObject, Irp));
  330. /*
  331. * Get a pointer to the device extension.
  332. */
  333. DeviceExtension = GET_MINIDRIVER_DEVICE_EXTENSION (DeviceObject);
  334. /*
  335. * Get Stack location.
  336. */
  337. IrpStack = IoGetCurrentIrpStackLocation(Irp);
  338. /*
  339. * First check the size of the output buffer (there is no input buffer)
  340. */
  341. if( IrpStack->Parameters.DeviceIoControl.OutputBufferLength < sizeof(HIDGAME_INPUT_DATA) )
  342. {
  343. HGM_DBGPRINT(FILE_IOCTL | HGM_WARN,\
  344. ("HGM_ReadReport: Buffer too small, output=0x%x need=0x%x", \
  345. IrpStack->Parameters.DeviceIoControl.OutputBufferLength,
  346. sizeof(HIDGAME_INPUT_DATA) ) );
  347. ntStatus = STATUS_BUFFER_TOO_SMALL;
  348. }
  349. if( DeviceExtension->fStarted == FALSE )
  350. {
  351. ntStatus = STATUS_DEVICE_NOT_READY ;
  352. }
  353. /*
  354. * All the checking done so do device specific polling
  355. */
  356. if( NT_SUCCESS(ntStatus) )
  357. {
  358. ntStatus = HGM_UpdateLatestPollData( DeviceExtension );
  359. }
  360. /*
  361. * If all's well, translate device specific data to HID report
  362. */
  363. if( NT_SUCCESS(ntStatus) )
  364. {
  365. #ifdef CHANGE_DEVICE
  366. HGM_Game2HID( DeviceObject, DeviceExtension, (PHIDGAME_INPUT_DATA)Irp->UserBuffer );
  367. #else
  368. HGM_Game2HID( DeviceExtension, (PHIDGAME_INPUT_DATA)Irp->UserBuffer );
  369. #endif
  370. Irp->IoStatus.Information = sizeof(HIDGAME_INPUT_DATA);
  371. }
  372. else
  373. {
  374. Irp->IoStatus.Information = 0x0;
  375. }
  376. Irp->IoStatus.Status = ntStatus;
  377. HGM_EXITPROC(FILE_IOCTL|HGM_FEXIT, "HGM_ReadReport", ntStatus);
  378. return ntStatus;
  379. } /* HGM_ReadReport */
  380. /*****************************************************************************
  381. *
  382. * @doc EXTERNAL
  383. *
  384. * @func NTSTATUS | HGM_GetAttributes |
  385. *
  386. * Respond to IOCTL_HID_GET_ATTRIBUTES, by filling
  387. * the HID_DEVICE_ATTRIBUTES struct
  388. *
  389. * @parm IN PDRIVER_OBJECT | DeviceObject |
  390. *
  391. * Pointer to the driver object
  392. *
  393. * @parm IN PIRP | Irp |
  394. *
  395. * Pointer to an I/O Request Packet.
  396. *
  397. * @rvalue STATUS_SUCCESS | success
  398. * @rvalue ??? | ???
  399. *
  400. *****************************************************************************/
  401. NTSTATUS INTERNAL
  402. HGM_GetAttributes
  403. (
  404. PDEVICE_OBJECT DeviceObject,
  405. PIRP Irp
  406. )
  407. {
  408. NTSTATUS ntStatus = STATUS_SUCCESS;
  409. PIO_STACK_LOCATION IrpStack;
  410. PAGED_CODE();
  411. HGM_DBGPRINT(FILE_IOCTL | HGM_FENTRY,\
  412. ("HGM_GetAttributes(DeviceObject=0x%x,Irp=0x%x)",\
  413. DeviceObject, Irp));
  414. /*
  415. * Get a pointer to the current location in the Irp
  416. */
  417. IrpStack = IoGetCurrentIrpStackLocation(Irp);
  418. if( IrpStack->Parameters.DeviceIoControl.OutputBufferLength < sizeof (HID_DEVICE_ATTRIBUTES) )
  419. {
  420. ntStatus = STATUS_BUFFER_TOO_SMALL;
  421. HGM_DBGPRINT(FILE_IOCTL | HGM_ERROR,\
  422. ("HGM_GetAttributes: cbReport(0x%x) OutputBufferLength(0x%x)",\
  423. sizeof (HID_DEVICE_ATTRIBUTES), IrpStack->Parameters.DeviceIoControl.OutputBufferLength));
  424. } else
  425. {
  426. PDEVICE_EXTENSION DeviceExtension;
  427. PHID_DEVICE_ATTRIBUTES DeviceAttributes;
  428. POEMDATA OemData;
  429. /*
  430. * Get a pointer to the device extension
  431. */
  432. DeviceExtension = GET_MINIDRIVER_DEVICE_EXTENSION(DeviceObject);
  433. DeviceAttributes = (PHID_DEVICE_ATTRIBUTES) Irp->UserBuffer;
  434. OemData = &DeviceExtension->HidGameOemData.OemData[0];
  435. if( DeviceExtension->fSiblingFound)
  436. {
  437. OemData = &DeviceExtension->HidGameOemData.OemData[1];
  438. }
  439. RtlZeroMemory( DeviceAttributes, sizeof(*DeviceAttributes));
  440. /*
  441. * Report how many bytes were copied
  442. */
  443. Irp->IoStatus.Information = sizeof(*DeviceAttributes);
  444. DeviceAttributes->Size = sizeof (*DeviceAttributes);
  445. DeviceAttributes->VendorID = OemData->VID;
  446. DeviceAttributes->ProductID = OemData->PID;
  447. DeviceAttributes->VersionNumber = HIDGAME_VERSION_NUMBER;
  448. }
  449. HGM_EXITPROC(FILE_IOCTL|HGM_FEXIT_STATUSOK, "HGM_GetAttributes", ntStatus);
  450. return ntStatus;
  451. } /* HGM_GetAttributes */