Index: j720tp.c =================================================================== RCS file: /cvsroot/src/sys/arch/hpcarm/dev/j720tp.c,v retrieving revision 1.2 diff -u -r1.2 j720tp.c --- j720tp.c 27 Jun 2006 14:36:50 -0000 1.2 +++ j720tp.c 24 Sep 2006 18:30:43 -0000 @@ -41,6 +41,11 @@ #include __KERNEL_RCSID(0, "$NetBSD: j720tp.c,v 1.2 2006/06/27 14:36:50 peter Exp $"); +#ifdef _KERNEL_OPT +#include "opt_j720tp.h" +#include "opt_wsdisplay_compat.h" +#endif + #include #include #include @@ -48,6 +53,7 @@ #include #include #include +#include #include #include @@ -59,27 +65,44 @@ #include #include +#include +#include +#include #include #include -#include "opt_j720tp.h" +#ifdef WSDISPLAY_COMPAT_RAWKBD +#include +#endif + +#define arraysize(ary) (sizeof(ary) / sizeof(ary[0])) #ifdef J720TP_DEBUG -#define DPRINTF(arg) printf arg +int j720tp_debug = 0; +#define DPRINTF(arg) if (j720tp_debug) printf arg +#define DPRINTFN(n, arg) if (j720tp_debug >= (n)) printf arg #else -#define DPRINTF(arg) /* nothing */ +#define DPRINTF(arg) /* nothing */ +#define DPRINTFN(n, arg) /* nothing */ #endif struct j720tp_softc { struct device sc_dev; +#define J720TP_WSMOUSE_ENABLED 0x01 +#define J720TP_WSKBD_ENABLED 0x02 int sc_enabled; + int sc_hard_icon; +#ifdef WSDISPLAY_COMPAT_RAWKBD + int sc_rawkbd; +#endif struct callout sc_tpcallout; struct j720ssp_softc *sc_ssp; struct device *sc_wsmousedev; + struct device *sc_wskbddev; struct tpcalib_softc sc_tpcalib; }; @@ -92,13 +115,19 @@ struct lwp *); static void j720tp_wsmouse_disable(void *); +static int j720tp_wskbd_enable(void *, int); +static void j720tp_wskbd_set_leds(void *, int); +static int j720tp_wskbd_ioctl(void *, u_long, caddr_t, int, struct lwp *); + static void j720tp_enable_intr(struct j720tp_softc *); static void j720tp_disable_intr(struct j720tp_softc *); static int j720tp_intr(void *); static int j720tp_get_rawxy(struct j720tp_softc *, int *, int *); +static int j720tp_get_hard_icon(struct j720tp_softc *, int, int); static void j720tp_wsmouse_input(struct j720tp_softc *, int, int); static void j720tp_wsmouse_callout(void *); - +static void j720tp_wskbd_input(struct j720tp_softc *, u_int); +static void j720tp_wskbd_callout(void *); const struct wsmouse_accessops j720tp_wsmouse_accessops = { j720tp_wsmouse_enable, @@ -115,6 +144,63 @@ { 88, 940, 639, 239 }} }; +const struct wskbd_accessops j720tp_wskbd_accessops = { + j720tp_wskbd_enable, + j720tp_wskbd_set_leds, + j720tp_wskbd_ioctl +}; + +#ifndef J720TP_SETTINGS_ICON_KEYSYM +#define J720TP_SETTINGS_ICON_KEYSYM KS_Home +#endif +#ifndef J720TP_BACKUP_ICON_KEYSYM +#define J720TP_BACKUP_ICON_KEYSYM KS_Prior +#endif +#ifndef J720TP_DIALUP_ICON_KEYSYM +#define J720TP_DIALUP_ICON_KEYSYM KS_Next +#endif +#ifndef J720TP_MEDIA_ICON_KEYSYM +#define J720TP_MEDIA_ICON_KEYSYM KS_End +#endif + +/* Max Y value of the n'th hard icon. */ +#define J720TP_HARD_ICON_MAX_Y(n) \ + (((j720tp_hard_icon_bottom - j720tp_hard_icon_top) / 4) * (n)) + \ + j720tp_hard_icon_top + +/* Default raw X/Y values of the hard icon area. */ +static int j720tp_hard_icon_left = 70; +static int j720tp_hard_icon_right = 20; +static int j720tp_hard_icon_top = 70; +static int j720tp_hard_icon_bottom = 940; + +/* Maps the icon number to a raw keycode. */ +static const int j720tp_wskbd_keys[] = { + /* Icon 1 */ 199, + /* Icon 2 */ 201, + /* Icon 3 */ 209, + /* Icon 4 */ 207 +}; + +static const keysym_t j720tp_wskbd_keydesc[] = { + KS_KEYCODE(199), J720TP_SETTINGS_ICON_KEYSYM, + KS_KEYCODE(201), J720TP_BACKUP_ICON_KEYSYM, + KS_KEYCODE(209), J720TP_DIALUP_ICON_KEYSYM, + KS_KEYCODE(207), J720TP_MEDIA_ICON_KEYSYM +}; + +const struct wscons_keydesc j720tp_wskbd_keydesctab[] = { + { KB_US, 0, + sizeof(j720tp_wskbd_keydesc) / sizeof(keysym_t), + j720tp_wskbd_keydesc + }, + { 0, 0, 0, 0 } +}; + +const struct wskbd_mapdata j720tp_wskbd_keymapdata = { + j720tp_wskbd_keydesctab, KB_US +}; + CFATTACH_DECL(j720tp, sizeof(struct j720tp_softc), j720tp_match, j720tp_attach, NULL, NULL); @@ -134,13 +220,16 @@ static void j720tp_attach(struct device *parent, struct device *self, void *aux) { - struct j720tp_softc *sc = (struct j720tp_softc *)self; + struct j720tp_softc *sc = (struct j720tp_softc *)self; struct wsmousedev_attach_args wsma; + struct wskbddev_attach_args wska; printf("\n"); sc->sc_ssp = (struct j720ssp_softc *)parent; sc->sc_enabled = 0; + sc->sc_hard_icon = 0; + sc->sc_rawkbd = 0; /* Touch-panel as a pointing device. */ wsma.accessops = &j720tp_wsmouse_accessops; @@ -148,6 +237,8 @@ sc->sc_wsmousedev = config_found_ia(self, "wsmousedev", &wsma, wsmousedevprint); + if (sc->sc_wsmousedev == NULL) + return; /* Initialize calibration, set default parameters. */ tpcalib_init(&sc->sc_tpcalib); @@ -157,6 +248,15 @@ j720tp_wsmouse_disable(sc); callout_init(&sc->sc_tpcallout); + /* On-screen "hard icons" as a keyboard device. */ + wska.console = 0; + wska.keymap = &j720tp_wskbd_keymapdata; + wska.accessops = &j720tp_wskbd_accessops; + wska.accesscookie = sc; + + sc->sc_wskbddev = config_found_ia(self, "wskbddev", &wska, + wskbddevprint); + /* Setup touch-panel interrupt. */ sa11x0_intr_establish(0, 9, 1, IPL_TTY, j720tp_intr, sc); } @@ -171,7 +271,7 @@ j720tp_enable_intr(sc); - sc->sc_enabled = 1; + sc->sc_enabled |= J720TP_WSMOUSE_ENABLED; splx(s); return 0; @@ -197,11 +297,55 @@ j720tp_disable_intr(sc); callout_stop(&sc->sc_tpcallout); - sc->sc_enabled = 0; + sc->sc_enabled &= ~J720TP_WSMOUSE_ENABLED; splx(s); } +static int +j720tp_wskbd_enable(void *self, int on) +{ + struct j720tp_softc *sc = self; + int s; + + s = spltty(); + sc->sc_enabled |= J720TP_WSKBD_ENABLED; + splx(s); + + return 0; +} + +static void +j720tp_wskbd_set_leds(void *self, int leds) +{ + /* nothing to do */ +} + +static int +j720tp_wskbd_ioctl(void *self, u_long cmd, caddr_t data, int flag, + struct lwp *l) +{ +#ifdef WSDISPLAY_COMPAT_RAWKBD + struct j720tp_softc *sc = self; +#endif + + switch (cmd) { + case WSKBDIO_GTYPE: + *(int *)data = WSKBD_TYPE_HPC_BTN; + return 0; + case WSKBDIO_GETLEDS: + *(int *)data = 0; + return 0; +#ifdef WSDISPLAY_COMPAT_RAWKBD + case WSKBDIO_SETMODE: + sc->sc_rawkbd = (*(int *)data == WSKBD_RAW); + return 0; +#endif + } + + return EPASSTHROUGH; +} + /* * Enable touch-panel interrupt. Must be called at spltty(). */ @@ -239,17 +383,26 @@ bus_space_write_4(ssp->sc_iot, ssp->sc_gpioh, SAGPIO_EDR, 1 << 9); - if (!sc->sc_enabled) { + if (!(sc->sc_enabled & J720TP_WSMOUSE_ENABLED)) { DPRINTF(("j720tp_intr: !sc_enabled\n")); return 0; } j720tp_disable_intr(sc); - if (j720tp_get_rawxy(sc, &rawx, &rawy)) - j720tp_wsmouse_input(sc, rawx, rawy); + if (j720tp_get_rawxy(sc, &rawx, &rawy)) { + sc->sc_hard_icon = j720tp_get_hard_icon(sc, rawx, rawy); - callout_reset(&sc->sc_tpcallout, hz / 32, j720tp_wsmouse_callout, sc); + if (sc->sc_hard_icon > 0) { + j720tp_wskbd_input(sc, WSCONS_EVENT_KEY_DOWN); + callout_reset(&sc->sc_tpcallout, hz / 32, + j720tp_wskbd_callout, sc); + } else { + j720tp_wsmouse_input(sc, rawx, rawy); + callout_reset(&sc->sc_tpcallout, hz / 32, + j720tp_wsmouse_callout, sc); + } + } return 1; } @@ -285,10 +438,8 @@ buf[7] >>= 2; } -#if 0 - DPRINTF(("j720tp_get_rawxy: %d:%d:%d:%d:%d:%d:%d:%d\n", buf[0], buf[1], - buf[2], buf[3], buf[4], buf[5], buf[6], buf[7])); -#endif + DPRINTFN(2, ("j720tp_get_rawxy: %d:%d:%d:%d:%d:%d:%d:%d\n", + buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6], buf[7])); *rawx = buf[1]; *rawy = buf[4]; @@ -306,6 +457,29 @@ return 0; } +static int +j720tp_get_hard_icon(struct j720tp_softc *sc, int rawx, int rawy) +{ + int icon = 0; + + if (!(sc->sc_enabled & J720TP_WSKBD_ENABLED)) + return 0; + /* Check if the touch was in the hard icons area. */ + if (rawx > j720tp_hard_icon_left) + return 0; + + if (rawy < J720TP_HARD_ICON_MAX_Y(1)) + icon = 1; + else if (rawy < J720TP_HARD_ICON_MAX_Y(2)) + icon = 2; + else if (rawy < J720TP_HARD_ICON_MAX_Y(3)) + icon = 3; + else if (rawy < J720TP_HARD_ICON_MAX_Y(4)) + icon = 4; + + return icon; +} + static void j720tp_wsmouse_input(struct j720tp_softc *sc, int rawx, int rawy) { @@ -325,7 +499,7 @@ s = spltty(); - if (!sc->sc_enabled) { + if (!(sc->sc_enabled & J720TP_WSMOUSE_ENABLED)) { DPRINTF(("j720tp_wsmouse_callout: !sc_enabled\n")); splx(s); return; @@ -337,9 +511,109 @@ } else { if (j720tp_get_rawxy(sc, &rawx, &rawy)) j720tp_wsmouse_input(sc, rawx, rawy); + callout_schedule(&sc->sc_tpcallout, hz / 32); + } + + splx(s); +} + +static void +j720tp_wskbd_input(struct j720tp_softc *sc, u_int evtype) +{ + int key = j720tp_wskbd_keys[sc->sc_hard_icon - 1]; + +#ifdef WSDISPLAY_COMPAT_RAWKBD + if (sc->sc_rawkbd) { + int n; + u_char data[16]; + + n = pckbd_encode(evtype, key, data); + wskbd_rawinput(sc->sc_wskbddev, data, n); + } else +#endif + wskbd_input(sc->sc_wskbddev, evtype, key); +} + +static void +j720tp_wskbd_callout(void *arg) +{ + struct j720tp_softc *sc = arg; + struct j720ssp_softc *ssp = sc->sc_ssp; + int s; + + s = spltty(); + + if (!sc->sc_enabled) { + DPRINTF(("j720tp_wskbd_callout: !sc_enabled\n")); + splx(s); + return; + } + if (bus_space_read_4(ssp->sc_iot, ssp->sc_gpioh, SAGPIO_PLR) & (1<<9)) { + j720tp_wskbd_input(sc, WSCONS_EVENT_KEY_UP); + j720tp_enable_intr(sc); + } else { callout_schedule(&sc->sc_tpcallout, hz / 32); } splx(s); } + +SYSCTL_SETUP(sysctl_j720tp, "sysctl j720tp subtree setup") +{ + const struct sysctlnode *rnode; + int rc; + + if ((rc = sysctl_createv(clog, 0, NULL, &rnode, + CTLFLAG_PERMANENT, CTLTYPE_NODE, "hw", NULL, + NULL, 0, NULL, 0, CTL_HW, CTL_EOL)) != 0) + goto err; + + if ((rc = sysctl_createv(clog, 0, &rnode, &rnode, + CTLFLAG_PERMANENT, CTLTYPE_NODE, "j720tp", + SYSCTL_DESCR("Jornada 720 touch panel controls"), + NULL, 0, NULL, 0, CTL_CREATE, CTL_EOL)) != 0) + goto err; + +#ifdef J720TP_DEBUG + if ((rc = sysctl_createv(clog, 0, &rnode, NULL, + CTLFLAG_PERMANENT | CTLFLAG_READWRITE, CTLTYPE_INT, "debug", + SYSCTL_DESCR("Verbosity of debugging messages"), + NULL, 0, &j720tp_debug, 0, CTL_CREATE, CTL_EOL)) != 0) + goto err; +#endif /* J720TP_DEBUG */ + + if ((rc = sysctl_createv(clog, 0, &rnode, &rnode, + CTLFLAG_PERMANENT, CTLTYPE_NODE, "hard_icons", + SYSCTL_DESCR("Touch panel hard icons controls"), + NULL, 0, NULL, 0, CTL_CREATE, CTL_EOL)) != 0) + goto err; + + if ((rc = sysctl_createv(clog, 0, &rnode, NULL, + CTLFLAG_PERMANENT | CTLFLAG_READWRITE, CTLTYPE_INT, "left", + SYSCTL_DESCR("Raw left X value of the hard icon area"), + NULL, 0, &j720tp_hard_icon_left, 0, CTL_CREATE, CTL_EOL)) != 0) + goto err; + + if ((rc = sysctl_createv(clog, 0, &rnode, NULL, + CTLFLAG_PERMANENT | CTLFLAG_READWRITE, CTLTYPE_INT, "right", + SYSCTL_DESCR("Raw right X value of the hard icon area"), + NULL, 0, &j720tp_hard_icon_right, 0, CTL_CREATE, CTL_EOL)) != 0) + goto err; + + if ((rc = sysctl_createv(clog, 0, &rnode, NULL, + CTLFLAG_PERMANENT | CTLFLAG_READWRITE, CTLTYPE_INT, "top", + SYSCTL_DESCR("Raw top Y value of the hard icon area"), + NULL, 0, &j720tp_hard_icon_top, 0, CTL_CREATE, CTL_EOL)) != 0) + goto err; + + if ((rc = sysctl_createv(clog, 0, &rnode, NULL, + CTLFLAG_PERMANENT | CTLFLAG_READWRITE, CTLTYPE_INT, "bottom", + SYSCTL_DESCR("Raw bottom Y value of the hard icon area"), + NULL, 0, &j720tp_hard_icon_bottom, 0, CTL_CREATE, CTL_EOL)) != 0) + goto err; + + return; +err: + printf("%s: sysctl_createv failed (rc = %d)\n", __func__, rc); +}