Tips for Coding in Driverland
Try the Mouse Driver First
Sending data the mouse driver is easier than sending it to the joystick driver, and way easier than sending it to the keyboard driver. Once you have it working with the mouse driver, you will understand the basics of working with the drivers. So start with the mouse.
Use the Keyboard Driver Ping and Timeout Features
It is possible to send a key-down command to the driver, then not send the corresponding key-up command (due to a crash or maybe forgot). This leaves the key in a pressed state and acts like you are physically pressing the key on the real keyboard. The keyboard driver has special feature which requires that you ping it every so often (every 100 ms is good) and if the driver has not received a ping in the timeout value (5000 ms is good), the driver will automatically release all the keys.
If you are using the keyboard driver, you will appreciate this feature. Without this feature, you would be rebooting. Often.
Use the SDK utils during development
When you are coding for sending data to a driver, use the SDK’s keyboard and joystick reader utilities to see if the data is being sent correctly to the driver. This way you are sure it is being read correctly from the driver, so you can concentrate of the sending to the driver.
Find the drivers in Windows Device Manager
Just set the View menu to Devices by connection and that makes it easier to see the drivers listed.

Get to know the driver installation log
There is a C:\Windows\INF\setupapi.dev.log file that records all driver install and uninstall activity. Any error’s will be listed in the log with a !!! prefix. This log can get quite large, but you can delete it so that it is recreated when you install the drivers. There’s a lot of fascinating driver info in this log. If a driver didn’t install, this should be your first stop.
Here’s the log entries for running install.bat in the Joystick driver folder. There are no errors during the installation:
[Device Install Log]OS Version = 10.0.18363Service Pack = 0.0Suite = 0x0100ProductType = 1Architecture = amd64
[BeginLog]
[Boot Session: 2020/06/14 07:43:13.938]
>>> [Delete Device - ROOT\HIDCLASS\0001]>>> Section start 2020/06/14 11:09:59.223cmd: devcon.exe remove root\ttcvcontr -runhiddendvi: Query-and-Remove succeeded<<< Section end 2020/06/14 11:09:59.250<<< [Exit status: SUCCESS]
>>> [Device Install (UpdateDriverForPlugAndPlayDevices) - root\ttcvcontr]>>> Section start 2020/06/14 11:09:59.278cmd: devcon.exe install ttcvcontr.inf root\ttcvcontr -runhiddenndv: INF path: C:\HID Virtual Device Kit Standard 1.6\Drivers Signed\Joystick\ttcvcontr.infndv: Install flags: 0x00000001ndv: {Update Device Driver - ROOT\HIDCLASS\0001}ndv: Search options: 0x00000080ndv: Searching single INF 'C:\HID Virtual Device Kit Standard 1.6\Drivers Signed\Joystick\ttcvcontr.inf'dvi: {Build Driver List} 11:09:59.309dvi: Searching for hardware ID(s):dvi: root\ttcvcontrdvi: Created Driver Node:dvi: HardwareID - root\ttcvcontrdvi: InfName - c:\hid virtual device kit standard 1.6\drivers signed\joystick\ttcvcontr.infdvi: DevDesc - Tetherscript Virtual Joystickdvi: Section - ttcvcontrollershim.win8.NTdvi: Rank - 0x00ff0000dvi: Signer Score - Authenticodedvi: DrvDate - 05/26/2020dvi: Version - 9.31.12.96dvi: {Build Driver List - exit(0x00000000)} 11:09:59.364dvi: {DIF_SELECTBESTCOMPATDRV} 11:09:59.368dvi: Default installer: Enter 11:09:59.371dvi: {Select Best Driver}dvi: Class GUID of device changed to: {745a17a0-74d3-11d0-b6fe-00a0c90f57da}.dvi: Selected Driver:dvi: Description - Tetherscript Virtual Joystickdvi: InfFile - c:\hid virtual device kit standard 1.6\drivers signed\joystick\ttcvcontr.infdvi: Section - ttcvcontrollershim.win8dvi: {Select Best Driver - exit(0x00000000)}dvi: Default installer: Exitdvi: {DIF_SELECTBESTCOMPATDRV - exit(0x00000000)} 11:09:59.404ndv: Force Installing Driver:ndv: Inf Name - ttcvcontr.infndv: Driver Date - 05/26/2020ndv: Driver Version - 9.31.12.96ndv: Driver package 'C:\WINDOWS\System32\DriverStore\FileRepository\ttcvcontr.inf_amd64_834f068120bd2a35\ttcvcontr.inf' is already imported.sto: {Setup Import Driver Package: c:\hid virtual device kit standard 1.6\drivers signed\joystick\ttcvcontr.inf} 11:09:59.428sto: Driver package already imported as 'oem25.inf'.sto: {Setup Import Driver Package - exit (0x00000000)} 11:09:59.438dvi: Searching for hardware ID(s):dvi: root\ttcvcontrdvi: Class GUID of device changed to: {745a17a0-74d3-11d0-b6fe-00a0c90f57da}.dvi: {Plug and Play Service: Device Install for ROOT\HIDCLASS\0001}dvi: Driver INF Path: C:\WINDOWS\INF\oem25.infdvi: Driver Node Name: ttcvcontr.inf:ed86ca11221ae399:ttcvcontrollershim.win8:9.31.12.96:root\ttcvcontr,dvi: Driver Store Path: C:\WINDOWS\System32\DriverStore\FileRepository\ttcvcontr.inf_amd64_834f068120bd2a35\ttcvcontr.infdvi: Searching for hardware ID(s):dvi: root\ttcvcontrdvi: Class GUID of device changed to: {745a17a0-74d3-11d0-b6fe-00a0c90f57da}.dvi: {Core Device Install} 11:09:59.483dvi: {Install Device - ROOT\HIDCLASS\0001} 11:09:59.484dvi: Device Status: 0x01802001, Problem: 0x0 (0x00000000)dvi: Parent device: HTREE\ROOT\0dvi: {Configure Device - ROOT\HIDCLASS\0001} 11:09:59.486dvi: Device Status: 0x01802001, Problem: 0x0 (0x00000000)dvi: Parent device: HTREE\ROOT\0sto: {Configure Driver Package: C:\WINDOWS\System32\DriverStore\FileRepository\ttcvcontr.inf_amd64_834f068120bd2a35\ttcvcontr.inf}sto: Source Filter = root\ttcvcontrinf: Class GUID = {745a17a0-74d3-11d0-b6fe-00a0c90f57da}inf: Class Options = Configurable BootCriticalinf: {Configure Driver: Tetherscript Virtual Joystick}inf: Section Name = ttcvcontrollershim.win8.NTinf: {Add Service: WUDFRd}inf: Start Type = 3inf: Service Type = 1inf: Error Control = 1inf: Image Path = \SystemRoot\System32\drivers\WUDFRd.sysinf: Display Name = Windows Driver Foundation - User-mode Driver Framework Reflectorinf: Group = Baseinf: Updated service 'WUDFRd'.inf: Leaving existing description (A kernel mode driver that uses message-based interprocess communication mechanism to communicate with the driver manager and host process to facilitate UMDF drivers).inf: {Add Service: exit(0x00000000)}inf: {Add Service: mshidumdf}inf: Start Type = 3inf: Service Type = 1inf: Error Control = 1inf: Image Path = \SystemRoot\System32\Drivers\mshidumdf.sysinf: Leaving existing error control (0).inf: Leaving existing load order group (Base).inf: Leaving existing display name (Pass-through HID to UMDF Driver).inf: Updated service 'mshidumdf'.inf: Leaving existing description (Device Driver to provide pass-through interface between HIDCLASS and UMDF).inf: {Add Service: exit(0x00000000)}inf: Hardware Id = root\ttcvcontrinf: {Configure Driver Configuration: ttcvcontrollershim.win8.NT}inf: Service Name = mshidumdfinf: Lower Filters = WUDFRdinf: Config Flags = 0x00000000inf: {Configure Driver Configuration: exit(0x00000000)}inf: {Configure Driver: exit(0x00000000)}flq: Copying 'C:\WINDOWS\System32\DriverStore\FileRepository\ttcvcontr.inf_amd64_834f068120bd2a35\ttcvcontr.dll' to 'C:\WINDOWS\System32\drivers\UMDF\ttcvcontr.dll'.cpy: Existing file 'C:\WINDOWS\System32\drivers\UMDF\ttcvcontr.dll' remains unchanged.flq: Copying 'C:\WINDOWS\System32\DriverStore\FileRepository\ttcvcontr.inf_amd64_834f068120bd2a35\WudfUpdate_01011.dll' to 'C:\WINDOWS\System32\WudfUpdate_01011.dll'.cpy: Existing file 'C:\WINDOWS\System32\WudfUpdate_01011.dll' remains unchanged.sto: {Configure Driver Package: exit(0x00000000)}dvi: Install Device: Configuring device (oem25.inf:root\ttcvcontr,ttcvcontrollershim.win8.NT). 11:09:59.521dvi: Install Device: Configuring device completed. 11:09:59.525dvi: Device Status: 0x01802001, Problem: 0x0 (0x00000000)dvi: Install Device: Starting device 'ROOT\HIDCLASS\0001'. 11:09:59.527dvi: Install Device: Starting device completed. 11:09:59.561dvi: {Configure Device - exit(0x00000000)} 11:09:59.562dvi: {Install Device - exit(0x00000000)} 11:09:59.565dvi: {Core Device Install - exit(0x00000000)} 11:09:59.565ump: {Plug and Play Service: Device Install exit(00000000)}ndv: {Update Device Driver - exit(00000000)}ndv: {Install Related Drivers} 11:09:59.583ndv: {Install Related Drivers: exit(0x00000000)} 11:09:59.590<<< Section end 2020/06/14 11:09:59.596<<< [Exit status: SUCCESS]
