Kmdf Hid Minidriver For Touch I2c Device Calibration -
VOID EvtIoDeviceControl(WDFQUEUE Queue, WDFREQUEST Request,
size_t OutputBufferLength, size_t InputBufferLength, ULONG IoControlCode)
switch (IoControlCode)
case IOCTL_SET_CALIBRATION:
CALIBRATION_DATA newCal;
WdfRequestRetrieveInputBuffer(Request, sizeof(newCal), &newCal, NULL);
// Apply and persist
g_Calibration = newCal;
SaveToRegistry(Device, &g_Calibration);
WdfRequestComplete(Request, STATUS_SUCCESS);
break;
default:
WdfRequestComplete(Request, STATUS_INVALID_DEVICE_REQUEST);
Two models dominate touch calibration:
Your KMDF minidriver must store these coefficients in the registry (or device firmware) and apply them to every touch report.
Expose a private IOCTL that user‑mode calibration tool calls:
#define IOCTL_SET_CALIBRATION CTL_CODE(FILE_DEVICE_UNKNOWN, 0x800, METHOD_BUFFERED, FILE_ANY_ACCESS)
EVT_WDF_IO_QUEUE_IO_DEVICE_CONTROL EvtIoDeviceControl;kmdf hid minidriver for touch i2c device calibration
The handler validates input, updates driver’s calibration structure, saves to registry, and optionally applies it to the hardware.
In most cases, hidi2c.sys is sufficient. However, it does NOT support custom calibration. It forwards raw HID reports directly from the I2C device to the HID class driver. To inject calibration, we must replace or layer our own KMDF HID Minidriver. Two models dominate touch calibration:
Your INF must declare the driver as a HID minidriver:
[MyDevice_Install.NT] CopyFiles = MyDriver.Copy AddReg = MyDevice_AddReg
[MyDevice_AddReg] HKR,,"UpperFilters",0x00010000,"HidUsb" ; For HID class HKR,,"LowerFilters",0x00010000,"SpbCx" ; For I2C bus
NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath)
WDF_DRIVER_CONFIG config;
WDF_DRIVER_CONFIG_INIT(&config, DeviceAdd);
return WdfDriverCreate(DriverObject, RegistryPath, WDF_NO_OBJECT_ATTRIBUTES, &config, WDF_NO_HANDLE);
For a multi-touch device, your HID Report Descriptor must conform to the Windows Precision Touchpad (PTP) or HID-over-I2C v1.0 spec. A minimal single-touch descriptor:
0x05, 0x0D, // Usage Page (Digitizer)
0x09, 0x04, // Usage (Touch Screen)
0xA1, 0x01, // Collection (Application)
0x85, 0x01, // Report ID 1
0x09, 0x22, // Usage (Finger)
0xA1, 0x00, // Collection (Physical)
0x09, 0x42, // Usage (Tip Switch)
0x15, 0x00, // Logical Minimum (0)
0x25, 0x01, // Logical Maximum (1)
0x75, 0x01, // Report Size (1)
0x95, 0x01, // Report Count (1)
0x81, 0x02, // Input (Data,Var,Abs)
0x09, 0x30, // Usage (X)
0x27, 0xFF, 0xFF, 0x00, 0x00, // Logical Maximum (65535)
0x75, 0x10, // Report Size (16)
0x95, 0x01, // Report Count (1)
0x81, 0x02, // Input (Data,Var,Abs)
... etc ...
0xC0, 0xC0
Your minidriver returns this descriptor in TouchCalibEvtGetDescriptor. The calibrated X and Y values must fit within the logical maximum defined here.