Commit 2e688e65 authored by Jiri Kosina's avatar Jiri Kosina

Merge branch 'for-5.19/uclogic' into for-linus

- support for wider variety of Huion tablets ported from DIGImend
  project (José Expósito, Nikolai Kondrashov)
parents fa4c7c64 f7d8e387
......@@ -1278,6 +1278,7 @@
#define USB_DEVICE_ID_UGEE_XPPEN_TABLET_G540 0x0075
#define USB_DEVICE_ID_UGEE_XPPEN_TABLET_G640 0x0094
#define USB_DEVICE_ID_UGEE_XPPEN_TABLET_DECO01 0x0042
#define USB_DEVICE_ID_UGEE_XPPEN_TABLET_STAR06 0x0078
#define USB_DEVICE_ID_UGEE_TABLET_G5 0x0074
#define USB_DEVICE_ID_UGEE_TABLET_EX07S 0x0071
#define USB_DEVICE_ID_UGEE_TABLET_RAINBOW_CV720 0x0055
......
......@@ -33,7 +33,7 @@ static __u8 easypen_i405x_rdesc_fixed[] = {
0xB1, 0x02, /* Feature (Variable), */
0xC0, /* End Collection, */
0x05, 0x0D, /* Usage Page (Digitizer), */
0x09, 0x02, /* Usage (Pen), */
0x09, 0x01, /* Usage (Digitizer), */
0xA1, 0x01, /* Collection (Application), */
0x85, 0x10, /* Report ID (16), */
0x09, 0x20, /* Usage (Stylus), */
......@@ -91,7 +91,7 @@ static __u8 mousepen_i608x_rdesc_fixed[] = {
0xB1, 0x02, /* Feature (Variable), */
0xC0, /* End Collection, */
0x05, 0x0D, /* Usage Page (Digitizer), */
0x09, 0x02, /* Usage (Pen), */
0x09, 0x01, /* Usage (Digitizer), */
0xA1, 0x01, /* Collection (Application), */
0x85, 0x10, /* Report ID (16), */
0x09, 0x20, /* Usage (Stylus), */
......@@ -190,7 +190,7 @@ static __u8 mousepen_i608x_v2_rdesc_fixed[] = {
0xB1, 0x02, /* Feature (Variable), */
0xC0, /* End Collection, */
0x05, 0x0D, /* Usage Page (Digitizer), */
0x09, 0x02, /* Usage (Pen), */
0x09, 0x01, /* Usage (Digitizer), */
0xA1, 0x01, /* Collection (Application), */
0x85, 0x10, /* Report ID (16), */
0x09, 0x20, /* Usage (Stylus), */
......@@ -289,7 +289,7 @@ static __u8 easypen_m610x_rdesc_fixed[] = {
0xB1, 0x02, /* Feature (Variable), */
0xC0, /* End Collection, */
0x05, 0x0D, /* Usage Page (Digitizer), */
0x09, 0x02, /* Usage (Pen), */
0x09, 0x01, /* Usage (Digitizer), */
0xA1, 0x01, /* Collection (Application), */
0x85, 0x10, /* Report ID (16), */
0x09, 0x20, /* Usage (Stylus), */
......@@ -368,7 +368,7 @@ static __u8 pensketch_m912_rdesc_fixed[] = {
0xB1, 0x02, /* Feature (Variable), */
0xC0, /* End Collection, */
0x05, 0x0D, /* Usage Page (Digitizer), */
0x09, 0x02, /* Usage (Pen), */
0x09, 0x01, /* Usage (Digitizer), */
0xA1, 0x01, /* Collection (Application), */
0x85, 0x10, /* Report ID (16), */
0x09, 0x20, /* Usage (Stylus), */
......@@ -497,7 +497,7 @@ static __u8 easypen_m406xe_rdesc_fixed[] = {
0xB1, 0x02, /* Feature (Variable), */
0xC0, /* End Collection, */
0x05, 0x0D, /* Usage Page (Digitizer), */
0x09, 0x02, /* Usage (Pen), */
0x09, 0x01, /* Usage (Digitizer), */
0xA1, 0x01, /* Collection (Application), */
0x85, 0x10, /* Report ID (16), */
0x09, 0x20, /* Usage (Stylus), */
......
......@@ -81,6 +81,24 @@ 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 invalid pen usages */
if (params->pen.usage_invalid && (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)
{
......@@ -90,6 +108,8 @@ static int uclogic_input_configured(struct hid_device *hdev,
const char *suffix = NULL;
struct hid_field *field;
size_t len;
size_t i;
const struct uclogic_params_frame *frame;
/* no report associated (HID_QUIRK_MULTI_INPUT not set) */
if (!hi->report)
......@@ -104,27 +124,44 @@ static int uclogic_input_configured(struct hid_device *hdev,
drvdata->pen_input = hi->input;
}
field = hi->report->field[0];
/* If it's one of the frame devices */
for (i = 0; i < ARRAY_SIZE(params->frame_list); i++) {
frame = &params->frame_list[i];
if (hi->report->id == frame->id) {
/* Assign custom suffix, if any */
suffix = frame->suffix;
/*
* Disable EV_MSC reports for touch ring interfaces to
* make the Wacom driver pickup touch ring extents
*/
if (frame->touch_byte > 0)
__clear_bit(EV_MSC, hi->input->evbit);
}
}
switch (field->application) {
case HID_GD_KEYBOARD:
suffix = "Keyboard";
break;
case HID_GD_MOUSE:
suffix = "Mouse";
break;
case HID_GD_KEYPAD:
suffix = "Pad";
break;
case HID_DG_PEN:
suffix = "Pen";
break;
case HID_CP_CONSUMER_CONTROL:
suffix = "Consumer Control";
break;
case HID_GD_SYSTEM_CONTROL:
suffix = "System Control";
break;
if (!suffix) {
field = hi->report->field[0];
switch (field->application) {
case HID_GD_KEYBOARD:
suffix = "Keyboard";
break;
case HID_GD_MOUSE:
suffix = "Mouse";
break;
case HID_GD_KEYPAD:
suffix = "Pad";
break;
case HID_DG_PEN:
suffix = "Pen";
break;
case HID_CP_CONSUMER_CONTROL:
suffix = "Consumer Control";
break;
case HID_GD_SYSTEM_CONTROL:
suffix = "System Control";
break;
}
}
if (suffix) {
......@@ -172,8 +209,8 @@ static int uclogic_probe(struct hid_device *hdev,
goto failure;
}
params_initialized = true;
hid_dbg(hdev, "parameters:\n" UCLOGIC_PARAMS_FMT_STR,
UCLOGIC_PARAMS_FMT_ARGS(&drvdata->params));
hid_dbg(hdev, "parameters:\n");
uclogic_params_hid_dbg(hdev, &drvdata->params);
if (drvdata->params.invalid) {
hid_info(hdev, "interface is invalid, ignoring\n");
rc = -ENODEV;
......@@ -313,8 +350,15 @@ static int uclogic_raw_event_frame(
/* 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 we also have a touch ring and the finger left it */
if (frame->touch_byte > 0 && frame->touch_byte < size &&
data[frame->touch_byte] == 0) {
data[frame->dev_id_byte] = 0;
} else {
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;
......@@ -341,6 +385,26 @@ static int uclogic_raw_event_frame(
drvdata->re_state = state;
}
/* If need to, and can, transform the touch ring reports */
if (frame->touch_byte > 0 && frame->touch_byte < size) {
__s8 value = data[frame->touch_byte];
if (value != 0) {
if (frame->touch_flip_at != 0) {
value = frame->touch_flip_at - value;
if (value <= 0)
value = frame->touch_max + value;
}
data[frame->touch_byte] = value - 1;
}
}
/* If need to, and can, transform the bitmap dial reports */
if (frame->bitmap_dial_byte > 0 && frame->bitmap_dial_byte < size) {
if (data[frame->bitmap_dial_byte] == 2)
data[frame->bitmap_dial_byte] = -1;
}
return 0;
}
......@@ -457,6 +521,8 @@ static const struct hid_device_id uclogic_devices[] = {
USB_DEVICE_ID_UGEE_XPPEN_TABLET_G640) },
{ HID_USB_DEVICE(USB_VENDOR_ID_UGEE,
USB_DEVICE_ID_UGEE_XPPEN_TABLET_DECO01) },
{ HID_USB_DEVICE(USB_VENDOR_ID_UGEE,
USB_DEVICE_ID_UGEE_XPPEN_TABLET_STAR06) },
{ }
};
MODULE_DEVICE_TABLE(hid, uclogic_devices);
......@@ -468,6 +534,7 @@ 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,
......
This diff is collapsed.
......@@ -29,11 +29,6 @@ enum uclogic_params_pen_inrange {
UCLOGIC_PARAMS_PEN_INRANGE_NONE,
};
/* Convert a pen in-range reporting type to a string */
extern const char *uclogic_params_pen_inrange_to_str(
enum uclogic_params_pen_inrange inrange);
/*
* Pen report's subreport data.
*/
......@@ -62,8 +57,13 @@ struct uclogic_params_pen_subreport {
*/
struct uclogic_params_pen {
/*
* Pointer to report descriptor describing the inputs.
* Allocated with kmalloc.
* True if pen usage is invalid for this interface and should be
* ignored, false otherwise.
*/
bool usage_invalid;
/*
* Pointer to report descriptor part describing the pen inputs.
* Allocated with kmalloc. NULL if the part is not specified.
*/
__u8 *desc_ptr;
/*
......@@ -73,8 +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];
/* The list of subreports, only valid if "id" is not zero */
struct uclogic_params_pen_subreport subreport_list[3];
/* Type of in-range reporting, only valid if "id" is not zero */
enum uclogic_params_pen_inrange inrange;
/*
......@@ -101,8 +101,8 @@ struct uclogic_params_pen {
*/
struct uclogic_params_frame {
/*
* Pointer to report descriptor describing the inputs.
* Allocated with kmalloc.
* Pointer to report descriptor part describing the frame inputs.
* Allocated with kmalloc. NULL if the part is not specified.
*/
__u8 *desc_ptr;
/*
......@@ -114,6 +114,10 @@ struct uclogic_params_frame {
* Report ID, if reports should be tweaked, zero if not.
*/
unsigned int id;
/*
* The suffix to add to the input device name, if not NULL.
*/
const char *suffix;
/*
* Number of the least-significant bit of the 2-bit state of a rotary
* encoder, in the report. Cannot point to a 2-bit field crossing a
......@@ -123,10 +127,40 @@ struct uclogic_params_frame {
/*
* Offset of the Wacom-style device ID byte in the report, to be set
* to pad device ID (0xf), for compatibility with Wacom drivers. Zero
* if no changes to the report should be made. Only valid if "id" is
* not zero.
* if no changes to the report should be made. The ID byte will be set
* to zero whenever the byte pointed by "touch_byte" is zero, if
* the latter is valid. Only valid if "id" is not zero.
*/
unsigned int dev_id_byte;
/*
* Offset of the touch ring/strip state byte, in the report.
* Zero if not present. If dev_id_byte is also valid and non-zero,
* then the device ID byte will be cleared when the byte pointed to by
* this offset is zero. Only valid if "id" is not zero.
*/
unsigned int touch_byte;
/*
* The value to anchor the reversed touch ring/strip reports at.
* I.e. one, if the reports should be flipped without offset.
* Zero if no reversal should be done.
* Only valid if "touch_byte" is valid and not zero.
*/
__s8 touch_flip_at;
/*
* Maximum value of the touch ring/strip report around which the value
* should be wrapped when flipping according to "touch_flip_at".
* The minimum valid value is considered to be one, with zero being
* out-of-proximity (finger lift) value.
* Only valid if "touch_flip_at" is valid and not zero.
*/
__s8 touch_max;
/*
* Offset of the bitmap dial byte, in the report. Zero if not present.
* Only valid if "id" is not zero. A bitmap dial sends reports with a
* dedicated bit per direction: 1 means clockwise rotation, 2 means
* counterclockwise, as opposed to the normal 1 and -1.
*/
unsigned int bitmap_dial_byte;
};
/*
......@@ -156,7 +190,7 @@ struct uclogic_params {
__u8 *desc_ptr;
/*
* Size of the common part of the replacement report descriptor.
* Only valid, if "desc_ptr" is not NULL.
* Only valid, if "desc_ptr" is valid and not NULL.
*/
unsigned int desc_size;
/*
......@@ -168,50 +202,13 @@ struct uclogic_params {
* The list of frame control parameters and optional report descriptor
* parts. Only valid, if "invalid" is false.
*/
struct uclogic_params_frame frame_list[1];
struct uclogic_params_frame frame_list[3];
};
/* Initialize a tablet interface and discover its parameters */
extern int uclogic_params_init(struct uclogic_params *params,
struct hid_device *hdev);
/* Tablet interface parameters *printf format string */
#define UCLOGIC_PARAMS_FMT_STR \
".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.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)->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,
__u8 **pdesc,
......@@ -220,4 +217,8 @@ extern int uclogic_params_get_desc(const struct uclogic_params *params,
/* Free resources used by tablet interface's parameters */
extern void uclogic_params_cleanup(struct uclogic_params *params);
/* Dump tablet interface parameters with hid_dbg() */
extern void uclogic_params_hid_dbg(const struct hid_device *hdev,
const struct uclogic_params *params);
#endif /* _HID_UCLOGIC_PARAMS_H */
This diff is collapsed.
......@@ -124,12 +124,36 @@ extern const size_t uclogic_rdesc_v2_pen_template_size;
extern const __u8 uclogic_rdesc_v1_frame_arr[];
extern const size_t uclogic_rdesc_v1_frame_size;
/* Report ID for tweaked v2 frame reports */
#define UCLOGIC_RDESC_V2_FRAME_ID 0xf7
/* Report ID for tweaked v2 frame button reports */
#define UCLOGIC_RDESC_V2_FRAME_BUTTONS_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 (tweaked) v2 frame button reports */
extern const __u8 uclogic_rdesc_v2_frame_buttons_arr[];
extern const size_t uclogic_rdesc_v2_frame_buttons_size;
/* Report ID for tweaked v2 frame touch ring/strip reports */
#define UCLOGIC_RDESC_V2_FRAME_TOUCH_ID 0xf8
/* Fixed report descriptor for (tweaked) v2 frame touch ring reports */
extern const __u8 uclogic_rdesc_v2_frame_touch_ring_arr[];
extern const size_t uclogic_rdesc_v2_frame_touch_ring_size;
/* Fixed report descriptor for (tweaked) v2 frame touch strip reports */
extern const __u8 uclogic_rdesc_v2_frame_touch_strip_arr[];
extern const size_t uclogic_rdesc_v2_frame_touch_strip_size;
/* Device ID byte offset in v2 frame touch ring/strip reports */
#define UCLOGIC_RDESC_V2_FRAME_TOUCH_DEV_ID_BYTE 0x4
/* Report ID for tweaked v2 frame dial reports */
#define UCLOGIC_RDESC_V2_FRAME_DIAL_ID 0xf9
/* Fixed report descriptor for (tweaked) v2 frame dial reports */
extern const __u8 uclogic_rdesc_v2_frame_dial_arr[];
extern const size_t uclogic_rdesc_v2_frame_dial_size;
/* Device ID byte offset in v2 frame dial reports */
#define UCLOGIC_RDESC_V2_FRAME_DIAL_DEV_ID_BYTE 0x4
/* Fixed report descriptor for Ugee EX07 frame */
extern const __u8 uclogic_rdesc_ugee_ex07_frame_arr[];
......
......@@ -24,7 +24,7 @@
/* Fixed report descriptor of PD1011 signature pad */
static __u8 pd1011_rdesc_fixed[] = {
0x05, 0x0D, /* Usage Page (Digitizer), */
0x09, 0x02, /* Usage (Pen), */
0x09, 0x01, /* Usage (Digitizer), */
0xA1, 0x01, /* Collection (Application), */
0x85, 0x02, /* Report ID (2), */
0x09, 0x20, /* Usage (Stylus), */
......
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