Skip to content

Commit 7e41866

Browse files
spbnickJiri Kosina
authored andcommitted
HID: uclogic: Split pen and frame raw event handling
In order to avoid ending up with a big uclogic_raw_event function, split it in two smaller functions: uclogic_raw_event_pen for the pen events and uclogic_raw_event_frame for the pad events. Signed-off-by: Nikolai Kondrashov <spbnick@gmail.com> Signed-off-by: José Expósito <jose.exposito89@gmail.com> Signed-off-by: Jiri Kosina <jkosina@suse.cz>
1 parent 5591403 commit 7e41866

1 file changed

Lines changed: 120 additions & 75 deletions

File tree

drivers/hid/hid-uclogic-core.c

Lines changed: 120 additions & 75 deletions
Original file line numberDiff line numberDiff line change
@@ -246,6 +246,123 @@ static int uclogic_resume(struct hid_device *hdev)
246246
}
247247
#endif
248248

249+
/**
250+
* uclogic_raw_event_pen - handle raw pen events (pen HID reports).
251+
*
252+
* @drvdata: Driver data.
253+
* @data: Report data buffer, can be modified.
254+
* @size: Report data size, bytes.
255+
*
256+
* Returns:
257+
* Negative value on error (stops event delivery), zero for success.
258+
*/
259+
static int uclogic_raw_event_pen(struct uclogic_drvdata *drvdata,
260+
u8 *data, int size)
261+
{
262+
struct uclogic_params *params = &drvdata->params;
263+
264+
WARN_ON(drvdata == NULL);
265+
WARN_ON(data == NULL && size != 0);
266+
267+
/* If in-range reports are inverted */
268+
if (params->pen.inrange ==
269+
UCLOGIC_PARAMS_PEN_INRANGE_INVERTED) {
270+
/* Invert the in-range bit */
271+
data[1] ^= 0x40;
272+
}
273+
/*
274+
* If report contains fragmented high-resolution pen
275+
* coordinates
276+
*/
277+
if (size >= 10 && params->pen.fragmented_hires) {
278+
u8 pressure_low_byte;
279+
u8 pressure_high_byte;
280+
281+
/* Lift pressure bytes */
282+
pressure_low_byte = data[6];
283+
pressure_high_byte = data[7];
284+
/*
285+
* Move Y coord to make space for high-order X
286+
* coord byte
287+
*/
288+
data[6] = data[5];
289+
data[5] = data[4];
290+
/* Move high-order X coord byte */
291+
data[4] = data[8];
292+
/* Move high-order Y coord byte */
293+
data[7] = data[9];
294+
/* Place pressure bytes */
295+
data[8] = pressure_low_byte;
296+
data[9] = pressure_high_byte;
297+
}
298+
/* If we need to emulate in-range detection */
299+
if (params->pen.inrange == UCLOGIC_PARAMS_PEN_INRANGE_NONE) {
300+
/* Set in-range bit */
301+
data[1] |= 0x40;
302+
/* (Re-)start in-range timeout */
303+
mod_timer(&drvdata->inrange_timer,
304+
jiffies + msecs_to_jiffies(100));
305+
}
306+
/* If we report tilt and Y direction is flipped */
307+
if (size >= 12 && params->pen.tilt_y_flipped)
308+
data[11] = -data[11];
309+
310+
return 0;
311+
}
312+
313+
/**
314+
* uclogic_raw_event_frame - handle raw frame events (frame HID reports).
315+
*
316+
* @drvdata: Driver data.
317+
* @data: Report data buffer, can be modified.
318+
* @size: Report data size, bytes.
319+
*
320+
* Returns:
321+
* Negative value on error (stops event delivery), zero for success.
322+
*/
323+
static int uclogic_raw_event_frame(struct uclogic_drvdata *drvdata,
324+
u8 *data, int size)
325+
{
326+
struct uclogic_params *params = &drvdata->params;
327+
328+
WARN_ON(drvdata == NULL);
329+
WARN_ON(data == NULL && size != 0);
330+
331+
/* If need to, and can, set pad device ID for Wacom drivers */
332+
if (params->frame.dev_id_byte > 0 &&
333+
params->frame.dev_id_byte < size) {
334+
data[params->frame.dev_id_byte] = 0xf;
335+
}
336+
/* If need to, and can, read rotary encoder state change */
337+
if (params->frame.re_lsb > 0 &&
338+
params->frame.re_lsb / 8 < size) {
339+
unsigned int byte = params->frame.re_lsb / 8;
340+
unsigned int bit = params->frame.re_lsb % 8;
341+
342+
u8 change;
343+
u8 prev_state = drvdata->re_state;
344+
/* Read Gray-coded state */
345+
u8 state = (data[byte] >> bit) & 0x3;
346+
/* Encode state change into 2-bit signed integer */
347+
if ((prev_state == 1 && state == 0) ||
348+
(prev_state == 2 && state == 3)) {
349+
change = 1;
350+
} else if ((prev_state == 2 && state == 0) ||
351+
(prev_state == 1 && state == 3)) {
352+
change = 3;
353+
} else {
354+
change = 0;
355+
}
356+
/* Write change */
357+
data[byte] = (data[byte] & ~((u8)3 << bit)) |
358+
(change << bit);
359+
/* Remember state */
360+
drvdata->re_state = state;
361+
}
362+
363+
return 0;
364+
}
365+
249366
static int uclogic_raw_event(struct hid_device *hdev,
250367
struct hid_report *report,
251368
u8 *data, int size)
@@ -265,85 +382,13 @@ static int uclogic_raw_event(struct hid_device *hdev,
265382
data[0] = params->frame.id;
266383
return 0;
267384
}
268-
/* If in-range reports are inverted */
269-
if (params->pen.inrange ==
270-
UCLOGIC_PARAMS_PEN_INRANGE_INVERTED) {
271-
/* Invert the in-range bit */
272-
data[1] ^= 0x40;
273-
}
274-
/*
275-
* If report contains fragmented high-resolution pen
276-
* coordinates
277-
*/
278-
if (size >= 10 && params->pen.fragmented_hires) {
279-
u8 pressure_low_byte;
280-
u8 pressure_high_byte;
281-
282-
/* Lift pressure bytes */
283-
pressure_low_byte = data[6];
284-
pressure_high_byte = data[7];
285-
/*
286-
* Move Y coord to make space for high-order X
287-
* coord byte
288-
*/
289-
data[6] = data[5];
290-
data[5] = data[4];
291-
/* Move high-order X coord byte */
292-
data[4] = data[8];
293-
/* Move high-order Y coord byte */
294-
data[7] = data[9];
295-
/* Place pressure bytes */
296-
data[8] = pressure_low_byte;
297-
data[9] = pressure_high_byte;
298-
}
299-
/* If we need to emulate in-range detection */
300-
if (params->pen.inrange == UCLOGIC_PARAMS_PEN_INRANGE_NONE) {
301-
/* Set in-range bit */
302-
data[1] |= 0x40;
303-
/* (Re-)start in-range timeout */
304-
mod_timer(&drvdata->inrange_timer,
305-
jiffies + msecs_to_jiffies(100));
306-
}
307-
/* If we report tilt and Y direction is flipped */
308-
if (size >= 12 && params->pen.tilt_y_flipped)
309-
data[11] = -data[11];
385+
return uclogic_raw_event_pen(drvdata, data, size);
310386
}
311387

312388
/* Tweak frame control reports, if necessary */
313389
if ((report->type == HID_INPUT_REPORT) &&
314-
(report->id == params->frame.id)) {
315-
/* If need to, and can, set pad device ID for Wacom drivers */
316-
if (params->frame.dev_id_byte > 0 &&
317-
params->frame.dev_id_byte < size) {
318-
data[params->frame.dev_id_byte] = 0xf;
319-
}
320-
/* If need to, and can, read rotary encoder state change */
321-
if (params->frame.re_lsb > 0 &&
322-
params->frame.re_lsb / 8 < size) {
323-
unsigned int byte = params->frame.re_lsb / 8;
324-
unsigned int bit = params->frame.re_lsb % 8;
325-
326-
u8 change;
327-
u8 prev_state = drvdata->re_state;
328-
/* Read Gray-coded state */
329-
u8 state = (data[byte] >> bit) & 0x3;
330-
/* Encode state change into 2-bit signed integer */
331-
if ((prev_state == 1 && state == 0) ||
332-
(prev_state == 2 && state == 3)) {
333-
change = 1;
334-
} else if ((prev_state == 2 && state == 0) ||
335-
(prev_state == 1 && state == 3)) {
336-
change = 3;
337-
} else {
338-
change = 0;
339-
}
340-
/* Write change */
341-
data[byte] = (data[byte] & ~((u8)3 << bit)) |
342-
(change << bit);
343-
/* Remember state */
344-
drvdata->re_state = state;
345-
}
346-
}
390+
(report->id == params->frame.id))
391+
return uclogic_raw_event_frame(drvdata, data, size);
347392

348393
return 0;
349394
}

0 commit comments

Comments
 (0)