Input: synaptics - process finger (<=5) transitions
[pandora-kernel.git] / drivers / input / mouse / synaptics.c
index aec9cf7..30c85a5 100644 (file)
@@ -762,6 +762,10 @@ static void synaptics_image_sensor_1f(struct synaptics_data *priv,
                synaptics_mt_state_set(mt_state, 1, -1, -1);
                priv->mt_state_lost = true;
                break;
+       case 4:
+       case 5:
+               /* mt_state was updated by AGM-CONTACT packet */
+               break;
        }
 }
 
@@ -816,6 +820,10 @@ static void synaptics_image_sensor_2f(struct synaptics_data *priv,
                synaptics_mt_state_set(mt_state, 2, -1, -1);
                priv->mt_state_lost = true;
                break;
+       case 4:
+       case 5:
+               /* mt_state was updated by AGM-CONTACT packet */
+               break;
        }
 }
 
@@ -843,6 +851,22 @@ static void synaptics_image_sensor_3f(struct synaptics_data *priv,
                        synaptics_mt_state_set(mt_state, 3, 0, 2);
                break;
        case 2:
+               /*
+                * If the AGM previously contained slot 3 or higher, then the
+                * newly touching finger is in the lowest available slot.
+                *
+                * If SGM was previously 1 or higher, then the new SGM is
+                * now slot 0 (with a new finger), otherwise, the new finger
+                * is now in a hidden slot between 0 and AGM's slot.
+                *
+                * In all such cases, the SGM now contains slot 0, and the AGM
+                * continues to contain the same slot as before.
+                */
+               if (old->agm >= 3) {
+                       synaptics_mt_state_set(mt_state, 3, 0, old->agm);
+                       break;
+               }
+
                /*
                 * After some 3->1 and all 3->2 transitions, we lose track
                 * of which slot is reported by SGM and AGM.
@@ -883,9 +907,22 @@ static void synaptics_image_sensor_3f(struct synaptics_data *priv,
                 * received AGM-CONTACT packet.
                 */
                break;
+
+       case 4:
+       case 5:
+               /* mt_state was updated by AGM-CONTACT packet */
+               break;
        }
 }
 
+/* Handle case where mt_state->count = 4, or = 5 */
+static void synaptics_image_sensor_45f(struct synaptics_data *priv,
+                                      struct synaptics_mt_state *mt_state)
+{
+       /* mt_state was updated correctly by AGM-CONTACT packet */
+       priv->mt_state_lost = false;
+}
+
 static void synaptics_image_sensor_process(struct psmouse *psmouse,
                                           struct synaptics_hw_state *sgm)
 {
@@ -905,8 +942,10 @@ static void synaptics_image_sensor_process(struct psmouse *psmouse,
                synaptics_image_sensor_1f(priv, &mt_state);
        else if (sgm->w == 0)
                synaptics_image_sensor_2f(priv, &mt_state);
-       else if (sgm->w == 1)
+       else if (sgm->w == 1 && mt_state.count <= 3)
                synaptics_image_sensor_3f(priv, &mt_state);
+       else
+               synaptics_image_sensor_45f(priv, &mt_state);
 
        /* Send resulting input events to user space */
        synaptics_report_mt_data(psmouse, &mt_state, sgm);
@@ -1110,6 +1149,10 @@ static void set_input_params(struct input_dev *dev, struct synaptics_data *priv)
                                        ABS_MT_POSITION_Y);
                /* Image sensors can report per-contact pressure */
                input_set_abs_params(dev, ABS_MT_PRESSURE, 0, 255, 0, 0);
+
+               /* Image sensors can signal 4 and 5 finger clicks */
+               __set_bit(BTN_TOOL_QUADTAP, dev->keybit);
+               __set_bit(BTN_TOOL_QUINTTAP, dev->keybit);
        } else if (SYN_CAP_ADV_GESTURE(priv->ext_cap_0c)) {
                /* Non-image sensors with AGM use semi-mt */
                __set_bit(INPUT_PROP_SEMI_MT, dev->propbit);