virtual mouse

Hello folks.

I need to create virtual mouse device that will contain two features: ability of setting coordinates and clicking (pretty standard thing isn’t it?).
I decided to modify vhidmini sample, as it seem to fit to my requirements. What I did till now:

  1. I found HID spec for mouse.
  2. Modified report descriptor to fit to mouse class HID spec
  3. Prepared structures and modifed code to react accrodingly to reports

Issue I have now is with installation of this driver.
Here is my INF:

===================================================== STARTof INF =====================================================
;/++
;
;Copyright (c) Microsoft Corporation All rights Reserved
;
;Module Name:
;
; vihidmini.inf
;
;Abstract:
; INF file for installing HID minidriver (KMDF version)
;
;Installation Notes:
; Using Devcon: Type “devcon install vhidmini.inf root\vhidmini” to install
;
;–
/
[Version]
Signature=“$WINDOWS NT$”
Class=Mouse
ClassGUID={4d36e96f-e325-11ce-bfc1-08002be10318}
Provider=%ProviderString%
DriverVer = 12/22/2018,23.12.1.10
CatalogFile=wudf.cat

; ================= Class section =====================

;[ClassInstall32]
;Addreg=SampleClassReg

;[SampleClassReg]
;HKR,0,%ClassName%
;HKR,Icon,-5

; ================= Device section =====================

[Manufacturer]
%ManufacturerString%=Microsoft,NTx86.6.1

; Works on Win7 and later because we use inbox HID-KMDF mapper
[Microsoft.NTx86.6.1]
%DeviceDesc%=vhidmini,{4d36e96f-e325-11ce-bfc1-08002be10318}\vhidmini

[vhidmini.NT]
CopyFiles=KMDriverCopy

[vhidmini.NT.hw]
AddReg=vhidmini_AddReg

[vhidmini.NT.Services]
AddService=vhidmini,0,vhidmini_Service_Inst,
AddService=mshidkmdf,0x00000002,mshidkmdf_Service_Inst ;flag 0x2 sets this as the service for the device

[vhidmini_AddReg]
HKR,“LowerFilters”,0x00010008,“vhidmini” ; FLG_ADDREG_TYPE_MULTI_SZ | FLG_ADDREG_APPEND

[mshidkmdf_Service_Inst]
ServiceType = 1 ; SERVICE_KERNEL_DRIVER
StartType = 3 ; SERVICE_DEMAND_START
ErrorControl = 1 ; SERVICE_ERROR_NORMAL
ServiceBinary = %12%\mshidkmdf.sys

[vhidmini_Service_Inst]
DisplayName = %ServiceDesc%
ServiceType = 1
StartType = 3
ErrorControl = 1
ServiceBinary = %12%\vhidmini.sys

[vhidmini.NT.Wdf]
KmdfService=vhidmini, vhidmini_wdfsect

[vhidmini_wdfsect]
KmdfLibraryVersion=1.9

; ================= copy files =====================

[KMDriverCopy]
vhidmini.sys

[SourceDisksNames]
1=%DiskDesc%,

[SourceDisksFiles]
vhidmini.sys=1

[DestinationDirs]
KMDriverCopy=12

;---------------------------------------------------------------;

[Strings]
ProviderString = “TODO-Set-Provider”
ManufacturerString = “TODO-Set-Manufacturer”
ClassName = “Sample Device”
DeviceDesc = “HID minidriver (KMDF version) Device virtual MOUSE”
ServiceDesc = “HID minidriver (KMDF version) Service”
DiskDesc = “HID minidriver (KMDF version) Installation Disk”

===================================================== END of INF =====================================================

way Im installing driver is:
devcon install vhidmini.inf “{4d36e96f-e325-11ce-bfc1-08002be10318}\vhidmini”

Driver is installing, and in device manager I see device under MOUSE node, but additionally in “Other devices” group I see “unknown device” that is created along with my driver.
It appears to be related with report descriptor as if I change it for test to one from sample it is working. Here is my descriptor:

HID_REPORT_DESCRIPTOR G_DefaultReportDescriptor = {
0x05, 0x01, // USAGE_PAGE (Generic Desktop)
0x09, 0x02, // USAGE (Mouse)
0xA1, 0x01, // COLLECTION (Application)
0x09, 0x01, // USAGE_PAGE (Pointer)
0xA1, 0x00, // COLLECTION (Physical)
0x05, 0x09, // USAGE_PAGE (Buttons)
0x19, 0x01, // USAGE_MINIMUM (1)
0x29, 0x03, // USAGE_MAXIMUM (3)
0x15, 0x00, // LOGICAL_MINIMUM (0)
0x25, 0x01, // LOGICAL_MAXIMUM (1)
0x95, 0x03, // REPORT_COUNT (3)
0x75, 0x01, // REPORT_SIZE (1)
0x81, 0x02, // INPUT (Data, Variable, Absolute) ; 3 button bits
0x95, 0x01, // REPORT_COUNT (1)
0x75, 0x05, // REPORT_SIZE (5)
0x81, 0x01, // INPUT (Constant)
0x05, 0x01, // USAGE_PAGE (Generic Desktop)
0x09, 0x30, // USAGE (X)
0x09, 0x31, // USAGE (Y)
0x15, 0x81, // LOGICAL_MINIMUM (-127)
0x25, 0x7F, // LOGICAL_MAXIMUM (127)
0x75, 0x08, // REPORT_SIZE (8)
0x95, 0x02, // REPORT_COUNT (2)
0x81, 0x06, // Input (Data, Variable, Relative) ; 2 position bytes (X&Y)
0xC0, // END_COLLECTION
0xC0, // END_COLLECTION
};

in Logs I see “no hardware id found”.

Can you please point me some directions I should follow to go further?

Thanks for help,
JJ

You should install vhidmini in the HID class, not the mouse class, in the inf. I assume the original sample installs in the hid class , so revert your change. The mouse will be enumerated as a child of vhidmini and the in box mouhid.sys will load on it. If you open the child device in device manager and open the properties page for the device, go to the details tab and copy/paste the reported hardware and compatible ids on the page and send them in your response.

d

Bent from my phone


From: JamesJoyce
Sent: Saturday, December 22, 2018 2:28:54 PM
To: Doron Holan
Subject: [NTDEV] virtual mouse

OSR https://nam06.safelinks.protection.outlook.com/?url=https%3A%2F%2Fcommunity.osr.com%2F&data=02|01|doron.holan%40microsoft.com|8054ecf573ef41bb7b3d08d6685cdbeb|72f988bf86f141af91ab2d7cd011db47|1|1|636811145373392791&sdata=DTy20q%2FJA4mySesIeE6KXaoyif2bmCkgA3%2FTl%2BD9RxE%3D&reserved=0
JamesJoyce started a new discussion: virtual mouse

Hello folks.

I need to create virtual mouse device that will contain two features: ability of setting coordinates and clicking (pretty standard thing isn’t it?).

I decided to modify vhidmini sample, as it seem to fit to my requirements. What I did till now:

* I found HID spec for mouse.
* Modified report descriptor to fit to mouse class HID spec
* Prepared structures and modifed code to react accrodingly to reports

Issue I have now is with installation of this driver.

Here is my INF:

===================================================== STARTof INF =====================================================

;/++

;

;Copyright (c) Microsoft Corporation All rights Reserved

;

;Module Name:

;

; vihidmini.inf

;

;Abstract:

; INF file for installing HID minidriver (KMDF version)

;

;Installation Notes:

; Using Devcon: Type “devcon install vhidmini.inf root\vhidmini” to install

;

;–/

[Version]

Signature=“$WINDOWS NT$”

Class=Mouse

ClassGUID={4d36e96f-e325-11ce-bfc1-08002be10318}

Provider=%ProviderString%

DriverVer = 12/22/2018,23.12.1.10

CatalogFile=wudf.cat

; ================= Class section =====================

;[ClassInstall32]

;Addreg=SampleClassReg

;[SampleClassReg]

;HKR,0,%ClassName%

;HKR,Icon,-5

; ================= Device section =====================

[Manufacturer]

%ManufacturerString%=Microsoft,NTx86.6.1

; Works on Win7 and later because we use inbox HID-KMDF mapper

[Microsoft.NTx86.6.1]

%DeviceDesc%=vhidmini,{4d36e96f-e325-11ce-bfc1-08002be10318}\vhidmini

[vhidmini.NT]

CopyFiles=KMDriverCopy

[vhidmini.NT.hw]

AddReg=vhidmini_AddReg

[vhidmini.NT.Services]

AddService=vhidmini,0,vhidmini_Service_Inst,

AddService=mshidkmdf,0x00000002,mshidkmdf_Service_Inst ;flag 0x2 sets this as the service for the device

[vhidmini_AddReg]

HKR,“LowerFilters”,0x00010008,“vhidmini” ; FLG_ADDREG_TYPE_MULTI_SZ | FLG_ADDREG_APPEND

[mshidkmdf_Service_Inst]

ServiceType = 1 ; SERVICE_KERNEL_DRIVER

StartType = 3 ; SERVICE_DEMAND_START

ErrorControl = 1 ; SERVICE_ERROR_NORMAL

ServiceBinary = %12%\mshidkmdf.sys

[vhidmini_Service_Inst]

DisplayName = %ServiceDesc%

ServiceType = 1

StartType = 3

ErrorControl = 1

ServiceBinary = %12%\vhidmini.sys

[vhidmini.NT.Wdf]

KmdfService=vhidmini, vhidmini_wdfsect

[vhidmini_wdfsect]

KmdfLibraryVersion=1.9

; ================= copy files =====================

[KMDriverCopy]

vhidmini.sys

[SourceDisksNames]

1=%DiskDesc%,

[SourceDisksFiles]

vhidmini.sys=1

[DestinationDirs]

KMDriverCopy=12

;---------------------------------------------------------------;

[Strings]

ProviderString = “TODO-Set-Provider”

ManufacturerString = “TODO-Set-Manufacturer”

ClassName = “Sample Device”

DeviceDesc = “HID minidriver (KMDF version) Device virtual MOUSE”

ServiceDesc = “HID minidriver (KMDF version) Service”

DiskDesc = “HID minidriver (KMDF version) Installation Disk”

===================================================== END of INF =====================================================

way Im installing driver is:

devcon install vhidmini.inf “{4d36e96f-e325-11ce-bfc1-08002be10318}\vhidmini”

Driver is installing, and in device manager I see device under MOUSE node, but additionally in “Other devices” group I see “unknown device” that is created along with my driver.

It appears to be related with report descriptor as if I change it for test to one from sample it is working. Here is my descriptor:

HID_REPORT_DESCRIPTOR G_DefaultReportDescriptor = {

0x05, 0x01, // USAGE_PAGE (Generic Desktop)

0x09, 0x02, // USAGE (Mouse)

0xA1, 0x01, // COLLECTION (Application)

0x09, 0x01, // USAGE_PAGE (Pointer)

0xA1, 0x00, // COLLECTION (Physical)

0x05, 0x09, // USAGE_PAGE (Buttons)

0x19, 0x01, // USAGE_MINIMUM (1)

0x29, 0x03, // USAGE_MAXIMUM (3)

0x15, 0x00, // LOGICAL_MINIMUM (0)

0x25, 0x01, // LOGICAL_MAXIMUM (1)

0x95, 0x03, // REPORT_COUNT (3)

0x75, 0x01, // REPORT_SIZE (1)

0x81, 0x02, // INPUT (Data, Variable, Absolute) ; 3 button bits

0x95, 0x01, // REPORT_COUNT (1)

0x75, 0x05, // REPORT_SIZE (5)

0x81, 0x01, // INPUT (Constant)

0x05, 0x01, // USAGE_PAGE (Generic Desktop)

0x09, 0x30, // USAGE (X)

0x09, 0x31, // USAGE (Y)

0x15, 0x81, // LOGICAL_MINIMUM (-127)

0x25, 0x7F, // LOGICAL_MAXIMUM (127)

0x75, 0x08, // REPORT_SIZE (8)

0x95, 0x02, // REPORT_COUNT (2)

0x81, 0x06, // Input (Data, Variable, Relative) ; 2 position bytes (X&Y)

0xC0, // END_COLLECTION

0xC0, // END_COLLECTION

};

in Logs I see “no hardware id found”.

Can you please point me some directions I should follow to go further?

Thanks for help,

JJ

Hi Doron,
Big thank you for answer and advice.

Actually vhidmini in samples is installed with “Sample device” class.

  1. I replaced it in INF to install it to HID class (+ section in INF: %DeviceDesc%=vhidmini,root\vhidmini). Effect is I see my device in device manager put into HID class drivers, but still dont see new mouse device. This happens for Windows 7 and Windows 10
  2. With my INF I posted above (MOUSE class) effect is more wierd as on Windows 7 effect is I pointed above, but on Windows 10 - I see new device MOUSE in device manager - do you know why it is like this?
  3. According to your suggestion: if I install my driver as HID, then what exactly will determine there should be MOUSE added. I assume this is based on descriptor - but looking for some confirmation.
  4. If I install my driver as MOUSe on Windows 10 (there is no issue reported by dev manager) - I cannot open this device. I pressume this is because it is exclusively opened by subsystem (got access denied), but in such case how can I open device to eventually send to it some commands?

Thank you!

I don

I don’t know why win7 is behaving differently than w10 but it doesn’t matter. The vhidmini driver is never the mouse. The mouse is enumerated by hidclass based on the reported hid descriptor. You can’t open vhidmini, hidclasss blocks opens to the FDO. You can’t open the mouse as it is opened exclusively by win32k. You need to report a second top level collection (TLC) in your hid descriptor with a custom usage page. This second TLC allows you to send commands to the hid miniport. d

Doron,

Thank you for your answers. Those were very valuable for me.
I modified descriptor in following way:

`HID_REPORT_DESCRIPTOR G_DefaultReportDescriptor = {

0x05, 0x01,                    // USAGE_PAGE (Generic Desktop)
0x09, 0x02,                    // USAGE (Mouse)
0xA1, 0x01,     // COLLECTION (Application)
0x09, 0x01,         // USAGE_PAGE (Pointer)
0xA1, 0x00,         // COLLECTION (Physical)
0x85, M_CONTROL_FEATURE_REPORT_ID,    // REPORT_ID (1)
0x05, 0x09,             // USAGE_PAGE (Buttons)
0x19, 0x01,             // USAGE_MINIMUM (1)
0x29, 0x03,             // USAGE_MAXIMUM (3)
0x15, 0x00,             // LOGICAL_MINIMUM (0)
0x25, 0x01,             // LOGICAL_MAXIMUM (1)
0x95, 0x03,             // REPORT_COUNT (3)
0x75, 0x01,             // REPORT_SIZE (1)
0x81, 0x02,             // INPUT (Data, Variable, Absolute) ; 3 button bits
0x95, 0x01,             // REPORT_COUNT (1)
0x75, 0x05,             // REPORT_SIZE (5)
0x81, 0x01,             // INPUT (Constant)
0x05, 0x01,             // USAGE_PAGE (Generic Desktop)
0x09, 0x30,             // USAGE (X)
0x09, 0x31,             // USAGE (Y)
0x15, 0x81,             // LOGICAL_MINIMUM (-127)
0x25, 0x7F,             // LOGICAL_MAXIMUM (127)
0x75, 0x08,             // REPORT_SIZE (8)
0x95, 0x02,             // REPORT_COUNT (2)
0x81, 0x06,             // Input (Data, Variable, Relative) ; 2 position bytes (X&Y)
0xC0,               // END_COLLECTION
0xC0,           // END_COLLECTION

0x06,0x00, 0xFF,                // USAGE_PAGE (Vendor Defined Usage Page)
0x09,0x01,                      // USAGE (Vendor Usage 0x01)
0xA1,0x01,                      // COLLECTION (Application)
0x85,CONTROL_FEATURE_REPORT_ID,    // REPORT_ID (1)
0x09,0x01,                         // USAGE (Vendor Usage 0x01)
0x15,0x00,                         // LOGICAL_MINIMUM(0)
0x26,0xff, 0x00,                   // LOGICAL_MAXIMUM(255)
0x75,0x08,                         // REPORT_SIZE (0x08)
0x96,(FEATURE_REPORT_SIZE_CB & 0xff), (FEATURE_REPORT_SIZE_CB >> 8), // REPORT_COUNT
0xB1,0x00,                         // FEATURE (Data,Ary,Abs)
0x09,0x01,                         // USAGE (Vendor Usage 0x01)
0x75,0x08,                         // REPORT_SIZE (0x08)
0x96,(INPUT_REPORT_SIZE_CB & 0xff), (INPUT_REPORT_SIZE_CB >> 8), // REPORT_COUNT
0x81,0x00,                         // INPUT (Data,Ary,Abs)
0x09,0x01,                         // USAGE (Vendor Usage 0x01)
0x75,0x08,                         // REPORT_SIZE (0x08)
0x96,(OUTPUT_REPORT_SIZE_CB & 0xff), (OUTPUT_REPORT_SIZE_CB >> 8), // REPORT_COUNT
0x91,0x00,                         // OUTPUT (Data,Ary,Abs)
0xC0,                           // END_COLLECTION

};`

So there are two TLCs (main mouse has report id:2, controlling TLC has id:1).
I can see that now, device manager is showing created two devices in tree:

  • HID-compilant vendor defined device under HID class
  • HID-compilant mouse device under pointing devices.

This seem to be fine now (greeting to you).
Now. I can see once driver starts, its queried with: IOCTL_HID_GET_DEVICE_DESCRIPTOR,IOCTL_HID_GET_DEVICE_ATTRIBUTES and IOCTL_HID_GET_REPORT_DESCRIPTOR. which is fine.
After that it is queried with IOCTL_HID_READ_REPORT, which is sent to manual queue (exactly as in vhidmini sample) and expiered timer is providing data.

Problem Im fancing is I cant see OS is taking its data, mouse pointer is not moving.
I pressume it may be related to report ids OR structure sizes, but unfortunately I cant find proper place. Maybe you will have some advice here:

timer function looks like this:
`void
EvtTimerFunc(
In WDFTIMER Timer
)
{
NTSTATUS status;
WDFQUEUE queue;
PMANUAL_QUEUE_CONTEXT queueContext;
WDFREQUEST request;
HIDMINI_INPUT_REPORT readReport;

KdPrint(("EvtTimerFunc\n"));

queue = (WDFQUEUE)WdfTimerGetParentObject(Timer);
queueContext = GetManualQueueContext(queue);

//
// see if we have a request in manual queue
//
status = WdfIoQueueRetrieveNextRequest(
                        queueContext->Queue,
                        &request);

if (NT_SUCCESS(status)) {

    readReport.ReportId = CONTROL_FEATURE_REPORT_ID;
	readReport.X = queueContext->DeviceContext->X;
	readReport.Y= queueContext->DeviceContext->Y;
	readReport.Buttons= queueContext->DeviceContext->Buttons;

    status = RequestCopyFromBuffer(request,
                        &readReport,
                        sizeof(readReport));

    WdfRequestComplete(request, status);
}

}`

structure:
typedef struct _HIDMINI_INPUT_REPORT { UCHAR ReportId; UCHAR Buttons; UCHAR X; UCHAR Y; } HIDMINI_INPUT_REPORT, *PHIDMINI_INPUT_REPORT;

Big thanks for your time!
JJ