From patchwork Tue Dec 15 08:25:18 2009 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Dmitry Torokhov X-Patchwork-Id: 67553 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by demeter.kernel.org (8.14.2/8.14.2) with ESMTP id nBF8PRwJ017041 for ; Tue, 15 Dec 2009 08:25:27 GMT Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752247AbZLOIZY (ORCPT ); Tue, 15 Dec 2009 03:25:24 -0500 Received: (majordomo@vger.kernel.org) by vger.kernel.org id S1752283AbZLOIZY (ORCPT ); Tue, 15 Dec 2009 03:25:24 -0500 Received: from mail-px0-f174.google.com ([209.85.216.174]:53605 "EHLO mail-px0-f174.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752245AbZLOIZX (ORCPT ); Tue, 15 Dec 2009 03:25:23 -0500 Received: by pxi4 with SMTP id 4so2441836pxi.33 for ; Tue, 15 Dec 2009 00:25:23 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=gamma; h=domainkey-signature:received:received:date:from:to:cc:subject :message-id:references:mime-version:content-type:content-disposition :in-reply-to:user-agent; bh=pa4qm8Nb/R1OOYmK8hafHNgitw1z4cEXNd3tWfLFZ5o=; b=dNch/uYY0jMQajc1NCE0m0DfCrCTrAURJ6aFPZqx13VyyrcwxOHHhgWqIsWHSgzmeP kdpT+/DhEsyGSqdEU2B8NrOc6d7qODHS6wQR3w5wSvIR+Us85EcIS6SNXfQUcWA5JpB8 7ggqO8tUvau4tBG49a7GkGtJdJg8UreLmZMPk= DomainKey-Signature: a=rsa-sha1; c=nofws; d=gmail.com; s=gamma; h=date:from:to:cc:subject:message-id:references:mime-version :content-type:content-disposition:in-reply-to:user-agent; b=j+dbP77bX32TiQmciqNg+N7ODgpu54Qc+0RcqHITKYZaDhmUMiA/1ASFYUce/rW3Bm HGGPaqwzoWzHon/H+ALSSvxvOScJSfraGD8kBgdXrCxKH5hy1qkjAfHuknWABHjh4kXA zv6giZJEPbApOEkAOiUJg8Y0JiOrq/Z7wtcKE= Received: by 10.141.105.5 with SMTP id h5mr4170359rvm.178.1260865523088; Tue, 15 Dec 2009 00:25:23 -0800 (PST) Received: from mailhub.coreip.homeip.net (c-24-6-153-137.hsd1.ca.comcast.net [24.6.153.137]) by mx.google.com with ESMTPS id 20sm5695665pzk.1.2009.12.15.00.25.21 (version=TLSv1/SSLv3 cipher=RC4-MD5); Tue, 15 Dec 2009 00:25:21 -0800 (PST) Date: Tue, 15 Dec 2009 00:25:18 -0800 From: Dmitry Torokhov To: Takashi Iwai Cc: Alex Chiang , linux-kernel , linux-input@vger.kernel.org Subject: Re: synaptics touchpad doesn't click Message-ID: <20091215082518.GD12669@core.coreip.homeip.net> References: <20091214014828.GA28402@ldl.fc.hp.com> <20091214173450.GB2373@core.coreip.homeip.net> <20091215034127.GC587@ldl.fc.hp.com> <20091215062628.GA12669@core.coreip.homeip.net> <20091215073358.GC12669@core.coreip.homeip.net> MIME-Version: 1.0 Content-Disposition: inline In-Reply-To: User-Agent: Mutt/1.5.19 (2009-01-05) Sender: linux-input-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-input@vger.kernel.org diff --git a/drivers/input/mouse/synaptics.c b/drivers/input/mouse/synaptics.c index 7047558..34df70f 100644 --- a/drivers/input/mouse/synaptics.c +++ b/drivers/input/mouse/synaptics.c @@ -41,6 +41,15 @@ #define YMIN_NOMINAL 1408 #define YMAX_NOMINAL 4448 +/* + * Left and right ClickPad button ranges; the gap between them is reserved + * for middle button. + */ +#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) + /***************************************************************************** * Stuff we need even when we do not want native Synaptics support @@ -327,23 +336,56 @@ static void synaptics_pt_create(struct psmouse *psmouse) * Functions to interpret the absolute mode packets ****************************************************************************/ static void synaptics_parse_new_hw(unsigned char buf[], - struct synaptics_data *priv, - struct synaptics_hw_state *hw) + struct synaptics_data *priv) { - hw->x = ((buf[3] & 0x10) << 8) | ((buf[1] & 0x0f) << 8) | buf[4]; - hw->y = ((buf[3] & 0x20) << 7) | ((buf[1] & 0xf0) << 4) | buf[5]; + struct synaptics_hw_state *hw = &priv->hw; + int x = ((buf[3] & 0x10) << 8) | ((buf[1] & 0x0f) << 8) | buf[4]; + int y = ((buf[3] & 0x20) << 7) | ((buf[1] & 0xf0) << 4) | buf[5]; hw->z = buf[2]; hw->w = ((buf[0] & 0x30) >> 2) | ((buf[0] & 0x04) >> 1) | ((buf[3] & 0x04) >> 2); - hw->left = buf[0] & 0x01; - hw->right = buf[0] & 0x02; + if (SYN_CAP_CLICKPAD(priv->ext_cap)) { + int click = (buf[0] ^ buf[3]) & 0x01; - if (SYN_CAP_MIDDLE_BUTTON(priv->capabilities)) { - hw->middle = (buf[0] ^ buf[3]) & 0x01; - hw->scroll = hw->w == 2 ? (signed char)buf[1] : 0; + if (click && y < YMIN_NOMINAL) { + /* + * User pressed in ClickZone; report new button + * state but use :w + * old coordinates and don't report + * any pressure to prevent pointer movement. + */ + hw->left = x < CLICKPAD_LEFT_BTN_X; + hw->right = x > CLICKPAD_RIGHT_BTN_X; + hw->middle = x >= CLICKPAD_LEFT_BTN_X && + x <= CLICKPAD_RIGHT_BTN_X; + hw->z = 0; + + } else { + /* + * Finger is outside of the ClickZone - report + * current coordinates. + */ + hw->x = x; + hw->y = y; + + if (!click) + hw->left = hw->right = hw->middle = 0; + } + + } else { + hw->x = x; + hw->y = y; + + hw->left = buf[0] & 0x01; + hw->right = buf[0] & 0x02; + + if (SYN_CAP_MIDDLE_BUTTON(priv->capabilities)) { + hw->middle = (buf[0] ^ buf[3]) & 0x01; + hw->scroll = hw->w == 2 ? (signed char)buf[1] : 0; + } } if (SYN_CAP_FOUR_BUTTON(priv->capabilities)) { @@ -379,9 +421,10 @@ static void synaptics_parse_new_hw(unsigned char buf[], } static void synaptics_parse_old_hw(unsigned char buf[], - struct synaptics_data *priv, - struct synaptics_hw_state *hw) + struct synaptics_data *priv) { + struct synaptics_hw_state *hw = &priv->hw; + hw->x = ((buf[1] & 0x1f) << 8) | buf[2]; hw->y = ((buf[4] & 0x1f) << 8) | buf[5]; @@ -399,44 +442,44 @@ static void synaptics_process_packet(struct psmouse *psmouse) { struct input_dev *dev = psmouse->dev; struct synaptics_data *priv = psmouse->private; - struct synaptics_hw_state hw; + struct synaptics_hw_state *hw = &priv->hw; int num_fingers; int finger_width; int i; if (SYN_MODEL_NEWABS(priv->model_id)) - synaptics_parse_new_hw(psmouse->packet, priv, &hw); + synaptics_parse_new_hw(psmouse->packet, priv); else - synaptics_parse_old_hw(psmouse->packet, priv, &hw); + synaptics_parse_old_hw(psmouse->packet, priv); - if (hw.scroll) { - priv->scroll += hw.scroll; + if (hw->scroll) { + priv->scroll += hw->scroll; while (priv->scroll >= 4) { - input_report_key(dev, BTN_BACK, !hw.down); + input_report_key(dev, BTN_BACK, !hw->down); input_sync(dev); - input_report_key(dev, BTN_BACK, hw.down); + input_report_key(dev, BTN_BACK, hw->down); input_sync(dev); priv->scroll -= 4; } while (priv->scroll <= -4) { - input_report_key(dev, BTN_FORWARD, !hw.up); + input_report_key(dev, BTN_FORWARD, !hw->up); input_sync(dev); - input_report_key(dev, BTN_FORWARD, hw.up); + input_report_key(dev, BTN_FORWARD, hw->up); input_sync(dev); priv->scroll += 4; } return; } - if (hw.z > 0) { + if (hw->z > 0) { num_fingers = 1; finger_width = 5; if (SYN_CAP_EXTENDED(priv->capabilities)) { - switch (hw.w) { + switch (hw->w) { case 0 ... 1: if (SYN_CAP_MULTIFINGER(priv->capabilities)) - num_fingers = hw.w + 2; + num_fingers = hw->w + 2; break; case 2: if (SYN_MODEL_PEN(priv->model_id)) @@ -444,7 +487,7 @@ static void synaptics_process_packet(struct psmouse *psmouse) break; case 4 ... 15: if (SYN_CAP_PALMDETECT(priv->capabilities)) - finger_width = hw.w; + finger_width = hw->w; break; } } @@ -457,35 +500,37 @@ static void synaptics_process_packet(struct psmouse *psmouse) * BTN_TOUCH has to be first as mousedev relies on it when doing * absolute -> relative conversion */ - if (hw.z > 30) input_report_key(dev, BTN_TOUCH, 1); - if (hw.z < 25) input_report_key(dev, BTN_TOUCH, 0); + if (hw->z > 30) input_report_key(dev, BTN_TOUCH, 1); + if (hw->z < 25) input_report_key(dev, BTN_TOUCH, 0); - if (hw.z > 0) { - input_report_abs(dev, ABS_X, hw.x); - input_report_abs(dev, ABS_Y, YMAX_NOMINAL + YMIN_NOMINAL - hw.y); + if (hw->z > 0) { + input_report_abs(dev, ABS_X, hw->x); + input_report_abs(dev, ABS_Y, YMAX_NOMINAL + YMIN_NOMINAL - hw->y); } - input_report_abs(dev, ABS_PRESSURE, hw.z); + input_report_abs(dev, ABS_PRESSURE, hw->z); input_report_abs(dev, ABS_TOOL_WIDTH, finger_width); input_report_key(dev, BTN_TOOL_FINGER, num_fingers == 1); - input_report_key(dev, BTN_LEFT, hw.left); - input_report_key(dev, BTN_RIGHT, hw.right); + input_report_key(dev, BTN_LEFT, hw->left); + input_report_key(dev, BTN_RIGHT, hw->right); if (SYN_CAP_MULTIFINGER(priv->capabilities)) { input_report_key(dev, BTN_TOOL_DOUBLETAP, num_fingers == 2); input_report_key(dev, BTN_TOOL_TRIPLETAP, num_fingers == 3); } - if (SYN_CAP_MIDDLE_BUTTON(priv->capabilities)) - input_report_key(dev, BTN_MIDDLE, hw.middle); + if (SYN_CAP_MIDDLE_BUTTON(priv->capabilities) || + SYN_CAP_CLICKPAD(priv->ext_cap)) { + input_report_key(dev, BTN_MIDDLE, hw->middle); + } if (SYN_CAP_FOUR_BUTTON(priv->capabilities)) { - input_report_key(dev, BTN_FORWARD, hw.up); - input_report_key(dev, BTN_BACK, hw.down); + input_report_key(dev, BTN_FORWARD, hw->up); + input_report_key(dev, BTN_BACK, hw->down); } for (i = 0; i < SYN_CAP_MULTI_BUTTON_NO(priv->ext_cap); i++) - input_report_key(dev, BTN_0 + i, hw.ext_buttons & (1 << i)); + input_report_key(dev, BTN_0 + i, hw->ext_buttons & (1 << i)); input_sync(dev); } diff --git a/drivers/input/mouse/synaptics.h b/drivers/input/mouse/synaptics.h index 838e7f2..e00c53d 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)) @@ -100,9 +102,10 @@ struct synaptics_data { int x_res; /* X resolution in units/mm */ int y_res; /* Y resolution in units/mm */ + struct synaptics_hw_state hw; + int scroll; unsigned char pkt_type; /* packet type - old, new, etc */ unsigned char mode; /* current mode byte */ - int scroll; }; void synaptics_module_init(void);