* Re: [PATCH 2/7] Input: pmic8xxx-pwrkey - Migrate to regmap APIs
From: Dmitry Torokhov @ 2013-12-15 11:33 UTC (permalink / raw)
To: Stephen Boyd; +Cc: linux-kernel, linux-arm-msm, linux-arm-kernel, linux-input
In-Reply-To: <1386718996-3733-3-git-send-email-sboyd@codeaurora.org>
On Tue, Dec 10, 2013 at 03:43:11PM -0800, Stephen Boyd wrote:
> Use the regmap APIs for this driver instead of custom pm8xxx
> APIs. This breaks this driver's dependency on the pm8xxx APIs and
> allows us to easily port it to other bus protocols in the future.
>
> Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
> ---
> drivers/input/misc/pmic8xxx-pwrkey.c | 13 +++++++++----
> 1 file changed, 9 insertions(+), 4 deletions(-)
>
> diff --git a/drivers/input/misc/pmic8xxx-pwrkey.c b/drivers/input/misc/pmic8xxx-pwrkey.c
> index 233b216..a4de105 100644
> --- a/drivers/input/misc/pmic8xxx-pwrkey.c
> +++ b/drivers/input/misc/pmic8xxx-pwrkey.c
> @@ -18,9 +18,9 @@
> #include <linux/input.h>
> #include <linux/interrupt.h>
> #include <linux/platform_device.h>
> +#include <linux/regmap.h>
> #include <linux/log2.h>
>
> -#include <linux/mfd/pm8xxx/core.h>
> #include <linux/input/pmic8xxx-pwrkey.h>
>
> #define PON_CNTL_1 0x1C
> @@ -83,7 +83,8 @@ static int pmic8xxx_pwrkey_probe(struct platform_device *pdev)
> int key_press_irq = platform_get_irq(pdev, 1);
> int err;
> unsigned int delay;
> - u8 pon_cntl;
> + unsigned int pon_cntl;
> + struct regmap *regmap;
> struct pmic8xxx_pwrkey *pwrkey;
> const struct pm8xxx_pwrkey_platform_data *pdata =
> dev_get_platdata(&pdev->dev);
> @@ -108,6 +109,10 @@ static int pmic8xxx_pwrkey_probe(struct platform_device *pdev)
> err = -ENOMEM;
> }
>
> + regmap = dev_get_regmap(pdev->dev.parent, NULL);
> + if (!regmap)
> + return -ENODEV;
And you are leaking memory here...
> +
> input_set_capability(pwr, EV_KEY, KEY_POWER);
>
> pwr->name = "pmic8xxx_pwrkey";
> @@ -116,7 +121,7 @@ static int pmic8xxx_pwrkey_probe(struct platform_device *pdev)
> delay = (pdata->kpd_trigger_delay_us << 10) / USEC_PER_SEC;
> delay = 1 + ilog2(delay);
>
> - err = pm8xxx_readb(pdev->dev.parent, PON_CNTL_1, &pon_cntl);
> + err = regmap_read(regmap, PON_CNTL_1, &pon_cntl);
> if (err < 0) {
> dev_err(&pdev->dev, "failed reading PON_CNTL_1 err=%d\n", err);
> return err;
> @@ -129,7 +134,7 @@ static int pmic8xxx_pwrkey_probe(struct platform_device *pdev)
> else
> pon_cntl &= ~PON_CNTL_PULL_UP;
>
> - err = pm8xxx_writeb(pdev->dev.parent, PON_CNTL_1, pon_cntl);
> + err = regmap_write(regmap, PON_CNTL_1, pon_cntl);
> if (err < 0) {
> dev_err(&pdev->dev, "failed writing PON_CNTL_1 err=%d\n", err);
> return err;
> --
> The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
> hosted by The Linux Foundation
>
--
Dmitry
^ permalink raw reply
* Re: [PATCH] input synaptics-rmi4: Debugfs initialization fixes
From: Dmitry Torokhov @ 2013-12-15 11:56 UTC (permalink / raw)
To: Christopher Heiny
Cc: Linux Input, Andrew Duggan, Vincent Huang, Vivian Ly,
Daniel Rosenberg, Jean Delvare, Joerie de Gram, Linus Walleij,
Benjamin Tissoires
In-Reply-To: <1386727924-11522-1-git-send-email-cheiny@synaptics.com>
On Tue, Dec 10, 2013 at 06:12:04PM -0800, Christopher Heiny wrote:
> This fixes the broken #ifdefs on CONFIG_RMI4_DEBUG. Per device debugfs
> setup is reordered to ensure that the debugfs tree for a given device is
> created before it is registered (since the action of registering a device
> may cause other things to happen that depend on debugfs being initialized
> already).
>
> Signed-off-by: Christopher Heiny <cheiny@synaptics.com>
> Cc: Dmitry Torokhov <dmitry.torokhov@gmail.com>
> Cc: Jean Delvare <khali@linux-fr.org>
> Cc: Linus Walleij <linus.walleij@stericsson.com>
> Cc: Joerie de Gram <j.de.gram@gmail.com>
> Cc: Benjamin Tissoires <benjamin.tissoires@redhat.com>
>
Applied, thank you.
> ---
>
> This patch implements changes to the synaptics-rmi4 branch of
> Dmitry's input tree. The base for the patch is commit
> f154022b208a59b048f52b7b5d58a5ec1949b96e.
>
> drivers/input/rmi4/rmi_bus.c | 24 +++++++++++++++---------
> 1 file changed, 15 insertions(+), 9 deletions(-)
>
> diff --git a/drivers/input/rmi4/rmi_bus.c b/drivers/input/rmi4/rmi_bus.c
> index cb14cf6..173f6be 100644
> --- a/drivers/input/rmi4/rmi_bus.c
> +++ b/drivers/input/rmi4/rmi_bus.c
> @@ -47,7 +47,7 @@ bool rmi_is_physical_device(struct device *dev)
> return dev->type == &rmi_device_type;
> }
>
> -#if CONFIG_RMI4_DEBUG
> +#ifdef CONFIG_RMI4_DEBUG
>
> static void rmi_physical_setup_debugfs(struct rmi_device *rmi_dev)
> {
> @@ -109,12 +109,12 @@ int rmi_register_physical_device(struct rmi_phys_device *phys)
>
> phys->rmi_dev = rmi_dev;
>
> + rmi_physical_setup_debugfs(rmi_dev);
> +
> error = device_register(&rmi_dev->dev);
> if (error)
> return error;
>
> - rmi_physical_setup_debugfs(rmi_dev);
> -
> dev_dbg(phys->dev, "%s: Registered %s as %s.\n", __func__,
> pdata->sensor_name, dev_name(&rmi_dev->dev));
>
> @@ -155,7 +155,7 @@ bool rmi_is_function_device(struct device *dev)
> return dev->type == &rmi_function_type;
> }
>
> -#if CONFIG_RMI4_DEBUG
> +#ifdef CONFIG_RMI4_DEBUG
>
> static void rmi_function_setup_debugfs(struct rmi_function *fn)
> {
> @@ -233,18 +233,23 @@ int rmi_register_function(struct rmi_function *fn)
> fn->dev.type = &rmi_function_type;
> fn->dev.bus = &rmi_bus_type;
>
> + rmi_function_setup_debugfs(fn);
> +
> error = device_register(&fn->dev);
> if (error) {
> dev_err(&rmi_dev->dev,
> "Failed device_register function device %s\n",
> dev_name(&fn->dev));
> - return error;
> + goto error_exit;
> }
>
> dev_dbg(&rmi_dev->dev, "Registered F%02X.\n", fn->fd.function_number);
>
> - rmi_function_setup_debugfs(fn);
> return 0;
> +
> +error_exit:
> + rmi_function_teardown_debugfs(fn);
> + return error;
> }
>
> void rmi_unregister_function(struct rmi_function *fn)
> @@ -357,6 +362,8 @@ static int __init rmi_bus_init(void)
> return error;
> }
>
> + rmi_bus_setup_debugfs();
> +
> error = rmi_register_f01_handler();
> if (error) {
> pr_err("%s: error registering the RMI F01 handler: %d\n",
> @@ -371,13 +378,12 @@ static int __init rmi_bus_init(void)
> goto err_unregister_f01;
> }
>
> - rmi_bus_setup_debugfs();
> -
> return 0;
>
> err_unregister_f01:
> rmi_unregister_f01_handler();
> err_unregister_bus:
> + rmi_bus_teardown_debugfs();
> bus_unregister(&rmi_bus_type);
> return error;
> }
> @@ -390,9 +396,9 @@ static void __exit rmi_bus_exit(void)
> * all we have to do at this point is unregister ourselves.
> */
>
> - rmi_bus_teardown_debugfs();
> rmi_unregister_physical_driver();
> rmi_unregister_f01_handler();
> + rmi_bus_teardown_debugfs();
> bus_unregister(&rmi_bus_type);
> }
> module_exit(rmi_bus_exit);
--
Dmitry
^ permalink raw reply
* Re: [PATCH] input synaptics-rmi4: Eliminate packed structs in rmi_f11.c
From: Dmitry Torokhov @ 2013-12-15 11:57 UTC (permalink / raw)
To: Christopher Heiny
Cc: Linux Input, Andrew Duggan, Vincent Huang, Vivian Ly,
Daniel Rosenberg, Jean Delvare, Joerie de Gram, Linus Walleij,
Benjamin Tissoires
In-Reply-To: <1386729594-5471-1-git-send-email-cheiny@synaptics.com>
On Tue, Dec 10, 2013 at 06:39:54PM -0800, Christopher Heiny wrote:
> This converts rmi_f11.c from using bitfields in packed structs, converting
> to bitmasks and shifts to parse out bitfields, nibbles, and so on.
>
> Signed-off-by: Christopher Heiny <cheiny@synaptics.com>
> Cc: Dmitry Torokhov <dmitry.torokhov@gmail.com>
> Cc: Jean Delvare <khali@linux-fr.org>
> Cc: Linus Walleij <linus.walleij@stericsson.com>
> Cc: Joerie de Gram <j.de.gram@gmail.com>
> Cc: Benjamin Tissoires <benjamin.tissoires@redhat.com>
>
Applied, thank you.
>
>
> > ---
> >
> > This patch implements changes to the synaptics-rmi4 branch of
> > Dmitry's input tree. The base for the patch is commit
> > f154022b208a59b048f52b7b5d58a5ec1949b96e.
> >
> > drivers/input/rmi4/rmi_f11.c | 1526 +++++++++++++++---------------------------
> > 1 file changed, 553 insertions(+), 973 deletions(-)
> >
> > diff --git a/drivers/input/rmi4/rmi_f11.c b/drivers/input/rmi4/rmi_f11.c
> > index d3a9ba8..d63ef31 100644
> > --- a/drivers/input/rmi4/rmi_f11.c
> > +++ b/drivers/input/rmi4/rmi_f11.c
> > @@ -69,33 +69,124 @@
> > */
> >
> > /**
> > - * @rezero - writing 1 to this will cause the sensor to calibrate to the
> > - * current capacitive state.
> > + * @rezero - writing this to the F11 command register will cause the sensor to
> > + * calibrate to the current capacitive state.
> > */
> > -struct f11_2d_commands {
> > - u8 rezero:1;
> > - u8 reserved:7;
> > -} __attribute__((__packed__));
> > +#define RMI_F11_REZERO 0x01
> > +
> > +#define RMI_F11_HAS_QUERY9 (1 << 3)
> > +#define RMI_F11_HAS_QUERY11 (1 << 4)
> > +#define RMI_F11_HAS_QUERY12 (1 << 5)
> > +#define RMI_F11_HAS_QUERY27 (1 << 6)
> > +#define RMI_F11_HAS_QUERY28 (1 << 7)
> > +
> > +/** Defs for Query 1 */
> > +
> > +#define RMI_F11_NR_FINGERS_MASK 0x07
> > +#define RMI_F11_HAS_REL (1 << 3)
> > +#define RMI_F11_HAS_ABS (1 << 4)
> > +#define RMI_F11_HAS_GESTURES (1 << 5)
> > +#define RMI_F11_HAS_SENSITIVITY_ADJ (1 << 6)
> > +#define RMI_F11_CONFIGURABLE (1 << 7)
> > +
> > +/** Defs for Query 2, 3, and 4. */
> > +#define RMI_F11_NR_ELECTRODES_MASK 0x7F
> > +
> > +/** Defs for Query 5 */
> > +
> > +#define RMI_F11_ABS_DATA_SIZE_MASK 0x03
> > +#define RMI_F11_HAS_ANCHORED_FINGER (1 << 2)
> > +#define RMI_F11_HAS_ADJ_HYST (1 << 3)
> > +#define RMI_F11_HAS_DRIBBLE (1 << 4)
> > +#define RMI_F11_HAS_BENDING_CORRECTION (1 << 5)
> > +#define RMI_F11_HAS_LARGE_OBJECT_SUPPRESSION (1 << 6)
> > +#define RMI_F11_HAS_JITTER_FILTER (1 << 7)
> > +
> > +/** Defs for Query 7 */
> > +#define RMI_F11_HAS_SINGLE_TAP (1 << 0)
> > +#define RMI_F11_HAS_TAP_AND_HOLD (1 << 1)
> > +#define RMI_F11_HAS_DOUBLE_TAP (1 << 2)
> > +#define RMI_F11_HAS_EARLY_TAP (1 << 3)
> > +#define RMI_F11_HAS_FLICK (1 << 4)
> > +#define RMI_F11_HAS_PRESS (1 << 5)
> > +#define RMI_F11_HAS_PINCH (1 << 6)
> > +#define RMI_F11_HAS_CHIRAL (1 << 7)
> > +
> > +/** Defs for Query 8 */
> > +#define RMI_F11_HAS_PALM_DET (1 << 0)
> > +#define RMI_F11_HAS_ROTATE (1 << 1)
> > +#define RMI_F11_HAS_TOUCH_SHAPES (1 << 2)
> > +#define RMI_F11_HAS_SCROLL_ZONES (1 << 3)
> > +#define RMI_F11_HAS_INDIVIDUAL_SCROLL_ZONES (1 << 4)
> > +#define RMI_F11_HAS_MF_SCROLL (1 << 5)
> > +#define RMI_F11_HAS_MF_EDGE_MOTION (1 << 6)
> > +#define RMI_F11_HAS_MF_SCROLL_INERTIA (1 << 7)
> > +
> > +/** Defs for Query 9. */
> > +#define RMI_F11_HAS_PEN (1 << 0)
> > +#define RMI_F11_HAS_PROXIMITY (1 << 1)
> > +#define RMI_F11_HAS_PALM_DET_SENSITIVITY (1 << 2)
> > +#define RMI_F11_HAS_SUPPRESS_ON_PALM_DETECT (1 << 3)
> > +#define RMI_F11_HAS_TWO_PEN_THRESHOLDS (1 << 4)
> > +#define RMI_F11_HAS_CONTACT_GEOMETRY (1 << 5)
> > +#define RMI_F11_HAS_PEN_HOVER_DISCRIMINATION (1 << 6)
> > +#define RMI_F11_HAS_PEN_FILTERS (1 << 7)
> > +
> > +/** Defs for Query 10. */
> > +#define RMI_F11_NR_TOUCH_SHAPES_MASK 0x1F
> > +
> > +/** Defs for Query 11 */
> > +
> > +#define RMI_F11_HAS_Z_TUNING (1 << 0)
> > +#define RMI_F11_HAS_ALGORITHM_SELECTION (1 << 1)
> > +#define RMI_F11_HAS_W_TUNING (1 << 2)
> > +#define RMI_F11_HAS_PITCH_INFO (1 << 3)
> > +#define RMI_F11_HAS_FINGER_SIZE (1 << 4)
> > +#define RMI_F11_HAS_SEGMENTATION_AGGRESSIVENESS (1 << 5)
> > +#define RMI_F11_HAS_XY_CLIP (1 << 6)
> > +#define RMI_F11_HAS_DRUMMING_FILTER (1 << 7)
> > +
> > +/** Defs for Query 12. */
> > +
> > +#define RMI_F11_HAS_GAPLESS_FINGER (1 << 0)
> > +#define RMI_F11_HAS_GAPLESS_FINGER_TUNING (1 << 1)
> > +#define RMI_F11_HAS_8BIT_W (1 << 2)
> > +#define RMI_F11_HAS_ADJUSTABLE_MAPPING (1 << 3)
> > +#define RMI_F11_HAS_INFO2 (1 << 4)
> > +#define RMI_F11_HAS_PHYSICAL_PROPS (1 << 5)
> > +#define RMI_F11_HAS_FINGER_LIMIT (1 << 6)
> > +#define RMI_F11_HAS_LINEAR_COEFF (1 << 7)
> > +
> > +/** Defs for Query 13. */
> > +
> > +#define RMI_F11_JITTER_WINDOW_MASK 0x1F
> > +#define RMI_F11_JITTER_FILTER_MASK 0x60
> > +#define RMI_F11_JITTER_FILTER_SHIFT 5
> > +
> > +/** Defs for Query 14. */
> > +#define RMI_F11_LIGHT_CONTROL_MASK 0x03
> > +#define RMI_F11_IS_CLEAR (1 << 2)
> > +#define RMI_F11_CLICKPAD_PROPS_MASK 0x18
> > +#define RMI_F11_CLICKPAD_PROPS_SHIFT 3
> > +#define RMI_F11_MOUSE_BUTTONS_MASK 0x60
> > +#define RMI_F11_MOUSE_BUTTONS_SHIFT 5
> > +#define RMI_F11_HAS_ADVANCED_GESTURES (1 << 7)
> > +
> > +#define RMI_F11_QUERY_SIZE 4
> > +#define RMI_F11_QUERY_GESTURE_SIZE 2
> >
> > -/** This query is always present, and is on a per device basis. All other
> > - * queries are on a per-sensor basis.
> > +#define F11_LIGHT_CTL_NONE 0x00
> > +#define F11_LUXPAD 0x01
> > +#define F11_DUAL_MODE 0x02
> > +
> > +#define F11_NOT_CLICKPAD 0x00
> > +#define F11_HINGED_CLICKPAD 0x01
> > +#define F11_UNIFORM_CLICKPAD 0x02
> > +
> > +/**
> > + * Query registers 1 through 4 are always present.
> > *
> > - * @nbr_of_sensors - the number of 2D sensors on the touch device.
> > - * @has_query9 - indicates the F11_2D_Query9 register exists.
> > - * @has_query11 - indicates the F11_2D_Query11 register exists.
> > - * @has_query12 - indicates the F11_2D_Query12 register exists.
> > - */
> > -struct f11_2d_device_query {
> > - u8 nbr_of_sensors:3;
> > - u8 has_query9:1;
> > - u8 has_query11:1;
> > - u8 has_query12:1;
> > - u8 has_query27:1;
> > - u8 has_query28:1;
> > -} __attribute__((__packed__));
> > -
> > -/** Query registers 1 through 4 are always present.
> > - * @number_of_fingers - describes the maximum number of fingers the 2-D sensor
> > + * @nr_fingers - describes the maximum number of fingers the 2-D sensor
> > * supports.
> > * @has_rel - the sensor supports relative motion reporting.
> > * @has_abs - the sensor supports absolute poition reporting.
> > @@ -109,27 +200,8 @@ struct f11_2d_device_query {
> > * supports on the Y axis.
> > * @max_electrodes - the total number of X and Y electrodes that may be
> > * configured.
> > - */
> > -struct f11_2d_sensor_info {
> > - /* query1 */
> > - u8 number_of_fingers:3;
> > - u8 has_rel:1;
> > - u8 has_abs:1;
> > - u8 has_gestures:1;
> > - u8 has_sensitivity_adjust:1;
> > - u8 configurable:1;
> > - /* query2 */
> > - u8 num_of_x_electrodes:7;
> > - u8 reserved_1:1;
> > - /* query3 */
> > - u8 num_of_y_electrodes:7;
> > - u8 reserved_2:1;
> > - /* query4 */
> > - u8 max_electrodes:7;
> > - u8 reserved_3:1;
> > -} __attribute__((__packed__));
> > -
> > -/** Query 5 - this is present if the has_abs bit is set.
> > + *
> > + * Query 5 is present if the has_abs bit is set.
> > *
> > * @abs_data_size - describes the format of data reported by the absolute
> > * data source. Only one format (the kind used here) is supported at this
> > @@ -146,18 +218,8 @@ struct f11_2d_sensor_info {
> > * @has_large_object_suppression - control register 58 and data register 28
> > * exist.
> > * @has_jitter_filter - query 13 and control 73..76 exist.
> > - */
> > -struct f11_2d_abs_info {
> > - u8 abs_data_size:2;
> > - u8 has_anchored_finger:1;
> > - u8 has_adj_hyst:1;
> > - u8 has_dribble:1;
> > - u8 has_bending_correction:1;
> > - u8 has_large_object_suppression:1;
> > - u8 has_jitter_filter:1;
> > -} __attribute__((__packed__));
> > -
> > -/** Gesture information queries 7 and 8 are present if has_gestures bit is set.
> > + *
> > + * Gesture information queries 7 and 8 are present if has_gestures bit is set.
> > *
> > * @has_single_tap - a basic single-tap gesture is supported.
> > * @has_tap_n_hold - tap-and-hold gesture is supported.
> > @@ -176,38 +238,17 @@ struct f11_2d_abs_info {
> > * @has_scroll_zones - scrolling areas near the sensor edges are supported.
> > * @has_individual_scroll_zones - if 1, then 4 scroll zones are supported;
> > * if 0, then only two are supported.
> > - * @has_multi_finger_scroll - the multifinger_scrolling bit will be set when
> > + * @has_mf_scroll - the multifinger_scrolling bit will be set when
> > * more than one finger is involved in a scrolling action.
> > - */
> > -struct f11_2d_gesture_info {
> > - u8 has_single_tap:1;
> > - u8 has_tap_n_hold:1;
> > - u8 has_double_tap:1;
> > - u8 has_early_tap:1;
> > - u8 has_flick:1;
> > - u8 has_press:1;
> > - u8 has_pinch:1;
> > - u8 has_chiral:1;
> > -
> > - u8 has_palm_det:1;
> > - u8 has_rotate:1;
> > - u8 has_touch_shapes:1;
> > - u8 has_scroll_zones:1;
> > - u8 has_individual_scroll_zones:1;
> > - u8 has_multi_finger_scroll:1;
> > - u8 has_mf_edge_motion:1;
> > - u8 has_mf_scroll_inertia:1;
> > -} __attribute__((__packed__));
> > -
> > -/** Utility for checking bytes in the gesture info registers. This is done
> > - * often enough that we put it here to declutter the conditionals.
> > - */
> > -static bool has_gesture_bits(const struct f11_2d_gesture_info *info,
> > - const u8 byte) {
> > - return ((u8 *) info)[byte] != 0;
> > -}
> > -
> > -/**
> > + *
> > + * Convenience for checking bytes in the gesture info registers. This is done
> > + * often enough that we put it here to declutter the conditionals
> > + *
> > + * @query7_nonzero - true if none of the query 7 bits are set
> > + * @query8_nonzero - true if none of the query 8 bits are set
> > + *
> > + * Query 9 is present if the has_query9 is set.
> > + *
> > * @has_pen - detection of a stylus is supported and registers F11_2D_Ctrl20
> > * and F11_2D_Ctrl21 exist.
> > * @has_proximity - detection of fingers near the sensor is supported and
> > @@ -216,30 +257,14 @@ static bool has_gesture_bits(const struct f11_2d_gesture_info *info,
> > * feature and register F11_2D_Ctrl27 exists.
> > * @has_two_pen_thresholds - is has_pen is also set, then F11_2D_Ctrl35 exists.
> > * @has_contact_geometry - the sensor supports the use of contact geometry to
> > - * map absolute X and Y target positions and registers F11_2D_Data18.* through
> > - * F11_2D_Data27 exist.
> > - */
> > -struct f11_2d_query9 {
> > - u8 has_pen:1;
> > - u8 has_proximity:1;
> > - u8 has_palm_det_sensitivity:1;
> > - u8 has_suppress_on_palm_detect:1;
> > - u8 has_two_pen_thresholds:1;
> > - u8 has_contact_geometry:1;
> > - u8 has_pen_hover_discrimination:1;
> > - u8 has_pen_filters:1;
> > -} __attribute__((__packed__));
> > -
> > -/** Touch shape info (query 10) is present if has_touch_shapes is set.
> > + * map absolute X and Y target positions and registers F11_2D_Data18
> > + * through F11_2D_Data27 exist.
> > *
> > - * @nbr_touch_shapes - the total number of touch shapes supported.
> > - */
> > -struct f11_2d_ts_info {
> > - u8 nbr_touch_shapes:5;
> > - u8 reserved:3;
> > -} __attribute__((__packed__));
> > -
> > -/** Query 11 is present if the has_query11 bit is set in query 0.
> > + * Touch shape info (query 10) is present if has_touch_shapes is set.
> > + *
> > + * @nr_touch_shapes - the total number of touch shapes supported.
> > + *
> > + * Query 11 is present if the has_query11 bit is set in query 0.
> > *
> > * @has_z_tuning - if set, the sensor supports Z tuning and registers
> > * F11_2D_Ctrl29 through F11_2D_Ctrl33 exist.
> > @@ -259,19 +284,9 @@ struct f11_2d_ts_info {
> > * @has_drumming_filter - the sensor can be configured to distinguish
> > * between a fast flick and a quick drumming movement and registers
> > * F11_2D_Ctrl50 and F11_2D_Ctrl51 exist.
> > - */
> > -struct f11_2d_query11 {
> > - u8 has_z_tuning:1;
> > - u8 has_algorithm_selection:1;
> > - u8 has_w_tuning:1;
> > - u8 has_pitch_info:1;
> > - u8 has_finger_size:1;
> > - u8 has_segmentation_aggressiveness:1;
> > - u8 has_XY_clip:1;
> > - u8 has_drumming_filter:1;
> > -} __attribute__((__packed__));
> > -
> > -/**
> > + *
> > + * Query 12 is present if hasQuery12 bit is set.
> > + *
> > * @has_gapless_finger - control registers relating to gapless finger are
> > * present.
> > * @has_gapless_finger_tuning - additional control and data registers relating
> > @@ -283,29 +298,12 @@ struct f11_2d_query11 {
> > * of the sensor are present.
> > * @has_finger_limit - indicates that F11 Ctrl 80 exists.
> > * @has_linear_coeff - indicates that F11 Ctrl 81 exists.
> > - */
> > -struct f11_2d_query12 {
> > - u8 has_gapless_finger:1;
> > - u8 has_gapless_finger_tuning:1;
> > - u8 has_8bit_w:1;
> > - u8 has_adjustable_mapping:1;
> > - u8 has_info2:1;
> > - u8 has_physical_props:1;
> > - u8 has_finger_limit:1;
> > - u8 has_linear_coeff_2:1;
> > -} __attribute__((__packed__));
> > -
> > -/** This register is present if Query 5's has_jitter_filter bit is set.
> > + *
> > + * Query 13 is present if Query 5's has_jitter_filter bit is set.
> > * @jitter_window_size - used by Design Studio 4.
> > * @jitter_filter_type - used by Design Studio 4.
> > - */
> > -struct f11_2d_query13 {
> > - u8 jtter_window_size:5;
> > - u8 jitter_filter_type:2;
> > - u8 reserved:1;
> > -} __attribute__((__packed__));
> > -
> > -/** This register is present if query 12's has_general_info2 flag is set.
> > + *
> > + * Query 14 is present if query 12's has_general_info2 flag is set.
> > *
> > * @light_control - Indicates what light/led control features are present, if
> > * any.
> > @@ -316,422 +314,174 @@ struct f11_2d_query13 {
> > * @mouse_buttons - specifies the number of mouse buttons present (if any).
> > * @has_advanced_gestures - advanced driver gestures are supported.
> > */
> > -struct f11_2d_query14 {
> > - u8 light_control:2;
> > - u8 is_clear:1;
> > - u8 clickpad_props:2;
> > - u8 mouse_buttons:2;
> > - u8 has_advanced_gestures:1;
> > -} __attribute__((__packed__));
> > -
> > -#define F11_LIGHT_CTL_NONE 0x00
> > -#define F11_LUXPAD 0x01
> > -#define F11_DUAL_MODE 0x02
> > -
> > -#define F11_NOT_CLICKPAD 0x00
> > -#define F11_HINGED_CLICKPAD 0x01
> > -#define F11_UNIFORM_CLICKPAD 0x02
> > -
> > -/** See notes above for information about specific query register sets.
> > - */
> > struct f11_2d_sensor_queries {
> > - struct f11_2d_sensor_info info;
> > - struct f11_2d_abs_info abs_info;
> > - u8 f11_2d_query6;
> > - struct f11_2d_gesture_info gesture_info;
> > - struct f11_2d_query9 query9;
> > - struct f11_2d_ts_info ts_info;
> > - struct f11_2d_query11 features_1;
> > - struct f11_2d_query12 features_2;
> > - struct f11_2d_query13 jitter_filter;
> > - struct f11_2d_query14 info_2;
> > -};
> > -
> > -/**
> > - * @reporting_mode - controls how often finger position data is reported.
> > - * @abs_pos_filt - when set, enables various noise and jitter filtering
> > - * algorithms for absolute reports.
> > - * @rel_pos_filt - when set, enables various noise and jitter filtering
> > - * algorithms for relative reports.
> > - * @rel_ballistics - enables ballistics processing for the relative finger
> > - * motion on the 2-D sensor.
> > - * @dribble - enables the dribbling feature.
> > - * @report_beyond_clip - when this is set, fingers outside the active area
> > - * specified by the x_clip and y_clip registers will be reported, but with
> > - * reported finger position clipped to the edge of the active area.
> > - * @palm_detect_thresh - the threshold at which a wide finger is considered a
> > - * palm. A value of 0 inhibits palm detection.
> > - * @motion_sensitivity - specifies the threshold an anchored finger must move
> > - * before it is considered no longer anchored. High values mean more
> > - * sensitivity.
> > - * @man_track_en - for anchored finger tracking, whether the host (1) or the
> > - * device (0) determines which finger is the tracked finger.
> > - * @man_tracked_finger - when man_track_en is 1, specifies whether finger 0 or
> > - * finger 1 is the tracked finger.
> > - * @delta_x_threshold - 2-D position update interrupts are inhibited unless
> > - * the finger moves more than a certain threshold distance along the X axis.
> > - * @delta_y_threshold - 2-D position update interrupts are inhibited unless
> > - * the finger moves more than a certain threshold distance along the Y axis.
> > - * @velocity - When rel_ballistics is set, this register defines the
> > - * velocity ballistic parameter applied to all relative motion events.
> > - * @acceleration - When rel_ballistics is set, this register defines the
> > - * acceleration ballistic parameter applied to all relative motion events.
> > - * @sensor_max_x_pos - the maximum X coordinate reported by the sensor.
> > - * @sensor_max_y_pos - the maximum Y coordinate reported by the sensor.
> > - */
> > -struct f11_2d_ctrl0_9 {
> > - /* F11_2D_Ctrl0 */
> > - u8 reporting_mode:3;
> > - u8 abs_pos_filt:1;
> > - u8 rel_pos_filt:1;
> > - u8 rel_ballistics:1;
> > - u8 dribble:1;
> > - u8 report_beyond_clip:1;
> > - /* F11_2D_Ctrl1 */
> > - u8 palm_detect_thres:4;
> > - u8 motion_sensitivity:2;
> > - u8 man_track_en:1;
> > - u8 man_tracked_finger:1;
> > - /* F11_2D_Ctrl2 and 3 */
> > - u8 delta_x_threshold:8;
> > - u8 delta_y_threshold:8;
> > - /* F11_2D_Ctrl4 and 5 */
> > - u8 velocity:8;
> > - u8 acceleration:8;
> > - /* F11_2D_Ctrl6 thru 9 */
> > - u16 sensor_max_x_pos:12;
> > - u8 ctrl7_reserved:4;
> > - u16 sensor_max_y_pos:12;
> > - u8 ctrl9_reserved:4;
> > -} __attribute__((__packed__));
> > -
> > -/**
> > - * @single_tap_int_enable - enable tap gesture recognition.
> > - * @tap_n_hold_int_enable - enable tap-and-hold gesture recognition.
> > - * @double_tap_int_enable - enable double-tap gesture recognition.
> > - * @early_tap_int_enable - enable early tap notification.
> > - * @flick_int_enable - enable flick detection.
> > - * @press_int_enable - enable press gesture recognition.
> > - * @pinch_int_enable - enable pinch detection.
> > - */
> > -struct f11_2d_ctrl10 {
> > - u8 single_tap_int_enable:1;
> > - u8 tap_n_hold_int_enable:1;
> > - u8 double_tap_int_enable:1;
> > - u8 early_tap_int_enable:1;
> > - u8 flick_int_enable:1;
> > - u8 press_int_enable:1;
> > - u8 pinch_int_enable:1;
> > - u8 reserved:1;
> > -} __attribute__((__packed__));
> > -
> > -/**
> > - * @palm_detect_int_enable - enable palm detection feature.
> > - * @rotate_int_enable - enable rotate gesture detection.
> > - * @touch_shape_int_enable - enable the TouchShape feature.
> > - * @scroll_zone_int_enable - enable scroll zone reporting.
> > - * @multi_finger_scroll_int_enable - enable the multfinger scroll feature.
> > - */
> > -struct f11_2d_ctrl11 {
> > - u8 palm_detect_int_enable:1;
> > - u8 rotate_int_enable:1;
> > - u8 touch_shape_int_enable:1;
> > - u8 scroll_zone_int_enable:1;
> > - u8 multi_finger_scroll_int_enable:1;
> > - u8 reserved:3;
> > -} __attribute__((__packed__));
> > -
> > -/**
> > - * @sens_adjustment - allows a host to alter the overall sensitivity of a
> > - * 2-D sensor. A positive value in this register will make the sensor more
> > - * sensitive than the factory defaults, and a negative value will make it
> > - * less sensitive.
> > - * @hyst_adjustment - increase the touch/no-touch hysteresis by 2 Z-units for
> > - * each one unit increment in this setting.
> > - */
> > -struct f11_2d_ctrl14 {
> > - s8 sens_adjustment:5;
> > - u8 hyst_adjustment:3;
> > -} __attribute__((__packed__));
> > -
> > -/**
> > - * @max_tap_time - the maximum duration of a tap, in 10-millisecond units.
> > - */
> > -struct f11_2d_ctrl15 {
> > - u8 max_tap_time:8;
> > -} __attribute__((__packed__));
> > -
> > -/**
> > - * @min_press_time - The minimum duration required for stationary finger(s) to
> > - * generate a press gesture, in 10-millisecond units.
> > - */
> > -struct f11_2d_ctrl16 {
> > - u8 min_press_time:8;
> > -} __attribute__((__packed__));
> > + /* query1 */
> > + u8 nr_fingers;
> > + bool has_rel;
> > + bool has_abs;
> > + bool has_gestures;
> > + bool has_sensitivity_adjust;
> > + bool configurable;
> >
> > -/**
> > - * @max_tap_distance - Determines the maximum finger movement allowed during
> > - * a tap, in 0.1-millimeter units.
> > - */
> > -struct f11_2d_ctrl17 {
> > - u8 max_tap_distance:8;
> > -} __attribute__((__packed__));
> > + /* query2 */
> > + u8 nr_x_electrodes;
> >
> > -/**
> > - * @min_flick_distance - the minimum finger movement for a flick gesture,
> > - * in 1-millimeter units.
> > - * @min_flick_speed - the minimum finger speed for a flick gesture, in
> > - * 10-millimeter/second units.
> > - */
> > -struct f11_2d_ctrl18_19 {
> > - u8 min_flick_distance:8;
> > - u8 min_flick_speed:8;
> > -} __attribute__((__packed__));
> > + /* query3 */
> > + u8 nr_y_electrodes;
> >
> > -/**
> > - * @pen_detect_enable - enable reporting of stylus activity.
> > - * @pen_jitter_filter_enable - Setting this enables the stylus anti-jitter
> > - * filter.
> > - * @pen_z_threshold - This is the stylus-detection lower threshold. Smaller
> > - * values result in higher sensitivity.
> > - */
> > -struct f11_2d_ctrl20_21 {
> > - u8 pen_detect_enable:1;
> > - u8 pen_jitter_filter_enable:1;
> > - u8 ctrl20_reserved:6;
> > - u8 pen_z_threshold:8;
> > -} __attribute__((__packed__));
> > + /* query4 */
> > + u8 max_electrodes;
> >
> > -/**
> > - * These are not accessible through sysfs yet.
> > - *
> > - * @proximity_detect_int_en - enable proximity detection feature.
> > - * @proximity_jitter_filter_en - enables an anti-jitter filter on proximity
> > - * data.
> > - * @proximity_detection_z_threshold - the threshold for finger-proximity
> > - * detection.
> > - * @proximity_delta_x_threshold - In reduced-reporting modes, this is the
> > - * threshold for proximate-finger movement in the direction parallel to the
> > - * X-axis.
> > - * @proximity_delta_y_threshold - In reduced-reporting modes, this is the
> > - * threshold for proximate-finger movement in the direction parallel to the
> > - * Y-axis.
> > - * * @proximity_delta_Z_threshold - In reduced-reporting modes, this is the
> > - * threshold for proximate-finger movement in the direction parallel to the
> > - * Z-axis.
> > - */
> > -struct f11_2d_ctrl22_26 {
> > - /* control 22 */
> > - u8 proximity_detect_int_en:1;
> > - u8 proximity_jitter_filter_en:1;
> > - u8 f11_2d_ctrl6_b3__7:6;
> > + /* query5 */
> > + u8 abs_data_size;
> > + bool has_anchored_finger;
> > + bool has_adj_hyst;
> > + bool has_dribble;
> > + bool has_bending_correction;
> > + bool has_large_object_suppression;
> > + bool has_jitter_filter;
> >
> > - /* control 23 */
> > - u8 proximity_detection_z_threshold;
> > + u8 f11_2d_query6;
> >
> > - /* control 24 */
> > - u8 proximity_delta_x_threshold;
> > + /* query 7 */
> > + bool has_single_tap;
> > + bool has_tap_n_hold;
> > + bool has_double_tap;
> > + bool has_early_tap;
> > + bool has_flick;
> > + bool has_press;
> > + bool has_pinch;
> > + bool has_chiral;
> > +
> > + bool query7_nonzero;
> > +
> > + /* query 8 */
> > + bool has_palm_det;
> > + bool has_rotate;
> > + bool has_touch_shapes;
> > + bool has_scroll_zones;
> > + bool has_individual_scroll_zones;
> > + bool has_mf_scroll;
> > + bool has_mf_edge_motion;
> > + bool has_mf_scroll_inertia;
> > +
> > + bool query8_nonzero;
> > +
> > + /* Query 9 */
> > + bool has_pen;
> > + bool has_proximity;
> > + bool has_palm_det_sensitivity;
> > + bool has_suppress_on_palm_detect;
> > + bool has_two_pen_thresholds;
> > + bool has_contact_geometry;
> > + bool has_pen_hover_discrimination;
> > + bool has_pen_filters;
> > +
> > + /* Query 10 */
> > + u8 nr_touch_shapes;
> > +
> > + /* Query 11. */
> > + bool has_z_tuning;
> > + bool has_algorithm_selection;
> > + bool has_w_tuning;
> > + bool has_pitch_info;
> > + bool has_finger_size;
> > + bool has_segmentation_aggressiveness;
> > + bool has_XY_clip;
> > + bool has_drumming_filter;
> > +
> > + /* Query 12 */
> > + bool has_gapless_finger;
> > + bool has_gapless_finger_tuning;
> > + bool has_8bit_w;
> > + bool has_adjustable_mapping;
> > + bool has_info2;
> > + bool has_physical_props;
> > + bool has_finger_limit;
> > + bool has_linear_coeff_2;
> > +
> > + /* Query 13 */
> > + u8 jitter_window_size;
> > + u8 jitter_filter_type;
> > +
> > + /* Query 14 */
> > + u8 light_control;
> > + bool is_clear;
> > + u8 clickpad_props;
> > + u8 mouse_buttons;
> > + bool has_advanced_gestures;
> > +};
> >
> > - /* control 25 */
> > - u8 proximity_delta_y_threshold;
> > +/* Defs for Ctrl0. */
> > +#define RMI_F11_REPORT_MODE_MASK 0x07
> > +#define RMI_F11_ABS_POS_FILT (1 << 3)
> > +#define RMI_F11_REL_POS_FILT (1 << 4)
> > +#define RMI_F11_REL_BALLISTICS (1 << 5)
> > +#define RMI_F11_DRIBBLE (1 << 6)
> > +#define RMI_F11_REPORT_BEYOND_CLIP (1 << 7)
> >
> > - /* control 26 */
> > - u8 proximity_delta_z_threshold;
> > -} __attribute__((__packed__));
> > +/* Defs for Ctrl1. */
> > +#define RMI_F11_PALM_DETECT_THRESH_MASK 0x0F
> > +#define RMI_F11_MOTION_SENSITIVITY_MASK 0x30
> > +#define RMI_F11_MANUAL_TRACKING (1 << 6)
> > +#define RMI_F11_MANUAL_TRACKED_FINGER (1 << 7)
> >
> > -/**
> > - * @palm_detecy_sensitivity - When this value is small, smaller objects will
> > - * be identified as palms; when this value is large, only larger objects will
> > - * be identified as palms. 0 represents the factory default.
> > - * @suppress_on_palm_detect - when set, all F11 interrupts except palm_detect
> > - * are suppressed while a palm is detected.
> > - */
> > -struct f11_2d_ctrl27 {
> > - s8 palm_detect_sensitivity:4;
> > - u8 suppress_on_palm_detect:1;
> > - u8 f11_2d_ctrl27_b5__7:3;
> > -} __attribute__((__packed__));
> > -
> > -/**
> > - * @multi_finger_scroll_mode - allows choice of multi-finger scroll mode and
> > - * determines whether and how X or Y displacements are reported.
> > - * @edge_motion_en - enables the edge_motion feature.
> > - * @multi_finger_scroll_momentum - controls the length of time that scrolling
> > - * continues after fingers have been lifted.
> > - */
> > -struct f11_2d_ctrl28 {
> > - u8 multi_finger_scroll_mode:2;
> > - u8 edge_motion_en:1;
> > - u8 f11_2d_ctrl28b_3:1;
> > - u8 multi_finger_scroll_momentum:4;
> > -} __attribute__((__packed__));
> > -
> > -/**
> > - * @z_touch_threshold - Specifies the finger-arrival Z threshold. Large values
> > - * may cause smaller fingers to be rejected.
> > - * @z_touch_hysteresis - Specifies the difference between the finger-arrival
> > - * Z threshold and the finger-departure Z threshold.
> > - */
> > -struct f11_2d_ctrl29_30 {
> > - u8 z_touch_threshold;
> > - u8 z_touch_hysteresis;
> > -} __attribute__((__packed__));
> > +#define RMI_F11_DELTA_X_THRESHOLD 2
> > +#define RMI_F11_DELTA_Y_THRESHOLD 3
> >
> > +#define RMI_F11_CTRL_REG_COUNT 10
> >
> > struct f11_2d_ctrl {
> > - struct f11_2d_ctrl0_9 *ctrl0_9;
> > - u16 ctrl0_9_address;
> > - struct f11_2d_ctrl10 *ctrl10;
> > - struct f11_2d_ctrl11 *ctrl11;
> > - u8 ctrl12_size;
> > - struct f11_2d_ctrl14 *ctrl14;
> > - struct f11_2d_ctrl15 *ctrl15;
> > - struct f11_2d_ctrl16 *ctrl16;
> > - struct f11_2d_ctrl17 *ctrl17;
> > - struct f11_2d_ctrl18_19 *ctrl18_19;
> > - struct f11_2d_ctrl20_21 *ctrl20_21;
> > - struct f11_2d_ctrl22_26 *ctrl22_26;
> > - struct f11_2d_ctrl27 *ctrl27;
> > - struct f11_2d_ctrl28 *ctrl28;
> > - struct f11_2d_ctrl29_30 *ctrl29_30;
> > + u8 ctrl0_9[RMI_F11_CTRL_REG_COUNT];
> > + u16 ctrl0_9_address;
> > };
> >
> > -/**
> > - * @x_msb - top 8 bits of X finger position.
> > - * @y_msb - top 8 bits of Y finger position.
> > - * @x_lsb - bottom 4 bits of X finger position.
> > - * @y_lsb - bottom 4 bits of Y finger position.
> > - * @w_y - contact patch width along Y axis.
> > - * @w_x - contact patch width along X axis.
> > - * @z - finger Z value (proxy for pressure).
> > - */
> > -struct f11_2d_data_1_5 {
> > - u8 x_msb;
> > - u8 y_msb;
> > - u8 x_lsb:4;
> > - u8 y_lsb:4;
> > - u8 w_y:4;
> > - u8 w_x:4;
> > - u8 z;
> > -} __attribute__((__packed__));
> > -
> > -/**
> > - * @delta_x - relative motion along X axis.
> > - * @delta_y - relative motion along Y axis.
> > - */
> > -struct f11_2d_data_6_7 {
> > - s8 delta_x;
> > - s8 delta_y;
> > -} __attribute__((__packed__));
> > -
> > -/**
> > - * @single_tap - a single tap was recognized.
> > - * @tap_and_hold - a tap-and-hold gesture was recognized.
> > - * @double_tap - a double tap gesture was recognized.
> > - * @early_tap - a tap gesture might be happening.
> > - * @flick - a flick gesture was detected.
> > - * @press - a press gesture was recognized.
> > - * @pinch - a pinch gesture was detected.
> > - */
> > -struct f11_2d_data_8 {
> > - bool single_tap:1;
> > - bool tap_and_hold:1;
> > - bool double_tap:1;
> > - bool early_tap:1;
> > - bool flick:1;
> > - bool press:1;
> > - bool pinch:1;
> > -} __attribute__((__packed__));
> > -
> > -/**
> > - * @palm_detect - a palm or other large object is in contact with the sensor.
> > - * @rotate - a rotate gesture was detected.
> > - * @shape - a TouchShape has been activated.
> > - * @scrollzone - scrolling data is available.
> > - * @finger_count - number of fingers involved in the reported gesture.
> > - */
> > -struct f11_2d_data_9 {
> > - bool palm_detect:1;
> > - bool rotate:1;
> > - bool shape:1;
> > - bool scrollzone:1;
> > - u8 finger_count:3;
> > -} __attribute__((__packed__));
> > -
> > -/**
> > - * @pinch_motion - when a pinch gesture is detected, this is the change in
> > - * distance between the two fingers since this register was last read.
> > - */
> > -struct f11_2d_data_10 {
> > - s8 pinch_motion;
> > -} __attribute__((__packed__));
> > +#define RMI_F11_ABS_BYTES 5
> > +#define RMI_F11_REL_BYTES 2
> >
> > -/**
> > - * @x_flick_dist - when a flick gesture is detected, the distance of flick
> > - * gesture in X direction.
> > - * @y_flick_dist - when a flick gesture is detected, the distance of flick
> > - * gesture in Y direction.
> > - * @flick_time - the total time of the flick gesture, in 10ms units.
> > - */
> > -struct f11_2d_data_10_12 {
> > - s8 x_flick_dist;
> > - s8 y_flick_dist;
> > - u8 flick_time;
> > -} __attribute__((__packed__));
> > +/* Defs for Data 8 */
> >
> > -/**
> > - * @motion - when a rotate gesture is detected, the accumulated distance
> > - * of the rotate motion. Clockwise motion is positive and counterclockwise
> > - * motion is negative.
> > - * @finger_separation - when a rotate gesture is detected, the distance
> > - * between the fingers.
> > - */
> > -struct f11_2d_data_11_12 {
> > - s8 motion;
> > - u8 finger_separation;
> > -} __attribute__((__packed__));
> > +#define RMI_F11_SINGLE_TAP (1 << 0)
> > +#define RMI_F11_TAP_AND_HOLD (1 << 1)
> > +#define RMI_F11_DOUBLE_TAP (1 << 2)
> > +#define RMI_F11_EARLY_TAP (1 << 3)
> > +#define RMI_F11_FLICK (1 << 4)
> > +#define RMI_F11_PRESS (1 << 5)
> > +#define RMI_F11_PINCH (1 << 6)
> >
> > -/**
> > - * @shape_n - a bitmask of the currently activate TouchShapes (if any).
> > - */
> > -struct f11_2d_data_13 {
> > - u8 shape_n;
> > -} __attribute__((__packed__));
> > +/* Defs for Data 9 */
> >
> > -/**
> > - * @horizontal - chiral scrolling distance in the X direction.
> > - * @vertical - chiral scrolling distance in the Y direction.
> > - */
> > -struct f11_2d_data_14_15 {
> > - s8 horizontal;
> > - s8 vertical;
> > -} __attribute__((__packed__));
> > +#define RMI_F11_PALM_DETECT (1 << 0)
> > +#define RMI_F11_ROTATE (1 << 1)
> > +#define RMI_F11_SHAPE (1 << 2)
> > +#define RMI_F11_SCROLLZONE (1 << 3)
> > +#define RMI_F11_GESTURE_FINGER_COUNT_MASK 0x70
> >
> > -/**
> > - * @x_low - scroll zone motion along the lower edge of the sensor.
> > - * @y_right - scroll zone motion along the right edge of the sensor.
> > - * @x_upper - scroll zone motion along the upper edge of the sensor.
> > - * @y_left - scroll zone motion along the left edge of the sensor.
> > +/** Handy pointers into our data buffer.
> > + *
> > + * @f_state - start of finger state registers.
> > + * @abs_pos - start of absolute position registers (if present).
> > + * @rel_pos - start of relative data registers (if present).
> > + * @gest_1 - gesture flags (if present).
> > + * @gest_2 - gesture flags & finger count (if present).
> > + * @pinch - pinch motion register (if present).
> > + * @flick - flick distance X & Y, flick time (if present).
> > + * @rotate - rotate motion and finger separation.
> > + * @multi_scroll - chiral deltas for X and Y (if present).
> > + * @scroll_zones - scroll deltas for 4 regions (if present).
> > */
> > -struct f11_2d_data_14_17 {
> > - s8 x_low;
> > - s8 y_right;
> > - s8 x_upper;
> > - s8 y_left;
> > -} __attribute__((__packed__));
> > -
> > struct f11_2d_data {
> > - u8 *f_state;
> > - const struct f11_2d_data_1_5 *abs_pos;
> > - const struct f11_2d_data_6_7 *rel_pos;
> > - const struct f11_2d_data_8 *gest_1;
> > - const struct f11_2d_data_9 *gest_2;
> > - const struct f11_2d_data_10 *pinch;
> > - const struct f11_2d_data_10_12 *flick;
> > - const struct f11_2d_data_11_12 *rotate;
> > - const struct f11_2d_data_13 *shapes;
> > - const struct f11_2d_data_14_15 *multi_scroll;
> > - const struct f11_2d_data_14_17 *scroll_zones;
> > + u8 *f_state;
> > + u8 *abs_pos;
> > + s8 *rel_pos;
> > + u8 *gest_1;
> > + u8 *gest_2;
> > + s8 *pinch;
> > + u8 *flick;
> > + u8 *rotate;
> > + u8 *shapes;
> > + s8 *multi_scroll;
> > + s8 *scroll_zones;
> > };
> >
> > /**
> > @@ -785,11 +535,13 @@ struct f11_2d_sensor {
> > * poor electrical behavior on resume, where the initial calibration of the
> > * sensor(s) coming out of sleep state may be bogus.
> > * @sensors - per sensor data structures.
> > - * @debugfs_rezero_wait - allows control of the rezero_wait value. Useful
> > - * during system prototyping.
> > */
> > struct f11_data {
> > - struct f11_2d_device_query dev_query;
> > + bool has_query9;
> > + bool has_query11;
> > + bool has_query12;
> > + bool has_query27;
> > + bool has_query28;
> > struct f11_2d_ctrl dev_controls;
> > struct mutex dev_controls_mutex;
> > u16 rezero_wait_ms;
> > @@ -809,7 +561,7 @@ enum finger_state_values {
> > static int get_tool_type(struct f11_2d_sensor *sensor, u8 finger_state)
> > {
> > if (IS_ENABLED(CONFIG_RMI4_F11_PEN) &&
> > - sensor->sens_query.query9.has_pen &&
> > + sensor->sens_query.has_pen &&
> > finger_state == F11_PEN)
> > return MT_TOOL_PEN;
> > return MT_TOOL_FINGER;
> > @@ -822,8 +574,8 @@ static void rmi_f11_rel_pos_report(struct f11_2d_sensor *sensor, u8 n_finger)
> > s8 x, y;
> > s8 temp;
> >
> > - x = data->rel_pos[n_finger].delta_x;
> > - y = data->rel_pos[n_finger].delta_y;
> > + x = data->rel_pos[n_finger * 2];
> > + y = data->rel_pos[n_finger * 2 + 1];
> >
> > x = min(F11_REL_POS_MAX, max(F11_REL_POS_MIN, (int)x));
> > y = min(F11_REL_POS_MAX, max(F11_REL_POS_MIN, (int)y));
> > @@ -856,17 +608,18 @@ static void rmi_f11_abs_pos_report(struct f11_data *f11,
> > u16 x, y, z;
> > int w_x, w_y, w_max, w_min, orient;
> > int temp;
> > + u8 abs_base = n_finger * RMI_F11_ABS_BYTES;
> >
> > if (finger_state) {
> > - x = ((data->abs_pos[n_finger].x_msb << 4) |
> > - data->abs_pos[n_finger].x_lsb);
> > - y = ((data->abs_pos[n_finger].y_msb << 4) |
> > - data->abs_pos[n_finger].y_lsb);
> > - z = data->abs_pos[n_finger].z;
> > - w_x = data->abs_pos[n_finger].w_x;
> > - w_y = data->abs_pos[n_finger].w_y;
> > + x = (data->abs_pos[abs_base] << 4) |
> > + (data->abs_pos[abs_base + 2] & 0x0F);
> > + y = (data->abs_pos[abs_base + 1] << 4) |
> > + (data->abs_pos[abs_base + 2] >> 4);
> > + w_x = data->abs_pos[abs_base + 3] & 0x0F;
> > + w_y = data->abs_pos[abs_base + 3] >> 4;
> > w_max = max(w_x, w_y);
> > w_min = min(w_x, w_y);
> > + z = data->abs_pos[abs_base + 4];
> >
> > if (axis_align->swap_axes) {
> > temp = x;
> > @@ -976,38 +729,36 @@ static int f11_2d_construct_data(struct f11_2d_sensor *sensor)
> > struct f11_2d_data *data = &sensor->data;
> > int i;
> >
> > - sensor->nbr_fingers = (query->info.number_of_fingers == 5 ? 10 :
> > - query->info.number_of_fingers + 1);
> > + sensor->nbr_fingers = (query->nr_fingers == 5 ? 10 :
> > + query->nr_fingers + 1);
> >
> > sensor->pkt_size = DIV_ROUND_UP(sensor->nbr_fingers, 4);
> >
> > - if (query->info.has_abs)
> > + if (query->has_abs)
> > sensor->pkt_size += (sensor->nbr_fingers * 5);
> >
> > - if (query->info.has_rel)
> > + if (query->has_rel)
> > sensor->pkt_size += (sensor->nbr_fingers * 2);
> >
> > /* Check if F11_2D_Query7 is non-zero */
> > - if (has_gesture_bits(&query->gesture_info, 0))
> > + if (query->query7_nonzero)
> > sensor->pkt_size += sizeof(u8);
> >
> > /* Check if F11_2D_Query7 or F11_2D_Query8 is non-zero */
> > - if (has_gesture_bits(&query->gesture_info, 0) ||
> > - has_gesture_bits(&query->gesture_info, 1))
> > + if (query->query7_nonzero || query->query8_nonzero)
> > sensor->pkt_size += sizeof(u8);
> >
> > - if (query->gesture_info.has_pinch || query->gesture_info.has_flick
> > - || query->gesture_info.has_rotate) {
> > + if (query->has_pinch || query->has_flick || query->has_rotate) {
> > sensor->pkt_size += 3;
> > - if (!query->gesture_info.has_flick)
> > + if (!query->has_flick)
> > sensor->pkt_size--;
> > - if (!query->gesture_info.has_rotate)
> > + if (!query->has_rotate)
> > sensor->pkt_size--;
> > }
> >
> > - if (query->gesture_info.has_touch_shapes)
> > + if (query->has_touch_shapes)
> > sensor->pkt_size +=
> > - DIV_ROUND_UP(query->ts_info.nbr_touch_shapes + 1, 8);
> > + DIV_ROUND_UP(query->nr_touch_shapes + 1, 8);
> >
> > sensor->data_pkt = kzalloc(sensor->pkt_size, GFP_KERNEL);
> > if (!sensor->data_pkt)
> > @@ -1016,58 +767,52 @@ static int f11_2d_construct_data(struct f11_2d_sensor *sensor)
> > data->f_state = sensor->data_pkt;
> > i = DIV_ROUND_UP(sensor->nbr_fingers, 4);
> >
> > - if (query->info.has_abs) {
> > - data->abs_pos = (struct f11_2d_data_1_5 *)
> > - &sensor->data_pkt[i];
> > - i += (sensor->nbr_fingers * 5);
> > + if (query->has_abs) {
> > + data->abs_pos = &sensor->data_pkt[i];
> > + i += (sensor->nbr_fingers * RMI_F11_ABS_BYTES);
> > }
> >
> > - if (query->info.has_rel) {
> > - data->rel_pos = (struct f11_2d_data_6_7 *)
> > - &sensor->data_pkt[i];
> > - i += (sensor->nbr_fingers * 2);
> > + if (query->has_rel) {
> > + data->rel_pos = &sensor->data_pkt[i];
> > + i += (sensor->nbr_fingers * RMI_F11_REL_BYTES);
> > }
> >
> > - if (has_gesture_bits(&query->gesture_info, 0)) {
> > - data->gest_1 = (struct f11_2d_data_8 *)&sensor->data_pkt[i];
> > + if (query->query7_nonzero) {
> > + data->gest_1 = &sensor->data_pkt[i];
> > i++;
> > }
> >
> > - if (has_gesture_bits(&query->gesture_info, 0) ||
> > - has_gesture_bits(&query->gesture_info, 1)) {
> > - data->gest_2 = (struct f11_2d_data_9 *)&sensor->data_pkt[i];
> > + if (query->query7_nonzero || query->query8_nonzero) {
> > + data->gest_2 = &sensor->data_pkt[i];
> > i++;
> > }
> >
> > - if (query->gesture_info.has_pinch) {
> > - data->pinch = (struct f11_2d_data_10 *)&sensor->data_pkt[i];
> > + if (query->has_pinch) {
> > + data->pinch = &sensor->data_pkt[i];
> > i++;
> > }
> >
> > - if (query->gesture_info.has_flick) {
> > - if (query->gesture_info.has_pinch) {
> > - data->flick = (struct f11_2d_data_10_12 *)data->pinch;
> > + if (query->has_flick) {
> > + if (query->has_pinch) {
> > + data->flick = data->pinch;
> > i += 2;
> > } else {
> > - data->flick = (struct f11_2d_data_10_12 *)
> > - &sensor->data_pkt[i];
> > + data->flick = &sensor->data_pkt[i];
> > i += 3;
> > }
> > }
> >
> > - if (query->gesture_info.has_rotate) {
> > - if (query->gesture_info.has_flick) {
> > - data->rotate = (struct f11_2d_data_11_12 *)
> > - (data->flick + 1);
> > + if (query->has_rotate) {
> > + if (query->has_flick) {
> > + data->rotate = data->flick + 1;
> > } else {
> > - data->rotate = (struct f11_2d_data_11_12 *)
> > - &sensor->data_pkt[i];
> > + data->rotate = &sensor->data_pkt[i];
> > i += 2;
> > }
> > }
> >
> > - if (query->gesture_info.has_touch_shapes)
> > - data->shapes = (struct f11_2d_data_13 *)&sensor->data_pkt[i];
> > + if (query->has_touch_shapes)
> > + data->shapes = &sensor->data_pkt[i];
> >
> > return 0;
> > }
> > @@ -1075,213 +820,16 @@ static int f11_2d_construct_data(struct f11_2d_sensor *sensor)
> > static int f11_read_control_regs(struct rmi_function *fn,
> > struct f11_2d_ctrl *ctrl, u16 ctrl_base_addr) {
> > struct rmi_device *rmi_dev = fn->rmi_dev;
> > - u16 read_address = ctrl_base_addr;
> > int error = 0;
> >
> > - ctrl->ctrl0_9_address = read_address;
> > - error = rmi_read_block(rmi_dev, read_address, ctrl->ctrl0_9,
> > - sizeof(*ctrl->ctrl0_9));
> > + ctrl->ctrl0_9_address = ctrl_base_addr;
> > + error = rmi_read_block(rmi_dev, ctrl_base_addr, ctrl->ctrl0_9,
> > + RMI_F11_CTRL_REG_COUNT);
> > if (error < 0) {
> > dev_err(&fn->dev, "Failed to read ctrl0, code: %d.\n", error);
> > return error;
> > }
> > - read_address += sizeof(*ctrl->ctrl0_9);
> >
> > - if (ctrl->ctrl10) {
> > - error = rmi_read_block(rmi_dev, read_address,
> > - ctrl->ctrl10, sizeof(*ctrl->ctrl10));
> > - if (error < 0) {
> > - dev_err(&fn->dev,
> > - "Failed to read ctrl10, code: %d.\n", error);
> > - return error;
> > - }
> > - read_address += sizeof(*ctrl->ctrl10);
> > - }
> > -
> > - if (ctrl->ctrl11) {
> > - error = rmi_read_block(rmi_dev, read_address,
> > - ctrl->ctrl11, sizeof(*ctrl->ctrl11));
> > - if (error < 0) {
> > - dev_err(&fn->dev,
> > - "Failed to read ctrl11, code: %d.\n", error);
> > - return error;
> > - }
> > - read_address += sizeof(*ctrl->ctrl11);
> > - }
> > -
> > - if (ctrl->ctrl14) {
> > - error = rmi_read_block(rmi_dev, read_address,
> > - ctrl->ctrl14, sizeof(*ctrl->ctrl14));
> > - if (error < 0) {
> > - dev_err(&fn->dev,
> > - "Failed to read ctrl14, code: %d.\n", error);
> > - return error;
> > - }
> > - read_address += sizeof(*ctrl->ctrl14);
> > - }
> > -
> > - if (ctrl->ctrl15) {
> > - error = rmi_read_block(rmi_dev, read_address,
> > - ctrl->ctrl15, sizeof(*ctrl->ctrl15));
> > - if (error < 0) {
> > - dev_err(&fn->dev,
> > - "Failed to read ctrl15, code: %d.\n", error);
> > - return error;
> > - }
> > - read_address += sizeof(*ctrl->ctrl15);
> > - }
> > -
> > - if (ctrl->ctrl16) {
> > - error = rmi_read_block(rmi_dev, read_address,
> > - ctrl->ctrl16, sizeof(*ctrl->ctrl16));
> > - if (error < 0) {
> > - dev_err(&fn->dev,
> > - "Failed to read ctrl16, code: %d.\n", error);
> > - return error;
> > - }
> > - read_address += sizeof(*ctrl->ctrl16);
> > - }
> > -
> > - if (ctrl->ctrl17) {
> > - error = rmi_read_block(rmi_dev, read_address,
> > - ctrl->ctrl17, sizeof(*ctrl->ctrl17));
> > - if (error < 0) {
> > - dev_err(&fn->dev,
> > - "Failed to read ctrl17, code: %d.\n", error);
> > - return error;
> > - }
> > - read_address += sizeof(*ctrl->ctrl17);
> > - }
> > -
> > - if (ctrl->ctrl18_19) {
> > - error = rmi_read_block(rmi_dev, read_address,
> > - ctrl->ctrl18_19, sizeof(*ctrl->ctrl18_19));
> > - if (error < 0) {
> > - dev_err(&fn->dev,
> > - "Failed to read ctrl18_19, code: %d.\n", error);
> > - return error;
> > - }
> > - read_address += sizeof(*ctrl->ctrl18_19);
> > - }
> > -
> > - if (ctrl->ctrl20_21) {
> > - error = rmi_read_block(rmi_dev, read_address,
> > - ctrl->ctrl20_21, sizeof(*ctrl->ctrl20_21));
> > - if (error < 0) {
> > - dev_err(&fn->dev,
> > - "Failed to read ctrl20_21, code: %d.\n", error);
> > - return error;
> > - }
> > - read_address += sizeof(*ctrl->ctrl20_21);
> > - }
> > -
> > - if (ctrl->ctrl22_26) {
> > - error = rmi_read_block(rmi_dev, read_address,
> > - ctrl->ctrl22_26, sizeof(*ctrl->ctrl22_26));
> > - if (error < 0) {
> > - dev_err(&fn->dev,
> > - "Failed to read ctrl22_26, code: %d.\n", error);
> > - return error;
> > - }
> > - read_address += sizeof(*ctrl->ctrl22_26);
> > - }
> > -
> > - if (ctrl->ctrl27) {
> > - error = rmi_read_block(rmi_dev, read_address,
> > - ctrl->ctrl27, sizeof(*ctrl->ctrl27));
> > - if (error < 0) {
> > - dev_err(&fn->dev,
> > - "Failed to read ctrl27, code: %d.\n", error);
> > - return error;
> > - }
> > - read_address += sizeof(*ctrl->ctrl27);
> > - }
> > -
> > - if (ctrl->ctrl28) {
> > - error = rmi_read_block(rmi_dev, read_address,
> > - ctrl->ctrl28, sizeof(*ctrl->ctrl28));
> > - if (error < 0) {
> > - dev_err(&fn->dev,
> > - "Failed to read ctrl28, code: %d.\n", error);
> > - return error;
> > - }
> > - read_address += sizeof(*ctrl->ctrl28);
> > - }
> > -
> > - if (ctrl->ctrl29_30) {
> > - error = rmi_read_block(rmi_dev, read_address,
> > - ctrl->ctrl29_30, sizeof(*ctrl->ctrl29_30));
> > - if (error < 0) {
> > - dev_err(&fn->dev,
> > - "Failed to read ctrl29_30, code: %d.\n", error);
> > - return error;
> > - }
> > - read_address += sizeof(*ctrl->ctrl29_30);
> > - }
> > - return 0;
> > -}
> > -
> > -static int f11_allocate_control_regs(struct rmi_function *fn,
> > - struct f11_2d_device_query *device_query,
> > - struct f11_2d_sensor_queries *sensor_query,
> > - struct f11_2d_ctrl *ctrl,
> > - u16 ctrl_base_addr) {
> > -
> > - ctrl->ctrl0_9 = devm_kzalloc(&fn->dev, sizeof(struct f11_2d_ctrl0_9),
> > - GFP_KERNEL);
> > - if (!ctrl->ctrl0_9)
> > - return -ENOMEM;
> > - if (has_gesture_bits(&sensor_query->gesture_info, 0)) {
> > - ctrl->ctrl10 = devm_kzalloc(&fn->dev,
> > - sizeof(struct f11_2d_ctrl10), GFP_KERNEL);
> > - if (!ctrl->ctrl10)
> > - return -ENOMEM;
> > - }
> > -
> > - if (has_gesture_bits(&sensor_query->gesture_info, 1)) {
> > - ctrl->ctrl11 = devm_kzalloc(&fn->dev,
> > - sizeof(struct f11_2d_ctrl11), GFP_KERNEL);
> > - if (!ctrl->ctrl11)
> > - return -ENOMEM;
> > - }
> > -
> > - if (device_query->has_query9 && sensor_query->query9.has_pen) {
> > - ctrl->ctrl20_21 = devm_kzalloc(&fn->dev,
> > - sizeof(struct f11_2d_ctrl20_21), GFP_KERNEL);
> > - if (!ctrl->ctrl20_21)
> > - return -ENOMEM;
> > - }
> > -
> > - if (device_query->has_query9 && sensor_query->query9.has_proximity) {
> > - ctrl->ctrl22_26 = devm_kzalloc(&fn->dev,
> > - sizeof(struct f11_2d_ctrl22_26), GFP_KERNEL);
> > - if (!ctrl->ctrl22_26)
> > - return -ENOMEM;
> > - }
> > -
> > - if (device_query->has_query9 &&
> > - (sensor_query->query9.has_palm_det_sensitivity ||
> > - sensor_query->query9.has_suppress_on_palm_detect)) {
> > - ctrl->ctrl27 = devm_kzalloc(&fn->dev,
> > - sizeof(struct f11_2d_ctrl27), GFP_KERNEL);
> > - if (!ctrl->ctrl27)
> > - return -ENOMEM;
> > - }
> > -
> > - if (sensor_query->gesture_info.has_multi_finger_scroll) {
> > - ctrl->ctrl28 = devm_kzalloc(&fn->dev,
> > - sizeof(struct f11_2d_ctrl28), GFP_KERNEL);
> > - if (!ctrl->ctrl28)
> > - return -ENOMEM;
> > - }
> > -
> > - if (device_query->has_query11 &&
> > - sensor_query->features_1.has_z_tuning) {
> > - ctrl->ctrl29_30 = devm_kzalloc(&fn->dev,
> > - sizeof(struct f11_2d_ctrl29_30), GFP_KERNEL);
> > - if (!ctrl->ctrl29_30)
> > - return -ENOMEM;
> > - }
> >
> > return 0;
> > }
> > @@ -1292,139 +840,71 @@ static int f11_write_control_regs(struct rmi_function *fn,
> > u16 ctrl_base_addr)
> > {
> > struct rmi_device *rmi_dev = fn->rmi_dev;
> > - u16 write_address = ctrl_base_addr;
> > int error;
> >
> > - error = rmi_write_block(rmi_dev, write_address,
> > - ctrl->ctrl0_9,
> > - sizeof(*ctrl->ctrl0_9));
> > + error = rmi_write_block(rmi_dev, ctrl_base_addr, ctrl->ctrl0_9,
> > + RMI_F11_CTRL_REG_COUNT);
> > if (error < 0)
> > return error;
> > - write_address += sizeof(ctrl->ctrl0_9);
> > -
> > - if (ctrl->ctrl10) {
> > - error = rmi_write_block(rmi_dev, write_address,
> > - ctrl->ctrl10, sizeof(*ctrl->ctrl10));
> > - if (error < 0)
> > - return error;
> > - write_address++;
> > - }
> > -
> > - if (ctrl->ctrl11) {
> > - error = rmi_write_block(rmi_dev, write_address,
> > - ctrl->ctrl11, sizeof(*ctrl->ctrl11));
> > - if (error < 0)
> > - return error;
> > - write_address++;
> > - }
> > -
> > - if (ctrl->ctrl14) {
> > - error = rmi_write_block(rmi_dev, write_address,
> > - ctrl->ctrl14, sizeof(ctrl->ctrl14));
> > - if (error < 0)
> > - return error;
> > - write_address += sizeof(*ctrl->ctrl15);
> > - }
> >
> > - if (ctrl->ctrl15) {
> > - error = rmi_write_block(rmi_dev, write_address,
> > - ctrl->ctrl15, sizeof(*ctrl->ctrl15));
> > - if (error < 0)
> > - return error;
> > - write_address += sizeof(*ctrl->ctrl15);
> > - }
> > -
> > - if (ctrl->ctrl16) {
> > - error = rmi_write_block(rmi_dev, write_address,
> > - ctrl->ctrl16, sizeof(*ctrl->ctrl16));
> > - if (error < 0)
> > - return error;
> > - write_address += sizeof(*ctrl->ctrl16);
> > - }
> > -
> > - if (ctrl->ctrl17) {
> > - error = rmi_write_block(rmi_dev, write_address,
> > - ctrl->ctrl17, sizeof(*ctrl->ctrl17));
> > - if (error < 0)
> > - return error;
> > - write_address += sizeof(*ctrl->ctrl17);
> > - }
> > -
> > - if (ctrl->ctrl18_19) {
> > - error = rmi_write_block(rmi_dev, write_address,
> > - ctrl->ctrl18_19, sizeof(*ctrl->ctrl18_19));
> > - if (error < 0)
> > - return error;
> > - write_address += sizeof(*ctrl->ctrl18_19);
> > - }
> > -
> > - if (ctrl->ctrl20_21) {
> > - error = rmi_write_block(rmi_dev, write_address,
> > - ctrl->ctrl20_21, sizeof(*ctrl->ctrl20_21));
> > - if (error < 0)
> > - return error;
> > - write_address += sizeof(*ctrl->ctrl20_21);
> > - }
> > -
> > - if (ctrl->ctrl22_26) {
> > - error = rmi_write_block(rmi_dev, write_address,
> > - ctrl->ctrl22_26, sizeof(*ctrl->ctrl22_26));
> > - if (error < 0)
> > - return error;
> > - write_address += sizeof(*ctrl->ctrl22_26);
> > - }
> > -
> > - if (ctrl->ctrl27) {
> > - error = rmi_write_block(rmi_dev, write_address,
> > - ctrl->ctrl27, sizeof(*ctrl->ctrl27));
> > - if (error < 0)
> > - return error;
> > - write_address += sizeof(*ctrl->ctrl27);
> > - }
> > -
> > - if (ctrl->ctrl28) {
> > - error = rmi_write_block(rmi_dev, write_address,
> > - ctrl->ctrl28, sizeof(*ctrl->ctrl28));
> > - if (error < 0)
> > - return error;
> > - write_address += sizeof(*ctrl->ctrl28);
> > - }
> > -
> > - if (ctrl->ctrl29_30) {
> > - error = rmi_write_block(rmi_dev, write_address,
> > - ctrl->ctrl29_30,
> > - sizeof(struct f11_2d_ctrl29_30));
> > - if (error < 0)
> > - return error;
> > - write_address += sizeof(struct f11_2d_ctrl29_30);
> > - }
> >
> > return 0;
> > }
> >
> > static int rmi_f11_get_query_parameters(struct rmi_device *rmi_dev,
> > - struct f11_2d_device_query *dev_query,
> > + struct f11_data *f11,
> > struct f11_2d_sensor_queries *sensor_query,
> > u16 query_base_addr)
> > {
> > int query_size;
> > int rc;
> > + u8 query_buf[RMI_F11_QUERY_SIZE];
> >
> > - rc = rmi_read_block(rmi_dev, query_base_addr,
> > - &sensor_query->info, sizeof(sensor_query->info));
> > + rc = rmi_read_block(rmi_dev, query_base_addr, query_buf,
> > + RMI_F11_QUERY_SIZE);
> > if (rc < 0)
> > return rc;
> > - query_size = sizeof(sensor_query->info);
> >
> > - if (sensor_query->info.has_abs) {
> > - rc = rmi_read(rmi_dev, query_base_addr + query_size,
> > - &sensor_query->abs_info);
> > + sensor_query->nr_fingers = query_buf[0] & RMI_F11_NR_FINGERS_MASK;
> > + sensor_query->has_rel = !!(query_buf[0] & RMI_F11_HAS_REL);
> > + sensor_query->has_abs = !!(query_buf[0] & RMI_F11_HAS_ABS);
> > + sensor_query->has_gestures = !!(query_buf[0] & RMI_F11_HAS_GESTURES);
> > + sensor_query->has_sensitivity_adjust =
> > + !!(query_buf[0] && RMI_F11_HAS_SENSITIVITY_ADJ);
> > + sensor_query->configurable = !!(query_buf[0] & RMI_F11_CONFIGURABLE);
> > +
> > + sensor_query->nr_x_electrodes =
> > + query_buf[1] & RMI_F11_NR_ELECTRODES_MASK;
> > + sensor_query->nr_y_electrodes =
> > + query_buf[2] & RMI_F11_NR_ELECTRODES_MASK;
> > + sensor_query->max_electrodes =
> > + query_buf[3] & RMI_F11_NR_ELECTRODES_MASK;
> > +
> > + query_size = RMI_F11_QUERY_SIZE;
> > +
> > + if (sensor_query->has_abs) {
> > + rc = rmi_read(rmi_dev, query_base_addr + query_size, query_buf);
> > if (rc < 0)
> > return rc;
> > +
> > + sensor_query->abs_data_size =
> > + query_buf[0] & RMI_F11_ABS_DATA_SIZE_MASK;
> > + sensor_query->has_anchored_finger =
> > + !!(query_buf[0] & RMI_F11_HAS_ANCHORED_FINGER);
> > + sensor_query->has_adj_hyst =
> > + !!(query_buf[0] & RMI_F11_HAS_ADJ_HYST);
> > + sensor_query->has_dribble =
> > + !!(query_buf[0] & RMI_F11_HAS_DRIBBLE);
> > + sensor_query->has_bending_correction =
> > + !!(query_buf[0] & RMI_F11_HAS_BENDING_CORRECTION);
> > + sensor_query->has_large_object_suppression =
> > + !!(query_buf[0] && RMI_F11_HAS_LARGE_OBJECT_SUPPRESSION);
> > + sensor_query->has_jitter_filter =
> > + !!(query_buf[0] & RMI_F11_HAS_JITTER_FILTER);
> > query_size++;
> > }
> >
> > - if (sensor_query->info.has_rel) {
> > + if (sensor_query->has_rel) {
> > rc = rmi_read(rmi_dev, query_base_addr + query_size,
> > &sensor_query->f11_2d_query6);
> > if (rc < 0)
> > @@ -1432,67 +912,173 @@ static int rmi_f11_get_query_parameters(struct rmi_device *rmi_dev,
> > query_size++;
> > }
> >
> > - if (sensor_query->info.has_gestures) {
> > + if (sensor_query->has_gestures) {
> > rc = rmi_read_block(rmi_dev, query_base_addr + query_size,
> > - &sensor_query->gesture_info,
> > - sizeof(sensor_query->gesture_info));
> > + query_buf, RMI_F11_QUERY_GESTURE_SIZE);
> > if (rc < 0)
> > return rc;
> > - query_size += sizeof(sensor_query->gesture_info);
> > - }
> >
> > - if (dev_query->has_query9) {
> > - rc = rmi_read_block(rmi_dev, query_base_addr + query_size,
> > - &sensor_query->query9,
> > - sizeof(sensor_query->query9));
> > + sensor_query->has_single_tap =
> > + !!(query_buf[0] & RMI_F11_HAS_SINGLE_TAP);
> > + sensor_query->has_tap_n_hold =
> > + !!(query_buf[0] & RMI_F11_HAS_TAP_AND_HOLD);
> > + sensor_query->has_double_tap =
> > + !!(query_buf[0] & RMI_F11_HAS_DOUBLE_TAP);
> > + sensor_query->has_early_tap =
> > + !!(query_buf[0] & RMI_F11_HAS_EARLY_TAP);
> > + sensor_query->has_flick =
> > + !!(query_buf[0] & RMI_F11_HAS_FLICK);
> > + sensor_query->has_press =
> > + !!(query_buf[0] & RMI_F11_HAS_PRESS);
> > + sensor_query->has_pinch =
> > + !!(query_buf[0] & RMI_F11_HAS_PINCH);
> > + sensor_query->has_chiral =
> > + !!(query_buf[0] & RMI_F11_HAS_CHIRAL);
> > +
> > + /* query 8 */
> > + sensor_query->has_palm_det =
> > + !!(query_buf[1] & RMI_F11_HAS_PALM_DET);
> > + sensor_query->has_rotate =
> > + !!(query_buf[1] & RMI_F11_HAS_ROTATE);
> > + sensor_query->has_touch_shapes =
> > + !!(query_buf[1] & RMI_F11_HAS_TOUCH_SHAPES);
> > + sensor_query->has_scroll_zones =
> > + !!(query_buf[1] & RMI_F11_HAS_SCROLL_ZONES);
> > + sensor_query->has_individual_scroll_zones =
> > + !!(query_buf[1] & RMI_F11_HAS_INDIVIDUAL_SCROLL_ZONES);
> > + sensor_query->has_mf_scroll =
> > + !!(query_buf[1] & RMI_F11_HAS_MF_SCROLL);
> > + sensor_query->has_mf_edge_motion =
> > + !!(query_buf[1] & RMI_F11_HAS_MF_EDGE_MOTION);
> > + sensor_query->has_mf_scroll_inertia =
> > + !!(query_buf[1] & RMI_F11_HAS_MF_SCROLL_INERTIA);
> > +
> > + sensor_query->query7_nonzero = !!(query_buf[0]);
> > + sensor_query->query8_nonzero = !!(query_buf[1]);
> > +
> > + query_size += 2;
> > + }
> > +
> > + if (f11->has_query9) {
> > + rc = rmi_read(rmi_dev, query_base_addr + query_size, query_buf);
> > if (rc < 0)
> > return rc;
> > - query_size += sizeof(sensor_query->query9);
> > +
> > + sensor_query->has_pen =
> > + !!(query_buf[0] & RMI_F11_HAS_PEN);
> > + sensor_query->has_proximity =
> > + !!(query_buf[0] & RMI_F11_HAS_PROXIMITY);
> > + sensor_query->has_palm_det_sensitivity =
> > + !!(query_buf[0] & RMI_F11_HAS_PALM_DET_SENSITIVITY);
> > + sensor_query->has_suppress_on_palm_detect =
> > + !!(query_buf[0] & RMI_F11_HAS_SUPPRESS_ON_PALM_DETECT);
> > + sensor_query->has_two_pen_thresholds =
> > + !!(query_buf[0] & RMI_F11_HAS_TWO_PEN_THRESHOLDS);
> > + sensor_query->has_contact_geometry =
> > + !!(query_buf[0] & RMI_F11_HAS_CONTACT_GEOMETRY);
> > + sensor_query->has_pen_hover_discrimination =
> > + !!(query_buf[0] & RMI_F11_HAS_PEN_HOVER_DISCRIMINATION);
> > + sensor_query->has_pen_filters =
> > + !!(query_buf[0] & RMI_F11_HAS_PEN_FILTERS);
> > +
> > + query_size++;
> > }
> >
> > - if (sensor_query->gesture_info.has_touch_shapes) {
> > - rc = rmi_read_block(rmi_dev, query_base_addr + query_size,
> > - &sensor_query->ts_info,
> > - sizeof(sensor_query->ts_info));
> > + if (sensor_query->has_touch_shapes) {
> > + rc = rmi_read(rmi_dev, query_base_addr + query_size, query_buf);
> > if (rc < 0)
> > return rc;
> > - query_size += sizeof(sensor_query->ts_info);
> > +
> > + sensor_query->nr_touch_shapes = query_buf[0] &
> > + RMI_F11_NR_TOUCH_SHAPES_MASK;
> > +
> > + query_size++;
> > }
> >
> > - if (dev_query->has_query11) {
> > - rc = rmi_read_block(rmi_dev, query_base_addr + query_size,
> > - &sensor_query->features_1,
> > - sizeof(sensor_query->features_1));
> > + if (f11->has_query11) {
> > + rc = rmi_read(rmi_dev, query_base_addr + query_size, query_buf);
> > if (rc < 0)
> > return rc;
> > - query_size += sizeof(sensor_query->features_1);
> > +
> > + sensor_query->has_z_tuning =
> > + !!(query_buf[0] & RMI_F11_HAS_Z_TUNING);
> > + sensor_query->has_algorithm_selection =
> > + !!(query_buf[0] & RMI_F11_HAS_ALGORITHM_SELECTION);
> > + sensor_query->has_w_tuning =
> > + !!(query_buf[0] & RMI_F11_HAS_W_TUNING);
> > + sensor_query->has_pitch_info =
> > + !!(query_buf[0] & RMI_F11_HAS_PITCH_INFO);
> > + sensor_query->has_finger_size =
> > + !!(query_buf[0] & RMI_F11_HAS_FINGER_SIZE);
> > + sensor_query->has_segmentation_aggressiveness =
> > + !!(query_buf[0] &
> > + RMI_F11_HAS_SEGMENTATION_AGGRESSIVENESS);
> > + sensor_query->has_XY_clip =
> > + !!(query_buf[0] & RMI_F11_HAS_XY_CLIP);
> > + sensor_query->has_drumming_filter =
> > + !!(query_buf[0] & RMI_F11_HAS_DRUMMING_FILTER);
> > +
> > + query_size++;
> > }
> >
> > - if (dev_query->has_query12) {
> > - rc = rmi_read_block(rmi_dev, query_base_addr + query_size,
> > - &sensor_query->features_2,
> > - sizeof(sensor_query->features_2));
> > + if (f11->has_query12) {
> > + rc = rmi_read(rmi_dev, query_base_addr + query_size, query_buf);
> > if (rc < 0)
> > return rc;
> > - query_size += sizeof(sensor_query->features_2);
> > +
> > + sensor_query->has_gapless_finger =
> > + !!(query_buf[0] & RMI_F11_HAS_GAPLESS_FINGER);
> > + sensor_query->has_gapless_finger_tuning =
> > + !!(query_buf[0] & RMI_F11_HAS_GAPLESS_FINGER_TUNING);
> > + sensor_query->has_8bit_w =
> > + !!(query_buf[0] & RMI_F11_HAS_8BIT_W);
> > + sensor_query->has_adjustable_mapping =
> > + !!(query_buf[0] & RMI_F11_HAS_ADJUSTABLE_MAPPING);
> > + sensor_query->has_info2 =
> > + !!(query_buf[0] & RMI_F11_HAS_INFO2);
> > + sensor_query->has_physical_props =
> > + !!(query_buf[0] & RMI_F11_HAS_PHYSICAL_PROPS);
> > + sensor_query->has_finger_limit =
> > + !!(query_buf[0] & RMI_F11_HAS_FINGER_LIMIT);
> > + sensor_query->has_linear_coeff_2 =
> > + !!(query_buf[0] & RMI_F11_HAS_LINEAR_COEFF);
> > +
> > + query_size++;
> > }
> >
> > - if (sensor_query->abs_info.has_jitter_filter) {
> > - rc = rmi_read_block(rmi_dev, query_base_addr + query_size,
> > - &sensor_query->jitter_filter,
> > - sizeof(sensor_query->jitter_filter));
> > + if (sensor_query->has_jitter_filter) {
> > + rc = rmi_read(rmi_dev, query_base_addr + query_size, query_buf);
> > if (rc < 0)
> > return rc;
> > - query_size += sizeof(sensor_query->jitter_filter);
> > +
> > + sensor_query->jitter_window_size = query_buf[0] &
> > + RMI_F11_JITTER_WINDOW_MASK;
> > + sensor_query->jitter_filter_type = (query_buf[0] &
> > + RMI_F11_JITTER_FILTER_MASK) >>
> > + RMI_F11_JITTER_FILTER_SHIFT;
> > +
> > + query_size++;
> > }
> >
> > - if (dev_query->has_query12 && sensor_query->features_2.has_info2) {
> > - rc = rmi_read_block(rmi_dev, query_base_addr + query_size,
> > - &sensor_query->info_2,
> > - sizeof(sensor_query->info_2));
> > + if (f11->has_query12 && sensor_query->has_info2) {
> > + rc = rmi_read(rmi_dev, query_base_addr + query_size, query_buf);
> > if (rc < 0)
> > return rc;
> > - query_size += sizeof(sensor_query->info_2);
> > +
> > + sensor_query->light_control =
> > + query_buf[0] & RMI_F11_LIGHT_CONTROL_MASK;
> > + sensor_query->is_clear =
> > + !!(query_buf[0] & RMI_F11_IS_CLEAR);
> > + sensor_query->clickpad_props =
> > + (query_buf[0] & RMI_F11_CLICKPAD_PROPS_MASK) >>
> > + RMI_F11_CLICKPAD_PROPS_SHIFT;
> > + sensor_query->mouse_buttons =
> > + (query_buf[0] & RMI_F11_MOUSE_BUTTONS_MASK) >>
> > + RMI_F11_MOUSE_BUTTONS_SHIFT;
> > + sensor_query->has_advanced_gestures =
> > + !!(query_buf[0] & RMI_F11_HAS_ADVANCED_GESTURES);
> > +
> > + query_size++;
> > }
> >
> > return query_size;
> > @@ -1506,10 +1092,15 @@ static void f11_set_abs_params(struct rmi_function *fn)
> > struct f11_data *f11 = fn->data;
> > struct f11_2d_sensor *sensor = &f11->sensor;
> > struct input_dev *input = sensor->input;
> > - u16 device_x_max =
> > - f11->dev_controls.ctrl0_9->sensor_max_x_pos;
> > - u16 device_y_max =
> > - f11->dev_controls.ctrl0_9->sensor_max_y_pos;
> > + /* These two lines are not doing what we want them to. So we use
> > + * some shifts instead.
> > + int device_x_max = le16_to_cpu(*(f11->dev_controls.ctrl0_9 + 6));
> > + int device_y_max = le16_to_cpu(*(f11->dev_controls.ctrl0_9 + 8));
> > + */
> > + u16 device_x_max = f11->dev_controls.ctrl0_9[6] |
> > + ((f11->dev_controls.ctrl0_9[7] & 0x0F) << 8);
> > + u16 device_y_max = f11->dev_controls.ctrl0_9[8] |
> > + ((f11->dev_controls.ctrl0_9[9] & 0x0F) << 8);
> > u16 x_min, x_max, y_min, y_max;
> > unsigned int input_flags;
> >
> > @@ -1517,8 +1108,8 @@ static void f11_set_abs_params(struct rmi_function *fn)
> > * as a touchpad in the platform data
> > */
> > if (sensor->sensor_type == rmi_f11_sensor_touchpad ||
> > - (sensor->sens_query.features_2.has_info2 &&
> > - !sensor->sens_query.info_2.is_clear))
> > + (sensor->sens_query.has_info2 &&
> > + !sensor->sens_query.is_clear))
> > input_flags = INPUT_PROP_POINTER;
> > else
> > input_flags = INPUT_PROP_DIRECT;
> > @@ -1567,8 +1158,7 @@ static void f11_set_abs_params(struct rmi_function *fn)
> > y_min, y_max, 0, 0);
> > if (!sensor->type_a)
> > input_mt_init_slots(input, sensor->nbr_fingers, input_flags);
> > - if (IS_ENABLED(CONFIG_RMI4_F11_PEN) &&
> > - sensor->sens_query.query9.has_pen)
> > + if (IS_ENABLED(CONFIG_RMI4_F11_PEN) && sensor->sens_query.has_pen)
> > input_set_abs_params(input, ABS_MT_TOOL_TYPE,
> > 0, MT_TOOL_MAX, 0, 0);
> > else
> > @@ -1588,6 +1178,7 @@ static int rmi_f11_initialize(struct rmi_function *fn)
> > int rc;
> > struct rmi_device_platform_data *pdata = to_rmi_platform_data(rmi_dev);
> > struct f11_2d_sensor *sensor;
> > + u8 buf;
> >
> > dev_dbg(&fn->dev, "Initializing F11 values for %s.\n",
> > pdata->sensor_name);
> > @@ -1605,29 +1196,26 @@ static int rmi_f11_initialize(struct rmi_function *fn)
> > query_base_addr = fn->fd.query_base_addr;
> > control_base_addr = fn->fd.control_base_addr;
> >
> > - rc = rmi_read(rmi_dev, query_base_addr, &f11->dev_query);
> > + rc = rmi_read(rmi_dev, query_base_addr, &buf);
> > if (rc < 0)
> > return rc;
> >
> > + f11->has_query9 = !!(buf & RMI_F11_HAS_QUERY9);
> > + f11->has_query11 = !!(buf & RMI_F11_HAS_QUERY11);
> > + f11->has_query12 = !!(buf & RMI_F11_HAS_QUERY12);
> > + f11->has_query27 = !!(buf & RMI_F11_HAS_QUERY27);
> > + f11->has_query28 = !!(buf & RMI_F11_HAS_QUERY28);
> > +
> > query_offset = (query_base_addr + 1);
> > sensor = &f11->sensor;
> > sensor->fn = fn;
> >
> > - rc = rmi_f11_get_query_parameters(rmi_dev, &f11->dev_query,
> > + rc = rmi_f11_get_query_parameters(rmi_dev, f11,
> > &sensor->sens_query, query_offset);
> > if (rc < 0)
> > return rc;
> > query_offset += rc;
> >
> > - rc = f11_allocate_control_regs(fn,
> > - &f11->dev_query, &sensor->sens_query,
> > - &f11->dev_controls, control_base_addr);
> > - if (rc < 0) {
> > - dev_err(&fn->dev,
> > - "Failed to allocate F11 control params.\n");
> > - return rc;
> > - }
> > -
> > rc = f11_read_control_regs(fn, &f11->dev_controls,
> > control_base_addr);
> > if (rc < 0) {
> > @@ -1670,12 +1258,11 @@ static int rmi_f11_initialize(struct rmi_function *fn)
> >
> > ctrl = &f11->dev_controls;
> > if (sensor->axis_align.delta_x_threshold) {
> > - ctrl->ctrl0_9->delta_x_threshold =
> > + ctrl->ctrl0_9[RMI_F11_DELTA_X_THRESHOLD] =
> > sensor->axis_align.delta_x_threshold;
> > - rc = rmi_write_block(rmi_dev,
> > - ctrl->ctrl0_9_address,
> > + rc = rmi_write_block(rmi_dev, ctrl->ctrl0_9_address,
> > ctrl->ctrl0_9,
> > - sizeof(*ctrl->ctrl0_9));
> > + RMI_F11_CTRL_REG_COUNT);
> > if (rc < 0)
> > dev_warn(&fn->dev, "Failed to write to delta_x_threshold. Code: %d.\n",
> > rc);
> > @@ -1683,12 +1270,10 @@ static int rmi_f11_initialize(struct rmi_function *fn)
> > }
> >
> > if (sensor->axis_align.delta_y_threshold) {
> > - ctrl->ctrl0_9->delta_y_threshold =
> > + ctrl->ctrl0_9[RMI_F11_DELTA_Y_THRESHOLD] =
> > sensor->axis_align.delta_y_threshold;
> > - rc = rmi_write_block(rmi_dev,
> > - ctrl->ctrl0_9_address,
> > - ctrl->ctrl0_9,
> > - sizeof(*ctrl->ctrl0_9));
> > + rc = rmi_write_block(rmi_dev, ctrl->ctrl0_9_address,
> > + ctrl->ctrl0_9, RMI_F11_CTRL_REG_COUNT);
> > if (rc < 0)
> > dev_warn(&fn->dev, "Failed to write to delta_y_threshold. Code: %d.\n",
> > rc);
> > @@ -1737,7 +1322,7 @@ static int rmi_f11_register_devices(struct rmi_function *fn)
> >
> > f11_set_abs_params(fn);
> >
> > - if (sensor->sens_query.info.has_rel) {
> > + if (sensor->sens_query.has_rel) {
> > set_bit(EV_REL, input_dev->evbit);
> > set_bit(REL_X, input_dev->relbit);
> > set_bit(REL_Y, input_dev->relbit);
> > @@ -1749,7 +1334,7 @@ static int rmi_f11_register_devices(struct rmi_function *fn)
> > goto error_unregister;
> > }
> >
> > - if (sensor->sens_query.info.has_rel) {
> > + if (sensor->sens_query.has_rel) {
> > /*create input device for mouse events */
> > input_dev_mouse = input_allocate_device();
> > if (!input_dev_mouse) {
> > @@ -1857,10 +1442,6 @@ static int rmi_f11_resume(struct device *dev)
> > struct rmi_function *fn = to_rmi_function(dev);
> > struct rmi_device *rmi_dev = fn->rmi_dev;
> > struct f11_data *data = fn->data;
> > - /* Command register always reads as 0, so we can just use a local. */
> > - struct f11_2d_commands commands = {
> > - .rezero = true,
> > - };
> > int error;
> >
> > dev_dbg(&fn->dev, "Resuming...\n");
> > @@ -1869,8 +1450,7 @@ static int rmi_f11_resume(struct device *dev)
> >
> > mdelay(data->rezero_wait_ms);
> >
> > - error = rmi_write_block(rmi_dev, fn->fd.command_base_addr,
> > - &commands, sizeof(commands));
> > + error = rmi_write(rmi_dev, fn->fd.command_base_addr, RMI_F11_REZERO);
> > if (error < 0) {
> > dev_err(&fn->dev,
> > "%s: failed to issue rezero command, error = %d.",
>
> --
> Dmitry
^ permalink raw reply
* Re: [PATCH] input synaptics-rmi4: Eliminate packed structs in PDT handling
From: Dmitry Torokhov @ 2013-12-15 11:57 UTC (permalink / raw)
To: Christopher Heiny
Cc: Linux Input, Andrew Duggan, Vincent Huang, Vivian Ly,
Daniel Rosenberg, Jean Delvare, Joerie de Gram, Linus Walleij,
Benjamin Tissoires
In-Reply-To: <1386731442-31146-1-git-send-email-cheiny@synaptics.com>
On Tue, Dec 10, 2013 at 07:10:42PM -0800, Christopher Heiny wrote:
> This converts the PDT handling routines from using bitfields in packed structs,
> converting to bitmasks and shifts to parse out bitfields, nibbles, and so on.
>
> Signed-off-by: Christopher Heiny <cheiny@synaptics.com>
> Cc: Dmitry Torokhov <dmitry.torokhov@gmail.com>
> Cc: Jean Delvare <khali@linux-fr.org>
> Cc: Linus Walleij <linus.walleij@stericsson.com>
> Cc: Joerie de Gram <j.de.gram@gmail.com>
> Cc: Benjamin Tissoires <benjamin.tissoires@redhat.com>
>
Applied, thank you.
> ---
>
> This patch implements changes to the synaptics-rmi4 branch of
> Dmitry's input tree. The base for the patch is commit
> f154022b208a59b048f52b7b5d58a5ec1949b96e.
>
> drivers/input/rmi4/rmi_driver.c | 45 +++++++++++++++++++++++++++-------------
> drivers/input/rmi4/rmi_driver.h | 46 +++++++++++++++--------------------------
> 2 files changed, 48 insertions(+), 43 deletions(-)
>
> diff --git a/drivers/input/rmi4/rmi_driver.c b/drivers/input/rmi4/rmi_driver.c
> index dffbfa0..a30c7d3 100644
> --- a/drivers/input/rmi4/rmi_driver.c
> +++ b/drivers/input/rmi4/rmi_driver.c
> @@ -483,6 +483,31 @@ int rmi_driver_irq_get_mask(struct rmi_device *rmi_dev,
> return -ENOMEM;
> }
>
> +int rmi_read_pdt_entry(struct rmi_device *rmi_dev, struct pdt_entry *entry,
> + u16 pdt_address)
> +{
> + u8 buf[RMI_PDT_ENTRY_SIZE];
> + int error;
> +
> + error = rmi_read_block(rmi_dev, pdt_address, buf, RMI_PDT_ENTRY_SIZE);
> + if (error < 0) {
> + dev_err(&rmi_dev->dev, "Read PDT entry at %#06x failed, code: %d.\n",
> + pdt_address, error);
> + return error;
> + }
> +
> + entry->query_base_addr = buf[0];
> + entry->command_base_addr = buf[1];
> + entry->control_base_addr = buf[2];
> + entry->data_base_addr = buf[3];
> + entry->interrupt_source_count = buf[4] & RMI_PDT_INT_SOURCE_COUNT_MASK;
> + entry->function_version = (buf[4] & RMI_PDT_FUNCTION_VERSION_MASK) >> 5;
> + entry->function_number = buf[5];
> +
> + return 0;
> +}
> +EXPORT_SYMBOL_GPL(rmi_read_pdt_entry);
> +
> static void rmi_driver_copy_pdt_to_fd(struct pdt_entry *pdt,
> struct rmi_function_descriptor *fd,
> u16 page_start)
> @@ -572,14 +597,10 @@ static int reset_and_reflash(struct rmi_device *rmi_dev)
> u16 pdt_end = page_start + PDT_END_SCAN_LOCATION;
>
> done = true;
> - for (i = pdt_start; i >= pdt_end; i -= sizeof(pdt_entry)) {
> - retval = rmi_read_block(rmi_dev, i, &pdt_entry,
> - sizeof(pdt_entry));
> - if (retval != sizeof(pdt_entry)) {
> - dev_err(dev, "Read PDT entry at %#06x failed, code = %d.\n",
> - i, retval);
> + for (i = pdt_start; i >= pdt_end; i -= RMI_PDT_ENTRY_SIZE) {
> + retval = rmi_read_pdt_entry(rmi_dev, &pdt_entry, i);
> + if (retval < 0)
> return retval;
> - }
>
> if (RMI4_END_OF_PDT(pdt_entry.function_number))
> break;
> @@ -634,14 +655,10 @@ static int rmi_scan_pdt(struct rmi_device *rmi_dev)
> u16 pdt_end = page_start + PDT_END_SCAN_LOCATION;
>
> done = true;
> - for (i = pdt_start; i >= pdt_end; i -= sizeof(pdt_entry)) {
> - retval = rmi_read_block(rmi_dev, i, &pdt_entry,
> - sizeof(pdt_entry));
> - if (retval != sizeof(pdt_entry)) {
> - dev_err(dev, "Read of PDT entry at %#06x failed.\n",
> - i);
> + for (i = pdt_start; i >= pdt_end; i -= RMI_PDT_ENTRY_SIZE) {
> + retval = rmi_read_pdt_entry(rmi_dev, &pdt_entry, i);
> + if (retval < 0)
> goto error_exit;
> - }
>
> if (RMI4_END_OF_PDT(pdt_entry.function_number))
> break;
> diff --git a/drivers/input/rmi4/rmi_driver.h b/drivers/input/rmi4/rmi_driver.h
> index f8d87e9..5e3c4d4 100644
> --- a/drivers/input/rmi4/rmi_driver.h
> +++ b/drivers/input/rmi4/rmi_driver.h
> @@ -29,11 +29,7 @@
> #define PDT_PROPERTIES_LOCATION 0x00EF
> #define BSR_LOCATION 0x00FE
>
> -struct pdt_properties {
> - u8 reserved_1:6;
> - u8 has_bsr:1;
> - u8 reserved_2:1;
> -} __attribute__((__packed__));
> +#define RMI_PDT_PROPS_HAS_BSR 0x02
>
> struct rmi_driver_data {
> struct list_head function_list;
> @@ -61,7 +57,7 @@ struct rmi_driver_data {
> ktime_t poll_interval;
>
> struct mutex pdt_mutex;
> - struct pdt_properties pdt_props;
> + u8 pdt_props;
> u8 bsr;
>
> bool enabled;
> @@ -90,34 +86,26 @@ struct rmi_driver_data {
> void *data;
> };
>
> +#define RMI_PDT_ENTRY_SIZE 6
> +#define RMI_PDT_FUNCTION_VERSION_MASK 0x60
> +#define RMI_PDT_INT_SOURCE_COUNT_MASK 0x07
> +
> #define PDT_START_SCAN_LOCATION 0x00e9
> #define PDT_END_SCAN_LOCATION 0x0005
> #define RMI4_END_OF_PDT(id) ((id) == 0x00 || (id) == 0xff)
>
> struct pdt_entry {
> - u8 query_base_addr:8;
> - u8 command_base_addr:8;
> - u8 control_base_addr:8;
> - u8 data_base_addr:8;
> - u8 interrupt_source_count:3;
> - u8 bits3and4:2;
> - u8 function_version:2;
> - u8 bit7:1;
> - u8 function_number:8;
> -} __attribute__((__packed__));
> -
> -static inline void copy_pdt_entry_to_fd(struct pdt_entry *pdt,
> - struct rmi_function_descriptor *fd,
> - u16 page_start)
> -{
> - fd->query_base_addr = pdt->query_base_addr + page_start;
> - fd->command_base_addr = pdt->command_base_addr + page_start;
> - fd->control_base_addr = pdt->control_base_addr + page_start;
> - fd->data_base_addr = pdt->data_base_addr + page_start;
> - fd->function_number = pdt->function_number;
> - fd->interrupt_source_count = pdt->interrupt_source_count;
> - fd->function_version = pdt->function_version;
> -}
> + u8 query_base_addr;
> + u8 command_base_addr;
> + u8 control_base_addr;
> + u8 data_base_addr;
> + u8 interrupt_source_count;
> + u8 function_version;
> + u8 function_number;
> +};
> +
> +int rmi_read_pdt_entry(struct rmi_device *rmi_dev, struct pdt_entry *entry,
> + u16 pdt_address);
>
> bool rmi_is_physical_driver(struct device_driver *);
> int rmi_register_physical_driver(void);
--
Dmitry
^ permalink raw reply
* [PATCH] Input: pmic8xxx-pwrkey - switch to using managed resources
From: Dmitry Torokhov @ 2013-12-15 12:07 UTC (permalink / raw)
To: linux-input; +Cc: Stephen Boyd, Lars-Peter Clausen, Sachin Kamat, linux-kernel
This simplifies error handling and device removal paths.
Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
---
drivers/input/misc/pmic8xxx-pwrkey.c | 74 ++++++++++++------------------------
1 file changed, 25 insertions(+), 49 deletions(-)
diff --git a/drivers/input/misc/pmic8xxx-pwrkey.c b/drivers/input/misc/pmic8xxx-pwrkey.c
index ef93840..aaf3325 100644
--- a/drivers/input/misc/pmic8xxx-pwrkey.c
+++ b/drivers/input/misc/pmic8xxx-pwrkey.c
@@ -32,7 +32,6 @@
* @key_press_irq: key press irq number
*/
struct pmic8xxx_pwrkey {
- struct input_dev *pwr;
int key_press_irq;
};
@@ -110,22 +109,22 @@ static int pmic8xxx_pwrkey_probe(struct platform_device *pdev)
return -ENODEV;
}
- pwrkey = kzalloc(sizeof(*pwrkey), GFP_KERNEL);
+ pwrkey = devm_kzalloc(&pdev->dev, sizeof(*pwrkey), GFP_KERNEL);
if (!pwrkey)
return -ENOMEM;
- pwr = input_allocate_device();
+ pwrkey->key_press_irq = key_press_irq;
+
+ pwr = devm_input_allocate_device(&pdev->dev);
if (!pwr) {
dev_dbg(&pdev->dev, "Can't allocate power button\n");
- err = -ENOMEM;
- goto free_pwrkey;
+ return -ENOMEM;
}
input_set_capability(pwr, EV_KEY, KEY_POWER);
pwr->name = "pmic8xxx_pwrkey";
pwr->phys = "pmic8xxx_pwrkey/input0";
- pwr->dev.parent = &pdev->dev;
delay = (pdata->kpd_trigger_delay_us << 10) / USEC_PER_SEC;
delay = 1 + ilog2(delay);
@@ -133,7 +132,7 @@ static int pmic8xxx_pwrkey_probe(struct platform_device *pdev)
err = regmap_read(regmap, PON_CNTL_1, &pon_cntl);
if (err < 0) {
dev_err(&pdev->dev, "failed reading PON_CNTL_1 err=%d\n", err);
- goto free_input_dev;
+ return err;
}
pon_cntl &= ~PON_CNTL_TRIG_DELAY_MASK;
@@ -146,66 +145,43 @@ static int pmic8xxx_pwrkey_probe(struct platform_device *pdev)
err = regmap_write(regmap, PON_CNTL_1, pon_cntl);
if (err < 0) {
dev_err(&pdev->dev, "failed writing PON_CNTL_1 err=%d\n", err);
- goto free_input_dev;
+ return err;
}
- err = input_register_device(pwr);
+ err = devm_request_irq(&pdev->dev, key_press_irq, pwrkey_press_irq,
+ IRQF_TRIGGER_RISING,
+ "pmic8xxx_pwrkey_press", pwr);
if (err) {
- dev_dbg(&pdev->dev, "Can't register power key: %d\n", err);
- goto free_input_dev;
+ dev_err(&pdev->dev, "Can't get %d IRQ for pwrkey: %d\n",
+ key_press_irq, err);
+ return err;
}
- pwrkey->key_press_irq = key_press_irq;
- pwrkey->pwr = pwr;
-
- platform_set_drvdata(pdev, pwrkey);
-
- err = request_irq(key_press_irq, pwrkey_press_irq,
- IRQF_TRIGGER_RISING, "pmic8xxx_pwrkey_press", pwr);
- if (err < 0) {
- dev_dbg(&pdev->dev, "Can't get %d IRQ for pwrkey: %d\n",
- key_press_irq, err);
- goto unreg_input_dev;
+ err = devm_request_irq(&pdev->dev, key_release_irq, pwrkey_release_irq,
+ IRQF_TRIGGER_RISING,
+ "pmic8xxx_pwrkey_release", pwr);
+ if (err) {
+ dev_err(&pdev->dev, "Can't get %d IRQ for pwrkey: %d\n",
+ key_release_irq, err);
+ return err;
}
- err = request_irq(key_release_irq, pwrkey_release_irq,
- IRQF_TRIGGER_RISING, "pmic8xxx_pwrkey_release", pwr);
- if (err < 0) {
- dev_dbg(&pdev->dev, "Can't get %d IRQ for pwrkey: %d\n",
- key_release_irq, err);
-
- goto free_press_irq;
+ err = input_register_device(pwr);
+ if (err) {
+ dev_err(&pdev->dev, "Can't register power key: %d\n", err);
+ return err;
}
+ platform_set_drvdata(pdev, pwrkey);
device_init_wakeup(&pdev->dev, pdata->wakeup);
return 0;
-
-free_press_irq:
- free_irq(key_press_irq, pwrkey);
-unreg_input_dev:
- input_unregister_device(pwr);
- pwr = NULL;
-free_input_dev:
- input_free_device(pwr);
-free_pwrkey:
- kfree(pwrkey);
- return err;
}
static int pmic8xxx_pwrkey_remove(struct platform_device *pdev)
{
- struct pmic8xxx_pwrkey *pwrkey = platform_get_drvdata(pdev);
- int key_release_irq = platform_get_irq(pdev, 0);
- int key_press_irq = platform_get_irq(pdev, 1);
-
device_init_wakeup(&pdev->dev, 0);
- free_irq(key_press_irq, pwrkey->pwr);
- free_irq(key_release_irq, pwrkey->pwr);
- input_unregister_device(pwrkey->pwr);
- kfree(pwrkey);
-
return 0;
}
--
1.8.3.1
--
Dmitry
^ permalink raw reply related
* Re: [RFC] Add ff-memless-next driver
From: Michal Malý @ 2013-12-15 13:07 UTC (permalink / raw)
To: Joe Perches
Cc: dmitry.torokhov, linux-kernel, linux-input, elias.vds,
anssi.hannula
In-Reply-To: <1387073042.2276.21.camel@joe-AO722>
On Saturday 14 of December 2013 18:04:02 Joe Perches wrote:
> On Sun, 2013-12-15 at 01:19 +0100, Michal Malý wrote:
> > diff --git a/drivers/input/ff-memless-next.c
> > b/drivers/input/ff-memless-next.c
> []
>
> > +static inline s32 mlnx_clamp_level(const s32 level)
> > +{
> > + return (level > 0x7fff) ? 0x7fff : ((level < -0x7fff) ? -0x7fff :
> > level);
>
> clamp(level, -0x7fff, 0x7fff);
> []
>
> > +static inline int mlnx_is_conditional(const struct ff_effect *effect)
> > +{
> > + return (effect->type == FF_DAMPER) || (effect->type == FF_FRICTION) ||
> > (effect->type == FF_INERTIA) || (effect->type == FF_SPRING); +}
>
> Maybe try to run your patch through scripts/checkpatch.pl
>
> bool?
> 80 char line max? (true for the file, not just here)
> switch?
> switch (effect->type) {
> case FF_DAMPER:
> case FF_FRICTION:
> case FF_INERTIA:
> case FF_SPRING:
> return true;
> }
> return false;
Okay, thanks for the input. I found a problem regarding effect updating in the code anyway. I'll submit a corrected version of the patch once I'm sure it's fixed.
Michal
^ permalink raw reply
* T440s Synaptics clickpad: lost sync / KBC bad data
From: J. Domburg @ 2013-12-15 14:37 UTC (permalink / raw)
To: linux-input
Hello everyone,
I hope I'm at the right address here with my problems. If not, please do
point me in the correct direction.
I have a Lenovo Thinkpad T440s with a Synaptics clickpad and an IBM
trackpoint in it:
input: PS/2 Synaptics TouchPad as /devices/platform/i8042/serio1/input/input120
psmouse serio1: synaptics: Touchpad model: 1, fw: 8.1, id: 0x1e2b1, caps: 0xd001a3/0x940300/0x127c00, board id: 2668, fw id: 1293989
psmouse serio1: synaptics: serio: Synaptics pass-through port at isa0060/serio1/input0
input: SynPS/2 Synaptics TouchPad as /devices/platform/i8042/serio1/input/input123
psmouse serio34: alps: Unknown ALPS touchpad: E7=10 00 64, EC=10 00 64
psmouse serio34: trackpoint: IBM TrackPoint firmware: 0x0e,
buttons: 3/3 input: TPPS/2 IBM TrackPoint as /devices/platform/i8042/serio1/serio34/input/input124
The problem is that the trackpoint behaves incredibly erratic, sometimes
working correctly for minutes at a time, sometimes just jumping around and
many times just hanging. I need to remove and re-insert the psmouse module
to solve that. Alongside this behaviour, my kernel log also is getting
spammed with messages like:
psmouse serio1: TouchPad at isa0060/serio1/input0 lost sync at byte 1
psmouse serio1: TouchPad at isa0060/serio1/input0 lost sync at byte 1
psmouse serio1: TouchPad at isa0060/serio1/input0 lost sync at byte 1
psmouse serio1: TouchPad at isa0060/serio1/input0 - driver resynced.
and
psmouse serio1: bad data from KBC - timeout
What I've tried:
- Tried the kernel options i8042.nomux=1 and i8042.reset=1
- Disable acpi by passing acpi=off to the kernel
- Disabled CPU frequency scaling
- Trying other protocols, e.g. by doing modprobe psmouse proto=imps or
proto=bare
- Switching from vanilla 3.12 kernel to both the latest&greatest kernel
from Linus' Git and an antique 3.1.0 kernel
- Turning on i8042.debug. To my untrained eye, it looks like bytes of PS/2
data are just disappearing when the 'lost sync' messages kick in. I can
give an example of that if needed.
Strangely, the symptoms have been getting worse in the 10 days I've had
this machine: from the first few days with no trouble to today with the
mouse crapping out almost once every ten seconds or so. I would say it's a
DOA and claim my warranty, if not frustratingly the machine works
perfectly fine in Windows 8, with no touchpad trouble at all.
I'm willing to try things on this machine, run patches or take any hint in
what I can change to get this working; if it helps I can even poke an
oscilloscope at the PS2 lines. Not having a working touchpad or
touchpoint is getting a bit frustrating...
Cheers,
Jeroen
^ permalink raw reply
* Re: [PATCH V2] Input: define KEY_WWAN for Wireless WAN
From: Dmitry Torokhov @ 2013-12-16 5:02 UTC (permalink / raw)
To: Jiri Kosina; +Cc: Rafał Miłecki, linux-input, Hauke Mehrtens
In-Reply-To: <alpine.LNX.2.00.1312102036250.1413@pobox.suse.cz>
On Tue, Dec 10, 2013 at 08:36:41PM +0100, Jiri Kosina wrote:
> On Tue, 10 Dec 2013, Rafał Miłecki wrote:
>
> > Some devices with support for mobile networks may have buttons for
> > enabling/disabling such connection. An example can be Linksys router
> > 54G3G.
> > We already have KEY_BLUETOOTH, KEY_WLAN and KEY_UWB so it makes sense
> > to add KEY_WWAN as well.
> > As we already have KEY_WIMAX, use it's value for KEY_WWAN and make it an
> > alias.
> >
> > Signed-off-by: Rafał Miłecki <zajec5@gmail.com>
> > ---
> > V2: Re-use 246 value for WWAN and make WIMAX an aliast to WWAN
> > ---
> > include/uapi/linux/input.h | 3 ++-
> > 1 file changed, 2 insertions(+), 1 deletion(-)
> >
> > diff --git a/include/uapi/linux/input.h b/include/uapi/linux/input.h
> > index a372627..7c69941 100644
> > --- a/include/uapi/linux/input.h
> > +++ b/include/uapi/linux/input.h
> > @@ -464,7 +464,8 @@ struct input_keymap_entry {
> > #define KEY_BRIGHTNESS_ZERO 244 /* brightness off, use ambient */
> > #define KEY_DISPLAY_OFF 245 /* display device to off state */
> >
> > -#define KEY_WIMAX 246
> > +#define KEY_WWAN 246 /* Wireless WAN (LTE, UMTS, GSM, etc.) */
> > +#define KEY_WIMAX KEY_WWAN
> > #define KEY_RFKILL 247 /* Key that controls all radios */
> >
> > #define KEY_MICMUTE 248 /* Mute / unmute the microphone */
>
> Adding Dmitry to CC
Applied, thank you.
--
Dmitry
--
To unsubscribe from this list: send the line "unsubscribe linux-input" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* Re: [PATCH] drivers/input/misc: new PC speaker sounds, clicks and notes
From: Dmitry Torokhov @ 2013-12-16 5:21 UTC (permalink / raw)
To: Karl Dahlke; +Cc: linux-input, linux-kernel
In-Reply-To: <20131109072257.eklhad@comcast.net>
Hi Karl,
On Mon, Dec 09, 2013 at 07:22:57AM -0500, Karl Dahlke wrote:
> From: Karl Dahlke <eklhad@gmail.com>
>
> The speaker driver can play a tone at a specified frequency,
> or the standard control G bell,
> which is a special case of TONE at 1000 hz 0.1 seconds.
> This patch adds kd_mkpulse() to generate a soft click.
> This is introduced to support accessibility modules and adapters in the future.
> With this in place, a module can easily provide soft clicks,
> i.e. audible feedback, whenever a key is depressed,
> or when that keystroke is echoed on screen, whichever you prefer.
> (Many people find the latter more valuable.)
> This allows a blind user, for example, to have ongoing feedback while typing,
> even if he is, at the same time, listening to text that is already on screen.
> This is faster and more convenient than having characters echoed verbally.
> And it works all the time, even if speech or braille is not working
> for whatever reason. And there are many reasons those adapters could fail.
> Misconfigured sound card, bad serial connection,
> software synth not loading, etc.
> Thus these forms of audio feedback are very important.
>
> This should not be confused with the click function in certain specialized
> keyboards such as lkkbd.c.
> That function does a serio write to the client to activate clicks locally.
> In contrast, this function generates a one-time pulse at the pc speaker,
> or through a similar driver, so that modules can click whenever they want,
> e.g. when a key is echoed back to you by a running application,
> perhaps a thousand miles away over ssh, so you know all is well.
> A module may want to click, or issue a series of clicks, for many reasons.
I do not think it is a good idea to add SND_PULSE as it can be easily
implemented by SND_TONE with the additional benefit that parameters of
the click can be adjusted. Also, if clicking is done elsewhere, it would
work with other speaker drivers besides pcspkr.
>
> Another function introduced by this patch is kd_mknotes,
> which plays a series of tones in the background.
> You could do this yourself with kd_mksound and timers,
> but why should everyone reinvent the wheel?
> It is better to write the function once, properly, in the kernel,
> and let modules use it thereafter.
Can it be put into a library instead? Especially given David's work on
trying to push the VT code out of the kernel. Also, what if you want
clicks to go through sound card and not the speaker interface?
Thanks.
--
Dmitry
^ permalink raw reply
* [PATCH 0/2] Input: joystick - documentation fixes
From: Antonio Ospite @ 2013-12-16 8:57 UTC (permalink / raw)
To: linux-input; +Cc: Antonio Ospite, Dmitry Torokhov
Hi,
here are a couple of fixes for the joystick API documentation.
Ciao,
Antonio
Antonio Ospite (2):
Input: joystick - refer to /dev/input/js0 in documentation
Input: joystick - use sizeof(VARIABLE) in documentation
Documentation/input/joystick-api.txt | 12 ++++++------
Documentation/input/joystick.txt | 8 ++++----
2 files changed, 10 insertions(+), 10 deletions(-)
--
Antonio Ospite
http://ao2.it
A: Because it messes up the order in which people normally read text.
See http://en.wikipedia.org/wiki/Posting_style
Q: Why is top-posting such a bad thing?
^ permalink raw reply
* [PATCH 2/2] Input: joystick - use sizeof(VARIABLE) in documentation
From: Antonio Ospite @ 2013-12-16 8:57 UTC (permalink / raw)
To: linux-input; +Cc: Antonio Ospite, Dmitry Torokhov
In-Reply-To: <1387184235-20169-1-git-send-email-ospite@studenti.unina.it>
Use the preferred style sizeof(VARIABLE) instead of sizeof(TYPE) in the
joystick API documentation, Documentation/CodingStyle states that this
is the preferred style for allocations but using it elsewhere is good
too.
Also fix some errors like "sizeof(struct mybuffer)" which didn't mean
anything.
Signed-off-by: Antonio Ospite <ospite@studenti.unina.it>
---
Documentation/input/joystick-api.txt | 10 +++++-----
1 file changed, 5 insertions(+), 5 deletions(-)
diff --git a/Documentation/input/joystick-api.txt b/Documentation/input/joystick-api.txt
index f95f648..47e60a5 100644
--- a/Documentation/input/joystick-api.txt
+++ b/Documentation/input/joystick-api.txt
@@ -23,7 +23,7 @@ By default, the device is opened in blocking mode.
~~~~~~~~~~~~~~~~
struct js_event e;
- read (fd, &e, sizeof(struct js_event));
+ read (fd, &e, sizeof(e));
where js_event is defined as
@@ -34,8 +34,8 @@ where js_event is defined as
__u8 number; /* axis/button number */
};
-If the read is successful, it will return sizeof(struct js_event), unless
-you wanted to read more than one event per read as described in section 3.1.
+If the read is successful, it will return sizeof(e), unless you wanted to read
+more than one event per read as described in section 3.1.
2.1 js_event.type
@@ -144,7 +144,7 @@ all events on the queue (that is, until you get a -1).
For example,
while (1) {
- while (read (fd, &e, sizeof(struct js_event)) > 0) {
+ while (read (fd, &e, sizeof(e)) > 0) {
process_event (e);
}
/* EAGAIN is returned when the queue is empty */
@@ -181,7 +181,7 @@ at a time using the typical read(2) functionality. For that, you would
replace the read above with something like
struct js_event mybuffer[0xff];
- int i = read (fd, mybuffer, sizeof(struct mybuffer));
+ int i = read (fd, mybuffer, ARRAY_SIZE(mybuffer));
In this case, read would return -1 if the queue was empty, or some
other value in which the number of events read would be i /
--
1.8.5.1
^ permalink raw reply related
* [PATCH 1/2] Input: joystick - refer to /dev/input/js0 in documentation
From: Antonio Ospite @ 2013-12-16 8:57 UTC (permalink / raw)
To: linux-input; +Cc: Antonio Ospite, Dmitry Torokhov
In-Reply-To: <1387184235-20169-1-git-send-email-ospite@studenti.unina.it>
Nowadays the joystick device nodes are created under /dev/input, reflect
this in the documentation in order to make copy and paste easier for
users.
Signed-off-by: Antonio Ospite <ospite@studenti.unina.it>
---
Documentation/input/joystick-api.txt | 2 +-
Documentation/input/joystick.txt | 8 ++++----
2 files changed, 5 insertions(+), 5 deletions(-)
diff --git a/Documentation/input/joystick-api.txt b/Documentation/input/joystick-api.txt
index c507330..f95f648 100644
--- a/Documentation/input/joystick-api.txt
+++ b/Documentation/input/joystick-api.txt
@@ -16,7 +16,7 @@ joystick.
By default, the device is opened in blocking mode.
- int fd = open ("/dev/js0", O_RDONLY);
+ int fd = open ("/dev/input/js0", O_RDONLY);
2. Event Reading
diff --git a/Documentation/input/joystick.txt b/Documentation/input/joystick.txt
index 304262b..8d027dc 100644
--- a/Documentation/input/joystick.txt
+++ b/Documentation/input/joystick.txt
@@ -116,7 +116,7 @@ your needs:
For testing the joystick driver functionality, there is the jstest
program in the utilities package. You run it by typing:
- jstest /dev/js0
+ jstest /dev/input/js0
And it should show a line with the joystick values, which update as you
move the stick, and press its buttons. The axes should all be zero when the
@@ -136,7 +136,7 @@ joystick should be autocalibrated by the driver automagically. However, with
some analog joysticks, that either do not use linear resistors, or if you
want better precision, you can use the jscal program
- jscal -c /dev/js0
+ jscal -c /dev/input/js0
included in the joystick package to set better correction coefficients than
what the driver would choose itself.
@@ -145,7 +145,7 @@ what the driver would choose itself.
calibration using the jstest command, and if you do, you then can save the
correction coefficients into a file
- jscal -p /dev/js0 > /etc/joystick.cal
+ jscal -p /dev/input/js0 > /etc/joystick.cal
And add a line to your rc script executing that file
@@ -556,7 +556,7 @@ interface, and "old" for the "0.x" interface. You run it by typing:
5. FAQ
~~~~~~
-Q: Running 'jstest /dev/js0' results in "File not found" error. What's the
+Q: Running 'jstest /dev/input/js0' results in "File not found" error. What's the
cause?
A: The device files don't exist. Create them (see section 2.2).
--
1.8.5.1
^ permalink raw reply related
* Re: [PATCH 2/2] Input: joystick - use sizeof(VARIABLE) in documentation
From: Dmitry Torokhov @ 2013-12-16 9:51 UTC (permalink / raw)
To: Antonio Ospite; +Cc: linux-input
In-Reply-To: <1387184235-20169-3-git-send-email-ospite@studenti.unina.it>
Hi Antonio,
On Mon, Dec 16, 2013 at 09:57:15AM +0100, Antonio Ospite wrote:
> @@ -181,7 +181,7 @@ at a time using the typical read(2) functionality. For that, you would
> replace the read above with something like
>
> struct js_event mybuffer[0xff];
> - int i = read (fd, mybuffer, sizeof(struct mybuffer));
> + int i = read (fd, mybuffer, ARRAY_SIZE(mybuffer));
>
This is wrong, as ARRAY_SIZE(mybuffer) would be 0xff and not the size of
buffer in bytes. I'll fix it up.
Thanks.
--
Dmitry
^ permalink raw reply
* Re: [PATCH 2/2] Input: joystick - use sizeof(VARIABLE) in documentation
From: Antonio Ospite @ 2013-12-16 10:06 UTC (permalink / raw)
To: Dmitry Torokhov; +Cc: linux-input
In-Reply-To: <20131216095140.GA15405@core.coreip.homeip.net>
On Mon, 16 Dec 2013 01:51:41 -0800
Dmitry Torokhov <dmitry.torokhov@gmail.com> wrote:
> Hi Antonio,
>
> On Mon, Dec 16, 2013 at 09:57:15AM +0100, Antonio Ospite wrote:
> > @@ -181,7 +181,7 @@ at a time using the typical read(2) functionality. For that, you would
> > replace the read above with something like
> >
> > struct js_event mybuffer[0xff];
> > - int i = read (fd, mybuffer, sizeof(struct mybuffer));
> > + int i = read (fd, mybuffer, ARRAY_SIZE(mybuffer));
> >
>
> This is wrong, as ARRAY_SIZE(mybuffer) would be 0xff and not the size of
> buffer in bytes. I'll fix it up.
>
> Thanks.
You're right of course, thank you.
Ciao,
Antonio
--
Antonio Ospite
http://ao2.it
A: Because it messes up the order in which people normally read text.
See http://en.wikipedia.org/wiki/Posting_style
Q: Why is top-posting such a bad thing?
^ permalink raw reply
* [PATCH] Input: add i2c/smbus driver for elan touchpad
From: Duson Lin @ 2013-12-16 12:26 UTC (permalink / raw)
To: linux-kernel, linux-input, dmitry.torokhov
Cc: bleung, agnescheng, phoenix, Duson Lin
This driver adds support for elan i2c/smbus touchpad found on some laptops PC
Signed-off-by: Duson Lin <dusonlin@emc.com.tw>
---
drivers/input/mouse/Kconfig | 10 +
drivers/input/mouse/Makefile | 1 +
drivers/input/mouse/elan_i2c.c | 908 ++++++++++++++++++++++++++++++++++++++++
3 files changed, 919 insertions(+)
create mode 100644 drivers/input/mouse/elan_i2c.c
diff --git a/drivers/input/mouse/Kconfig b/drivers/input/mouse/Kconfig
index effa9c5..095eccc 100644
--- a/drivers/input/mouse/Kconfig
+++ b/drivers/input/mouse/Kconfig
@@ -215,6 +215,16 @@ config MOUSE_CYAPA
To compile this driver as a module, choose M here: the module will be
called cyapa.
+config MOUSE_ELAN_I2C
+ tristate "ELAN I2C Touchpad support"
+ depends on I2C
+ help
+ This driver adds support for Elan I2C Trackpads.
+ Say Y here if you have a ELAN I2C Touchpad.
+
+ To compile this driver as a module, choose M here: the module will be
+ called elan_i2c.
+
config MOUSE_INPORT
tristate "InPort/MS/ATIXL busmouse"
depends on ISA
diff --git a/drivers/input/mouse/Makefile b/drivers/input/mouse/Makefile
index c25efdb..24a12a6 100644
--- a/drivers/input/mouse/Makefile
+++ b/drivers/input/mouse/Makefile
@@ -9,6 +9,7 @@ obj-$(CONFIG_MOUSE_APPLETOUCH) += appletouch.o
obj-$(CONFIG_MOUSE_ATARI) += atarimouse.o
obj-$(CONFIG_MOUSE_BCM5974) += bcm5974.o
obj-$(CONFIG_MOUSE_CYAPA) += cyapa.o
+obj-$(CONFIG_MOUSE_ELAN_I2C) += elan_i2c.o
obj-$(CONFIG_MOUSE_GPIO) += gpio_mouse.o
obj-$(CONFIG_MOUSE_INPORT) += inport.o
obj-$(CONFIG_MOUSE_LOGIBM) += logibm.o
diff --git a/drivers/input/mouse/elan_i2c.c b/drivers/input/mouse/elan_i2c.c
new file mode 100644
index 0000000..a5a11bb
--- /dev/null
+++ b/drivers/input/mouse/elan_i2c.c
@@ -0,0 +1,908 @@
+/*
+ * Elan I2C/SMBus Touchpad driver
+ *
+ * Copyright (c) 2013 ELAN Microelectronics Corp.
+ *
+ * Author: 林政維 (Duson Lin) <dusonlin@emc.com.tw>
+ * Version: 1.4.6
+ *
+ * Based on cyapa driver:
+ * copyright (c) 2011-2012 Cypress Semiconductor, Inc.
+ * copyright (c) 2011-2012 Google, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published
+ * by the Free Software Foundation.
+ *
+ * Trademarks are the property of their respective owners.
+ */
+
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/firmware.h>
+#include <linux/i2c.h>
+#include <linux/init.h>
+#include <linux/input/mt.h>
+#include <linux/interrupt.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/debugfs.h>
+#include <linux/cdev.h>
+#include <linux/kernel.h>
+#include <linux/major.h>
+#include <linux/sched.h>
+#include <linux/input.h>
+#include <linux/uaccess.h>
+#include <linux/jiffies.h>
+
+#define DRIVER_NAME "elan_i2c"
+#define ELAN_DRIVER_VERSION "1.4.6"
+#define ETP_PRESSURE_OFFSET 25
+#define ETP_MAX_PRESSURE 255
+#define ETP_FWIDTH_REDUCE 90
+#define ETP_FINGER_WIDTH 15
+
+#define ELAN_ADAPTER_FUNC_NONE 0
+#define ELAN_ADAPTER_FUNC_I2C 1
+#define ELAN_ADAPTER_FUNC_SMBUS 2
+#define ELAN_ADAPTER_FUNC_BOTH 3
+
+/* Length of Elan touchpad information */
+#define ETP_INF_LENGTH 2
+#define ETP_MAX_FINGERS 5
+#define ETP_FINGER_DATA_LEN 5
+#define ETP_REPORT_ID 0x5D
+#define ETP_MAX_REPORT_LEN 34
+#define ETP_ENABLE_ABS 0x0001
+#define ETP_ENABLE_CALIBRATE 0x0002
+#define ETP_DISABLE_CALIBRATE 0x0000
+
+/* Elan smbus command */
+#define ETP_SMBUS_IAP_CMD 0x00
+#define ETP_SMBUS_ENABLE_TP 0x20
+#define ETP_SMBUS_SLEEP_CMD 0x21
+#define ETP_SMBUS_IAP_PASSWORD_WRITE 0x29
+#define ETP_SMBUS_IAP_PASSWORD_READ 0x80
+#define ETP_SMBUS_WRITE_FW_BLOCK 0x2A
+#define ETP_SMBUS_IAP_RESET_CMD 0x2B
+#define ETP_SMBUS_RANGE_CMD 0xA0
+#define ETP_SMBUS_FW_VERSION_CMD 0xA1
+#define ETP_SMBUS_XY_TRACENUM_CMD 0xA2
+#define ETP_SMBUS_SM_VERSION_CMD 0xA3
+#define ETP_SMBUS_UNIQUEID_CMD 0xA3
+#define ETP_SMBUS_RESOLUTION_CMD 0xA4
+#define ETP_SMBUS_HELLOPACKET_CMD 0xA7
+#define ETP_SMBUS_PACKET_QUERY 0xA8
+#define ETP_SMBUS_IAP_VERSION_CMD 0xAC
+#define ETP_SMBUS_IAP_CTRL_CMD 0xAD
+#define ETP_SMBUS_IAP_CHECKSUM_CMD 0xAE
+#define ETP_SMBUS_FW_CHECKSUM_CMD 0xAF
+#define ETP_SMBUS_MAX_BASELINE_CMD 0xC3
+#define ETP_SMBUS_MIN_BASELINE_CMD 0xC4
+#define ETP_SMBUS_CALIBRATE_QUERY 0xC5
+#define ETP_SMBUS_REPORT_LEN 32
+#define ETP_SMBUS_FINGER_DATA_OFFSET 2
+#define ETP_SMBUS_HELLOPACKET_LEN 5
+#define ETP_SMBUS_IAP_PASSWORD 0x1234
+#define ETP_SMBUS_IAP_MODE_ON (1<<6)
+
+/* Elan i2c command */
+#define ETP_I2C_RESET 0x0100
+#define ETP_I2C_WAKE_UP 0x0800
+#define ETP_I2C_SLEEP 0x0801
+#define ETP_I2C_DESC_CMD 0x0001
+#define ETP_I2C_REPORT_DESC_CMD 0x0002
+#define ETP_I2C_STAND_CMD 0x0005
+#define ETP_I2C_UNIQUEID_CMD 0x0101
+#define ETP_I2C_FW_VERSION_CMD 0x0102
+#define ETP_I2C_SM_VERSION_CMD 0x0103
+#define ETP_I2C_XY_TRACENUM_CMD 0x0105
+#define ETP_I2C_MAX_X_AXIS_CMD 0x0106
+#define ETP_I2C_MAX_Y_AXIS_CMD 0x0107
+#define ETP_I2C_RESOLUTION_CMD 0x0108
+#define ETP_I2C_IAP_VERSION_CMD 0x0110
+#define ETP_I2C_SET_CMD 0x0300
+#define ETP_I2C_MAX_BASELINE_CMD 0x0306
+#define ETP_I2C_MIN_BASELINE_CMD 0x0307
+#define ETP_I2C_FW_CHECKSUM_CMD 0x030F
+#define ETP_I2C_IAP_CTRL_CMD 0x0310
+#define ETP_I2C_IAP_CMD 0x0311
+#define ETP_I2C_IAP_RESET_CMD 0x0314
+#define ETP_I2C_IAP_CHECKSUM_CMD 0x0315
+#define ETP_I2C_CALIBRATE_CMD 0x0316
+#define ETP_I2C_REPORT_LEN 34
+#define ETP_I2C_FINGER_DATA_OFFSET 4
+#define ETP_I2C_REPORT_ID_OFFSET 2
+#define ETP_I2C_DESC_LENGTH 30
+#define ETP_I2C_REPORT_DESC_LENGTH 158
+#define ETP_I2C_IAP_PASSWORD 0x1EA5
+#define ETP_I2C_IAP_RESET 0xF0F0
+#define ETP_I2C_MAIN_MODE_ON (1<<9)
+#define ETP_I2C_IAP_REG_L 0x01
+#define ETP_I2C_IAP_REG_H 0x06
+
+/* The main device structure */
+struct elan_tp_data {
+ struct i2c_client *client;
+ struct input_dev *input;
+ unsigned int max_x;
+ unsigned int max_y;
+ unsigned int width_x;
+ unsigned int width_y;
+ unsigned int irq;
+ u16 unique_id;
+ u16 fw_version;
+ u16 sm_version;
+ u16 iap_version;
+ bool smbus;
+};
+
+/*
+ *******************************************************************
+ * Elan smbus interface
+ *******************************************************************
+ */
+static int elan_smbus_initialize(struct i2c_client *client)
+{
+ u8 check[ETP_SMBUS_HELLOPACKET_LEN] = {0x55, 0x55, 0x55, 0x55, 0x55};
+ u8 values[ETP_SMBUS_HELLOPACKET_LEN] = {0, 0, 0, 0, 0};
+ int ret;
+
+ /* Get hello packet */
+ ret = i2c_smbus_read_block_data(client,
+ ETP_SMBUS_HELLOPACKET_CMD, values);
+ if (ret != ETP_SMBUS_HELLOPACKET_LEN) {
+ dev_err(&client->dev, "hello packet length fail\n");
+ return -1;
+ }
+
+ /* compare hello packet */
+ if (memcmp(values, check, ETP_SMBUS_HELLOPACKET_LEN)) {
+ dev_err(&client->dev, "hello packet fail [%x %x %x %x %x]\n",
+ values[0], values[1], values[2], values[3], values[4]);
+ return -1;
+ }
+
+ /* enable tp */
+ ret = i2c_smbus_write_byte(client, ETP_SMBUS_ENABLE_TP);
+ return ret;
+}
+
+static int elan_smbus_enable_absolute_mode(struct i2c_client *client)
+{
+ u8 cmd[4] = {0x00, 0x07, 0x00, ETP_ENABLE_ABS};
+
+ return i2c_smbus_write_block_data(client, ETP_SMBUS_IAP_CMD, 4, cmd);
+}
+
+/*
+ ******************************************************************
+ * Elan i2c interface
+ ******************************************************************
+ */
+static int elan_i2c_read_block(struct i2c_client *client,
+ u16 reg, u8 *val, u16 len)
+{
+ struct i2c_msg msgs[2];
+ u8 buf[2];
+ int ret;
+
+ buf[0] = reg & 0xff;
+ buf[1] = (reg >> 8) & 0xff;
+
+ msgs[0].addr = client->addr;
+ msgs[0].flags = client->flags & I2C_M_TEN;
+ msgs[0].len = 2;
+ msgs[0].buf = buf;
+
+ msgs[1].addr = client->addr;
+ msgs[1].flags = client->flags & I2C_M_TEN;
+ msgs[1].flags |= I2C_M_RD;
+ msgs[1].len = len;
+ msgs[1].buf = val;
+
+ ret = i2c_transfer(client->adapter, msgs, 2);
+ return ret != 2 ? -EIO : 0;
+}
+
+static int elan_i2c_read_cmd(struct i2c_client *client, u16 reg, u8 *val)
+{
+ int retval;
+
+ retval = elan_i2c_read_block(client, reg, val, ETP_INF_LENGTH);
+ if (retval < 0) {
+ dev_err(&client->dev, "reading cmd (0x%04x) fail.\n", reg);
+ return retval;
+ }
+ return 0;
+}
+
+static int elan_i2c_write_cmd(struct i2c_client *client, u16 reg, u16 cmd)
+{
+ struct i2c_msg msg;
+ u8 buf[4];
+ int ret;
+
+ buf[0] = reg & 0xff;
+ buf[1] = (reg >> 8) & 0xff;
+ buf[2] = cmd & 0xff;
+ buf[3] = (cmd >> 8) & 0xff;
+
+ msg.addr = client->addr;
+ msg.flags = client->flags & I2C_M_TEN;
+ msg.len = 4;
+ msg.buf = buf;
+
+ ret = i2c_transfer(client->adapter, &msg, 1);
+ return ret != 1 ? -EIO : 0;
+}
+
+static int elan_i2c_reset(struct i2c_client *client)
+{
+ return elan_i2c_write_cmd(client, ETP_I2C_STAND_CMD,
+ ETP_I2C_RESET);
+}
+
+static int elan_i2c_wake_up(struct i2c_client *client)
+{
+ return elan_i2c_write_cmd(client, ETP_I2C_STAND_CMD,
+ ETP_I2C_WAKE_UP);
+}
+
+static int elan_i2c_sleep(struct i2c_client *client)
+{
+ return elan_i2c_write_cmd(client, ETP_I2C_STAND_CMD,
+ ETP_I2C_SLEEP);
+}
+
+static int elan_i2c_enable_absolute_mode(struct i2c_client *client)
+{
+ return elan_i2c_write_cmd(client, ETP_I2C_SET_CMD,
+ ETP_ENABLE_ABS);
+}
+
+static int elan_i2c_get_desc(struct i2c_client *client, u8 *val)
+{
+ return elan_i2c_read_block(client, ETP_I2C_DESC_CMD, val,
+ ETP_I2C_DESC_LENGTH);
+}
+
+static int elan_i2c_get_report_desc(struct i2c_client *client, u8 *val)
+{
+ return elan_i2c_read_block(client, ETP_I2C_REPORT_DESC_CMD,
+ val, ETP_I2C_REPORT_DESC_LENGTH);
+}
+
+static int elan_i2c_initialize(struct i2c_client *client)
+{
+ struct device *dev = &client->dev;
+ int rc;
+ u8 val[256];
+
+ rc = elan_i2c_reset(client);
+ if (rc < 0) {
+ dev_err(dev, "device reset failed.\n");
+ return -1;
+ }
+
+ /* wait for get reset return flag */
+ msleep(100);
+ /* get reset return flag 0000 */
+ rc = i2c_master_recv(client, val, ETP_INF_LENGTH);
+ if (rc < 0) {
+ dev_err(dev, "get device reset return value failed.\n");
+ return -1;
+ }
+
+ rc = elan_i2c_get_desc(client, val);
+ if (rc < 0) {
+ dev_err(dev, "cannot get device descriptor.\n");
+ return -1;
+ }
+
+ rc = elan_i2c_get_report_desc(client, val);
+ if (rc < 0) {
+ dev_err(dev, "fetching report descriptor failed.\n");
+ return -1;
+ }
+ return 0;
+}
+
+/*
+ ******************************************************************
+ * General functions
+ ******************************************************************
+ */
+/*
+ * (value from firmware) * 10 + 790 = dpi
+ * we also have to convert dpi to dots/mm (*10/254 to avoid floating point)
+ */
+static unsigned int elan_convert_res(char val)
+{
+ int res;
+ if (val & 0x80) {
+ val = ~val + 1;
+ res = (790 - val * 10) * 10 / 254;
+ } else
+ res = (val * 10 + 790) * 10 / 254;
+ return res;
+}
+
+static int elan_get_iap_version(struct elan_tp_data *data)
+{
+ int ret;
+ u8 val[3];
+ if (data->smbus) {
+ i2c_smbus_read_block_data(data->client,
+ ETP_SMBUS_IAP_VERSION_CMD, val);
+ ret = val[2];
+ } else {
+ elan_i2c_read_cmd(data->client,
+ ETP_I2C_IAP_VERSION_CMD, val);
+ ret = val[0];
+ }
+ return ret;
+}
+
+static int elan_get_x_max(struct elan_tp_data *data)
+{
+ int ret;
+ u8 val[3];
+ if (data->smbus) {
+ i2c_smbus_read_block_data(data->client,
+ ETP_SMBUS_RANGE_CMD, val);
+ ret = (0x0f & val[0]) << 8 | val[1];
+ } else {
+ elan_i2c_read_cmd(data->client,
+ ETP_I2C_MAX_X_AXIS_CMD, val);
+ ret = (0x0f & val[1]) << 8 | val[0];
+ }
+ return ret;
+}
+
+static int elan_get_y_max(struct elan_tp_data *data)
+{
+ int ret;
+ u8 val[3];
+ if (data->smbus) {
+ i2c_smbus_read_block_data(data->client,
+ ETP_SMBUS_RANGE_CMD, val);
+ ret = (0xf0 & val[0]) << 4 | val[2];
+ } else {
+ elan_i2c_read_cmd(data->client,
+ ETP_I2C_MAX_Y_AXIS_CMD, val);
+ ret = (0x0f & val[1]) << 8 | val[0];
+ }
+ return ret;
+}
+
+static int elan_get_x_tracenum(struct elan_tp_data *data)
+{
+ int ret;
+ u8 val[3];
+ if (data->smbus) {
+ i2c_smbus_read_block_data(data->client,
+ ETP_SMBUS_XY_TRACENUM_CMD, val);
+ ret = (val[1] - 1);
+ } else {
+ elan_i2c_read_cmd(data->client,
+ ETP_I2C_XY_TRACENUM_CMD, val);
+ ret = (val[0] - 1);
+ }
+ return ret;
+}
+
+static int elan_get_y_tracenum(struct elan_tp_data *data)
+{
+ int ret;
+ u8 val[3];
+ if (data->smbus) {
+ i2c_smbus_read_block_data(data->client,
+ ETP_SMBUS_XY_TRACENUM_CMD, val);
+ ret = (val[2] - 1);
+ } else {
+ ret = elan_i2c_read_cmd(data->client,
+ ETP_I2C_XY_TRACENUM_CMD, val);
+ ret = (val[1] - 1);
+ }
+ return ret;
+}
+
+static int elan_get_fw_version(struct elan_tp_data *data)
+{
+ int ret;
+ u8 val[3];
+ if (data->smbus) {
+ i2c_smbus_read_block_data(data->client,
+ ETP_SMBUS_FW_VERSION_CMD, val);
+ ret = val[2];
+ } else {
+ elan_i2c_read_cmd(data->client,
+ ETP_I2C_FW_VERSION_CMD, val);
+ ret = val[0];
+ }
+ return ret;
+}
+
+static int elan_get_sm_version(struct elan_tp_data *data)
+{
+ int ret;
+ u8 val[3];
+ if (data->smbus)
+ i2c_smbus_read_block_data(data->client,
+ ETP_SMBUS_SM_VERSION_CMD, val);
+ else
+ elan_i2c_read_block(data->client,
+ ETP_I2C_SM_VERSION_CMD, val, 1);
+ ret = val[0];
+ return ret;
+}
+
+static int elan_get_unique_id(struct elan_tp_data *data)
+{
+ int ret;
+ u8 val[3];
+ if (data->smbus) {
+ i2c_smbus_read_block_data(data->client,
+ ETP_SMBUS_UNIQUEID_CMD, val);
+ ret = val[1];
+ } else {
+ elan_i2c_read_cmd(data->client,
+ ETP_I2C_UNIQUEID_CMD, val);
+ ret = val[0];
+ }
+ return ret;
+}
+
+static int elan_get_x_resolution(struct elan_tp_data *data)
+{
+ int ret;
+ u8 val[3];
+ if (data->smbus) {
+ i2c_smbus_read_block_data(data->client,
+ ETP_SMBUS_RESOLUTION_CMD, val);
+ ret = elan_convert_res(val[1] & 0x0F);
+ } else {
+ elan_i2c_read_cmd(data->client,
+ ETP_I2C_RESOLUTION_CMD, val);
+ ret = elan_convert_res(val[0]);
+ }
+ return ret;
+}
+
+static int elan_get_y_resolution(struct elan_tp_data *data)
+{
+ int ret;
+ u8 val[3];
+ if (data->smbus) {
+ i2c_smbus_read_block_data(data->client,
+ ETP_SMBUS_RESOLUTION_CMD, val);
+ ret = elan_convert_res((val[1] & 0xF0) >> 4);
+ } else {
+ elan_i2c_read_cmd(data->client,
+ ETP_I2C_RESOLUTION_CMD, val);
+ ret = elan_convert_res(val[1]);
+ }
+ return ret;
+}
+
+static int elan_initialize(struct elan_tp_data *data)
+{
+ int ret;
+ if (data->smbus) {
+ ret = elan_smbus_initialize(data->client);
+ if (ret < 0) {
+ dev_err(&data->client->dev,
+ "device initialize failed.\n");
+ goto err_initialize;
+ }
+
+ ret = elan_smbus_enable_absolute_mode(data->client);
+ if (ret < 0)
+ dev_err(&data->client->dev,
+ "cannot switch to absolute mode.\n");
+ } else {
+ ret = elan_i2c_initialize(data->client);
+ if (ret < 0) {
+ dev_err(&data->client->dev,
+ "device initialize failed.\n");
+ goto err_initialize;
+ }
+
+ ret = elan_i2c_enable_absolute_mode(data->client);
+ if (ret < 0) {
+ dev_err(&data->client->dev,
+ "cannot switch to absolute mode.\n");
+ goto err_initialize;
+ }
+
+ ret = elan_i2c_wake_up(data->client);
+ if (ret < 0)
+ dev_err(&data->client->dev,
+ "device wake up failed.\n");
+ }
+err_initialize:
+ return ret;
+}
+
+
+/*
+ ******************************************************************
+ * Elan isr functions
+ ******************************************************************
+ */
+static int elan_check_packet(struct elan_tp_data *data, u8 *packet)
+{
+ u8 rid;
+
+ if (data->smbus)
+ rid = packet[0];
+ else
+ rid = packet[ETP_I2C_REPORT_ID_OFFSET];
+
+ /* check report id */
+ if (rid != ETP_REPORT_ID) {
+ dev_err(&data->client->dev, "report id [%x] fail.\n", rid);
+ return -1;
+ }
+ return 0;
+}
+
+static void elan_report_absolute(struct elan_tp_data *data, u8 *packet)
+{
+ struct input_dev *input = data->input;
+ u8 *finger_data;
+ bool finger_on;
+ int pos_x, pos_y;
+ int pressure, mk_x, mk_y;
+ int i, area_x, area_y, major, minor, new_pressure;
+ int finger_count = 0;
+ int btn_click;
+ u8 tp_info;
+
+ if (data->smbus) {
+ finger_data = &packet[ETP_SMBUS_FINGER_DATA_OFFSET];
+ tp_info = packet[1];
+ } else {
+ finger_data = &packet[ETP_I2C_FINGER_DATA_OFFSET];
+ tp_info = packet[3];
+ }
+
+ btn_click = (tp_info & 0x01);
+ for (i = 0; i < ETP_MAX_FINGERS; i++) {
+ finger_on = (tp_info >> (3 + i)) & 0x01;
+
+ /* analyze touched finger raw data*/
+ if (finger_on) {
+ pos_x = ((finger_data[0] & 0xf0) << 4) |
+ finger_data[1];
+ pos_y = ((finger_data[0] & 0x0f) << 8) |
+ finger_data[2];
+ pos_y = data->max_y - pos_y;
+ mk_x = (finger_data[3] & 0x0f);
+ mk_y = (finger_data[3] >> 4);
+ pressure = finger_data[4];
+
+ /*
+ * to avoid fat finger be as palm, so reduce the
+ * width x and y per trace
+ */
+ area_x = mk_x * (data->width_x - ETP_FWIDTH_REDUCE);
+ area_y = mk_y * (data->width_y - ETP_FWIDTH_REDUCE);
+
+ major = max(area_x, area_y);
+ minor = min(area_x, area_y);
+
+ new_pressure = pressure + ETP_PRESSURE_OFFSET;
+ if (new_pressure > ETP_MAX_PRESSURE)
+ new_pressure = ETP_MAX_PRESSURE;
+
+ input_mt_slot(input, i);
+ input_mt_report_slot_state(input, MT_TOOL_FINGER,
+ true);
+ input_report_abs(input, ABS_MT_POSITION_X, pos_x);
+ input_report_abs(input, ABS_MT_POSITION_Y, pos_y);
+ input_report_abs(input, ABS_MT_PRESSURE, new_pressure);
+ input_report_abs(input, ABS_TOOL_WIDTH, mk_x);
+ input_report_abs(input, ABS_MT_TOUCH_MAJOR, major);
+ input_report_abs(input, ABS_MT_TOUCH_MINOR, minor);
+ finger_data += ETP_FINGER_DATA_LEN;
+ finger_count++;
+ } else {
+ input_mt_slot(input, i);
+ input_mt_report_slot_state(input,
+ MT_TOOL_FINGER, false);
+ }
+ }
+
+ input_report_key(input, BTN_LEFT, (btn_click == 1));
+ input_mt_report_pointer_emulation(input, true);
+ input_sync(input);
+}
+
+static irqreturn_t elan_isr(int irq, void *dev_id)
+{
+ struct elan_tp_data *data = dev_id;
+ u8 raw[ETP_MAX_REPORT_LEN];
+ int retval;
+ int report_len;
+
+ if (data->smbus) {
+ report_len = ETP_SMBUS_REPORT_LEN;
+ retval = i2c_smbus_read_block_data(data->client,
+ ETP_SMBUS_PACKET_QUERY,
+ raw);
+ } else {
+ report_len = ETP_I2C_REPORT_LEN;
+ retval = i2c_master_recv(data->client, raw, report_len);
+ }
+
+ if (retval != report_len) {
+ dev_err(&data->client->dev, "wrong packet len(%d)", retval);
+ goto elan_isr_end;
+ }
+
+ if (elan_check_packet(data, raw) < 0) {
+ dev_err(&data->client->dev, "wrong packet format.");
+ goto elan_isr_end;
+ }
+ elan_report_absolute(data, raw);
+
+elan_isr_end:
+ return IRQ_HANDLED;
+}
+
+/*
+ ******************************************************************
+ * Elan initial functions
+ ******************************************************************
+ */
+static int elan_input_dev_create(struct elan_tp_data *data)
+{
+ struct i2c_client *client = data->client;
+ struct input_dev *input;
+ unsigned int x_res, y_res;
+ int ret, max_width, min_width;
+
+ data->input = input = input_allocate_device();
+ if (!input)
+ return -ENOMEM;
+ input->name = "Elan Touchpad";
+ input->id.bustype = BUS_I2C;
+ input->dev.parent = &data->client->dev;
+
+ __set_bit(EV_ABS, input->evbit);
+ __set_bit(INPUT_PROP_BUTTONPAD, input->propbit);
+ __set_bit(BTN_LEFT, input->keybit);
+
+ data->unique_id = elan_get_unique_id(data);
+ data->fw_version = elan_get_fw_version(data);
+ data->sm_version = elan_get_sm_version(data);
+ data->iap_version = elan_get_iap_version(data);
+ data->max_x = elan_get_x_max(data);
+ data->max_y = elan_get_y_max(data);
+ data->width_x = data->max_x / elan_get_x_tracenum(data);
+ data->width_y = data->max_y / elan_get_y_tracenum(data);
+ x_res = elan_get_x_resolution(data);
+ y_res = elan_get_y_resolution(data);
+ max_width = max(data->width_x, data->width_y);
+ min_width = min(data->width_x, data->width_y);
+
+ dev_dbg(&client->dev,
+ "Elan Touchpad Information:\n"
+ " Module unique ID: 0x%04x\n"
+ " Firmware Version: 0x%04x\n"
+ " Sample Version: 0x%04x\n"
+ " IAP Version: 0x%04x\n"
+ " Max ABS X,Y: %d,%d\n"
+ " Width X,Y: %d,%d\n"
+ " Resolution X,Y: %d,%d (dots/mm)\n",
+ data->unique_id,
+ data->fw_version,
+ data->sm_version,
+ data->iap_version,
+ data->max_x, data->max_y,
+ data->width_x, data->width_y,
+ (char)x_res, (char)y_res);
+
+ input_set_abs_params(input, ABS_X, 0, data->max_x, 0, 0);
+ input_set_abs_params(input, ABS_Y, 0, data->max_y, 0, 0);
+ input_abs_set_res(input, ABS_X, x_res);
+ input_abs_set_res(input, ABS_Y, y_res);
+ input_set_abs_params(input, ABS_PRESSURE, 0, ETP_MAX_PRESSURE, 0, 0);
+ input_set_abs_params(input, ABS_TOOL_WIDTH, 0, ETP_FINGER_WIDTH, 0, 0);
+
+ /* handle pointer emulation and unused slots in core */
+ ret = input_mt_init_slots(input, ETP_MAX_FINGERS,
+ INPUT_MT_POINTER | INPUT_MT_DROP_UNUSED);
+ if (ret) {
+ dev_err(&client->dev, "allocate MT slots failed, %d\n", ret);
+ goto err_free_device;
+ }
+ input_set_abs_params(input, ABS_MT_POSITION_X, 0, data->max_x, 0, 0);
+ input_set_abs_params(input, ABS_MT_POSITION_Y, 0, data->max_y, 0, 0);
+ input_abs_set_res(input, ABS_MT_POSITION_X, x_res);
+ input_abs_set_res(input, ABS_MT_POSITION_Y, y_res);
+ input_set_abs_params(input, ABS_MT_PRESSURE, 0,
+ ETP_MAX_PRESSURE, 0, 0);
+ input_set_abs_params(input, ABS_MT_TOUCH_MAJOR, 0,
+ ETP_FINGER_WIDTH * max_width, 0, 0);
+ input_set_abs_params(input, ABS_MT_TOUCH_MINOR, 0,
+ ETP_FINGER_WIDTH * min_width, 0, 0);
+
+ /* Register the device in input subsystem */
+ ret = input_register_device(input);
+ if (ret) {
+ dev_err(&client->dev, "input_dev register failed, %d\n", ret);
+ goto err_free_device;
+ }
+
+ return 0;
+
+err_free_device:
+ input_free_device(input);
+ return ret;
+}
+
+static u8 elan_check_adapter_functionality(struct i2c_client *client)
+{
+ u8 ret = ELAN_ADAPTER_FUNC_NONE;
+
+ if (i2c_check_functionality(client->adapter, I2C_FUNC_I2C))
+ ret |= ELAN_ADAPTER_FUNC_I2C;
+ if (i2c_check_functionality(client->adapter,
+ I2C_FUNC_SMBUS_BYTE_DATA |
+ I2C_FUNC_SMBUS_BLOCK_DATA |
+ I2C_FUNC_SMBUS_I2C_BLOCK))
+ ret |= ELAN_ADAPTER_FUNC_SMBUS;
+ return ret;
+}
+
+static int elan_probe(struct i2c_client *client,
+ const struct i2c_device_id *dev_id)
+{
+ struct elan_tp_data *data;
+ int ret;
+ u8 adapter_func;
+ union i2c_smbus_data dummy;
+ struct device *dev = &client->dev;
+
+ adapter_func = elan_check_adapter_functionality(client);
+ if (adapter_func == ELAN_ADAPTER_FUNC_NONE) {
+ dev_err(dev, "not a supported I2C/SMBus adapter\n");
+ return -EIO;
+ }
+
+ /* Make sure there is something at this address */
+ if (i2c_smbus_xfer(client->adapter, client->addr, 0,
+ I2C_SMBUS_READ, 0, I2C_SMBUS_BYTE, &dummy) < 0)
+ return -ENODEV;
+
+ data = kzalloc(sizeof(struct elan_tp_data), GFP_KERNEL);
+ if (!data)
+ return -ENOMEM;
+
+ /* check protocol type */
+ if (adapter_func == ELAN_ADAPTER_FUNC_SMBUS)
+ data->smbus = true;
+ else
+ data->smbus = false;
+ data->client = client;
+ data->irq = client->irq;
+
+ ret = request_threaded_irq(client->irq, NULL, elan_isr,
+ IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
+ client->name, data);
+ if (ret < 0) {
+ dev_err(&client->dev, "cannot register irq=%d\n",
+ client->irq);
+ goto err_irq;
+ }
+
+ /* initial elan touch pad */
+ ret = elan_initialize(data);
+ if (ret < 0)
+ goto err_init;
+
+ /* create input device */
+ ret = elan_input_dev_create(data);
+ if (ret < 0)
+ goto err_input_dev;
+
+ device_init_wakeup(&client->dev, 1);
+ i2c_set_clientdata(client, data);
+ return 0;
+
+err_input_dev:
+err_init:
+ free_irq(data->irq, data);
+err_irq:
+ kfree(data);
+ dev_err(&client->dev, "Elan Trackpad probe fail!\n");
+ return ret;
+}
+
+static int elan_remove(struct i2c_client *client)
+{
+ struct elan_tp_data *data = i2c_get_clientdata(client);
+ free_irq(data->irq, data);
+ input_free_device(data->input);
+ input_unregister_device(data->input);
+ kfree(data);
+ return 0;
+}
+
+#ifdef CONFIG_PM_SLEEP
+static int elan_suspend(struct device *dev)
+{
+ int ret = 0;
+ struct elan_tp_data *data = dev_get_drvdata(dev);
+
+ disable_irq(data->irq);
+ if (data->smbus)
+ ret = i2c_smbus_write_byte(data->client,
+ ETP_SMBUS_SLEEP_CMD);
+ else
+ ret = elan_i2c_sleep(data->client);
+
+ if (ret < 0)
+ dev_err(dev, "suspend mode failed, %d\n", ret);
+
+ return ret;
+}
+
+static int elan_resume(struct device *dev)
+{
+ int ret = 0;
+ struct elan_tp_data *data = dev_get_drvdata(dev);
+
+ ret = elan_initialize(data);
+ if (ret < 0)
+ dev_err(dev, "resume active power failed, %d\n", ret);
+
+ enable_irq(data->irq);
+ return ret;
+}
+#endif
+
+static SIMPLE_DEV_PM_OPS(elan_pm_ops, elan_suspend, elan_resume);
+
+static const struct i2c_device_id elan_id[] = {
+ { DRIVER_NAME, 0 },
+ { },
+};
+MODULE_DEVICE_TABLE(i2c, elan_id);
+
+static struct i2c_driver elan_driver = {
+ .driver = {
+ .name = DRIVER_NAME,
+ .owner = THIS_MODULE,
+ .pm = &elan_pm_ops,
+ },
+ .probe = elan_probe,
+ .remove = elan_remove,
+ .id_table = elan_id,
+};
+
+
+static int __init elan_init(void)
+{
+ int ret;
+ ret = i2c_add_driver(&elan_driver);
+ if (ret)
+ pr_err("elan driver register FAILED.\n");
+
+ return ret;
+}
+
+static void __exit elan_exit(void)
+{
+ i2c_del_driver(&elan_driver);
+}
+
+module_init(elan_init);
+module_exit(elan_exit);
+
+MODULE_AUTHOR("Duson Lin <dusonlin@emc.com.tw>");
+MODULE_DESCRIPTION("Elan I2C/SMBus Touchpad driver");
+MODULE_LICENSE("GPL");
--
1.7.10.4
--
To unsubscribe from this list: send the line "unsubscribe linux-input" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply related
* Re: [v3.11][Regression] HID: hyperv: convert alloc+memcpy to memdup
From: Jiri Kosina @ 2013-12-16 13:01 UTC (permalink / raw)
To: Joseph Salisbury
Cc: Dan Carpenter, thomas, list, Haiyang Zhang, LKML, open,
HID CORE LAYER, devel
In-Reply-To: <52459942.3020600@canonical.com>
On Fri, 27 Sep 2013, Joseph Salisbury wrote:
> >> commit b1a1442a23776756b254b69786848a94d92445ba
> >> Author: Jiri Kosina <jkosina@suse.cz>
> >> Date: Mon Jun 3 11:27:48 2013 +0200
> >>
> >> HID: core: fix reporting of raw events
> >>
> >> Reverting this commit in v3.12-rc2 prevents the system from locking up,
> >> which happens when connecting a bluetooth trackpad.
> >>
> >> Jiri, do you think we should revert this patch, or is there some further
> >> debugging/data collecting you would like to do?
> > Hi Joseph,
> >
> > in this mail:
> >
> > Message-ID: <5241992E.3090805@canonical.com>
> > Date: Tue, 24 Sep 2013 09:52:46 -0400
> >
> > you said that reverting this commit doesn't prevent the lockups, so I am
> > rather confused ... ?
> >
> > Thanks,
> >
> The testing was invalid. Reverting commit b1a1442 does resolve the bug
> and stop the lockups.
Okay, I finally got some sense of this, sorry for the delay.
Could you please test with the patch below, instead of reverting
b1a1442a23? Thanks a lot.
diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c
index 253fe23..81eacd3 100644
--- a/drivers/hid/hid-core.c
+++ b/drivers/hid/hid-core.c
@@ -1334,7 +1334,7 @@ int hid_report_raw_event(struct hid_device *hid, int type, u8 *data, int size,
csize--;
}
- rsize = ((report->size - 1) >> 3) + 1;
+ rsize = ((report->size - 1) >> 3) + 1 + (report->id > 0) + 7;
if (rsize > HID_MAX_BUFFER_SIZE)
rsize = HID_MAX_BUFFER_SIZE;
--
Jiri Kosina
SUSE Labs
^ permalink raw reply related
* Re: Recent change to hid-core.c
From: Jiri Kosina @ 2013-12-16 13:24 UTC (permalink / raw)
To: Mark Lord; +Cc: linux-input
In-Reply-To: <52AD3D74.90905@pobox.com>
On Sun, 15 Dec 2013, Mark Lord wrote:
> The recent update 08ec2dcc3527a20c619aca2fb36f800908256bac
> "Merge branches 'for-3.11/multitouch', 'for-3.11/sony' and 'for-3.11/upstream' into for-linus"
> included an unexpected change to the return code handing for ->raw_event() calls.
>
> A HID driver's raw_event() method previously could return these values:
> 0 --> keep processing.
> 1 --> no further processing required.
> <0 --> error.
>
> Now, "1" and "0" are both treated as "keep processing",
> so a lower level HID driver has to return a negative error code
> to achieve the "no further processing required" state.
>
> Was this intentional? Doesn't that have side-effects for some drivers?
Hi Mark,
this was intentional -- please see commit b1a1442a23 and discussion here:
https://lkml.org/lkml/2013/3/21/591
If you have any other concerns, please let me know.
--
Jiri Kosina
SUSE Labs
^ permalink raw reply
* Re: Recent change to hid-core.c
From: Mark Lord @ 2013-12-16 14:52 UTC (permalink / raw)
To: Jiri Kosina; +Cc: linux-input
In-Reply-To: <alpine.LNX.2.00.1312161418110.12882@pobox.suse.cz>
[-- Attachment #1: Type: text/plain, Size: 1298 bytes --]
On 13-12-16 08:24 AM, Jiri Kosina wrote:
> On Sun, 15 Dec 2013, Mark Lord wrote:
>
>> The recent update 08ec2dcc3527a20c619aca2fb36f800908256bac
>> "Merge branches 'for-3.11/multitouch', 'for-3.11/sony' and 'for-3.11/upstream' into for-linus"
>> included an unexpected change to the return code handing for ->raw_event() calls.
,,
>> Was this intentional? Doesn't that have side-effects for some drivers?
..
> this was intentional -- please see commit b1a1442a23 and discussion here:
> https://lkml.org/lkml/2013/3/21/591
..
Thanks Jiri.
In that case you'll be wanting this patch (unmangled copy attached) as well
to clean up a tiny bit of leftover logic in there.
* * * * * * SNIP * * * * * *
Recent updates to raw_event handling resulted in some leftover "dead" logic
in hid-core.c::hid_input_report(). Nuke it.
Signed-off-by: Mark Lord <mlord@pobox.com>
--- old/drivers/hid/hid-core.c 2013-12-12 01:38:07.000000000 -0500
+++ linux/drivers/hid/hid-core.c 2013-12-16 09:48:27.339162173 -0500
@@ -1418,10 +1418,8 @@
if (hdrv && hdrv->raw_event && hid_match_report(hid, report)) {
ret = hdrv->raw_event(hid, report, data, size);
- if (ret < 0) {
- ret = ret < 0 ? ret : 0;
+ if (ret < 0)
goto unlock;
- }
}
ret = hid_report_raw_event(hid, type, data, size, interrupt);
[-- Attachment #2: hid_core_remove_leftover_logic.patch --]
[-- Type: text/x-patch, Size: 599 bytes --]
Recent updates to raw_event handling resulted in some leftover "dead" logic
in hid-core.c::hid_input_report(). Nuke it.
Signed-off-by: Mark Lord <mlord@pobox.com>
--- old/drivers/hid/hid-core.c 2013-12-12 01:38:07.000000000 -0500
+++ linux/drivers/hid/hid-core.c 2013-12-16 09:48:27.339162173 -0500
@@ -1418,10 +1418,8 @@
if (hdrv && hdrv->raw_event && hid_match_report(hid, report)) {
ret = hdrv->raw_event(hid, report, data, size);
- if (ret < 0) {
- ret = ret < 0 ? ret : 0;
+ if (ret < 0)
goto unlock;
- }
}
ret = hid_report_raw_event(hid, type, data, size, interrupt);
^ permalink raw reply
* Re: Recent change to hid-core.c
From: Jiri Kosina @ 2013-12-16 14:56 UTC (permalink / raw)
To: Mark Lord; +Cc: linux-input
In-Reply-To: <52AF13A4.8030900@pobox.com>
On Mon, 16 Dec 2013, Mark Lord wrote:
> >> The recent update 08ec2dcc3527a20c619aca2fb36f800908256bac
> >> "Merge branches 'for-3.11/multitouch', 'for-3.11/sony' and 'for-3.11/upstream' into for-linus"
> >> included an unexpected change to the return code handing for ->raw_event() calls.
> ,,
> >> Was this intentional? Doesn't that have side-effects for some drivers?
> ..
> > this was intentional -- please see commit b1a1442a23 and discussion here:
> > https://lkml.org/lkml/2013/3/21/591
> ..
>
> Thanks Jiri.
> In that case you'll be wanting this patch (unmangled copy attached) as well
> to clean up a tiny bit of leftover logic in there.
>
> * * * * * * SNIP * * * * * *
>
> Recent updates to raw_event handling resulted in some leftover "dead" logic
> in hid-core.c::hid_input_report(). Nuke it.
>
> Signed-off-by: Mark Lord <mlord@pobox.com>
>
> --- old/drivers/hid/hid-core.c 2013-12-12 01:38:07.000000000 -0500
> +++ linux/drivers/hid/hid-core.c 2013-12-16 09:48:27.339162173 -0500
> @@ -1418,10 +1418,8 @@
>
> if (hdrv && hdrv->raw_event && hid_match_report(hid, report)) {
> ret = hdrv->raw_event(hid, report, data, size);
> - if (ret < 0) {
> - ret = ret < 0 ? ret : 0;
> + if (ret < 0)
> goto unlock;
> - }
Please see commit 556483e2a ("HID: remove self-assignment from
hid_input_report") in Linus' tree.
--
Jiri Kosina
SUSE Labs
^ permalink raw reply
* [PATCH v3 1/2] xen/pvhvm: If xen_platform_pci=0 is set don't blow up (v3).
From: Konrad Rzeszutek Wilk @ 2013-12-16 15:04 UTC (permalink / raw)
To: axboe, stefano.stabellini, ian.campbell, xen-devel, linux-kernel,
boris.ostrovsky, david.vrabel, leosilva, ashley, peterhuewe, mail,
tpmdd, dmitry.torokhov, bhelgaas, plagnioj, tomi.valkeinen,
tpmdd-devel, linux-input, netdev, linux-pci, linux-fbdev
Cc: Konrad Rzeszutek Wilk
In-Reply-To: <1387206250-13963-1-git-send-email-konrad.wilk@oracle.com>
The user has the option of disabling the platform driver:
00:02.0 Unassigned class [ff80]: XenSource, Inc. Xen Platform Device (rev 01)
which is used to unplug the emulated drivers (IDE, Realtek 8169, etc)
and allow the PV drivers to take over. If the user wishes
to disable that they can set:
xen_platform_pci=0
(in the guest config file)
or
xen_emul_unplug=never
(on the Linux command line)
except it does not work properly. The PV drivers still try to
load and since the Xen platform driver is not run - and it
has not initialized the grant tables, most of the PV drivers
stumble upon:
input: Xen Virtual Keyboard as /devices/virtual/input/input5
input: Xen Virtual Pointer as /devices/virtual/input/input6M
------------[ cut here ]------------
kernel BUG at /home/konrad/ssd/konrad/linux/drivers/xen/grant-table.c:1206!
invalid opcode: 0000 [#1] SMP
Modules linked in: xen_kbdfront(+) xenfs xen_privcmd
CPU: 6 PID: 1389 Comm: modprobe Not tainted 3.13.0-rc1upstream-00021-ga6c892b-dirty #1
Hardware name: Xen HVM domU, BIOS 4.4-unstable 11/26/2013
RIP: 0010:[<ffffffff813ddc40>] [<ffffffff813ddc40>] get_free_entries+0x2e0/0x300
Call Trace:
[<ffffffff8150d9a3>] ? evdev_connect+0x1e3/0x240
[<ffffffff813ddd0e>] gnttab_grant_foreign_access+0x2e/0x70
[<ffffffffa0010081>] xenkbd_connect_backend+0x41/0x290 [xen_kbdfront]
[<ffffffffa0010a12>] xenkbd_probe+0x2f2/0x324 [xen_kbdfront]
[<ffffffff813e5757>] xenbus_dev_probe+0x77/0x130
[<ffffffff813e7217>] xenbus_frontend_dev_probe+0x47/0x50
[<ffffffff8145e9a9>] driver_probe_device+0x89/0x230
[<ffffffff8145ebeb>] __driver_attach+0x9b/0xa0
[<ffffffff8145eb50>] ? driver_probe_device+0x230/0x230
[<ffffffff8145eb50>] ? driver_probe_device+0x230/0x230
[<ffffffff8145cf1c>] bus_for_each_dev+0x8c/0xb0
[<ffffffff8145e7d9>] driver_attach+0x19/0x20
[<ffffffff8145e260>] bus_add_driver+0x1a0/0x220
[<ffffffff8145f1ff>] driver_register+0x5f/0xf0
[<ffffffff813e55c5>] xenbus_register_driver_common+0x15/0x20
[<ffffffff813e76b3>] xenbus_register_frontend+0x23/0x40
[<ffffffffa0015000>] ? 0xffffffffa0014fff
[<ffffffffa001502b>] xenkbd_init+0x2b/0x1000 [xen_kbdfront]
[<ffffffff81002049>] do_one_initcall+0x49/0x170
.. snip..
which is hardly nice. This patch fixes this by having each
PV driver check for:
- if running in PV, then it is fine to execute (as that is their
native environment).
- if running in HVM, check if user wanted 'xen_emul_unplug=never',
in which case bail out and don't load any PV drivers.
- if running in HVM, and if PCI device 5853:0001 (xen_platform_pci)
does not exist, then bail out and not load PV drivers.
- (v2) if running in HVM, and if the user wanted 'xen_emul_unplug=disks',
then bail out for all PV devices _except_ the block one.
Ditto for the network one ('nics').
- (v2) if running in HVM, and if the user wanted 'xen_emul_unplug=unnecessary'
then load block PV driver, and also setup the legacy IDE paths.
In (v3) make it actually load PV drivers.
Reported-by: Sander Eikelenboom <linux@eikelenboom.it
Reported-by: Anthony PERARD <anthony.perard@citrix.com>
Reported-by: Fabio Fantoni <fabio.fantoni@m2r.biz>
Signed-off-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
[v2: Add extra logic to handle the myrid ways 'xen_emul_unplug'
can be used per Ian and Stefano suggestion]
[v3: Make the unnecessary case work properly]
Reviewed-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com>
---
arch/x86/xen/platform-pci-unplug.c | 74 ++++++++++++++++++++++++++++++
drivers/block/xen-blkfront.c | 4 +-
drivers/char/tpm/xen-tpmfront.c | 4 ++
drivers/input/misc/xen-kbdfront.c | 4 ++
drivers/net/xen-netfront.c | 2 +-
drivers/pci/xen-pcifront.c | 4 ++
drivers/video/xen-fbfront.c | 4 ++
drivers/xen/xenbus/xenbus_probe_frontend.c | 2 +-
include/xen/platform_pci.h | 23 ++++++++++
9 files changed, 117 insertions(+), 4 deletions(-)
diff --git a/arch/x86/xen/platform-pci-unplug.c b/arch/x86/xen/platform-pci-unplug.c
index 0a78524..ab84ac1 100644
--- a/arch/x86/xen/platform-pci-unplug.c
+++ b/arch/x86/xen/platform-pci-unplug.c
@@ -69,6 +69,80 @@ static int check_platform_magic(void)
return 0;
}
+bool xen_has_pv_devices()
+{
+ if (!xen_domain())
+ return false;
+
+ /* PV domains always have them. */
+ if (xen_pv_domain())
+ return true;
+
+ /* And user has xen_platform_pci=0 set in guest config as
+ * driver did not modify the value. */
+ if (xen_platform_pci_unplug == 0)
+ return false;
+
+ if (xen_platform_pci_unplug & XEN_UNPLUG_NEVER)
+ return false;
+
+ if (xen_platform_pci_unplug & XEN_UNPLUG_ALL)
+ return true;
+
+ /* This is an odd one - we are going to run legacy
+ * and PV drivers at the same time. */
+ if (xen_platform_pci_unplug & XEN_UNPLUG_UNNECESSARY)
+ return true;
+
+ /* And the caller has to follow with xen_pv_{disk,nic}_devices
+ * to be certain which driver can load. */
+ return false;
+}
+EXPORT_SYMBOL_GPL(xen_has_pv_devices);
+
+static bool __xen_has_pv_device(int state)
+{
+ /* HVM domains might or might not */
+ if (xen_hvm_domain() && (xen_platform_pci_unplug & state))
+ return true;
+
+ return xen_has_pv_devices();
+}
+
+bool xen_has_pv_nic_devices(void)
+{
+ return __xen_has_pv_device(XEN_UNPLUG_ALL_NICS | XEN_UNPLUG_ALL);
+}
+EXPORT_SYMBOL_GPL(xen_has_pv_nic_devices);
+
+bool xen_has_pv_disk_devices(void)
+{
+ return __xen_has_pv_device(XEN_UNPLUG_ALL_IDE_DISKS |
+ XEN_UNPLUG_AUX_IDE_DISKS | XEN_UNPLUG_ALL);
+}
+EXPORT_SYMBOL_GPL(xen_has_pv_disk_devices);
+
+/*
+ * This one is odd - it determines whether you want to run PV _and_
+ * legacy (IDE) drivers together. This combination is only possible
+ * under HVM.
+ */
+bool xen_has_pv_and_legacy_disk_devices(void)
+{
+ if (!xen_domain())
+ return false;
+
+ /* N.B. This is only ever used in HVM mode */
+ if (xen_pv_domain())
+ return false;
+
+ if (xen_platform_pci_unplug & XEN_UNPLUG_UNNECESSARY)
+ return true;
+
+ return false;
+}
+EXPORT_SYMBOL_GPL(xen_has_pv_and_legacy_disk_devices);
+
void xen_unplug_emulated_devices(void)
{
int r;
diff --git a/drivers/block/xen-blkfront.c b/drivers/block/xen-blkfront.c
index a4660bb..ed88b3c 100644
--- a/drivers/block/xen-blkfront.c
+++ b/drivers/block/xen-blkfront.c
@@ -1278,7 +1278,7 @@ static int blkfront_probe(struct xenbus_device *dev,
char *type;
int len;
/* no unplug has been done: do not hook devices != xen vbds */
- if (xen_platform_pci_unplug & XEN_UNPLUG_UNNECESSARY) {
+ if (xen_has_pv_and_legacy_disk_devices()) {
int major;
if (!VDEV_IS_EXTENDED(vdevice))
@@ -2022,7 +2022,7 @@ static int __init xlblk_init(void)
if (!xen_domain())
return -ENODEV;
- if (xen_hvm_domain() && !xen_platform_pci_unplug)
+ if (!xen_has_pv_disk_devices())
return -ENODEV;
if (register_blkdev(XENVBD_MAJOR, DEV_NAME)) {
diff --git a/drivers/char/tpm/xen-tpmfront.c b/drivers/char/tpm/xen-tpmfront.c
index 06189e5..9c2cbd1 100644
--- a/drivers/char/tpm/xen-tpmfront.c
+++ b/drivers/char/tpm/xen-tpmfront.c
@@ -16,6 +16,7 @@
#include <xen/xenbus.h>
#include <xen/page.h>
#include "tpm.h"
+#include <xen/platform_pci.h>
struct tpm_private {
struct tpm_chip *chip;
@@ -422,6 +423,9 @@ static int __init xen_tpmfront_init(void)
if (!xen_domain())
return -ENODEV;
+ if (!xen_has_pv_devices())
+ return -ENODEV;
+
return xenbus_register_frontend(&tpmfront_driver);
}
module_init(xen_tpmfront_init);
diff --git a/drivers/input/misc/xen-kbdfront.c b/drivers/input/misc/xen-kbdfront.c
index e21c181..fbfdc10 100644
--- a/drivers/input/misc/xen-kbdfront.c
+++ b/drivers/input/misc/xen-kbdfront.c
@@ -29,6 +29,7 @@
#include <xen/interface/io/fbif.h>
#include <xen/interface/io/kbdif.h>
#include <xen/xenbus.h>
+#include <xen/platform_pci.h>
struct xenkbd_info {
struct input_dev *kbd;
@@ -380,6 +381,9 @@ static int __init xenkbd_init(void)
if (xen_initial_domain())
return -ENODEV;
+ if (!xen_has_pv_devices())
+ return -ENODEV;
+
return xenbus_register_frontend(&xenkbd_driver);
}
diff --git a/drivers/net/xen-netfront.c b/drivers/net/xen-netfront.c
index 36808bf..eea2392 100644
--- a/drivers/net/xen-netfront.c
+++ b/drivers/net/xen-netfront.c
@@ -2106,7 +2106,7 @@ static int __init netif_init(void)
if (!xen_domain())
return -ENODEV;
- if (xen_hvm_domain() && !xen_platform_pci_unplug)
+ if (!xen_has_pv_nic_devices())
return -ENODEV;
pr_info("Initialising Xen virtual ethernet driver\n");
diff --git a/drivers/pci/xen-pcifront.c b/drivers/pci/xen-pcifront.c
index f7197a7..eae7cd9 100644
--- a/drivers/pci/xen-pcifront.c
+++ b/drivers/pci/xen-pcifront.c
@@ -20,6 +20,7 @@
#include <linux/workqueue.h>
#include <linux/bitops.h>
#include <linux/time.h>
+#include <xen/platform_pci.h>
#include <asm/xen/swiotlb-xen.h>
#define INVALID_GRANT_REF (0)
@@ -1138,6 +1139,9 @@ static int __init pcifront_init(void)
if (!xen_pv_domain() || xen_initial_domain())
return -ENODEV;
+ if (!xen_has_pv_devices())
+ return -ENODEV;
+
pci_frontend_registrar(1 /* enable */);
return xenbus_register_frontend(&xenpci_driver);
diff --git a/drivers/video/xen-fbfront.c b/drivers/video/xen-fbfront.c
index cd005c2..4b2d3ab 100644
--- a/drivers/video/xen-fbfront.c
+++ b/drivers/video/xen-fbfront.c
@@ -35,6 +35,7 @@
#include <xen/interface/io/fbif.h>
#include <xen/interface/io/protocols.h>
#include <xen/xenbus.h>
+#include <xen/platform_pci.h>
struct xenfb_info {
unsigned char *fb;
@@ -699,6 +700,9 @@ static int __init xenfb_init(void)
if (xen_initial_domain())
return -ENODEV;
+ if (!xen_has_pv_devices())
+ return -ENODEV;
+
return xenbus_register_frontend(&xenfb_driver);
}
diff --git a/drivers/xen/xenbus/xenbus_probe_frontend.c b/drivers/xen/xenbus/xenbus_probe_frontend.c
index 34b20bf..6244f9c 100644
--- a/drivers/xen/xenbus/xenbus_probe_frontend.c
+++ b/drivers/xen/xenbus/xenbus_probe_frontend.c
@@ -496,7 +496,7 @@ subsys_initcall(xenbus_probe_frontend_init);
#ifndef MODULE
static int __init boot_wait_for_devices(void)
{
- if (xen_hvm_domain() && !xen_platform_pci_unplug)
+ if (!xen_has_pv_devices())
return -ENODEV;
ready_to_wait_for_devices = 1;
diff --git a/include/xen/platform_pci.h b/include/xen/platform_pci.h
index 438c256..b49eeab 100644
--- a/include/xen/platform_pci.h
+++ b/include/xen/platform_pci.h
@@ -48,4 +48,27 @@ static inline int xen_must_unplug_disks(void) {
extern int xen_platform_pci_unplug;
+#if defined(CONFIG_XEN_PVHVM)
+extern bool xen_has_pv_devices(void);
+extern bool xen_has_pv_disk_devices(void);
+extern bool xen_has_pv_nic_devices(void);
+extern bool xen_has_pv_and_legacy_disk_devices(void);
+#else
+static inline bool xen_has_pv_devices(void)
+{
+ return IS_ENABLED(CONFIG_XEN);
+}
+static inline bool xen_has_pv_disk_devices(void)
+{
+ return IS_ENABLED(CONFIG_XEN);
+}
+static inline bool xen_has_pv_nic_devices(void)
+{
+ return IS_ENABLED(CONFIG_XEN);
+}
+static inline bool xen_has_pv_and_legacy_disk_devices(void)
+{
+ return false;
+}
+#endif
#endif /* _XEN_PLATFORM_PCI_H */
--
1.8.3.1
^ permalink raw reply related
* [PATCH v3] if xen_platform_pci=0 is set don't blow up.
From: Konrad Rzeszutek Wilk @ 2013-12-16 15:04 UTC (permalink / raw)
To: axboe, stefano.stabellini, ian.campbell, xen-devel, linux-kernel,
boris.ostrovsky, david.vrabel, leosilva, ashley, peterhuewe, mail,
tpmdd, dmitry.torokhov, bhelgaas, plagnioj, tomi.valkeinen,
tpmdd-devel, linux-input, netdev, linux-pci, linux-fbdev
The first patch:
[PATCH v3 1/2] xen/pvhvm: If xen_platform_pci=0 is set don't blow up
I would like to commit to stable as it is fixing an eggregious bug -
where we blow up if the guest config has: "xen_platform_pci=0" setup.
This bug has been in existence for years and it is time to stamp it out.
The second patch is a cleanup - not a stable candidate.
It touches all of the Xen frontend drivers and adds the logic of:
"if user disabled us, don't init" - with variations. As you can
specify exactly which ones you want to init and which ones
not (Linux runtime parameter 'xen_emul_unplug'). But for the majority
of drivers - it is just an on/off switch.
Since it touches a lot of maintainers I figured I would send it
to Linus on Wednesday or Thursday.
Thank you!
arch/x86/xen/platform-pci-unplug.c | 79 ++++++++++++++++++++++++++++--
drivers/block/xen-blkfront.c | 4 +-
drivers/char/tpm/xen-tpmfront.c | 4 ++
drivers/input/misc/xen-kbdfront.c | 4 ++
drivers/net/xen-netfront.c | 2 +-
drivers/pci/xen-pcifront.c | 4 ++
drivers/video/xen-fbfront.c | 4 ++
drivers/xen/xenbus/xenbus_probe_frontend.c | 2 +-
include/xen/platform_pci.h | 25 +++++++++-
9 files changed, 119 insertions(+), 9 deletions(-)
Konrad Rzeszutek Wilk (2):
xen/pvhvm: If xen_platform_pci=0 is set don't blow up (v3).
xen/pvhvm: Remove the xen_platform_pci int.
^ permalink raw reply
* [PATCH v3 2/2] xen/pvhvm: Remove the xen_platform_pci int.
From: Konrad Rzeszutek Wilk @ 2013-12-16 15:04 UTC (permalink / raw)
To: axboe, stefano.stabellini, ian.campbell, xen-devel, linux-kernel,
boris.ostrovsky, david.vrabel, leosilva, ashley, peterhuewe, mail,
tpmdd, dmitry.torokhov, bhelgaas, plagnioj, tomi.valkeinen,
tpmdd-devel, linux-input, netdev, linux-pci, linux-fbdev
Cc: Konrad Rzeszutek Wilk
In-Reply-To: <1387206250-13963-1-git-send-email-konrad.wilk@oracle.com>
Since we have xen_has_pv_devices,xen_has_pv_disk_devices,
xen_has_pv_nic_devices, and xen_has_pv_and_legacy_disk_devices
to figure out the different 'unplug' behaviors - lets
use those instead of this single int.
Signed-off-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
---
arch/x86/xen/platform-pci-unplug.c | 5 ++---
include/xen/platform_pci.h | 2 --
2 files changed, 2 insertions(+), 5 deletions(-)
diff --git a/arch/x86/xen/platform-pci-unplug.c b/arch/x86/xen/platform-pci-unplug.c
index ab84ac1..a826171 100644
--- a/arch/x86/xen/platform-pci-unplug.c
+++ b/arch/x86/xen/platform-pci-unplug.c
@@ -30,10 +30,9 @@
#define XEN_PLATFORM_ERR_PROTOCOL -2
#define XEN_PLATFORM_ERR_BLACKLIST -3
-/* store the value of xen_emul_unplug after the unplug is done */
-int xen_platform_pci_unplug;
-EXPORT_SYMBOL_GPL(xen_platform_pci_unplug);
#ifdef CONFIG_XEN_PVHVM
+/* store the value of xen_emul_unplug after the unplug is done */
+static int xen_platform_pci_unplug;
static int xen_emul_unplug;
static int check_platform_magic(void)
diff --git a/include/xen/platform_pci.h b/include/xen/platform_pci.h
index b49eeab..5c52b55 100644
--- a/include/xen/platform_pci.h
+++ b/include/xen/platform_pci.h
@@ -46,8 +46,6 @@ static inline int xen_must_unplug_disks(void) {
#endif
}
-extern int xen_platform_pci_unplug;
-
#if defined(CONFIG_XEN_PVHVM)
extern bool xen_has_pv_devices(void);
extern bool xen_has_pv_disk_devices(void);
--
1.8.3.1
^ permalink raw reply related
* Re: [PATCH] Input: fix typos in Documentation/input/gamepad.txt
From: Antonio Ospite @ 2013-12-16 15:10 UTC (permalink / raw)
To: David Herrmann; +Cc: linux-input, linux-kernel, Dmitry Torokhov, Jiri Kosina
In-Reply-To: <CANq1E4TUC-Gfu0nkjLOs0BEkxh37pWpqQodK88TW9o96ej5OiQ@mail.gmail.com>
On Mon, 16 Dec 2013 14:03:43 +0100
David Herrmann <dh.herrmann@gmail.com> wrote:
> Hi
>
CCing linux-input which I forgot.
> On Mon, Dec 16, 2013 at 1:34 PM, Antonio Ospite
> <ospite@studenti.unina.it> wrote:
> > Fix some typos and while at it also use "PS" as the name for the central
> > "HOME" button on Sony controllers, this is how Sony itself calls it.
>
> Thanks, looks good. Any news regarding the absolute DPad?
>
I plan on sending a patch to add the individual axes this week.
Any news regarding the ABS_* fixes? :)
Will they make it for 3.14?
I do have an ugly hack to evtest but without the mechanism for
checking the ABS protocol version it's not backward compatible.
> Reviewed-by: David Herrmann <dh.herrmann@gmail.com>
>
> Thanks
> David
>
> > Signed-off-by: Antonio Ospite <ospite@studenti.unina.it>
> > ---
> > Documentation/input/gamepad.txt | 6 +++---
> > 1 file changed, 3 insertions(+), 3 deletions(-)
> >
> > diff --git a/Documentation/input/gamepad.txt b/Documentation/input/gamepad.txt
> > index 4be7f21..63c0256 100644
> > --- a/Documentation/input/gamepad.txt
> > +++ b/Documentation/input/gamepad.txt
> > @@ -71,7 +71,7 @@ features that you need, first. How each feature is mapped is described below.
> > Legacy drivers often don't comply to these rules. As we cannot change them
> > for backwards-compatibility reasons, you need to provide fixup mappings in
> > user-space yourself. Some of them might also provide module-options that
> > -change the mappings so you can adivce users to set these.
> > +change the mappings so you can advice users to set these.
> >
> > All new gamepads are supposed to comply with this mapping. Please report any
> > bugs, if they don't.
> > @@ -156,10 +156,10 @@ Menu-Pad:
> > BTN_START
> > Many pads also have a third button which is branded or has a special symbol
> > and meaning. Such buttons are mapped as BTN_MODE. Examples are the Nintendo
> > - "HOME" button, the XBox "X"-button or Sony "P" button.
> > + "HOME" button, the XBox "X"-button or Sony "PS" button.
> >
> > Rumble:
> > - Rumble is adverticed as FF_RUMBLE.
> > + Rumble is advertised as FF_RUMBLE.
> >
> > Motion-tracking:
> > Motion-tracking is defined in ./Documentation/input/motion-tracking.txt and
> > --
> > 1.8.5.1
> >
>
--
Antonio Ospite
http://ao2.it
A: Because it messes up the order in which people normally read text.
See http://en.wikipedia.org/wiki/Posting_style
Q: Why is top-posting such a bad thing?
^ permalink raw reply
* [PATCH] Input: add short note about ABS_MISC+<n> axes
From: David Herrmann @ 2013-12-16 15:23 UTC (permalink / raw)
To: linux-input
Cc: Jiri Kosina, Dmitry Torokhov, Benjamin Tissoires, David Herrmann
We must not reassign those axes or we will break backwards-compat. Add a
small note for that so we don't accidentally some day reuse these.
Signed-off-by: David Herrmann <dh.herrmann@gmail.com>
---
include/uapi/linux/input.h | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/include/uapi/linux/input.h b/include/uapi/linux/input.h
index a372627..da1125e 100644
--- a/include/uapi/linux/input.h
+++ b/include/uapi/linux/input.h
@@ -816,6 +816,10 @@ struct input_keymap_entry {
#define ABS_MISC 0x28
+/* ABS_MISC+x is used by HID to assign to unknown axes. Note that they used to
+ * flow over into the MT definitions. For backwards-compatibility, we must
+ * not reassign [0x29-0x2e] */
+
#define ABS_MT_SLOT 0x2f /* MT slot being modified */
#define ABS_MT_TOUCH_MAJOR 0x30 /* Major axis of touching ellipse */
#define ABS_MT_TOUCH_MINOR 0x31 /* Minor axis (omit if circular) */
--
1.8.5.1
^ permalink raw reply related
* Re: [PATCH 6/7] Input: pmic8xxx-keypad - Migrate to devm_* APIs
From: Dmitry Torokhov @ 2013-12-16 15:37 UTC (permalink / raw)
To: Stephen Boyd; +Cc: linux-kernel, linux-arm-msm, linux-arm-kernel, linux-input
In-Reply-To: <1386718996-3733-7-git-send-email-sboyd@codeaurora.org>
On Tue, Dec 10, 2013 at 03:43:15PM -0800, Stephen Boyd wrote:
> Simplify the error paths and reduce the lines of code in this
> driver by using the devm_* APIs.
>
> Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
> ---
> drivers/input/keyboard/pmic8xxx-keypad.c | 62 +++++++++-----------------------
> 1 file changed, 17 insertions(+), 45 deletions(-)
>
> diff --git a/drivers/input/keyboard/pmic8xxx-keypad.c b/drivers/input/keyboard/pmic8xxx-keypad.c
> index 2c9f19a..4e6bfbf 100644
> --- a/drivers/input/keyboard/pmic8xxx-keypad.c
> +++ b/drivers/input/keyboard/pmic8xxx-keypad.c
> @@ -586,7 +586,7 @@ static int pmic8xxx_kp_probe(struct platform_device *pdev)
> return -EINVAL;
> }
>
> - kp = kzalloc(sizeof(*kp), GFP_KERNEL);
> + kp = devm_kzalloc(&pdev->dev, sizeof(*kp), GFP_KERNEL);
> if (!kp)
> return -ENOMEM;
>
> @@ -595,32 +595,27 @@ static int pmic8xxx_kp_probe(struct platform_device *pdev)
> kp->pdata = pdata;
> kp->dev = &pdev->dev;
>
> - kp->input = input_allocate_device();
> + kp->input = devm_input_allocate_device(&pdev->dev);
> if (!kp->input) {
> dev_err(&pdev->dev, "unable to allocate input device\n");
> - rc = -ENOMEM;
> - goto err_alloc_device;
> + return -ENOMEM;
> }
>
> kp->key_sense_irq = platform_get_irq(pdev, 0);
> if (kp->key_sense_irq < 0) {
> dev_err(&pdev->dev, "unable to get keypad sense irq\n");
> - rc = -ENXIO;
> - goto err_get_irq;
> + return kp->key_sense_irq;
> }
>
> kp->key_stuck_irq = platform_get_irq(pdev, 1);
> if (kp->key_stuck_irq < 0) {
> dev_err(&pdev->dev, "unable to get keypad stuck irq\n");
> - rc = -ENXIO;
> - goto err_get_irq;
> + return kp->key_stuck_irq;
> }
>
> kp->input->name = pdata->input_name ? : "PMIC8XXX keypad";
> kp->input->phys = pdata->input_phys_device ? : "pmic8xxx_keypad/input0";
>
> - kp->input->dev.parent = &pdev->dev;
> -
> kp->input->id.bustype = BUS_I2C;
> kp->input->id.version = 0x0001;
> kp->input->id.product = 0x0001;
> @@ -634,7 +629,7 @@ static int pmic8xxx_kp_probe(struct platform_device *pdev)
> kp->keycodes, kp->input);
> if (rc) {
> dev_err(&pdev->dev, "failed to build keymap\n");
> - goto err_get_irq;
> + return rc;
> }
>
> if (pdata->rep)
> @@ -650,7 +645,7 @@ static int pmic8xxx_kp_probe(struct platform_device *pdev)
> rc = pmic8xxx_kpd_init(kp);
> if (rc < 0) {
> dev_err(&pdev->dev, "unable to initialize keypad controller\n");
> - goto err_get_irq;
> + return rc;
> }
>
> rc = pmic8xxx_kp_config_gpio(pdata->cols_gpio_start,
> @@ -667,24 +662,26 @@ static int pmic8xxx_kp_probe(struct platform_device *pdev)
> goto err_gpio_config;
> }
>
> - rc = request_any_context_irq(kp->key_sense_irq, pmic8xxx_kp_irq,
> - IRQF_TRIGGER_RISING, "pmic-keypad", kp);
> + rc = devm_request_any_context_irq(&pdev->dev, kp->key_sense_irq,
> + pmic8xxx_kp_irq, IRQF_TRIGGER_RISING, "pmic-keypad",
> + kp);
> if (rc < 0) {
> dev_err(&pdev->dev, "failed to request keypad sense irq\n");
> - goto err_get_irq;
> + return rc;
> }
>
> - rc = request_any_context_irq(kp->key_stuck_irq, pmic8xxx_kp_stuck_irq,
> - IRQF_TRIGGER_RISING, "pmic-keypad-stuck", kp);
> + rc = devm_request_any_context_irq(&pdev->dev, kp->key_stuck_irq,
> + pmic8xxx_kp_stuck_irq, IRQF_TRIGGER_RISING,
> + "pmic-keypad-stuck", kp);
> if (rc < 0) {
> dev_err(&pdev->dev, "failed to request keypad stuck irq\n");
> - goto err_req_stuck_irq;
> + return rc;
> }
>
> rc = pmic8xxx_kp_read_u8(kp, &ctrl_val, KEYP_CTRL);
> if (rc < 0) {
> dev_err(&pdev->dev, "failed to read KEYP_CTRL register\n");
> - goto err_pmic_reg_read;
> + return rc;
> }
>
> kp->ctrl_reg = ctrl_val;
> @@ -692,36 +689,12 @@ static int pmic8xxx_kp_probe(struct platform_device *pdev)
> rc = input_register_device(kp->input);
> if (rc < 0) {
> dev_err(&pdev->dev, "unable to register keypad input device\n");
> - goto err_pmic_reg_read;
> + return rc;
> }
>
> device_init_wakeup(&pdev->dev, pdata->wakeup);
>
> return 0;
> -
> -err_pmic_reg_read:
> - free_irq(kp->key_stuck_irq, kp);
> -err_req_stuck_irq:
> - free_irq(kp->key_sense_irq, kp);
> -err_gpio_config:
> -err_get_irq:
> - input_free_device(kp->input);
> -err_alloc_device:
> - kfree(kp);
> - return rc;
> -}
> -
> -static int pmic8xxx_kp_remove(struct platform_device *pdev)
> -{
> - struct pmic8xxx_kp *kp = platform_get_drvdata(pdev);
> -
> - device_init_wakeup(&pdev->dev, 0);
Why are we removing restoring wakeup capable state?
> - free_irq(kp->key_stuck_irq, kp);
> - free_irq(kp->key_sense_irq, kp);
> - input_unregister_device(kp->input);
> - kfree(kp);
> -
> - return 0;
> }
>
> #ifdef CONFIG_PM_SLEEP
> @@ -771,7 +744,6 @@ static SIMPLE_DEV_PM_OPS(pm8xxx_kp_pm_ops,
>
> static struct platform_driver pmic8xxx_kp_driver = {
> .probe = pmic8xxx_kp_probe,
> - .remove = pmic8xxx_kp_remove,
> .driver = {
> .name = PM8XXX_KEYPAD_DEV_NAME,
> .owner = THIS_MODULE,
> --
> The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
> hosted by The Linux Foundation
>
--
Dmitry
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox