Date: Thu, 25 Jun 2009 10:19:11 +0200 From: Andreas Tobler <andreast-list@fgznet.ch> To: FreeBSD PowerPC ML <freebsd-ppc@freebsd.org>, Nathan Whitehorn <nwhitehorn@freebsd.org> Subject: [RFT] Adb ams tapping support Message-ID: <4A4332FF.6030402@fgznet.ch>
next in thread | raw e-mail | index | archive | help
This is a multi-part message in MIME format. --------------050408020106010401080507 Content-Type: text/plain; charset=ISO-8859-1; format=flowed Content-Transfer-Encoding: 7bit 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 --------------050408020106010401080507 Content-Type: text/plain; x-mac-type="0"; x-mac-creator="0"; name="ams_tapping.diff" Content-Transfer-Encoding: 7bit Content-Disposition: inline; filename="ams_tapping.diff" 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); +} --------------050408020106010401080507--
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?4A4332FF.6030402>