Commit 945d5dd5 authored by Nikolai Kondrashov's avatar Nikolai Kondrashov Committed by Jiri Kosina

HID: uclogic: Return raw parameters from v2 pen init

Return the raw parameters buffer from uclogic_params_pen_init_v2(), if
requested, as a way to identify the tablet.
Signed-off-by: default avatarNikolai Kondrashov <spbnick@gmail.com>
Signed-off-by: default avatarJosé Expósito <jose.exposito89@gmail.com>
Signed-off-by: default avatarJiri Kosina <jkosina@suse.cz>
parent a228809f
...@@ -339,27 +339,44 @@ static s32 uclogic_params_get_le24(const void *p) ...@@ -339,27 +339,44 @@ static s32 uclogic_params_get_le24(const void *p)
* input and retrieve its parameters from the device, using v2 protocol. * input and retrieve its parameters from the device, using v2 protocol.
* *
* @pen: Pointer to the pen parameters to initialize (to be * @pen: Pointer to the pen parameters to initialize (to be
* cleaned up with uclogic_params_pen_cleanup()). Not modified in * cleaned up with uclogic_params_pen_cleanup()). Not
* case of error, or if parameters are not found. Cannot be NULL. * modified in case of error, or if parameters are not
* @pfound: Location for a flag which is set to true if the parameters * found. Cannot be NULL.
* were found, and to false if not (e.g. device was * @pfound: Location for a flag which is set to true if the
* incompatible). Not modified in case of error. Cannot be NULL. * parameters were found, and to false if not (e.g.
* @hdev: The HID device of the tablet interface to initialize and get * device was incompatible). Not modified in case of
* parameters from. Cannot be NULL. * error. Cannot be NULL.
* @pparams_ptr: Location for a kmalloc'ed pointer to the retrieved raw
* parameters, which could be used to identify the tablet
* to some extent. Should be freed with kfree after use.
* NULL, if not needed. Not modified in case of error.
* Only set if *pfound is set to true.
* @pparams_len: Location for the length of the retrieved raw
* parameters. NULL, if not needed. Not modified in case
* of error. Only set if *pfound is set to true.
* @hdev: The HID device of the tablet interface to initialize
* and get parameters from. Cannot be NULL.
* *
* Returns: * Returns:
* Zero, if successful. A negative errno code on error. * Zero, if successful. A negative errno code on error.
*/ */
static int uclogic_params_pen_init_v2(struct uclogic_params_pen *pen, static int uclogic_params_pen_init_v2(struct uclogic_params_pen *pen,
bool *pfound, bool *pfound,
__u8 **pparams_ptr,
size_t *pparams_len,
struct hid_device *hdev) struct hid_device *hdev)
{ {
int rc; int rc;
bool found = false; bool found = false;
/* Buffer for (part of) the string descriptor */ /* Buffer for (part of) the parameter string descriptor */
__u8 *buf = NULL; __u8 *buf = NULL;
/* Descriptor length required */ /* Parameter string descriptor required length */
const int len = 18; const int params_len_min = 18;
/* Parameter string descriptor accepted length */
const int params_len_max = 32;
/* Parameter string descriptor received length */
int params_len;
size_t i;
s32 resolution; s32 resolution;
/* Pen report descriptor template parameters */ /* Pen report descriptor template parameters */
s32 desc_params[UCLOGIC_RDESC_PEN_PH_ID_NUM]; s32 desc_params[UCLOGIC_RDESC_PEN_PH_ID_NUM];
...@@ -377,7 +394,7 @@ static int uclogic_params_pen_init_v2(struct uclogic_params_pen *pen, ...@@ -377,7 +394,7 @@ static int uclogic_params_pen_init_v2(struct uclogic_params_pen *pen,
* the Windows driver traffic. * the Windows driver traffic.
* NOTE: This enables fully-functional tablet mode. * NOTE: This enables fully-functional tablet mode.
*/ */
rc = uclogic_params_get_str_desc(&buf, hdev, 200, len); rc = uclogic_params_get_str_desc(&buf, hdev, 200, params_len_max);
if (rc == -EPIPE) { if (rc == -EPIPE) {
hid_dbg(hdev, hid_dbg(hdev,
"string descriptor with pen parameters not found, assuming not compatible\n"); "string descriptor with pen parameters not found, assuming not compatible\n");
...@@ -385,28 +402,29 @@ static int uclogic_params_pen_init_v2(struct uclogic_params_pen *pen, ...@@ -385,28 +402,29 @@ static int uclogic_params_pen_init_v2(struct uclogic_params_pen *pen,
} else if (rc < 0) { } else if (rc < 0) {
hid_err(hdev, "failed retrieving pen parameters: %d\n", rc); hid_err(hdev, "failed retrieving pen parameters: %d\n", rc);
goto cleanup; goto cleanup;
} else if (rc != len) { } else if (rc < params_len_min) {
hid_dbg(hdev, hid_dbg(hdev,
"string descriptor with pen parameters has invalid length (got %d, expected %d), assuming not compatible\n", "string descriptor with pen parameters is too short (got %d, expected at least %d), assuming not compatible\n",
rc, len); rc, params_len_min);
goto finish; goto finish;
} else { }
size_t i;
params_len = rc;
/* /*
* Check it's not just a catch-all UTF-16LE-encoded ASCII * Check it's not just a catch-all UTF-16LE-encoded ASCII
* string (such as the model name) some tablets put into all * string (such as the model name) some tablets put into all
* unknown string descriptors. * unknown string descriptors.
*/ */
for (i = 2; for (i = 2;
i < len && i < params_len &&
(buf[i] >= 0x20 && buf[i] < 0x7f && buf[i + 1] == 0); (buf[i] >= 0x20 && buf[i] < 0x7f && buf[i + 1] == 0);
i += 2); i += 2);
if (i >= len) { if (i >= params_len) {
hid_dbg(hdev, hid_dbg(hdev,
"string descriptor with pen parameters seems to contain only text, assuming not compatible\n"); "string descriptor with pen parameters seems to contain only text, assuming not compatible\n");
goto finish; goto finish;
} }
}
/* /*
* Fill report descriptor parameters from the string descriptor * Fill report descriptor parameters from the string descriptor
...@@ -429,8 +447,6 @@ static int uclogic_params_pen_init_v2(struct uclogic_params_pen *pen, ...@@ -429,8 +447,6 @@ static int uclogic_params_pen_init_v2(struct uclogic_params_pen *pen,
desc_params[UCLOGIC_RDESC_PEN_PH_ID_Y_LM] * 1000 / desc_params[UCLOGIC_RDESC_PEN_PH_ID_Y_LM] * 1000 /
resolution; resolution;
} }
kfree(buf);
buf = NULL;
/* /*
* Generate pen report descriptor * Generate pen report descriptor
...@@ -456,6 +472,13 @@ static int uclogic_params_pen_init_v2(struct uclogic_params_pen *pen, ...@@ -456,6 +472,13 @@ static int uclogic_params_pen_init_v2(struct uclogic_params_pen *pen,
pen->fragmented_hires = true; pen->fragmented_hires = true;
pen->tilt_y_flipped = true; pen->tilt_y_flipped = true;
found = true; found = true;
if (pparams_ptr != NULL) {
*pparams_ptr = buf;
buf = NULL;
}
if (pparams_len != NULL)
*pparams_len = params_len;
finish: finish:
*pfound = found; *pfound = found;
rc = 0; rc = 0;
...@@ -828,7 +851,8 @@ static int uclogic_params_huion_init(struct uclogic_params *params, ...@@ -828,7 +851,8 @@ static int uclogic_params_huion_init(struct uclogic_params *params,
"transition firmware detected, not probing pen v2 parameters\n"); "transition firmware detected, not probing pen v2 parameters\n");
} else { } else {
/* Try to probe v2 pen parameters */ /* Try to probe v2 pen parameters */
rc = uclogic_params_pen_init_v2(&p.pen, &found, hdev); rc = uclogic_params_pen_init_v2(&p.pen, &found,
NULL, NULL, hdev);
if (rc != 0) { if (rc != 0) {
hid_err(hdev, hid_err(hdev,
"failed probing pen v2 parameters: %d\n", rc); "failed probing pen v2 parameters: %d\n", rc);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment