patch-2.1.79 linux/drivers/macintosh/mac_keyb.c

Next file: linux/drivers/macintosh/macio-adb.c
Previous file: linux/drivers/macintosh/control.c
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.1.78/linux/drivers/macintosh/mac_keyb.c linux/drivers/macintosh/mac_keyb.c
@@ -18,6 +18,7 @@
 
 #include <asm/keyboard.h>
 #include <asm/bitops.h>
+#include <asm/adb.h>
 #include <asm/cuda.h>
 
 #include <linux/kbd_kern.h>
@@ -27,15 +28,19 @@
 #define KEYB_LEDREG	2	/* register # for leds on ADB keyboard */
 #define MOUSE_DATAREG	0	/* reg# for movement/button codes from mouse */
 
-unsigned char kbd_read_mask = 0;	/* XXX */
-
 static void kbd_repeat(unsigned long);
 static struct timer_list repeat_timer = { NULL, NULL, 0, 0, kbd_repeat };
 static int last_keycode;
 
-static void keyboard_input(unsigned char *, int, struct pt_regs *);
+static void keyboard_input(unsigned char *, int, struct pt_regs *, int);
 static void input_keycode(int, int);
-static void leds_done(struct cuda_request *);
+static void leds_done(struct adb_request *);
+
+/* XXX: Hook for mouse driver */
+void (*adb_mouse_interrupt_hook) (char *, int);
+int adb_emulate_button2;
+int adb_emulate_button3;
+extern int console_loglevel;
 
 extern struct kbd_struct kbd_table[];
 
@@ -75,14 +80,11 @@
 	if (!raw_mode) {
 		/*
 		 * Convert R-shift/control/option to L version.
-		 * Remap keycode 0 (A) to the unused keycode 0x5a.
-		 * Other parts of the system assume 0 is not a valid keycode.
 		 */
 		switch (keycode) {
 		case 0x7b: keycode = 0x38; break; /* R-shift */
 		case 0x7c: keycode = 0x3a; break; /* R-option */
 		case 0x7d: keycode = 0x36; break; /* R-control */
-		case 0:	   keycode = 0x5a; break; /* A */
 		}
 	}
 	*keycodep = keycode;
@@ -95,15 +97,15 @@
 }
 
 static void
-keyboard_input(unsigned char *data, int nb, struct pt_regs *regs)
+keyboard_input(unsigned char *data, int nb, struct pt_regs *regs, int apoll)
 {
 	/* first check this is from register 0 */
-	if (nb != 5 || (data[2] & 3) != KEYB_KEYREG)
+	if (nb != 3 || (data[0] & 3) != KEYB_KEYREG)
 		return;		/* ignore it */
 	kbd_pt_regs = regs;
-	input_keycode(data[3], 0);
-	if (!(data[4] == 0xff || (data[4] == 0x7f && data[3] == 0x7f)))
-		input_keycode(data[4], 0);
+	input_keycode(data[1], 0);
+	if (!(data[2] == 0xff || (data[2] == 0x7f && data[1] == 0x7f)))
+		input_keycode(data[2], 0);
 }
 
 static void
@@ -114,10 +116,66 @@
 
  	kbd = kbd_table + fg_console;
 	up_flag = (keycode & 0x80);
-        keycode &= 0x7f;
+	keycode &= 0x7f;
+
 	if (!repeat)
 		del_timer(&repeat_timer);
 
+	/*
+	 * XXX: Add mouse button 2+3 fake codes here if mouse open.
+	 *	Keep track of 'button' states here as we only send 
+	 *	single up/down events!
+	 *	Really messy; might need to check if keyboard is in
+	 *	VC_RAW mode.
+	 *	Might also want to know how many buttons need to be emulated.
+	 *	-> hide this as function in arch/m68k/mac ?
+	 */
+	if (adb_mouse_interrupt_hook || console_loglevel == 10) {
+		unsigned char button, button2, button3, fake_event;
+		static unsigned char button2state=0, button3state=0; /* up */
+		/* faked ADB packet */
+		static char data[4] = { 0, 0x80, 0x80, 0x80 };
+
+		button = 0;
+		fake_event = 0;
+		switch (keycode) {	/* which 'button' ? */
+			case 0x7c:	/* R-option */
+				button2 = (!up_flag);		/* new state */
+				if (button2 != button2state)	/* change ? */
+					button = 2; 
+				button2state = button2;		/* save state */
+				fake_event = 2;
+				break; 
+			case 0x7d:	/* R-control */
+				button3 = (!up_flag);		/* new state */
+				if (button3 != button3state)	/* change ? */ 
+					button = 3; 
+				button3state = button3; 	/* save state */
+				fake_event = 3;
+				break; 
+		}
+		if (fake_event && console_loglevel >= 8)
+			printk("fake event: button2 %d button3 %d button %d\n",
+				 button2state, button3state, button);
+		if (button) {		/* there's been a button state change */
+			/* fake a mouse packet : send all bytes, change one! */
+			data[button] = (up_flag ? 0x80 : 0);
+			if (adb_mouse_interrupt_hook)
+				adb_mouse_interrupt_hook(data, -1);
+			else
+				printk("mouse_fake: data %x %x %x buttons %x \n", 
+					data[1], data[2], data[3],
+					~( (data[1] & 0x80 ? 0 : 4) 
+					 | (data[2] & 0x80 ? 0 : 1) 
+					 | (data[3] & 0x80 ? 0 : 2) )&7 );
+		}
+		/*
+		 * XXX: testing mouse emulation ... don't process fake keys!
+		 */
+		if (fake_event)
+			return;
+	}
+
 	if (kbd->kbdmode != VC_RAW) {
 		if (!up_flag && !dont_repeat[keycode]) {
 			last_keycode = keycode;
@@ -126,11 +184,23 @@
 		}
 
 		/*
-		 * XXX fix caps-lock behaviour by turning the key-up
-		 * transition into a key-down transition.
+		 * adb kludge!! Imitate pc caps lock behaviour by
+		 * generating an up/down event for each time caps
+		 * is pressed/released. Also, makes sure that the
+		 * LED are handled.  atong@uiuc.edu
 		 */
-		if (keycode == 0x39 && up_flag && vc_kbd_led(kbd, VC_CAPSLOCK))
-			up_flag = 0;
+		 switch (keycode) {
+		 /*case 0xb9:*/
+		 case 0x39:
+			handle_scancode(0x39);
+			handle_scancode(0xb9);
+		 	mark_bh(KEYBOARD_BH);
+		 	return;
+		 case 0x47:
+		 /*case 0xc7:*/
+		 	mark_bh(KEYBOARD_BH);
+		 	break;
+		 }
 	}
 
 	handle_scancode(keycode + up_flag);
@@ -148,7 +218,7 @@
 }
 
 static void
-mouse_input(unsigned char *data, int nb, struct pt_regs *regs)
+mouse_input(unsigned char *data, int nb, struct pt_regs *regs, int autopoll)
 {
   /* [ACA:23-Mar-97] Three button mouse support.  This is designed to
      function with MkLinux DR-2.1 style X servers.  It only works with
@@ -230,6 +300,18 @@
   */
 	struct kbd_struct *kbd;
 
+	if (adb_mouse_interrupt_hook)
+		adb_mouse_interrupt_hook(data, nb);
+	else
+		if (console_loglevel == 10)
+		    printk("mouse_input: data %x %x %x buttons %x dx %d dy %d \n", 
+			data[1], data[2], data[3],
+			~((data[1] & 0x80 ? 0 : 4) 
+			| (data[2] & 0x80 ? 0 : 1)
+			| (data[3] & 0x80 ? 0 : 2))&7,
+			((data[2]&0x7f) < 64 ? (data[2]&0x7f) : (data[2]&0x7f)-128 ),
+			((data[1]&0x7f) < 64 ? -(data[1]&0x7f) : 128-(data[1]&0x7f) ) );
+
 	kbd = kbd_table + fg_console;
 
 	/* Only send mouse codes when keyboard is in raw mode. */
@@ -239,13 +321,13 @@
 
 		/* Send first button, second button and movement. */
 		put_queue( 0x7e );
-		put_queue( data[3] );
-		put_queue( data[4] );
+		put_queue( data[1] );
+		put_queue( data[2] );
 
 		/* [ACA: Are there any two-button ADB mice that use handler 1 or 2?] */
 
 		/* Store the button state. */
-		uchButtonSecond = (data[4] & 0x80);
+		uchButtonSecond = (data[2] & 0x80);
 
 		/* Send second button. */
 		if (uchButtonSecond != uch_ButtonStateSecond) {
@@ -254,12 +336,12 @@
 		}
 
 		/* Macintosh 3-button mouse (handler 4). */
-		if ((nb == 6) && (data[1] & 0x40)) {
+		if ((nb == 6) && autopoll /*?*/) {
 			static unsigned char uch_ButtonStateThird = 0;
 			unsigned char uchButtonThird;
 
 			/* Store the button state for speed. */
-			uchButtonThird = (data[5] & 0x80);
+			uchButtonThird = (data[3] & 0x80);
 
 			/* Send third button. */
 			if (uchButtonThird != uch_ButtonStateThird) {
@@ -282,20 +364,20 @@
     7,		/* caps + num + scroll lock */
 };
 
-static struct cuda_request led_request;
+static struct adb_request led_request;
 static int leds_pending;
 
 void mackbd_leds(unsigned char leds)
 {
-	if (led_request.got_reply) {
-		cuda_request(&led_request, leds_done, 4, ADB_PACKET,
+	if (led_request.complete) {
+		adb_request(&led_request, leds_done, 0, 3,
 			     ADB_WRITEREG(ADB_KEYBOARD, KEYB_LEDREG),
 			     0xff, ~mac_ledmap[leds]);
 	} else
 		leds_pending = leds | 0x100;
 }
 
-static void leds_done(struct cuda_request *req)
+static void leds_done(struct adb_request *req)
 {
 	int leds;
 
@@ -308,36 +390,32 @@
 
 void mackbd_init_hw(void)
 {
-	struct cuda_request req;
+	struct adb_request req;
+
+	/* initialize mouse interrupt hook */
+	adb_mouse_interrupt_hook = NULL;
+	/* assume broken mouse :-) - should be adjusted based on 
+	 * result of the mouse setup !! (or passed as  kernel option) */
+	adb_emulate_button2 = 1;
+	adb_emulate_button3 = 1;
 
 	adb_register(ADB_KEYBOARD, keyboard_input);
 	adb_register(ADB_MOUSE, mouse_input);
 
-	/* turn on ADB auto-polling in the CUDA */
-	cuda_request(&req, NULL, 3, CUDA_PACKET, CUDA_AUTOPOLL, 1);
-	while (!req.got_reply)
-	    cuda_poll();
-
 	/* turn off all leds */
-	cuda_request(&req, NULL, 4, ADB_PACKET,
-		     ADB_WRITEREG(ADB_KEYBOARD, KEYB_LEDREG), 0xff, 0xff);
-	while (!req.got_reply)
-	    cuda_poll();
+	adb_request(&req, NULL, ADBREQ_SYNC, 3,
+		    ADB_WRITEREG(ADB_KEYBOARD, KEYB_LEDREG), 0xff, 0xff);
 
 	/* get the keyboard to send separate codes for
 	   left and right shift, control, option keys. */
-	cuda_request(&req, NULL, 4, ADB_PACKET,
-		     ADB_WRITEREG(ADB_KEYBOARD, 3), 0, 3);
-	while (!req.got_reply)
-	    cuda_poll();
+	adb_request(&req, NULL, ADBREQ_SYNC, 3,
+		    ADB_WRITEREG(ADB_KEYBOARD, 3), 0, 3);
 
-	led_request.got_reply = 1;
+	led_request.complete = 1;
 
 	/* Try to switch the mouse (id 3) to handler 4, for three-button
 	   mode. (0x20 is Service Request Enable, 0x03 is Device ID). */
-	cuda_request(&req, NULL, 4, ADB_PACKET,
-		     ADB_WRITEREG(ADB_MOUSE, 3), 0x23, 4 );
-	while (!req.got_reply)
-		cuda_poll();
+	adb_request(&req, NULL, ADBREQ_SYNC, 3,
+		    ADB_WRITEREG(ADB_MOUSE, 3), 0x23, 4 );
 }
 

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov