summaryrefslogtreecommitdiffstats
path: root/drivers/hid/hid-uclogic-params.h
blob: d6ffadb2f601568a17b826aa3406b49713dfcb1e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
/* SPDX-License-Identifier: GPL-2.0+ */
/*
 *  HID driver for UC-Logic devices not fully compliant with HID standard
 *  - tablet initialization and parameter retrieval
 *
 *  Copyright (c) 2018 Nikolai Kondrashov
 */

/*
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License as published by the Free
 * Software Foundation; either version 2 of the License, or (at your option)
 * any later version.
 */

#ifndef _HID_UCLOGIC_PARAMS_H
#define _HID_UCLOGIC_PARAMS_H

#include <linux/usb.h>
#include <linux/hid.h>
#include <linux/list.h>

#define UCLOGIC_MOUSE_FRAME_QUIRK	BIT(0)
#define UCLOGIC_BATTERY_QUIRK		BIT(1)

/* Types of pen in-range reporting */
enum uclogic_params_pen_inrange {
	/* Normal reports: zero - out of proximity, one - in proximity */
	UCLOGIC_PARAMS_PEN_INRANGE_NORMAL = 0,
	/* Inverted reports: zero - in proximity, one - out of proximity */
	UCLOGIC_PARAMS_PEN_INRANGE_INVERTED,
	/* No reports */
	UCLOGIC_PARAMS_PEN_INRANGE_NONE,
};

/* Types of frames */
enum uclogic_params_frame_type {
	/* Frame with buttons */
	UCLOGIC_PARAMS_FRAME_BUTTONS = 0,
	/* Frame with buttons and a dial */
	UCLOGIC_PARAMS_FRAME_DIAL,
	/* Frame with buttons and a mouse (shaped as a dial + touchpad) */
	UCLOGIC_PARAMS_FRAME_MOUSE,
};

/*
 * Pen report's subreport data.
 */
struct uclogic_params_pen_subreport {
	/*
	 * The value of the second byte of the pen report indicating this
	 * subreport. If zero, the subreport should be considered invalid and
	 * not matched.
	 */
	__u8 value;

	/*
	 * The ID to be assigned to the report, if the second byte of the pen
	 * report is equal to "value". Only valid if "value" is not zero.
	 */
	__u8 id;
};

/*
 * Tablet interface's pen input parameters.
 *
 * Must use declarative (descriptive) language, not imperative, to simplify
 * understanding and maintain consistency.
 *
 * Noop (preserving functionality) when filled with zeroes.
 */
struct uclogic_params_pen {
	/*
	 * True if pen usage is invalid for this interface and should be
	 * ignored, false otherwise.
	 */
	bool usage_invalid;
	/*
	 * Pointer to report descriptor part describing the pen inputs.
	 * Allocated with kmalloc. NULL if the part is not specified.
	 */
	__u8 *desc_ptr;
	/*
	 * Size of the report descriptor.
	 * Only valid, if "desc_ptr" is not NULL.
	 */
	unsigned int desc_size;
	/* Report ID, if reports should be tweaked, zero if not */
	unsigned int id;
	/* The list of subreports, only valid if "id" is not zero */
	struct uclogic_params_pen_subreport subreport_list[3];
	/* Type of in-range reporting, only valid if "id" is not zero */
	enum uclogic_params_pen_inrange inrange;
	/*
	 * True, if reports include fragmented high resolution coords, with
	 * high-order X and then Y bytes following the pressure field.
	 * Only valid if "id" is not zero.
	 */
	bool fragmented_hires;
	/*
	 * True if the pen reports tilt in bytes at offset 10 (X) and 11 (Y),
	 * and the Y tilt direction is flipped.
	 * Only valid if "id" is not zero.
	 */
	bool tilt_y_flipped;
};

/*
 * Parameters of frame control inputs of a tablet interface.
 *
 * Must use declarative (descriptive) language, not imperative, to simplify
 * understanding and maintain consistency.
 *
 * Noop (preserving functionality) when filled with zeroes.
 */
struct uclogic_params_frame {
	/*
	 * Pointer to report descriptor part describing the frame inputs.
	 * Allocated with kmalloc. NULL if the part is not specified.
	 */
	__u8 *desc_ptr;
	/*
	 * Size of the report descriptor.
	 * Only valid, if "desc_ptr" is not NULL.
	 */
	unsigned int desc_size;
	/*
	 * Report ID, if reports should be tweaked, zero if not.
	 */
	unsigned int id;
	/*
	 * The suffix to add to the input device name, if not NULL.
	 */
	const char *suffix;
	/*
	 * Number of the least-significant bit of the 2-bit state of a rotary
	 * encoder, in the report. Cannot point to a 2-bit field crossing a
	 * byte boundary. Zero if not present. Only valid if "id" is not zero.
	 */
	unsigned int re_lsb;
	/*
	 * Offset of the Wacom-style device ID byte in the report, to be set
	 * to pad device ID (0xf), for compatibility with Wacom drivers. Zero
	 * if no changes to the report should be made. The ID byte will be set
	 * to zero whenever the byte pointed by "touch_byte" is zero, if
	 * the latter is valid. Only valid if "id" is not zero.
	 */
	unsigned int dev_id_byte;
	/*
	 * Offset of the touch ring/strip state byte, in the report.
	 * Zero if not present. If dev_id_byte is also valid and non-zero,
	 * then the device ID byte will be cleared when the byte pointed to by
	 * this offset is zero. Only valid if "id" is not zero.
	 */
	unsigned int touch_byte;
	/*
	 * The value to anchor the reversed touch ring/strip reports at.
	 * I.e. one, if the reports should be flipped without offset.
	 * Zero if no reversal should be done.
	 * Only valid if "touch_byte" is valid and not zero.
	 */
	__s8 touch_flip_at;
	/*
	 * Maximum value of the touch ring/strip report around which the value
	 * should be wrapped when flipping according to "touch_flip_at".
	 * The minimum valid value is considered to be one, with zero being
	 * out-of-proximity (finger lift) value.
	 * Only valid if "touch_flip_at" is valid and not zero.
	 */
	__s8 touch_max;
	/*
	 * Offset of the bitmap dial byte, in the report. Zero if not present.
	 * Only valid if "id" is not zero. A bitmap dial sends reports with a
	 * dedicated bit per direction: 1 means clockwise rotation, 2 means
	 * counterclockwise, as opposed to the normal 1 and -1.
	 */
	unsigned int bitmap_dial_byte;
};

/*
 * List of works to be performed when a certain raw event is received.
 */
struct uclogic_raw_event_hook {
	struct hid_device *hdev;
	__u8 *event;
	size_t size;
	struct work_struct work;
	struct list_head list;
};

/*
 * Tablet interface report parameters.
 *
 * Must use declarative (descriptive) language, not imperative, to simplify
 * understanding and maintain consistency.
 *
 * When filled with zeros represents a "noop" configuration - passes all
 * reports unchanged and lets the generic HID driver handle everything.
 *
 * The resulting device report descriptor is assembled from all the report
 * descriptor parts referenced by the structure. No order of assembly should
 * be assumed. The structure represents original device report descriptor if
 * all the parts are NULL.
 */
struct uclogic_params {
	/*
	 * True if the whole interface is invalid, false otherwise.
	 */
	bool invalid;
	/*
	 * Pointer to the common part of the replacement report descriptor,
	 * allocated with kmalloc. NULL if no common part is needed.
	 * Only valid, if "invalid" is false.
	 */
	__u8 *desc_ptr;
	/*
	 * Size of the common part of the replacement report descriptor.
	 * Only valid, if "desc_ptr" is valid and not NULL.
	 */
	unsigned int desc_size;
	/*
	 * Pen parameters and optional report descriptor part.
	 * Only valid, if "invalid" is false.
	 */
	struct uclogic_params_pen pen;
	/*
	 * The list of frame control parameters and optional report descriptor
	 * parts. Only valid, if "invalid" is false.
	 */
	struct uclogic_params_frame frame_list[3];
	/*
	 * List of event hooks.
	 */
	struct uclogic_raw_event_hook *event_hooks;
};

/* Driver data */
struct uclogic_drvdata {
	/* Interface parameters */
	struct uclogic_params params;
	/* Pointer to the replacement report descriptor. NULL if none. */
	__u8 *desc_ptr;
	/*
	 * Size of the replacement report descriptor.
	 * Only valid if desc_ptr is not NULL
	 */
	unsigned int desc_size;
	/* Pen input device */
	struct input_dev *pen_input;
	/* In-range timer */
	struct timer_list inrange_timer;
	/* Last rotary encoder state, or U8_MAX for none */
	u8 re_state;
	/* Device quirks */
	unsigned long quirks;
};

/* Initialize a tablet interface and discover its parameters */
extern int uclogic_params_init(struct uclogic_params *params,
				struct hid_device *hdev);

/* Get a replacement report descriptor for a tablet's interface. */
extern int uclogic_params_get_desc(const struct uclogic_params *params,
					__u8 **pdesc,
					unsigned int *psize);

/* Free resources used by tablet interface's parameters */
extern void uclogic_params_cleanup(struct uclogic_params *params);

/* Dump tablet interface parameters with hid_dbg() */
extern void uclogic_params_hid_dbg(const struct hid_device *hdev,
					const struct uclogic_params *params);

#endif /* _HID_UCLOGIC_PARAMS_H */