@@ -337,28 +337,45 @@ static s32 uclogic_params_get_le24(const void *p)
337337 * uclogic_params_pen_init_v2() - initialize tablet interface pen
338338 * input and retrieve its parameters from the device, using v2 protocol.
339339 *
340- * @pen: Pointer to the pen parameters to initialize (to be
341- * cleaned up with uclogic_params_pen_cleanup()). Not modified in
342- * case of error, or if parameters are not found. Cannot be NULL.
343- * @pfound: Location for a flag which is set to true if the parameters
344- * were found, and to false if not (e.g. device was
345- * incompatible). Not modified in case of error. Cannot be NULL.
346- * @hdev: The HID device of the tablet interface to initialize and get
347- * parameters from. Cannot be NULL.
340+ * @pen: Pointer to the pen parameters to initialize (to be
341+ * cleaned up with uclogic_params_pen_cleanup()). Not
342+ * modified in case of error, or if parameters are not
343+ * found. Cannot be NULL.
344+ * @pfound: Location for a flag which is set to true if the
345+ * parameters were found, and to false if not (e.g.
346+ * device was incompatible). Not modified in case of
347+ * error. Cannot be NULL.
348+ * @pparams_ptr: Location for a kmalloc'ed pointer to the retrieved raw
349+ * parameters, which could be used to identify the tablet
350+ * to some extent. Should be freed with kfree after use.
351+ * NULL, if not needed. Not modified in case of error.
352+ * Only set if *pfound is set to true.
353+ * @pparams_len: Location for the length of the retrieved raw
354+ * parameters. NULL, if not needed. Not modified in case
355+ * of error. Only set if *pfound is set to true.
356+ * @hdev: The HID device of the tablet interface to initialize
357+ * and get parameters from. Cannot be NULL.
348358 *
349359 * Returns:
350360 * Zero, if successful. A negative errno code on error.
351361 */
352362static int uclogic_params_pen_init_v2 (struct uclogic_params_pen * pen ,
353363 bool * pfound ,
364+ __u8 * * pparams_ptr ,
365+ size_t * pparams_len ,
354366 struct hid_device * hdev )
355367{
356368 int rc ;
357369 bool found = false;
358- /* Buffer for (part of) the string descriptor */
370+ /* Buffer for (part of) the parameter string descriptor */
359371 __u8 * buf = NULL ;
360- /* Descriptor length required */
361- const int len = 18 ;
372+ /* Parameter string descriptor required length */
373+ const int params_len_min = 18 ;
374+ /* Parameter string descriptor accepted length */
375+ const int params_len_max = 32 ;
376+ /* Parameter string descriptor received length */
377+ int params_len ;
378+ size_t i ;
362379 s32 resolution ;
363380 /* Pen report descriptor template parameters */
364381 s32 desc_params [UCLOGIC_RDESC_PEN_PH_ID_NUM ];
@@ -376,35 +393,36 @@ static int uclogic_params_pen_init_v2(struct uclogic_params_pen *pen,
376393 * the Windows driver traffic.
377394 * NOTE: This enables fully-functional tablet mode.
378395 */
379- rc = uclogic_params_get_str_desc (& buf , hdev , 200 , len );
396+ rc = uclogic_params_get_str_desc (& buf , hdev , 200 , params_len_max );
380397 if (rc == - EPIPE ) {
381398 hid_dbg (hdev ,
382399 "string descriptor with pen parameters not found, assuming not compatible\n" );
383400 goto finish ;
384401 } else if (rc < 0 ) {
385402 hid_err (hdev , "failed retrieving pen parameters: %d\n" , rc );
386403 goto cleanup ;
387- } else if (rc != len ) {
404+ } else if (rc < params_len_min ) {
388405 hid_dbg (hdev ,
389- "string descriptor with pen parameters has invalid length (got %d, expected %d), assuming not compatible\n" ,
390- rc , len );
406+ "string descriptor with pen parameters is too short (got %d, expected at least %d), assuming not compatible\n" ,
407+ rc , params_len_min );
408+ goto finish ;
409+ }
410+
411+ params_len = rc ;
412+
413+ /*
414+ * Check it's not just a catch-all UTF-16LE-encoded ASCII
415+ * string (such as the model name) some tablets put into all
416+ * unknown string descriptors.
417+ */
418+ for (i = 2 ;
419+ i < params_len &&
420+ (buf [i ] >= 0x20 && buf [i ] < 0x7f && buf [i + 1 ] == 0 );
421+ i += 2 );
422+ if (i >= params_len ) {
423+ hid_dbg (hdev ,
424+ "string descriptor with pen parameters seems to contain only text, assuming not compatible\n" );
391425 goto finish ;
392- } else {
393- size_t i ;
394- /*
395- * Check it's not just a catch-all UTF-16LE-encoded ASCII
396- * string (such as the model name) some tablets put into all
397- * unknown string descriptors.
398- */
399- for (i = 2 ;
400- i < len &&
401- (buf [i ] >= 0x20 && buf [i ] < 0x7f && buf [i + 1 ] == 0 );
402- i += 2 );
403- if (i >= len ) {
404- hid_dbg (hdev ,
405- "string descriptor with pen parameters seems to contain only text, assuming not compatible\n" );
406- goto finish ;
407- }
408426 }
409427
410428 /*
@@ -428,8 +446,6 @@ static int uclogic_params_pen_init_v2(struct uclogic_params_pen *pen,
428446 desc_params [UCLOGIC_RDESC_PEN_PH_ID_Y_LM ] * 1000 /
429447 resolution ;
430448 }
431- kfree (buf );
432- buf = NULL ;
433449
434450 /*
435451 * Generate pen report descriptor
@@ -455,6 +471,13 @@ static int uclogic_params_pen_init_v2(struct uclogic_params_pen *pen,
455471 pen -> fragmented_hires = true;
456472 pen -> tilt_y_flipped = true;
457473 found = true;
474+ if (pparams_ptr != NULL ) {
475+ * pparams_ptr = buf ;
476+ buf = NULL ;
477+ }
478+ if (pparams_len != NULL ) {
479+ * pparams_len = params_len ;
480+ }
458481finish :
459482 * pfound = found ;
460483 rc = 0 ;
@@ -820,7 +843,8 @@ static int uclogic_params_huion_init(struct uclogic_params *params,
820843 "transition firmware detected, not probing pen v2 parameters\n" );
821844 } else {
822845 /* Try to probe v2 pen parameters */
823- rc = uclogic_params_pen_init_v2 (& p .pen , & found , hdev );
846+ rc = uclogic_params_pen_init_v2 (& p .pen , & found ,
847+ NULL , NULL , hdev );
824848 if (rc != 0 ) {
825849 hid_err (hdev ,
826850 "failed probing pen v2 parameters: %d\n" , rc );
0 commit comments