Calibration: Kmdf Hid Minidriver For Touch I2c Device
Once the data is loaded, you must format it as an I2C write request.
NTSTATUS ApplyCalibrationToHardware(WDFIOTARGET I2CTarget, PTOUCH_CALIBRATION_DATA CalibData)
NTSTATUS status;
WDF_MEMORY_DESCRIPTOR memDesc;
WDF_MEMORY_DESCRIPTOR inputDesc;
PUCHAR writeBuffer;
ULONG writeLength = sizeof(TOUCH_CMD_SET_CALIBRATION) + sizeof(TOUCH_CALIBRATION_DATA);
// Allocate a buffer for the I2C Write (Command + Data)
writeBuffer = ExAllocatePoolWithTag(NonPagedPool, writeLength, 'ClaC');
if (!writeBuffer) return STATUS_INSUFFICIENT_RESOURCES;
// Pack the command
writeBuffer[0] = TOUCH_CMD_SET_CALIBRATION;
RtlCopyMemory(&writeBuffer[1], CalibData, sizeof(TOUCH_CALIBRATION_DATA));
WDF_MEMORY_DESCRIPTOR_INIT_BUFFER(&inputDesc, writeBuffer, writeLength);
// Perform the I2C Write
// This assumes the I2C target is already opened
status = WdfIoTargetSendWriteSynchronously(
I2CTarget,
NULL,
&inputDesc,
NULL,
NULL
);
ExFreePool(writeBuffer);
return status;
In your EvtDevicePrepareHardware, retrieve the I2C connection resources. The I2C target is represented by a WDFIOTARGET.
NTSTATUS TouchCalibGetI2cTarget(WDFDEVICE Device, WDFIOTARGET *IoTarget) DECLARE_CONST_UNICODE_STRING(i2cResource, L"I2C1"); WDF_IO_TARGET_OPEN_PARAMS openParams; WDFIOTARGET target;// Get the I2C controller object from the system NTSTATUS status = WdfDeviceGetDeviceStackIoType(Device, ...); status = WdfIoTargetCreate(Device, WDF_NO_OBJECT_ATTRIBUTES, &target); WDF_IO_TARGET_OPEN_PARAMS_INIT_OPEN_BY_NAME(&openParams, &i2cResource, FILE_ANY_ACCESS); status = WdfIoTargetOpen(target, &openParams); *IoTarget = target; return status;
Assume your raw touch data from I2C is 3 bytes per coordinate (X/Y pressure). You read a packet: kmdf hid minidriver for touch i2c device calibration
typedef struct _RAW_TOUCH_REPORT
UCHAR TouchID;
USHORT RawX;
USHORT RawY;
UCHAR Pressure;
RAW_TOUCH_REPORT;
Calibration parameters could be stored in the registry, e.g.:
[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\TouchCalibMini\Parameters]
"CalibMatrix"=hex:01,00,00,00,...
A simple linear calibration:
VOID ApplyCalibration(RAW_TOUCH_REPORT *raw, HID_TOUCH_REPORT *calib, PCALIB_PARAMS params)
calib->X = (raw->RawX - params->XMin) * params->ScreenWidth / (params->XMax - params->XMin);
calib->Y = (raw->RawY - params->YMin) * params->ScreenHeight / (params->YMax - params->YMin);
// Clip to screen bounds
if (calib->X > params->ScreenWidth) calib->X = params->ScreenWidth;
if (calib->Y > params->ScreenHeight) calib->Y = params->ScreenHeight;
Advanced calibration uses an affine matrix for rotation, skew, and translation:
X_cal = A * X_raw + B * Y_raw + C
Y_cal = D * X_raw + E * Y_raw + F
This corrects for misaligned sensor grids. Once the data is loaded, you must format