Skip to content

Commit b8cd2d9

Browse files
yangflJiri Kosina
authored andcommitted
HID: kye: Rewrite tablet descriptor fixup routine
Genius digitizer tablets send incorrect (vendor-defined) report descriptors by default. Descriptors for several models were added to override original ones. Since they share the same structure and are handled by the same Windows driver routine, extract the descriptor template and dynamic parameters for easier new device adoption. Signed-off-by: David Yang <mmyangfl@gmail.com> Signed-off-by: Jiri Kosina <jkosina@suse.cz>
1 parent 2653e3f commit b8cd2d9

1 file changed

Lines changed: 102 additions & 12 deletions

File tree

drivers/hid/hid-kye.c

Lines changed: 102 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,10 @@
55
* Copyright (c) 2009 Jiri Kosina
66
* Copyright (c) 2009 Tomas Hanak
77
* Copyright (c) 2012 Nikolai Kondrashov
8+
* Copyright (c) 2023 David Yang
89
*/
910

10-
/*
11-
*/
12-
11+
#include <asm-generic/unaligned.h>
1312
#include <linux/device.h>
1413
#include <linux/hid.h>
1514
#include <linux/module.h>
@@ -554,8 +553,25 @@ static __u8 easypen_m406xe_rdesc_fixed[] = {
554553
0xC0 /* End Collection */
555554
};
556555

556+
static const struct kye_tablet_info {
557+
__u32 product;
558+
__s32 x_logical_maximum;
559+
__s32 y_logical_maximum;
560+
__s32 pressure_logical_maximum;
561+
__s32 x_physical_maximum;
562+
__s32 y_physical_maximum;
563+
__s8 unit_exponent;
564+
__s8 unit;
565+
bool has_punk;
566+
unsigned int control_rsize;
567+
const __u8 *control_rdesc;
568+
} kye_tablets_info[] = {
569+
{}
570+
};
571+
557572
static __u8 *kye_consumer_control_fixup(struct hid_device *hdev, __u8 *rdesc,
558-
unsigned int *rsize, int offset, const char *device_name) {
573+
unsigned int *rsize, int offset, const char *device_name)
574+
{
559575
/*
560576
* the fixup that need to be done:
561577
* - change Usage Maximum in the Consumer Control
@@ -574,6 +590,79 @@ static __u8 *kye_consumer_control_fixup(struct hid_device *hdev, __u8 *rdesc,
574590
return rdesc;
575591
}
576592

593+
/*
594+
* Fix tablet descriptor of so-called "DataFormat 2".
595+
*
596+
* Though we may achieve a usable descriptor from original vendor-defined one,
597+
* some problems exist:
598+
* - Their Logical Maximum never exceed 32767 (7F FF), though device do report
599+
* values greater than that;
600+
* - Physical Maximums are arbitrarily filled (always equal to Logical
601+
* Maximum);
602+
* - Detail for control buttons are not provided (a vendor-defined Usage Page
603+
* with fixed content).
604+
*
605+
* Thus we use a pre-defined parameter table rather than digging it from
606+
* original descriptor.
607+
*
608+
* We may as well write a fallback routine for unrecognized kye tablet, but it's
609+
* clear kye are unlikely to produce new models in the foreseeable future, so we
610+
* simply enumerate all possible models.
611+
*/
612+
static __u8 *kye_tablet_fixup(struct hid_device *hdev, __u8 *rdesc, unsigned int *rsize)
613+
{
614+
const struct kye_tablet_info *info;
615+
unsigned int newsize;
616+
617+
if (*rsize < sizeof(kye_tablet_rdesc)) {
618+
hid_warn(hdev,
619+
"tablet report size too small, or kye_tablet_rdesc unexpectedly large\n");
620+
return rdesc;
621+
}
622+
623+
for (info = kye_tablets_info; info->product; info++) {
624+
if (hdev->product == info->product)
625+
break;
626+
}
627+
628+
if (!info->product) {
629+
hid_err(hdev, "tablet unknown, someone forget to add kye_tablet_info entry?\n");
630+
return rdesc;
631+
}
632+
633+
newsize = info->has_punk ? sizeof(kye_tablet_rdesc) : 112;
634+
memcpy(rdesc, kye_tablet_rdesc, newsize);
635+
636+
put_unaligned_le32(info->x_logical_maximum, rdesc + 66);
637+
put_unaligned_le32(info->x_physical_maximum, rdesc + 72);
638+
rdesc[77] = info->unit;
639+
rdesc[79] = info->unit_exponent;
640+
put_unaligned_le32(info->y_logical_maximum, rdesc + 87);
641+
put_unaligned_le32(info->y_physical_maximum, rdesc + 92);
642+
put_unaligned_le32(info->pressure_logical_maximum, rdesc + 104);
643+
644+
if (info->has_punk) {
645+
put_unaligned_le32(info->x_logical_maximum, rdesc + 156);
646+
put_unaligned_le32(info->x_physical_maximum, rdesc + 162);
647+
rdesc[167] = info->unit;
648+
rdesc[169] = info->unit_exponent;
649+
put_unaligned_le32(info->y_logical_maximum, rdesc + 177);
650+
put_unaligned_le32(info->y_physical_maximum, rdesc + 182);
651+
}
652+
653+
if (info->control_rsize) {
654+
if (newsize + info->control_rsize > *rsize)
655+
hid_err(hdev, "control rdesc unexpectedly large");
656+
else {
657+
memcpy(rdesc + newsize, info->control_rdesc, info->control_rsize);
658+
newsize += info->control_rsize;
659+
}
660+
}
661+
662+
*rsize = newsize;
663+
return rdesc;
664+
}
665+
577666
static __u8 *kye_report_fixup(struct hid_device *hdev, __u8 *rdesc,
578667
unsigned int *rsize)
579668
{
@@ -654,14 +743,6 @@ static __u8 *kye_report_fixup(struct hid_device *hdev, __u8 *rdesc,
654743
return rdesc;
655744
}
656745

657-
/**
658-
* kye_tablet_enable() - Enable fully-functional tablet mode by setting a special feature report.
659-
*
660-
* @hdev: HID device
661-
*
662-
* The specific report ID and data were discovered by sniffing the
663-
* Windows driver traffic.
664-
*/
665746
static int kye_tablet_enable(struct hid_device *hdev)
666747
{
667748
struct list_head *list;
@@ -688,6 +769,15 @@ static int kye_tablet_enable(struct hid_device *hdev)
688769

689770
value = report->field[0]->value;
690771

772+
/*
773+
* The code is for DataFormat 2 of config xml. They have no obvious
774+
* meaning (at least not configurable in Windows driver) except enabling
775+
* fully-functional tablet mode (absolute positioning). Otherwise, the
776+
* tablet acts like a relative mouse.
777+
*
778+
* Though there're magic codes for DataFormat 3 and 4, no devices use
779+
* these DataFormats.
780+
*/
691781
value[0] = 0x12;
692782
value[1] = 0x10;
693783
value[2] = 0x11;

0 commit comments

Comments
 (0)