Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 227137
b: refs/heads/master
c: fec6e52
h: refs/heads/master
i:
  227135: 69ac730
v: v3
  • Loading branch information
Henrik Rydberg committed Dec 21, 2010
1 parent f41d1df commit e6aadad
Show file tree
Hide file tree
Showing 3 changed files with 89 additions and 4 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: c14890a8e54977f895773d393d6a640d6d698fb8
refs/heads/master: fec6e5252b542e748871c88f8455e69ae73ea156
88 changes: 85 additions & 3 deletions trunk/drivers/input/mouse/synaptics.c
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@

#include <linux/module.h>
#include <linux/dmi.h>
#include <linux/input.h>
#include <linux/input/mt.h>
#include <linux/serio.h>
#include <linux/libps2.h>
#include <linux/slab.h>
Expand Down Expand Up @@ -279,6 +279,25 @@ static void synaptics_set_rate(struct psmouse *psmouse, unsigned int rate)
synaptics_mode_cmd(psmouse, priv->mode);
}

static int synaptics_set_advanced_gesture_mode(struct psmouse *psmouse)
{
static unsigned char param = 0xc8;
struct synaptics_data *priv = psmouse->private;

if (!SYN_CAP_ADV_GESTURE(priv->ext_cap_0c))
return 0;

if (psmouse_sliced_command(psmouse, SYN_QUE_MODEL))
return -1;
if (ps2_command(&psmouse->ps2dev, &param, PSMOUSE_CMD_SETRATE))
return -1;

/* Advanced gesture mode also sends multi finger data */
priv->capabilities |= BIT(1);

return 0;
}

/*****************************************************************************
* Synaptics pass-through PS/2 port support
****************************************************************************/
Expand Down Expand Up @@ -380,7 +399,9 @@ static void synaptics_pt_create(struct psmouse *psmouse)
* Functions to interpret the absolute mode packets
****************************************************************************/

static void synaptics_parse_hw_state(unsigned char buf[], struct synaptics_data *priv, struct synaptics_hw_state *hw)
static int synaptics_parse_hw_state(const unsigned char buf[],
struct synaptics_data *priv,
struct synaptics_hw_state *hw)
{
memset(hw, 0, sizeof(struct synaptics_hw_state));

Expand All @@ -397,6 +418,14 @@ static void synaptics_parse_hw_state(unsigned char buf[], struct synaptics_data
((buf[0] & 0x04) >> 1) |
((buf[3] & 0x04) >> 2));

if (SYN_CAP_ADV_GESTURE(priv->ext_cap_0c) && hw->w == 2) {
/* Gesture packet: (x, y, z) at half resolution */
priv->mt.x = (((buf[4] & 0x0f) << 8) | buf[1]) << 1;
priv->mt.y = (((buf[4] & 0xf0) << 4) | buf[2]) << 1;
priv->mt.z = ((buf[3] & 0x30) | (buf[5] & 0x0f)) << 1;
return 1;
}

hw->left = (buf[0] & 0x01) ? 1 : 0;
hw->right = (buf[0] & 0x02) ? 1 : 0;

Expand Down Expand Up @@ -452,6 +481,36 @@ static void synaptics_parse_hw_state(unsigned char buf[], struct synaptics_data
hw->left = (buf[0] & 0x01) ? 1 : 0;
hw->right = (buf[0] & 0x02) ? 1 : 0;
}

return 0;
}

static void set_slot(struct input_dev *dev, int slot, bool active, int x, int y)
{
input_mt_slot(dev, slot);
input_mt_report_slot_state(dev, MT_TOOL_FINGER, active);
if (active) {
input_report_abs(dev, ABS_MT_POSITION_X, x);
input_report_abs(dev, ABS_MT_POSITION_Y,
YMAX_NOMINAL + YMIN_NOMINAL - y);
}
}

static void synaptics_report_semi_mt_data(struct input_dev *dev,
const struct synaptics_hw_state *a,
const struct synaptics_hw_state *b,
int num_fingers)
{
if (num_fingers >= 2) {
set_slot(dev, 0, true, min(a->x, b->x), min(a->y, b->y));
set_slot(dev, 1, true, max(a->x, b->x), max(a->y, b->y));
} else if (num_fingers == 1) {
set_slot(dev, 0, true, a->x, a->y);
set_slot(dev, 1, false, 0, 0);
} else {
set_slot(dev, 0, false, 0, 0);
set_slot(dev, 1, false, 0, 0);
}
}

/*
Expand All @@ -466,7 +525,8 @@ static void synaptics_process_packet(struct psmouse *psmouse)
int finger_width;
int i;

synaptics_parse_hw_state(psmouse->packet, priv, &hw);
if (synaptics_parse_hw_state(psmouse->packet, priv, &hw))
return;

if (hw.scroll) {
priv->scroll += hw.scroll;
Expand Down Expand Up @@ -512,6 +572,9 @@ static void synaptics_process_packet(struct psmouse *psmouse)
finger_width = 0;
}

if (SYN_CAP_ADV_GESTURE(priv->ext_cap_0c))
synaptics_report_semi_mt_data(dev, &hw, &priv->mt, num_fingers);

/* Post events
* BTN_TOUCH has to be first as mousedev relies on it when doing
* absolute -> relative conversion
Expand Down Expand Up @@ -631,6 +694,15 @@ static void set_input_params(struct input_dev *dev, struct synaptics_data *priv)
YMIN_NOMINAL, priv->y_max ?: YMAX_NOMINAL, 0, 0);
input_set_abs_params(dev, ABS_PRESSURE, 0, 255, 0, 0);

if (SYN_CAP_ADV_GESTURE(priv->ext_cap_0c)) {
__set_bit(INPUT_PROP_SEMI_MT, dev->propbit);
input_mt_init_slots(dev, 2);
input_set_abs_params(dev, ABS_MT_POSITION_X, XMIN_NOMINAL,
priv->x_max ?: XMAX_NOMINAL, 0, 0);
input_set_abs_params(dev, ABS_MT_POSITION_Y, YMIN_NOMINAL,
priv->y_max ?: YMAX_NOMINAL, 0, 0);
}

if (SYN_CAP_PALMDETECT(priv->capabilities))
input_set_abs_params(dev, ABS_TOOL_WIDTH, 0, 15, 0, 0);

Expand Down Expand Up @@ -705,6 +777,11 @@ static int synaptics_reconnect(struct psmouse *psmouse)
return -1;
}

if (synaptics_set_advanced_gesture_mode(psmouse)) {
printk(KERN_ERR "Advanced gesture mode reconnect failed.\n");
return -1;
}

return 0;
}

Expand Down Expand Up @@ -772,6 +849,11 @@ int synaptics_init(struct psmouse *psmouse)
goto init_fail;
}

if (synaptics_set_advanced_gesture_mode(psmouse)) {
printk(KERN_ERR "Advanced gesture mode init failed.\n");
goto init_fail;
}

priv->pkt_type = SYN_MODEL_NEWABS(priv->model_id) ? SYN_NEWABS : SYN_OLDABS;

printk(KERN_INFO "Synaptics Touchpad, model: %ld, fw: %ld.%ld, id: %#lx, caps: %#lx/%#lx/%#lx\n",
Expand Down
3 changes: 3 additions & 0 deletions trunk/drivers/input/mouse/synaptics.h
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@
#define SYN_CAP_PRODUCT_ID(ec) (((ec) & 0xff0000) >> 16)
#define SYN_CAP_CLICKPAD(ex0c) ((ex0c) & 0x100100)
#define SYN_CAP_MAX_DIMENSIONS(ex0c) ((ex0c) & 0x020000)
#define SYN_CAP_ADV_GESTURE(ex0c) ((ex0c) & 0x080000)

/* synaptics modes query bits */
#define SYN_MODE_ABSOLUTE(m) ((m) & (1 << 7))
Expand Down Expand Up @@ -112,6 +113,8 @@ struct synaptics_data {
int scroll;

struct serio *pt_port; /* Pass-through serio port */

struct synaptics_hw_state mt; /* current gesture packet */
};

void synaptics_module_init(void);
Expand Down

0 comments on commit e6aadad

Please sign in to comment.