@@ -81,24 +81,6 @@ static __u8 *uclogic_report_fixup(struct hid_device *hdev, __u8 *rdesc,
8181 return rdesc ;
8282}
8383
84- static int uclogic_input_mapping (struct hid_device * hdev ,
85- struct hid_input * hi ,
86- struct hid_field * field ,
87- struct hid_usage * usage ,
88- unsigned long * * bit ,
89- int * max )
90- {
91- struct uclogic_drvdata * drvdata = hid_get_drvdata (hdev );
92- struct uclogic_params * params = & drvdata -> params ;
93-
94- /* discard the unused pen interface */
95- if (params -> pen_unused && (field -> application == HID_DG_PEN ))
96- return -1 ;
97-
98- /* let hid-core decide what to do */
99- return 0 ;
100- }
101-
10284static int uclogic_input_configured (struct hid_device * hdev ,
10385 struct hid_input * hi )
10486{
@@ -246,100 +228,171 @@ static int uclogic_resume(struct hid_device *hdev)
246228}
247229#endif
248230
231+ /**
232+ * uclogic_raw_event_pen - handle raw pen events (pen HID reports).
233+ *
234+ * @drvdata: Driver data.
235+ * @data: Report data buffer, can be modified.
236+ * @size: Report data size, bytes.
237+ *
238+ * Returns:
239+ * Negative value on error (stops event delivery), zero for success.
240+ */
241+ static int uclogic_raw_event_pen (struct uclogic_drvdata * drvdata ,
242+ u8 * data , int size )
243+ {
244+ struct uclogic_params_pen * pen = & drvdata -> params .pen ;
245+
246+ WARN_ON (drvdata == NULL );
247+ WARN_ON (data == NULL && size != 0 );
248+
249+ /* If in-range reports are inverted */
250+ if (pen -> inrange ==
251+ UCLOGIC_PARAMS_PEN_INRANGE_INVERTED ) {
252+ /* Invert the in-range bit */
253+ data [1 ] ^= 0x40 ;
254+ }
255+ /*
256+ * If report contains fragmented high-resolution pen
257+ * coordinates
258+ */
259+ if (size >= 10 && pen -> fragmented_hires ) {
260+ u8 pressure_low_byte ;
261+ u8 pressure_high_byte ;
262+
263+ /* Lift pressure bytes */
264+ pressure_low_byte = data [6 ];
265+ pressure_high_byte = data [7 ];
266+ /*
267+ * Move Y coord to make space for high-order X
268+ * coord byte
269+ */
270+ data [6 ] = data [5 ];
271+ data [5 ] = data [4 ];
272+ /* Move high-order X coord byte */
273+ data [4 ] = data [8 ];
274+ /* Move high-order Y coord byte */
275+ data [7 ] = data [9 ];
276+ /* Place pressure bytes */
277+ data [8 ] = pressure_low_byte ;
278+ data [9 ] = pressure_high_byte ;
279+ }
280+ /* If we need to emulate in-range detection */
281+ if (pen -> inrange == UCLOGIC_PARAMS_PEN_INRANGE_NONE ) {
282+ /* Set in-range bit */
283+ data [1 ] |= 0x40 ;
284+ /* (Re-)start in-range timeout */
285+ mod_timer (& drvdata -> inrange_timer ,
286+ jiffies + msecs_to_jiffies (100 ));
287+ }
288+ /* If we report tilt and Y direction is flipped */
289+ if (size >= 12 && pen -> tilt_y_flipped )
290+ data [11 ] = - data [11 ];
291+
292+ return 0 ;
293+ }
294+
295+ /**
296+ * uclogic_raw_event_frame - handle raw frame events (frame HID reports).
297+ *
298+ * @drvdata: Driver data.
299+ * @frame: The parameters of the frame controls to handle.
300+ * @data: Report data buffer, can be modified.
301+ * @size: Report data size, bytes.
302+ *
303+ * Returns:
304+ * Negative value on error (stops event delivery), zero for success.
305+ */
306+ static int uclogic_raw_event_frame (
307+ struct uclogic_drvdata * drvdata ,
308+ const struct uclogic_params_frame * frame ,
309+ u8 * data , int size )
310+ {
311+ WARN_ON (drvdata == NULL );
312+ WARN_ON (data == NULL && size != 0 );
313+
314+ /* If need to, and can, set pad device ID for Wacom drivers */
315+ if (frame -> dev_id_byte > 0 && frame -> dev_id_byte < size ) {
316+ data [frame -> dev_id_byte ] = 0xf ;
317+ }
318+ /* If need to, and can, read rotary encoder state change */
319+ if (frame -> re_lsb > 0 && frame -> re_lsb / 8 < size ) {
320+ unsigned int byte = frame -> re_lsb / 8 ;
321+ unsigned int bit = frame -> re_lsb % 8 ;
322+
323+ u8 change ;
324+ u8 prev_state = drvdata -> re_state ;
325+ /* Read Gray-coded state */
326+ u8 state = (data [byte ] >> bit ) & 0x3 ;
327+ /* Encode state change into 2-bit signed integer */
328+ if ((prev_state == 1 && state == 0 ) ||
329+ (prev_state == 2 && state == 3 )) {
330+ change = 1 ;
331+ } else if ((prev_state == 2 && state == 0 ) ||
332+ (prev_state == 1 && state == 3 )) {
333+ change = 3 ;
334+ } else {
335+ change = 0 ;
336+ }
337+ /* Write change */
338+ data [byte ] = (data [byte ] & ~((u8 )3 << bit )) |
339+ (change << bit );
340+ /* Remember state */
341+ drvdata -> re_state = state ;
342+ }
343+
344+ return 0 ;
345+ }
346+
249347static int uclogic_raw_event (struct hid_device * hdev ,
250348 struct hid_report * report ,
251349 u8 * data , int size )
252350{
351+ unsigned int report_id = report -> id ;
253352 struct uclogic_drvdata * drvdata = hid_get_drvdata (hdev );
254353 struct uclogic_params * params = & drvdata -> params ;
354+ struct uclogic_params_pen_subreport * subreport ;
355+ struct uclogic_params_pen_subreport * subreport_list_end ;
356+ size_t i ;
255357
256- /* Tweak pen reports, if necessary */
257- if (!params -> pen_unused &&
258- (report -> type == HID_INPUT_REPORT ) &&
259- (report -> id == params -> pen .id ) &&
260- (size >= 2 )) {
261- /* If it's the "virtual" frame controls report */
262- if (params -> frame .id != 0 &&
263- data [1 ] & params -> pen_frame_flag ) {
264- /* Change to virtual frame controls report ID */
265- data [0 ] = params -> frame .id ;
266- return 0 ;
267- }
268- /* If in-range reports are inverted */
269- if (params -> pen .inrange ==
270- UCLOGIC_PARAMS_PEN_INRANGE_INVERTED ) {
271- /* Invert the in-range bit */
272- data [1 ] ^= 0x40 ;
273- }
274- /*
275- * If report contains fragmented high-resolution pen
276- * coordinates
277- */
278- if (size >= 10 && params -> pen .fragmented_hires ) {
279- u8 pressure_low_byte ;
280- u8 pressure_high_byte ;
281-
282- /* Lift pressure bytes */
283- pressure_low_byte = data [6 ];
284- pressure_high_byte = data [7 ];
285- /*
286- * Move Y coord to make space for high-order X
287- * coord byte
288- */
289- data [6 ] = data [5 ];
290- data [5 ] = data [4 ];
291- /* Move high-order X coord byte */
292- data [4 ] = data [8 ];
293- /* Move high-order Y coord byte */
294- data [7 ] = data [9 ];
295- /* Place pressure bytes */
296- data [8 ] = pressure_low_byte ;
297- data [9 ] = pressure_high_byte ;
298- }
299- /* If we need to emulate in-range detection */
300- if (params -> pen .inrange == UCLOGIC_PARAMS_PEN_INRANGE_NONE ) {
301- /* Set in-range bit */
302- data [1 ] |= 0x40 ;
303- /* (Re-)start in-range timeout */
304- mod_timer (& drvdata -> inrange_timer ,
305- jiffies + msecs_to_jiffies (100 ));
306- }
307- }
358+ /* Do not handle anything but input reports */
359+ if (report -> type != HID_INPUT_REPORT )
360+ return 0 ;
308361
309- /* Tweak frame control reports, if necessary */
310- if ((report -> type == HID_INPUT_REPORT ) &&
311- (report -> id == params -> frame .id )) {
312- /* If need to, and can, set pad device ID for Wacom drivers */
313- if (params -> frame .dev_id_byte > 0 &&
314- params -> frame .dev_id_byte < size ) {
315- data [params -> frame .dev_id_byte ] = 0xf ;
316- }
317- /* If need to, and can, read rotary encoder state change */
318- if (params -> frame .re_lsb > 0 &&
319- params -> frame .re_lsb / 8 < size ) {
320- unsigned int byte = params -> frame .re_lsb / 8 ;
321- unsigned int bit = params -> frame .re_lsb % 8 ;
322-
323- u8 change ;
324- u8 prev_state = drvdata -> re_state ;
325- /* Read Gray-coded state */
326- u8 state = (data [byte ] >> bit ) & 0x3 ;
327- /* Encode state change into 2-bit signed integer */
328- if ((prev_state == 1 && state == 0 ) ||
329- (prev_state == 2 && state == 3 )) {
330- change = 1 ;
331- } else if ((prev_state == 2 && state == 0 ) ||
332- (prev_state == 1 && state == 3 )) {
333- change = 3 ;
362+ while (true) {
363+ /* Tweak pen reports, if necessary */
364+ if ((report_id == params -> pen .id ) && (size >= 2 )) {
365+ subreport_list_end =
366+ params -> pen .subreport_list +
367+ ARRAY_SIZE (params -> pen .subreport_list );
368+ /* Try to match a subreport */
369+ for (subreport = params -> pen .subreport_list ;
370+ subreport < subreport_list_end ; subreport ++ ) {
371+ if (subreport -> value != 0 &&
372+ subreport -> value == data [1 ]) {
373+ break ;
374+ }
375+ }
376+ /* If a subreport matched */
377+ if (subreport < subreport_list_end ) {
378+ /* Change to subreport ID, and restart */
379+ report_id = data [0 ] = subreport -> id ;
380+ continue ;
334381 } else {
335- change = 0 ;
382+ return uclogic_raw_event_pen (drvdata , data , size );
383+ }
384+ }
385+
386+ /* Tweak frame control reports, if necessary */
387+ for (i = 0 ; i < ARRAY_SIZE (params -> frame_list ); i ++ ) {
388+ if (report_id == params -> frame_list [i ].id ) {
389+ return uclogic_raw_event_frame (
390+ drvdata , & params -> frame_list [i ],
391+ data , size );
336392 }
337- /* Write change */
338- data [byte ] = (data [byte ] & ~((u8 )3 << bit )) |
339- (change << bit );
340- /* Remember state */
341- drvdata -> re_state = state ;
342393 }
394+
395+ break ;
343396 }
344397
345398 return 0 ;
@@ -373,7 +426,7 @@ static const struct hid_device_id uclogic_devices[] = {
373426 { HID_USB_DEVICE (USB_VENDOR_ID_HUION ,
374427 USB_DEVICE_ID_HUION_TABLET ) },
375428 { HID_USB_DEVICE (USB_VENDOR_ID_HUION ,
376- USB_DEVICE_ID_HUION_HS64 ) },
429+ USB_DEVICE_ID_HUION_TABLET2 ) },
377430 { HID_USB_DEVICE (USB_VENDOR_ID_TRUST ,
378431 USB_DEVICE_ID_TRUST_PANORA_TABLET ) },
379432 { HID_USB_DEVICE (USB_VENDOR_ID_UCLOGIC ,
@@ -415,7 +468,6 @@ static struct hid_driver uclogic_driver = {
415468 .remove = uclogic_remove ,
416469 .report_fixup = uclogic_report_fixup ,
417470 .raw_event = uclogic_raw_event ,
418- .input_mapping = uclogic_input_mapping ,
419471 .input_configured = uclogic_input_configured ,
420472#ifdef CONFIG_PM
421473 .resume = uclogic_resume ,
0 commit comments