forked from Minki/linux
Merge branch 'for-5.18/uclogic' into for-linus
- integration of first part of DIGImend [1] patches in order to vastly improve Linux support of tablets (Nikolai Kondrashov, José Expósito) [1] https://github.com/DIGImend/digimend-kernel-drivers
This commit is contained in:
commit
b146dbbd3b
@ -614,7 +614,7 @@
|
||||
|
||||
#define USB_VENDOR_ID_HUION 0x256c
|
||||
#define USB_DEVICE_ID_HUION_TABLET 0x006e
|
||||
#define USB_DEVICE_ID_HUION_HS64 0x006d
|
||||
#define USB_DEVICE_ID_HUION_TABLET2 0x006d
|
||||
|
||||
#define USB_VENDOR_ID_IBM 0x04b3
|
||||
#define USB_DEVICE_ID_IBM_SCROLLPOINT_III 0x3100
|
||||
|
@ -81,24 +81,6 @@ static __u8 *uclogic_report_fixup(struct hid_device *hdev, __u8 *rdesc,
|
||||
return rdesc;
|
||||
}
|
||||
|
||||
static int uclogic_input_mapping(struct hid_device *hdev,
|
||||
struct hid_input *hi,
|
||||
struct hid_field *field,
|
||||
struct hid_usage *usage,
|
||||
unsigned long **bit,
|
||||
int *max)
|
||||
{
|
||||
struct uclogic_drvdata *drvdata = hid_get_drvdata(hdev);
|
||||
struct uclogic_params *params = &drvdata->params;
|
||||
|
||||
/* discard the unused pen interface */
|
||||
if (params->pen_unused && (field->application == HID_DG_PEN))
|
||||
return -1;
|
||||
|
||||
/* let hid-core decide what to do */
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int uclogic_input_configured(struct hid_device *hdev,
|
||||
struct hid_input *hi)
|
||||
{
|
||||
@ -246,100 +228,171 @@ static int uclogic_resume(struct hid_device *hdev)
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* uclogic_raw_event_pen - handle raw pen events (pen HID reports).
|
||||
*
|
||||
* @drvdata: Driver data.
|
||||
* @data: Report data buffer, can be modified.
|
||||
* @size: Report data size, bytes.
|
||||
*
|
||||
* Returns:
|
||||
* Negative value on error (stops event delivery), zero for success.
|
||||
*/
|
||||
static int uclogic_raw_event_pen(struct uclogic_drvdata *drvdata,
|
||||
u8 *data, int size)
|
||||
{
|
||||
struct uclogic_params_pen *pen = &drvdata->params.pen;
|
||||
|
||||
WARN_ON(drvdata == NULL);
|
||||
WARN_ON(data == NULL && size != 0);
|
||||
|
||||
/* If in-range reports are inverted */
|
||||
if (pen->inrange ==
|
||||
UCLOGIC_PARAMS_PEN_INRANGE_INVERTED) {
|
||||
/* Invert the in-range bit */
|
||||
data[1] ^= 0x40;
|
||||
}
|
||||
/*
|
||||
* If report contains fragmented high-resolution pen
|
||||
* coordinates
|
||||
*/
|
||||
if (size >= 10 && pen->fragmented_hires) {
|
||||
u8 pressure_low_byte;
|
||||
u8 pressure_high_byte;
|
||||
|
||||
/* Lift pressure bytes */
|
||||
pressure_low_byte = data[6];
|
||||
pressure_high_byte = data[7];
|
||||
/*
|
||||
* Move Y coord to make space for high-order X
|
||||
* coord byte
|
||||
*/
|
||||
data[6] = data[5];
|
||||
data[5] = data[4];
|
||||
/* Move high-order X coord byte */
|
||||
data[4] = data[8];
|
||||
/* Move high-order Y coord byte */
|
||||
data[7] = data[9];
|
||||
/* Place pressure bytes */
|
||||
data[8] = pressure_low_byte;
|
||||
data[9] = pressure_high_byte;
|
||||
}
|
||||
/* If we need to emulate in-range detection */
|
||||
if (pen->inrange == UCLOGIC_PARAMS_PEN_INRANGE_NONE) {
|
||||
/* Set in-range bit */
|
||||
data[1] |= 0x40;
|
||||
/* (Re-)start in-range timeout */
|
||||
mod_timer(&drvdata->inrange_timer,
|
||||
jiffies + msecs_to_jiffies(100));
|
||||
}
|
||||
/* If we report tilt and Y direction is flipped */
|
||||
if (size >= 12 && pen->tilt_y_flipped)
|
||||
data[11] = -data[11];
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* uclogic_raw_event_frame - handle raw frame events (frame HID reports).
|
||||
*
|
||||
* @drvdata: Driver data.
|
||||
* @frame: The parameters of the frame controls to handle.
|
||||
* @data: Report data buffer, can be modified.
|
||||
* @size: Report data size, bytes.
|
||||
*
|
||||
* Returns:
|
||||
* Negative value on error (stops event delivery), zero for success.
|
||||
*/
|
||||
static int uclogic_raw_event_frame(
|
||||
struct uclogic_drvdata *drvdata,
|
||||
const struct uclogic_params_frame *frame,
|
||||
u8 *data, int size)
|
||||
{
|
||||
WARN_ON(drvdata == NULL);
|
||||
WARN_ON(data == NULL && size != 0);
|
||||
|
||||
/* If need to, and can, set pad device ID for Wacom drivers */
|
||||
if (frame->dev_id_byte > 0 && frame->dev_id_byte < size) {
|
||||
data[frame->dev_id_byte] = 0xf;
|
||||
}
|
||||
/* If need to, and can, read rotary encoder state change */
|
||||
if (frame->re_lsb > 0 && frame->re_lsb / 8 < size) {
|
||||
unsigned int byte = frame->re_lsb / 8;
|
||||
unsigned int bit = frame->re_lsb % 8;
|
||||
|
||||
u8 change;
|
||||
u8 prev_state = drvdata->re_state;
|
||||
/* Read Gray-coded state */
|
||||
u8 state = (data[byte] >> bit) & 0x3;
|
||||
/* Encode state change into 2-bit signed integer */
|
||||
if ((prev_state == 1 && state == 0) ||
|
||||
(prev_state == 2 && state == 3)) {
|
||||
change = 1;
|
||||
} else if ((prev_state == 2 && state == 0) ||
|
||||
(prev_state == 1 && state == 3)) {
|
||||
change = 3;
|
||||
} else {
|
||||
change = 0;
|
||||
}
|
||||
/* Write change */
|
||||
data[byte] = (data[byte] & ~((u8)3 << bit)) |
|
||||
(change << bit);
|
||||
/* Remember state */
|
||||
drvdata->re_state = state;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int uclogic_raw_event(struct hid_device *hdev,
|
||||
struct hid_report *report,
|
||||
u8 *data, int size)
|
||||
{
|
||||
unsigned int report_id = report->id;
|
||||
struct uclogic_drvdata *drvdata = hid_get_drvdata(hdev);
|
||||
struct uclogic_params *params = &drvdata->params;
|
||||
struct uclogic_params_pen_subreport *subreport;
|
||||
struct uclogic_params_pen_subreport *subreport_list_end;
|
||||
size_t i;
|
||||
|
||||
/* Tweak pen reports, if necessary */
|
||||
if (!params->pen_unused &&
|
||||
(report->type == HID_INPUT_REPORT) &&
|
||||
(report->id == params->pen.id) &&
|
||||
(size >= 2)) {
|
||||
/* If it's the "virtual" frame controls report */
|
||||
if (params->frame.id != 0 &&
|
||||
data[1] & params->pen_frame_flag) {
|
||||
/* Change to virtual frame controls report ID */
|
||||
data[0] = params->frame.id;
|
||||
return 0;
|
||||
}
|
||||
/* If in-range reports are inverted */
|
||||
if (params->pen.inrange ==
|
||||
UCLOGIC_PARAMS_PEN_INRANGE_INVERTED) {
|
||||
/* Invert the in-range bit */
|
||||
data[1] ^= 0x40;
|
||||
}
|
||||
/*
|
||||
* If report contains fragmented high-resolution pen
|
||||
* coordinates
|
||||
*/
|
||||
if (size >= 10 && params->pen.fragmented_hires) {
|
||||
u8 pressure_low_byte;
|
||||
u8 pressure_high_byte;
|
||||
/* Do not handle anything but input reports */
|
||||
if (report->type != HID_INPUT_REPORT)
|
||||
return 0;
|
||||
|
||||
/* Lift pressure bytes */
|
||||
pressure_low_byte = data[6];
|
||||
pressure_high_byte = data[7];
|
||||
/*
|
||||
* Move Y coord to make space for high-order X
|
||||
* coord byte
|
||||
*/
|
||||
data[6] = data[5];
|
||||
data[5] = data[4];
|
||||
/* Move high-order X coord byte */
|
||||
data[4] = data[8];
|
||||
/* Move high-order Y coord byte */
|
||||
data[7] = data[9];
|
||||
/* Place pressure bytes */
|
||||
data[8] = pressure_low_byte;
|
||||
data[9] = pressure_high_byte;
|
||||
}
|
||||
/* If we need to emulate in-range detection */
|
||||
if (params->pen.inrange == UCLOGIC_PARAMS_PEN_INRANGE_NONE) {
|
||||
/* Set in-range bit */
|
||||
data[1] |= 0x40;
|
||||
/* (Re-)start in-range timeout */
|
||||
mod_timer(&drvdata->inrange_timer,
|
||||
jiffies + msecs_to_jiffies(100));
|
||||
}
|
||||
}
|
||||
|
||||
/* Tweak frame control reports, if necessary */
|
||||
if ((report->type == HID_INPUT_REPORT) &&
|
||||
(report->id == params->frame.id)) {
|
||||
/* If need to, and can, set pad device ID for Wacom drivers */
|
||||
if (params->frame.dev_id_byte > 0 &&
|
||||
params->frame.dev_id_byte < size) {
|
||||
data[params->frame.dev_id_byte] = 0xf;
|
||||
}
|
||||
/* If need to, and can, read rotary encoder state change */
|
||||
if (params->frame.re_lsb > 0 &&
|
||||
params->frame.re_lsb / 8 < size) {
|
||||
unsigned int byte = params->frame.re_lsb / 8;
|
||||
unsigned int bit = params->frame.re_lsb % 8;
|
||||
|
||||
u8 change;
|
||||
u8 prev_state = drvdata->re_state;
|
||||
/* Read Gray-coded state */
|
||||
u8 state = (data[byte] >> bit) & 0x3;
|
||||
/* Encode state change into 2-bit signed integer */
|
||||
if ((prev_state == 1 && state == 0) ||
|
||||
(prev_state == 2 && state == 3)) {
|
||||
change = 1;
|
||||
} else if ((prev_state == 2 && state == 0) ||
|
||||
(prev_state == 1 && state == 3)) {
|
||||
change = 3;
|
||||
} else {
|
||||
change = 0;
|
||||
while (true) {
|
||||
/* Tweak pen reports, if necessary */
|
||||
if ((report_id == params->pen.id) && (size >= 2)) {
|
||||
subreport_list_end =
|
||||
params->pen.subreport_list +
|
||||
ARRAY_SIZE(params->pen.subreport_list);
|
||||
/* Try to match a subreport */
|
||||
for (subreport = params->pen.subreport_list;
|
||||
subreport < subreport_list_end; subreport++) {
|
||||
if (subreport->value != 0 &&
|
||||
subreport->value == data[1]) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
/* If a subreport matched */
|
||||
if (subreport < subreport_list_end) {
|
||||
/* Change to subreport ID, and restart */
|
||||
report_id = data[0] = subreport->id;
|
||||
continue;
|
||||
} else {
|
||||
return uclogic_raw_event_pen(drvdata, data, size);
|
||||
}
|
||||
/* Write change */
|
||||
data[byte] = (data[byte] & ~((u8)3 << bit)) |
|
||||
(change << bit);
|
||||
/* Remember state */
|
||||
drvdata->re_state = state;
|
||||
}
|
||||
|
||||
/* Tweak frame control reports, if necessary */
|
||||
for (i = 0; i < ARRAY_SIZE(params->frame_list); i++) {
|
||||
if (report_id == params->frame_list[i].id) {
|
||||
return uclogic_raw_event_frame(
|
||||
drvdata, ¶ms->frame_list[i],
|
||||
data, size);
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
@ -373,7 +426,7 @@ static const struct hid_device_id uclogic_devices[] = {
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_HUION,
|
||||
USB_DEVICE_ID_HUION_TABLET) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_HUION,
|
||||
USB_DEVICE_ID_HUION_HS64) },
|
||||
USB_DEVICE_ID_HUION_TABLET2) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_TRUST,
|
||||
USB_DEVICE_ID_TRUST_PANORA_TABLET) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC,
|
||||
@ -415,7 +468,6 @@ static struct hid_driver uclogic_driver = {
|
||||
.remove = uclogic_remove,
|
||||
.report_fixup = uclogic_report_fixup,
|
||||
.raw_event = uclogic_raw_event,
|
||||
.input_mapping = uclogic_input_mapping,
|
||||
.input_configured = uclogic_input_configured,
|
||||
#ifdef CONFIG_PM
|
||||
.resume = uclogic_resume,
|
||||
|
@ -207,8 +207,8 @@ static int uclogic_params_pen_init_v1(struct uclogic_params_pen *pen,
|
||||
* Generate pen report descriptor
|
||||
*/
|
||||
desc_ptr = uclogic_rdesc_template_apply(
|
||||
uclogic_rdesc_pen_v1_template_arr,
|
||||
uclogic_rdesc_pen_v1_template_size,
|
||||
uclogic_rdesc_v1_pen_template_arr,
|
||||
uclogic_rdesc_v1_pen_template_size,
|
||||
desc_params, ARRAY_SIZE(desc_params));
|
||||
if (desc_ptr == NULL) {
|
||||
rc = -ENOMEM;
|
||||
@ -221,8 +221,8 @@ static int uclogic_params_pen_init_v1(struct uclogic_params_pen *pen,
|
||||
memset(pen, 0, sizeof(*pen));
|
||||
pen->desc_ptr = desc_ptr;
|
||||
desc_ptr = NULL;
|
||||
pen->desc_size = uclogic_rdesc_pen_v1_template_size;
|
||||
pen->id = UCLOGIC_RDESC_PEN_V1_ID;
|
||||
pen->desc_size = uclogic_rdesc_v1_pen_template_size;
|
||||
pen->id = UCLOGIC_RDESC_V1_PEN_ID;
|
||||
pen->inrange = UCLOGIC_PARAMS_PEN_INRANGE_INVERTED;
|
||||
found = true;
|
||||
finish:
|
||||
@ -351,8 +351,8 @@ static int uclogic_params_pen_init_v2(struct uclogic_params_pen *pen,
|
||||
* Generate pen report descriptor
|
||||
*/
|
||||
desc_ptr = uclogic_rdesc_template_apply(
|
||||
uclogic_rdesc_pen_v2_template_arr,
|
||||
uclogic_rdesc_pen_v2_template_size,
|
||||
uclogic_rdesc_v2_pen_template_arr,
|
||||
uclogic_rdesc_v2_pen_template_size,
|
||||
desc_params, ARRAY_SIZE(desc_params));
|
||||
if (desc_ptr == NULL) {
|
||||
rc = -ENOMEM;
|
||||
@ -365,10 +365,11 @@ static int uclogic_params_pen_init_v2(struct uclogic_params_pen *pen,
|
||||
memset(pen, 0, sizeof(*pen));
|
||||
pen->desc_ptr = desc_ptr;
|
||||
desc_ptr = NULL;
|
||||
pen->desc_size = uclogic_rdesc_pen_v2_template_size;
|
||||
pen->id = UCLOGIC_RDESC_PEN_V2_ID;
|
||||
pen->desc_size = uclogic_rdesc_v2_pen_template_size;
|
||||
pen->id = UCLOGIC_RDESC_V2_PEN_ID;
|
||||
pen->inrange = UCLOGIC_PARAMS_PEN_INRANGE_NONE;
|
||||
pen->fragmented_hires = true;
|
||||
pen->tilt_y_flipped = true;
|
||||
found = true;
|
||||
finish:
|
||||
*pfound = found;
|
||||
@ -430,8 +431,8 @@ static int uclogic_params_frame_init_with_desc(
|
||||
}
|
||||
|
||||
/**
|
||||
* uclogic_params_frame_init_v1_buttonpad() - initialize abstract buttonpad
|
||||
* on a v1 tablet interface.
|
||||
* uclogic_params_frame_init_v1() - initialize v1 tablet interface frame
|
||||
* controls.
|
||||
*
|
||||
* @frame: Pointer to the frame parameters to initialize (to be cleaned
|
||||
* up with uclogic_params_frame_cleanup()). Not modified in case
|
||||
@ -445,8 +446,7 @@ static int uclogic_params_frame_init_with_desc(
|
||||
* Returns:
|
||||
* Zero, if successful. A negative errno code on error.
|
||||
*/
|
||||
static int uclogic_params_frame_init_v1_buttonpad(
|
||||
struct uclogic_params_frame *frame,
|
||||
static int uclogic_params_frame_init_v1(struct uclogic_params_frame *frame,
|
||||
bool *pfound,
|
||||
struct hid_device *hdev)
|
||||
{
|
||||
@ -487,9 +487,9 @@ static int uclogic_params_frame_init_v1_buttonpad(
|
||||
hid_dbg(hdev, "generic buttons enabled\n");
|
||||
rc = uclogic_params_frame_init_with_desc(
|
||||
frame,
|
||||
uclogic_rdesc_buttonpad_v1_arr,
|
||||
uclogic_rdesc_buttonpad_v1_size,
|
||||
UCLOGIC_RDESC_BUTTONPAD_V1_ID);
|
||||
uclogic_rdesc_v1_frame_arr,
|
||||
uclogic_rdesc_v1_frame_size,
|
||||
UCLOGIC_RDESC_V1_FRAME_ID);
|
||||
if (rc != 0)
|
||||
goto cleanup;
|
||||
found = true;
|
||||
@ -512,10 +512,12 @@ cleanup:
|
||||
void uclogic_params_cleanup(struct uclogic_params *params)
|
||||
{
|
||||
if (!params->invalid) {
|
||||
size_t i;
|
||||
kfree(params->desc_ptr);
|
||||
if (!params->pen_unused)
|
||||
uclogic_params_pen_cleanup(¶ms->pen);
|
||||
uclogic_params_frame_cleanup(¶ms->frame);
|
||||
uclogic_params_pen_cleanup(¶ms->pen);
|
||||
for (i = 0; i < ARRAY_SIZE(params->frame_list); i++)
|
||||
uclogic_params_frame_cleanup(¶ms->frame_list[i]);
|
||||
|
||||
memset(params, 0, sizeof(*params));
|
||||
}
|
||||
}
|
||||
@ -543,60 +545,53 @@ int uclogic_params_get_desc(const struct uclogic_params *params,
|
||||
__u8 **pdesc,
|
||||
unsigned int *psize)
|
||||
{
|
||||
bool common_present;
|
||||
bool pen_present;
|
||||
bool frame_present;
|
||||
unsigned int size;
|
||||
int rc = -ENOMEM;
|
||||
bool present = false;
|
||||
unsigned int size = 0;
|
||||
__u8 *desc = NULL;
|
||||
size_t i;
|
||||
|
||||
/* Check arguments */
|
||||
if (params == NULL || pdesc == NULL || psize == NULL)
|
||||
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);
|
||||
pen_present = (!params->pen_unused && params->pen.desc_ptr != NULL);
|
||||
frame_present = (params->frame.desc_ptr != NULL);
|
||||
|
||||
if (common_present)
|
||||
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;
|
||||
ADD_DESC(params->desc_ptr, params->desc_size);
|
||||
ADD_DESC(params->pen.desc_ptr, params->pen.desc_size);
|
||||
for (i = 0; i < ARRAY_SIZE(params->frame_list); i++) {
|
||||
ADD_DESC(params->frame_list[i].desc_ptr,
|
||||
params->frame_list[i].desc_size);
|
||||
}
|
||||
|
||||
*pdesc = desc;
|
||||
return 0;
|
||||
#undef ADD_DESC
|
||||
|
||||
if (present) {
|
||||
*pdesc = desc;
|
||||
*psize = size;
|
||||
desc = NULL;
|
||||
}
|
||||
rc = 0;
|
||||
cleanup:
|
||||
kfree(desc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -679,21 +674,6 @@ cleanup:
|
||||
return rc;
|
||||
}
|
||||
|
||||
/**
|
||||
* uclogic_params_init_with_pen_unused() - initialize tablet interface
|
||||
* parameters preserving original reports and generic HID processing, but
|
||||
* disabling pen usage.
|
||||
*
|
||||
* @params: Parameters to initialize (to be cleaned with
|
||||
* uclogic_params_cleanup()). Not modified in case of
|
||||
* error. Cannot be NULL.
|
||||
*/
|
||||
static void uclogic_params_init_with_pen_unused(struct uclogic_params *params)
|
||||
{
|
||||
memset(params, 0, sizeof(*params));
|
||||
params->pen_unused = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* uclogic_params_huion_init() - initialize a Huion tablet interface and discover
|
||||
* its parameters.
|
||||
@ -733,8 +713,7 @@ static int uclogic_params_huion_init(struct uclogic_params *params,
|
||||
|
||||
/* If it's not a pen interface */
|
||||
if (bInterfaceNumber != 0) {
|
||||
/* TODO: Consider marking the interface invalid */
|
||||
uclogic_params_init_with_pen_unused(&p);
|
||||
uclogic_params_init_invalid(&p);
|
||||
goto output;
|
||||
}
|
||||
|
||||
@ -766,20 +745,22 @@ static int uclogic_params_huion_init(struct uclogic_params *params,
|
||||
goto cleanup;
|
||||
} else if (found) {
|
||||
hid_dbg(hdev, "pen v2 parameters found\n");
|
||||
/* Create v2 buttonpad parameters */
|
||||
/* Create v2 frame parameters */
|
||||
rc = uclogic_params_frame_init_with_desc(
|
||||
&p.frame,
|
||||
uclogic_rdesc_buttonpad_v2_arr,
|
||||
uclogic_rdesc_buttonpad_v2_size,
|
||||
UCLOGIC_RDESC_BUTTONPAD_V2_ID);
|
||||
&p.frame_list[0],
|
||||
uclogic_rdesc_v2_frame_arr,
|
||||
uclogic_rdesc_v2_frame_size,
|
||||
UCLOGIC_RDESC_V2_FRAME_ID);
|
||||
if (rc != 0) {
|
||||
hid_err(hdev,
|
||||
"failed creating v2 buttonpad parameters: %d\n",
|
||||
"failed creating v2 frame parameters: %d\n",
|
||||
rc);
|
||||
goto cleanup;
|
||||
}
|
||||
/* Set bitmask marking frame reports in pen reports */
|
||||
p.pen_frame_flag = 0x20;
|
||||
/* Link frame button subreports from pen reports */
|
||||
p.pen.subreport_list[0].value = 0xe0;
|
||||
p.pen.subreport_list[0].id =
|
||||
UCLOGIC_RDESC_V2_FRAME_ID;
|
||||
goto output;
|
||||
}
|
||||
hid_dbg(hdev, "pen v2 parameters not found\n");
|
||||
@ -793,19 +774,20 @@ static int uclogic_params_huion_init(struct uclogic_params *params,
|
||||
goto cleanup;
|
||||
} else if (found) {
|
||||
hid_dbg(hdev, "pen v1 parameters found\n");
|
||||
/* Try to probe v1 buttonpad */
|
||||
rc = uclogic_params_frame_init_v1_buttonpad(
|
||||
&p.frame,
|
||||
&found, hdev);
|
||||
/* Try to probe v1 frame */
|
||||
rc = uclogic_params_frame_init_v1(&p.frame_list[0],
|
||||
&found, hdev);
|
||||
if (rc != 0) {
|
||||
hid_err(hdev, "v1 buttonpad probing failed: %d\n", rc);
|
||||
hid_err(hdev, "v1 frame probing failed: %d\n", rc);
|
||||
goto cleanup;
|
||||
}
|
||||
hid_dbg(hdev, "buttonpad v1 parameters%s found\n",
|
||||
hid_dbg(hdev, "frame v1 parameters%s found\n",
|
||||
(found ? "" : " not"));
|
||||
if (found) {
|
||||
/* Set bitmask marking frame reports */
|
||||
p.pen_frame_flag = 0x20;
|
||||
/* Link frame button subreports from pen reports */
|
||||
p.pen.subreport_list[0].value = 0xe0;
|
||||
p.pen.subreport_list[0].id =
|
||||
UCLOGIC_RDESC_V1_FRAME_ID;
|
||||
}
|
||||
goto output;
|
||||
}
|
||||
@ -992,7 +974,7 @@ int uclogic_params_init(struct uclogic_params *params,
|
||||
case VID_PID(USB_VENDOR_ID_HUION,
|
||||
USB_DEVICE_ID_HUION_TABLET):
|
||||
case VID_PID(USB_VENDOR_ID_HUION,
|
||||
USB_DEVICE_ID_HUION_HS64):
|
||||
USB_DEVICE_ID_HUION_TABLET2):
|
||||
case VID_PID(USB_VENDOR_ID_UCLOGIC,
|
||||
USB_DEVICE_ID_HUION_TABLET):
|
||||
case VID_PID(USB_VENDOR_ID_UCLOGIC,
|
||||
@ -1032,8 +1014,7 @@ int uclogic_params_init(struct uclogic_params *params,
|
||||
uclogic_params_init_invalid(&p);
|
||||
}
|
||||
} else {
|
||||
/* TODO: Consider marking the interface invalid */
|
||||
uclogic_params_init_with_pen_unused(&p);
|
||||
uclogic_params_init_invalid(&p);
|
||||
}
|
||||
break;
|
||||
case VID_PID(USB_VENDOR_ID_UGEE,
|
||||
@ -1048,15 +1029,14 @@ int uclogic_params_init(struct uclogic_params *params,
|
||||
}
|
||||
/* Initialize frame parameters */
|
||||
rc = uclogic_params_frame_init_with_desc(
|
||||
&p.frame,
|
||||
&p.frame_list[0],
|
||||
uclogic_rdesc_xppen_deco01_frame_arr,
|
||||
uclogic_rdesc_xppen_deco01_frame_size,
|
||||
0);
|
||||
if (rc != 0)
|
||||
goto cleanup;
|
||||
} else {
|
||||
/* TODO: Consider marking the interface invalid */
|
||||
uclogic_params_init_with_pen_unused(&p);
|
||||
uclogic_params_init_invalid(&p);
|
||||
}
|
||||
break;
|
||||
case VID_PID(USB_VENDOR_ID_TRUST,
|
||||
@ -1075,19 +1055,19 @@ int uclogic_params_init(struct uclogic_params *params,
|
||||
goto cleanup;
|
||||
} else if (found) {
|
||||
rc = uclogic_params_frame_init_with_desc(
|
||||
&p.frame,
|
||||
&p.frame_list[0],
|
||||
uclogic_rdesc_ugee_g5_frame_arr,
|
||||
uclogic_rdesc_ugee_g5_frame_size,
|
||||
UCLOGIC_RDESC_UGEE_G5_FRAME_ID);
|
||||
if (rc != 0) {
|
||||
hid_err(hdev,
|
||||
"failed creating buttonpad parameters: %d\n",
|
||||
"failed creating frame parameters: %d\n",
|
||||
rc);
|
||||
goto cleanup;
|
||||
}
|
||||
p.frame.re_lsb =
|
||||
p.frame_list[0].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;
|
||||
} else {
|
||||
hid_warn(hdev, "pen parameters not found");
|
||||
@ -1109,13 +1089,13 @@ int uclogic_params_init(struct uclogic_params *params,
|
||||
goto cleanup;
|
||||
} else if (found) {
|
||||
rc = uclogic_params_frame_init_with_desc(
|
||||
&p.frame,
|
||||
uclogic_rdesc_ugee_ex07_buttonpad_arr,
|
||||
uclogic_rdesc_ugee_ex07_buttonpad_size,
|
||||
&p.frame_list[0],
|
||||
uclogic_rdesc_ugee_ex07_frame_arr,
|
||||
uclogic_rdesc_ugee_ex07_frame_size,
|
||||
0);
|
||||
if (rc != 0) {
|
||||
hid_err(hdev,
|
||||
"failed creating buttonpad parameters: %d\n",
|
||||
"failed creating frame parameters: %d\n",
|
||||
rc);
|
||||
goto cleanup;
|
||||
}
|
||||
|
@ -33,6 +33,25 @@ enum uclogic_params_pen_inrange {
|
||||
extern const char *uclogic_params_pen_inrange_to_str(
|
||||
enum uclogic_params_pen_inrange inrange);
|
||||
|
||||
|
||||
/*
|
||||
* Pen report's subreport data.
|
||||
*/
|
||||
struct uclogic_params_pen_subreport {
|
||||
/*
|
||||
* The value of the second byte of the pen report indicating this
|
||||
* subreport. If zero, the subreport should be considered invalid and
|
||||
* not matched.
|
||||
*/
|
||||
__u8 value;
|
||||
|
||||
/*
|
||||
* The ID to be assigned to the report, if the second byte of the pen
|
||||
* report is equal to "value". Only valid if "value" is not zero.
|
||||
*/
|
||||
__u8 id;
|
||||
};
|
||||
|
||||
/*
|
||||
* Tablet interface's pen input parameters.
|
||||
*
|
||||
@ -54,6 +73,8 @@ struct uclogic_params_pen {
|
||||
unsigned int desc_size;
|
||||
/* Report ID, if reports should be tweaked, zero if not */
|
||||
unsigned int id;
|
||||
/* The list of subreports */
|
||||
struct uclogic_params_pen_subreport subreport_list[1];
|
||||
/* Type of in-range reporting, only valid if "id" is not zero */
|
||||
enum uclogic_params_pen_inrange inrange;
|
||||
/*
|
||||
@ -62,6 +83,12 @@ struct uclogic_params_pen {
|
||||
* Only valid if "id" is not zero.
|
||||
*/
|
||||
bool fragmented_hires;
|
||||
/*
|
||||
* True if the pen reports tilt in bytes at offset 10 (X) and 11 (Y),
|
||||
* and the Y tilt direction is flipped.
|
||||
* Only valid if "id" is not zero.
|
||||
*/
|
||||
bool tilt_y_flipped;
|
||||
};
|
||||
|
||||
/*
|
||||
@ -132,28 +159,16 @@ struct uclogic_params {
|
||||
* Only valid, if "desc_ptr" is not NULL.
|
||||
*/
|
||||
unsigned int desc_size;
|
||||
/*
|
||||
* True, if pen usage in report descriptor is invalid, when present.
|
||||
* Only valid, if "invalid" is false.
|
||||
*/
|
||||
bool pen_unused;
|
||||
/*
|
||||
* Pen parameters and optional report descriptor part.
|
||||
* Only valid if "pen_unused" is valid and false.
|
||||
* Only valid, if "invalid" is false.
|
||||
*/
|
||||
struct uclogic_params_pen pen;
|
||||
/*
|
||||
* Frame control parameters and optional report descriptor part.
|
||||
* Only valid, if "invalid" is false.
|
||||
* The list of frame control parameters and optional report descriptor
|
||||
* parts. Only valid, if "invalid" is false.
|
||||
*/
|
||||
struct uclogic_params_frame frame;
|
||||
/*
|
||||
* Bitmask matching frame controls "sub-report" flag in the second
|
||||
* byte of the pen report, or zero if it's not expected.
|
||||
* Only valid if both "pen" and "frame" are valid, and "frame.id" is
|
||||
* not zero.
|
||||
*/
|
||||
__u8 pen_frame_flag;
|
||||
struct uclogic_params_frame frame_list[1];
|
||||
};
|
||||
|
||||
/* Initialize a tablet interface and discover its parameters */
|
||||
@ -162,39 +177,40 @@ extern int uclogic_params_init(struct uclogic_params *params,
|
||||
|
||||
/* Tablet interface parameters *printf format string */
|
||||
#define UCLOGIC_PARAMS_FMT_STR \
|
||||
".invalid = %s\n" \
|
||||
".desc_ptr = %p\n" \
|
||||
".desc_size = %u\n" \
|
||||
".pen_unused = %s\n" \
|
||||
".pen.desc_ptr = %p\n" \
|
||||
".pen.desc_size = %u\n" \
|
||||
".pen.id = %u\n" \
|
||||
".pen.inrange = %s\n" \
|
||||
".pen.fragmented_hires = %s\n" \
|
||||
".frame.desc_ptr = %p\n" \
|
||||
".frame.desc_size = %u\n" \
|
||||
".frame.id = %u\n" \
|
||||
".frame.re_lsb = %u\n" \
|
||||
".frame.dev_id_byte = %u\n" \
|
||||
".pen_frame_flag = 0x%02x\n"
|
||||
".invalid = %s\n" \
|
||||
".desc_ptr = %p\n" \
|
||||
".desc_size = %u\n" \
|
||||
".pen.desc_ptr = %p\n" \
|
||||
".pen.desc_size = %u\n" \
|
||||
".pen.id = %u\n" \
|
||||
".pen.subreport_list[0] = {0x%02hhx, %hhu}\n" \
|
||||
".pen.inrange = %s\n" \
|
||||
".pen.fragmented_hires = %s\n" \
|
||||
".pen.tilt_y_flipped = %s\n" \
|
||||
".frame_list[0].desc_ptr = %p\n" \
|
||||
".frame_list[0].desc_size = %u\n" \
|
||||
".frame_list[0].id = %u\n" \
|
||||
".frame_list[0].re_lsb = %u\n" \
|
||||
".frame_list[0].dev_id_byte = %u\n"
|
||||
|
||||
/* Tablet interface parameters *printf format arguments */
|
||||
#define UCLOGIC_PARAMS_FMT_ARGS(_params) \
|
||||
((_params)->invalid ? "true" : "false"), \
|
||||
(_params)->desc_ptr, \
|
||||
(_params)->desc_size, \
|
||||
((_params)->pen_unused ? "true" : "false"), \
|
||||
(_params)->pen.desc_ptr, \
|
||||
(_params)->pen.desc_size, \
|
||||
(_params)->pen.id, \
|
||||
(_params)->pen.subreport_list[0].value, \
|
||||
(_params)->pen.subreport_list[0].id, \
|
||||
uclogic_params_pen_inrange_to_str((_params)->pen.inrange), \
|
||||
((_params)->pen.fragmented_hires ? "true" : "false"), \
|
||||
(_params)->frame.desc_ptr, \
|
||||
(_params)->frame.desc_size, \
|
||||
(_params)->frame.id, \
|
||||
(_params)->frame.re_lsb, \
|
||||
(_params)->frame.dev_id_byte, \
|
||||
(_params)->pen_frame_flag
|
||||
((_params)->pen.tilt_y_flipped ? "true" : "false"), \
|
||||
(_params)->frame_list[0].desc_ptr, \
|
||||
(_params)->frame_list[0].desc_size, \
|
||||
(_params)->frame_list[0].id, \
|
||||
(_params)->frame_list[0].re_lsb, \
|
||||
(_params)->frame_list[0].dev_id_byte
|
||||
|
||||
/* Get a replacement report descriptor for a tablet's interface. */
|
||||
extern int uclogic_params_get_desc(const struct uclogic_params *params,
|
||||
|
@ -532,7 +532,7 @@ const size_t uclogic_rdesc_twha60_fixed1_size =
|
||||
sizeof(uclogic_rdesc_twha60_fixed1_arr);
|
||||
|
||||
/* Fixed report descriptor template for (tweaked) v1 pen reports */
|
||||
const __u8 uclogic_rdesc_pen_v1_template_arr[] = {
|
||||
const __u8 uclogic_rdesc_v1_pen_template_arr[] = {
|
||||
0x05, 0x0D, /* Usage Page (Digitizer), */
|
||||
0x09, 0x02, /* Usage (Pen), */
|
||||
0xA1, 0x01, /* Collection (Application), */
|
||||
@ -582,11 +582,11 @@ const __u8 uclogic_rdesc_pen_v1_template_arr[] = {
|
||||
0xC0 /* End Collection */
|
||||
};
|
||||
|
||||
const size_t uclogic_rdesc_pen_v1_template_size =
|
||||
sizeof(uclogic_rdesc_pen_v1_template_arr);
|
||||
const size_t uclogic_rdesc_v1_pen_template_size =
|
||||
sizeof(uclogic_rdesc_v1_pen_template_arr);
|
||||
|
||||
/* Fixed report descriptor template for (tweaked) v2 pen reports */
|
||||
const __u8 uclogic_rdesc_pen_v2_template_arr[] = {
|
||||
const __u8 uclogic_rdesc_v2_pen_template_arr[] = {
|
||||
0x05, 0x0D, /* Usage Page (Digitizer), */
|
||||
0x09, 0x02, /* Usage (Pen), */
|
||||
0xA1, 0x01, /* Collection (Application), */
|
||||
@ -633,25 +633,35 @@ const __u8 uclogic_rdesc_pen_v2_template_arr[] = {
|
||||
0x27, UCLOGIC_RDESC_PEN_PH(PRESSURE_LM),
|
||||
/* Logical Maximum (PLACEHOLDER), */
|
||||
0x81, 0x02, /* Input (Variable), */
|
||||
0x81, 0x03, /* Input (Constant, Variable), */
|
||||
0x54, /* Unit Exponent (0), */
|
||||
0x65, 0x14, /* Unit (Degrees), */
|
||||
0x35, 0xC4, /* Physical Minimum (-60), */
|
||||
0x45, 0x3C, /* Physical Maximum (60), */
|
||||
0x15, 0xC4, /* Logical Minimum (-60), */
|
||||
0x25, 0x3C, /* Logical Maximum (60), */
|
||||
0x75, 0x08, /* Report Size (8), */
|
||||
0x95, 0x02, /* Report Count (2), */
|
||||
0x09, 0x3D, /* Usage (X Tilt), */
|
||||
0x09, 0x3E, /* Usage (Y Tilt), */
|
||||
0x81, 0x02, /* Input (Variable), */
|
||||
0xC0, /* End Collection, */
|
||||
0xC0 /* End Collection */
|
||||
};
|
||||
|
||||
const size_t uclogic_rdesc_pen_v2_template_size =
|
||||
sizeof(uclogic_rdesc_pen_v2_template_arr);
|
||||
const size_t uclogic_rdesc_v2_pen_template_size =
|
||||
sizeof(uclogic_rdesc_v2_pen_template_arr);
|
||||
|
||||
/*
|
||||
* Expand to the contents of a generic buttonpad report descriptor.
|
||||
* Expand to the contents of a generic frame report descriptor.
|
||||
*
|
||||
* @_padding: Padding from the end of button bits at bit 44, until
|
||||
* the end of the report, in bits.
|
||||
* @_id: The report ID to use.
|
||||
* @_size: Size of the report to pad to, including report ID, bytes.
|
||||
*/
|
||||
#define UCLOGIC_RDESC_BUTTONPAD_BYTES(_padding) \
|
||||
#define UCLOGIC_RDESC_FRAME_BYTES(_id, _size) \
|
||||
0x05, 0x01, /* Usage Page (Desktop), */ \
|
||||
0x09, 0x07, /* Usage (Keypad), */ \
|
||||
0xA1, 0x01, /* Collection (Application), */ \
|
||||
0x85, 0xF7, /* Report ID (247), */ \
|
||||
0x85, (_id), /* Report ID (_id), */ \
|
||||
0x14, /* Logical Minimum (0), */ \
|
||||
0x25, 0x01, /* Logical Maximum (1), */ \
|
||||
0x75, 0x01, /* Report Size (1), */ \
|
||||
@ -679,30 +689,31 @@ const size_t uclogic_rdesc_pen_v2_template_size =
|
||||
0xA0, /* Collection (Physical), */ \
|
||||
0x05, 0x09, /* Usage Page (Button), */ \
|
||||
0x19, 0x01, /* Usage Minimum (01h), */ \
|
||||
0x29, 0x02, /* Usage Maximum (02h), */ \
|
||||
0x95, 0x02, /* Report Count (2), */ \
|
||||
0x29, 0x03, /* Usage Maximum (03h), */ \
|
||||
0x95, 0x03, /* Report Count (3), */ \
|
||||
0x81, 0x02, /* Input (Variable), */ \
|
||||
0x95, _padding, /* Report Count (_padding), */ \
|
||||
0x95, ((_size) * 8 - 45), \
|
||||
/* Report Count (padding), */ \
|
||||
0x81, 0x01, /* Input (Constant), */ \
|
||||
0xC0, /* End Collection, */ \
|
||||
0xC0 /* End Collection */
|
||||
|
||||
/* Fixed report descriptor for (tweaked) v1 buttonpad reports */
|
||||
const __u8 uclogic_rdesc_buttonpad_v1_arr[] = {
|
||||
UCLOGIC_RDESC_BUTTONPAD_BYTES(20)
|
||||
/* Fixed report descriptor for (tweaked) v1 frame reports */
|
||||
const __u8 uclogic_rdesc_v1_frame_arr[] = {
|
||||
UCLOGIC_RDESC_FRAME_BYTES(UCLOGIC_RDESC_V1_FRAME_ID, 8)
|
||||
};
|
||||
const size_t uclogic_rdesc_buttonpad_v1_size =
|
||||
sizeof(uclogic_rdesc_buttonpad_v1_arr);
|
||||
const size_t uclogic_rdesc_v1_frame_size =
|
||||
sizeof(uclogic_rdesc_v1_frame_arr);
|
||||
|
||||
/* Fixed report descriptor for (tweaked) v2 buttonpad reports */
|
||||
const __u8 uclogic_rdesc_buttonpad_v2_arr[] = {
|
||||
UCLOGIC_RDESC_BUTTONPAD_BYTES(52)
|
||||
/* Fixed report descriptor for (tweaked) v2 frame reports */
|
||||
const __u8 uclogic_rdesc_v2_frame_arr[] = {
|
||||
UCLOGIC_RDESC_FRAME_BYTES(UCLOGIC_RDESC_V2_FRAME_ID, 12)
|
||||
};
|
||||
const size_t uclogic_rdesc_buttonpad_v2_size =
|
||||
sizeof(uclogic_rdesc_buttonpad_v2_arr);
|
||||
const size_t uclogic_rdesc_v2_frame_size =
|
||||
sizeof(uclogic_rdesc_v2_frame_arr);
|
||||
|
||||
/* Fixed report descriptor for Ugee EX07 buttonpad */
|
||||
const __u8 uclogic_rdesc_ugee_ex07_buttonpad_arr[] = {
|
||||
/* Fixed report descriptor for Ugee EX07 frame */
|
||||
const __u8 uclogic_rdesc_ugee_ex07_frame_arr[] = {
|
||||
0x05, 0x01, /* Usage Page (Desktop), */
|
||||
0x09, 0x07, /* Usage (Keypad), */
|
||||
0xA1, 0x01, /* Collection (Application), */
|
||||
@ -725,8 +736,8 @@ const __u8 uclogic_rdesc_ugee_ex07_buttonpad_arr[] = {
|
||||
0xC0, /* End Collection, */
|
||||
0xC0 /* End Collection */
|
||||
};
|
||||
const size_t uclogic_rdesc_ugee_ex07_buttonpad_size =
|
||||
sizeof(uclogic_rdesc_ugee_ex07_buttonpad_arr);
|
||||
const size_t uclogic_rdesc_ugee_ex07_frame_size =
|
||||
sizeof(uclogic_rdesc_ugee_ex07_frame_arr);
|
||||
|
||||
/* Fixed report descriptor for Ugee G5 frame controls */
|
||||
const __u8 uclogic_rdesc_ugee_g5_frame_arr[] = {
|
||||
|
@ -104,36 +104,36 @@ enum uclogic_rdesc_pen_ph_id {
|
||||
UCLOGIC_RDESC_PH_HEAD, UCLOGIC_RDESC_PEN_PH_ID_##_ID
|
||||
|
||||
/* Report ID for v1 pen reports */
|
||||
#define UCLOGIC_RDESC_PEN_V1_ID 0x07
|
||||
#define UCLOGIC_RDESC_V1_PEN_ID 0x07
|
||||
|
||||
/* Fixed report descriptor template for (tweaked) v1 pen reports */
|
||||
extern const __u8 uclogic_rdesc_pen_v1_template_arr[];
|
||||
extern const size_t uclogic_rdesc_pen_v1_template_size;
|
||||
extern const __u8 uclogic_rdesc_v1_pen_template_arr[];
|
||||
extern const size_t uclogic_rdesc_v1_pen_template_size;
|
||||
|
||||
/* Report ID for v2 pen reports */
|
||||
#define UCLOGIC_RDESC_PEN_V2_ID 0x08
|
||||
#define UCLOGIC_RDESC_V2_PEN_ID 0x08
|
||||
|
||||
/* Fixed report descriptor template for (tweaked) v2 pen reports */
|
||||
extern const __u8 uclogic_rdesc_pen_v2_template_arr[];
|
||||
extern const size_t uclogic_rdesc_pen_v2_template_size;
|
||||
extern const __u8 uclogic_rdesc_v2_pen_template_arr[];
|
||||
extern const size_t uclogic_rdesc_v2_pen_template_size;
|
||||
|
||||
/* Fixed report descriptor for (tweaked) v1 buttonpad reports */
|
||||
extern const __u8 uclogic_rdesc_buttonpad_v1_arr[];
|
||||
extern const size_t uclogic_rdesc_buttonpad_v1_size;
|
||||
/* Report ID for tweaked v1 frame reports */
|
||||
#define UCLOGIC_RDESC_V1_FRAME_ID 0xf7
|
||||
|
||||
/* Report ID for tweaked v1 buttonpad reports */
|
||||
#define UCLOGIC_RDESC_BUTTONPAD_V1_ID 0xf7
|
||||
/* Fixed report descriptor for (tweaked) v1 frame reports */
|
||||
extern const __u8 uclogic_rdesc_v1_frame_arr[];
|
||||
extern const size_t uclogic_rdesc_v1_frame_size;
|
||||
|
||||
/* Fixed report descriptor for (tweaked) v2 buttonpad reports */
|
||||
extern const __u8 uclogic_rdesc_buttonpad_v2_arr[];
|
||||
extern const size_t uclogic_rdesc_buttonpad_v2_size;
|
||||
/* Report ID for tweaked v2 frame reports */
|
||||
#define UCLOGIC_RDESC_V2_FRAME_ID 0xf7
|
||||
|
||||
/* Report ID for tweaked v2 buttonpad reports */
|
||||
#define UCLOGIC_RDESC_BUTTONPAD_V2_ID 0xf7
|
||||
/* Fixed report descriptor for (tweaked) v2 frame reports */
|
||||
extern const __u8 uclogic_rdesc_v2_frame_arr[];
|
||||
extern const size_t uclogic_rdesc_v2_frame_size;
|
||||
|
||||
/* Fixed report descriptor for Ugee EX07 buttonpad */
|
||||
extern const __u8 uclogic_rdesc_ugee_ex07_buttonpad_arr[];
|
||||
extern const size_t uclogic_rdesc_ugee_ex07_buttonpad_size;
|
||||
/* Fixed report descriptor for Ugee EX07 frame */
|
||||
extern const __u8 uclogic_rdesc_ugee_ex07_frame_arr[];
|
||||
extern const size_t uclogic_rdesc_ugee_ex07_frame_size;
|
||||
|
||||
/* Fixed report descriptor for XP-Pen Deco 01 frame controls */
|
||||
extern const __u8 uclogic_rdesc_xppen_deco01_frame_arr[];
|
||||
|
Loading…
Reference in New Issue
Block a user