19614219eSNikolai Kondrashov /* SPDX-License-Identifier: GPL-2.0+ */ 29614219eSNikolai Kondrashov /* 39614219eSNikolai Kondrashov * HID driver for UC-Logic devices not fully compliant with HID standard 49614219eSNikolai Kondrashov * - tablet initialization and parameter retrieval 59614219eSNikolai Kondrashov * 69614219eSNikolai Kondrashov * Copyright (c) 2018 Nikolai Kondrashov 79614219eSNikolai Kondrashov */ 89614219eSNikolai Kondrashov 99614219eSNikolai Kondrashov /* 109614219eSNikolai Kondrashov * This program is free software; you can redistribute it and/or modify it 119614219eSNikolai Kondrashov * under the terms of the GNU General Public License as published by the Free 129614219eSNikolai Kondrashov * Software Foundation; either version 2 of the License, or (at your option) 139614219eSNikolai Kondrashov * any later version. 149614219eSNikolai Kondrashov */ 159614219eSNikolai Kondrashov 169614219eSNikolai Kondrashov #ifndef _HID_UCLOGIC_PARAMS_H 179614219eSNikolai Kondrashov #define _HID_UCLOGIC_PARAMS_H 189614219eSNikolai Kondrashov 199614219eSNikolai Kondrashov #include <linux/usb.h> 209614219eSNikolai Kondrashov #include <linux/hid.h> 219614219eSNikolai Kondrashov 229614219eSNikolai Kondrashov /* Types of pen in-range reporting */ 239614219eSNikolai Kondrashov enum uclogic_params_pen_inrange { 249614219eSNikolai Kondrashov /* Normal reports: zero - out of proximity, one - in proximity */ 259614219eSNikolai Kondrashov UCLOGIC_PARAMS_PEN_INRANGE_NORMAL = 0, 269614219eSNikolai Kondrashov /* Inverted reports: zero - in proximity, one - out of proximity */ 279614219eSNikolai Kondrashov UCLOGIC_PARAMS_PEN_INRANGE_INVERTED, 2801309e29SNikolai Kondrashov /* No reports */ 2901309e29SNikolai Kondrashov UCLOGIC_PARAMS_PEN_INRANGE_NONE, 309614219eSNikolai Kondrashov }; 319614219eSNikolai Kondrashov 329614219eSNikolai Kondrashov /* Convert a pen in-range reporting type to a string */ 339614219eSNikolai Kondrashov extern const char *uclogic_params_pen_inrange_to_str( 349614219eSNikolai Kondrashov enum uclogic_params_pen_inrange inrange); 359614219eSNikolai Kondrashov 368b013098SNikolai Kondrashov 378b013098SNikolai Kondrashov /* 388b013098SNikolai Kondrashov * Pen report's subreport data. 398b013098SNikolai Kondrashov */ 408b013098SNikolai Kondrashov struct uclogic_params_pen_subreport { 418b013098SNikolai Kondrashov /* 42e6be956fSNikolai Kondrashov * The value of the second byte of the pen report indicating this 43e6be956fSNikolai Kondrashov * subreport. If zero, the subreport should be considered invalid and 44e6be956fSNikolai Kondrashov * not matched. 458b013098SNikolai Kondrashov */ 46e6be956fSNikolai Kondrashov __u8 value; 478b013098SNikolai Kondrashov 488b013098SNikolai Kondrashov /* 49e6be956fSNikolai Kondrashov * The ID to be assigned to the report, if the second byte of the pen 50e6be956fSNikolai Kondrashov * report is equal to "value". Only valid if "value" is not zero. 518b013098SNikolai Kondrashov */ 528b013098SNikolai Kondrashov __u8 id; 538b013098SNikolai Kondrashov }; 548b013098SNikolai Kondrashov 559614219eSNikolai Kondrashov /* 569614219eSNikolai Kondrashov * Tablet interface's pen input parameters. 579614219eSNikolai Kondrashov * 589614219eSNikolai Kondrashov * Must use declarative (descriptive) language, not imperative, to simplify 599614219eSNikolai Kondrashov * understanding and maintain consistency. 609614219eSNikolai Kondrashov * 619614219eSNikolai Kondrashov * Noop (preserving functionality) when filled with zeroes. 629614219eSNikolai Kondrashov */ 639614219eSNikolai Kondrashov struct uclogic_params_pen { 649614219eSNikolai Kondrashov /* 659614219eSNikolai Kondrashov * Pointer to report descriptor describing the inputs. 669614219eSNikolai Kondrashov * Allocated with kmalloc. 679614219eSNikolai Kondrashov */ 689614219eSNikolai Kondrashov __u8 *desc_ptr; 699614219eSNikolai Kondrashov /* 709614219eSNikolai Kondrashov * Size of the report descriptor. 719614219eSNikolai Kondrashov * Only valid, if "desc_ptr" is not NULL. 729614219eSNikolai Kondrashov */ 739614219eSNikolai Kondrashov unsigned int desc_size; 749614219eSNikolai Kondrashov /* Report ID, if reports should be tweaked, zero if not */ 759614219eSNikolai Kondrashov unsigned int id; 763e200d6cSNikolai Kondrashov /* The list of subreports, only valid if "id" is not zero */ 773e200d6cSNikolai Kondrashov struct uclogic_params_pen_subreport subreport_list[3]; 789614219eSNikolai Kondrashov /* Type of in-range reporting, only valid if "id" is not zero */ 799614219eSNikolai Kondrashov enum uclogic_params_pen_inrange inrange; 8059f2e0fcSNikolai Kondrashov /* 8159f2e0fcSNikolai Kondrashov * True, if reports include fragmented high resolution coords, with 8259f2e0fcSNikolai Kondrashov * high-order X and then Y bytes following the pressure field. 8359f2e0fcSNikolai Kondrashov * Only valid if "id" is not zero. 8459f2e0fcSNikolai Kondrashov */ 8559f2e0fcSNikolai Kondrashov bool fragmented_hires; 861324c5acSNikolai Kondrashov /* 871324c5acSNikolai Kondrashov * True if the pen reports tilt in bytes at offset 10 (X) and 11 (Y), 881324c5acSNikolai Kondrashov * and the Y tilt direction is flipped. 891324c5acSNikolai Kondrashov * Only valid if "id" is not zero. 901324c5acSNikolai Kondrashov */ 911324c5acSNikolai Kondrashov bool tilt_y_flipped; 929614219eSNikolai Kondrashov }; 939614219eSNikolai Kondrashov 949614219eSNikolai Kondrashov /* 959614219eSNikolai Kondrashov * Parameters of frame control inputs of a tablet interface. 969614219eSNikolai Kondrashov * 979614219eSNikolai Kondrashov * Must use declarative (descriptive) language, not imperative, to simplify 989614219eSNikolai Kondrashov * understanding and maintain consistency. 999614219eSNikolai Kondrashov * 1009614219eSNikolai Kondrashov * Noop (preserving functionality) when filled with zeroes. 1019614219eSNikolai Kondrashov */ 1029614219eSNikolai Kondrashov struct uclogic_params_frame { 1039614219eSNikolai Kondrashov /* 1049614219eSNikolai Kondrashov * Pointer to report descriptor describing the inputs. 1059614219eSNikolai Kondrashov * Allocated with kmalloc. 1069614219eSNikolai Kondrashov */ 1079614219eSNikolai Kondrashov __u8 *desc_ptr; 1089614219eSNikolai Kondrashov /* 1099614219eSNikolai Kondrashov * Size of the report descriptor. 1109614219eSNikolai Kondrashov * Only valid, if "desc_ptr" is not NULL. 1119614219eSNikolai Kondrashov */ 1129614219eSNikolai Kondrashov unsigned int desc_size; 1139614219eSNikolai Kondrashov /* 1149614219eSNikolai Kondrashov * Report ID, if reports should be tweaked, zero if not. 1159614219eSNikolai Kondrashov */ 1169614219eSNikolai Kondrashov unsigned int id; 117fde44ac5SNikolai Kondrashov /* 118ee007036SNikolai Kondrashov * The suffix to add to the input device name, if not NULL. 119ee007036SNikolai Kondrashov */ 120ee007036SNikolai Kondrashov const char *suffix; 121ee007036SNikolai Kondrashov /* 1228a47670cSNikolai Kondrashov * Number of the least-significant bit of the 2-bit state of a rotary 1238a47670cSNikolai Kondrashov * encoder, in the report. Cannot point to a 2-bit field crossing a 1248a47670cSNikolai Kondrashov * byte boundary. Zero if not present. Only valid if "id" is not zero. 1258a47670cSNikolai Kondrashov */ 1268a47670cSNikolai Kondrashov unsigned int re_lsb; 1278a47670cSNikolai Kondrashov /* 128fde44ac5SNikolai Kondrashov * Offset of the Wacom-style device ID byte in the report, to be set 129fde44ac5SNikolai Kondrashov * to pad device ID (0xf), for compatibility with Wacom drivers. Zero 130d170e8e0SNikolai Kondrashov * if no changes to the report should be made. The ID byte will be set 131d170e8e0SNikolai Kondrashov * to zero whenever the byte pointed by "touch_ring_byte" is zero, if 132d170e8e0SNikolai Kondrashov * the latter is valid. Only valid if "id" is not zero. 133fde44ac5SNikolai Kondrashov */ 134fde44ac5SNikolai Kondrashov unsigned int dev_id_byte; 135d170e8e0SNikolai Kondrashov /* 136d170e8e0SNikolai Kondrashov * Offset of the touch ring state byte, in the report. 137d170e8e0SNikolai Kondrashov * Zero if not present. If dev_id_byte is also valid and non-zero, 138d170e8e0SNikolai Kondrashov * then the device ID byte will be cleared when the byte pointed to by 139d170e8e0SNikolai Kondrashov * this offset is zero. Only valid if "id" is not zero. 140d170e8e0SNikolai Kondrashov */ 141d170e8e0SNikolai Kondrashov unsigned int touch_ring_byte; 142d170e8e0SNikolai Kondrashov 143d170e8e0SNikolai Kondrashov /* 144d170e8e0SNikolai Kondrashov * Maximum value of the touch ring report. 145d170e8e0SNikolai Kondrashov * The minimum valid value is considered to be one, 146d170e8e0SNikolai Kondrashov * with zero being out-of-proximity (finger lift) value. 147d170e8e0SNikolai Kondrashov */ 148d170e8e0SNikolai Kondrashov __s8 touch_ring_max; 149d170e8e0SNikolai Kondrashov 150d170e8e0SNikolai Kondrashov /* 151d170e8e0SNikolai Kondrashov * The value to anchor the reversed reports at. 152d170e8e0SNikolai Kondrashov * I.e. one, if the reports should be flipped without offset. 153d170e8e0SNikolai Kondrashov * Zero if no reversal should be done. 154d170e8e0SNikolai Kondrashov */ 155d170e8e0SNikolai Kondrashov __s8 touch_ring_flip_at; 1569614219eSNikolai Kondrashov }; 1579614219eSNikolai Kondrashov 1589614219eSNikolai Kondrashov /* 1599614219eSNikolai Kondrashov * Tablet interface report parameters. 1609614219eSNikolai Kondrashov * 1619614219eSNikolai Kondrashov * Must use declarative (descriptive) language, not imperative, to simplify 1629614219eSNikolai Kondrashov * understanding and maintain consistency. 1639614219eSNikolai Kondrashov * 1649614219eSNikolai Kondrashov * When filled with zeros represents a "noop" configuration - passes all 1659614219eSNikolai Kondrashov * reports unchanged and lets the generic HID driver handle everything. 1669614219eSNikolai Kondrashov * 1679614219eSNikolai Kondrashov * The resulting device report descriptor is assembled from all the report 1689614219eSNikolai Kondrashov * descriptor parts referenced by the structure. No order of assembly should 1699614219eSNikolai Kondrashov * be assumed. The structure represents original device report descriptor if 1709614219eSNikolai Kondrashov * all the parts are NULL. 1719614219eSNikolai Kondrashov */ 1729614219eSNikolai Kondrashov struct uclogic_params { 1739614219eSNikolai Kondrashov /* 1749614219eSNikolai Kondrashov * True if the whole interface is invalid, false otherwise. 1759614219eSNikolai Kondrashov */ 1769614219eSNikolai Kondrashov bool invalid; 1779614219eSNikolai Kondrashov /* 1789614219eSNikolai Kondrashov * Pointer to the common part of the replacement report descriptor, 1799614219eSNikolai Kondrashov * allocated with kmalloc. NULL if no common part is needed. 1809614219eSNikolai Kondrashov * Only valid, if "invalid" is false. 1819614219eSNikolai Kondrashov */ 1829614219eSNikolai Kondrashov __u8 *desc_ptr; 1839614219eSNikolai Kondrashov /* 1849614219eSNikolai Kondrashov * Size of the common part of the replacement report descriptor. 1859614219eSNikolai Kondrashov * Only valid, if "desc_ptr" is not NULL. 1869614219eSNikolai Kondrashov */ 1879614219eSNikolai Kondrashov unsigned int desc_size; 1889614219eSNikolai Kondrashov /* 1899614219eSNikolai Kondrashov * Pen parameters and optional report descriptor part. 190606dadc1SNikolai Kondrashov * Only valid, if "invalid" is false. 1919614219eSNikolai Kondrashov */ 1929614219eSNikolai Kondrashov struct uclogic_params_pen pen; 1939614219eSNikolai Kondrashov /* 194337fa051SNikolai Kondrashov * The list of frame control parameters and optional report descriptor 195337fa051SNikolai Kondrashov * parts. Only valid, if "invalid" is false. 1969614219eSNikolai Kondrashov */ 1973e200d6cSNikolai Kondrashov struct uclogic_params_frame frame_list[3]; 1989614219eSNikolai Kondrashov }; 1999614219eSNikolai Kondrashov 2009614219eSNikolai Kondrashov /* Initialize a tablet interface and discover its parameters */ 2019614219eSNikolai Kondrashov extern int uclogic_params_init(struct uclogic_params *params, 2029614219eSNikolai Kondrashov struct hid_device *hdev); 2039614219eSNikolai Kondrashov 2049614219eSNikolai Kondrashov /* Tablet interface parameters *printf format string */ 2059614219eSNikolai Kondrashov #define UCLOGIC_PARAMS_FMT_STR \ 2069614219eSNikolai Kondrashov ".invalid = %s\n" \ 2079614219eSNikolai Kondrashov ".desc_ptr = %p\n" \ 2089614219eSNikolai Kondrashov ".desc_size = %u\n" \ 209*eea4269fSNikolai Kondrashov ".pen = {\n" \ 210*eea4269fSNikolai Kondrashov "\t.desc_ptr = %p\n" \ 211*eea4269fSNikolai Kondrashov "\t.desc_size = %u\n" \ 212*eea4269fSNikolai Kondrashov "\t.id = %u\n" \ 213*eea4269fSNikolai Kondrashov "\t.subreport_list = {\n" \ 214*eea4269fSNikolai Kondrashov "\t\t{0x%02hhx, %hhu},\n" \ 215*eea4269fSNikolai Kondrashov "\t\t{0x%02hhx, %hhu},\n" \ 216*eea4269fSNikolai Kondrashov "\t\t{0x%02hhx, %hhu},\n" \ 217*eea4269fSNikolai Kondrashov "\t}\n" \ 218*eea4269fSNikolai Kondrashov "\t.inrange = %s\n" \ 219*eea4269fSNikolai Kondrashov "\t.fragmented_hires = %s\n" \ 220*eea4269fSNikolai Kondrashov "\t.tilt_y_flipped = %s\n" \ 221*eea4269fSNikolai Kondrashov "}\n" \ 222*eea4269fSNikolai Kondrashov ".frame_list = {\n" \ 223*eea4269fSNikolai Kondrashov "\t{\n" \ 224*eea4269fSNikolai Kondrashov "\t\t.desc_ptr = %p\n" \ 225*eea4269fSNikolai Kondrashov "\t\t.desc_size = %u\n" \ 226*eea4269fSNikolai Kondrashov "\t\t.id = %u\n" \ 227*eea4269fSNikolai Kondrashov "\t\t.suffix = %s\n" \ 228*eea4269fSNikolai Kondrashov "\t\t.re_lsb = %u\n" \ 229*eea4269fSNikolai Kondrashov "\t\t.dev_id_byte = %u\n" \ 230*eea4269fSNikolai Kondrashov "\t\t.touch_ring_byte = %u\n" \ 231*eea4269fSNikolai Kondrashov "\t\t.touch_ring_max = %hhd\n" \ 232*eea4269fSNikolai Kondrashov "\t\t.touch_ring_flip_at = %hhd\n" \ 233*eea4269fSNikolai Kondrashov "\t},\n" \ 234*eea4269fSNikolai Kondrashov "\t{\n" \ 235*eea4269fSNikolai Kondrashov "\t\t.desc_ptr = %p\n" \ 236*eea4269fSNikolai Kondrashov "\t\t.desc_size = %u\n" \ 237*eea4269fSNikolai Kondrashov "\t\t.id = %u\n" \ 238*eea4269fSNikolai Kondrashov "\t\t.suffix = %s\n" \ 239*eea4269fSNikolai Kondrashov "\t\t.re_lsb = %u\n" \ 240*eea4269fSNikolai Kondrashov "\t\t.dev_id_byte = %u\n" \ 241*eea4269fSNikolai Kondrashov "\t\t.touch_ring_byte = %u\n" \ 242*eea4269fSNikolai Kondrashov "\t\t.touch_ring_max = %hhd\n" \ 243*eea4269fSNikolai Kondrashov "\t\t.touch_ring_flip_at = %hhd\n" \ 244*eea4269fSNikolai Kondrashov "\t},\n" \ 245*eea4269fSNikolai Kondrashov "\t{\n" \ 246*eea4269fSNikolai Kondrashov "\t\t.desc_ptr = %p\n" \ 247*eea4269fSNikolai Kondrashov "\t\t.desc_size = %u\n" \ 248*eea4269fSNikolai Kondrashov "\t\t.id = %u\n" \ 249*eea4269fSNikolai Kondrashov "\t\t.suffix = %s\n" \ 250*eea4269fSNikolai Kondrashov "\t\t.re_lsb = %u\n" \ 251*eea4269fSNikolai Kondrashov "\t\t.dev_id_byte = %u\n" \ 252*eea4269fSNikolai Kondrashov "\t\t.touch_ring_byte = %u\n" \ 253*eea4269fSNikolai Kondrashov "\t\t.touch_ring_max = %hhd\n" \ 254*eea4269fSNikolai Kondrashov "\t\t.touch_ring_flip_at = %hhd\n" \ 255*eea4269fSNikolai Kondrashov "\t},\n" \ 256*eea4269fSNikolai Kondrashov "}\n" 2579614219eSNikolai Kondrashov 2589614219eSNikolai Kondrashov /* Tablet interface parameters *printf format arguments */ 2599614219eSNikolai Kondrashov #define UCLOGIC_PARAMS_FMT_ARGS(_params) \ 2609614219eSNikolai Kondrashov ((_params)->invalid ? "true" : "false"), \ 2619614219eSNikolai Kondrashov (_params)->desc_ptr, \ 2629614219eSNikolai Kondrashov (_params)->desc_size, \ 2639614219eSNikolai Kondrashov (_params)->pen.desc_ptr, \ 2649614219eSNikolai Kondrashov (_params)->pen.desc_size, \ 2659614219eSNikolai Kondrashov (_params)->pen.id, \ 266e6be956fSNikolai Kondrashov (_params)->pen.subreport_list[0].value, \ 2678b013098SNikolai Kondrashov (_params)->pen.subreport_list[0].id, \ 2683e200d6cSNikolai Kondrashov (_params)->pen.subreport_list[1].value, \ 2693e200d6cSNikolai Kondrashov (_params)->pen.subreport_list[1].id, \ 2703e200d6cSNikolai Kondrashov (_params)->pen.subreport_list[2].value, \ 2713e200d6cSNikolai Kondrashov (_params)->pen.subreport_list[2].id, \ 2729614219eSNikolai Kondrashov uclogic_params_pen_inrange_to_str((_params)->pen.inrange), \ 27359f2e0fcSNikolai Kondrashov ((_params)->pen.fragmented_hires ? "true" : "false"), \ 2741324c5acSNikolai Kondrashov ((_params)->pen.tilt_y_flipped ? "true" : "false"), \ 275337fa051SNikolai Kondrashov (_params)->frame_list[0].desc_ptr, \ 276337fa051SNikolai Kondrashov (_params)->frame_list[0].desc_size, \ 277337fa051SNikolai Kondrashov (_params)->frame_list[0].id, \ 278ee007036SNikolai Kondrashov (_params)->frame_list[0].suffix, \ 279337fa051SNikolai Kondrashov (_params)->frame_list[0].re_lsb, \ 280d170e8e0SNikolai Kondrashov (_params)->frame_list[0].dev_id_byte, \ 281d170e8e0SNikolai Kondrashov (_params)->frame_list[0].touch_ring_byte, \ 282d170e8e0SNikolai Kondrashov (_params)->frame_list[0].touch_ring_max, \ 2833e200d6cSNikolai Kondrashov (_params)->frame_list[0].touch_ring_flip_at, \ 2843e200d6cSNikolai Kondrashov (_params)->frame_list[1].desc_ptr, \ 2853e200d6cSNikolai Kondrashov (_params)->frame_list[1].desc_size, \ 2863e200d6cSNikolai Kondrashov (_params)->frame_list[1].id, \ 2873e200d6cSNikolai Kondrashov (_params)->frame_list[1].suffix, \ 2883e200d6cSNikolai Kondrashov (_params)->frame_list[1].re_lsb, \ 2893e200d6cSNikolai Kondrashov (_params)->frame_list[1].dev_id_byte, \ 2903e200d6cSNikolai Kondrashov (_params)->frame_list[1].touch_ring_byte, \ 2913e200d6cSNikolai Kondrashov (_params)->frame_list[1].touch_ring_max, \ 2923e200d6cSNikolai Kondrashov (_params)->frame_list[1].touch_ring_flip_at, \ 2933e200d6cSNikolai Kondrashov (_params)->frame_list[2].desc_ptr, \ 2943e200d6cSNikolai Kondrashov (_params)->frame_list[2].desc_size, \ 2953e200d6cSNikolai Kondrashov (_params)->frame_list[2].id, \ 2963e200d6cSNikolai Kondrashov (_params)->frame_list[2].suffix, \ 2973e200d6cSNikolai Kondrashov (_params)->frame_list[2].re_lsb, \ 2983e200d6cSNikolai Kondrashov (_params)->frame_list[2].dev_id_byte, \ 2993e200d6cSNikolai Kondrashov (_params)->frame_list[2].touch_ring_byte, \ 3003e200d6cSNikolai Kondrashov (_params)->frame_list[2].touch_ring_max, \ 3013e200d6cSNikolai Kondrashov (_params)->frame_list[2].touch_ring_flip_at 3029614219eSNikolai Kondrashov 3039614219eSNikolai Kondrashov /* Get a replacement report descriptor for a tablet's interface. */ 3049614219eSNikolai Kondrashov extern int uclogic_params_get_desc(const struct uclogic_params *params, 3059614219eSNikolai Kondrashov __u8 **pdesc, 3069614219eSNikolai Kondrashov unsigned int *psize); 3079614219eSNikolai Kondrashov 3089614219eSNikolai Kondrashov /* Free resources used by tablet interface's parameters */ 3099614219eSNikolai Kondrashov extern void uclogic_params_cleanup(struct uclogic_params *params); 3109614219eSNikolai Kondrashov 3119614219eSNikolai Kondrashov #endif /* _HID_UCLOGIC_PARAMS_H */ 312