new, simplified ADB drivers

This commit is contained in:
macallan 2007-01-17 23:20:16 +00:00
parent b2962c40b6
commit fcde3ac6f3
6 changed files with 2215 additions and 0 deletions

282
sys/dev/adb/adb_bus.c Normal file
View File

@ -0,0 +1,282 @@
/* $NetBSD: adb_bus.c,v 1.1 2007/01/17 23:20:16 macallan Exp $ */
/*-
* Copyright (c) 2006 Michael Lorenz
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of The NetBSD Foundation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: adb_bus.c,v 1.1 2007/01/17 23:20:16 macallan Exp $");
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/kernel.h>
#include <sys/device.h>
#include <sys/proc.h>
#include <machine/bus.h>
#include <machine/autoconf.h>
#include <dev/adb/adbvar.h>
#include "adbdebug.h"
#ifdef ADB_DEBUG
#define DPRINTF printf
#else
#define DPRINTF while (0) printf
#endif
static int nadb_match(struct device *, struct cfdata *, void *);
static void nadb_attach(struct device *, struct device *, void *);
struct nadb_softc {
struct device sc_dev;
struct adb_bus_accessops *sc_ops;
uint32_t sc_msg;
uint32_t sc_event;
struct adb_device sc_devtable[16];
int sc_free; /* highest free address */
int sc_len; /* length of received message */
uint8_t sc_data[16];
};
CFATTACH_DECL(nadb, sizeof(struct nadb_softc),
nadb_match, nadb_attach, NULL, NULL);
static void nadb_init(struct device *);
static void nadb_handler(void *, int, uint8_t *);
static void nadb_send_sync(void *, int, int, uint8_t *);
static int nadb_register(struct nadb_softc *, int, int, int);
static void nadb_remove(struct nadb_softc *, int);
static int nadb_devprint(void *, const char *);
static int
nadb_match(struct device *parent, struct cfdata *cf, void *aux)
{
return 1;
}
static void
nadb_attach(struct device *parent, struct device *us, void *aux)
{
struct nadb_softc *sc = (struct nadb_softc *)us;
struct adb_bus_accessops *ops = aux;
sc->sc_ops = ops;
sc->sc_ops->set_handler(sc->sc_ops->cookie, nadb_handler, sc);
config_interrupts(us, nadb_init);
}
static void
nadb_init(struct device *dev)
{
struct nadb_softc *sc = (struct nadb_softc *)dev;
struct adb_attach_args aaa;
int i, last_moved_up, devmask = 0;
uint8_t cmd[2];
sc->sc_free = 15;
for (i = 0; i < 16; i++) {
sc->sc_devtable[i].original_addr = 0;
sc->sc_devtable[i].current_addr = 0;
sc->sc_devtable[i].handler_id = 0;
sc->sc_devtable[i].cookie = NULL;
sc->sc_devtable[i].handler = NULL;
}
/* bus reset (?) */
//nadb_send_sync(sc, 0, 0, NULL);
//delay(200000);
/*
* scan only addresses 1 - 7
* if something responds move it to >7 and see if something else is
* there. If not move the previous one back.
* XXX we don't check for collisions if we use up all addresses >7
*/
for (i = 1; i < 8; i++) {
DPRINTF("\n%d: ", i);
last_moved_up = 0;
nadb_send_sync(sc, ADBTALK(i, 3), 0, NULL);
/* found something? */
while (sc->sc_len > 2) {
/* something answered, so move it up */
DPRINTF("Found a device on address %d\n", i);
cmd[0] = sc->sc_free | 0x60;
cmd[1] = 0xfe;
nadb_send_sync(sc, ADBLISTEN(i, 3), 2, cmd);
/* see if it really moved */
nadb_send_sync(sc, ADBTALK(sc->sc_free, 3), 0, NULL);
if (sc->sc_len > 2) {
/* ok */
DPRINTF("moved it to %d\n", sc->sc_free);
nadb_register(sc, sc->sc_free, i, sc->sc_data[3]);
last_moved_up = sc->sc_free;
sc->sc_free--;
}
/* see if something else is there */
nadb_send_sync(sc, ADBTALK(i, 3), 0, NULL);
}
if (last_moved_up != 0) {
/* move last one back to original address */
cmd[0] = i | 0x60;
cmd[1] = 0xfe;
nadb_send_sync(sc, ADBLISTEN(last_moved_up, 3), 2, cmd);
nadb_send_sync(sc, ADBTALK(i, 3), 0, NULL);
if (sc->sc_len > 2) {
DPRINTF("moved %d back to %d\n", last_moved_up, i);
nadb_remove(sc, last_moved_up);
nadb_register(sc, i, i, sc->sc_data[3]);
sc->sc_free = last_moved_up;
}
}
}
/* now attach the buggers we've found */
aaa.ops = sc->sc_ops;
for (i = 0; i < 16; i++) {
if (sc->sc_devtable[i].current_addr != 0) {
DPRINTF("dev: %d %d %02x\n",
sc->sc_devtable[i].current_addr,
sc->sc_devtable[i].original_addr,
sc->sc_devtable[i].handler_id);
aaa.dev = &sc->sc_devtable[i];
if (config_found(&sc->sc_dev, &aaa, nadb_devprint)) {
devmask |= (1 << i);
} else {
printf(" not configured\n");
}
}
}
/* now enable autopolling */
DPRINTF("devmask: %04x\n", devmask);
sc->sc_ops->autopoll(sc->sc_ops->cookie, devmask);
}
int
nadb_print(void *aux, const char *what)
{
printf(": Apple Desktop Bus\n");
return 0;
}
static int
nadb_devprint(void *aux, const char *what)
{
struct adb_attach_args *aaa = aux;
switch(aaa->dev->original_addr) {
case 2:
printf(": ADB Keyboard");
break;
case 3:
printf(": ADB relative pointing device");
break;
default:
printf(": something from address %d:%02x",
aaa->dev->original_addr,
aaa->dev->handler_id);
break;
}
return 0;
}
static void
nadb_handler(void *cookie, int len, uint8_t *data)
{
struct nadb_softc *sc = cookie;
struct adb_device *dev;
int addr;
#ifdef ADB_DEBUG
int i;
printf("adb:");
for (i = 0; i < len; i++) {
printf(" %02x", data[i]);
}
printf("\n");
#endif
addr = data[1] >> 4;
dev = &sc->sc_devtable[addr];
if ((dev->current_addr != 0) && (dev->handler != NULL)) {
dev->handler(dev->cookie, len, data);
} else {
sc->sc_msg = 1;
sc->sc_len = len;
memcpy(sc->sc_data, data, len);
wakeup(&sc->sc_event);
}
}
static void
nadb_send_sync(void *cookie, int command, int len, uint8_t *data)
{
struct nadb_softc *sc = cookie;
sc->sc_msg = 0;
sc->sc_ops->send(sc->sc_ops->cookie, 0, command, len, data);
while (sc->sc_msg == 0) {
tsleep(&sc->sc_event, 0, "adb_send", 100);
}
}
static int
nadb_register(struct nadb_softc *sc, int current, int orig, int handler)
{
struct adb_device *dev;
if ((current > 0) && (current < 16)) {
dev = &sc->sc_devtable[current];
if (dev->current_addr != 0)
/* in use! */
return -1;
dev->current_addr = current;
dev->original_addr = orig;
dev->handler_id = handler;
return 0;
}
return -1;
}
static void
nadb_remove(struct nadb_softc *sc, int addr)
{
if ((addr > 0) && (addr < 16)) {
sc->sc_devtable[addr].current_addr = 0;
sc->sc_devtable[addr].original_addr = 0;
sc->sc_devtable[addr].handler_id = 0;
}
}

661
sys/dev/adb/adb_kbd.c Normal file
View File

@ -0,0 +1,661 @@
/* $NetBSD: adb_kbd.c,v 1.1 2007/01/17 23:20:16 macallan Exp $ */
/*
* Copyright (C) 1998 Colin Wood
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by Colin Wood.
* 4. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: adb_kbd.c,v 1.1 2007/01/17 23:20:16 macallan Exp $");
#include <sys/param.h>
#include <sys/device.h>
#include <sys/fcntl.h>
#include <sys/poll.h>
#include <sys/select.h>
#include <sys/proc.h>
#include <sys/systm.h>
#include <sys/kernel.h>
#include <sys/sysctl.h>
#include <dev/wscons/wsconsio.h>
#include <dev/wscons/wskbdvar.h>
#include <dev/wscons/wsksymdef.h>
#include <dev/wscons/wsksymvar.h>
#include <dev/wscons/wsmousevar.h>
#include <machine/autoconf.h>
#define KEYBOARD_ARRAY
#include <machine/keyboard.h>
#include <machine/adbsys.h>
#include <dev/adb/adbvar.h>
#include <dev/adb/adb_keymap.h>
#include "adbdebug.h"
struct adbkbd_softc {
struct device sc_dev;
struct adb_device *sc_adbdev;
struct adb_bus_accessops *sc_ops;
struct device *sc_wskbddev;
struct device *sc_wsmousedev;
int sc_leds;
int sc_have_led_control;
int sc_msg_len;
int sc_event;
int sc_poll;
int sc_polled_chars;
int sc_trans[3];
int sc_capslock;
#ifdef WSDISPLAY_COMPAT_RAWKBD
int sc_rawkbd;
#endif
uint8_t sc_buffer[16];
uint8_t sc_pollbuf[16];
uint8_t sc_us;
};
/*
* Function declarations.
*/
static int adbkbd_match(struct device *, struct cfdata *, void *);
static void adbkbd_attach(struct device *, struct device *, void *);
static void adbkbd_initleds(struct adbkbd_softc *);
static void adbkbd_keys(struct adbkbd_softc *, uint8_t, uint8_t);
static inline void adbkbd_key(struct adbkbd_softc *, uint8_t);
static int adbkbd_wait(struct adbkbd_softc *, int);
/* Driver definition. */
CFATTACH_DECL(adbkbd, sizeof(struct adbkbd_softc),
adbkbd_match, adbkbd_attach, NULL, NULL);
extern struct cfdriver akbd_cd;
static int adbkbd_enable(void *, int);
static int adbkbd_ioctl(void *, u_long, caddr_t, int, struct lwp *);
static void adbkbd_set_leds(void *, int);
static void adbkbd_handler(void *, int, uint8_t *);
struct wskbd_accessops adbkbd_accessops = {
adbkbd_enable,
adbkbd_set_leds,
adbkbd_ioctl,
};
static void adbkbd_cngetc(void *, u_int *, int *);
static void adbkbd_cnpollc(void *, int);
struct wskbd_consops adbkbd_consops = {
adbkbd_cngetc,
adbkbd_cnpollc,
};
struct wskbd_mapdata adbkbd_keymapdata = {
akbd_keydesctab,
#ifdef AKBD_LAYOUT
AKBD_LAYOUT,
#else
KB_US,
#endif
};
static int adbkms_enable(void *);
static int adbkms_ioctl(void *, u_long, caddr_t, int, struct lwp *);
static void adbkms_disable(void *);
const struct wsmouse_accessops adbkms_accessops = {
adbkms_enable,
adbkms_ioctl,
adbkms_disable,
};
static int adbkbd_sysctl_button(SYSCTLFN_ARGS);
static void adbkbd_setup_sysctl(struct adbkbd_softc *);
#ifdef ADBKBD_DEBUG
#define DPRINTF printf
#else
#define DPRINTF while (0) printf
#endif
static int adbkbd_is_console = 0;
static int adbkbd_console_attached = 0;
static int
adbkbd_match(parent, cf, aux)
struct device *parent;
struct cfdata *cf;
void *aux;
{
struct adb_attach_args *aaa = aux;
if (aaa->dev->original_addr == ADBADDR_KBD)
return 1;
else
return 0;
}
static void
adbkbd_attach(struct device *parent, struct device *self, void *aux)
{
struct adbkbd_softc *sc = (struct adbkbd_softc *)self;
struct adb_attach_args *aaa = aux;
short cmd;
struct wskbddev_attach_args a;
struct wsmousedev_attach_args am;
sc->sc_ops = aaa->ops;
sc->sc_adbdev = aaa->dev;
sc->sc_adbdev->cookie = sc;
sc->sc_adbdev->handler = adbkbd_handler;
sc->sc_us = ADBTALK(sc->sc_adbdev->current_addr, 0);
sc->sc_leds = 0; /* initially off */
sc->sc_have_led_control = 0;
sc->sc_msg_len = 0;
sc->sc_poll = 0;
sc->sc_capslock = 0;
sc->sc_trans[1] = 103; /* F11 */
sc->sc_trans[2] = 111; /* F12 */
printf(" addr %d ", sc->sc_adbdev->current_addr);
switch (sc->sc_adbdev->handler_id) {
case ADB_STDKBD:
printf("standard keyboard\n");
break;
case ADB_ISOKBD:
printf("standard keyboard (ISO layout)\n");
break;
case ADB_EXTKBD:
cmd = ADBTALK(sc->sc_adbdev->current_addr, 1);
sc->sc_msg_len = 0;
sc->sc_ops->send(sc->sc_ops->cookie, sc->sc_poll, cmd, 0, NULL);
adbkbd_wait(sc, 10);
/* Ignore Logitech MouseMan/Trackman pseudo keyboard */
/* XXX needs testing */
if (sc->sc_buffer[2] == 0x9a && sc->sc_buffer[3] == 0x20) {
printf("Mouseman (non-EMP) pseudo keyboard\n");
return;
} else if (sc->sc_buffer[2] == 0x9a &&
sc->sc_buffer[3] == 0x21) {
printf("Trackman (non-EMP) pseudo keyboard\n");
return;
} else {
printf("extended keyboard\n");
adbkbd_initleds(sc);
}
break;
case ADB_EXTISOKBD:
printf("extended keyboard (ISO layout)\n");
adbkbd_initleds(sc);
break;
case ADB_KBDII:
printf("keyboard II\n");
break;
case ADB_ISOKBDII:
printf("keyboard II (ISO layout)\n");
break;
case ADB_PBKBD:
printf("PowerBook keyboard\n");
break;
case ADB_PBISOKBD:
printf("PowerBook keyboard (ISO layout)\n");
break;
case ADB_ADJKPD:
printf("adjustable keypad\n");
break;
case ADB_ADJKBD:
printf("adjustable keyboard\n");
break;
case ADB_ADJISOKBD:
printf("adjustable keyboard (ISO layout)\n");
break;
case ADB_ADJJAPKBD:
printf("adjustable keyboard (Japanese layout)\n");
break;
case ADB_PBEXTISOKBD:
printf("PowerBook extended keyboard (ISO layout)\n");
break;
case ADB_PBEXTJAPKBD:
printf("PowerBook extended keyboard (Japanese layout)\n");
break;
case ADB_JPKBDII:
printf("keyboard II (Japanese layout)\n");
break;
case ADB_PBEXTKBD:
printf("PowerBook extended keyboard\n");
break;
case ADB_DESIGNKBD:
printf("extended keyboard\n");
adbkbd_initleds(sc);
break;
case ADB_PBJPKBD:
printf("PowerBook keyboard (Japanese layout)\n");
break;
case ADB_PBG3KBD:
printf("PowerBook G3 keyboard\n");
break;
case ADB_PBG3JPKBD:
printf("PowerBook G3 keyboard (Japanese layout)\n");
break;
case ADB_IBOOKKBD:
printf("iBook keyboard\n");
break;
default:
printf("mapped device (%d)\n", sc->sc_adbdev->handler_id);
break;
}
if (adbkbd_is_console && (adbkbd_console_attached == 0)) {
wskbd_cnattach(&adbkbd_consops, sc, &adbkbd_keymapdata);
adbkbd_console_attached = 1;
a.console = 1;
} else {
a.console = 0;
}
a.keymap = &adbkbd_keymapdata;
a.accessops = &adbkbd_accessops;
a.accesscookie = sc;
sc->sc_wskbddev = config_found_ia(self, "wskbddev", &a, wskbddevprint);
/* attach the mouse device */
am.accessops = &adbkms_accessops;
am.accesscookie = sc;
sc->sc_wsmousedev = config_found_ia(self, "wsmousedev", &am, wsmousedevprint);
if (sc->sc_wsmousedev != NULL)
adbkbd_setup_sysctl(sc);
}
static void
adbkbd_handler(void *cookie, int len, uint8_t *data)
{
struct adbkbd_softc *sc = cookie;
#ifdef ADBKBD_DEBUG
int i;
printf("%s: %02x - ", sc->sc_dev.dv_xname, sc->sc_us);
for (i = 0; i < len; i++) {
printf(" %02x", data[i]);
}
printf("\n");
#endif
if (len >= 2) {
if (data[1] == sc->sc_us) {
adbkbd_keys(sc, data[2], data[3]);
return;
} else {
memcpy(sc->sc_buffer, data, len);
}
sc->sc_msg_len = len;
wakeup(&sc->sc_event);
} else {
DPRINTF("bogus message\n");
}
}
static int
adbkbd_wait(struct adbkbd_softc *sc, int timeout)
{
int cnt = 0;
if (sc->sc_poll) {
while (sc->sc_msg_len == 0) {
sc->sc_ops->poll(sc->sc_ops->cookie);
}
} else {
while ((sc->sc_msg_len == 0) && (cnt < timeout)) {
tsleep(&sc->sc_event, 0, "adbkbdio", hz);
cnt++;
}
}
return (sc->sc_msg_len > 0);
}
static void
adbkbd_keys(struct adbkbd_softc *sc, uint8_t k1, uint8_t k2)
{
/* keyboard event processing */
DPRINTF("[%02x %02x]", k1, k2);
if (((k1 == k2) && (k1 == 0x7f)) || (k1 == 0x7e)) {
/* power button, handle separately */
#ifdef ADBKBD_POWER_PANIC
panic("power button pressed");
#endif
} else {
adbkbd_key(sc, k1);
if (k2 != 0xff)
adbkbd_key(sc, k2);
}
}
static inline void
adbkbd_key(struct adbkbd_softc *sc, uint8_t k)
{
if (sc->sc_poll) {
if (sc->sc_polled_chars >= 16) {
printf("%s: polling buffer is full\n",
sc->sc_dev.dv_xname);
}
sc->sc_pollbuf[sc->sc_polled_chars] = k;
sc->sc_polled_chars++;
return;
}
/* translate some keys to mouse events */
if (sc->sc_wsmousedev != NULL) {
if (ADBK_KEYVAL(k) == sc->sc_trans[1]) {
wsmouse_input(sc->sc_wsmousedev, ADBK_PRESS(k) ? 2 : 0,
0, 0, 0, 0,
WSMOUSE_INPUT_DELTA);
return;
}
if (ADBK_KEYVAL(k) == sc->sc_trans[2]) {
wsmouse_input(sc->sc_wsmousedev, ADBK_PRESS(k) ? 4 : 0,
0, 0, 0, 0,
WSMOUSE_INPUT_DELTA);
return;
}
}
#ifdef WSDISPLAY_COMPAT_RAWKBD
if (sc->sc_rawkbd) {
char cbuf[2];
int s;
int j = 0;
int c = keyboard[ADBK_KEYVAL(k)][3]
if (k & 0x80)
cbuf[j++] = 0xe0;
cbuf[j++] = (c & 0x7f) | (ADBK_PRESS(k)? 0 : 0x80);
s = spltty();
wskbd_rawinput(sc->sc_wskbddev, cbuf, j);
splx(s);
} else {
#endif
if (ADBK_KEYVAL(k) == 0x39) {
/* caps lock - send up and down */
if (ADBK_PRESS(k) != sc->sc_capslock) {
sc->sc_capslock = ADBK_PRESS(k);
wskbd_input(sc->sc_wskbddev,
WSCONS_EVENT_KEY_DOWN, 0x39);
wskbd_input(sc->sc_wskbddev,
WSCONS_EVENT_KEY_UP, 0x39);
}
} else {
/* normal event */
int type;
type = ADBK_PRESS(k) ?
WSCONS_EVENT_KEY_DOWN : WSCONS_EVENT_KEY_UP;
wskbd_input(sc->sc_wskbddev, type, ADBK_KEYVAL(k));
}
#ifdef WSDISPLAY_COMPAT_RAWKBD
}
#endif
}
/*
* Set the keyboard LED's.
*
* Automatically translates from ioctl/softc format to the
* actual keyboard register format
*/
static void
adbkbd_set_leds(void *cookie, int leds)
{
struct adbkbd_softc *sc = cookie;
int aleds;
short cmd;
uint8_t buffer[2];
DPRINTF("adbkbd_set_leds: %02x\n", leds);
if ((leds & 0x07) == (sc->sc_leds & 0x07))
return;
if (sc->sc_have_led_control) {
aleds = (~leds & 0x04) | 3;
if (leds & 1)
aleds &= ~2;
if (leds & 2)
aleds &= ~1;
buffer[0] = 0xff;
buffer[1] = aleds | 0xf8;
cmd = ADBLISTEN(sc->sc_adbdev->current_addr, 2);
sc->sc_ops->send(sc->sc_ops->cookie, sc->sc_poll, cmd, 2, buffer);
}
sc->sc_leds = leds & 7;
}
static void
adbkbd_initleds(struct adbkbd_softc *sc)
{
short cmd;
/* talk R2 */
cmd = ADBTALK(sc->sc_adbdev->current_addr, 2);
sc->sc_msg_len = 0;
sc->sc_ops->send(sc->sc_ops->cookie, sc->sc_poll, cmd, 0, NULL);
if (!adbkbd_wait(sc, 10)) {
printf("unable to read LED state\n");
return;
}
sc->sc_have_led_control = 1;
DPRINTF("have LED control\n");
return;
}
static int
adbkbd_enable(void *v, int on)
{
return 0;
}
static int
adbkbd_ioctl(void *v, u_long cmd, caddr_t data, int flag, struct lwp *l)
{
struct adbkbd_softc *sc = (struct adbkbd_softc *) v;
switch (cmd) {
case WSKBDIO_GTYPE:
*(int *)data = WSKBD_TYPE_ADB;
return 0;
case WSKBDIO_SETLEDS:
adbkbd_set_leds(sc, *(int *)data);
return 0;
case WSKBDIO_GETLEDS:
*(int *)data = sc->sc_leds;
return 0;
#ifdef WSDISPLAY_COMPAT_RAWKBD
case WSKBDIO_SETMODE:
sc->sc_rawkbd = *(int *)data == WSKBD_RAW;
return 0;
#endif
}
return EPASSTHROUGH;
}
int
adbkbd_cnattach()
{
adbkbd_is_console = 1;
return 0;
}
static void
adbkbd_cngetc(void *v, u_int *type, int *data)
{
struct adbkbd_softc *sc = v;
int key, press, val;
int s;
s = splhigh();
KASSERT(sc->sc_poll);
DPRINTF("polling...");
while (sc->sc_polled_chars == 0) {
sc->sc_ops->poll(sc->sc_ops->cookie);
}
DPRINTF(" got one\n");
splx(s);
key = sc->sc_pollbuf[0];
sc->sc_polled_chars--;
memmove(sc->sc_pollbuf, sc->sc_pollbuf + 1,
sc->sc_polled_chars);
press = ADBK_PRESS(key);
val = ADBK_KEYVAL(key);
*data = val;
*type = press ? WSCONS_EVENT_KEY_DOWN : WSCONS_EVENT_KEY_UP;
}
static void
adbkbd_cnpollc(void *v, int on)
{
struct adbkbd_softc *sc = v;
sc->sc_poll = on;
if (!on) {
int i;
/* feed the poll buffer's content to wskbd */
for (i = 0; i < sc->sc_polled_chars; i++) {
adbkbd_key(sc, sc->sc_pollbuf[i]);
}
sc->sc_polled_chars = 0;
}
}
/* stuff for the pseudo mouse */
static int
adbkms_enable(void *v)
{
return 0;
}
static int
adbkms_ioctl(void *v, u_long cmd, caddr_t data, int flag, struct lwp *l)
{
switch (cmd) {
case WSMOUSEIO_GTYPE:
*(u_int *)data = WSMOUSE_TYPE_PSEUDO;
break;
default:
return (EPASSTHROUGH);
}
return (0);
}
static void
adbkms_disable(void *v)
{
}
static void
adbkbd_setup_sysctl(struct adbkbd_softc *sc)
{
struct sysctlnode *node, *me;
int ret;
DPRINTF("%s: sysctl setup\n", sc->sc_dev.dv_xname);
ret = sysctl_createv(NULL, 0, NULL, (const struct sysctlnode **)&me,
CTLFLAG_READWRITE,
CTLTYPE_NODE, sc->sc_dev.dv_xname, NULL,
NULL, 0, NULL, 0,
CTL_MACHDEP, CTL_CREATE, CTL_EOL);
ret = sysctl_createv(NULL, 0, NULL,
(const struct sysctlnode **)&node,
CTLFLAG_READWRITE | CTLFLAG_OWNDESC | CTLFLAG_IMMEDIATE,
CTLTYPE_INT, "middle", "middle mouse button", adbkbd_sysctl_button,
1, NULL, 0, CTL_MACHDEP, me->sysctl_num, CTL_CREATE, CTL_EOL);
node->sysctl_data = sc;
ret = sysctl_createv(NULL, 0, NULL,
(const struct sysctlnode **)&node,
CTLFLAG_READWRITE | CTLFLAG_OWNDESC | CTLFLAG_IMMEDIATE,
CTLTYPE_INT, "right", "right mouse button", adbkbd_sysctl_button,
2, NULL, 0, CTL_MACHDEP, me->sysctl_num, CTL_CREATE, CTL_EOL);
node->sysctl_data = sc;
}
static int
adbkbd_sysctl_button(SYSCTLFN_ARGS)
{
struct sysctlnode node = *rnode;
struct adbkbd_softc *sc=(struct adbkbd_softc *)node.sysctl_data;
const int *np = newp;
int btn = node.sysctl_idata, reg;
DPRINTF("adbkbd_sysctl_button %d\n", btn);
node.sysctl_idata = sc->sc_trans[btn];
reg = sc->sc_trans[btn];
if (np) {
/* we're asked to write */
node.sysctl_data = &reg;
if (sysctl_lookup(SYSCTLFN_CALL(&node)) == 0) {
sc->sc_trans[btn] = node.sysctl_idata;
return 0;
}
return EINVAL;
} else {
node.sysctl_size = 4;
return (sysctl_lookup(SYSCTLFN_CALL(&node)));
}
}
SYSCTL_SETUP(sysctl_adbkbdtrans_setup, "adbkbd translator setup")
{
sysctl_createv(NULL, 0, NULL, NULL,
CTLFLAG_PERMANENT,
CTLTYPE_NODE, "machdep", NULL,
NULL, 0, NULL, 0,
CTL_MACHDEP, CTL_EOL);
}

431
sys/dev/adb/adb_keymap.h Normal file
View File

@ -0,0 +1,431 @@
/* $NetBSD: adb_keymap.h,v 1.1 2007/01/17 23:20:16 macallan Exp $ */
/*-
* Copyright (c) 1997 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
* by Juergen Hannken-Illjes.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the NetBSD
* Foundation, Inc. and its contributors.
* 4. Neither the name of The NetBSD Foundation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/* XXX This list is incomplete. */
#define KC(n) KS_KEYCODE(n)
static const keysym_t akbd_keydesc_us[] = {
/* pos command normal shifted */
KC(0), KS_a,
KC(1), KS_s,
KC(2), KS_d,
KC(3), KS_f,
KC(4), KS_h,
KC(5), KS_g,
KC(6), KS_z,
KC(7), KS_x,
KC(8), KS_c,
KC(9), KS_v,
KC(10), KS_paragraph,
KC(11), KS_b,
KC(12), KS_q,
KC(13), KS_w,
KC(14), KS_e,
KC(15), KS_r,
KC(16), KS_y,
KC(17), KS_t,
KC(18), KS_1, KS_exclam,
KC(19), KS_2, KS_at,
KC(20), KS_3, KS_numbersign,
KC(21), KS_4, KS_dollar,
KC(22), KS_6, KS_asciicircum,
KC(23), KS_5, KS_percent,
KC(24), KS_equal, KS_plus,
KC(25), KS_9, KS_parenleft,
KC(26), KS_7, KS_ampersand,
KC(27), KS_minus, KS_underscore,
KC(28), KS_8, KS_asterisk,
KC(29), KS_0, KS_parenright,
KC(30), KS_bracketright, KS_braceright,
KC(31), KS_o,
KC(32), KS_u,
KC(33), KS_bracketleft, KS_braceleft,
KC(34), KS_i,
KC(35), KS_p,
KC(36), KS_Return,
KC(37), KS_l,
KC(38), KS_j,
KC(39), KS_apostrophe, KS_quotedbl,
KC(40), KS_k,
KC(41), KS_semicolon, KS_colon,
KC(42), KS_backslash, KS_bar,
KC(43), KS_comma, KS_less,
KC(44), KS_slash, KS_question,
KC(45), KS_n,
KC(46), KS_m,
KC(47), KS_period, KS_greater,
KC(48), KS_Tab,
KC(49), KS_space,
KC(50), KS_grave, KS_asciitilde,
KC(51), KS_Delete,
KC(52), KS_KP_Enter, /* Pretend this is alt-R ? */
KC(53), KS_Escape,
KC(54), KS_Control_L,
KC(55), KS_Cmd, /* Command */
KC(56), KS_Shift_L,
KC(57), KS_Caps_Lock,
KC(58), KS_Cmd1, /* Option */
KC(59), KS_Left,
KC(60), KS_Right,
KC(61), KS_Down,
KC(62), KS_Up,
KC(65), KS_KP_Decimal,
KC(67), KS_KP_Multiply,
KC(69), KS_KP_Add,
KC(71), KS_Num_Lock,
KC(75), KS_KP_Divide,
KC(76), KS_KP_Enter,
KC(78), KS_KP_Subtract,
KC(81), KS_KP_Equal,
KC(82), KS_KP_Insert, KS_KP_0,
KC(83), KS_KP_End, KS_KP_1,
KC(84), KS_KP_Down, KS_KP_2,
KC(85), KS_KP_Next, KS_KP_3,
KC(86), KS_KP_Left, KS_KP_4,
KC(87), KS_KP_Begin, KS_KP_5,
KC(88), KS_KP_Right, KS_KP_6,
KC(89), KS_KP_Home, KS_KP_7,
KC(91), KS_KP_Up, KS_KP_8,
KC(92), KS_KP_Prior, KS_KP_9,
KC(95), KS_KP_Delete, KS_KP_Decimal,
KC(96), KS_Cmd_Screen4, KS_f5,
KC(97), KS_Cmd_Screen5, KS_f6,
KC(98), KS_Cmd_Screen6, KS_f7,
KC(99), KS_Cmd_Screen2, KS_f3,
KC(100),KS_Cmd_Screen7, KS_f8,
KC(101),KS_Cmd_Screen8, KS_f9,
KC(103), KS_f11,
KC(105), KS_Print_Screen,
KC(106), KS_KP_Enter,
KC(107), KS_Hold_Screen,
KC(109),KS_Cmd_Screen9, KS_f10,
KC(111), KS_f12,
KC(113), KS_Pause,
KC(114), KS_Insert,
KC(115), KS_Home,
KC(116), KS_Prior,
KC(117), KS_Delete, /* BackSpace */
KC(118),KS_Cmd_Screen3, KS_f4,
KC(119), KS_End,
KC(120),KS_Cmd_Screen1, KS_f2,
KC(121), KS_Next,
KC(122),KS_Cmd_Screen0, KS_f1,
KC(127), KS_Cmd_Debugger,
};
static const keysym_t akbd_keydesc_fr[] = {
/* pos normal shifted altgr shift-altgr */
KC(0), KS_q,
KC(1), KS_s, KS_S, KS_Ograve,
KC(4), KS_h, KS_H, KS_Igrave, KS_Icircumflex,
KC(6), KS_w, KS_W, KS_less, KS_greater,
KC(8), KS_c, KS_C, KS_copyright, KS_cent,
KC(10), KS_at, KS_numbersign,
KC(11), KS_b, KS_B, KS_ssharp,
KC(12), KS_a, KS_A, KS_ae, KS_AE,
KC(13), KS_z, KS_Z, KS_Acircumflex, KS_Aring,
KC(14), KS_e, KS_E, KS_ecircumflex, KS_Ecircumflex,
KC(15), KS_r, KS_R, KS_registered, /* Euro */
KC(16), KS_y, KS_Y, KS_Uacute,
KC(18), KS_ampersand, KS_1, KS_voidSymbol, KS_dead_acute,
KC(19), KS_eacute, KS_2, KS_ediaeresis,
KC(20), KS_quotedbl, KS_3,
KC(21), KS_apostrophe, KS_4, KS_braceleft, KS_bracketleft,
KC(22), KS_section, KS_6, KS_paragraph,
KC(23), KS_parenleft, KS_5, KS_braceleft, KS_bracketleft,
KC(24), KS_minus, KS_underscore, KS_braceright,
KC(25), KS_ccedilla, KS_9, KS_Ccedilla, KS_Agrave,
KC(26), KS_egrave, KS_7, KS_guillemotleft,KS_guillemotright,
KC(27), KS_parenright, KS_degree, KS_braceright, KS_bracketright,
KC(28), KS_exclam, KS_8, KS_exclamdown, KS_Ucircumflex,
KC(29), KS_agrave, KS_0, KS_oslash,
KC(30), KS_dollar, KS_asterisk, KS_comma, KS_yen,
KC(33), KS_dead_circumflex, KS_dead_diaeresis,KS_ocircumflex,KS_Ocircumflex,
KC(34), KS_i, KS_I, KS_icircumflex, KS_Icircumflex,
KC(37), KS_l, KS_L, KS_notsign, KS_bar,
KC(38), KS_j, KS_J, KS_Idiaeresis, KS_Igrave,
KC(39), KS_ugrave, KS_percent, KS_Ugrave,
KC(40), KS_k, KS_K, KS_Egrave, KS_Ediaeresis,
KC(41), KS_m, KS_M, KS_mu, KS_Ograve,
KC(42), KS_dead_grave, KS_sterling, KS_at, KS_numbersign,
KC(43), KS_semicolon, KS_period,
KC(44), KS_equal, KS_plus, KS_voidSymbol, KS_plusminus,
KC(45), KS_n, KS_N, KS_dead_tilde,
KC(46), KS_comma, KS_question, KS_voidSymbol, KS_questiondown,
KC(47), KS_colon, KS_slash, KS_division, KS_backslash,
KC(50), KS_less, KS_greater,
KC(52), KS_Alt_R,
KC(55), KS_Meta_L, /* Command */
KC(58), KS_Mode_switch, KS_Multi_key, /* Option */
};
static const keysym_t akbd_keydesc_fr_nodead[] = {
KC(18), KS_ampersand, KS_1, KS_voidSymbol, KS_acute,
KC(33), KS_asciicircum, KS_diaeresis, KS_ocircumflex, KS_Ocircumflex,
KC(42), KS_grave, KS_sterling, KS_at, KS_numbersign,
KC(45), KS_n, KS_N, KS_asciitilde,
};
static const keysym_t akbd_keydesc_jp[] = {
/* pos command normal shifted */
KC(19), KS_2, KS_quotedbl,
KC(22), KS_6, KS_ampersand,
KC(24), KS_asciicircum, KS_asciitilde,
KC(25), KS_9, KS_parenright,
KC(26), KS_7, KS_apostrophe,
KC(27), KS_minus, KS_equal,
KC(28), KS_8, KS_parenleft,
KC(29), KS_0,
KC(30), KS_bracketleft, KS_braceleft,
KC(33), KS_at, KS_grave,
KC(39), KS_colon, KS_asterisk,
KC(41), KS_semicolon, KS_plus,
KC(42), KS_bracketright,KS_braceright,
KC(93), KS_backslash, KS_bar,
KC(94), KS_underscore,
};
static const keysym_t akbd_keydesc_uk[] = {
/* pos normal shifted altgr shift-altgr */
KC(10), KS_section, KS_plusminus,
KC(20), KS_3, KS_sterling, KS_numbersign,
KC(52), KS_KP_Enter,
KC(58), KS_Mode_switch, KS_Multi_key, /* Option */
};
static const keysym_t akbd_keydesc_sv[] = {
/* pos normal shifted altgr shift-altgr */
KC(10), KS_section, KS_degree,
KC(19), KS_2, KS_quotedbl, KS_at,
KC(21), KS_4, KS_dollar,
KC(22), KS_6, KS_ampersand,
KC(24), KS_dead_acute, KS_dead_grave,
KC(25), KS_9, KS_parenright, KS_bracketright,
KC(26), KS_7, KS_slash, KS_braceleft,
KC(27), KS_plus, KS_question, KS_backslash,
KC(28), KS_8, KS_parenleft, KS_bracketleft,
KC(29), KS_0, KS_equal, KS_braceright,
KC(30), KS_dead_diaeresis,KS_dead_circumflex,KS_dead_tilde,
KC(33), KS_aring,
KC(39), KS_adiaeresis,
KC(41), KS_odiaeresis,
KC(42), KS_apostrophe, KS_asterisk,
KC(43), KS_comma, KS_semicolon,
KC(44), KS_minus, KS_underscore,
KC(47), KS_period, KS_colon,
KC(50), KS_less, KS_greater, KS_bar,
KC(58), KS_Mode_switch,KS_Multi_key,
};
static const keysym_t akbd_keydesc_sv_nodead[] = {
/* pos normal shifted altgr shift-altgr */
KC(24), KS_apostrophe, KS_grave,
KC(30), KS_diaeresis, KS_asciicircum, KS_asciitilde,
};
static const keysym_t akbd_keydesc_de[] = {
/* pos normal shifted altgr shift-altgr */
KC(0), KS_a, KS_A, KS_aring, KS_Aring,
KC(1), KS_s, KS_S, KS_voidSymbol, KS_Iacute,
KC(3), KS_f, KS_F, KS_voidSymbol, KS_Idiaeresis,
KC(4), KS_h, KS_H, KS_ordfeminine, KS_Oacute,
KC(5), KS_g, KS_G, KS_copyright, KS_Igrave,
KC(6), KS_y, KS_Y, KS_yen,
KC(7), KS_x, KS_X, KS_voidSymbol, KS_Ugrave,
KC(8), KS_c, KS_C, KS_ccedilla, KS_Ccedilla,
KC(10), KS_dead_circumflex,KS_degree,
KC(12), KS_q, KS_Q, KS_guillemotleft,KS_guillemotright,
KC(15), KS_r, KS_R, KS_registered, KS_cedilla,
KC(16), KS_z, KS_Z,
KC(18), KS_1, KS_exclam, KS_exclamdown, KS_notsign,
KC(19), KS_2, KS_quotedbl,
KC(20), KS_3, KS_section, KS_paragraph, KS_numbersign,
KC(21), KS_4, KS_dollar, KS_cent, KS_sterling,
KC(22), KS_6, KS_ampersand, KS_bracketright,KS_dead_circumflex,
KC(23), KS_5, KS_percent, KS_bracketleft,
KC(24), KS_dead_acute, KS_dead_grave, KS_apostrophe,
KC(25), KS_9, KS_parenright, KS_braceright, KS_periodcentered,
KC(26), KS_7, KS_slash, KS_bar, KS_backslash,
KC(27), KS_ssharp, KS_question, KS_questiondown,
KC(28), KS_8, KS_parenleft, KS_braceleft,
KC(29), KS_0, KS_equal, KS_voidSymbol, KS_macron,
KC(30), KS_plus, KS_asterisk, KS_plusminus,
KC(31), KS_o, KS_O, KS_oslash, KS_Ooblique,
KC(32), KS_u, KS_U, KS_dead_diaeresis,KS_Aacute,
KC(33), KS_udiaeresis, KS_Udiaeresis, KS_voidSymbol, KS_degree,
KC(34), KS_i, KS_I, KS_voidSymbol, KS_Ucircumflex,
KC(37), KS_l, KS_L, KS_at,
KC(38), KS_j, KS_J, KS_masculine,
KC(39), KS_adiaeresis, KS_Adiaeresis, KS_ae, KS_AE,
KC(41), KS_odiaeresis, KS_Odiaeresis,
KC(42), KS_numbersign, KS_apostrophe,
KC(43), KS_comma, KS_semicolon,
KC(44), KS_minus, KS_underscore,
KC(45), KS_n, KS_N, KS_dead_tilde,
KC(46), KS_m, KS_M, KS_mu,
KC(47), KS_period, KS_colon,
KC(50), KS_less, KS_greater,
KC(52), KS_Multi_key,
KC(58), KS_Mode_switch,
};
static const keysym_t akbd_keydesc_de_nodead[] = {
/* pos normal shifted altgr shift-altgr */
KC(10), KS_asciicircum, KS_degree,
KC(22), KS_6, KS_ampersand, KS_bracketright,KS_asciicircum,
KC(24), KS_acute, KS_grave, KS_apostrophe,
KC(32), KS_u, KS_U, KS_diaeresis, KS_Aacute,
KC(45), KS_n, KS_N, KS_asciitilde,
};
static const keysym_t akbd_keydesc_sf[] = {
/* pos normal shifted altgr shift-altgr */
KC(6), KS_y,
KC(10), KS_paragraph, KS_degree,
KC(16), KS_z,
KC(18), KS_plus, KS_1,
KC(19), KS_quotedbl, KS_2,
KC(20), KS_asterisk, KS_3,
KC(21), KS_ccedilla, KS_4, KS_Ccedilla,
KC(22), KS_ampersand, KS_6,
KC(23), KS_percent, KS_5,
KC(24), KS_dead_circumflex,KS_grave,
KC(25), KS_parenright, KS_9,
KC(26), KS_slash, KS_7,
KC(27), KS_apostrophe, KS_question,
KC(28), KS_parenleft, KS_8,
KC(29), KS_equal, KS_0,
KC(30), KS_dead_diaeresis,KS_exclam,
KC(33), KS_egrave, KS_udiaeresis,
KC(39), KS_agrave, KS_adiaeresis,
KC(41), KS_eacute, KS_odiaeresis,
KC(42), KS_dollar, KS_sterling,
KC(43), KS_period, KS_colon,
KC(46), KS_comma, KS_semicolon,
KC(47), KS_minus, KS_underscore,
KC(50), KS_less, KS_greater,
};
static const keysym_t akbd_keydesc_es[] = {
/* pos normal shifted altgr shift-altgr */
KC(10), KS_degree, KS_ordfeminine, KS_backslash,
KC(18), KS_1, KS_exclam, KS_bar,
KC(19), KS_2, KS_quotedbl, KS_at,
KC(20), KS_3, KS_periodcentered, KS_numbersign,
KC(21), KS_4, KS_dollar, KS_asciitilde,
KC(22), KS_6, KS_ampersand, KS_notsign,
KC(23), KS_5, KS_percent,
KC(24), KS_exclamdown, KS_questiondown,
KC(25), KS_9, KS_parenright,
KC(26), KS_7, KS_slash,
KC(27), KS_apostrophe, KS_question,
KC(28), KS_8, KS_parenleft,
KC(29), KS_0, KS_equal,
KC(30), KS_plus, KS_asterisk, KS_bracketright,
KC(33), KS_dead_grave, KS_dead_circumflex, KS_bracketleft,
KC(39), KS_dead_acute, KS_dead_diaeresis, KS_braceleft,
KC(41), KS_ntilde,
KC(42), KS_ccedilla, KS_Ccedilla, KS_braceright,
KC(43), KS_comma, KS_semicolon,
KC(44), KS_minus, KS_underscore,
KC(47), KS_period, KS_colon,
KC(50), KS_less, KS_greater,
KC(55), KS_Alt_L, /* Command */
KC(58), KS_Mode_switch, KS_Multi_key, /* Option */
};
static const keysym_t akbd_keydesc_pt[] = {
/* pos normal shifted altgr shift-altgr */
KC(7), KS_x, KS_X, KS_guillemotleft, KS_guillemotright,
KC(10), KS_section, KS_plusminus,
KC(19), KS_2, KS_quotedbl, KS_at,
KC(20), KS_3, KS_numbersign, KS_sterling,
KC(22), KS_6, KS_ampersand,
KC(24), KS_plus, KS_asterisk,
KC(25), KS_9, KS_parenright, KS_bracketright, KS_braceright,
KC(26), KS_7, KS_slash,
KC(27), KS_apostrophe, KS_question,
KC(28), KS_8, KS_parenleft, KS_bracketleft, KS_braceleft,
KC(29), KS_0, KS_equal,
KC(30), KS_dead_acute, KS_dead_grave,
KC(33), KS_masculine, KS_ordfeminine,
KC(39), KS_dead_tilde, KS_dead_circumflex,
KC(41), KS_ccedilla, KS_Ccedilla,
KC(43), KS_comma, KS_semicolon,
KC(44), KS_minus, KS_underscore,
KC(47), KS_period, KS_colon,
KC(50), KS_less, KS_greater,
KC(58), KS_Mode_switch,
KC(81), KS_KP_Equal,
};
#define KBD_MAP(name, base, map) \
{ name, base, sizeof(map)/sizeof(keysym_t), map }
static const struct wscons_keydesc akbd_keydesctab[] = {
KBD_MAP(KB_US, 0, akbd_keydesc_us),
KBD_MAP(KB_FR, KB_US, akbd_keydesc_fr),
KBD_MAP(KB_JP, KB_US, akbd_keydesc_jp),
KBD_MAP(KB_FR | KB_NODEAD, KB_FR, akbd_keydesc_fr_nodead),
KBD_MAP(KB_SF, KB_US, akbd_keydesc_sf),
KBD_MAP(KB_SV, KB_US, akbd_keydesc_sv),
KBD_MAP(KB_SV | KB_NODEAD, KB_SV, akbd_keydesc_sv_nodead),
KBD_MAP(KB_DE, KB_US, akbd_keydesc_de),
KBD_MAP(KB_DE | KB_NODEAD, KB_DE, akbd_keydesc_de_nodead),
KBD_MAP(KB_UK, KB_US, akbd_keydesc_uk),
KBD_MAP(KB_ES, KB_US, akbd_keydesc_es),
KBD_MAP(KB_PT, KB_US, akbd_keydesc_pt),
{0, 0, 0, 0}
};
#undef KBD_MAP
#undef KC

750
sys/dev/adb/adb_ms.c Normal file
View File

@ -0,0 +1,750 @@
/* $NetBSD: adb_ms.c,v 1.1 2007/01/17 23:20:16 macallan Exp $ */
/*
* Copyright (C) 1998 Colin Wood
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by Colin Wood.
* 4. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: adb_ms.c,v 1.1 2007/01/17 23:20:16 macallan Exp $");
#include <sys/param.h>
#include <sys/device.h>
#include <sys/fcntl.h>
#include <sys/poll.h>
#include <sys/select.h>
#include <sys/proc.h>
#include <sys/signalvar.h>
#include <sys/systm.h>
#include <sys/kernel.h>
#include <machine/autoconf.h>
#include <dev/wscons/wsconsio.h>
#include <dev/wscons/wsmousevar.h>
#include <machine/adbsys.h>
#include <dev/adb/adbvar.h>
#include "adbdebug.h"
#ifdef ADBMS_DEBUG
#define DPRINTF printf
#else
#define DPRINTF while (0) printf
#endif
/*
* State info, per mouse instance.
*/
struct adbms_softc {
struct device sc_dev;
struct adb_device *sc_adbdev;
struct adb_bus_accessops *sc_ops;
/* Extended Mouse Protocol info, faked for non-EMP mice */
u_int8_t sc_class; /* mouse class (mouse, trackball) */
u_int8_t sc_buttons; /* number of buttons */
u_int32_t sc_res; /* mouse resolution (dpi) */
char sc_devid[5]; /* device indentifier */
uint8_t sc_us; /* cmd to watch for */
int sc_mb; /* current button state */
struct device *sc_wsmousedev;
/* helpers for trackpads */
int sc_down;
/*
* trackpad protocol variant. Known so far:
* 2 buttons - PowerBook 3400, single events on button 3 and 4 indicate
* finger down and up
* 4 buttons - iBook G4, button 6 indicates finger down, button 4 is
* always down
*/
int sc_x, sc_y;
/* buffers */
int sc_poll;
int sc_msg_len;
int sc_event;
uint8_t sc_buffer[16];
};
/* EMP device classes */
#define MSCLASS_TABLET 0
#define MSCLASS_MOUSE 1
#define MSCLASS_TRACKBALL 2
#define MSCLASS_TRACKPAD 3
/*
* Function declarations.
*/
static int adbms_match(struct device *, struct cfdata *, void *);
static void adbms_attach(struct device *, struct device *, void *);
static void ems_init(struct adbms_softc *);
//static void ms_processevent(adb_event_t *event, struct adbms_softc *);
static void init_trackpad(struct adbms_softc *);
static void adbms_init_mouse(struct adbms_softc *);
static void adbms_init_turbo(struct adbms_softc *);
static void adbms_init_uspeed(struct adbms_softc *);
static void adbms_process_event(struct adbms_softc *, int, uint8_t *);
static int adbms_send_sync(struct adbms_softc *, uint8_t, int, uint8_t *);
/* Driver definition. */
CFATTACH_DECL(adbms, sizeof(struct adbms_softc),
adbms_match, adbms_attach, NULL, NULL);
static int adbms_enable(void *);
static int adbms_ioctl(void *, u_long, caddr_t, int, struct lwp *);
static void adbms_disable(void *);
/*
* handle tapping the trackpad
* different pads report different button counts and use slightly different
* protocols
*/
static void adbms_mangle_2(struct adbms_softc *, int);
static void adbms_mangle_4(struct adbms_softc *, int);
static void adbms_handler(void *, int, uint8_t *);
static int adbms_wait(struct adbms_softc *, int);
const struct wsmouse_accessops adbms_accessops = {
adbms_enable,
adbms_ioctl,
adbms_disable,
};
static int
adbms_match(struct device *parent, struct cfdata *cf, void *aux)
{
struct adb_attach_args *aaa = aux;
if (aaa->dev->original_addr == ADBADDR_MS)
return 1;
else
return 0;
}
static void
adbms_attach(struct device *parent, struct device *self, void *aux)
{
struct adbms_softc *sc = (struct adbms_softc *)self;
struct adb_attach_args *aaa = aux;
struct wsmousedev_attach_args a;
sc->sc_ops = aaa->ops;
sc->sc_adbdev = aaa->dev;
sc->sc_adbdev->cookie = sc;
sc->sc_adbdev->handler = adbms_handler;
sc->sc_us = ADBTALK(sc->sc_adbdev->current_addr, 0);
printf(" addr %d ", sc->sc_adbdev->current_addr);
sc->sc_class = MSCLASS_MOUSE;
sc->sc_buttons = 1;
sc->sc_res = 100;
sc->sc_devid[0] = 0;
sc->sc_devid[4] = 0;
sc->sc_poll = 0;
sc->sc_msg_len = 0;
ems_init(sc);
/* print out the type of mouse we have */
switch (sc->sc_adbdev->handler_id) {
case ADBMS_100DPI:
printf("%d-button, %d dpi mouse\n", sc->sc_buttons,
(int)(sc->sc_res));
break;
case ADBMS_200DPI:
sc->sc_res = 200;
printf("%d-button, %d dpi mouse\n", sc->sc_buttons,
(int)(sc->sc_res));
break;
case ADBMS_MSA3:
printf("Mouse Systems A3 mouse, %d-button, %d dpi\n",
sc->sc_buttons, (int)(sc->sc_res));
break;
case ADBMS_USPEED:
printf("MicroSpeed mouse, default parameters\n");
break;
case ADBMS_UCONTOUR:
printf("Contour mouse, default parameters\n");
break;
case ADBMS_TURBO:
printf("Kensington Turbo Mouse\n");
break;
case ADBMS_EXTENDED:
if (sc->sc_devid[0] == '\0') {
printf("Logitech ");
switch (sc->sc_class) {
case MSCLASS_MOUSE:
printf("MouseMan (non-EMP) mouse");
break;
case MSCLASS_TRACKBALL:
printf("TrackMan (non-EMP) trackball");
break;
default:
printf("non-EMP relative positioning device");
break;
}
printf("\n");
} else {
printf("EMP ");
switch (sc->sc_class) {
case MSCLASS_TABLET:
printf("tablet");
break;
case MSCLASS_MOUSE:
printf("mouse");
break;
case MSCLASS_TRACKBALL:
printf("trackball");
break;
case MSCLASS_TRACKPAD:
printf("trackpad");
init_trackpad(sc);
break;
default:
printf("unknown device");
break;
}
printf(" <%s> %d-button, %d dpi\n", sc->sc_devid,
sc->sc_buttons, (int)(sc->sc_res));
}
break;
default:
printf("relative positioning device (mouse?) (%d)\n",
sc->sc_adbdev->handler_id);
break;
}
a.accessops = &adbms_accessops;
a.accesscookie = sc;
sc->sc_wsmousedev = config_found(self, &a, wsmousedevprint);
}
/*
* Initialize extended mouse support -- probes devices as described
* in Inside Macintosh: Devices, Chapter 5 "ADB Manager".
*
* Extended Mouse Protocol is documented in TechNote HW1:
* "ADB - The Untold Story: Space Aliens Ate My Mouse"
*
* Supports: Extended Mouse Protocol, MicroSpeed Mouse Deluxe,
* Mouse Systems A^3 Mouse, Logitech non-EMP MouseMan
*/
void
ems_init(struct adbms_softc *sc)
{
DPRINTF("ems_init %d\n", sc->sc_adbdev->handler_id);
switch (sc->sc_adbdev->handler_id) {
case ADBMS_USPEED:
case ADBMS_UCONTOUR:
adbms_init_uspeed(sc);
return;
case ADBMS_TURBO:
adbms_init_turbo(sc);
return;
case ADBMS_100DPI:
case ADBMS_200DPI:
adbms_init_mouse(sc);
}
}
static void
adbms_init_uspeed(struct adbms_softc *sc)
{
uint8_t cmd, addr, buffer[4];
addr = sc->sc_adbdev->current_addr;
/* Found MicroSpeed Mouse Deluxe Mac or Contour Mouse */
cmd = ADBLISTEN(addr, 1);
/*
* To setup the MicroSpeed or the Contour, it appears
* that we can send the following command to the mouse
* and then expect data back in the form:
* buffer[0] = 4 (bytes)
* buffer[1], buffer[2] as std. mouse
* buffer[3] = buffer[4] = 0xff when no buttons
* are down. When button N down, bit N is clear.
* buffer[4]'s locking mask enables a
* click to toggle the button down state--sort of
* like the "Easy Access" shift/control/etc. keys.
* buffer[3]'s alternative speed mask enables using
* different speed when the corr. button is down
*/
buffer[0] = 0x00; /* Alternative speed */
buffer[1] = 0x00; /* speed = maximum */
buffer[2] = 0x10; /* enable extended protocol,
* lower bits = alt. speed mask
* = 0000b
*/
buffer[3] = 0x07; /* Locking mask = 0000b,
* enable buttons = 0111b
*/
adbms_send_sync(sc, cmd, 4, buffer);
sc->sc_buttons = 3;
sc->sc_res = 200;
}
static void
adbms_init_turbo(struct adbms_softc *sc)
{
uint8_t addr;
/* Found Kensington Turbo Mouse */
static u_char data1[] =
{ 0xe7, 0x8c, 0, 0, 0, 0xff, 0xff, 0x94 };
static u_char data2[] =
{ 0xa5, 0x14, 0, 0, 0x69, 0xff, 0xff, 0x27 };
addr = sc->sc_adbdev->current_addr;
adbms_send_sync(sc, ADBFLUSH(addr), 0, NULL);
adbms_send_sync(sc, ADBLISTEN(addr, 2), 8, data1);
adbms_send_sync(sc, ADBFLUSH(addr), 0, NULL);
adbms_send_sync(sc, ADBLISTEN(addr, 2), 8, data2);
}
static void
adbms_init_mouse(struct adbms_softc *sc)
{
int len;
uint8_t cmd, addr, buffer[16];
addr = sc->sc_adbdev->current_addr;
/* found a mouse */
cmd = ADBTALK(addr, 3);
if (!adbms_send_sync(sc, cmd, 0, NULL)) {
#ifdef ADBMS_DEBUG
printf("adb: ems_init timed out\n");
#endif
return;
}
/* Attempt to initialize Extended Mouse Protocol */
len = sc->sc_msg_len;
memcpy(buffer, sc->sc_buffer, len);
DPRINTF("buffer: %02x %02x\n", buffer[0], buffer[1]);
buffer[1] = 4; /* make handler ID 4 */
cmd = ADBLISTEN(addr, 3);
if (!adbms_send_sync(sc, cmd, len, buffer)) {
#ifdef ADBMS_DEBUG
printf("adb: ems_init timed out\n");
#endif
return;
}
/*
* Check to see if successful, if not
* try to initialize it as other types
*/
cmd = ADBTALK(addr, 3);
if (!adbms_send_sync(sc, cmd, 0, NULL)) {
DPRINTF("timeout checking for EMP switch\n");
return;
}
DPRINTF("new handler ID: %02x\n", sc->sc_buffer[1]);
if (sc->sc_buffer[1] == ADBMS_EXTENDED) {
sc->sc_adbdev->handler_id = ADBMS_EXTENDED;
cmd = ADBTALK(addr, 1);
if(!adbms_send_sync(sc, cmd, 0, NULL)) {
DPRINTF("adb: ems_init timed out\n");
return;
}
len = sc->sc_msg_len;
memcpy(buffer, sc->sc_buffer, len);
if (sc->sc_msg_len == 8) {
/* we have a true EMP device */
#ifdef ADB_PRINT_EMP
printf("EMP: %02x %02x %02x %02x %02x %02x %02x %02x\n",
buffer[0], buffer[1], buffer[2], buffer[3],
buffer[4], buffer[5], buffer[6], buffer[7]);
#endif
sc->sc_class = buffer[6];
sc->sc_buttons = buffer[7];
sc->sc_res = (int)*(short *)&buffer[4];
memcpy(sc->sc_devid, &(buffer[0]), 4);
} else if (buffer[0] == 0x9a &&
((buffer[1] == 0x20) || (buffer[1] == 0x21))) {
/*
* Set up non-EMP Mouseman/Trackman to put
* button bits in 3rd byte instead of sending
* via pseudo keyboard device.
*/
if (buffer[1] == 0x21)
sc->sc_class = MSCLASS_TRACKBALL;
else
sc->sc_class = MSCLASS_MOUSE;
cmd = ADBLISTEN(addr, 1);
buffer[0]=0x00;
buffer[1]=0x81;
adbms_send_sync(sc, cmd, 2, buffer);
cmd = ADBLISTEN(addr, 1);
buffer[0]=0x01;
buffer[1]=0x81;
adbms_send_sync(sc, cmd, 2, buffer);
cmd = ADBLISTEN(addr, 1);
buffer[0]=0x02;
buffer[1]=0x81;
adbms_send_sync(sc, cmd, 2, buffer);
cmd = ADBLISTEN(addr, 1);
buffer[0]=0x03;
buffer[1]=0x38;
adbms_send_sync(sc, cmd, 2, buffer);
sc->sc_buttons = 3;
sc->sc_res = 400;
}
} else {
/* Attempt to initialize as an A3 mouse */
buffer[1] = 0x03; /* make handler ID 3 */
cmd = ADBLISTEN(addr, 3);
if (!adbms_send_sync(sc, cmd, len, buffer)) {
#ifdef ADBMS_DEBUG
printf("adb: ems_init timed out\n");
#endif
return;
}
/*
* Check to see if successful, if not
* try to initialize it as other types
*/
cmd = ADBTALK(addr, 3);
if(adbms_send_sync(sc, cmd, 0, NULL)) {
len = sc->sc_msg_len;
memcpy(buffer, sc->sc_buffer, len);
if (buffer[1] == ADBMS_MSA3) {
sc->sc_adbdev->handler_id = ADBMS_MSA3;
/* Initialize as above */
cmd = ADBLISTEN(addr, 2);
/* listen 2 */
buffer[0] = 0x00;
/* Irrelevant, buffer has 0x77 */
buffer[2] = 0x07;
/*
* enable 3 button mode = 0111b,
* speed = normal
*/
adbms_send_sync(sc, cmd, 3, buffer);
sc->sc_buttons = 3;
sc->sc_res = 300;
}
}
}
}
static void
adbms_handler(void *cookie, int len, uint8_t *data)
{
struct adbms_softc *sc = cookie;
#ifdef ADBMS_DEBUG
int i;
printf("%s: %02x - ", sc->sc_dev.dv_xname, sc->sc_us);
for (i = 0; i < len; i++) {
printf(" %02x", data[i]);
}
printf("\n");
#endif
if (len >= 2) {
memcpy(sc->sc_buffer, &data[2], len - 2);
sc->sc_msg_len = len - 2;
if (data[1] == sc->sc_us) {
/* make sense of the mouse message */
adbms_process_event(sc, sc->sc_msg_len, sc->sc_buffer);
return;
}
wakeup(&sc->sc_event);
} else {
DPRINTF("bogus message\n");
}
}
static void
adbms_process_event(struct adbms_softc *sc, int len, uint8_t *buffer)
{
int buttons = 0, mask, dx, dy, i;
int button_bit = 1;
if ((sc->sc_adbdev->handler_id == ADBMS_EXTENDED) && (sc->sc_devid[0] == 0)) {
/* massage the data to look like EMP data */
if ((buffer[2] & 0x04) == 0x04)
buffer[0] &= 0x7f;
else
buffer[0] |= 0x80;
if ((buffer[2] & 0x02) == 0x02)
buffer[1] &= 0x7f;
else
buffer[1] |= 0x80;
if ((buffer[2] & 0x01) == 0x01)
buffer[2] = 0x00;
else
buffer[2] = 0x80;
}
switch (sc->sc_adbdev->handler_id) {
case ADBMS_USPEED:
case ADBMS_UCONTOUR:
/* MicroSpeed mouse and Contour mouse */
if (len == 4)
buttons = (~buffer[3]) & 0xff;
else
buttons = (buffer[1] & 0x80) ? 0 : 1;
break;
case ADBMS_MSA3:
/* Mouse Systems A3 mouse */
if (len == 3)
buttons = (~buffer[2]) & 0x07;
else
buttons = (buffer[0] & 0x80) ? 0 : 1;
break;
default:
/* Classic Mouse Protocol (up to 2 buttons) */
for (i = 0; i < 2; i++, button_bit <<= 1)
/* 0 when button down */
if (!(buffer[i] & 0x80))
buttons |= button_bit;
else
buttons &= ~button_bit;
/* Extended Protocol (up to 6 more buttons) */
for (mask = 0x80; i < len;
i += (mask == 0x80), button_bit <<= 1) {
/* 0 when button down */
if (!(buffer[i] & mask))
buttons |= button_bit;
else
buttons &= ~button_bit;
mask = ((mask >> 4) & 0xf)
| ((mask & 0xf) << 4);
}
break;
}
dx = ((int)(buffer[1] & 0x3f)) - ((buffer[1] & 0x40) ? 64 : 0);
dy = ((int)(buffer[0] & 0x3f)) - ((buffer[0] & 0x40) ? 64 : 0);
if (sc->sc_class == MSCLASS_TRACKPAD) {
if (sc->sc_down) {
/* finger is down - collect motion data */
sc->sc_x += dx;
sc->sc_y += dy;
}
DPRINTF("buttons: %02x\n", buttons);
switch (sc->sc_buttons) {
case 2:
buttons |= ((buttons & 2) >> 1);
adbms_mangle_2(sc, buttons);
break;
case 4:
adbms_mangle_4(sc, buttons);
break;
}
/* filter the pseudo-buttons out */
buttons &= 1;
}
if (sc->sc_wsmousedev)
wsmouse_input(sc->sc_wsmousedev, sc->sc_mb | buttons,
dx, -dy, 0, 0,
WSMOUSE_INPUT_DELTA);
#if NAED > 0
aed_input(&new_event);
#endif
}
static void
adbms_mangle_2(struct adbms_softc *sc, int buttons)
{
if (buttons & 4) {
/* finger down on pad */
if (sc->sc_down == 0) {
sc->sc_down = 1;
sc->sc_x = 0;
sc->sc_y = 0;
}
}
if (buttons & 8) {
/* finger up */
if (sc->sc_down) {
if (((sc->sc_x * sc->sc_x +
sc->sc_y * sc->sc_y) < 20) &&
(sc->sc_wsmousedev)) {
/*
* if there wasn't much movement between
* finger down and up again we assume
* someone tapped the pad and we just
* send a mouse button event
*/
wsmouse_input(sc->sc_wsmousedev,
1, 0, 0, 0, 0, WSMOUSE_INPUT_DELTA);
}
sc->sc_down = 0;
}
}
}
static void
adbms_mangle_4(struct adbms_softc *sc, int buttons)
{
if (buttons & 0x20) {
/* finger down on pad */
if (sc->sc_down == 0) {
sc->sc_down = 1;
sc->sc_x = 0;
sc->sc_y = 0;
}
}
if ((buttons & 0x20) == 0) {
/* finger up */
if (sc->sc_down) {
if (((sc->sc_x * sc->sc_x +
sc->sc_y * sc->sc_y) < 20) &&
(sc->sc_wsmousedev)) {
/*
* if there wasn't much movement between
* finger down and up again we assume
* someone tapped the pad and we just
* send a mouse button event
*/
wsmouse_input(sc->sc_wsmousedev,
1, 0, 0, 0, 0, WSMOUSE_INPUT_DELTA);
}
sc->sc_down = 0;
}
}
}
static int
adbms_enable(void *v)
{
return 0;
}
static int
adbms_ioctl(void *v, u_long cmd, caddr_t data, int flag, struct lwp *l)
{
switch (cmd) {
case WSMOUSEIO_GTYPE:
*(u_int *)data = WSMOUSE_TYPE_ADB;
break;
default:
return (EPASSTHROUGH);
}
return (0);
}
static void
adbms_disable(void *v)
{
}
static void
init_trackpad(struct adbms_softc *sc)
{
int cmd, addr;
uint8_t buffer[16];
uint8_t b2[] = {0x99, 0x94, 0x19, 0xff, 0xb2, 0x8a, 0x1b, 0x50};
addr = sc->sc_adbdev->current_addr;
cmd = ADBTALK(addr, 1);
if (!adbms_send_sync(sc, cmd, 0, NULL))
return;
if (sc->sc_msg_len != 8)
return;
memcpy(buffer, sc->sc_buffer, 8);
/* now whack the pad */
cmd = ADBLISTEN(addr, 1);
buffer[6] = 0x0d;
adbms_send_sync(sc, cmd, 8, buffer);
delay(1000);
cmd = ADBLISTEN(addr, 2);
adbms_send_sync(sc, cmd, 8, b2);
delay(1000);
cmd = ADBLISTEN(addr, 1);
buffer[6] = 0x03;
adbms_send_sync(sc, cmd, 8, buffer);
cmd = ADBFLUSH(addr);
adbms_send_sync(sc, cmd, 0, NULL);
delay(1000);
}
static int
adbms_wait(struct adbms_softc *sc, int timeout)
{
int cnt = 0;
if (sc->sc_poll) {
while (sc->sc_msg_len == -1) {
sc->sc_ops->poll(sc->sc_ops->cookie);
}
} else {
while ((sc->sc_msg_len == -1) && (cnt < timeout)) {
tsleep(&sc->sc_event, 0, "adbkbdio", hz);
cnt++;
}
}
return (sc->sc_msg_len > 0);
}
static int
adbms_send_sync(struct adbms_softc *sc, uint8_t cmd, int len, uint8_t *msg)
{
int i;
sc->sc_msg_len = -1;
DPRINTF("send: %02x", cmd);
for (i = 0; i < len; i++)
DPRINTF(" %02x", msg[i]);
DPRINTF("\n");
sc->sc_ops->send(sc->sc_ops->cookie, sc->sc_poll, cmd, len, msg);
adbms_wait(sc, 1000);
return (sc->sc_msg_len != -1);
}

68
sys/dev/adb/adbvar.h Normal file
View File

@ -0,0 +1,68 @@
/* $NetBSD: adbvar.h,v 1.1 2007/01/17 23:20:16 macallan Exp $ */
/*-
* Copyright (c) 2006 Michael Lorenz
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of The NetBSD Foundation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: adbvar.h,v 1.1 2007/01/17 23:20:16 macallan Exp $");
#ifndef ADBVAR_H
#define ADBVAR_H
#define ADB_CMDADDR(cmd) ((u_int8_t)((cmd) & 0xf0) >> 4)
#define ADBFLUSH(dev) ((((u_int8_t)(dev) & 0x0f) << 4) | 0x01)
#define ADBLISTEN(dev, reg) ((((u_int8_t)(dev) & 0x0f) << 4) | 0x08 | (reg))
#define ADBTALK(dev, reg) ((((u_int8_t)(dev) & 0x0f) << 4) | 0x0c | (reg))
struct adb_bus_accessops {
void *cookie;
/* cookie, poll, address/command, length, data */
int (*send)(void *, int, int, int, uint8_t *);
void (*poll)(void *);
void (*autopoll)(void *, int); /* bitmask of ADB addresses to poll */
int (*set_handler)(void *, void (*)(void *, int, uint8_t *), void *);
};
struct adb_device {
void *cookie;
void (*handler)(void *, int, uint8_t *);
int current_addr;
int original_addr;
int handler_id;
};
struct adb_attach_args {
struct adb_bus_accessops *ops;
struct adb_device *dev;
};
int nadb_print(void *, const char *);
#endif /* ADBVAR_H */

23
sys/dev/adb/files.adb Normal file
View File

@ -0,0 +1,23 @@
#
# $NetBSD: files.adb,v 1.1 2007/01/17 23:20:16 macallan Exp $
#
# Apple Desktop Bus protocol and drivers
defflag adbdebug.h ADB_DEBUG
defflag adbdebug.h ADBKBD_DEBUG
defflag adbdebug.h ADBMS_DEBUG
defflag adbdebug.h ADBKBD_POWER_PANIC
define adb_bus {}
device nadb {}
attach nadb at adb_bus
file dev/adb/adb_bus.c nadb needs-flag
device adbkbd : wskbddev, wsmousedev
attach adbkbd at nadb
file dev/adb/adb_kbd.c adbkbd needs-flag
device adbms : wsmousedev
attach adbms at nadb
file dev/adb/adb_ms.c adbms needs-flag