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.

724 lines
17 KiB

  1. /*++
  2. Copyright (c) 1998 - 1999 Microsoft Corporation
  3. Module Name:
  4. hidgame.h
  5. Abstract: Contains definitions of all constants and
  6. data types for the joystick driver.
  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. OmSharma ( April 12, 1998)
  15. MarcAnd 02-Jul-98 Quick tidy for DDK
  16. @@END_DDKSPLIT
  17. --*/
  18. /*****************************************************************************
  19. * @doc EXTERNAL
  20. *
  21. * @module HidGame | Analog WDM/HID Joystick driver.
  22. *
  23. * HidGame is the HID minidriver for analog joysticks.
  24. * This driver registers with the HID class driver and
  25. * responds to IRPs put out by HIDclass. It informs HIDClass
  26. * about the capabilities of the joystick and polls the joystick
  27. * in response to a read IOCTL.
  28. *
  29. * This driver is loaded in reponse to a "New hardware Found"
  30. * PnP event, and consequently must have an entry in an inf file
  31. * that binds a PnP hardware ID to this driver.
  32. *
  33. * Gameport joysticks are not true PnP devices, so the user has to
  34. * inform the system about the joystick that was added to the
  35. * gameport by using the Game Controllers CPL "Add" a joystick.
  36. * An example of how a new joystick type can be created is provided
  37. * in the accompanying inf file.
  38. *
  39. * Once a user selects a joystick and gameport, the GameCPL passes
  40. * this information to DirectInput which sends an IOCTL to the
  41. * gameport bus driver (GameEnum), specifying the number of axes,
  42. * buttons and a PnPHardware ID for the joystick. The Gameport Bus
  43. * informs PnP of a new device arrival. PnP searches the system for
  44. * a match for the hardwareID and loads the appropriate driver.
  45. *
  46. *
  47. * The following files are part of this driver.
  48. *
  49. * <nl>HidGame.c
  50. * <nl>DriverEntry, CreateClose, AddDevice and Unload Routines.
  51. * This code performs functions required for any device driver
  52. * and so can probably be used without changes for any game
  53. * other game device.
  54. *
  55. * <nl>PnP.c
  56. * <nl>Support routines for PnP IOCTLs.
  57. *
  58. * <nl>Ioctl.c
  59. * <nl>Support routines for Non PnP IOCTLs
  60. * These deal with all the HID IOCTLs required for an ordinary
  61. * game device and so could be used without change as there is
  62. * no analog specific funtionality in these routines.
  63. * Drivers for some devices may need to add code to support more
  64. * complex devices.
  65. *
  66. * <nl>HidJoy.c
  67. * <nl>Support routines to translate legacy joystick flags and
  68. * data into HID descriptors. The majority of this code is
  69. * needed to support the wide variety of analog joysticks
  70. * available so is not relevant to drivers written for specific
  71. * devices.
  72. *
  73. * <nl>Poll.c
  74. * <nl>Support routines to read analog joystick data from a
  75. * gameport. These functions are likely to be of little use
  76. * in a digital joystick driver.
  77. *
  78. * <nl>i386\timing.c
  79. * <nl>Support routines to use x86 Time Stamp Counter.
  80. * Includes code to check for the presence of, calibrate and
  81. * read the high speed CPU timer.
  82. *
  83. * <nl>Hidgame.h
  84. * <nl>Common include file.
  85. * The general definitions are likely to be of use in most
  86. * drivers for game devices but some customization will be needed.
  87. *
  88. * <nl>Debug.h
  89. * <nl>Definitions to aid debugging.
  90. * This contains the tag for the driver name used in debug output
  91. * which must be changed.
  92. *
  93. * <nl>Analog.h
  94. * <nl>Specific include file.
  95. * Definitions specific to analog joystick devices.
  96. *
  97. * <nl>OemSetup.inf
  98. * <nl>Sample inf file.
  99. * See comments in this file for how to install devices.
  100. *
  101. * <nl>Source
  102. * <nl> Source file for the NT build utility
  103. *
  104. * <nl>Makefile
  105. * <nl> Used as part of the build process
  106. *
  107. *****************************************************************************/
  108. #ifndef __HIDGAME_H__
  109. #define __HIDGAME_H__
  110. /* @@BEGIN_DDKSPLIT
  111. *
  112. * Only define CHANGE_DEVICE in DDK sample
  113. */
  114. #if 0
  115. /* @@END_DDKSPLIT */
  116. /*
  117. * When CHANGE_DEVICE is defined it turns on code to use expose sibling and
  118. * remove self to allow the driver to change its capabilities on-the-fly.
  119. * This code is not used in the retail version of HIDGame.
  120. */
  121. #define CHANGE_DEVICE
  122. /* @@BEGIN_DDKSPLIT */
  123. #endif
  124. /* @@END_DDKSPLIT */
  125. /* @@BEGIN_DDKSPLIT Disable common benign warnings for W4 testing */
  126. #pragma warning( disable:4514 ) /* unreferenced inline function has been removed */
  127. #pragma warning( disable:4214 ) /* nonstandard extension used : bit field types other than int */
  128. /* @@END_DDKSPLIT */
  129. /*
  130. * Include Files
  131. */
  132. #include "wdm.h"
  133. #include "hidtoken.h"
  134. #include "hidusage.h"
  135. #include "hidport.h"
  136. #include "gameport.h"
  137. #include "debug.h"
  138. #include "analog.h"
  139. /*
  140. * A value guaranteed to be considered a timeout
  141. */
  142. #define AXIS_TIMEOUT ( 0xffffffffL )
  143. /*
  144. * Defines for hidgame
  145. */
  146. #define HIDGAME_VERSION_NUMBER ((USHORT) 1)
  147. #define JOY_START_TIMERS ( 0 )
  148. #define MAXBYTES_GAME_REPORT ( 256 )
  149. #define BUTTON_1 0x10
  150. #define BUTTON_2 0x20
  151. #define BUTTON_3 0x40
  152. #define BUTTON_4 0x80
  153. #define AXIS_X 0x01
  154. #define AXIS_Y 0x02
  155. #define AXIS_R 0x04
  156. #define AXIS_Z 0x08
  157. #define BUTTON_BIT 0
  158. #define BUTTON_ON ( 1 << BUTTON_BIT )
  159. /*
  160. * Function type used for timing.
  161. * MUST be compatible with KeQueryPerformanceCounter
  162. */
  163. typedef
  164. LARGE_INTEGER
  165. (*COUNTER_FUNCTION) (
  166. PLARGE_INTEGER pDummy
  167. );
  168. /*
  169. * Typedef the structs we need
  170. */
  171. /*****************************************************************************
  172. *
  173. * @doc EXTERNAL
  174. *
  175. * @struct HIDGAME_GLOBAL |
  176. *
  177. * Global struct to store driver wide data.
  178. * Stuff we need to share across multiple instances of this driver.
  179. *
  180. * @field FAST_MUTEX | Mutex |
  181. *
  182. * Mutex to synchronize access to the following list entry
  183. *
  184. * @field LIST_ENTRY | DeviceListHead |
  185. *
  186. * Keeps a list of all devices.
  187. *
  188. * @field KSPIN_LOCK | SpinLock |
  189. *
  190. * Spinlock used to stop multiple processors polling gameports at
  191. * once. It would be better to keep a list of spinlocks, one for
  192. * each gameport but then processors could contend for IO access
  193. * and we'd have to maintain another list.
  194. *
  195. * @field COUNTER_FUNCTION | ReadCounter |
  196. *
  197. * Function to retrieve clock time
  198. *
  199. * @field ULONG | CounterScale |
  200. *
  201. * The scale to be used.
  202. *
  203. *****************************************************************************/
  204. typedef struct _HIDGAME_GLOBAL
  205. {
  206. FAST_MUTEX Mutex; /* A syncronization for access to list */
  207. LIST_ENTRY DeviceListHead; /* Keeps list of all the devices */
  208. KSPIN_LOCK SpinLock; /* Lock so that only one port is accessed */
  209. COUNTER_FUNCTION ReadCounter; /* Function to retrieve clock time */
  210. ULONG CounterScale; /* Clock scale factor */
  211. } HIDGAME_GLOBAL;
  212. /*****************************************************************************
  213. *
  214. * @doc EXTERNAL
  215. *
  216. * @struct DEVICE_EXTENSION |
  217. *
  218. * Device specific data.
  219. *
  220. * @field PGAMEENUM_READPORT | ReadAccessor |
  221. *
  222. * Read Accessor function for the gameport. Obtained in the return from
  223. * IOCTL to the gameport.
  224. *
  225. * @field PGAMEENUM_WRITEPORT | WriteAccessor |
  226. *
  227. * Write Accessor function for the gameport. Obtained in the return from
  228. * IOCTL to the gameport.
  229. *
  230. * @field PGAMEENUM_READPORT_DIGITAL | ReadAccessorDigital |
  231. *
  232. * Digital read accessor for the gameport. Obtained as part of return from
  233. * IOCTL to the gameport
  234. *
  235. * @field PGAMEENUM_ACQUIRE_PORT | AcquirePort |
  236. *
  237. * Function to call before reading/writing to the port. Obtained as
  238. * part of return from IOCTL to the gameport
  239. *
  240. * @field PGAMEENUM_RELEASE_PORT | ReleasePort |
  241. *
  242. * Function to call when done reading/writing to the port. Obtained as
  243. * part of return from IOCTL to the gameport
  244. *
  245. * @field PVOID | GameContext |
  246. *
  247. * Token to read this game port. Obtained as part of the return from
  248. * IOCTL to the gameport.
  249. *
  250. * @field PVOID | PortContext |
  251. *
  252. * Context to pass to AcquirePort and ReleasePort. Obtained as part
  253. * of the return from IOCTL to the gameport.
  254. *
  255. * @field LIST_ENTRY | Link |
  256. *
  257. * Link to other hidgame devices on the system.
  258. *
  259. * @field KEVENT | RemoveEvent |
  260. *
  261. * The remove plugplay request must use this event to make sure all
  262. * other requests have completed before it deletes the device object.
  263. *
  264. * @field LONG | RequestCount |
  265. *
  266. * Number of IRPs underway.
  267. *
  268. * @field PDEVICE_OBJECT | NextDeviceObject |
  269. *
  270. * NOTE: Only present if CHANGE_DEVICE is defined
  271. *
  272. * DeviceObject to send self created IRPs down to
  273. *
  274. * @field WORK_QUEUE_ITEM | WorkItem |
  275. *
  276. * NOTE: Only present if CHANGE_DEVICE is defined
  277. *
  278. * Work item used for expose sibling/remove self
  279. *
  280. * @field ANALOG_DEVICE | unnamed structure see ANALOG_DEVICE |
  281. *
  282. * Structure containing analog device specific information.
  283. *
  284. * NOTE: this structure is placed after the DWORD aligned elements.
  285. *
  286. * @xref <t ANALOG_DEVICE>.
  287. *
  288. * @field BOOLEAN | fRemoved |
  289. *
  290. * Set to true if the device has been removed => all requests should be failed
  291. *
  292. * @field BOOLEAN | fStarted |
  293. *
  294. * Set to true is device has started.
  295. *
  296. * @field BOOLEAN | fSurpriseRemoved |
  297. *
  298. * Set to true if the device has been surprise removed by PnPs device has started.
  299. *
  300. *****************************************************************************/
  301. typedef struct _DEVICE_EXTENSION
  302. {
  303. /*
  304. * read accessor for the game port
  305. */
  306. PGAMEENUM_READPORT ReadAccessor;
  307. /*
  308. * write the game port
  309. */
  310. PGAMEENUM_WRITEPORT WriteAccessor;
  311. /*
  312. * Digital read accessor for the gameport
  313. */
  314. PGAMEENUM_READPORT_DIGITAL ReadAccessorDigital;
  315. /*
  316. * Function to call before reading/writing to the port
  317. */
  318. PGAMEENUM_ACQUIRE_PORT AcquirePort;
  319. /*
  320. * Function to call when done reading/writing to the port
  321. */
  322. PGAMEENUM_RELEASE_PORT ReleasePort;
  323. /*
  324. * token to read this game port
  325. */
  326. PVOID GameContext;
  327. /*
  328. * Context to pass to AcquirePort and ReleasePort
  329. */
  330. PVOID PortContext;
  331. /*
  332. * List of other joystick devices
  333. */
  334. LIST_ENTRY Link;
  335. /*
  336. * The remove plugplay request must use this event to make sure all
  337. * other requests have completed before it deletes the device object.
  338. */
  339. KEVENT RemoveEvent;
  340. /*
  341. * Number of IRPs underway.
  342. */
  343. LONG RequestCount;
  344. #ifdef CHANGE_DEVICE
  345. /*
  346. * DeviceObject to send self created IRPs down to.
  347. */
  348. PDEVICE_OBJECT NextDeviceObject;
  349. /*
  350. * Work item used for expose sibling/remove self
  351. */
  352. WORK_QUEUE_ITEM WorkItem;
  353. #endif /* CHANGE_DEVICE */
  354. /*
  355. * Structure containing analog device specific information.
  356. */
  357. ANALOG_DEVICE;
  358. /*
  359. * Set to true if the device has been removed => all requests should be failed
  360. */
  361. BOOLEAN fRemoved;
  362. /*
  363. * Set to true if the device has started
  364. */
  365. BOOLEAN fStarted;
  366. /*
  367. * Set to true if the device has been surprise removed by PnPs device has started.
  368. */
  369. BOOLEAN fSurpriseRemoved;
  370. #ifdef CHANGE_DEVICE
  371. /*
  372. * Indicates that a replacement sibling is being started
  373. */
  374. BOOLEAN fReplaced;
  375. #endif /* CHANGE_DEVICE */
  376. } DEVICE_EXTENSION, *PDEVICE_EXTENSION;
  377. #define GET_MINIDRIVER_DEVICE_EXTENSION(DO) \
  378. ((PDEVICE_EXTENSION) (((PHID_DEVICE_EXTENSION)(DO)->DeviceExtension)->MiniDeviceExtension))
  379. #define GET_NEXT_DEVICE_OBJECT(DO) \
  380. (((PHID_DEVICE_EXTENSION)(DO)->DeviceExtension)->NextDeviceObject)
  381. /*
  382. * Globals
  383. */
  384. extern HIDGAME_GLOBAL Global;
  385. /*
  386. * Function prototypes
  387. */
  388. #define INTERNAL /* Called only within a translation unit */
  389. #define EXTERNAL /* Called from other translation units */
  390. /*
  391. * hidgame.c
  392. */
  393. NTSTATUS EXTERNAL
  394. DriverEntry
  395. (
  396. IN PDRIVER_OBJECT DriverObject,
  397. IN PUNICODE_STRING registryPath
  398. );
  399. NTSTATUS EXTERNAL
  400. HGM_CreateClose
  401. (
  402. IN PDEVICE_OBJECT DeviceObject,
  403. IN PIRP Irp
  404. );
  405. NTSTATUS EXTERNAL
  406. HGM_SystemControl
  407. (
  408. IN PDEVICE_OBJECT DeviceObject,
  409. IN PIRP Irp
  410. );
  411. NTSTATUS EXTERNAL
  412. HGM_AddDevice
  413. (
  414. IN PDRIVER_OBJECT DriverObject,
  415. IN PDEVICE_OBJECT FunctionalDeviceObject
  416. );
  417. VOID EXTERNAL
  418. HGM_Unload
  419. (
  420. IN PDRIVER_OBJECT DriverObject
  421. );
  422. /*
  423. * ioctl.c
  424. */
  425. NTSTATUS EXTERNAL
  426. HGM_InternalIoctl
  427. (
  428. IN PDEVICE_OBJECT DeviceObject,
  429. IN PIRP Irp
  430. );
  431. NTSTATUS EXTERNAL
  432. HGM_GetDeviceDescriptor
  433. (
  434. IN PDEVICE_OBJECT DeviceObject,
  435. IN PIRP Irp
  436. );
  437. NTSTATUS INTERNAL
  438. HGM_GetReportDescriptor
  439. (
  440. IN PDEVICE_OBJECT DeviceObject,
  441. IN PIRP Irp
  442. );
  443. NTSTATUS INTERNAL
  444. HGM_ReadReport
  445. (
  446. IN PDEVICE_OBJECT DeviceObject,
  447. IN PIRP Irp
  448. );
  449. NTSTATUS INTERNAL
  450. HGM_GetAttributes
  451. (
  452. PDEVICE_OBJECT DeviceObject,
  453. PIRP Irp
  454. );
  455. /*
  456. * pnp.c
  457. */
  458. NTSTATUS INTERNAL
  459. HGM_IncRequestCount
  460. (
  461. PDEVICE_EXTENSION DeviceExtension
  462. );
  463. VOID INTERNAL
  464. HGM_DecRequestCount
  465. (
  466. PDEVICE_EXTENSION DeviceExtension
  467. );
  468. VOID INTERNAL
  469. HGM_RemoveDevice
  470. (
  471. PDEVICE_EXTENSION DeviceExtension
  472. );
  473. NTSTATUS EXTERNAL
  474. HGM_PnP
  475. (
  476. IN PDEVICE_OBJECT DeviceObject,
  477. IN PIRP Irp
  478. );
  479. NTSTATUS INTERNAL
  480. HGM_InitDevice
  481. (
  482. IN PDEVICE_OBJECT DeviceObject,
  483. IN PIRP Irp
  484. );
  485. NTSTATUS INTERNAL
  486. HGM_Power
  487. (
  488. IN PDEVICE_OBJECT DeviceObject,
  489. IN PIRP pIrp
  490. );
  491. NTSTATUS INTERNAL
  492. HGM_GetResources
  493. (
  494. IN PDEVICE_OBJECT DeviceObject,
  495. IN PIRP Irp
  496. );
  497. NTSTATUS INTERNAL
  498. HGM_PnPComplete
  499. (
  500. IN PDEVICE_OBJECT DeviceObject,
  501. IN PIRP Irp,
  502. IN PVOID Context
  503. );
  504. /*
  505. * hidjoy.c
  506. */
  507. NTSTATUS EXTERNAL
  508. HGM_DriverInit
  509. (
  510. VOID
  511. );
  512. NTSTATUS INTERNAL
  513. HGM_SetupButtons
  514. (
  515. IN OUT PDEVICE_EXTENSION DeviceExtension
  516. );
  517. NTSTATUS INTERNAL
  518. HGM_MapAxesFromDevExt
  519. (
  520. IN OUT PDEVICE_EXTENSION DeviceExtension
  521. );
  522. NTSTATUS INTERNAL
  523. HGM_GenerateReport
  524. (
  525. IN PDEVICE_OBJECT DeviceObject,
  526. OUT UCHAR rgGameReport[MAXBYTES_GAME_REPORT],
  527. OUT PUSHORT pCbReport
  528. );
  529. NTSTATUS INTERNAL
  530. HGM_JoystickConfig
  531. (
  532. IN PDEVICE_OBJECT DeviceObject
  533. );
  534. NTSTATUS EXTERNAL
  535. HGM_InitAnalog
  536. (
  537. IN PDEVICE_OBJECT DeviceObject
  538. );
  539. /*
  540. * Sample only code for changing the device
  541. */
  542. #ifdef CHANGE_DEVICE
  543. VOID
  544. HGM_ChangeHandler
  545. (
  546. IN OUT PDEVICE_EXTENSION DeviceExtension
  547. );
  548. VOID
  549. HGM_DeviceChanged
  550. (
  551. IN OUT PDEVICE_EXTENSION DeviceExtension
  552. );
  553. #endif /* CHANGE_DEVICE */
  554. VOID
  555. HGM_Game2HID
  556. (
  557. IN PDEVICE_EXTENSION DeviceExtension,
  558. IN OUT PUHIDGAME_INPUT_DATA pHIDData
  559. );
  560. /*
  561. * poll.c
  562. */
  563. NTSTATUS INTERNAL
  564. HGM_AnalogPoll
  565. (
  566. IN PDEVICE_EXTENSION DeviceExtension,
  567. IN UCHAR resistiveInputMask,
  568. IN BOOLEAN bApproximate,
  569. IN OUT ULONG Axis[MAX_AXES],
  570. OUT UCHAR Buttons[PORT_BUTTONS]
  571. );
  572. NTSTATUS
  573. HGM_UpdateLatestPollData
  574. (
  575. IN OUT PDEVICE_EXTENSION DeviceExtension
  576. );
  577. /*
  578. * <CPU>\timing.c (or macro equivalents for external functions)
  579. */
  580. #ifdef _X86_
  581. BOOLEAN INTERNAL
  582. HGM_x86IsClockAvailable
  583. (
  584. VOID
  585. );
  586. LARGE_INTEGER INTERNAL
  587. HGM_x86ReadCounter
  588. (
  589. IN PLARGE_INTEGER Dummy
  590. );
  591. VOID INTERNAL
  592. HGM_x86SampleClocks
  593. (
  594. OUT PULONGLONG pTSC,
  595. OUT PULONGLONG pQPC
  596. );
  597. BOOLEAN EXTERNAL
  598. HGM_x86CounterInit();
  599. #define HGM_CPUCounterInit HGM_x86CounterInit
  600. #else
  601. /*
  602. * For all other processors a value to cause the default timing to be used
  603. */
  604. #define HGM_CPUCounterInit() FALSE
  605. #endif /* _X86_ */
  606. #endif /* __HIDGAME_H__ */