/* $NetBSD: adbsys.c,v 1.48 2009/11/01 01:51:35 snj Exp $ */ /*- * Copyright (C) 1994 Bradley A. Grantham * 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. * * 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 __KERNEL_RCSID(0, "$NetBSD: adbsys.c,v 1.48 2009/11/01 01:51:35 snj Exp $"); #include "opt_adb.h" #include #include #include #include #include #include extern struct mac68k_machine_S mac68k_machine; /* from adb.c */ void adb_processevent(adb_event_t *); extern void adb_jadbproc(void); void adb_complete(void *buffer, void *data_area, int adb_command) { adb_event_t event; ADBDataBlock adbdata; int adbaddr; int error; #ifdef ADB_DEBUG int i; if (adb_debug) printf("adb: transaction completion\n"); #endif adbaddr = ADB_CMDADDR(adb_command); error = GetADBInfo(&adbdata, adbaddr); #ifdef ADB_DEBUG if (adb_debug) printf("adb: GetADBInfo returned %d\n", error); #endif event.addr = adbaddr; event.hand_id = (int)(adbdata.devType); event.def_addr = (int)(adbdata.origADBAddr); event.byte_count = buffer[0]; memcpy(event.bytes, buffer + 1, event.byte_count); #ifdef ADB_DEBUG if (adb_debug) { printf("adb: 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); adb_processevent(&event); } void adb_msa3_complete(void *buffer, void *data_area, int adb_command) { adb_event_t event; ADBDataBlock adbdata; int adbaddr; int error; #ifdef ADB_DEBUG int i; if (adb_debug) printf("adb: transaction completion\n"); #endif adbaddr = ADB_CMDADDR(adb_command); error = GetADBInfo(&adbdata, adbaddr); #ifdef ADB_DEBUG if (adb_debug) printf("adb: GetADBInfo returned %d\n", error); #endif event.addr = adbaddr; event.hand_id = ADBMS_MSA3; event.def_addr = (int)(adbdata.origADBAddr); event.byte_count = buffer[0]; memcpy(event.bytes, buffer + 1, event.byte_count); #ifdef ADB_DEBUG if (adb_debug) { printf("adb: 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); adb_processevent(&event); } void adb_mm_nonemp_complete(void *buffer, void *data_area, int adb_command) { adb_event_t event; ADBDataBlock adbdata; int adbaddr; int error; #ifdef ADB_DEBUG int i; if (adb_debug) printf("adb: transaction completion\n"); #endif adbaddr = ADB_CMDADDR(adb_command); error = GetADBInfo(&adbdata, adbaddr); #ifdef ADB_DEBUG if (adb_debug) printf("adb: GetADBInfo returned %d\n", error); #endif #if 0 printf("adb: 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 /* 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 = (int)(adbdata.devType); event.def_addr = (int)(adbdata.origADBAddr); event.byte_count = buffer[0]; memcpy(event.bytes, buffer + 1, event.byte_count); #ifdef ADB_DEBUG if (adb_debug) { printf("adb: 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); adb_processevent(&event); } static volatile int extdms_done; /* * initialize extended mouse - probes devices as * described in _Inside Macintosh, Devices_. */ void extdms_init(int totaladbs) { ADBDataBlock adbdata; int adbindex, adbaddr, count; short cmd; u_char buffer[9]; for (adbindex = 1; adbindex <= totaladbs; adbindex++) { /* Get the ADB information */ adbaddr = GetIndADB(&adbdata, adbindex); if (adbdata.origADBAddr == ADBADDR_MS && (adbdata.devType == ADBMS_USPEED || adbdata.devType == 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 */ extdms_done = 0; ADBOp((Ptr)buffer, (Ptr)extdms_complete, (Ptr)&extdms_done, cmd); while (!extdms_done) /* busy wait until done */; } if (adbdata.origADBAddr == ADBADDR_MS && (adbdata.devType == ADBMS_100DPI || adbdata.devType == ADBMS_200DPI)) { /* found a mouse */ cmd = ADBTALK(adbaddr, 3); extdms_done = 0; ADBOp((Ptr)buffer, (Ptr)extdms_complete, (Ptr)&extdms_done, cmd); /* Wait until done, but no more than 2 secs */ count = 40000; while (!extdms_done && count-- > 0) delay(50); if (!extdms_done) { #ifdef ADB_DEBUG if (adb_debug) printf("adb: extdms_init timed out\n"); #endif return; } /* Attempt to initialize Extended Mouse Protocol */ buffer[2] = '\004'; /* make handler ID 4 */ extdms_done = 0; cmd = ADBLISTEN(adbaddr, 3); ADBOp((Ptr)buffer, (Ptr)extdms_complete, (Ptr)&extdms_done, cmd); while (!extdms_done) /* busy wait until done */; /* * Check to see if successful, if not * try to initialize it as other types */ cmd = ADBTALK(adbaddr, 3); extdms_done = 0; ADBOp((Ptr)buffer, (Ptr)extdms_complete, (Ptr)&extdms_done, cmd); while (!extdms_done) /* busy wait until done */; if (buffer[2] != ADBMS_EXTENDED) { /* Attempt to initialize as an A3 mouse */ buffer[2] = 0x03; /* make handler ID 3 */ extdms_done = 0; cmd = ADBLISTEN(adbaddr, 3); ADBOp((Ptr)buffer, (Ptr)extdms_complete, (Ptr)&extdms_done, cmd); while (!extdms_done) /* busy wait until done */; /* * Check to see if successful, if not * try to initialize it as other types */ cmd = ADBTALK(adbaddr, 3); extdms_done = 0; ADBOp((Ptr)buffer, (Ptr)extdms_complete, (Ptr)&extdms_done, cmd); while (!extdms_done) /* busy wait until done */; if (buffer[2] == 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 */ extdms_done = 0; ADBOp((Ptr)buffer, (Ptr)extdms_complete, (Ptr)&extdms_done, cmd); while (!extdms_done) /* busy wait until done */; } else { /* No special support for this mouse */ } } } } }