Skip to content

Commit 988b16e

Browse files
committed
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.
1 parent 8214bc5 commit 988b16e

3 files changed

Lines changed: 73 additions & 71 deletions

File tree

hid-uclogic-core.c

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -308,17 +308,18 @@ static int uclogic_raw_event_pen(struct uclogic_drvdata *drvdata,
308308
* uclogic_raw_event_frame - handle raw frame events (frame HID reports).
309309
*
310310
* @drvdata: Driver data.
311+
* @frame: The parameters of the frame controls to handle.
311312
* @data: Report data buffer, can be modified.
312313
* @size: Report data size, bytes.
313314
*
314315
* Returns:
315316
* Negative value on error (stops event delivery), zero for success.
316317
*/
317-
static int uclogic_raw_event_frame(struct uclogic_drvdata *drvdata,
318-
u8 *data, int size)
318+
static int uclogic_raw_event_frame(
319+
struct uclogic_drvdata *drvdata,
320+
const struct uclogic_params_frame *frame,
321+
u8 *data, int size)
319322
{
320-
struct uclogic_params_frame *frame = &drvdata->params.frame;
321-
322323
WARN_ON(drvdata == NULL);
323324
WARN_ON(data == NULL && size != 0);
324325

@@ -364,6 +365,7 @@ static int uclogic_raw_event(struct hid_device *hdev,
364365
struct uclogic_params *params = &drvdata->params;
365366
struct uclogic_params_pen_subreport *subreport;
366367
struct uclogic_params_pen_subreport *subreport_list_end;
368+
size_t i;
367369

368370
/* Do not handle anything but input reports */
369371
if (report->type != HID_INPUT_REPORT) {
@@ -395,8 +397,12 @@ static int uclogic_raw_event(struct hid_device *hdev,
395397
}
396398

397399
/* Tweak frame control reports, if necessary */
398-
if (report_id == params->frame.id) {
399-
return uclogic_raw_event_frame(drvdata, data, size);
400+
for (i = 0; i < ARRAY_SIZE(params->frame_list); i++) {
401+
if (report_id == params->frame_list[i].id) {
402+
return uclogic_raw_event_frame(
403+
drvdata, &params->frame_list[i],
404+
data, size);
405+
}
400406
}
401407

402408
break;

hid-uclogic-params.c

Lines changed: 48 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -509,9 +509,12 @@ static int uclogic_params_frame_init_v1(struct uclogic_params_frame *frame,
509509
void uclogic_params_cleanup(struct uclogic_params *params)
510510
{
511511
if (!params->invalid) {
512+
size_t i;
512513
kfree(params->desc_ptr);
513514
uclogic_params_pen_cleanup(&params->pen);
514-
uclogic_params_frame_cleanup(&params->frame);
515+
for (i = 0; i < ARRAY_SIZE(params->frame_list); i++) {
516+
uclogic_params_frame_cleanup(&params->frame_list[i]);
517+
}
515518
memset(params, 0, sizeof(*params));
516519
}
517520
}
@@ -538,60 +541,53 @@ int uclogic_params_get_desc(const struct uclogic_params *params,
538541
__u8 **pdesc,
539542
unsigned int *psize)
540543
{
541-
bool common_present;
542-
bool pen_present;
543-
bool frame_present;
544-
unsigned int size;
544+
int rc = -ENOMEM;
545+
bool present = false;
546+
unsigned int size = 0;
545547
__u8 *desc = NULL;
548+
size_t i;
546549

547550
/* Check arguments */
548551
if (params == NULL || pdesc == NULL || psize == NULL)
549552
return -EINVAL;
550553

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

588-
WARN_ON(p != desc + size);
580+
#undef ADD_DESC
589581

582+
if (present) {
583+
*pdesc = desc;
590584
*psize = size;
585+
desc = NULL;
591586
}
592-
593-
*pdesc = desc;
594-
return 0;
587+
rc = 0;
588+
cleanup:
589+
kfree(desc);
590+
return rc;
595591
}
596592

597593
/**
@@ -743,7 +739,7 @@ static int uclogic_params_huion_init(struct uclogic_params *params,
743739
hid_dbg(hdev, "pen v2 parameters found\n");
744740
/* Create v2 frame parameters */
745741
rc = uclogic_params_frame_init_with_desc(
746-
&p.frame,
742+
&p.frame_list[0],
747743
uclogic_rdesc_v2_frame_arr,
748744
uclogic_rdesc_v2_frame_size,
749745
UCLOGIC_RDESC_V2_FRAME_ID);
@@ -771,7 +767,7 @@ static int uclogic_params_huion_init(struct uclogic_params *params,
771767
} else if (found) {
772768
hid_dbg(hdev, "pen v1 parameters found\n");
773769
/* Try to probe v1 frame */
774-
rc = uclogic_params_frame_init_v1(&p.frame,
770+
rc = uclogic_params_frame_init_v1(&p.frame_list[0],
775771
&found, hdev);
776772
if (rc != 0) {
777773
hid_err(hdev, "v1 frame probing failed: %d\n", rc);
@@ -1022,7 +1018,7 @@ int uclogic_params_init(struct uclogic_params *params,
10221018
}
10231019
/* Initialize frame parameters */
10241020
rc = uclogic_params_frame_init_with_desc(
1025-
&p.frame,
1021+
&p.frame_list[0],
10261022
uclogic_rdesc_xppen_deco01_frame_arr,
10271023
uclogic_rdesc_xppen_deco01_frame_size,
10281024
0);
@@ -1046,7 +1042,7 @@ int uclogic_params_init(struct uclogic_params *params,
10461042
goto cleanup;
10471043
} else if (found) {
10481044
rc = uclogic_params_frame_init_with_desc(
1049-
&p.frame,
1045+
&p.frame_list[0],
10501046
uclogic_rdesc_ugee_g5_frame_arr,
10511047
uclogic_rdesc_ugee_g5_frame_size,
10521048
UCLOGIC_RDESC_UGEE_G5_FRAME_ID);
@@ -1056,9 +1052,9 @@ int uclogic_params_init(struct uclogic_params *params,
10561052
rc);
10571053
goto cleanup;
10581054
}
1059-
p.frame.re_lsb =
1055+
p.frame_list[0].re_lsb =
10601056
UCLOGIC_RDESC_UGEE_G5_FRAME_RE_LSB;
1061-
p.frame.dev_id_byte =
1057+
p.frame_list[0].dev_id_byte =
10621058
UCLOGIC_RDESC_UGEE_G5_FRAME_DEV_ID_BYTE;
10631059
} else {
10641060
hid_warn(hdev, "pen parameters not found");
@@ -1080,7 +1076,7 @@ int uclogic_params_init(struct uclogic_params *params,
10801076
goto cleanup;
10811077
} else if (found) {
10821078
rc = uclogic_params_frame_init_with_desc(
1083-
&p.frame,
1079+
&p.frame_list[0],
10841080
uclogic_rdesc_ugee_ex07_frame_arr,
10851081
uclogic_rdesc_ugee_ex07_frame_size,
10861082
0);

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)