Skip to content

Commit 337fa05

Browse files
spbnickJiri Kosina
authored andcommitted
HID: uclogic: Support multiple frame input devices
Add support for multiple frame input devices and their parameters to the UC-Logic driver. This prepares for creating a separate input device for Huion HS610 virtual touch ring reports. Signed-off-by: Nikolai Kondrashov <[email protected]> Signed-off-by: José Expósito <[email protected]> Signed-off-by: Jiri Kosina <[email protected]>
1 parent 2daaeff commit 337fa05

File tree

3 files changed

+74
-71
lines changed

3 files changed

+74
-71
lines changed

drivers/hid/hid-uclogic-core.c

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -296,17 +296,18 @@ static int uclogic_raw_event_pen(struct uclogic_drvdata *drvdata,
296296
* uclogic_raw_event_frame - handle raw frame events (frame HID reports).
297297
*
298298
* @drvdata: Driver data.
299+
* @frame: The parameters of the frame controls to handle.
299300
* @data: Report data buffer, can be modified.
300301
* @size: Report data size, bytes.
301302
*
302303
* Returns:
303304
* Negative value on error (stops event delivery), zero for success.
304305
*/
305-
static int uclogic_raw_event_frame(struct uclogic_drvdata *drvdata,
306-
u8 *data, int size)
306+
static int uclogic_raw_event_frame(
307+
struct uclogic_drvdata *drvdata,
308+
const struct uclogic_params_frame *frame,
309+
u8 *data, int size)
307310
{
308-
struct uclogic_params_frame *frame = &drvdata->params.frame;
309-
310311
WARN_ON(drvdata == NULL);
311312
WARN_ON(data == NULL && size != 0);
312313

@@ -352,6 +353,7 @@ static int uclogic_raw_event(struct hid_device *hdev,
352353
struct uclogic_params *params = &drvdata->params;
353354
struct uclogic_params_pen_subreport *subreport;
354355
struct uclogic_params_pen_subreport *subreport_list_end;
356+
size_t i;
355357

356358
/* Do not handle anything but input reports */
357359
if (report->type != HID_INPUT_REPORT)
@@ -382,8 +384,13 @@ static int uclogic_raw_event(struct hid_device *hdev,
382384
}
383385

384386
/* Tweak frame control reports, if necessary */
385-
if (report_id == params->frame.id)
386-
return uclogic_raw_event_frame(drvdata, data, size);
387+
for (i = 0; i < ARRAY_SIZE(params->frame_list); i++) {
388+
if (report_id == params->frame_list[i].id) {
389+
return uclogic_raw_event_frame(
390+
drvdata, &params->frame_list[i],
391+
data, size);
392+
}
393+
}
387394

388395
break;
389396
}

drivers/hid/hid-uclogic-params.c

Lines changed: 48 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -512,9 +512,12 @@ static int uclogic_params_frame_init_v1(struct uclogic_params_frame *frame,
512512
void uclogic_params_cleanup(struct uclogic_params *params)
513513
{
514514
if (!params->invalid) {
515+
size_t i;
515516
kfree(params->desc_ptr);
516517
uclogic_params_pen_cleanup(&params->pen);
517-
uclogic_params_frame_cleanup(&params->frame);
518+
for (i = 0; i < ARRAY_SIZE(params->frame_list); i++)
519+
uclogic_params_frame_cleanup(&params->frame_list[i]);
520+
518521
memset(params, 0, sizeof(*params));
519522
}
520523
}
@@ -542,60 +545,53 @@ int uclogic_params_get_desc(const struct uclogic_params *params,
542545
__u8 **pdesc,
543546
unsigned int *psize)
544547
{
545-
bool common_present;
546-
bool pen_present;
547-
bool frame_present;
548-
unsigned int size;
548+
int rc = -ENOMEM;
549+
bool present = false;
550+
unsigned int size = 0;
549551
__u8 *desc = NULL;
552+
size_t i;
550553

551554
/* Check arguments */
552555
if (params == NULL || pdesc == NULL || psize == NULL)
553556
return -EINVAL;
554557

555-
size = 0;
556-
557-
common_present = (params->desc_ptr != NULL);
558-
pen_present = (params->pen.desc_ptr != NULL);
559-
frame_present = (params->frame.desc_ptr != NULL);
560-
561-
if (common_present)
562-
size += params->desc_size;
563-
if (pen_present)
564-
size += params->pen.desc_size;
565-
if (frame_present)
566-
size += params->frame.desc_size;
567-
568-
if (common_present || pen_present || frame_present) {
569-
__u8 *p;
570-
571-
desc = kmalloc(size, GFP_KERNEL);
572-
if (desc == NULL)
573-
return -ENOMEM;
574-
p = desc;
575-
576-
if (common_present) {
577-
memcpy(p, params->desc_ptr,
578-
params->desc_size);
579-
p += params->desc_size;
580-
}
581-
if (pen_present) {
582-
memcpy(p, params->pen.desc_ptr,
583-
params->pen.desc_size);
584-
p += params->pen.desc_size;
585-
}
586-
if (frame_present) {
587-
memcpy(p, params->frame.desc_ptr,
588-
params->frame.desc_size);
589-
p += params->frame.desc_size;
590-
}
558+
/* Concatenate descriptors */
559+
#define ADD_DESC(_desc_ptr, _desc_size) \
560+
do { \
561+
unsigned int new_size; \
562+
__u8 *new_desc; \
563+
if ((_desc_ptr) == NULL) { \
564+
break; \
565+
} \
566+
new_size = size + (_desc_size); \
567+
new_desc = krealloc(desc, new_size, GFP_KERNEL); \
568+
if (new_desc == NULL) { \
569+
goto cleanup; \
570+
} \
571+
memcpy(new_desc + size, (_desc_ptr), (_desc_size)); \
572+
desc = new_desc; \
573+
size = new_size; \
574+
present = true; \
575+
} while (0)
576+
577+
ADD_DESC(params->desc_ptr, params->desc_size);
578+
ADD_DESC(params->pen.desc_ptr, params->pen.desc_size);
579+
for (i = 0; i < ARRAY_SIZE(params->frame_list); i++) {
580+
ADD_DESC(params->frame_list[i].desc_ptr,
581+
params->frame_list[i].desc_size);
582+
}
591583

592-
WARN_ON(p != desc + size);
584+
#undef ADD_DESC
593585

586+
if (present) {
587+
*pdesc = desc;
594588
*psize = size;
589+
desc = NULL;
595590
}
596-
597-
*pdesc = desc;
598-
return 0;
591+
rc = 0;
592+
cleanup:
593+
kfree(desc);
594+
return rc;
599595
}
600596

601597
/**
@@ -751,7 +747,7 @@ static int uclogic_params_huion_init(struct uclogic_params *params,
751747
hid_dbg(hdev, "pen v2 parameters found\n");
752748
/* Create v2 frame parameters */
753749
rc = uclogic_params_frame_init_with_desc(
754-
&p.frame,
750+
&p.frame_list[0],
755751
uclogic_rdesc_v2_frame_arr,
756752
uclogic_rdesc_v2_frame_size,
757753
UCLOGIC_RDESC_V2_FRAME_ID);
@@ -779,7 +775,7 @@ static int uclogic_params_huion_init(struct uclogic_params *params,
779775
} else if (found) {
780776
hid_dbg(hdev, "pen v1 parameters found\n");
781777
/* Try to probe v1 frame */
782-
rc = uclogic_params_frame_init_v1(&p.frame,
778+
rc = uclogic_params_frame_init_v1(&p.frame_list[0],
783779
&found, hdev);
784780
if (rc != 0) {
785781
hid_err(hdev, "v1 frame probing failed: %d\n", rc);
@@ -1033,7 +1029,7 @@ int uclogic_params_init(struct uclogic_params *params,
10331029
}
10341030
/* Initialize frame parameters */
10351031
rc = uclogic_params_frame_init_with_desc(
1036-
&p.frame,
1032+
&p.frame_list[0],
10371033
uclogic_rdesc_xppen_deco01_frame_arr,
10381034
uclogic_rdesc_xppen_deco01_frame_size,
10391035
0);
@@ -1059,7 +1055,7 @@ int uclogic_params_init(struct uclogic_params *params,
10591055
goto cleanup;
10601056
} else if (found) {
10611057
rc = uclogic_params_frame_init_with_desc(
1062-
&p.frame,
1058+
&p.frame_list[0],
10631059
uclogic_rdesc_ugee_g5_frame_arr,
10641060
uclogic_rdesc_ugee_g5_frame_size,
10651061
UCLOGIC_RDESC_UGEE_G5_FRAME_ID);
@@ -1069,9 +1065,9 @@ int uclogic_params_init(struct uclogic_params *params,
10691065
rc);
10701066
goto cleanup;
10711067
}
1072-
p.frame.re_lsb =
1068+
p.frame_list[0].re_lsb =
10731069
UCLOGIC_RDESC_UGEE_G5_FRAME_RE_LSB;
1074-
p.frame.dev_id_byte =
1070+
p.frame_list[0].dev_id_byte =
10751071
UCLOGIC_RDESC_UGEE_G5_FRAME_DEV_ID_BYTE;
10761072
} else {
10771073
hid_warn(hdev, "pen parameters not found");
@@ -1093,7 +1089,7 @@ int uclogic_params_init(struct uclogic_params *params,
10931089
goto cleanup;
10941090
} else if (found) {
10951091
rc = uclogic_params_frame_init_with_desc(
1096-
&p.frame,
1092+
&p.frame_list[0],
10971093
uclogic_rdesc_ugee_ex07_frame_arr,
10981094
uclogic_rdesc_ugee_ex07_frame_size,
10991095
0);

drivers/hid/hid-uclogic-params.h

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -165,10 +165,10 @@ struct uclogic_params {
165165
*/
166166
struct uclogic_params_pen pen;
167167
/*
168-
* Frame control parameters and optional report descriptor part.
169-
* Only valid, if "invalid" is false.
168+
* The list of frame control parameters and optional report descriptor
169+
* parts. Only valid, if "invalid" is false.
170170
*/
171-
struct uclogic_params_frame frame;
171+
struct uclogic_params_frame frame_list[1];
172172
};
173173

174174
/* Initialize a tablet interface and discover its parameters */
@@ -187,11 +187,11 @@ extern int uclogic_params_init(struct uclogic_params *params,
187187
".pen.inrange = %s\n" \
188188
".pen.fragmented_hires = %s\n" \
189189
".pen.tilt_y_flipped = %s\n" \
190-
".frame.desc_ptr = %p\n" \
191-
".frame.desc_size = %u\n" \
192-
".frame.id = %u\n" \
193-
".frame.re_lsb = %u\n" \
194-
".frame.dev_id_byte = %u\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"
195195

196196
/* Tablet interface parameters *printf format arguments */
197197
#define UCLOGIC_PARAMS_FMT_ARGS(_params) \
@@ -206,11 +206,11 @@ extern int uclogic_params_init(struct uclogic_params *params,
206206
uclogic_params_pen_inrange_to_str((_params)->pen.inrange), \
207207
((_params)->pen.fragmented_hires ? "true" : "false"), \
208208
((_params)->pen.tilt_y_flipped ? "true" : "false"), \
209-
(_params)->frame.desc_ptr, \
210-
(_params)->frame.desc_size, \
211-
(_params)->frame.id, \
212-
(_params)->frame.re_lsb, \
213-
(_params)->frame.dev_id_byte
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
214214

215215
/* Get a replacement report descriptor for a tablet's interface. */
216216
extern int uclogic_params_get_desc(const struct uclogic_params *params,

0 commit comments

Comments
 (0)