plan 9 kernel history: overview | file list | diff list

1994/0520/port/devmouse.c (diff list | history)

port/devmouse.c on 1993/1006
1993/1006    
#include	"u.h" 
#include	"../port/lib.h" 
#include	<libg.h> 
#include	"mem.h" 
#include	"dat.h" 
#include	"fns.h" 
#include	"../port/error.h" 
 
#include	"devtab.h" 
1994/0210    
#include	"screen.h" 
1993/1006    
 
typedef struct Mouseinfo	Mouseinfo; 
 
struct Mouseinfo 
{ 
	/* 
	 * First three fields are known in some l.s's 
	 */ 
	int	dx; 
	int	dy; 
	int	track;		/* l.s has updated dx & dy */ 
	Mouse; 
	int	redraw;		/* update cursor on screen */ 
	ulong	counter;	/* increments every update */ 
	ulong	lastcounter;	/* value when /dev/mouse read */ 
	Rendez	r; 
	Ref; 
	QLock; 
	int	open; 
}; 
 
Mouseinfo	mouse; 
Cursorinfo	cursor; 
int		mouseshifted; 
int		mousetype; 
1994/0216    
int		mouseswap; 
1994/0414    
Cursor		curs; 
1993/1006    
 
Cursor	arrow = 
{ 
	{-1, -1}, 
	{0xFF, 0xE0, 0xFF, 0xE0, 0xFF, 0xC0, 0xFF, 0x00, 
	 0xFF, 0x00, 0xFF, 0x80, 0xFF, 0xC0, 0xFF, 0xE0, 
	 0xE7, 0xF0, 0xE3, 0xF8, 0xC1, 0xFC, 0x00, 0xFE, 
	 0x00, 0x7F, 0x00, 0x3E, 0x00, 0x1C, 0x00, 0x08, 
	}, 
	{0x00, 0x00, 0x7F, 0xC0, 0x7F, 0x00, 0x7C, 0x00, 
	 0x7E, 0x00, 0x7F, 0x00, 0x6F, 0x80, 0x67, 0xC0, 
	 0x43, 0xE0, 0x41, 0xF0, 0x00, 0xF8, 0x00, 0x7C, 
	 0x00, 0x3E, 0x00, 0x1C, 0x00, 0x08, 0x00, 0x00, 
	} 
}; 
 
void	Cursortocursor(Cursor*); 
int	mousechanged(void*); 
 
enum{ 
	Qdir, 
1993/1009    
	Qcursor, 
1993/1006    
	Qmouse, 
	Qmousectl, 
}; 
 
Dirtab mousedir[]={ 
1993/1009    
	"cursor",	{Qcursor},	0,			0666, 
1993/1006    
	"mouse",	{Qmouse},	0,			0666, 
	"mousectl",	{Qmousectl},	0,			0220, 
}; 
 
#define	NMOUSE	(sizeof(mousedir)/sizeof(Dirtab)) 
 
1994/0413    
extern	Bitmap	gscreen; 
1993/1006    
 
void 
mousereset(void) 
{ 
	if(!conf.monitor) 
		return; 
 
1993/1009    
	curs = arrow; 
1993/1006    
	Cursortocursor(&arrow); 
} 
 
void 
mouseinit(void) 
{ 
	if(!conf.monitor) 
		return; 
1994/0413    
 
1993/1006    
	cursoron(1); 
} 
 
Chan* 
mouseattach(char *spec) 
{ 
	if(!conf.monitor) 
		error(Egreg); 
	return devattach('m', spec); 
} 
 
Chan* 
mouseclone(Chan *c, Chan *nc) 
{ 
	nc = devclone(c, nc); 
	if(c->qid.path != CHDIR) 
		incref(&mouse); 
	return nc; 
} 
 
int 
mousewalk(Chan *c, char *name) 
{ 
	return devwalk(c, name, mousedir, NMOUSE, devgen); 
} 
 
void 
mousestat(Chan *c, char *db) 
{ 
	devstat(c, db, mousedir, NMOUSE, devgen); 
} 
 
Chan* 
mouseopen(Chan *c, int omode) 
{ 
	switch(c->qid.path){ 
	case CHDIR: 
		if(omode != OREAD) 
			error(Eperm); 
		break; 
	case Qmouse: 
		lock(&mouse); 
		if(mouse.open){ 
			unlock(&mouse); 
			error(Einuse); 
		} 
		mouse.open = 1; 
		mouse.ref++; 
		unlock(&mouse); 
		break; 
	default: 
		incref(&mouse); 
	} 
	c->mode = openmode(omode); 
	c->flag |= COPEN; 
	c->offset = 0; 
	return c; 
} 
 
void 
mousecreate(Chan *c, char *name, int omode, ulong perm) 
{ 
	if(!conf.monitor) 
		error(Egreg); 
	USED(c, name, omode, perm); 
	error(Eperm); 
} 
 
void 
mouseremove(Chan *c) 
{ 
	USED(c); 
	error(Eperm); 
} 
 
void 
mousewstat(Chan *c, char *db) 
{ 
	USED(c, db); 
	error(Eperm); 
} 
 
void 
mouseclose(Chan *c) 
{ 
	if(c->qid.path!=CHDIR && (c->flag&COPEN)){ 
		lock(&mouse); 
		if(c->qid.path == Qmouse) 
			mouse.open = 0; 
1993/1009    
		if(--mouse.ref == 0){ 
			cursoroff(1); 
			curs = arrow; 
			Cursortocursor(&arrow); 
			cursoron(1); 
		} 
1993/1006    
		unlock(&mouse); 
	} 
} 
 
1994/0216    
 
1993/1006    
long 
mouseread(Chan *c, void *va, long n, ulong offset) 
{ 
1993/1008    
	char buf[4*12+1]; 
1993/1009    
	uchar *p; 
1994/0216    
	static int map[8] = {0, 4, 2, 6, 1, 5, 3, 7 }; 
1993/1006    
 
1993/1009    
	p = va; 
	switch(c->qid.path){ 
	case CHDIR: 
1993/1006    
		return devdirread(c, va, n, mousedir, NMOUSE, devgen); 
 
1993/1009    
	case Qcursor: 
		if(offset != 0) 
			return 0; 
		if(n < 2*4+2*2*16) 
			error(Eshort); 
		n = 2*4+2*2*16; 
		lock(&cursor); 
		BPLONG(p+0, curs.offset.x); 
		BPLONG(p+4, curs.offset.y); 
		memmove(p+8, curs.clr, 2*16); 
		memmove(p+40, curs.set, 2*16); 
		unlock(&cursor); 
		return n; 
 
	case Qmouse: 
1993/1006    
		while(mousechanged(0) == 0) 
			sleep(&mouse.r, mousechanged, 0); 
		lock(&cursor); 
1993/1008    
		sprint(buf, "%11d %11d %11d %11d", 
1994/0216    
			mouse.xy.x, mouse.xy.y, 
			mouseswap ? map[mouse.buttons&7] : mouse.buttons, 
1993/1008    
			TK2MS(MACHP(0)->ticks)); 
1993/1006    
		mouse.lastcounter = mouse.counter; 
		unlock(&cursor); 
1993/1008    
		if(n > 4*12) 
			n = 4*12; 
		memmove(va, buf, n); 
		return n; 
1993/1006    
	} 
	return 0; 
} 
 
long 
mousewrite(Chan *c, void *va, long n, ulong offset) 
{ 
1993/1008    
	char *p; 
1993/1006    
	Point pt; 
	char buf[64]; 
 
1994/0325    
	USED(offset); 
1993/1009    
	p = va; 
1993/1006    
	switch(c->qid.path){ 
	case CHDIR: 
		error(Eisdir); 
1993/1009    
 
	case Qcursor: 
		cursoroff(1); 
		if(n < 2*4+2*2*16){ 
			curs = arrow; 
			Cursortocursor(&arrow); 
		}else{ 
			n = 2*4+2*2*16; 
			curs.offset.x = BGLONG(p+0); 
			curs.offset.y = BGLONG(p+4); 
			memmove(curs.clr, p+8, 2*16); 
			memmove(curs.set, p+40, 2*16); 
			Cursortocursor(&curs); 
		} 
1993/1108    
		qlock(&mouse); 
		mouse.redraw = 1; 
		mouseclock(); 
		qunlock(&mouse); 
1993/1009    
		cursoron(1); 
		return n; 
1993/1006    
 
	case Qmousectl: 
		if(n >= sizeof(buf)) 
			n = sizeof(buf)-1; 
		strncpy(buf, va, n); 
		buf[n] = 0; 
		mousectl(buf); 
		return n; 
 
	case Qmouse: 
1993/1008    
		if(n > sizeof buf-1) 
			n = sizeof buf -1; 
		memmove(buf, va, n); 
		buf[n] = 0; 
		p = 0; 
		pt.x = strtoul(buf, &p, 0); 
		if(p == 0) 
1993/1006    
			error(Eshort); 
1993/1008    
		pt.y = strtoul(p, 0, 0); 
1993/1006    
		qlock(&mouse); 
		if(ptinrect(pt, gscreen.r)){ 
			mouse.xy = pt; 
			mouse.redraw = 1; 
			mouse.track = 1; 
			mouseclock(); 
		} 
		qunlock(&mouse); 
		return n; 
	} 
 
	error(Egreg); 
	return -1; 
} 
 
void 
Cursortocursor(Cursor *c) 
{ 
	lock(&cursor); 
1994/0414    
	memmove(&cursor.Cursor, c, sizeof(Cursor)); 
1994/0520    
	setcursor(c); 
1993/1026    
	unlock(&cursor); 
} 
 
 
1993/1006    
/* 
 *  called by the clock routine to redraw the cursor 
 */ 
void 
mouseclock(void) 
{ 
	if(mouse.track){ 
		mousetrack(mouse.buttons, mouse.dx, mouse.dy); 
		mouse.track = 0; 
		mouse.dx = 0; 
		mouse.dy = 0; 
	} 
	if(mouse.redraw && canlock(&cursor)){ 
		mouse.redraw = 0; 
		cursoroff(0); 
		cursoron(0); 
		unlock(&cursor); 
	} 
} 
 
/* 
 *  called at interrupt level to update the structure and 
 *  awaken any waiting procs. 
 */ 
void 
mousetrack(int b, int dx, int dy) 
{ 
	int x, y; 
 
	x = mouse.xy.x + dx; 
	if(x < gscreen.r.min.x) 
		x = gscreen.r.min.x; 
	if(x >= gscreen.r.max.x) 
		x = gscreen.r.max.x; 
	y = mouse.xy.y + dy; 
	if(y < gscreen.r.min.y) 
		y = gscreen.r.min.y; 
	if(y >= gscreen.r.max.y) 
		y = gscreen.r.max.y; 
	mouse.counter++; 
	mouse.xy = Pt(x, y); 
	mouse.buttons = b; 
	mouse.redraw = 1; 
	wakeup(&mouse.r); 
} 
 
/* 
 *  microsoft 3 button, 7 bit bytes 
 * 
 *	byte 0 -	1  L  R Y7 Y6 X7 X6 
 *	byte 1 -	0 X5 X4 X3 X2 X1 X0 
 *	byte 2 -	0 Y5 Y4 Y3 Y2 Y1 Y0 
 *	byte 3 -	0  M  x  x  x  x  x	(optional) 
 * 
 *  shift & right button is the same as middle button (for 2 button mice) 
 */ 
int 
1993/1201    
m3mouseputc(int c) 
1993/1006    
{ 
	static uchar msg[3]; 
	static int nb; 
	static int middle; 
	static uchar b[] = { 0, 4, 1, 5, 0, 2, 1, 5 }; 
	short x; 
	int dx, dy, newbuttons; 
 
	/*  
	 *  check bit 6 for consistency 
	 */ 
	if(nb==0){ 
		if((c&0x40) == 0){ 
			/* an extra byte gets sent for the middle button */ 
			middle = (c&0x20) ? 2 : 0; 
			newbuttons = (mouse.buttons & ~2) | middle; 
			mousetrack(newbuttons, 0, 0); 
			return 0; 
		} 
	} 
	msg[nb] = c; 
	if(++nb == 3){ 
		nb = 0; 
		newbuttons = middle | b[(msg[0]>>4)&3 | (mouseshifted ? 4 : 0)]; 
		x = (msg[0]&0x3)<<14; 
		dx = (x>>8) | msg[1]; 
		x = (msg[0]&0xc)<<12; 
		dy = (x>>8) | msg[2]; 
		mousetrack(newbuttons, dx, dy); 
	} 
	return 0; 
} 
 
/* 
 *  Logitech 5 byte packed binary mouse format, 8 bit bytes 
 * 
 *  shift & right button is the same as middle button (for 2 button mice) 
 */ 
int 
1993/1201    
mouseputc(int c) 
1993/1006    
{ 
	static short msg[5]; 
	static int nb; 
	static uchar b[] = {0, 4, 2, 6, 1, 5, 3, 7, 0, 2, 2, 6, 1, 5, 3, 7}; 
	int dx, dy, newbuttons; 
 
	if((c&0xF0) == 0x80) 
		nb=0; 
	msg[nb] = c; 
	if(c & 0x80) 
		msg[nb] |= ~0xFF;	/* sign extend */ 
	if(++nb == 5){ 
		newbuttons = b[((msg[0]&7)^7) | (mouseshifted ? 8 : 0)]; 
		dx = msg[1]+msg[3]; 
		dy = -(msg[2]+msg[4]); 
		mousetrack(newbuttons, dx, dy); 
		nb = 0; 
	} 
	return 0; 
} 
 
int 
mousechanged(void *m) 
{ 
	USED(m); 
	return mouse.lastcounter - mouse.counter; 
1994/0414    
} 
 
Point 
mousexy(void) 
{ 
	return mouse.xy; 
1993/1006    
} 


source code copyright © 1990-2005 Lucent Technologies; see license
Plan 9 distribution
comments to russ cox (rsc@swtch.com)