[RFT] Adb ams tapping support

View: New views
1 Messages — Rating Filter:   Alert me  

[RFT] Adb ams tapping support

by Andreas Tobler-5 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Hello,

I'm looking for testers.

The attached patch enables tapping support for adb touchpads as found on
my PowerBook G4 15".

The support can be enabled/disabled via 'sysctl dev.ams.0.tapping=1/0.
By default it is off.

In X11 for example a single tap maps on button 2, a double tap maps on
button 3.

If you select a line in a terminal, you can 'paste' the line with a
double tap into a second terminal.

Would be great to get some feedback.

Andreas

Index: sys/dev/adb/adb.h
===================================================================
--- sys/dev/adb/adb.h (revision 194560)
+++ sys/dev/adb/adb.h (working copy)
@@ -69,6 +69,7 @@
 uint8_t adb_set_device_handler(device_t dev, uint8_t newhandler);
 
 size_t adb_read_register(device_t dev, u_char reg, void *data);
+size_t adb_write_register(device_t dev, u_char reg, size_t len, void *data);
 
 /* Bits for implementing ADB host bus adapters */
 extern devclass_t adb_devclass;
Index: sys/dev/adb/adb_bus.c
===================================================================
--- sys/dev/adb/adb_bus.c (revision 194560)
+++ sys/dev/adb/adb_bus.c (working copy)
@@ -402,3 +402,21 @@
  return (result);
 }
 
+size_t
+adb_write_register(device_t dev, u_char reg, size_t len, void *data)
+{
+ struct adb_softc *sc;
+ struct adb_devinfo *dinfo;
+ size_t result;
+
+ dinfo = device_get_ivars(dev);
+ sc = device_get_softc(device_get_parent(dev));
+
+ result = adb_send_raw_packet_sync(sc->sc_dev,dinfo->address,
+   ADB_COMMAND_LISTEN, reg, len, (u_char *)data, NULL);
+
+ result = adb_send_raw_packet_sync(sc->sc_dev,dinfo->address,
+           ADB_COMMAND_TALK, reg, 0, NULL, NULL);
+
+ return (result);
+}
Index: sys/dev/adb/adb_mouse.c
===================================================================
--- sys/dev/adb/adb_mouse.c (revision 194560)
+++ sys/dev/adb/adb_mouse.c (working copy)
@@ -35,6 +35,7 @@
 #include <sys/poll.h>
 #include <sys/condvar.h>
 #include <sys/selinfo.h>
+#include <sys/sysctl.h>
 #include <sys/uio.h>
 #include <sys/fcntl.h>
 #include <sys/kernel.h>
@@ -51,6 +52,8 @@
 static int adb_mouse_probe(device_t dev);
 static int adb_mouse_attach(device_t dev);
 static int adb_mouse_detach(device_t dev);
+static void adb_init_trackpad(device_t dev);
+static int adb_tapping_sysctl(SYSCTL_HANDLER_ARGS);
 
 static d_open_t  ams_open;
 static d_close_t ams_close;
@@ -77,6 +80,7 @@
  u_char id[4];
 
  int buttons;
+ u_int sc_tapping;
  int last_buttons;
  int xdelta, ydelta;
 
@@ -167,6 +171,7 @@
  sc->mode.packetsize = 5;
 
  sc->buttons = 0;
+ sc->sc_tapping = 0;
  sc->last_buttons = 0;
  sc->packet_read_len = 0;
 
@@ -205,6 +210,7 @@
  case 3:
  sc->flags |= AMS_TOUCHPAD;
  sc->hw.type = MOUSE_PAD;
+ adb_init_trackpad(dev);
  description = "Touchpad";
  break;
  }
@@ -259,6 +265,71 @@
  return (0);
 }
 
+static void
+adb_init_trackpad(device_t dev)
+{
+ struct adb_mouse_softc *sc;
+ struct sysctl_ctx_list *ctx;
+ struct sysctl_oid *tree;
+
+ size_t r1_len;
+ u_char r1[8];
+ u_char r2[8];
+
+ sc = device_get_softc(dev);
+
+ r1_len = adb_read_register(dev, 1, r1);
+
+ /* An Extended Mouse register1 must return 8 bytes. */
+ if (r1_len != 8)
+ return;
+
+ if((r1[6] != 0x0d))
+ {
+ r1[6] = 0x0d;
+
+ adb_write_register(dev, 1, 8, r1);
+      
+ r1_len = adb_read_register(dev, 1, r1);
+      
+ if (r1[6] != 0x0d)
+ {
+ device_printf(dev, "ADB Mouse = 0x%x "
+      "(non-Extended Mode)\n", r1[6]);
+ return;
+ } else {
+ device_printf(dev, "ADB Mouse = 0x%x "
+      "(Extended Mode)\n", r1[6]);
+
+ /* Set ADB Extended Features to default values,
+   enabled. */
+ r2[0] = 0x19; /* Clicking: 0x19 disabled 0x99 enabled */
+ r2[1] = 0x94; /* Dragging: 0x14 disabled 0x94 enabled */
+ r2[2] = 0x19;
+ r2[3] = 0xff; /* DragLock: 0xff disabled 0xb2 enabled */
+ r2[4] = 0xb2;
+ r2[5] = 0x8a;
+ r2[6] = 0x1b;
+      
+ r2[7] = 0x57;  /* 0x57 bits 3:0 for W mode */
+ r1_len = 8;
+
+ adb_write_register(dev, 2, 8, r2);
+
+ }
+ }
+ /*
+ * Set up sysctl
+ */
+
+ ctx = device_get_sysctl_ctx(dev);
+ tree = device_get_sysctl_tree(dev);
+ SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(tree), OID_AUTO, "tapping",
+ CTLTYPE_INT | CTLFLAG_RW, sc, 0, adb_tapping_sysctl,
+ "I", "Tapping the pad causes button events");
+ return;
+}
+
 static u_int
 adb_mouse_receive_packet(device_t dev, u_char status, u_char command,
     u_char reg, int len, u_char *data)
@@ -266,7 +337,8 @@
  struct adb_mouse_softc *sc;
  int i = 0;
  int xdelta, ydelta;
- int buttons;
+ int buttons, tmp_buttons;
+ static int prev_button = 0;
 
  sc = device_get_softc(dev);
 
@@ -298,6 +370,30 @@
  if (ydelta & (0x40 << 3*(len-2)))
  ydelta |= 0xffffffc0 << 3*(len - 2);
 
+ if ((sc->flags & AMS_TOUCHPAD) && (sc->sc_tapping == 1)) {
+ tmp_buttons = buttons;
+ if (buttons == 0x12) {
+ /* Map a double tap on button 3.
+   Keep the button state for the next sequence.
+   A double tap sequence is followed by a single tap
+   sequence.
+ */
+ tmp_buttons = 0x3;
+ prev_button = tmp_buttons;
+ } else if (buttons == 0x2) {
+ /* Map a single tap on button 2. But only if it is
+   not a successor from a double tap.
+ */
+ if (prev_button != 0x3)
+ tmp_buttons = 0x2;
+ else
+ tmp_buttons = 0;
+
+ prev_button = 0;
+ }
+ buttons = tmp_buttons;
+ }
+
  /*
  * Some mice report high-numbered buttons on the wrong button number,
  * so set the highest-numbered real button as pressed if there are
@@ -554,3 +650,36 @@
  return (0);
 }
 
+static int
+adb_tapping_sysctl(SYSCTL_HANDLER_ARGS)
+{
+ struct adb_mouse_softc *sc = arg1;
+ device_t dev;
+        int error;
+ u_char r2[8];
+ u_int tapping;
+
+ dev = sc->sc_dev;
+ tapping = sc->sc_tapping;
+
+ error = sysctl_handle_int(oidp, &tapping, 0, req);
+
+ if (error || !req->newptr)
+ return (error);
+
+ if (tapping == 1) {
+ adb_read_register(dev, 2, r2);
+ r2[0] = 0x99; /* enable tapping. */
+ adb_write_register(dev, 2, 8, r2);
+                sc->sc_tapping = 1;
+ } else if (tapping == 0) {
+ adb_read_register(dev, 2, r2);
+ r2[0] = 0x19; /* disable tapping. */
+ adb_write_register(dev, 2, 8, r2);
+ sc->sc_tapping = 0;
+ }
+        else
+ return (EINVAL);
+
+ return (0);
+}

_______________________________________________
freebsd-ppc@... mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-ppc
To unsubscribe, send any mail to "freebsd-ppc-unsubscribe@..."