=================================================================== RCS file: /cvs/sys/arch/jornada/dev/jmcu.c,v retrieving revision 1.2 retrieving revision 1.3 diff -u -r1.2 -r1.3 --- sys/arch/jornada/dev/jmcu.c 2008/03/05 20:31:27 1.2 +++ sys/arch/jornada/dev/jmcu.c 2008/05/11 10:26:11 1.3 @@ -1,4 +1,4 @@ -/* $Id: jmcu.c,v 1.2 2008/03/05 20:31:27 nbrk Exp $ */ +/* $Id: jmcu.c,v 1.3 2008/05/11 09:26:11 nbrk Exp $ */ #include #include #include @@ -23,6 +23,7 @@ #include #include +#include "wskbd.h" #define JMCU_KBD_GPIOINTR 0 #define JMCU_TS_GPIOINTR 15 @@ -32,14 +33,24 @@ struct jmcu_softc { struct device sc_dev; + /* parent SPI stuff */ struct spi_bus *sc_bus; void *sc_spisc; - uint8_t sc_kbdeventsbuf[JMCU_KBD_NEVENTS]; - uint8_t sc_kbdeventsnum; + /* keyboard stuff */ + struct device *sc_wskbddev; + int sc_polling; /* if in 'poll' mode now */ + u_int sc_kbdqtypes[JMCU_KBD_NEVENTS]; + uint8_t sc_kbdqkeys[JMCU_KBD_NEVENTS]; + uint8_t sc_kbdnevents; + + /* battery charge */ + uint16_t sc_batmain; + uint16_t sc_batback; }; struct jmcu_softc *jmcu_sc; + struct wskbd_mapdata jmcukbd_keymapdata = { jmcukbd_keydesctab, KB_US, @@ -53,11 +64,18 @@ int jmcu_kbdintr(void *arg); int jmcu_touchintr(void *arg); void jmcukbd_cngetc(void *v, u_int *type, int *data); -void jmcukbd_enqueue(struct jmcu_softc *sc, uint8_t keycode); -void jmcukbd_dequeue(struct jmcu_softc *sc, uint8_t *keycodep); -void jmcukbd_getcodes(struct jmcu_softc *sc, int block); -void jmcubatt_status(struct jmcu_softc *sc); +void jmcukbd_cnpollc(void *v, int on); +void jmcukbd_poll(void *v); +void jmcukbd_enqueue(struct jmcu_softc *sc, u_int type, uint8_t key); +void jmcukbd_dequeue(struct jmcu_softc *sc, u_int *type, int *data); +void jmcubatt_getstatus(struct jmcu_softc *sc); +void jmcukbd_readcodes(struct jmcu_softc *sc, char *buf); +/* accessops */ +int jmcukbd_enable(void *, int); +void jmcukbd_set_leds(void *, int); +int jmcukbd_ioctl(void *, u_long, caddr_t, int, struct proc *); + /* * Autoconf glue. */ @@ -76,11 +94,17 @@ */ struct wskbd_consops jmcukbd_consops = { jmcukbd_cngetc, - NULL, /* pollc */ + jmcukbd_cnpollc, NULL /* bell */ }; +struct wskbd_accessops jmcukbd_accessops = { + jmcukbd_enable, + jmcukbd_set_leds, + jmcukbd_ioctl, +}; + int jmcu_match(struct device *parent, void *cf, void *aux) { @@ -92,39 +116,50 @@ { struct jmcu_softc *sc = (struct jmcu_softc *)self; struct spibus_attach_args *sba = aux; +#if NWSKBD > 0 struct wskbddev_attach_args wda; - +#endif + /* leap to parent */ sc->sc_bus = sba->sba_bus; sc->sc_spisc = sba->sba_spisc; - printf(": Jornada MCU\n"); - jmcu_sc = sc; - /* XXX */ - jmcubatt_status(sc); + jmcubatt_getstatus(sc); + printf(": Jornada MCU (battery charge: main=%d backup=%d)\n", sc->sc_batmain, sc->sc_batback); + +#if 0 + sa11x0_gpio_intr_establish(JMCU_KBD_GPIOINTR, IST_EDGE_FALLING, IPL_TTY, jmcu_kbdintr, sc, "jmcukbd_intr"); +#endif /* 0 */ + +#if NWSKBD > 0 + /* empty event queue */ + sc->sc_kbdnevents = 0; + wskbd_cnattach(&jmcukbd_consops, sc, &jmcukbd_keymapdata); wda.console = 1; wda.keymap = &jmcukbd_keymapdata; - wda.accessops = NULL; //jmcukbd_accessops; + wda.accessops = &jmcukbd_accessops; wda.accesscookie = sc; - config_found(self, &wda, wskbddevprint); - + sc->sc_wskbddev = config_found(self, &wda, wskbddevprint); +#endif return; } +#if 0 int jmcu_kbdintr(void *arg) { - struct jmcu_softc *sc = arg; - printf("%s: jmcu_kbdintr\n", sc->sc_dev.dv_xname); + jmcukbd_poll(arg); return(0); } +#endif +#if 0 int jmcu_touchintr(void *arg) { @@ -133,84 +168,128 @@ return(0); } +#endif void jmcukbd_cngetc(void *v, u_int *type, int *data) { struct jmcu_softc *sc = v; - uint8_t ourdata; - printf("jmcukbd_cngetc:\n"); + /* XXX we should block until new keycode has been obtained */ - if (sc->sc_kbdeventsnum == 0) - jmcukbd_getcodes(sc, 1); /* note that we've passed blocking flag */ + sc->sc_polling = 1; + while (sc->sc_kbdnevents == 0) { + /* enqueue events */ + jmcukbd_poll(v); + } + sc->sc_polling = 0; - jmcukbd_dequeue(sc, &ourdata); + jmcukbd_dequeue(sc, type, data); +} - *data = ourdata & 0x7f; - *type = ourdata & 0x80 ? WSCONS_EVENT_KEY_UP : WSCONS_EVENT_KEY_DOWN; +void +jmcukbd_cnpollc(void *v, int on) +{ + } void -jmcukbd_getcodes(struct jmcu_softc *sc, int block) +jmcukbd_poll(void *v) { + struct jmcu_softc *sc = v; + u_int type; + int key, s; + char buf[JMCU_KBD_NEVENTS + 1], *p; + + s = spltty(); + + jmcukbd_readcodes(sc, buf); + + for (p = buf; *p; p++) { + type = *p & 0x80 ? WSCONS_EVENT_KEY_UP : WSCONS_EVENT_KEY_DOWN; + key = *p & 0x7f; + + /* XXX */ + if (sc->sc_polling == 0) + wskbd_input(sc->sc_wskbddev, type, key); + else { + /* enqueue event */ + jmcukbd_enqueue(sc, type, key); + } + } + + splx(s); +} + +void +jmcukbd_readcodes(struct jmcu_softc *sc, char *buf) +{ int nkeys; - uint8_t keycode; /* wake up the MCU */ sa11x0_gpio_clear_bit(25); spi_acquire(sc->sc_spisc); - do { - /* ask mcu about how many keypress events are there; should get TXDUMMY here */ - if (spi_shift_1(sc->sc_spisc, JMCU_CMD_GETKEYCODES) != JMCU_CMD_TXDUMMY) + /* ask mcu about how many keypress events are there; should get TXDUMMY here */ + if (spi_shift_1(sc->sc_spisc, JMCU_CMD_GETKEYCODES) != JMCU_CMD_TXDUMMY) { printf("%s: WARNING, no txdummy received\n", sc->sc_dev.dv_xname); - nkeys = spi_shift_1(sc->sc_spisc, JMCU_CMD_TXDUMMY); - } while(nkeys == 0 && block); + goto out; + } + nkeys = spi_shift_1(sc->sc_spisc, JMCU_CMD_TXDUMMY); + while (nkeys) { - keycode = spi_shift_1(sc->sc_spisc, JMCU_CMD_TXDUMMY); - jmcukbd_enqueue(sc, keycode); + *buf = spi_shift_1(sc->sc_spisc, JMCU_CMD_TXDUMMY); nkeys--; + buf++; } + +out: + /* terminate buffer */ + *buf = 0; + spi_release(sc->sc_spisc); /* park off the MCU */ sa11x0_gpio_set_bit(25); } + void -jmcukbd_enqueue(struct jmcu_softc *sc, uint8_t keycode) +jmcukbd_enqueue(struct jmcu_softc *sc, u_int type, uint8_t key) { - if (sc->sc_kbdeventsnum >= JMCU_KBD_NEVENTS) { - printf("%s: WARNING, event queue is full; keycode 0x%x will be discarded\n", sc->sc_dev.dv_xname, keycode); + + if (sc->sc_kbdnevents > JMCU_KBD_NEVENTS) { + printf("%s: WARNING, event queue is full; keycode 0x%x will be discarded\n", sc->sc_dev.dv_xname, key); return; } - sc->sc_kbdeventsbuf[sc->sc_kbdeventsnum] = keycode; - sc->sc_kbdeventsnum++; + sc->sc_kbdqtypes[sc->sc_kbdnevents] = type; + sc->sc_kbdqkeys[sc->sc_kbdnevents] = key; + sc->sc_kbdnevents++; } void -jmcukbd_dequeue(struct jmcu_softc *sc, uint8_t *keycodep) +jmcukbd_dequeue(struct jmcu_softc *sc, u_int *type, int *data) { +#if 0 if (sc->sc_kbdeventsnum < 1) { printf("%s: WARNING, event queue is empty\n", sc->sc_dev.dv_xname); return; } - - sc->sc_kbdeventsnum--; - *keycodep = sc->sc_kbdeventsbuf[sc->sc_kbdeventsnum]; +#endif + sc->sc_kbdnevents--; + *type = sc->sc_kbdqtypes[sc->sc_kbdnevents]; + *data = sc->sc_kbdqkeys[sc->sc_kbdnevents]; } + void -jmcubatt_status(struct jmcu_softc *sc) +jmcubatt_getstatus(struct jmcu_softc *sc) { - uint16_t mainbatt; - uint16_t backbatt; uint8_t fraction; /* wake up the MCU */ @@ -218,8 +297,8 @@ spi_acquire(sc->sc_spisc); spi_shift_1(sc->sc_spisc, JMCU_CMD_GETBATTERYDATA); - mainbatt = spi_shift_1(sc->sc_spisc, JMCU_CMD_TXDUMMY); - backbatt = spi_shift_1(sc->sc_spisc, JMCU_CMD_TXDUMMY); + sc->sc_batmain = spi_shift_1(sc->sc_spisc, JMCU_CMD_TXDUMMY); + sc->sc_batback = spi_shift_1(sc->sc_spisc, JMCU_CMD_TXDUMMY); fraction = spi_shift_1(sc->sc_spisc, JMCU_CMD_TXDUMMY); spi_release(sc->sc_spisc); @@ -227,9 +306,49 @@ sa11x0_gpio_set_bit(25); /* fraction[0:1] is mainbatt[8:9]; fraction[2:3] is backbatt[8:9] */ - mainbatt |= (uint16_t)((fraction & 0x03) << 8); - backbatt |= (uint16_t)((fraction & 0xc0) << 6); + sc->sc_batmain |= (uint16_t)((fraction & 0x03) << 8); + sc->sc_batback |= (uint16_t)((fraction & 0x0c) << 6); +} - printf("%s: battery status: main %d, backup %d\n", sc->sc_dev.dv_xname, mainbatt, backbatt); +int +jmcukbd_enable(void *v, int on) +{ + return 0; } + +void +jmcukbd_set_leds(void *v, int on) +{ +} + +int +jmcukbd_ioctl(void *v, u_long cmd, caddr_t data, int flag, struct proc *p) +{ +#ifdef WSDISPLAY_COMPAT_RAWKBD + struct jmcukbd_softc *sc = v; +#endif + + switch (cmd) { + + case WSKBDIO_GTYPE: + *(int *)data = WSKBD_TYPE_ZAURUS /* XXX WSKBD_TYPE_JORNADA */; + return 0; + case WSKBDIO_SETLEDS: + return 0; + case WSKBDIO_GETLEDS: + *(int *)data = 0; + return 0; +#ifdef WSDISPLAY_COMPAT_RAWKBD + case WSKBDIO_SETMODE: + sc->sc_rawkbd = *(int *)data == WSKBD_RAW; + timeout_del(&sc->sc_rawrepeat_ch); + return (0); +#endif + + } + /* kbdioctl(...); */ + + return -1; +} +