简体   繁体   中英

X and Y coordinate from Precision touchpad with raw input

Background

I am trying to get the touch coordinates from precision touchpads with C++ in Win10 with the program running in background.


Research

Rawinput can get data in background.

I can get the data with these usage id and pages from microsoft :

Member  Description                         Page    ID      Mandatory/Optional
X       X coordinate of contact position    0x01    0x30    Mandatory for T Optional for C
Y       Y coordinate of contact position    0x01    0x31    Mandatory for T Optional for C

I can put the two of them together with HIDP_functions, from this answer .


Code

case WM_INPUT: {
    UINT dwSize;
    GetRawInputData((HRAWINPUT)lParam, RID_INPUT, NULL, &dwSize, sizeof(RAWINPUTHEADER));
    LPBYTE lpb = new BYTE[dwSize];
    if (lpb == NULL) {
        return 0;
    }
    RAWINPUT* raw = (RAWINPUT*)lpb;
    GetRawInputDeviceInfo(raw->header.hDevice, RIDI_PREPARSEDDATA, NULL, &dwSize);
    PHIDP_PREPARSED_DATA preparsedData = (PHIDP_PREPARSED_DATA)HeapAlloc(GetProcessHeap(), 0, dwSize);
    GetRawInputDeviceInfo(raw->header.hDevice, RIDI_PREPARSEDDATA, preparsedData, &dwSize); 

    HIDP_CAPS caps;
    HidP_GetCaps(preparsedData, &caps);
    USHORT capsLength = caps.NumberInputValueCaps;
    PHIDP_VALUE_CAPS valueCaps = (PHIDP_VALUE_CAPS)HeapAlloc(GetProcessHeap(), 0, capsLength*sizeof(HIDP_VALUE_CAPS));

    HidP_GetValueCaps(HidP_Input, valueCaps, &capsLength, preparsedData);
    for (int i=0; i < capsLength; i++) {
        CHAR value;
        USHORT valuelength = valueCaps[i].BitSize * valueCaps[i].ReportCount;
        HidP_GetUsageValueArray (HidP_Input, valueCaps[i].UsagePage, 0, valueCaps[i].NotRange.Usage, &value, valuelength, preparsedData, (PCHAR)raw->data.hid.bRawData, raw->data.hid.dwSizeHid);
        std::cout << valueCaps[i].UsagePage << "  " << valueCaps[i].NotRange.Usage <<std::endl;
        std::cout << value << std::endl;

        switch(valueCaps[i].NotRange.Usage) {
            case 0x30:    // X-axis
                std::cout << "X: " << value << std::endl;
                break;

            case 0x31:    // Y-axis
                std::cout << "y: " << value << std::endl;
                break;
        }
    }

}

Problem

I compiled the code and touch my touchpad, but all the outputs are:

0  0
³

Have I done anything wrong? Does anyone have any idea?

A packet of minimal Contact ID, x, y, Contact, Scan may contain multiple Contact ID, x, y triplets for multiple points and then must be used valueCaps[i].LinkCollection from valueCaps[] array which increases from 1 for up to five points.

HidP_GetUsageValue
(
    HidP_Input, 
    valueCaps[i].UsagePage, 
    valueCaps[i].LinkCollection, //** !!!!!
    valueCaps[i].NotRange.Usage, 
    &value, 
    preparsedData, 
    (PCHAR)raw->data.hid.bRawData, 
    raw->data.hid.dwSizeHid
);

Coordinates are in array if valueCaps[i].UsagePage = 1 and valueCaps[i].NotRange.Usage = 0x30 (x), valueCaps[i].NotRange.Usage = 0x30 (y)

Very important are xLogicalMin, yLogicalMin, xLogicalMax, yLogicalMax in valueCaps[i] array

    xLogicalMin = valueCaps[i].LogicalMin;
    xLogicalMax = valueCaps[i].LogicalMax;
    xPhysicalMin = valueCaps[i].PhysicalMin;
    xPhysicalMax = valueCaps[i].PhysicalMax;

All allocated spaces must be correct released !!!!!

Pressing оп perimeter points of touchpad for initiate multiple functions, or cells of grid on touchpad as on ASUS NumberPad also with limited functions of capacitive and active pen, one finger flicks, moving along four sides of touchpad for scrolling / scale, moving cursor with one finger and click, press, press plus move, double click, click plus press second finger. Two finger operations count increased at finger space near or far possible with coordinates. With coordinates, times in "Scan" and contacts in "Contact" all possible complex gestures on touchpad are accessible.

Call of Your Program

HidP_GetUsageValueArray (HidP_Input, valueCaps[i].UsagePage, 0, valueCaps[i].NotRange.Usage, &value, valuelength, preparsedData, (PCHAR)raw->data.hid.bRawData, raw->data.hid.dwSizeHid);

returns HIDP_STATUS_NOT_VALUE_ARRAY = 0xc011000b

In Array valueCaps[] on my notebook with PTP are valueCaps[i].UsagePage = 1 and valueCaps[i].NotRange.Usage = 0x30 / 0x31. You can use simple

HidP_GetUsageValue ( HidP_Input, valueCaps[i].UsagePage, 0, valueCaps[i].NotRange.Usage, &value, preparsedData, (PCHAR)raw->data.hid.bRawData, raw->data.hid.dwSizeHid );

with 1 / 30h, 1 / 31h

corresponding to

_Must_inspect_result_ NTSTATUS __stdcall HidP_GetUsageValue( In HIDP_REPORT_TYPE ReportType, In USAGE UsagePage, _In_opt_ USHORT LinkCollection, In USAGE Usage, Out PULONG UsageValue, In PHIDP_PREPARSED_DATA PreparsedData, _In_reads_bytes_(ReportLength) PCHAR Report, In ULONG ReportLength );

and value ( UsageValue ) must be LONG !!!!!.

First value at WM_INPUT comes with UsagePage 0x0D Usage 0x51

Contact ID Uniquely identifies the contact within a given frame 0x0D 0x51 Mandatory

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM