All of lore.kernel.org
 help / color / mirror / Atom feed
From: Wanlong Gao <gaowanlong@cn.fujitsu.com>
To: Zhang Jiejing <jiejing.zhang@freescale.com>
Cc: Dmitry Torokhov <dmitry.torokhov@gmail.com>,
	Henrik Rydberg <rydberg@euromail.se>,
	linux-input@vger.kernel.org, dima@android.com, kzjeef@gmail.com
Subject: Re: [PATCH v2] input: add EETI eGalax I2C capacitive multi touch driver.
Date: Thu, 04 Aug 2011 08:19:43 +0800	[thread overview]
Message-ID: <4E39E59F.5050002@cn.fujitsu.com> (raw)
In-Reply-To: <1312370963-24965-1-git-send-email-jiejing.zhang@freescale.com>

On 08/03/2011 07:29 PM, Zhang Jiejing wrote:
> Hi Dmitry,
>
> This is the patch after change to mt Protocol-B.
> but I have a issue with test tool, in the orignal patch, I use
> android to do the test, but android still not support Protocol B.
>
> I also have a arm based ubuntu, could you which tool can test protocol B?
>
> Thanks,
> Jiejing
>
> Below is patch:
>
> this patch adds EETI eGalax serial multi touch controller driver.
>
> EETI eGalax serial touch screen controller is a I2C based multiple
> capacitive touch screen controller, it can supports 5 touch events maximum.
>
> Signed-off-by: Zhang Jiejing<jiejing.zhang@freescale.com>
Reviewed-by: Wanlong Gao <gaowanlong@cn.fujitsu.com>
>
> ---
> change since 1st verion:
> * use mt protocol B for report pointer.
> * get the pressure value from pointer.
> * use macro to define X,Y max value.
> ---
>   drivers/input/touchscreen/Kconfig     |   10 +
>   drivers/input/touchscreen/Makefile    |    1 +
>   drivers/input/touchscreen/egalax_ts.c |  293 +++++++++++++++++++++++++++++++++
>   3 files changed, 304 insertions(+), 0 deletions(-)
>   create mode 100644 drivers/input/touchscreen/egalax_ts.c
>
> diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig
> index 61834ae..cd6d01e 100644
> --- a/drivers/input/touchscreen/Kconfig
> +++ b/drivers/input/touchscreen/Kconfig
> @@ -165,6 +165,16 @@ config TOUCHSCREEN_EETI
>   	  To compile this driver as a module, choose M here: the
>   	  module will be called eeti_ts.
>
> +config TOUCHSCREEN_EGALAX
> +	tristate "EETI eGalax multi-touch panel support"
> +	depends on I2C
> +	help
> +	  Say Y here to enable support for I2C connected EETI
> +	  eGalax multi-touch panels.
> +
> +	  To compile this driver as a module, choose M here: the
> +	  module will be called egalax_ts.
> +
>   config TOUCHSCREEN_FUJITSU
>   	tristate "Fujitsu serial touchscreen"
>   	select SERIO
> diff --git a/drivers/input/touchscreen/Makefile b/drivers/input/touchscreen/Makefile
> index 718bcc8..ff1173f 100644
> --- a/drivers/input/touchscreen/Makefile
> +++ b/drivers/input/touchscreen/Makefile
> @@ -22,6 +22,7 @@ obj-$(CONFIG_TOUCHSCREEN_HAMPSHIRE)	+= hampshire.o
>   obj-$(CONFIG_TOUCHSCREEN_GUNZE)		+= gunze.o
>   obj-$(CONFIG_TOUCHSCREEN_EETI)		+= eeti_ts.o
>   obj-$(CONFIG_TOUCHSCREEN_ELO)		+= elo.o
> +obj-$(CONFIG_TOUCHSCREEN_EGALAX)	+= egalax_ts.o
>   obj-$(CONFIG_TOUCHSCREEN_FUJITSU)	+= fujitsu_ts.o
>   obj-$(CONFIG_TOUCHSCREEN_INEXIO)	+= inexio.o
>   obj-$(CONFIG_TOUCHSCREEN_INTEL_MID)	+= intel-mid-touch.o
> diff --git a/drivers/input/touchscreen/egalax_ts.c b/drivers/input/touchscreen/egalax_ts.c
> new file mode 100644
> index 0000000..153e64f
> --- /dev/null
> +++ b/drivers/input/touchscreen/egalax_ts.c
> @@ -0,0 +1,293 @@
> +/*
> + * Driver for EETI eGalax Multiple Touch Controller
> + *
> + * Copyright (C) 2011 Freescale Semiconductor, Inc.
> + *
> + * based on max11801_ts.c
> + *
> + * 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.
> + */
> +
> +/* EETI eGalax serial touch screen controller is a I2C based multiple
> + * touch screen controller, it can supports 5 pointer multiple touch. */
> +
> +/* TODO:
> +  - auto idle mode support
> +*/
> +
> +#include<linux/module.h>
> +#include<linux/init.h>
> +#include<linux/i2c.h>
> +#include<linux/interrupt.h>
> +#include<linux/input.h>
> +#include<linux/irq.h>
> +#include<linux/gpio.h>
> +#include<linux/delay.h>
> +#include<linux/slab.h>
> +#include<linux/bitops.h>
> +#include<linux/input/mt.h>
> +
> +#define REPORT_MODE_SINGLE		0x1
> +#define REPORT_MODE_VENDOR		0x3
> +#define REPORT_MODE_MTTOUCH		0x4
> +
> +#define MAX_SUPPORT_POINTS		5
> +
> +#define EVENT_VALID_OFFSET	7
> +#define EVENT_VAILD_MASK	(0x1<<  EVENT_VALID_OFFSET)
> +#define EVENT_ID_OFFSET		2
> +#define EVENT_ID_MASK		(0xf<<  EVENT_ID_OFFSET)
> +#define EVENT_IN_RANGE		(0x1<<  1)
> +#define EVENT_DOWN_UP		(0X1<<  0)
> +
> +#define MAX_I2C_DATA_LEN	10
> +
> +#define EGALAX_MAX_X	32760
> +#define EGALAX_MAX_Y	32760
> +
> +struct egalax_ts {
> +	struct i2c_client		*client;
> +	struct input_dev		*input_dev;
> +};
> +
> +static irqreturn_t egalax_ts_interrupt(int irq, void *dev_id)
> +{
> +	struct egalax_ts *data = dev_id;
> +	struct input_dev *input_dev = data->input_dev;
> +	struct i2c_client *client = data->client;
> +	u8 buf[MAX_I2C_DATA_LEN];
> +	int id, ret, x, y, z;
> +	bool down, valid;
> +	u8 state;
> +
> +retry:
> +	ret = i2c_master_recv(client, buf, MAX_I2C_DATA_LEN);
> +	if (ret == -EAGAIN)
> +		goto retry;
> +
> +	if (ret<  0)
> +		return IRQ_HANDLED;
> +
> +	if (buf[0] != REPORT_MODE_VENDOR
> +	&&  buf[0] != REPORT_MODE_SINGLE
> +	&&  buf[0] != REPORT_MODE_MTTOUCH) {
> +		/* invalid point */
> +		return IRQ_HANDLED;
> +	}
> +
> +	if (buf[0] == REPORT_MODE_VENDOR) {
> +		dev_dbg(&client->dev, "vendor message, ignore...\n");
> +		return IRQ_HANDLED;
> +	}
> +
> +	state = buf[1];
> +	x = (buf[3]<<  8) | buf[2];
> +	y = (buf[5]<<  8) | buf[4];
> +	z = (buf[7]<<  8) | buf[6]; /* only valid in multitouch mode. */
> +
> +	if (buf[0] == REPORT_MODE_SINGLE) {
> +		input_report_abs(input_dev, ABS_X, x);
> +		input_report_abs(input_dev, ABS_Y, y);
> +		input_report_key(input_dev, BTN_TOUCH, !!state);
> +		input_sync(input_dev);
> +		return IRQ_HANDLED;
> +	}
> +
> +	/* deal with multiple touch  */
> +	valid = state&  EVENT_VAILD_MASK;
> +	id = (state&  EVENT_ID_MASK)>>  EVENT_ID_OFFSET;
> +	down = state&  EVENT_DOWN_UP;
> +
> +	if (!valid || id>  MAX_SUPPORT_POINTS) {
> +		dev_dbg(&client->dev, "point invalid\n");
> +		return IRQ_HANDLED;
> +	}
> +
> +	input_mt_slot(input_dev, id);
> +	input_mt_report_slot_state(input_dev, MT_TOOL_FINGER, down);
> +
> +	dev_dbg(&client->dev, "%s id:%d x:%d y:%d z:%d",
> +		(down ? "down" : "up"), id, x, y, z);
> +
> +	if (down) {
> +		input_report_abs(input_dev, ABS_MT_POSITION_X, x);
> +		input_report_abs(input_dev, ABS_MT_POSITION_Y, y);
> +		input_report_abs(input_dev, ABS_MT_PRESSURE, z);
> +	}
> +
> +	input_mt_report_pointer_emulation(input_dev, true);
> +	input_sync(input_dev);
> +	return IRQ_HANDLED;
> +}
> +
> +/* wake up controller by an falling edge of interrupt gpio.  */
> +static int egalax_wake_up_device(struct i2c_client *client)
> +{
> +	int gpio = irq_to_gpio(client->irq);
> +	int ret;
> +
> +	ret = gpio_request(gpio, "egalax_irq");
> +	if (ret<  0) {
> +		dev_err(&client->dev, "request gpio failed:%d\n", ret);
> +		return ret;
> +	}
> +	/* wake up controller via an falling edge on IRQ. */
> +	gpio_direction_output(gpio, 0);
> +	gpio_set_value(gpio, 1);
> +	/* controller should be waken up, return irq.  */
> +	gpio_direction_input(gpio);
> +	gpio_free(gpio);
> +	return 0;
> +}
> +
> +static int egalax_firmware_version(struct i2c_client *client)
> +{
> +	static const u8 cmd[MAX_I2C_DATA_LEN] = { 0x03, 0x03, 0xa, 0x01, 0x41 };
In *ts_suspend(), you fill the cmd with others 0x0, but here not ?
> +	int ret;
> +	ret = i2c_master_send(client, cmd, MAX_I2C_DATA_LEN);
> +	if (ret<  0)
> +		return ret;
> +	return 0;
> +}
> +
> +static int __devinit egalax_ts_probe(struct i2c_client *client,
> +				       const struct i2c_device_id *id)
> +{
> +	struct egalax_ts *data;
> +	struct input_dev *input_dev;
> +	int ret;
> +
> +	data = kzalloc(sizeof(struct egalax_ts), GFP_KERNEL);
> +	if (!data) {
> +		dev_err(&client->dev, "Failed to allocate memory\n");
> +		return -ENOMEM;
> +	}
> +
> +	input_dev = input_allocate_device();
> +	if (!input_dev) {
> +		dev_err(&client->dev, "Failed to allocate memory\n");
> +		ret = -ENOMEM;
> +		goto err_free_data;
> +	}
> +
> +	data->client = client;
> +	data->input_dev = input_dev;
> +	/* controller may be in sleep, wake it up. */
> +	egalax_wake_up_device(client);
> +	ret = egalax_firmware_version(client);
> +	if (ret<  0) {
> +		dev_err(&client->dev,
> +			"egalax_ts: failed to read firmware version\n");
> +		ret = -EIO;
> +		goto err_free_dev;
> +	}
> +
> +	input_dev->name = "EETI eGalax Touch Screen";
> +	input_dev->phys = "I2C",
> +	input_dev->id.bustype = BUS_I2C;
> +	input_dev->dev.parent =&client->dev;
> +
> +	__set_bit(EV_ABS, input_dev->evbit);
> +	__set_bit(EV_KEY, input_dev->evbit);
> +	__set_bit(BTN_TOUCH, input_dev->keybit);
> +	__set_bit(ABS_X, input_dev->absbit);
> +	__set_bit(ABS_Y, input_dev->absbit);
> +	input_set_abs_params(input_dev, ABS_X, 0, EGALAX_MAX_X, 0, 0);
> +	input_set_abs_params(input_dev, ABS_Y, 0, EGALAX_MAX_Y, 0, 0);
> +	input_set_abs_params(input_dev,
> +			     ABS_MT_POSITION_X, 0, EGALAX_MAX_X, 0, 0);
> +	input_set_abs_params(input_dev,
> +			     ABS_MT_POSITION_X, 0, EGALAX_MAX_Y, 0, 0);
> +	input_mt_init_slots(input_dev, MAX_SUPPORT_POINTS);
> +
> +	input_set_drvdata(input_dev, data);
> +
> +	ret = request_threaded_irq(client->irq, NULL, egalax_ts_interrupt,
> +				   IRQF_TRIGGER_LOW | IRQF_ONESHOT,
> +				   "egalax_ts", data);
> +	if (ret<  0) {
> +		dev_err(&client->dev, "Failed to register interrupt\n");
> +		goto err_free_dev;
> +	}
> +
> +	ret = input_register_device(data->input_dev);
> +	if (ret<  0)
> +		goto err_free_irq;
> +	i2c_set_clientdata(client, data);
> +	return 0;
> +
> +err_free_irq:
> +	free_irq(client->irq, data);
> +err_free_dev:
> +	input_free_device(input_dev);
> +err_free_data:
> +	kfree(data);
> +
> +	return ret;
> +}
> +
> +static __devexit int egalax_ts_remove(struct i2c_client *client)
> +{
> +	struct egalax_ts *data = i2c_get_clientdata(client);
> +
> +	free_irq(client->irq, data);
> +	input_unregister_device(data->input_dev);
> +	input_free_device(data->input_dev);
Maybe you've forgotten this? No input_free_device() after *unregister*
by Dmitry?
> +	kfree(data);
> +
> +	return 0;
> +}
> +
> +static const struct i2c_device_id egalax_ts_id[] = {
> +	{"egalax_ts", 0},
> +	{}
> +};
> +MODULE_DEVICE_TABLE(i2c, egalax_ts_id);
> +
> +#ifdef CONFIG_PM_SLEEP
> +static int egalax_ts_suspend(struct device *dev)
> +{
> +	int ret;
> +	u8 suspend_cmd[MAX_I2C_DATA_LEN] = {0x3, 0x6, 0xa, 0x3, 0x36,
> +					    0x3f, 0x2, 0, 0, 0};
> +	struct i2c_client *client = to_i2c_client(dev);
> +	ret = i2c_master_send(client, suspend_cmd, MAX_I2C_DATA_LEN);
> +	return ret>  0 ? 0 : ret;
> +}
> +
> +static int egalax_ts_resume(struct device *dev)
> +{
> +	struct i2c_client *client = to_i2c_client(dev);
> +	return egalax_wake_up_device(client);
> +}
> +#endif
> +
> +static SIMPLE_DEV_PM_OPS(egalax_ts_pm_ops, egalax_ts_suspend, egalax_ts_resume);
> +static struct i2c_driver egalax_ts_driver = {
> +	.driver = {
> +		.name = "egalax_ts",
> +		.pm	=&egalax_ts_pm_ops,
> +	},
> +	.id_table	= egalax_ts_id,
> +	.probe		= egalax_ts_probe,
> +	.remove		= __devexit_p(egalax_ts_remove),
> +};
> +
> +static int __init egalax_ts_init(void)
> +{
> +	return i2c_add_driver(&egalax_ts_driver);
> +}
> +
> +static void __exit egalax_ts_exit(void)
> +{
> +	i2c_del_driver(&egalax_ts_driver);
> +}
> +
> +module_init(egalax_ts_init);
> +module_exit(egalax_ts_exit);
> +
> +MODULE_AUTHOR("Freescale Semiconductor, Inc.");
> +MODULE_DESCRIPTION("Touchscreen driver for EETI eGalax touch controller");
> +MODULE_LICENSE("GPL");


-- 
Thanks
Best Regards
Wanlong Gao

  parent reply	other threads:[~2011-08-04  0:21 UTC|newest]

Thread overview: 22+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2011-07-26  9:25 [PATCH] input: add EETI eGalax I2C capacitive multi touch driver Zhang Jiejing
2011-07-26  9:47 ` Wanlong Gao
2011-07-29  5:28   ` Jiejing.Zhang 
2011-07-29  6:00     ` Wanlong Gao
2011-08-01  6:34 ` Dmitry Torokhov
2011-08-02  8:49   ` Jiejing.Zhang 
2011-08-03 11:29   ` [PATCH v2] " Zhang Jiejing
2011-08-03 20:48     ` Chase Douglas
2011-08-04  0:19     ` Wanlong Gao [this message]
2011-08-11 20:34     ` Henrik Rydberg
2011-08-12 13:24       ` Jiejing.Zhang 
2011-08-12 20:30         ` Henrik Rydberg
2011-09-08 11:39           ` Jiejing.Zhang 
2011-09-08 11:40           ` [PATCH] " Zhang Jiejing
2011-09-13  9:15             ` Henrik Rydberg
2011-09-14  4:50               ` Jiejing.Zhang 
2011-09-14  4:57                 ` Dmitry Torokhov
2011-11-10 10:01                 ` [PATCH V3] " Zhang Jiejing
2011-11-10 18:38                   ` Dmitry Torokhov
2011-11-12  6:12                     ` [PATCH V4] " Zhang Jiejing
2011-11-12  8:02                       ` Dmitry Torokhov
2011-11-12  8:45                         ` Jiejing Zhang

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=4E39E59F.5050002@cn.fujitsu.com \
    --to=gaowanlong@cn.fujitsu.com \
    --cc=dima@android.com \
    --cc=dmitry.torokhov@gmail.com \
    --cc=jiejing.zhang@freescale.com \
    --cc=kzjeef@gmail.com \
    --cc=linux-input@vger.kernel.org \
    --cc=rydberg@euromail.se \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.