v 1
July 5, 2020

HID Virtual Driver Kit

The to Emulate

Joystick, Keyboard and Mouse for Windows 7, 8, 8.1, 10 64 bit

Using the Mouse Abs Driver

Overview

The mouse driver abs (absolute) allows you to:

  • Position the cursor with absolute desktop coordinates. Note that this is desktop coordinates, not monitor coordinates.
  • Press and/or release the left, middle and right buttons.

The Mouse Driver Abs Sender Utility

Use the SDK Mouse Driver Sender to send absolute coordinates and mouse button states to the mouse driver. The mouse cursor will respond as if a real physical mouse had been moved and its buttons pressed. Be sure to press the ‘Connect to Mouse Driver’ before sending coordinates and button states to the driver.

Absolute Coordinates

Since the driver uses absolute coordinates, you’ll need to use the desktop mouse coordinate system. This system defines:

  • [0,0] is the desktop upper left.
  • [16384,16384] is the desktop center.
  • [32767,32767] is the desktop lower right.

Using absolute desktop means that the coordinates are dependent on the number of monitors. The desktop ‘surface’ is defined by your monitor layout as shown below (from Windows 10). This means that sending the mouse to an absolute position of (1000, 1000) on one system will not go the the same place on another system with differently configured monitor(s). So absolute mouse positioning requires a real guarantee of anticipated monitor configurations.

The Windows Display Settings monitor setup screen.
A Windows desktop with three monitors. Note there are ‘gaps’ in the desktop due to varying monitor sizes. Send the mouse to the gap at (1000,1000) and where does it go? The answer is ‘nearby’.

If you send a coordinate that is not in the light blue area in the diagram above, Windows will send the cursor to the nearest visible location. To really get a good understanding of this logic, drag the Mouse Sender utility over to each monitor and try sending (1000, 1000). If you have multiple monitors, you’ll see the mouse is positioned at the nearest logical location to the coordinates sent.

Sending Data to the Driver

First, iterate through all drivers until you find ‘Tetherscript Virtual Mouse Abs’ and connect to that driver. Then send a packed record as a ‘Feature Report’ to the driver. More info on feature reports below:

https://docs.microsoft.com/en-us/windows-hardware/drivers/hid/

Mouse driver reports are based sdk/delphi/common/hut1_12v2.pdf

Delphi

Here’s the mouse driver report Delphi data format. In our Delphi source we call this a Feature, but really it is a standard HID Input Report. This is just the terminology left over from Delphi’s JCL and JVCL libraries.:

type
  PTSetFeatureMouseAbs = ^TSetFeatureMouseAbs;
  TSetFeatureMouseAbs = packed record
  ReportID: Byte;
  CommandCode: Byte;
  buttons: byte;
  X: Word;
  Y: Word;
end;

C#

[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct SetFeatureMouseAbs
{
  public Byte ReportID;
  public Byte CommandCode;
  public Byte Buttons;
  public UInt16 X;
  public UInt16 Y;
}

c

This corresponds to the following c struct (this is the actual receiving input report struct from the driver source):

typedef struct _HIDMINI_CONTROL_INFO {
  UCHAR ReportId;
  UCHAR CommandCode;
  BYTE buttons;
  UINT16 X;
  UINT16 Y;
} HIDMINI_CONTROL_INFO, * PHIDMINI_CONTROL_INFO;

  • ReportID: is always 1, whether sending data or resetting the driver. Just leave it as 1.
  • CommandCode: This is 1 if resetting the driver, 2 if sending data.
  • buttons: Left, middle and right mouse buttons are encoded in this byte. Left button down = 1. Right button down adds 2. Left button down adds 4. This is basically or’ing the rightmost three bits of the byte to indicate button state. Releasing a button is done by clearing the bit to zero and sending the report to the driver again. The hid spec supports only three buttons, but obviously most mice have more than that. Usually those mice will require some additional software/driver from the mouse manufacturer to recognize those buttons. We’re not sure how these are sent exactly.
    • 00000000 = no buttons pressed.
    • 00000001 = only left button pressed.
    • 00000010 = only right button pressed.
    • 00000100 = only middle button pressed.
    • 00000110 = only right and middle buttons pressed.
    • 00000101 = only left and middle buttons pressed.
    • 00000111 = all buttons pressed.
    • 00000010 and then wait x ms and then 00000000 = to right-click and then release the button. x is a delay, try at least 50ms. That is the time the button remains pressed.
  • X: The mouse absolute X position from 0 to 32767. This is a Delphi Word type, which is two bytes.
  • Y: The mouse absolute Y position from 0 to 32767. This is a Delphi Word type, which is two bytes.

Handling Stuck Mouse Buttons

As an example, normally a right-mouse-click is 00000010 and then wait x ms then 00000000. It is possible that you may have forgotten, or due to your app crashing, that a button remains pressed. There are three ways to unstuck a button.

  1. Send a Reset command to the mouse driver. This will release all mouse buttons.
  2. Physically press and release the button on a real physical mouse. That should clear it.
  3. Reboot.

Resetting the Driver

To reset the driver, send the report with a CommandCode = 1. The X and Z values are ignored, so Z and Y to any value you like. Internally, the driver will release the buttons and set X = 0 and Y = 0, but that will cause the cursor to noticeably jump. Instead, you can send a report with CommandCode = 1, buttons = 0, X and Y = the current desktop mouse coordinates to prevent that jumping cursor. It’s up to you whether to use the reset function, but it isn’t critical for the mouse driver.

Your First Hello-Driver App – a Suggestion

  1. Iterate through the drivers and find and connect to the mouse driver.
  2. Send data with a command code of 2, buttons = 0, X = 16384, Y = 16384.
  3. Run your code. If it works, you’ll see the mouse cursor snap to the exact desktop center.