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