[PATCH 1/1] UBUNTU: (pre-stable): input: Support Clickpad devices in ClickZone mode

Andy Whitcroft apw at canonical.com
Fri Apr 9 14:24:50 UTC 2010


On Thu, Apr 08, 2010 at 02:01:38PM -0400, Chase Douglas wrote:
> From: Takashi Iwai <tiwai at xxxxxxx>
> 
> Add the experimental support of new Synatpics "Clickpad" devices.
> 
> This device reports the click as the middle-button, but it doesn't set
> proper capability bits.  Thus the driver needs to check the product-id
> and forces to enable the button detection.
> 
> In this patch, the device behaves as "ClickZone" mode, and gives
> compatible events as other normal synaptics devices so that user-space
> app works as is.  In the ClickZone mode, the buttons are emulated as
> clicks in the bottom button zone.  Left and right clicks are judged by
> the touch position.  Clicking the narrow middle point in the button
> zone gives a middle click.
> 
> Dragging can be done by keeping the button down and touching the normal
> area again.  Strangely, the sequence to click after touching the area
> doesn't work with this device by unknown reason...
> 
> Signed-off-by: Takashi Iwai <tiwai at xxxxxxx>
> 
> BugLink: http://bugs.launchpad.net/bugs/516329
> 
> Signed-off-by: Chase Douglas <chase.douglas at canonical.com>
> ---
> 
> This is the second version, simply merged previous patches into one,
> per request of Dmitry.
> 
>  drivers/input/mouse/synaptics.c |   48 +++++++++++++++++++++++++++++++++++++++
>  drivers/input/mouse/synaptics.h |    3 ++
>  2 files changed, 51 insertions(+), 0 deletions(-)
> 
> diff --git a/drivers/input/mouse/synaptics.c b/drivers/input/mouse/synaptics.c
> index 05689e7..b2db417 100644
> --- a/drivers/input/mouse/synaptics.c
> +++ b/drivers/input/mouse/synaptics.c
> @@ -327,6 +327,45 @@ static void synaptics_pt_create(struct psmouse *psmouse)
>   *	Functions to interpret the absolute mode packets
>   ****************************************************************************/
>  
> +/* left and right clickpad button ranges;
> + * the gap between them is interpreted as a middle-button click
> + */
> +#define CLICKPAD_LEFT_BTN_X \
> +	((XMAX_NOMINAL - XMIN_NOMINAL) * 2 / 5 + XMIN_NOMINAL)
> +#define CLICKPAD_RIGHT_BTN_X \
> +	((XMAX_NOMINAL - XMIN_NOMINAL) * 3 / 5 + XMIN_NOMINAL)
> +
> +/* handle clickpad events */
> +static void clickpad_process_packet(struct synaptics_data *priv,
> +				    struct synaptics_hw_state *hw)
> +{
> +	/* clickpad mode reports Y range from 0 to YMAX_NOMINAL,
> +	 * where the area Y < YMIN_NOMINAL is used as click buttons
> +	 */
> +	if (hw->y < YMIN_NOMINAL) {
> +		/* button area */
> +		hw->z = 0; /* don't move pointer */
> +		/* clickpad reports only the middle button, and we need
> +		 * to fake left/right buttons depending on the touch position
> +		 */
> +		if (hw->middle) { /* clicked? */
> +			hw->middle = 0;
> +			if (hw->x < CLICKPAD_LEFT_BTN_X)
> +				hw->left = 1;
> +			else if (hw->x > CLICKPAD_RIGHT_BTN_X)
> +				hw->right = 1;
> +			else
> +				hw->middle = 1;
> +		}
> +	} else if (hw->middle) {
> +		/* dragging */
> +		hw->left = priv->prev_hw.left;
> +		hw->right = priv->prev_hw.right;
> +		hw->middle = priv->prev_hw.middle;
> +	}
> +	priv->prev_hw = *hw;
> +}
> +
>  static void synaptics_parse_hw_state(unsigned char buf[], struct synaptics_data *priv, struct synaptics_hw_state *hw)
>  {
>  	memset(hw, 0, sizeof(struct synaptics_hw_state));
> @@ -407,6 +446,9 @@ static void synaptics_process_packet(struct psmouse *psmouse)
>  
>  	synaptics_parse_hw_state(psmouse->packet, priv, &hw);
>  
> +	if (SYN_CAP_CLICKPAD(priv->ext_cap))
> +		clickpad_process_packet(priv, &hw);
> +
>  	if (hw.scroll) {
>  		priv->scroll += hw.scroll;
>  
> @@ -701,6 +743,12 @@ int synaptics_init(struct psmouse *psmouse)
>  		SYN_ID_MAJOR(priv->identity), SYN_ID_MINOR(priv->identity),
>  		priv->model_id, priv->capabilities, priv->ext_cap);
>  
> +	if (SYN_CAP_CLICKPAD(priv->ext_cap)) {
> +		printk(KERN_INFO "Synaptics: Clickpad mode enabled\n");
> +		/* force to enable the middle button */
> +		priv->capabilities |= (1 << 18);
> +	}
> +
>  	set_input_params(psmouse->dev, priv);
>  
>  	/*
> diff --git a/drivers/input/mouse/synaptics.h b/drivers/input/mouse/synaptics.h
> index 838e7f2..76df393 100644
> --- a/drivers/input/mouse/synaptics.h
> +++ b/drivers/input/mouse/synaptics.h
> @@ -48,6 +48,8 @@
>  #define SYN_CAP_VALID(c)		((((c) & 0x00ff00) >> 8) == 0x47)
>  #define SYN_EXT_CAP_REQUESTS(c)		(((c) & 0x700000) >> 20)
>  #define SYN_CAP_MULTI_BUTTON_NO(ec)	(((ec) & 0x00f000) >> 12)
> +#define SYN_CAP_PRODUCT_ID(ec)		(((ec) & 0xff0000) >> 16)
> +#define SYN_CAP_CLICKPAD(ec)		(SYN_CAP_PRODUCT_ID(ec) == 0xe4)
>  
>  /* synaptics modes query bits */
>  #define SYN_MODE_ABSOLUTE(m)		((m) & (1 << 7))
> @@ -103,6 +105,7 @@ struct synaptics_data {
>  	unsigned char pkt_type;			/* packet type - old, new, etc */
>  	unsigned char mode;			/* current mode byte */
>  	int scroll;
> +	struct synaptics_hw_state prev_hw;
>  };

Seems to only enable the functionality for devices with the capability
and to be nicely out of line otherwise.

Acked-by: Andy Whitcroft <apw at canonical.com>

-apw




More information about the kernel-team mailing list