From patchwork Thu Dec 9 01:23:49 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ping Cheng X-Patchwork-Id: 392642 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by demeter1.kernel.org (8.14.4/8.14.3) with ESMTP id oB91NJ8o013948 for ; Thu, 9 Dec 2010 01:23:20 GMT Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753372Ab0LIBXS (ORCPT ); Wed, 8 Dec 2010 20:23:18 -0500 Received: from mail-gy0-f174.google.com ([209.85.160.174]:56870 "EHLO mail-gy0-f174.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753581Ab0LIBXS (ORCPT ); Wed, 8 Dec 2010 20:23:18 -0500 Received: by gyb11 with SMTP id 11so1082218gyb.19 for ; Wed, 08 Dec 2010 17:23:17 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=gamma; h=domainkey-signature:received:received:from:to:cc:subject:date :message-id:x-mailer; bh=lzc+w7J8cBfY3edthcXAZFvOIPSSwltw2d+mfaFB8Uo=; b=Xfxb50961FLRDc3AwvOf1ZiRKNCOYm1X2lPVQLk9Y+mEHDhxzP/Yq9Uj4Ucj4NF2aU Izevj+9t8ICiYVaEIAFlu3RJVqiWPRVkQ8VTZz/Lw7w79CNNZf2wEzHrHIwFqtRT9fvU jHlBjWi7Ts+uFeWnmMVdbmdx/xAsm3Zf25UWI= DomainKey-Signature: a=rsa-sha1; c=nofws; d=gmail.com; s=gamma; h=from:to:cc:subject:date:message-id:x-mailer; b=K2FBvNnq6n48axDXJnobekgoT41YE9EyRc674Ywzg7DRcLP6xswy73rx+pA8I5ShoE /n626Qnt4kBAu0vKC5mZZCd+N0o/HtejKbvDC6u5VOp1gUsmtAaWY0nqjC9hCanT5ENi WjOgCLWOsOfsFdrV8ZVZT0CrPFKP9Agv94kcI= Received: by 10.90.70.17 with SMTP id s17mr2359862aga.80.1291857797481; Wed, 08 Dec 2010 17:23:17 -0800 (PST) Received: from localhost.localdomain ([204.119.25.150]) by mx.google.com with ESMTPS id x42sm775636yhc.11.2010.12.08.17.23.15 (version=TLSv1/SSLv3 cipher=RC4-MD5); Wed, 08 Dec 2010 17:23:16 -0800 (PST) From: Ping Cheng To: linux-input@vger.kernel.org Cc: dmitry.torokhov@gmail.com, Ping Cheng , Ping Cheng Subject: [PATCH 2/2]input - wacom_w8001: Add one finger touch support Date: Wed, 8 Dec 2010 17:23:49 -0800 Message-Id: <1291857829-13804-1-git-send-email-pinglinux@gmail.com> X-Mailer: git-send-email 1.7.2.3 Sender: linux-input-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-input@vger.kernel.org X-Greylist: IP, sender and recipient auto-whitelisted, not delayed by milter-greylist-4.2.3 (demeter1.kernel.org [140.211.167.41]); Thu, 09 Dec 2010 01:23:20 +0000 (UTC) diff --git a/drivers/input/touchscreen/wacom_w8001.c b/drivers/input/touchscreen/wacom_w8001.c index 90b92e8..68087d8 100644 --- a/drivers/input/touchscreen/wacom_w8001.c +++ b/drivers/input/touchscreen/wacom_w8001.c @@ -3,6 +3,7 @@ * * Copyright (c) 2008 Jaya Kumar * Copyright (c) 2010 Red Hat, Inc. + * Copyright (c) 2010 Ping Cheng, Wacom. * * This file is subject to the terms and conditions of the GNU General Public * License. See the file COPYING in the main directory of this archive for @@ -86,6 +87,12 @@ struct w8001 { char phys[32]; int type; unsigned int pktlen; + bool pen_in_prox; + bool has_touch; + int max_touch_x; + int max_touch_y; + int max_pen_x; + int max_pen_y; }; static void parse_data(u8 *data, struct w8001_coord *coord) @@ -112,6 +119,29 @@ static void parse_data(u8 *data, struct w8001_coord *coord) coord->tilt_y = data[8] & 0x7F; } +static void parse_single_touch(struct w8001 *w8001) +{ + struct input_dev *dev = w8001->dev; + unsigned char *data = w8001->data; + + int x = (data[1] << 7) | data[2]; + int y = (data[3] << 7) | data[4]; + w8001->has_touch = data[0] & 0x1; + + /* scale to pen maximum */ + if (w8001->max_pen_x && w8001->max_pen_y && w8001->max_touch_x) { + x = x * w8001->max_pen_x / w8001->max_touch_x; + y = y * w8001->max_pen_y / w8001->max_touch_y; + } + + input_report_abs(dev, ABS_X, x); + input_report_abs(dev, ABS_Y, y); + input_report_key(dev, BTN_TOUCH, w8001->has_touch); + input_report_key(dev, BTN_TOOL_FINGER, w8001->has_touch); + + input_sync(dev); +} + static void parse_touch(struct w8001 *w8001) { struct input_dev *dev = w8001->dev; @@ -151,6 +181,18 @@ static void parse_touchquery(u8 *data, struct w8001_touch_query *query) query->y = data[5] << 9; query->y |= data[6] << 2; query->y |= (data[2] >> 3) & 0x3; + + /* Early days' one finger touch models need the following defaults */ + if (!query->x && !query->y) { + query->x = 1024; + query->y = 1024; + query->panel_res = 10; + query->panel_res = 10; + if (data[1]) { + query->x = (1 << data[1]); + query->y = (1 << data[1]); + } + } } static void report_pen_events(struct w8001 *w8001, struct w8001_coord *coord) @@ -199,6 +241,7 @@ static irqreturn_t w8001_interrupt(struct serio *serio, unsigned char data, unsigned int flags) { struct w8001 *w8001 = serio_get_drvdata(serio); + struct input_dev *dev = w8001->dev; struct w8001_coord coord; unsigned char tmp; @@ -213,9 +256,15 @@ static irqreturn_t w8001_interrupt(struct serio *serio, case W8001_PKTLEN_TOUCH93 - 1: case W8001_PKTLEN_TOUCH9A - 1: - /* ignore one-finger touch packet. */ - if (w8001->pktlen == w8001->idx) + tmp = (w8001->data[0] & W8001_TOUCH_BYTE); + if (tmp != W8001_TOUCH_BYTE) + break; + + if (w8001->pktlen == w8001->idx) { w8001->idx = 0; + if (!w8001->pen_in_prox) + parse_single_touch(w8001); + } break; /* Pen coordinates packet */ @@ -228,9 +277,17 @@ static irqreturn_t w8001_interrupt(struct serio *serio, if (tmp == W8001_TOUCH_BYTE) break; + if (w8001->has_touch) { + /* send touch data out */ + w8001->has_touch = 0; + input_report_key(dev, BTN_TOUCH, 0); + input_report_key(dev, BTN_TOOL_FINGER, 0); + } + w8001->idx = 0; parse_data(w8001->data, &coord); report_pen_events(w8001, &coord); + w8001->pen_in_prox = coord.rdy ? true : false; break; /* control packet */ @@ -313,11 +370,20 @@ static int w8001_setup(struct w8001 *w8001) */ if (!error && w8001->response[1]) { struct w8001_touch_query touch; + int px, py; parse_touchquery(w8001->response, &touch); - input_set_abs_params(dev, ABS_X, 0, touch.x, 0, 0); - input_set_abs_params(dev, ABS_Y, 0, touch.y, 0, 0); + px = w8001->max_touch_x = touch.x; + py = w8001->max_touch_x = touch.y; + + /* scale to pen maximum */ + if (coord.x && coord.y) { + px = w8001->max_pen_x = coord.x; + py = w8001->max_pen_y = coord.y; + } + input_set_abs_params(dev, ABS_X, 0, px, 0, 0); + input_set_abs_params(dev, ABS_Y, 0, py, 0, 0); dev->keybit[BIT_WORD(BTN_TOOL_FINGER)] |= BIT_MASK(BTN_TOOL_FINGER); switch (touch.sensor_id) {