nanogui@linuxhacker.org
Hi,
I was playing around with nanogui 0.88 a while back and noticed that
the X11 keyboard driver is fairly broken with respect to control
characters and such. This patch makes wterm behave reasonably well
(nearly well enough to run Emacs, actually) on X11.
Unfortunately it appears that there are no globally defined constants
for the modifiers that are supposed to be returned in GetModifierInfo
and friends, so I'm using the nanoX ones.
Also, this patch adds a Linux /dev/psaux mouse driver (almost entirely
copy-and-paste from the serial driver - it should probably be merged
into there instead) and adds the third button in the PS/2 protocol to
the serial mouse driver.
Cheers
(comments should Cc:'ed to me as I'm not on the list)
diff -urN microwin-vanilla/src/drivers/Makefile microwin/src/drivers/Makefile
--- microwin-vanilla/src/drivers/Makefile Fri Aug 4 00:37:37 2000
+++ microwin/src/drivers/Makefile Sat Aug 5 15:37:05 2000
@@ -131,6 +131,10 @@
OBJS += mou_gpm.o
endif
+ifeq ($(PS2MOUSE), Y)
+OBJS += mou_ps2.o
+endif
+
ifeq ($(SERMOUSE), Y)
OBJS += mou_ser.o
endif
diff -urN microwin-vanilla/src/drivers/kbd_tty.c microwin/src/drivers/kbd_tty.c
--- microwin-vanilla/src/drivers/kbd_tty.c Wed Jun 14 12:54:37 2000
+++ microwin/src/drivers/kbd_tty.c Sat Aug 5 14:58:47 2000
@@ -95,7 +95,7 @@
static void
TTY_GetModifierInfo(int *modifiers)
{
- *modifiers = 0; /* no modifiers available */
+ *modifiers = 7;
}
/*
@@ -108,7 +108,7 @@
{
int cc; /* characters read */
- *modifiers = 0; /* no modifiers yet */
+ *modifiers = 0;
cc = read(fd, buf, 1);
if (cc > 0) {
if(*buf == 0x1b)
diff -urN microwin-vanilla/src/drivers/kbd_x11.c microwin/src/drivers/kbd_x11.c
--- microwin-vanilla/src/drivers/kbd_x11.c Fri Aug 4 01:31:08 2000
+++ microwin/src/drivers/kbd_x11.c Sat Aug 5 15:04:22 2000
@@ -3,9 +3,11 @@
*
* X11 Keyboard driver
*/
+#include <stdio.h>
#include <unistd.h>
#include <errno.h>
#include <X11/Xlib.h>
+#include <X11/Xutil.h>
#include <X11/keysym.h>
#include "device.h"
@@ -61,7 +63,7 @@
static void
X11_GetModifierInfo(int *modifiers)
{
- *modifiers = 0; /* no modifiers available */
+ *modifiers = 7;
}
/*
@@ -80,15 +82,22 @@
{
XEvent ev;
- *modifiers = 0; /* no modifiers yet */
+ *buf = 0;
+ *modifiers = 0;
/* check if we have a KeyPressedEvent */
if (XCheckMaskEvent(x11_dpy, KeyPressMask, &ev)) {
- KeySym sym = XKeycodeToKeysym(x11_dpy, ev.xkey.keycode, 0);
+ KeySym sym;
+ int l;
+
+ /* Note: only valid for Latin-1 */
+ l = XLookupString(&ev.xkey, buf, 1, &sym, NULL);
if (sym == NoSymbol)
return -1;
+ if (l == 0)
+ return 0;
else if (sym == XK_Escape) {
- if (ev.xkey.state & ControlMask) {
+ if (ev.xkey.state & Mod1Mask) {
/* toggle grab control */
if (grabbed) {
XUngrabPointer(x11_dpy, CurrentTime);
@@ -134,8 +143,16 @@
x11_accel_den, 0);
return -2;
}
- else
- *buf = sym & 0xff; /* strip symbol to ascii */
+
+ if (ev.xkey.state & ShiftMask) {
+ *modifiers |= 1;
+ }
+ if (ev.xkey.state & ControlMask) {
+ *modifiers |= 2;
+ }
+ if (ev.xkey.state & Mod1Mask) {
+ *modifiers |= 4;
+ }
return 1;
}
return 0;
diff -urN microwin-vanilla/src/drivers/mou_ps2.c microwin/src/drivers/mou_ps2.c
--- microwin-vanilla/src/drivers/mou_ps2.c Wed Dec 31 19:00:00 1969
+++ microwin/src/drivers/mou_ps2.c Sat Aug 5 15:37:19 2000
@@ -0,0 +1,220 @@
+/*
+ * Linux PS/2 and USB mouse driver.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <string.h>
+#include <termios.h>
+#include "device.h"
+
+#define SCALE 3 /* default scaling factor for acceleration */
+#define THRESH 5 /* default threshhold for acceleration */
+#define MOUSE_PORT "/dev/psaux" /* should be /dev/usbmouse for USB? */
+
+/* states for the mouse*/
+#define IDLE 0 /* start of byte sequence */
+#define XSET 1 /* setting x delta */
+#define YSET 2 /* setting y delta */
+#define XADD 3 /* adjusting x delta */
+#define YADD 4 /* adjusting y delta */
+
+#define PS2_CTRL_BYTE 0x08
+#define PS2_LEFT_BUTTON 1
+#define PS2_RIGHT_BUTTON 2
+#define PS2_MIDDLE_BUTTON 4
+
+static int mouse_fd;
+static int state;
+static int buttons;
+static int xd, yd;
+
+static int ps2_open(MOUSEDEVICE *pmd);
+static void ps2_close(void);
+static int ps2_get_button_info(void);
+static void ps2_get_default_accel(int *pscale,int *pthresh);
+static int ps2_read(MWCOORD *dx, MWCOORD *dy, MWCOORD *dz, int *bptr);
+
+MOUSEDEVICE mousedev = {
+ ps2_open,
+ ps2_close,
+ ps2_get_button_info,
+ ps2_get_default_accel,
+ ps2_read,
+ NULL
+};
+
+/*
+ * Open up the mouse device.
+ * Returns the fd if successful, or negative if unsuccessful.
+ */
+static int
+ps2_open(MOUSEDEVICE *pmd)
+{
+ static const unsigned char s2[] = { 246, 230, 244, 243, 100, 232, 3, };
+ char const *port;
+
+ if (!(port = getenv("MOUSE_PORT")))
+ port = MOUSE_PORT;
+ mouse_fd = open(port, O_RDONLY | O_NONBLOCK);
+ if (mouse_fd < 0) {
+ EPRINTF("Error %d opening PS/2 mouse on port %s.\n",
+ errno, port);
+ return -1;
+ }
+
+ write (mouse_fd, s2, sizeof s2);
+ usleep (30000);
+ tcflush (mouse_fd, TCIFLUSH);
+
+ state = IDLE;
+ buttons = 0;
+ xd = yd = 0;
+
+ return 0;
+}
+
+/*
+ * Close the mouse device.
+ */
+static void
+ps2_close(void)
+{
+ if (mouse_fd > 0) {
+ close(mouse_fd);
+ }
+ mouse_fd = 0;
+}
+
+/*
+ * Get mouse buttons supported
+ */
+static int
+ps2_get_button_info(void)
+{
+ return MWBUTTON_L | MWBUTTON_M | MWBUTTON_R;
+}
+
+/*
+ * Get default mouse acceleration settings
+ */
+static void
+ps2_get_default_accel(int *pscale,int *pthresh)
+{
+ *pscale = SCALE;
+ *pthresh = THRESH;
+}
+
+/*
+ * Input routine for PS/2 mouse.
+ * Returns nonzero when a new mouse state has been completed.
+ */
+static int
+parse_ps2(int byte)
+{
+ switch (state) {
+ case IDLE:
+ if (byte & PS2_CTRL_BYTE) {
+ buttons = byte &
+ (PS2_LEFT_BUTTON
+ | PS2_RIGHT_BUTTON
+ | PS2_MIDDLE_BUTTON);
+ state = XSET;
+ }
+ break;
+
+ case XSET:
+ if(byte > 127)
+ byte -= 256;
+ xd = byte;
+ state = YSET;
+ break;
+
+ case YSET:
+ if(byte > 127)
+ byte -= 256;
+ yd = -byte;
+ state = IDLE;
+ return 1;
+ }
+ return 0;
+}
+
+/*
+ * Attempt to read bytes from the mouse and interpret them.
+ * Returns -1 on error, 0 if either no bytes were read or not enough
+ * was read for a complete state, or 1 if the new state was read.
+ * When a new state is read, the current buttons and x and y deltas
+ * are returned. This routine does not block.
+ */
+static int
+ps2_read(MWCOORD *dx, MWCOORD *dy, MWCOORD *dz, int *bptr)
+{
+ int b;
+ static int nbytes;
+ static unsigned char *bp;
+ static unsigned char buffer[128];
+
+ /*
+ * If there are no more bytes left, then read some more,
+ * waiting for them to arrive. On a signal or a non-blocking
+ * error, return saying there is no new state available yet.
+ */
+ if (nbytes <= 0) {
+ bp = buffer;
+ nbytes = read(mouse_fd, bp, sizeof(buffer));
+ if (nbytes < 0) {
+ if (errno == EINTR || errno == EAGAIN)
+ return 0;
+ return -1;
+ }
+ }
+
+ /*
+ * Loop over all the bytes read in the buffer, parsing them.
+ * When a complete state has been read, return the results,
+ * leaving further bytes in the buffer for later calls.
+ */
+ while (nbytes-- > 0) {
+ if (parse_ps2(*bp++)) {
+ *dx = xd;
+ *dy = yd;
+ *dz = 0;
+ b = 0;
+ if (buttons & PS2_LEFT_BUTTON)
+ b |= MWBUTTON_L;
+ if (buttons & PS2_RIGHT_BUTTON)
+ b |= MWBUTTON_R;
+ if (buttons & PS2_MIDDLE_BUTTON)
+ b |= MWBUTTON_M;
+ *bptr = b;
+ return 1;
+ }
+ }
+ return 0;
+}
+
+
+/* #define TEST 1 */
+#if TEST
+main()
+{
+ MWCOORD x, y, z;
+ int b;
+
+ DPRINTF("Open Mouse\n");
+ if( ps2_open(0) < 0)
+ DPRINTF("open failed mouse\n" );
+
+ while(1)
+ {
+ if(ps2_read(&x, &y, &z, &b) == 1)
+ {
+ DPRINTF("%d,%d,%d\n", x, y, b);
+ }
+ }
+}
+#endif
diff -urN microwin-vanilla/src/drivers/mou_ser.c microwin/src/drivers/mou_ser.c
--- microwin-vanilla/src/drivers/mou_ser.c Wed Jun 14 12:53:50 2000
+++ microwin/src/drivers/mou_ser.c Sat Aug 5 15:44:04 2000
@@ -71,6 +71,7 @@
#define PS2_CTRL_BYTE 0x08
#define PS2_LEFT_BUTTON 1
#define PS2_RIGHT_BUTTON 2
+#define PS2_MIDDLE_BUTTON 4
/* Bit fields in the bytes sent by the mouse.*/
#define TOP_FIVE_BITS 0xf8
@@ -419,7 +420,9 @@
case IDLE:
if (byte & PS2_CTRL_BYTE) {
buttons = byte &
- (PS2_LEFT_BUTTON|PS2_RIGHT_BUTTON);
+ (PS2_LEFT_BUTTON
+ | PS2_RIGHT_BUTTON
+ | PS2_MIDDLE_BUTTON);
state = XSET;
}
break;
--
dhd@linuxcare.com, http://www.linuxcare.com/
Linuxcare. Support for the revolution.