/*
* Elantech Touchpad driver (v6)
*
* Copyright (C) 2007-2009 Arjan Opmeer <arjan@opmeer.net>
*
* 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.
*
* Trademarks are the property of their respective owners.
*/
#include <linux/delay.h>
#include <linux/dmi.h>
#include <linux/slab.h>
#include <linux/module.h>
#include <linux/input.h>
#include <linux/input/mt.h>
#include <linux/serio.h>
#include <linux/libps2.h>
#include "psmouse.h"
#include "elantech.h"
#define elantech_debug(fmt, ...) \
do { \
if (etd->debug) \
psmouse_printk(KERN_DEBUG, psmouse, \
fmt, ##__VA_ARGS__); \
} while (0)
/*
* Send a Synaptics style sliced query command
*/
static int synaptics_send_cmd(struct psmouse *psmouse, unsigned char c,
unsigned char *param)
{
if (psmouse_sliced_command(psmouse, c) ||
ps2_command(&psmouse->ps2dev, param, PSMOUSE_CMD_GETINFO)) {
psmouse_err(psmouse, "%s query 0x%02x failed.\n", __func__, c);
return -1;
}
return 0;
}
/*
* A retrying version of ps2_command
*/
static int elantech_ps2_command(struct psmouse *psmouse,
unsigned char *param, int command)
{
struct ps2dev *ps2dev = &psmouse->ps2dev;
struct elantech_data *etd = psmouse->private;
int rc;
int tries = ETP_PS2_COMMAND_TRIES;
do {
rc = ps2_command(ps2dev, param, command);
if (rc == 0)
break;
tries--;
elantech_debug("retrying ps2 command 0x%02x (%d).\n",
command, tries);
msleep(ETP_PS2_COMMAND_DELAY);
} while (tries > 0);
if (rc)
psmouse_err(psmouse, "ps2 command 0x%02x failed.\n", command);
return rc;
}
/*
* Send an Elantech style special command to read a value from a register
*/
static int elantech_read_reg(struct psmouse *psmouse, unsigned char reg,
unsigned char *val)
{
struct elantech_data *etd = psmouse->private;
unsigned char param[3];
int rc