linux/drivers/hid/hid-uclogic-params.c

// SPDX-License-Identifier: GPL-2.0+
/*
 *  HID driver for UC-Logic devices not fully compliant with HID standard
 *  - tablet initialization and parameter retrieval
 *
 *  Copyright (c) 2018 Nikolai Kondrashov
 */

/*
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License as published by the Free
 * Software Foundation; either version 2 of the License, or (at your option)
 * any later version.
 */

#include "hid-uclogic-params.h"
#include "hid-uclogic-rdesc.h"
#include "usbhid/usbhid.h"
#include "hid-ids.h"
#include <linux/ctype.h>
#include <linux/string.h>
#include <linux/unaligned.h>

/**
 * uclogic_params_pen_inrange_to_str() - Convert a pen in-range reporting type
 *                                       to a string.
 * @inrange:	The in-range reporting type to convert.
 *
 * Return:
 * * The string representing the type, or
 * * %NULL if the type is unknown.
 */
static const char *uclogic_params_pen_inrange_to_str(
				enum uclogic_params_pen_inrange inrange)
{}

/**
 * uclogic_params_pen_hid_dbg() - Dump tablet interface pen parameters
 * @hdev:	The HID device the pen parameters describe.
 * @pen:	The pen parameters to dump.
 *
 * Dump tablet interface pen parameters with hid_dbg(). The dump is indented
 * with a tab.
 */
static void uclogic_params_pen_hid_dbg(const struct hid_device *hdev,
					const struct uclogic_params_pen *pen)
{}

/**
 * uclogic_params_frame_hid_dbg() - Dump tablet interface frame parameters
 * @hdev:	The HID device the pen parameters describe.
 * @frame:	The frame parameters to dump.
 *
 * Dump tablet interface frame parameters with hid_dbg(). The dump is
 * indented with two tabs.
 */
static void uclogic_params_frame_hid_dbg(
				const struct hid_device *hdev,
				const struct uclogic_params_frame *frame)
{}

/**
 * uclogic_params_hid_dbg() - Dump tablet interface parameters
 * @hdev:	The HID device the parameters describe.
 * @params:	The parameters to dump.
 *
 * Dump tablet interface parameters with hid_dbg().
 */
void uclogic_params_hid_dbg(const struct hid_device *hdev,
				const struct uclogic_params *params)
{}

/**
 * uclogic_params_get_str_desc - retrieve a string descriptor from a HID
 * device interface, putting it into a kmalloc-allocated buffer as is, without
 * character encoding conversion.
 *
 * @pbuf:	Location for the kmalloc-allocated buffer pointer containing
 *		the retrieved descriptor. Not modified in case of error.
 *		Can be NULL to have retrieved descriptor discarded.
 * @hdev:	The HID device of the tablet interface to retrieve the string
 *		descriptor from. Cannot be NULL.
 * @idx:	Index of the string descriptor to request from the device.
 * @len:	Length of the buffer to allocate and the data to retrieve.
 *
 * Returns:
 *	number of bytes retrieved (<= len),
 *	-EPIPE, if the descriptor was not found, or
 *	another negative errno code in case of other error.
 */
static int uclogic_params_get_str_desc(__u8 **pbuf, struct hid_device *hdev,
					__u8 idx, size_t len)
{}

/**
 * uclogic_params_pen_cleanup - free resources used by struct
 * uclogic_params_pen (tablet interface's pen input parameters).
 * Can be called repeatedly.
 *
 * @pen:	Pen input parameters to cleanup. Cannot be NULL.
 */
static void uclogic_params_pen_cleanup(struct uclogic_params_pen *pen)
{}

/**
 * uclogic_params_pen_init_v1() - initialize tablet interface pen
 * input and retrieve its parameters from the device, using v1 protocol.
 *
 * @pen:	Pointer to the pen parameters to initialize (to be
 *		cleaned up with uclogic_params_pen_cleanup()). Not modified in
 *		case of error, or if parameters are not found. Cannot be NULL.
 * @pfound:	Location for a flag which is set to true if the parameters
 *		were found, and to false if not (e.g. device was
 *		incompatible). 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_pen_init_v1(struct uclogic_params_pen *pen,
				      bool *pfound,
				      struct hid_device *hdev)
{}

/**
 * uclogic_params_get_le24() - get a 24-bit little-endian number from a
 * buffer.
 *
 * @p:	The pointer to the number buffer.
 *
 * Returns:
 *	The retrieved number
 */
static s32 uclogic_params_get_le24(const void *p)
{}

/**
 * uclogic_params_pen_init_v2() - initialize tablet interface pen
 * input and retrieve its parameters from the device, using v2 protocol.
 *
 * @pen:		Pointer to the pen parameters to initialize (to be
 *			cleaned up with uclogic_params_pen_cleanup()). Not
 *			modified in case of error, or if parameters are not
 *			found. Cannot be NULL.
 * @pfound:		Location for a flag which is set to true if the
 *			parameters were found, and to false if not (e.g.
 *			device was incompatible). Not modified in case of
 *			error. Cannot be NULL.
 * @pparams_ptr:	Location for a kmalloc'ed pointer to the retrieved raw
 *			parameters, which could be used to identify the tablet
 *			to some extent. Should be freed with kfree after use.
 *			NULL, if not needed. Not modified in case of error.
 *			Only set if *pfound is set to true.
 * @pparams_len:	Location for the length of the retrieved raw
 *			parameters. NULL, if not needed. Not modified in case
 *			of error. Only set if *pfound is set to true.
 * @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_pen_init_v2(struct uclogic_params_pen *pen,
					bool *pfound,
					__u8 **pparams_ptr,
					size_t *pparams_len,
					struct hid_device *hdev)
{}

/**
 * uclogic_params_frame_cleanup - free resources used by struct
 * uclogic_params_frame (tablet interface's frame controls input parameters).
 * Can be called repeatedly.
 *
 * @frame:	Frame controls input parameters to cleanup. Cannot be NULL.
 */
static void uclogic_params_frame_cleanup(struct uclogic_params_frame *frame)
{}

/**
 * uclogic_params_frame_init_with_desc() - initialize tablet's frame control
 * parameters with a static report descriptor.
 *
 * @frame:	Pointer to the frame parameters to initialize (to be cleaned
 *		up with uclogic_params_frame_cleanup()). Not modified in case
 *		of error. Cannot be NULL.
 * @desc_ptr:	Report descriptor pointer. Can be NULL, if desc_size is zero.
 * @desc_size:	Report descriptor size.
 * @id:		Report ID used for frame reports, if they should be tweaked,
 *		zero if not.
 *
 * Returns:
 *	Zero, if successful. A negative errno code on error.
 */
static int uclogic_params_frame_init_with_desc(
					struct uclogic_params_frame *frame,
					const __u8 *desc_ptr,
					size_t desc_size,
					unsigned int id)
{}

/**
 * uclogic_params_frame_init_v1() - initialize v1 tablet interface frame
 * controls.
 *
 * @frame:	Pointer to the frame parameters to initialize (to be cleaned
 *		up with uclogic_params_frame_cleanup()). Not modified in case
 *		of error, or if parameters are not found. Cannot be NULL.
 * @pfound:	Location for a flag which is set to true if the parameters
 *		were found, and to false if not (e.g. device was
 *		incompatible). 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_frame_init_v1(struct uclogic_params_frame *frame,
					bool *pfound,
					struct hid_device *hdev)
{}

/**
 * uclogic_params_cleanup_event_hooks - free resources used by the list of raw
 * event hooks.
 * Can be called repeatedly.
 *
 * @params: Input parameters to cleanup. Cannot be NULL.
 */
static void uclogic_params_cleanup_event_hooks(struct uclogic_params *params)
{}

/**
 * uclogic_params_cleanup - free resources used by struct uclogic_params
 * (tablet interface's parameters).
 * Can be called repeatedly.
 *
 * @params:	Input parameters to cleanup. Cannot be NULL.
 */
void uclogic_params_cleanup(struct uclogic_params *params)
{}

/**
 * uclogic_params_get_desc() - Get a replacement report descriptor for a
 *                             tablet's interface.
 *
 * @params:	The parameters of a tablet interface to get report
 *		descriptor for. Cannot be NULL.
 * @pdesc:	Location for the resulting, kmalloc-allocated report
 *		descriptor pointer, or for NULL, if there's no replacement
 *		report descriptor. Not modified in case of error. Cannot be
 *		NULL.
 * @psize:	Location for the resulting report descriptor size, not set if
 *		there's no replacement report descriptor. Not modified in case
 *		of error. Cannot be NULL.
 *
 * Returns:
 *	Zero, if successful.
 *	-EINVAL, if invalid arguments are supplied.
 *	-ENOMEM, if failed to allocate memory.
 */
int uclogic_params_get_desc(const struct uclogic_params *params,
				const __u8 **pdesc,
				unsigned int *psize)
{}

/**
 * uclogic_params_init_invalid() - initialize tablet interface parameters,
 * specifying the interface is invalid.
 *
 * @params:		Parameters to initialize (to be cleaned with
 *			uclogic_params_cleanup()). Cannot be NULL.
 */
static void uclogic_params_init_invalid(struct uclogic_params *params)
{}

/**
 * uclogic_params_init_with_opt_desc() - initialize tablet interface
 * parameters with an optional replacement report descriptor. Only modify
 * report descriptor, if the original report descriptor matches the expected
 * size.
 *
 * @params:		Parameters to initialize (to be cleaned with
 *			uclogic_params_cleanup()). Not modified in case of
 *			error. Cannot be NULL.
 * @hdev:		The HID device of the tablet interface create the
 *			parameters for. Cannot be NULL.
 * @orig_desc_size:	Expected size of the original report descriptor to
 *			be replaced.
 * @desc_ptr:		Pointer to the replacement report descriptor.
 *			Can be NULL, if desc_size is zero.
 * @desc_size:		Size of the replacement report descriptor.
 *
 * Returns:
 *	Zero, if successful. -EINVAL if an invalid argument was passed.
 *	-ENOMEM, if failed to allocate memory.
 */
static int uclogic_params_init_with_opt_desc(struct uclogic_params *params,
					     struct hid_device *hdev,
					     unsigned int orig_desc_size,
					     const __u8 *desc_ptr,
					     unsigned int desc_size)
{}

/**
 * uclogic_params_huion_init() - initialize a Huion tablet interface and discover
 * its parameters.
 *
 * @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_huion_init(struct uclogic_params *params,
				     struct hid_device *hdev)
{}

/**
 * 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, const u8 *magic_arr,
				   size_t magic_size, int endpoint)
{}

/**
 * uclogic_params_parse_ugee_v2_desc - parse the string descriptor containing
 * pen and frame parameters returned by UGEE v2 devices.
 *
 * @str_desc:		String descriptor, cannot be NULL.
 * @str_desc_size:	Size of the string descriptor.
 * @desc_params:	Output description params list.
 * @desc_params_size:	Size of the output description params list.
 * @frame_type:		Output frame type.
 *
 * Returns:
 *	Zero, if successful. A negative errno code on error.
 */
static int uclogic_params_parse_ugee_v2_desc(const __u8 *str_desc,
					     size_t str_desc_size,
					     s32 *desc_params,
					     size_t desc_params_size,
					     enum uclogic_params_frame_type *frame_type)
{}

/**
 * uclogic_params_ugee_v2_init_frame_buttons() - initialize a UGEE v2 frame with
 * buttons.
 * @p:			Parameters to fill in, cannot be NULL.
 * @desc_params:	Device description params list.
 * @desc_params_size:	Size of the description params list.
 *
 * Returns:
 *	Zero, if successful. A negative errno code on error.
 */
static int uclogic_params_ugee_v2_init_frame_buttons(struct uclogic_params *p,
						     const s32 *desc_params,
						     size_t desc_params_size)
{}

/**
 * uclogic_params_ugee_v2_init_frame_dial() - initialize a UGEE v2 frame with a
 * bitmap dial.
 * @p:			Parameters to fill in, cannot be NULL.
 * @desc_params:	Device description params list.
 * @desc_params_size:	Size of the description params list.
 *
 * Returns:
 *	Zero, if successful. A negative errno code on error.
 */
static int uclogic_params_ugee_v2_init_frame_dial(struct uclogic_params *p,
						  const s32 *desc_params,
						  size_t desc_params_size)
{}

/**
 * uclogic_params_ugee_v2_init_frame_mouse() - initialize a UGEE v2 frame with a
 * mouse.
 * @p:			Parameters to fill in, cannot be NULL.
 *
 * Returns:
 *	Zero, if successful. A negative errno code on error.
 */
static int uclogic_params_ugee_v2_init_frame_mouse(struct uclogic_params *p)
{}

/**
 * uclogic_params_ugee_v2_has_battery() - check whether a UGEE v2 device has
 * battery or not.
 * @hdev:	The HID device of the tablet interface.
 *
 * Returns:
 *	True if the device has battery, false otherwise.
 */
static bool uclogic_params_ugee_v2_has_battery(struct hid_device *hdev)
{}

/**
 * uclogic_params_ugee_v2_init_battery() - initialize UGEE v2 battery reporting.
 * @hdev:	The HID device of the tablet interface, cannot be NULL.
 * @p:		Parameters to fill in, cannot be NULL.
 *
 * Returns:
 *	Zero, if successful. A negative errno code on error.
 */
static int uclogic_params_ugee_v2_init_battery(struct hid_device *hdev,
					       struct uclogic_params *p)
{}

/**
 * uclogic_params_ugee_v2_reconnect_work() - When a wireless tablet looses
 * connection to the USB dongle and reconnects, either because of its physical
 * distance or because it was switches off and on using the frame's switch,
 * uclogic_probe_interface() needs to be called again to enable the tablet.
 *
 * @work: The work that triggered this function.
 */
static void uclogic_params_ugee_v2_reconnect_work(struct work_struct *work)
{}

/**
 * uclogic_params_ugee_v2_init_event_hooks() - initialize the list of events
 * to be hooked for UGEE v2 devices.
 * @hdev:	The HID device of the tablet interface to initialize and get
 *		parameters from.
 * @p:		Parameters to fill in, cannot be NULL.
 *
 * Returns:
 *	Zero, if successful. A negative errno code on error.
 */
static int uclogic_params_ugee_v2_init_event_hooks(struct hid_device *hdev,
						   struct uclogic_params *p)
{}

/**
 * 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)
{}

/**
 * uclogic_params_init() - initialize a tablet interface and discover its
 * parameters.
 *
 * @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. Must be using the USB low-level
 *		driver, i.e. be an actual USB tablet.
 *
 * Returns:
 *	Zero, if successful. A negative errno code on error.
 */
int uclogic_params_init(struct uclogic_params *params,
			struct hid_device *hdev)
{}

#ifdef CONFIG_HID_KUNIT_TEST
#include "hid-uclogic-params-test.c"
#endif