1 /* SPDX-License-Identifier: GPL-2.0+ */ 2 /* 3 * HID driver for UC-Logic devices not fully compliant with HID standard 4 * - tablet initialization and parameter retrieval 5 * 6 * Copyright (c) 2018 Nikolai Kondrashov 7 */ 8 9 /* 10 * This program is free software; you can redistribute it and/or modify it 11 * under the terms of the GNU General Public License as published by the Free 12 * Software Foundation; either version 2 of the License, or (at your option) 13 * any later version. 14 */ 15 16 #ifndef _HID_UCLOGIC_PARAMS_H 17 #define _HID_UCLOGIC_PARAMS_H 18 19 #include <linux/usb.h> 20 #include <linux/hid.h> 21 22 /* Types of pen in-range reporting */ 23 enum uclogic_params_pen_inrange { 24 /* Normal reports: zero - out of proximity, one - in proximity */ 25 UCLOGIC_PARAMS_PEN_INRANGE_NORMAL = 0, 26 /* Inverted reports: zero - in proximity, one - out of proximity */ 27 UCLOGIC_PARAMS_PEN_INRANGE_INVERTED, 28 /* No reports */ 29 UCLOGIC_PARAMS_PEN_INRANGE_NONE, 30 }; 31 32 /* Convert a pen in-range reporting type to a string */ 33 extern const char *uclogic_params_pen_inrange_to_str( 34 enum uclogic_params_pen_inrange inrange); 35 36 37 /* 38 * Pen report's subreport data. 39 */ 40 struct uclogic_params_pen_subreport { 41 /* 42 * The value of the second byte of the pen report indicating this 43 * subreport. If zero, the subreport should be considered invalid and 44 * not matched. 45 */ 46 __u8 value; 47 48 /* 49 * The ID to be assigned to the report, if the second byte of the pen 50 * report is equal to "value". Only valid if "value" is not zero. 51 */ 52 __u8 id; 53 }; 54 55 /* 56 * Tablet interface's pen input parameters. 57 * 58 * Must use declarative (descriptive) language, not imperative, to simplify 59 * understanding and maintain consistency. 60 * 61 * Noop (preserving functionality) when filled with zeroes. 62 */ 63 struct uclogic_params_pen { 64 /* 65 * Pointer to report descriptor describing the inputs. 66 * Allocated with kmalloc. 67 */ 68 __u8 *desc_ptr; 69 /* 70 * Size of the report descriptor. 71 * Only valid, if "desc_ptr" is not NULL. 72 */ 73 unsigned int desc_size; 74 /* Report ID, if reports should be tweaked, zero if not */ 75 unsigned int id; 76 /* The list of subreports */ 77 struct uclogic_params_pen_subreport subreport_list[1]; 78 /* Type of in-range reporting, only valid if "id" is not zero */ 79 enum uclogic_params_pen_inrange inrange; 80 /* 81 * True, if reports include fragmented high resolution coords, with 82 * high-order X and then Y bytes following the pressure field. 83 * Only valid if "id" is not zero. 84 */ 85 bool fragmented_hires; 86 /* 87 * True if the pen reports tilt in bytes at offset 10 (X) and 11 (Y), 88 * and the Y tilt direction is flipped. 89 * Only valid if "id" is not zero. 90 */ 91 bool tilt_y_flipped; 92 }; 93 94 /* 95 * Parameters of frame control inputs of a tablet interface. 96 * 97 * Must use declarative (descriptive) language, not imperative, to simplify 98 * understanding and maintain consistency. 99 * 100 * Noop (preserving functionality) when filled with zeroes. 101 */ 102 struct uclogic_params_frame { 103 /* 104 * Pointer to report descriptor describing the inputs. 105 * Allocated with kmalloc. 106 */ 107 __u8 *desc_ptr; 108 /* 109 * Size of the report descriptor. 110 * Only valid, if "desc_ptr" is not NULL. 111 */ 112 unsigned int desc_size; 113 /* 114 * Report ID, if reports should be tweaked, zero if not. 115 */ 116 unsigned int id; 117 /* 118 * Number of the least-significant bit of the 2-bit state of a rotary 119 * encoder, in the report. Cannot point to a 2-bit field crossing a 120 * byte boundary. Zero if not present. Only valid if "id" is not zero. 121 */ 122 unsigned int re_lsb; 123 /* 124 * Offset of the Wacom-style device ID byte in the report, to be set 125 * to pad device ID (0xf), for compatibility with Wacom drivers. Zero 126 * if no changes to the report should be made. Only valid if "id" is 127 * not zero. 128 */ 129 unsigned int dev_id_byte; 130 }; 131 132 /* 133 * Tablet interface report parameters. 134 * 135 * Must use declarative (descriptive) language, not imperative, to simplify 136 * understanding and maintain consistency. 137 * 138 * When filled with zeros represents a "noop" configuration - passes all 139 * reports unchanged and lets the generic HID driver handle everything. 140 * 141 * The resulting device report descriptor is assembled from all the report 142 * descriptor parts referenced by the structure. No order of assembly should 143 * be assumed. The structure represents original device report descriptor if 144 * all the parts are NULL. 145 */ 146 struct uclogic_params { 147 /* 148 * True if the whole interface is invalid, false otherwise. 149 */ 150 bool invalid; 151 /* 152 * Pointer to the common part of the replacement report descriptor, 153 * allocated with kmalloc. NULL if no common part is needed. 154 * Only valid, if "invalid" is false. 155 */ 156 __u8 *desc_ptr; 157 /* 158 * Size of the common part of the replacement report descriptor. 159 * Only valid, if "desc_ptr" is not NULL. 160 */ 161 unsigned int desc_size; 162 /* 163 * Pen parameters and optional report descriptor part. 164 * Only valid, if "invalid" is false. 165 */ 166 struct uclogic_params_pen pen; 167 /* 168 * The list of frame control parameters and optional report descriptor 169 * parts. Only valid, if "invalid" is false. 170 */ 171 struct uclogic_params_frame frame_list[1]; 172 }; 173 174 /* Initialize a tablet interface and discover its parameters */ 175 extern int uclogic_params_init(struct uclogic_params *params, 176 struct hid_device *hdev); 177 178 /* Tablet interface parameters *printf format string */ 179 #define UCLOGIC_PARAMS_FMT_STR \ 180 ".invalid = %s\n" \ 181 ".desc_ptr = %p\n" \ 182 ".desc_size = %u\n" \ 183 ".pen.desc_ptr = %p\n" \ 184 ".pen.desc_size = %u\n" \ 185 ".pen.id = %u\n" \ 186 ".pen.subreport_list[0] = {0x%02hhx, %hhu}\n" \ 187 ".pen.inrange = %s\n" \ 188 ".pen.fragmented_hires = %s\n" \ 189 ".pen.tilt_y_flipped = %s\n" \ 190 ".frame_list[0].desc_ptr = %p\n" \ 191 ".frame_list[0].desc_size = %u\n" \ 192 ".frame_list[0].id = %u\n" \ 193 ".frame_list[0].re_lsb = %u\n" \ 194 ".frame_list[0].dev_id_byte = %u\n" 195 196 /* Tablet interface parameters *printf format arguments */ 197 #define UCLOGIC_PARAMS_FMT_ARGS(_params) \ 198 ((_params)->invalid ? "true" : "false"), \ 199 (_params)->desc_ptr, \ 200 (_params)->desc_size, \ 201 (_params)->pen.desc_ptr, \ 202 (_params)->pen.desc_size, \ 203 (_params)->pen.id, \ 204 (_params)->pen.subreport_list[0].value, \ 205 (_params)->pen.subreport_list[0].id, \ 206 uclogic_params_pen_inrange_to_str((_params)->pen.inrange), \ 207 ((_params)->pen.fragmented_hires ? "true" : "false"), \ 208 ((_params)->pen.tilt_y_flipped ? "true" : "false"), \ 209 (_params)->frame_list[0].desc_ptr, \ 210 (_params)->frame_list[0].desc_size, \ 211 (_params)->frame_list[0].id, \ 212 (_params)->frame_list[0].re_lsb, \ 213 (_params)->frame_list[0].dev_id_byte 214 215 /* Get a replacement report descriptor for a tablet's interface. */ 216 extern int uclogic_params_get_desc(const struct uclogic_params *params, 217 __u8 **pdesc, 218 unsigned int *psize); 219 220 /* Free resources used by tablet interface's parameters */ 221 extern void uclogic_params_cleanup(struct uclogic_params *params); 222 223 #endif /* _HID_UCLOGIC_PARAMS_H */ 224