+ key = dev->data[dev->datalen - 1] & ATP_STATUS_BUTTON;
+
+ if (x && y) {
+ if (dev->x_old != -1) {
+ x = (dev->x_old * 3 + x) >> 2;
+ y = (dev->y_old * 3 + y) >> 2;
+ dev->x_old = x;
+ dev->y_old = y;
+
+ if (debug > 1)
+ printk(KERN_DEBUG "appletouch: "
+ "X: %3d Y: %3d Xz: %3d Yz: %3d\n",
+ x, y, x_z, y_z);
+
+ input_report_key(dev->input, BTN_TOUCH, 1);
+ input_report_abs(dev->input, ABS_X, x);
+ input_report_abs(dev->input, ABS_Y, y);
+ input_report_abs(dev->input, ABS_PRESSURE,
+ min(ATP_PRESSURE, x_z + y_z));
+ atp_report_fingers(dev->input, max(x_f, y_f));
+ }
+ dev->x_old = x;
+ dev->y_old = y;
+
+ } else if (!x && !y) {
+
+ dev->x_old = dev->y_old = -1;
+ input_report_key(dev->input, BTN_TOUCH, 0);
+ input_report_abs(dev->input, ABS_PRESSURE, 0);
+ atp_report_fingers(dev->input, 0);
+
+ /* reset the accumulator on release */
+ memset(dev->xy_acc, 0, sizeof(dev->xy_acc));
+ }
+
+ input_report_key(dev->input, BTN_LEFT, key);
+ input_sync(dev->input);
+
+ exit:
+ retval = usb_submit_urb(dev->urb, GFP_ATOMIC);
+ if (retval)
+ err("atp_complete: usb_submit_urb failed with result %d",
+ retval);
+}
+
+/* Interrupt function for older touchpads: GEYSER3/GEYSER4 */
+
+static void atp_complete_geyser_3_4(struct urb *urb)
+{
+ int x, y, x_z, y_z, x_f, y_f;
+ int retval, i, j;
+ int key;
+ struct atp *dev = urb->context;
+ int status = atp_status_check(urb);
+
+ if (status == ATP_URB_STATUS_ERROR_FATAL)
+ return;
+ else if (status == ATP_URB_STATUS_ERROR)
+ goto exit;
+
+ /* Reorder the sensors values:
+ *
+ * The values are laid out like this:
+ * -, Y1, Y2, -, Y3, Y4, -, ..., -, X1, X2, -, X3, X4, ...
+ * '-' is an unused value.
+ */
+
+ /* read X values */
+ for (i = 0, j = 19; i < 20; i += 2, j += 3) {
+ dev->xy_cur[i] = dev->data[j + 1];
+ dev->xy_cur[i + 1] = dev->data[j + 2];
+ }
+ /* read Y values */
+ for (i = 0, j = 1; i < 9; i += 2, j += 3) {
+ dev->xy_cur[ATP_XSENSORS + i] = dev->data[j + 1];
+ dev->xy_cur[ATP_XSENSORS + i + 1] = dev->data[j + 2];
+ }
+
+ dbg_dump("sample", dev->xy_cur);
+
+ /* Just update the base values (i.e. touchpad in untouched state) */
+ if (dev->data[dev->datalen - 1] & ATP_STATUS_BASE_UPDATE) {
+
+ dprintk(KERN_DEBUG "appletouch: updated base values\n");
+
+ memcpy(dev->xy_old, dev->xy_cur, sizeof(dev->xy_old));
+ goto exit;
+ }
+
+ for (i = 0; i < ATP_XSENSORS + ATP_YSENSORS; i++) {
+ /* calculate the change */
+ dev->xy_acc[i] = dev->xy_cur[i] - dev->xy_old[i];
+
+ /* this is a round-robin value, so couple with that */
+ if (dev->xy_acc[i] > 127)
+ dev->xy_acc[i] -= 256;
+
+ if (dev->xy_acc[i] < -127)
+ dev->xy_acc[i] += 256;
+
+ /* prevent down drifting */
+ if (dev->xy_acc[i] < 0)
+ dev->xy_acc[i] = 0;
+ }
+
+ dbg_dump("accumulator", dev->xy_acc);
+
+ x = atp_calculate_abs(dev->xy_acc, ATP_XSENSORS,
+ ATP_XFACT, &x_z, &x_f);
+ y = atp_calculate_abs(dev->xy_acc + ATP_XSENSORS, ATP_YSENSORS,
+ ATP_YFACT, &y_z, &y_f);
+ key = dev->data[dev->datalen - 1] & ATP_STATUS_BUTTON;