Message ID | 20220516181323.59554-5-jose.exposito89@gmail.com (mailing list archive) |
---|---|
State | Superseded |
Delegated to: | Jiri Kosina |
Headers | show |
Series | Add support for XP-PEN Deco L | expand |
Hi "José, Thank you for the patch! Perhaps something to improve: [auto build test WARNING on f7d8e387d9aeff963e6691c0166269b8042b4ff9] url: https://github.com/intel-lab-lkp/linux/commits/Jos-Exp-sito/Add-support-for-XP-PEN-Deco-L/20220517-021641 base: f7d8e387d9aeff963e6691c0166269b8042b4ff9 config: m68k-allyesconfig (https://download.01.org/0day-ci/archive/20220517/202205171208.uAUnAkVJ-lkp@intel.com/config) compiler: m68k-linux-gcc (GCC) 11.3.0 reproduce (this is a W=1 build): wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross chmod +x ~/bin/make.cross # https://github.com/intel-lab-lkp/linux/commit/f117e735d50f52f57bdabb589453959d60ae3ce6 git remote add linux-review https://github.com/intel-lab-lkp/linux git fetch --no-tags linux-review Jos-Exp-sito/Add-support-for-XP-PEN-Deco-L/20220517-021641 git checkout f117e735d50f52f57bdabb589453959d60ae3ce6 # save the config file mkdir build_dir && cp config build_dir/.config COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-11.3.0 make.cross W=1 O=build_dir ARCH=m68k SHELL=/bin/bash drivers/hid/ If you fix the issue, kindly add following tag as appropriate Reported-by: kernel test robot <lkp@intel.com> All warnings (new ones prefixed by >>): drivers/hid/hid-uclogic-params.c: In function 'uclogic_params_ugee_v2_init': >> drivers/hid/hid-uclogic-params.c:1078:28: warning: variable 'udev' set but not used [-Wunused-but-set-variable] 1078 | struct usb_device *udev; | ^~~~ vim +/udev +1078 drivers/hid/hid-uclogic-params.c 1054 1055 /** 1056 * uclogic_params_ugee_v2_init() - initialize a UGEE graphics tablets by 1057 * discovering their parameters. 1058 * 1059 * These tables, internally designed as v2 to differentiate them from older 1060 * models, expect a payload of magic data in orther to be switched to the fully 1061 * functional mode and expose their parameters in a similar way to the 1062 * information present in uclogic_params_pen_init_v1() but with some 1063 * differences. 1064 * 1065 * @params: Parameters to fill in (to be cleaned with 1066 * uclogic_params_cleanup()). Not modified in case of error. 1067 * Cannot be NULL. 1068 * @hdev: The HID device of the tablet interface to initialize and get 1069 * parameters from. Cannot be NULL. 1070 * 1071 * Returns: 1072 * Zero, if successful. A negative errno code on error. 1073 */ 1074 static int uclogic_params_ugee_v2_init(struct uclogic_params *params, 1075 struct hid_device *hdev) 1076 { 1077 int rc = 0; > 1078 struct usb_device *udev; 1079 struct usb_interface *iface; 1080 __u8 bInterfaceNumber; 1081 const int str_desc_len = 12; 1082 __u8 *str_desc = NULL; 1083 __u8 *rdesc_pen = NULL; 1084 __u8 *rdesc_frame = NULL; 1085 s32 desc_params[UCLOGIC_RDESC_PH_ID_NUM]; 1086 s32 resolution; 1087 __u8 magic_arr[] = { 1088 0x02, 0xb0, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 1089 }; 1090 /* The resulting parameters (noop) */ 1091 struct uclogic_params p = {0, }; 1092 1093 if (!params || !hdev) { 1094 rc = -EINVAL; 1095 goto cleanup; 1096 } 1097 1098 udev = hid_to_usb_dev(hdev); 1099 iface = to_usb_interface(hdev->dev.parent); 1100 bInterfaceNumber = iface->cur_altsetting->desc.bInterfaceNumber; 1101 if (bInterfaceNumber != 2) { 1102 uclogic_params_init_invalid(&p); 1103 goto output; 1104 } 1105 1106 /* 1107 * Initialize the interface by sending magic data. 1108 * The specific data was discovered by sniffing the Windows driver 1109 * traffic. 1110 */ 1111 rc = uclogic_probe_interface(hdev, magic_arr, sizeof(magic_arr), 0x03); 1112 if (rc) { 1113 uclogic_params_init_invalid(&p); 1114 goto output; 1115 } 1116 1117 /* 1118 * Read the string descriptor containing pen and frame parameters. 1119 * The specific string descriptor and data were discovered by sniffing 1120 * the Windows driver traffic. 1121 */ 1122 rc = uclogic_params_get_str_desc(&str_desc, hdev, 100, str_desc_len); 1123 if (rc != str_desc_len) { 1124 hid_err(hdev, "failed retrieving pen and frame parameters: %d\n", rc); 1125 uclogic_params_init_invalid(&p); 1126 goto output; 1127 } 1128 1129 desc_params[UCLOGIC_RDESC_PEN_PH_ID_X_LM] = 1130 get_unaligned_le16(str_desc + 2); 1131 desc_params[UCLOGIC_RDESC_PEN_PH_ID_Y_LM] = 1132 get_unaligned_le16(str_desc + 4); 1133 desc_params[UCLOGIC_RDESC_FRAME_PH_ID_UM] = str_desc[6]; 1134 desc_params[UCLOGIC_RDESC_PEN_PH_ID_PRESSURE_LM] = 1135 get_unaligned_le16(str_desc + 8); 1136 resolution = get_unaligned_le16(str_desc + 10); 1137 if (resolution == 0) { 1138 desc_params[UCLOGIC_RDESC_PEN_PH_ID_X_PM] = 0; 1139 desc_params[UCLOGIC_RDESC_PEN_PH_ID_Y_PM] = 0; 1140 } else { 1141 desc_params[UCLOGIC_RDESC_PEN_PH_ID_X_PM] = 1142 desc_params[UCLOGIC_RDESC_PEN_PH_ID_X_LM] * 1000 / 1143 resolution; 1144 desc_params[UCLOGIC_RDESC_PEN_PH_ID_Y_PM] = 1145 desc_params[UCLOGIC_RDESC_PEN_PH_ID_Y_LM] * 1000 / 1146 resolution; 1147 } 1148 kfree(str_desc); 1149 str_desc = NULL; 1150 1151 /* Initialize the pen interface */ 1152 rdesc_pen = uclogic_rdesc_template_apply( 1153 uclogic_rdesc_ugee_v2_pen_template_arr, 1154 uclogic_rdesc_ugee_v2_pen_template_size, 1155 desc_params, ARRAY_SIZE(desc_params)); 1156 if (!rdesc_pen) { 1157 rc = -ENOMEM; 1158 goto cleanup; 1159 } 1160 1161 p.pen.desc_ptr = rdesc_pen; 1162 p.pen.desc_size = uclogic_rdesc_ugee_v2_pen_template_size; 1163 p.pen.id = 0x02; 1164 p.pen.subreport_list[0].value = 0xf0; 1165 p.pen.subreport_list[0].id = UCLOGIC_RDESC_V1_FRAME_ID; 1166 1167 /* Initialize the frame interface */ 1168 rdesc_frame = uclogic_rdesc_template_apply( 1169 uclogic_rdesc_ugee_v2_frame_btn_template_arr, 1170 uclogic_rdesc_ugee_v2_frame_btn_template_size, 1171 desc_params, ARRAY_SIZE(desc_params)); 1172 if (!rdesc_frame) { 1173 rc = -ENOMEM; 1174 goto cleanup; 1175 } 1176 1177 rc = uclogic_params_frame_init_with_desc(&p.frame_list[0], 1178 rdesc_frame, 1179 uclogic_rdesc_ugee_v2_frame_btn_template_size, 1180 UCLOGIC_RDESC_V1_FRAME_ID); 1181 kfree(rdesc_frame); 1182 if (rc) { 1183 uclogic_params_init_invalid(&p); 1184 goto output; 1185 } 1186 1187 output: 1188 /* Output parameters */ 1189 memcpy(params, &p, sizeof(*params)); 1190 memset(&p, 0, sizeof(p)); 1191 rc = 0; 1192 cleanup: 1193 kfree(str_desc); 1194 uclogic_params_cleanup(&p); 1195 return rc; 1196 } 1197
Hi "José, Thank you for the patch! Perhaps something to improve: [auto build test WARNING on f7d8e387d9aeff963e6691c0166269b8042b4ff9] url: https://github.com/intel-lab-lkp/linux/commits/Jos-Exp-sito/Add-support-for-XP-PEN-Deco-L/20220517-021641 base: f7d8e387d9aeff963e6691c0166269b8042b4ff9 config: i386-randconfig-a006-20220516 (https://download.01.org/0day-ci/archive/20220518/202205180632.TtyLPtA5-lkp@intel.com/config) compiler: clang version 15.0.0 (https://github.com/llvm/llvm-project 853fa8ee225edf2d0de94b0dcbd31bea916e825e) reproduce (this is a W=1 build): wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross chmod +x ~/bin/make.cross # https://github.com/intel-lab-lkp/linux/commit/f117e735d50f52f57bdabb589453959d60ae3ce6 git remote add linux-review https://github.com/intel-lab-lkp/linux git fetch --no-tags linux-review Jos-Exp-sito/Add-support-for-XP-PEN-Deco-L/20220517-021641 git checkout f117e735d50f52f57bdabb589453959d60ae3ce6 # save the config file mkdir build_dir && cp config build_dir/.config COMPILER_INSTALL_PATH=$HOME/0day COMPILER=clang make.cross W=1 O=build_dir ARCH=i386 SHELL=/bin/bash drivers/hid/ If you fix the issue, kindly add following tag as appropriate Reported-by: kernel test robot <lkp@intel.com> All warnings (new ones prefixed by >>): >> drivers/hid/hid-uclogic-params.c:1078:21: warning: variable 'udev' set but not used [-Wunused-but-set-variable] struct usb_device *udev; ^ 1 warning generated. vim +/udev +1078 drivers/hid/hid-uclogic-params.c 1054 1055 /** 1056 * uclogic_params_ugee_v2_init() - initialize a UGEE graphics tablets by 1057 * discovering their parameters. 1058 * 1059 * These tables, internally designed as v2 to differentiate them from older 1060 * models, expect a payload of magic data in orther to be switched to the fully 1061 * functional mode and expose their parameters in a similar way to the 1062 * information present in uclogic_params_pen_init_v1() but with some 1063 * differences. 1064 * 1065 * @params: Parameters to fill in (to be cleaned with 1066 * uclogic_params_cleanup()). Not modified in case of error. 1067 * Cannot be NULL. 1068 * @hdev: The HID device of the tablet interface to initialize and get 1069 * parameters from. Cannot be NULL. 1070 * 1071 * Returns: 1072 * Zero, if successful. A negative errno code on error. 1073 */ 1074 static int uclogic_params_ugee_v2_init(struct uclogic_params *params, 1075 struct hid_device *hdev) 1076 { 1077 int rc = 0; > 1078 struct usb_device *udev; 1079 struct usb_interface *iface; 1080 __u8 bInterfaceNumber; 1081 const int str_desc_len = 12; 1082 __u8 *str_desc = NULL; 1083 __u8 *rdesc_pen = NULL; 1084 __u8 *rdesc_frame = NULL; 1085 s32 desc_params[UCLOGIC_RDESC_PH_ID_NUM]; 1086 s32 resolution; 1087 __u8 magic_arr[] = { 1088 0x02, 0xb0, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 1089 }; 1090 /* The resulting parameters (noop) */ 1091 struct uclogic_params p = {0, }; 1092 1093 if (!params || !hdev) { 1094 rc = -EINVAL; 1095 goto cleanup; 1096 } 1097 1098 udev = hid_to_usb_dev(hdev); 1099 iface = to_usb_interface(hdev->dev.parent); 1100 bInterfaceNumber = iface->cur_altsetting->desc.bInterfaceNumber; 1101 if (bInterfaceNumber != 2) { 1102 uclogic_params_init_invalid(&p); 1103 goto output; 1104 } 1105 1106 /* 1107 * Initialize the interface by sending magic data. 1108 * The specific data was discovered by sniffing the Windows driver 1109 * traffic. 1110 */ 1111 rc = uclogic_probe_interface(hdev, magic_arr, sizeof(magic_arr), 0x03); 1112 if (rc) { 1113 uclogic_params_init_invalid(&p); 1114 goto output; 1115 } 1116 1117 /* 1118 * Read the string descriptor containing pen and frame parameters. 1119 * The specific string descriptor and data were discovered by sniffing 1120 * the Windows driver traffic. 1121 */ 1122 rc = uclogic_params_get_str_desc(&str_desc, hdev, 100, str_desc_len); 1123 if (rc != str_desc_len) { 1124 hid_err(hdev, "failed retrieving pen and frame parameters: %d\n", rc); 1125 uclogic_params_init_invalid(&p); 1126 goto output; 1127 } 1128 1129 desc_params[UCLOGIC_RDESC_PEN_PH_ID_X_LM] = 1130 get_unaligned_le16(str_desc + 2); 1131 desc_params[UCLOGIC_RDESC_PEN_PH_ID_Y_LM] = 1132 get_unaligned_le16(str_desc + 4); 1133 desc_params[UCLOGIC_RDESC_FRAME_PH_ID_UM] = str_desc[6]; 1134 desc_params[UCLOGIC_RDESC_PEN_PH_ID_PRESSURE_LM] = 1135 get_unaligned_le16(str_desc + 8); 1136 resolution = get_unaligned_le16(str_desc + 10); 1137 if (resolution == 0) { 1138 desc_params[UCLOGIC_RDESC_PEN_PH_ID_X_PM] = 0; 1139 desc_params[UCLOGIC_RDESC_PEN_PH_ID_Y_PM] = 0; 1140 } else { 1141 desc_params[UCLOGIC_RDESC_PEN_PH_ID_X_PM] = 1142 desc_params[UCLOGIC_RDESC_PEN_PH_ID_X_LM] * 1000 / 1143 resolution; 1144 desc_params[UCLOGIC_RDESC_PEN_PH_ID_Y_PM] = 1145 desc_params[UCLOGIC_RDESC_PEN_PH_ID_Y_LM] * 1000 / 1146 resolution; 1147 } 1148 kfree(str_desc); 1149 str_desc = NULL; 1150 1151 /* Initialize the pen interface */ 1152 rdesc_pen = uclogic_rdesc_template_apply( 1153 uclogic_rdesc_ugee_v2_pen_template_arr, 1154 uclogic_rdesc_ugee_v2_pen_template_size, 1155 desc_params, ARRAY_SIZE(desc_params)); 1156 if (!rdesc_pen) { 1157 rc = -ENOMEM; 1158 goto cleanup; 1159 } 1160 1161 p.pen.desc_ptr = rdesc_pen; 1162 p.pen.desc_size = uclogic_rdesc_ugee_v2_pen_template_size; 1163 p.pen.id = 0x02; 1164 p.pen.subreport_list[0].value = 0xf0; 1165 p.pen.subreport_list[0].id = UCLOGIC_RDESC_V1_FRAME_ID; 1166 1167 /* Initialize the frame interface */ 1168 rdesc_frame = uclogic_rdesc_template_apply( 1169 uclogic_rdesc_ugee_v2_frame_btn_template_arr, 1170 uclogic_rdesc_ugee_v2_frame_btn_template_size, 1171 desc_params, ARRAY_SIZE(desc_params)); 1172 if (!rdesc_frame) { 1173 rc = -ENOMEM; 1174 goto cleanup; 1175 } 1176 1177 rc = uclogic_params_frame_init_with_desc(&p.frame_list[0], 1178 rdesc_frame, 1179 uclogic_rdesc_ugee_v2_frame_btn_template_size, 1180 UCLOGIC_RDESC_V1_FRAME_ID); 1181 kfree(rdesc_frame); 1182 if (rc) { 1183 uclogic_params_init_invalid(&p); 1184 goto output; 1185 } 1186 1187 output: 1188 /* Output parameters */ 1189 memcpy(params, &p, sizeof(*params)); 1190 memset(&p, 0, sizeof(p)); 1191 rc = 0; 1192 cleanup: 1193 kfree(str_desc); 1194 uclogic_params_cleanup(&p); 1195 return rc; 1196 } 1197
diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h index f8b3774a3a10..ea4e60de46db 100644 --- a/drivers/hid/hid-ids.h +++ b/drivers/hid/hid-ids.h @@ -1272,6 +1272,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_DECO_L 0x0935 #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 diff --git a/drivers/hid/hid-uclogic-core.c b/drivers/hid/hid-uclogic-core.c index c0fe66e50c58..47a17375c7fc 100644 --- a/drivers/hid/hid-uclogic-core.c +++ b/drivers/hid/hid-uclogic-core.c @@ -521,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_DECO_L) }, { HID_USB_DEVICE(USB_VENDOR_ID_UGEE, USB_DEVICE_ID_UGEE_XPPEN_TABLET_STAR06) }, { } diff --git a/drivers/hid/hid-uclogic-params.c b/drivers/hid/hid-uclogic-params.c index b43142f98a8b..00090d11b413 100644 --- a/drivers/hid/hid-uclogic-params.c +++ b/drivers/hid/hid-uclogic-params.c @@ -1002,6 +1002,199 @@ static int uclogic_params_huion_init(struct uclogic_params *params, return rc; } +/** + * uclogic_probe_interface() - some tablets, like the Parblo A610 PLUS V2 or + * the XP-PEN Deco Mini 7, need to be initialized by sending them magic data. + * + * @hdev: The HID device of the tablet interface to initialize and get + * parameters from. Cannot be NULL. + * @magic_arr: The magic data that should be sent to probe the interface. + * Cannot be NULL. + * @magic_size: Size of the magic data. + * @endpoint: Endpoint where the magic data should be sent. + * + * Returns: + * Zero, if successful. A negative errno code on error. + */ +static int uclogic_probe_interface(struct hid_device *hdev, u8 *magic_arr, + int magic_size, int endpoint) +{ + struct usb_device *udev; + unsigned int pipe = 0; + int sent; + u8 *buf = NULL; + int rc = 0; + + if (!hdev || !magic_arr) { + rc = -EINVAL; + goto cleanup; + } + + buf = kmemdup(magic_arr, magic_size, GFP_KERNEL); + if (!buf) { + rc = -ENOMEM; + goto cleanup; + } + + udev = hid_to_usb_dev(hdev); + pipe = usb_sndintpipe(udev, endpoint); + + rc = usb_interrupt_msg(udev, pipe, buf, magic_size, &sent, 1000); + if (rc || sent != magic_size) { + hid_err(hdev, "Interface probing failed: %d\n", rc); + rc = -1; + goto cleanup; + } + + rc = 0; +cleanup: + kfree(buf); + return rc; +} + +/** + * uclogic_params_ugee_v2_init() - initialize a UGEE graphics tablets by + * discovering their parameters. + * + * These tables, internally designed as v2 to differentiate them from older + * models, expect a payload of magic data in orther to be switched to the fully + * functional mode and expose their parameters in a similar way to the + * information present in uclogic_params_pen_init_v1() but with some + * differences. + * + * @params: Parameters to fill in (to be cleaned with + * uclogic_params_cleanup()). Not modified in case of error. + * Cannot be NULL. + * @hdev: The HID device of the tablet interface to initialize and get + * parameters from. Cannot be NULL. + * + * Returns: + * Zero, if successful. A negative errno code on error. + */ +static int uclogic_params_ugee_v2_init(struct uclogic_params *params, + struct hid_device *hdev) +{ + int rc = 0; + struct usb_device *udev; + struct usb_interface *iface; + __u8 bInterfaceNumber; + const int str_desc_len = 12; + __u8 *str_desc = NULL; + __u8 *rdesc_pen = NULL; + __u8 *rdesc_frame = NULL; + s32 desc_params[UCLOGIC_RDESC_PH_ID_NUM]; + s32 resolution; + __u8 magic_arr[] = { + 0x02, 0xb0, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }; + /* The resulting parameters (noop) */ + struct uclogic_params p = {0, }; + + if (!params || !hdev) { + rc = -EINVAL; + goto cleanup; + } + + udev = hid_to_usb_dev(hdev); + iface = to_usb_interface(hdev->dev.parent); + bInterfaceNumber = iface->cur_altsetting->desc.bInterfaceNumber; + if (bInterfaceNumber != 2) { + uclogic_params_init_invalid(&p); + goto output; + } + + /* + * Initialize the interface by sending magic data. + * The specific data was discovered by sniffing the Windows driver + * traffic. + */ + rc = uclogic_probe_interface(hdev, magic_arr, sizeof(magic_arr), 0x03); + if (rc) { + uclogic_params_init_invalid(&p); + goto output; + } + + /* + * Read the string descriptor containing pen and frame parameters. + * The specific string descriptor and data were discovered by sniffing + * the Windows driver traffic. + */ + rc = uclogic_params_get_str_desc(&str_desc, hdev, 100, str_desc_len); + if (rc != str_desc_len) { + hid_err(hdev, "failed retrieving pen and frame parameters: %d\n", rc); + uclogic_params_init_invalid(&p); + goto output; + } + + desc_params[UCLOGIC_RDESC_PEN_PH_ID_X_LM] = + get_unaligned_le16(str_desc + 2); + desc_params[UCLOGIC_RDESC_PEN_PH_ID_Y_LM] = + get_unaligned_le16(str_desc + 4); + desc_params[UCLOGIC_RDESC_FRAME_PH_ID_UM] = str_desc[6]; + desc_params[UCLOGIC_RDESC_PEN_PH_ID_PRESSURE_LM] = + get_unaligned_le16(str_desc + 8); + resolution = get_unaligned_le16(str_desc + 10); + if (resolution == 0) { + desc_params[UCLOGIC_RDESC_PEN_PH_ID_X_PM] = 0; + desc_params[UCLOGIC_RDESC_PEN_PH_ID_Y_PM] = 0; + } else { + desc_params[UCLOGIC_RDESC_PEN_PH_ID_X_PM] = + desc_params[UCLOGIC_RDESC_PEN_PH_ID_X_LM] * 1000 / + resolution; + desc_params[UCLOGIC_RDESC_PEN_PH_ID_Y_PM] = + desc_params[UCLOGIC_RDESC_PEN_PH_ID_Y_LM] * 1000 / + resolution; + } + kfree(str_desc); + str_desc = NULL; + + /* Initialize the pen interface */ + rdesc_pen = uclogic_rdesc_template_apply( + uclogic_rdesc_ugee_v2_pen_template_arr, + uclogic_rdesc_ugee_v2_pen_template_size, + desc_params, ARRAY_SIZE(desc_params)); + if (!rdesc_pen) { + rc = -ENOMEM; + goto cleanup; + } + + p.pen.desc_ptr = rdesc_pen; + p.pen.desc_size = uclogic_rdesc_ugee_v2_pen_template_size; + p.pen.id = 0x02; + p.pen.subreport_list[0].value = 0xf0; + p.pen.subreport_list[0].id = UCLOGIC_RDESC_V1_FRAME_ID; + + /* Initialize the frame interface */ + rdesc_frame = uclogic_rdesc_template_apply( + uclogic_rdesc_ugee_v2_frame_btn_template_arr, + uclogic_rdesc_ugee_v2_frame_btn_template_size, + desc_params, ARRAY_SIZE(desc_params)); + if (!rdesc_frame) { + rc = -ENOMEM; + goto cleanup; + } + + rc = uclogic_params_frame_init_with_desc(&p.frame_list[0], + rdesc_frame, + uclogic_rdesc_ugee_v2_frame_btn_template_size, + UCLOGIC_RDESC_V1_FRAME_ID); + kfree(rdesc_frame); + if (rc) { + uclogic_params_init_invalid(&p); + goto output; + } + +output: + /* Output parameters */ + memcpy(params, &p, sizeof(*params)); + memset(&p, 0, sizeof(p)); + rc = 0; +cleanup: + kfree(str_desc); + uclogic_params_cleanup(&p); + return rc; +} + /** * uclogic_params_init() - initialize a tablet interface and discover its * parameters. @@ -1237,6 +1430,12 @@ int uclogic_params_init(struct uclogic_params *params, uclogic_params_init_invalid(&p); } break; + case VID_PID(USB_VENDOR_ID_UGEE, + USB_DEVICE_ID_UGEE_XPPEN_TABLET_DECO_L): + rc = uclogic_params_ugee_v2_init(&p, hdev); + if (rc != 0) + goto cleanup; + break; case VID_PID(USB_VENDOR_ID_TRUST, USB_DEVICE_ID_TRUST_PANORA_TABLET): case VID_PID(USB_VENDOR_ID_UGEE, diff --git a/drivers/hid/hid-uclogic-rdesc.c b/drivers/hid/hid-uclogic-rdesc.c index cf04e71b7bb5..c552c989976a 100644 --- a/drivers/hid/hid-uclogic-rdesc.c +++ b/drivers/hid/hid-uclogic-rdesc.c @@ -859,6 +859,108 @@ const __u8 uclogic_rdesc_v2_frame_dial_arr[] = { const size_t uclogic_rdesc_v2_frame_dial_size = sizeof(uclogic_rdesc_v2_frame_dial_arr); +/* Fixed report descriptor template for UGEE v2 pen reports */ +const __u8 uclogic_rdesc_ugee_v2_pen_template_arr[] = { + 0x05, 0x0d, /* Usage Page (Digitizers), */ + 0x09, 0x01, /* Usage (Digitizer), */ + 0xa1, 0x01, /* Collection (Application), */ + 0x85, 0x02, /* Report ID (2), */ + 0x09, 0x20, /* Usage (Stylus), */ + 0xa1, 0x00, /* Collection (Physical), */ + 0x09, 0x42, /* Usage (Tip Switch), */ + 0x09, 0x44, /* Usage (Barrel Switch), */ + 0x09, 0x46, /* Usage (Tablet Pick), */ + 0x75, 0x01, /* Report Size (1), */ + 0x95, 0x03, /* Report Count (3), */ + 0x14, /* Logical Minimum (0), */ + 0x25, 0x01, /* Logical Maximum (1), */ + 0x81, 0x02, /* Input (Variable), */ + 0x95, 0x02, /* Report Count (2), */ + 0x81, 0x03, /* Input (Constant, Variable), */ + 0x09, 0x32, /* Usage (In Range), */ + 0x95, 0x01, /* Report Count (1), */ + 0x81, 0x02, /* Input (Variable), */ + 0x95, 0x02, /* Report Count (2), */ + 0x81, 0x03, /* Input (Constant, Variable), */ + 0x75, 0x10, /* Report Size (16), */ + 0x95, 0x01, /* Report Count (1), */ + 0x35, 0x00, /* Physical Minimum (0), */ + 0xa4, /* Push, */ + 0x05, 0x01, /* Usage Page (Desktop), */ + 0x09, 0x30, /* Usage (X), */ + 0x65, 0x13, /* Unit (Inch), */ + 0x55, 0x0d, /* Unit Exponent (-3), */ + 0x27, UCLOGIC_RDESC_PEN_PH(X_LM), + /* Logical Maximum (PLACEHOLDER), */ + 0x47, UCLOGIC_RDESC_PEN_PH(X_PM), + /* Physical Maximum (PLACEHOLDER), */ + 0x81, 0x02, /* Input (Variable), */ + 0x09, 0x31, /* Usage (Y), */ + 0x27, UCLOGIC_RDESC_PEN_PH(Y_LM), + /* Logical Maximum (PLACEHOLDER), */ + 0x47, UCLOGIC_RDESC_PEN_PH(Y_PM), + /* Physical Maximum (PLACEHOLDER), */ + 0x81, 0x02, /* Input (Variable), */ + 0xb4, /* Pop, */ + 0x09, 0x30, /* Usage (Tip Pressure), */ + 0x45, 0x00, /* Physical Maximum (0), */ + 0x27, UCLOGIC_RDESC_PEN_PH(PRESSURE_LM), + /* Logical Maximum (PLACEHOLDER), */ + 0x75, 0x0D, /* Report Size (13), */ + 0x95, 0x01, /* Report Count (1), */ + 0x81, 0x02, /* Input (Variable), */ + 0x75, 0x01, /* Report Size (1), */ + 0x95, 0x03, /* Report Count (3), */ + 0x81, 0x01, /* Input (Constant), */ + 0x09, 0x3d, /* Usage (X Tilt), */ + 0x35, 0xC3, /* Physical Minimum (-61), */ + 0x45, 0x3C, /* Physical Maximum (60), */ + 0x15, 0xC3, /* Logical Minimum (-61), */ + 0x25, 0x3C, /* Logical Maximum (60), */ + 0x75, 0x08, /* Report Size (8), */ + 0x95, 0x01, /* Report Count (1), */ + 0x81, 0x02, /* Input (Variable), */ + 0x09, 0x3e, /* Usage (Y Tilt), */ + 0x35, 0xC3, /* Physical Minimum (-61), */ + 0x45, 0x3C, /* Physical Maximum (60), */ + 0x15, 0xC3, /* Logical Minimum (-61), */ + 0x25, 0x3C, /* Logical Maximum (60), */ + 0x81, 0x02, /* Input (Variable), */ + 0xc0, /* End Collection, */ + 0xc0, /* End Collection */ +}; +const size_t uclogic_rdesc_ugee_v2_pen_template_size = + sizeof(uclogic_rdesc_ugee_v2_pen_template_arr); + +/* Fixed report descriptor template for UGEE v2 frame reports (buttons only) */ +const __u8 uclogic_rdesc_ugee_v2_frame_btn_template_arr[] = { + 0x05, 0x01, /* Usage Page (Desktop), */ + 0x09, 0x07, /* Usage (Keypad), */ + 0xA1, 0x01, /* Collection (Application), */ + 0x85, UCLOGIC_RDESC_V1_FRAME_ID, + /* Report ID, */ + 0x05, 0x0D, /* Usage Page (Digitizer), */ + 0x09, 0x39, /* Usage (Tablet Function Keys), */ + 0xA0, /* Collection (Physical), */ + 0x75, 0x01, /* Report Size (1), */ + 0x95, 0x08, /* Report Count (8), */ + 0x81, 0x01, /* Input (Constant), */ + 0x05, 0x09, /* Usage Page (Button), */ + 0x19, 0x01, /* Usage Minimum (01h), */ + UCLOGIC_RDESC_FRAME_PH_BTN, + /* Usage Maximum (PLACEHOLDER), */ + 0x95, 0x0A, /* Report Count (10), */ + 0x14, /* Logical Minimum (0), */ + 0x25, 0x01, /* Logical Maximum (1), */ + 0x81, 0x02, /* Input (Variable), */ + 0x95, 0x46, /* Report Count (70), */ + 0x81, 0x01, /* Input (Constant), */ + 0xC0, /* End Collection, */ + 0xC0 /* End Collection */ +}; +const size_t uclogic_rdesc_ugee_v2_frame_btn_template_size = + sizeof(uclogic_rdesc_ugee_v2_frame_btn_template_arr); + /* Fixed report descriptor for Ugee EX07 frame */ const __u8 uclogic_rdesc_ugee_ex07_frame_arr[] = { 0x05, 0x01, /* Usage Page (Desktop), */ diff --git a/drivers/hid/hid-uclogic-rdesc.h b/drivers/hid/hid-uclogic-rdesc.h index 3d78299f082d..86e64a9ee6bd 100644 --- a/drivers/hid/hid-uclogic-rdesc.h +++ b/drivers/hid/hid-uclogic-rdesc.h @@ -161,6 +161,14 @@ 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 template for UGEE v2 pen reports */ +extern const __u8 uclogic_rdesc_ugee_v2_pen_template_arr[]; +extern const size_t uclogic_rdesc_ugee_v2_pen_template_size; + +/* Fixed report descriptor template for UGEE v2 frame reports (buttons only) */ +extern const __u8 uclogic_rdesc_ugee_v2_frame_btn_template_arr[]; +extern const size_t uclogic_rdesc_ugee_v2_frame_btn_template_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;
The XP-PEN Deco L (UGEE) needs to be initialized by sending a buffer of magic data, discovered by sniffing the Windows driver traffic. In order to differentiate UGEE tablets that need this kind of initialization from the previous ones, name them v2 internally and create an entry point for them. After initialization, the template report descriptors can be discovered by parsing a string descriptor, similar to the one exposed by HUION v1 devices. Add all the required elements to support the device. Signed-off-by: José Expósito <jose.exposito89@gmail.com> --- drivers/hid/hid-ids.h | 1 + drivers/hid/hid-uclogic-core.c | 2 + drivers/hid/hid-uclogic-params.c | 199 +++++++++++++++++++++++++++++++ drivers/hid/hid-uclogic-rdesc.c | 102 ++++++++++++++++ drivers/hid/hid-uclogic-rdesc.h | 8 ++ 5 files changed, 312 insertions(+)