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 <spbnick@gmail.com> Signed-off-by: José Expósito <jose.exposito89@gmail.com> Signed-off-by: Jiri Kosina <jkosina@suse.cz>
This commit is contained in:
parent
2daaeff382
commit
337fa051d9
|
@ -296,17 +296,18 @@ static int uclogic_raw_event_pen(struct uclogic_drvdata *drvdata,
|
||||||
* uclogic_raw_event_frame - handle raw frame events (frame HID reports).
|
* uclogic_raw_event_frame - handle raw frame events (frame HID reports).
|
||||||
*
|
*
|
||||||
* @drvdata: Driver data.
|
* @drvdata: Driver data.
|
||||||
|
* @frame: The parameters of the frame controls to handle.
|
||||||
* @data: Report data buffer, can be modified.
|
* @data: Report data buffer, can be modified.
|
||||||
* @size: Report data size, bytes.
|
* @size: Report data size, bytes.
|
||||||
*
|
*
|
||||||
* Returns:
|
* Returns:
|
||||||
* Negative value on error (stops event delivery), zero for success.
|
* Negative value on error (stops event delivery), zero for success.
|
||||||
*/
|
*/
|
||||||
static int uclogic_raw_event_frame(struct uclogic_drvdata *drvdata,
|
static int uclogic_raw_event_frame(
|
||||||
u8 *data, int size)
|
struct uclogic_drvdata *drvdata,
|
||||||
|
const struct uclogic_params_frame *frame,
|
||||||
|
u8 *data, int size)
|
||||||
{
|
{
|
||||||
struct uclogic_params_frame *frame = &drvdata->params.frame;
|
|
||||||
|
|
||||||
WARN_ON(drvdata == NULL);
|
WARN_ON(drvdata == NULL);
|
||||||
WARN_ON(data == NULL && size != 0);
|
WARN_ON(data == NULL && size != 0);
|
||||||
|
|
||||||
|
@ -352,6 +353,7 @@ static int uclogic_raw_event(struct hid_device *hdev,
|
||||||
struct uclogic_params *params = &drvdata->params;
|
struct uclogic_params *params = &drvdata->params;
|
||||||
struct uclogic_params_pen_subreport *subreport;
|
struct uclogic_params_pen_subreport *subreport;
|
||||||
struct uclogic_params_pen_subreport *subreport_list_end;
|
struct uclogic_params_pen_subreport *subreport_list_end;
|
||||||
|
size_t i;
|
||||||
|
|
||||||
/* Do not handle anything but input reports */
|
/* Do not handle anything but input reports */
|
||||||
if (report->type != HID_INPUT_REPORT)
|
if (report->type != HID_INPUT_REPORT)
|
||||||
|
@ -382,8 +384,13 @@ static int uclogic_raw_event(struct hid_device *hdev,
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Tweak frame control reports, if necessary */
|
/* Tweak frame control reports, if necessary */
|
||||||
if (report_id == params->frame.id)
|
for (i = 0; i < ARRAY_SIZE(params->frame_list); i++) {
|
||||||
return uclogic_raw_event_frame(drvdata, data, size);
|
if (report_id == params->frame_list[i].id) {
|
||||||
|
return uclogic_raw_event_frame(
|
||||||
|
drvdata, ¶ms->frame_list[i],
|
||||||
|
data, size);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -512,9 +512,12 @@ cleanup:
|
||||||
void uclogic_params_cleanup(struct uclogic_params *params)
|
void uclogic_params_cleanup(struct uclogic_params *params)
|
||||||
{
|
{
|
||||||
if (!params->invalid) {
|
if (!params->invalid) {
|
||||||
|
size_t i;
|
||||||
kfree(params->desc_ptr);
|
kfree(params->desc_ptr);
|
||||||
uclogic_params_pen_cleanup(¶ms->pen);
|
uclogic_params_pen_cleanup(¶ms->pen);
|
||||||
uclogic_params_frame_cleanup(¶ms->frame);
|
for (i = 0; i < ARRAY_SIZE(params->frame_list); i++)
|
||||||
|
uclogic_params_frame_cleanup(¶ms->frame_list[i]);
|
||||||
|
|
||||||
memset(params, 0, sizeof(*params));
|
memset(params, 0, sizeof(*params));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -542,60 +545,53 @@ int uclogic_params_get_desc(const struct uclogic_params *params,
|
||||||
__u8 **pdesc,
|
__u8 **pdesc,
|
||||||
unsigned int *psize)
|
unsigned int *psize)
|
||||||
{
|
{
|
||||||
bool common_present;
|
int rc = -ENOMEM;
|
||||||
bool pen_present;
|
bool present = false;
|
||||||
bool frame_present;
|
unsigned int size = 0;
|
||||||
unsigned int size;
|
|
||||||
__u8 *desc = NULL;
|
__u8 *desc = NULL;
|
||||||
|
size_t i;
|
||||||
|
|
||||||
/* Check arguments */
|
/* Check arguments */
|
||||||
if (params == NULL || pdesc == NULL || psize == NULL)
|
if (params == NULL || pdesc == NULL || psize == NULL)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
size = 0;
|
/* Concatenate descriptors */
|
||||||
|
#define ADD_DESC(_desc_ptr, _desc_size) \
|
||||||
|
do { \
|
||||||
|
unsigned int new_size; \
|
||||||
|
__u8 *new_desc; \
|
||||||
|
if ((_desc_ptr) == NULL) { \
|
||||||
|
break; \
|
||||||
|
} \
|
||||||
|
new_size = size + (_desc_size); \
|
||||||
|
new_desc = krealloc(desc, new_size, GFP_KERNEL); \
|
||||||
|
if (new_desc == NULL) { \
|
||||||
|
goto cleanup; \
|
||||||
|
} \
|
||||||
|
memcpy(new_desc + size, (_desc_ptr), (_desc_size)); \
|
||||||
|
desc = new_desc; \
|
||||||
|
size = new_size; \
|
||||||
|
present = true; \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
common_present = (params->desc_ptr != NULL);
|
ADD_DESC(params->desc_ptr, params->desc_size);
|
||||||
pen_present = (params->pen.desc_ptr != NULL);
|
ADD_DESC(params->pen.desc_ptr, params->pen.desc_size);
|
||||||
frame_present = (params->frame.desc_ptr != NULL);
|
for (i = 0; i < ARRAY_SIZE(params->frame_list); i++) {
|
||||||
|
ADD_DESC(params->frame_list[i].desc_ptr,
|
||||||
if (common_present)
|
params->frame_list[i].desc_size);
|
||||||
size += params->desc_size;
|
|
||||||
if (pen_present)
|
|
||||||
size += params->pen.desc_size;
|
|
||||||
if (frame_present)
|
|
||||||
size += params->frame.desc_size;
|
|
||||||
|
|
||||||
if (common_present || pen_present || frame_present) {
|
|
||||||
__u8 *p;
|
|
||||||
|
|
||||||
desc = kmalloc(size, GFP_KERNEL);
|
|
||||||
if (desc == NULL)
|
|
||||||
return -ENOMEM;
|
|
||||||
p = desc;
|
|
||||||
|
|
||||||
if (common_present) {
|
|
||||||
memcpy(p, params->desc_ptr,
|
|
||||||
params->desc_size);
|
|
||||||
p += params->desc_size;
|
|
||||||
}
|
|
||||||
if (pen_present) {
|
|
||||||
memcpy(p, params->pen.desc_ptr,
|
|
||||||
params->pen.desc_size);
|
|
||||||
p += params->pen.desc_size;
|
|
||||||
}
|
|
||||||
if (frame_present) {
|
|
||||||
memcpy(p, params->frame.desc_ptr,
|
|
||||||
params->frame.desc_size);
|
|
||||||
p += params->frame.desc_size;
|
|
||||||
}
|
|
||||||
|
|
||||||
WARN_ON(p != desc + size);
|
|
||||||
|
|
||||||
*psize = size;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
*pdesc = desc;
|
#undef ADD_DESC
|
||||||
return 0;
|
|
||||||
|
if (present) {
|
||||||
|
*pdesc = desc;
|
||||||
|
*psize = size;
|
||||||
|
desc = NULL;
|
||||||
|
}
|
||||||
|
rc = 0;
|
||||||
|
cleanup:
|
||||||
|
kfree(desc);
|
||||||
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -751,7 +747,7 @@ static int uclogic_params_huion_init(struct uclogic_params *params,
|
||||||
hid_dbg(hdev, "pen v2 parameters found\n");
|
hid_dbg(hdev, "pen v2 parameters found\n");
|
||||||
/* Create v2 frame parameters */
|
/* Create v2 frame parameters */
|
||||||
rc = uclogic_params_frame_init_with_desc(
|
rc = uclogic_params_frame_init_with_desc(
|
||||||
&p.frame,
|
&p.frame_list[0],
|
||||||
uclogic_rdesc_v2_frame_arr,
|
uclogic_rdesc_v2_frame_arr,
|
||||||
uclogic_rdesc_v2_frame_size,
|
uclogic_rdesc_v2_frame_size,
|
||||||
UCLOGIC_RDESC_V2_FRAME_ID);
|
UCLOGIC_RDESC_V2_FRAME_ID);
|
||||||
|
@ -779,7 +775,7 @@ static int uclogic_params_huion_init(struct uclogic_params *params,
|
||||||
} else if (found) {
|
} else if (found) {
|
||||||
hid_dbg(hdev, "pen v1 parameters found\n");
|
hid_dbg(hdev, "pen v1 parameters found\n");
|
||||||
/* Try to probe v1 frame */
|
/* Try to probe v1 frame */
|
||||||
rc = uclogic_params_frame_init_v1(&p.frame,
|
rc = uclogic_params_frame_init_v1(&p.frame_list[0],
|
||||||
&found, hdev);
|
&found, hdev);
|
||||||
if (rc != 0) {
|
if (rc != 0) {
|
||||||
hid_err(hdev, "v1 frame probing failed: %d\n", rc);
|
hid_err(hdev, "v1 frame probing failed: %d\n", rc);
|
||||||
|
@ -1033,7 +1029,7 @@ int uclogic_params_init(struct uclogic_params *params,
|
||||||
}
|
}
|
||||||
/* Initialize frame parameters */
|
/* Initialize frame parameters */
|
||||||
rc = uclogic_params_frame_init_with_desc(
|
rc = uclogic_params_frame_init_with_desc(
|
||||||
&p.frame,
|
&p.frame_list[0],
|
||||||
uclogic_rdesc_xppen_deco01_frame_arr,
|
uclogic_rdesc_xppen_deco01_frame_arr,
|
||||||
uclogic_rdesc_xppen_deco01_frame_size,
|
uclogic_rdesc_xppen_deco01_frame_size,
|
||||||
0);
|
0);
|
||||||
|
@ -1059,7 +1055,7 @@ int uclogic_params_init(struct uclogic_params *params,
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
} else if (found) {
|
} else if (found) {
|
||||||
rc = uclogic_params_frame_init_with_desc(
|
rc = uclogic_params_frame_init_with_desc(
|
||||||
&p.frame,
|
&p.frame_list[0],
|
||||||
uclogic_rdesc_ugee_g5_frame_arr,
|
uclogic_rdesc_ugee_g5_frame_arr,
|
||||||
uclogic_rdesc_ugee_g5_frame_size,
|
uclogic_rdesc_ugee_g5_frame_size,
|
||||||
UCLOGIC_RDESC_UGEE_G5_FRAME_ID);
|
UCLOGIC_RDESC_UGEE_G5_FRAME_ID);
|
||||||
|
@ -1069,9 +1065,9 @@ int uclogic_params_init(struct uclogic_params *params,
|
||||||
rc);
|
rc);
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
p.frame.re_lsb =
|
p.frame_list[0].re_lsb =
|
||||||
UCLOGIC_RDESC_UGEE_G5_FRAME_RE_LSB;
|
UCLOGIC_RDESC_UGEE_G5_FRAME_RE_LSB;
|
||||||
p.frame.dev_id_byte =
|
p.frame_list[0].dev_id_byte =
|
||||||
UCLOGIC_RDESC_UGEE_G5_FRAME_DEV_ID_BYTE;
|
UCLOGIC_RDESC_UGEE_G5_FRAME_DEV_ID_BYTE;
|
||||||
} else {
|
} else {
|
||||||
hid_warn(hdev, "pen parameters not found");
|
hid_warn(hdev, "pen parameters not found");
|
||||||
|
@ -1093,7 +1089,7 @@ int uclogic_params_init(struct uclogic_params *params,
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
} else if (found) {
|
} else if (found) {
|
||||||
rc = uclogic_params_frame_init_with_desc(
|
rc = uclogic_params_frame_init_with_desc(
|
||||||
&p.frame,
|
&p.frame_list[0],
|
||||||
uclogic_rdesc_ugee_ex07_frame_arr,
|
uclogic_rdesc_ugee_ex07_frame_arr,
|
||||||
uclogic_rdesc_ugee_ex07_frame_size,
|
uclogic_rdesc_ugee_ex07_frame_size,
|
||||||
0);
|
0);
|
||||||
|
|
|
@ -165,10 +165,10 @@ struct uclogic_params {
|
||||||
*/
|
*/
|
||||||
struct uclogic_params_pen pen;
|
struct uclogic_params_pen pen;
|
||||||
/*
|
/*
|
||||||
* Frame control parameters and optional report descriptor part.
|
* The list of frame control parameters and optional report descriptor
|
||||||
* Only valid, if "invalid" is false.
|
* parts. Only valid, if "invalid" is false.
|
||||||
*/
|
*/
|
||||||
struct uclogic_params_frame frame;
|
struct uclogic_params_frame frame_list[1];
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Initialize a tablet interface and discover its parameters */
|
/* Initialize a tablet interface and discover its parameters */
|
||||||
|
@ -187,11 +187,11 @@ extern int uclogic_params_init(struct uclogic_params *params,
|
||||||
".pen.inrange = %s\n" \
|
".pen.inrange = %s\n" \
|
||||||
".pen.fragmented_hires = %s\n" \
|
".pen.fragmented_hires = %s\n" \
|
||||||
".pen.tilt_y_flipped = %s\n" \
|
".pen.tilt_y_flipped = %s\n" \
|
||||||
".frame.desc_ptr = %p\n" \
|
".frame_list[0].desc_ptr = %p\n" \
|
||||||
".frame.desc_size = %u\n" \
|
".frame_list[0].desc_size = %u\n" \
|
||||||
".frame.id = %u\n" \
|
".frame_list[0].id = %u\n" \
|
||||||
".frame.re_lsb = %u\n" \
|
".frame_list[0].re_lsb = %u\n" \
|
||||||
".frame.dev_id_byte = %u\n"
|
".frame_list[0].dev_id_byte = %u\n"
|
||||||
|
|
||||||
/* Tablet interface parameters *printf format arguments */
|
/* Tablet interface parameters *printf format arguments */
|
||||||
#define UCLOGIC_PARAMS_FMT_ARGS(_params) \
|
#define UCLOGIC_PARAMS_FMT_ARGS(_params) \
|
||||||
|
@ -206,11 +206,11 @@ extern int uclogic_params_init(struct uclogic_params *params,
|
||||||
uclogic_params_pen_inrange_to_str((_params)->pen.inrange), \
|
uclogic_params_pen_inrange_to_str((_params)->pen.inrange), \
|
||||||
((_params)->pen.fragmented_hires ? "true" : "false"), \
|
((_params)->pen.fragmented_hires ? "true" : "false"), \
|
||||||
((_params)->pen.tilt_y_flipped ? "true" : "false"), \
|
((_params)->pen.tilt_y_flipped ? "true" : "false"), \
|
||||||
(_params)->frame.desc_ptr, \
|
(_params)->frame_list[0].desc_ptr, \
|
||||||
(_params)->frame.desc_size, \
|
(_params)->frame_list[0].desc_size, \
|
||||||
(_params)->frame.id, \
|
(_params)->frame_list[0].id, \
|
||||||
(_params)->frame.re_lsb, \
|
(_params)->frame_list[0].re_lsb, \
|
||||||
(_params)->frame.dev_id_byte
|
(_params)->frame_list[0].dev_id_byte
|
||||||
|
|
||||||
/* Get a replacement report descriptor for a tablet's interface. */
|
/* Get a replacement report descriptor for a tablet's interface. */
|
||||||
extern int uclogic_params_get_desc(const struct uclogic_params *params,
|
extern int uclogic_params_get_desc(const struct uclogic_params *params,
|
||||||
|
|
Loading…
Reference in New Issue