diff options
author | Dale Rahn <drahn@cvs.openbsd.org> | 2001-09-01 15:50:01 +0000 |
---|---|---|
committer | Dale Rahn <drahn@cvs.openbsd.org> | 2001-09-01 15:50:01 +0000 |
commit | 5ee20173f2267860f40c27cb85bb1a4092a97d93 (patch) | |
tree | fdc26169eac9a5701793ba9664c4f795eefd8f34 /sys/arch/macppc/dev/ams.c | |
parent | 65997b0cdeb6b9e16cdbbb314ede217802895ade (diff) |
The "powerpc" port which has supported the newer Apple Macintosh powerpc based
is being renamed to macppc. This is to allow sharing of common code
between different powerpc base platforms.
Most of the work involved in the renaming process was performed by miod@
Files moved from powerpc/mac to macppc/dev
Diffstat (limited to 'sys/arch/macppc/dev/ams.c')
-rw-r--r-- | sys/arch/macppc/dev/ams.c | 554 |
1 files changed, 554 insertions, 0 deletions
diff --git a/sys/arch/macppc/dev/ams.c b/sys/arch/macppc/dev/ams.c new file mode 100644 index 00000000000..08dd82193aa --- /dev/null +++ b/sys/arch/macppc/dev/ams.c @@ -0,0 +1,554 @@ +/* $OpenBSD: ams.c,v 1.1 2001/09/01 15:50:00 drahn Exp $ */ +/* $NetBSD: ams.c,v 1.11 2000/12/19 03:13:40 tsubai 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/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 <machine/autoconf.h> + +#include <dev/wscons/wsconsio.h> +#include <dev/wscons/wsmousevar.h> + +#include <macppc/mac/adbvar.h> +#include <macppc/mac/aedvar.h> +#include <macppc/mac/amsvar.h> +#include <macppc/mac/adb_direct.h> + +#include "aed.h" + +/* + * Function declarations. + */ +static int amsmatch __P((struct device *, void *, void *)); +static void amsattach __P((struct device *, struct device *, void *)); +static void ems_init __P((struct ams_softc *)); +static void ms_processevent __P((adb_event_t *event, struct ams_softc *)); + +/* Driver definition. */ +struct cfattach ams_ca = { + sizeof(struct ams_softc), amsmatch, amsattach +}; +/* Driver definition. */ +struct cfdriver ams_cd = { + NULL, "ams", DV_DULL +}; + + +int ams_enable __P((void *)); +int ams_ioctl __P((void *, u_long, caddr_t, int, struct proc *)); +void ams_disable __P((void *)); + +const struct wsmouse_accessops ams_accessops = { + ams_enable, + ams_ioctl, + ams_disable, +}; + +static int +amsmatch(parent, cf, aux) + struct device *parent; + void *cf; + void *aux; +{ + struct adb_attach_args *aa_args = aux; + + if (aa_args->origaddr == ADBADDR_MS) + return 1; + else + return 0; +} + +static void +amsattach(parent, self, aux) + struct device *parent, *self; + void *aux; +{ + ADBSetInfoBlock adbinfo; + struct ams_softc *sc = (struct ams_softc *)self; + struct adb_attach_args *aa_args = aux; + int error; + struct wsmousedev_attach_args a; + + sc->origaddr = aa_args->origaddr; + sc->adbaddr = aa_args->adbaddr; + sc->handler_id = aa_args->handler_id; + + sc->sc_class = MSCLASS_MOUSE; + sc->sc_buttons = 1; + sc->sc_res = 100; + sc->sc_devid[0] = 0; + sc->sc_devid[4] = 0; + + adbinfo.siServiceRtPtr = (Ptr)ms_adbcomplete; + adbinfo.siDataAreaAddr = (caddr_t)sc; + + ems_init(sc); + + /* print out the type of mouse we have */ + switch (sc->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"); + 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->handler_id); + break; + } + error = SetADBInfo(&adbinfo, sc->adbaddr); +#ifdef ADB_DEBUG + if (adb_debug) + printf("ams: returned %d from SetADBInfo\n", error); +#endif + + a.accessops = &ams_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(sc) + struct ams_softc *sc; +{ + int adbaddr; + short cmd; + u_char buffer[9]; + + adbaddr = sc->adbaddr; + if (sc->origaddr != ADBADDR_MS) + return; + if (sc->handler_id == ADBMS_USPEED || + sc->handler_id == ADBMS_UCONTOUR) { + /* Found MicroSpeed Mouse Deluxe Mac or Contour Mouse */ + cmd = ADBLISTEN(adbaddr, 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] = 4; + buffer[1] = 0x00; /* Alternative speed */ + buffer[2] = 0x00; /* speed = maximum */ + buffer[3] = 0x10; /* enable extended protocol, + * lower bits = alt. speed mask + * = 0000b + */ + buffer[4] = 0x07; /* Locking mask = 0000b, + * enable buttons = 0111b + */ + adb_op_sync((Ptr)buffer, (Ptr)0, (Ptr)0, cmd); + + sc->sc_buttons = 3; + sc->sc_res = 200; + return; + } + if (sc->handler_id == ADBMS_TURBO) { + /* Found Kensington Turbo Mouse */ + static u_char data1[] = + { 8, 0xe7, 0x8c, 0, 0, 0, 0xff, 0xff, 0x94 }; + static u_char data2[] = + { 8, 0xa5, 0x14, 0, 0, 0x69, 0xff, 0xff, 0x27 }; + + buffer[0] = 0; + adb_op_sync((Ptr)buffer, (Ptr)0, (Ptr)0, ADBFLUSH(adbaddr)); + + adb_op_sync((Ptr)data1, (Ptr)0, (Ptr)0, ADBLISTEN(adbaddr, 2)); + + buffer[0] = 0; + adb_op_sync((Ptr)buffer, (Ptr)0, (Ptr)0, ADBFLUSH(adbaddr)); + + adb_op_sync((Ptr)data2, (Ptr)0, (Ptr)0, ADBLISTEN(adbaddr, 2)); + return; + } + if ((sc->handler_id == ADBMS_100DPI) || + (sc->handler_id == ADBMS_200DPI)) { + /* found a mouse */ + cmd = ADBTALK(adbaddr, 3); + if (adb_op_sync((Ptr)buffer, (Ptr)0, (Ptr)0, cmd)) { +#ifdef ADB_DEBUG + if (adb_debug) + printf("adb: ems_init timed out\n"); +#endif + return; + } + + /* Attempt to initialize Extended Mouse Protocol */ + buffer[2] = 4; /* make handler ID 4 */ + cmd = ADBLISTEN(adbaddr, 3); + if (adb_op_sync((Ptr)buffer, (Ptr)0, (Ptr)0, cmd)) { +#ifdef ADB_DEBUG + if (adb_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(adbaddr, 3); + if (adb_op_sync((Ptr)buffer, (Ptr)0, (Ptr)0, cmd) == 0 && + buffer[2] == ADBMS_EXTENDED) { + sc->handler_id = ADBMS_EXTENDED; + cmd = ADBTALK(adbaddr, 1); + if (adb_op_sync((Ptr)buffer, (Ptr)0, (Ptr)0, cmd)) { +#ifdef ADB_DEBUG + if (adb_debug) + printf("adb: ems_init timed out\n"); +#endif + } else if (buffer[0] == 8) { + /* we have a true EMP device */ + sc->sc_class = buffer[7]; + sc->sc_buttons = buffer[8]; + sc->sc_res = (int)*(short *)&buffer[5]; + bcopy(&(buffer[1]), sc->sc_devid, 4); + } else if (buffer[1] == 0x9a && + ((buffer[2] == 0x20) || (buffer[2] == 0x21))) { + /* + * Set up non-EMP Mouseman/Trackman to put + * button bits in 3rd byte instead of sending + * via pseudo keyboard device. + */ + cmd = ADBLISTEN(adbaddr, 1); + buffer[0]=2; + buffer[1]=0x00; + buffer[2]=0x81; + adb_op_sync((Ptr)buffer, (Ptr)0, (Ptr)0, cmd); + + cmd = ADBLISTEN(adbaddr, 1); + buffer[0]=2; + buffer[1]=0x01; + buffer[2]=0x81; + adb_op_sync((Ptr)buffer, (Ptr)0, (Ptr)0, cmd); + + cmd = ADBLISTEN(adbaddr, 1); + buffer[0]=2; + buffer[1]=0x02; + buffer[2]=0x81; + adb_op_sync((Ptr)buffer, (Ptr)0, (Ptr)0, cmd); + + cmd = ADBLISTEN(adbaddr, 1); + buffer[0]=2; + buffer[1]=0x03; + buffer[2]=0x38; + adb_op_sync((Ptr)buffer, (Ptr)0, (Ptr)0, cmd); + + sc->sc_buttons = 3; + sc->sc_res = 400; + if (buffer[2] == 0x21) + sc->sc_class = MSCLASS_TRACKBALL; + else + sc->sc_class = MSCLASS_MOUSE; + } else + /* unknown device? */; + } else { + /* Attempt to initialize as an A3 mouse */ + buffer[2] = 0x03; /* make handler ID 3 */ + cmd = ADBLISTEN(adbaddr, 3); + if (adb_op_sync((Ptr)buffer, (Ptr)0, (Ptr)0, cmd)) { +#ifdef ADB_DEBUG + if (adb_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(adbaddr, 3); + if (adb_op_sync((Ptr)buffer, (Ptr)0, (Ptr)0, cmd) == 0 + && buffer[2] == ADBMS_MSA3) { + sc->handler_id = ADBMS_MSA3; + /* Initialize as above */ + cmd = ADBLISTEN(adbaddr, 2); + /* listen 2 */ + buffer[0] = 3; + buffer[1] = 0x00; + /* Irrelevant, buffer has 0x77 */ + buffer[2] = 0x07; + /* + * enable 3 button mode = 0111b, + * speed = normal + */ + adb_op_sync((Ptr)buffer, (Ptr)0, (Ptr)0, cmd); + sc->sc_buttons = 3; + sc->sc_res = 300; + } else { + /* No special support for this mouse */ + } + } + } +} + +/* + * Handle putting the mouse data received from the ADB into + * an ADB event record. + */ +void +ms_adbcomplete(buffer, data_area, adb_command) + caddr_t buffer; + caddr_t data_area; + int adb_command; +{ + adb_event_t event; + struct ams_softc *sc; + int adbaddr; +#ifdef ADB_DEBUG + int i; + + if (adb_debug) + printf("adb: transaction completion\n"); +#endif + + adbaddr = ADB_CMDADDR(adb_command); + sc = (struct ams_softc *)data_area; + + if ((sc->handler_id == ADBMS_EXTENDED) && (sc->sc_devid[0] == 0)) { + /* massage the data to look like EMP data */ + if ((buffer[3] & 0x04) == 0x04) + buffer[1] &= 0x7f; + else + buffer[1] |= 0x80; + if ((buffer[3] & 0x02) == 0x02) + buffer[2] &= 0x7f; + else + buffer[2] |= 0x80; + if ((buffer[3] & 0x01) == 0x01) + buffer[3] = 0x00; + else + buffer[3] = 0x80; + } + + event.addr = adbaddr; + event.hand_id = sc->handler_id; + event.def_addr = sc->origaddr; + event.byte_count = buffer[0]; + memcpy(event.bytes, buffer + 1, event.byte_count); + +#ifdef ADB_DEBUG + if (adb_debug) { + printf("ams: from %d at %d (org %d) %d:", event.addr, + event.hand_id, event.def_addr, buffer[0]); + for (i = 1; i <= buffer[0]; i++) + printf(" %x", buffer[i]); + printf("\n"); + } +#endif + + microtime(&event.timestamp); + + ms_processevent(&event, sc); +} + +/* + * Given a mouse ADB event, record the button settings, calculate the + * x- and y-axis motion, and handoff the event to the appropriate subsystem. + */ +static void +ms_processevent(event, sc) + adb_event_t *event; + struct ams_softc *sc; +{ + adb_event_t new_event; + int i, button_bit, max_byte, mask, buttons; + + new_event = *event; + buttons = 0; + + /* + * This should handle both plain ol' Apple mice and mice + * that claim to support the Extended Apple Mouse Protocol. + */ + max_byte = event->byte_count; + button_bit = 1; + switch (event->hand_id) { + case ADBMS_USPEED: + case ADBMS_UCONTOUR: + /* MicroSpeed mouse and Contour mouse */ + if (max_byte == 4) + buttons = (~event->bytes[2]) & 0xff; + else + buttons = (event->bytes[0] & 0x80) ? 0 : 1; + break; + case ADBMS_MSA3: + /* Mouse Systems A3 mouse */ + if (max_byte == 3) + buttons = (~event->bytes[2]) & 0x07; + else + buttons = (event->bytes[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 (!(event->bytes[i] & 0x80)) + buttons |= button_bit; + else + buttons &= ~button_bit; + /* Extended Protocol (up to 6 more buttons) */ + for (mask = 0x80; i < max_byte; + i += (mask == 0x80), button_bit <<= 1) { + /* 0 when button down */ + if (!(event->bytes[i] & mask)) + buttons |= button_bit; + else + buttons &= ~button_bit; + mask = ((mask >> 4) & 0xf) + | ((mask & 0xf) << 4); + } + break; + } + new_event.u.m.buttons = sc->sc_mb | buttons; + new_event.u.m.dx = ((signed int) (event->bytes[1] & 0x3f)) - + ((event->bytes[1] & 0x40) ? 64 : 0); + new_event.u.m.dy = ((signed int) (event->bytes[0] & 0x3f)) - + ((event->bytes[0] & 0x40) ? 64 : 0); + + if (sc->sc_wsmousedev) + wsmouse_input(sc->sc_wsmousedev, new_event.u.m.buttons, + new_event.u.m.dx, -new_event.u.m.dy, 0, + WSMOUSE_INPUT_DELTA); +#if NAED > 0 + aed_input(&new_event); +#endif +} + +int +ams_enable(v) + void *v; +{ + return 0; +} + +int +ams_ioctl(v, cmd, data, flag, p) + void *v; + u_long cmd; + caddr_t data; + int flag; + struct proc *p; +{ + return -1; +} + +void +ams_disable(v) + void *v; +{ +} |