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

Robert Hooker sarvatt at ubuntu.com
Tue Dec 14 22:06:32 UTC 2010


From: Takashi Iwai <tiwai at suse.de>

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 suse.de>

BugLink: http://bugs.launchpad.net/bugs/516329

Acked-by: Colin King <colin.king at canonical.com>
Acked-by: Andy Whitcroft <apw at canonical.com>
Signed-off-by: Chase Douglas <chase.douglas at canonical.com>
Signed-off-by: Andy Whitcroft <apw at canonical.com>

Fixed clickpad capability checks to only check the 0x0c cap.

Signed-off-by: Robert Hooker <robert.hooker at canonical.com>
---
 drivers/input/mouse/synaptics.c |   48 +++++++++++++++++++++++++++++++++++++++
 drivers/input/mouse/synaptics.h |    1 +
 2 files changed, 49 insertions(+), 0 deletions(-)

diff --git a/drivers/input/mouse/synaptics.c b/drivers/input/mouse/synaptics.c
index 705589d..ae9891c 100644
--- a/drivers/input/mouse/synaptics.c
+++ b/drivers/input/mouse/synaptics.c
@@ -357,6 +357,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));
@@ -445,6 +484,9 @@ static void synaptics_process_packet(struct psmouse *psmouse)
 
 	synaptics_parse_hw_state(psmouse->packet, priv, &hw);
 
+	if (SYN_CAP_CLICKPAD(priv->ext_cap_0c))
+		clickpad_process_packet(priv, &hw);
+
 	if (hw.scroll) {
 		priv->scroll += hw.scroll;
 
@@ -748,6 +790,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, priv->ext_cap_0c);
 
+	if (SYN_CAP_CLICKPAD(priv->ext_cap_0c)) {
+		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 b6aa7d2..80907d0 100644
--- a/drivers/input/mouse/synaptics.h
+++ b/drivers/input/mouse/synaptics.h
@@ -110,6 +110,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;
 };
 
 void synaptics_module_init(void);
-- 
1.7.0.4





More information about the kernel-team mailing list