cvsdist f476c1f
/*
Tomas Janousek d956636
 * $Id: inputattach.c,v 1.2 2007/04/02 14:18:54 tjanouse Exp $
cvsdist f476c1f
 *
cvsdist f476c1f
 *  Copyright (c) 1999-2000 Vojtech Pavlik
cvsdist f476c1f
 *
cvsdist f476c1f
 *  Sponsored by SuSE
cvsdist f476c1f
 *
cvsdist f476c1f
 *  Twiddler support Copyright (c) 2001 Arndt Schoenewald
cvsdist f476c1f
 *  Sponsored by Quelltext AG (http://www.quelltext-ag.de), Dortmund, Germany
cvsdist f476c1f
 */
cvsdist f476c1f
cvsdist f476c1f
/*
cvsdist f476c1f
 * Input line discipline attach program
cvsdist f476c1f
 */
cvsdist f476c1f
cvsdist f476c1f
/*
cvsdist f476c1f
 * This program is free software; you can redistribute it and/or modify
cvsdist f476c1f
 * it under the terms of the GNU General Public License as published by
cvsdist f476c1f
 * the Free Software Foundation; either version 2 of the License, or 
cvsdist f476c1f
 * (at your option) any later version.
cvsdist f476c1f
 * 
cvsdist f476c1f
 * This program is distributed in the hope that it will be useful,
cvsdist f476c1f
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
cvsdist f476c1f
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
cvsdist f476c1f
 * GNU General Public License for more details.
cvsdist f476c1f
 * 
cvsdist f476c1f
 * You should have received a copy of the GNU General Public License
cvsdist f476c1f
 * along with this program; if not, write to the Free Software
cvsdist f476c1f
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
cvsdist f476c1f
 * 
cvsdist f476c1f
 * Should you need to contact me, the author, you can do so either by
cvsdist f476c1f
 * e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail:
cvsdist f476c1f
 * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
cvsdist f476c1f
 */
cvsdist f476c1f
cvsdist f476c1f
#include <linux/serio.h>
cvsdist f476c1f
cvsdist f476c1f
#include <sys/types.h>
cvsdist f476c1f
#include <sys/stat.h>
cvsdist f476c1f
#include <sys/ioctl.h>
cvsdist f476c1f
#include <sys/time.h>
cvsdist f476c1f
cvsdist f476c1f
#include <stdio.h>
cvsdist f476c1f
#include <stdlib.h>
cvsdist f476c1f
#include <unistd.h>
cvsdist f476c1f
#include <fcntl.h>
cvsdist f476c1f
#include <termios.h>
cvsdist f476c1f
#include <string.h>
cvsdist f476c1f
#include <assert.h>
cvsdist f476c1f
#include <ctype.h>
cvsdist f476c1f
cvsdist f476c1f
int readchar(int fd, unsigned char *c, int timeout)
cvsdist f476c1f
{
cvsdist f476c1f
	struct timeval tv;
cvsdist f476c1f
	fd_set set;
cvsdist f476c1f
	
cvsdist f476c1f
	tv.tv_sec = 0;
cvsdist f476c1f
	tv.tv_usec = timeout * 1000;
cvsdist f476c1f
cvsdist f476c1f
	FD_ZERO(&set);
cvsdist f476c1f
	FD_SET(fd, &set);
cvsdist f476c1f
cvsdist f476c1f
	if (!select(fd+1, &set, NULL, NULL, &tv)) return -1;
cvsdist f476c1f
	if (read(fd, c, 1) != 1) return -1;
cvsdist f476c1f
cvsdist f476c1f
	return 0;
cvsdist f476c1f
}
cvsdist f476c1f
cvsdist f476c1f
cvsdist f476c1f
cvsdist f476c1f
void setline(int fd, int flags, int speed)
cvsdist f476c1f
{
cvsdist f476c1f
	struct termios t;
cvsdist f476c1f
cvsdist f476c1f
	tcgetattr(fd, &t);
cvsdist f476c1f
cvsdist f476c1f
	t.c_cflag = flags | CREAD | HUPCL | CLOCAL;
cvsdist f476c1f
	t.c_iflag = IGNBRK | IGNPAR;
cvsdist f476c1f
	t.c_oflag = 0;
cvsdist f476c1f
	t.c_lflag = 0;
cvsdist f476c1f
	t.c_cc[VMIN ] = 1;
cvsdist f476c1f
	t.c_cc[VTIME] = 0;
cvsdist f476c1f
cvsdist f476c1f
	cfsetispeed(&t, speed);
cvsdist f476c1f
	cfsetospeed(&t, speed);
cvsdist f476c1f
cvsdist f476c1f
	tcsetattr(fd, TCSANOW, &t);
cvsdist f476c1f
}
cvsdist f476c1f
cvsdist f476c1f
int logitech_command(int fd, char *c)
cvsdist f476c1f
{
cvsdist f476c1f
	int i;
cvsdist f476c1f
	unsigned char d;
cvsdist f476c1f
	for (i = 0; c[i]; i++) {
cvsdist f476c1f
		write(fd, c + i, 1);
cvsdist f476c1f
		if (readchar(fd, &d, 1000))
cvsdist f476c1f
			return -1;
cvsdist f476c1f
		if (c[i] != d)
cvsdist f476c1f
			return -1;
cvsdist f476c1f
	}
cvsdist f476c1f
	return 0;
cvsdist f476c1f
}
cvsdist f476c1f
cvsdist f476c1f
int magellan_init(int fd, long *id, long *extra)
cvsdist f476c1f
{
cvsdist f476c1f
	write(fd, "m3\rpBB\rz\r", 9);
cvsdist f476c1f
	return 0;
cvsdist f476c1f
}
cvsdist f476c1f
cvsdist f476c1f
int warrior_init(int fd, long *id, long *extra)
cvsdist f476c1f
{
cvsdist f476c1f
	if (logitech_command(fd, "*S")) return -1;
cvsdist f476c1f
	setline(fd, CS8, B4800);
cvsdist f476c1f
	return 0;
cvsdist f476c1f
}
cvsdist f476c1f
cvsdist f476c1f
int spaceball_waitchar(int fd, unsigned char c, unsigned char *d, int timeout)
cvsdist f476c1f
{
cvsdist f476c1f
	unsigned char b = 0;
cvsdist f476c1f
cvsdist f476c1f
	while (!readchar(fd, &b, timeout)) {
cvsdist f476c1f
		if (b == 0x0a) continue;
cvsdist f476c1f
		*d++ = b;
cvsdist f476c1f
		if (b == c) break;
cvsdist f476c1f
	}
cvsdist f476c1f
cvsdist f476c1f
	*d = 0;
cvsdist f476c1f
cvsdist f476c1f
	return -(b != c);
cvsdist f476c1f
}
cvsdist f476c1f
cvsdist f476c1f
int spaceball_waitcmd(int fd, char c, char *d)
cvsdist f476c1f
{
cvsdist f476c1f
	int i;
cvsdist f476c1f
cvsdist f476c1f
	for (i = 0; i < 8; i++) {
cvsdist f476c1f
		if (spaceball_waitchar(fd, 0x0d, d, 1000))
cvsdist f476c1f
			return -1;
cvsdist f476c1f
		if (d[0] == c)
cvsdist f476c1f
			return 0;
cvsdist f476c1f
	}
cvsdist f476c1f
cvsdist f476c1f
	return -1;
cvsdist f476c1f
}
cvsdist f476c1f
cvsdist f476c1f
int spaceball_cmd(int fd, char *c, char *d)
cvsdist f476c1f
{
cvsdist f476c1f
	int i;
cvsdist f476c1f
cvsdist f476c1f
	for (i = 0; c[i]; i++)
cvsdist f476c1f
		write(fd, c + i, 1);
cvsdist f476c1f
	write(fd, "\r", 1);
cvsdist f476c1f
cvsdist f476c1f
	i = spaceball_waitcmd(fd, toupper(c[0]), d);
cvsdist f476c1f
cvsdist f476c1f
	return i;
cvsdist f476c1f
}
cvsdist f476c1f
cvsdist f476c1f
#define SPACEBALL_1003		1
cvsdist f476c1f
#define SPACEBALL_2003B		3
cvsdist f476c1f
#define SPACEBALL_2003C		4
cvsdist f476c1f
#define SPACEBALL_3003C		7
cvsdist f476c1f
#define SPACEBALL_4000FLX	8
cvsdist f476c1f
#define SPACEBALL_4000FLX_L 	9
cvsdist f476c1f
cvsdist f476c1f
int spaceball_init(int fd, long *id, long *extra)
cvsdist f476c1f
{
cvsdist f476c1f
	char r[64];
cvsdist f476c1f
cvsdist f476c1f
	if (spaceball_waitchar(fd, 0x11, r, 4000) ||
cvsdist f476c1f
	    spaceball_waitchar(fd, 0x0d, r, 1000))
cvsdist f476c1f
		return -1;
cvsdist f476c1f
cvsdist f476c1f
	if (spaceball_waitcmd(fd, '@', r))
cvsdist f476c1f
		return -1; 
cvsdist f476c1f
cvsdist f476c1f
	if (strncmp("@1 Spaceball alive", r, 18))
cvsdist f476c1f
		return -1;
cvsdist f476c1f
cvsdist f476c1f
	if (spaceball_waitcmd(fd, '@', r))
cvsdist f476c1f
		return -1; 
cvsdist f476c1f
cvsdist f476c1f
	if (spaceball_cmd(fd, "hm", r))
cvsdist f476c1f
		return -1;
cvsdist f476c1f
cvsdist f476c1f
	if (!strncmp("Hm2003B", r, 7))
cvsdist f476c1f
		*id = SPACEBALL_2003B;
cvsdist f476c1f
	if (!strncmp("Hm2003C", r, 7))
cvsdist f476c1f
		*id = SPACEBALL_2003C;
cvsdist f476c1f
	if (!strncmp("Hm3003C", r, 7))
cvsdist f476c1f
		*id = SPACEBALL_3003C;
cvsdist f476c1f
cvsdist f476c1f
	if (!strncmp("HvFirmware", r, 10)) {
cvsdist f476c1f
cvsdist f476c1f
		if (spaceball_cmd(fd, "\"", r))
cvsdist f476c1f
			return -1;
cvsdist f476c1f
cvsdist f476c1f
		if (strncmp("\"1 Spaceball 4000 FLX", r, 21))
cvsdist f476c1f
			return -1;
cvsdist f476c1f
cvsdist f476c1f
		if (spaceball_waitcmd(fd, '"', r))
cvsdist f476c1f
			return -1; 
cvsdist f476c1f
cvsdist f476c1f
		if (strstr(r, " L "))
cvsdist f476c1f
			*id = SPACEBALL_4000FLX_L;
cvsdist f476c1f
		else
cvsdist f476c1f
			*id = SPACEBALL_4000FLX;
cvsdist f476c1f
cvsdist f476c1f
		if (spaceball_waitcmd(fd, '"', r))
cvsdist f476c1f
			return -1; 
cvsdist f476c1f
cvsdist f476c1f
		if (spaceball_cmd(fd, "YS", r))
cvsdist f476c1f
        	        return -1;
cvsdist f476c1f
cvsdist f476c1f
		if (spaceball_cmd(fd, "M", r))
cvsdist f476c1f
        	        return -1;
cvsdist f476c1f
cvsdist f476c1f
		return 0;
cvsdist f476c1f
	}
cvsdist f476c1f
cvsdist f476c1f
	if (spaceball_cmd(fd, "P@A@A", r) ||
cvsdist f476c1f
	    spaceball_cmd(fd, "FT@", r)   ||
cvsdist f476c1f
	    spaceball_cmd(fd, "MSS", r))
cvsdist f476c1f
		return -1;
cvsdist f476c1f
cvsdist f476c1f
	return 0;
cvsdist f476c1f
}
cvsdist f476c1f
cvsdist f476c1f
int stinger_init(int fd, long *id, long *extra)
cvsdist f476c1f
{
cvsdist f476c1f
	int i;
cvsdist f476c1f
	unsigned char c;
cvsdist f476c1f
	unsigned char *response = "\r\n0600520058C272";
cvsdist f476c1f
cvsdist f476c1f
	if (write(fd, " E5E5", 5) != 5)		/* Enable command */
cvsdist f476c1f
		return -1; 
cvsdist f476c1f
cvsdist f476c1f
	for (i = 0; i < 16; i++)		/* Check for Stinger */
cvsdist f476c1f
		if (readchar(fd, &c, 200) || (c != response[i])) 
cvsdist f476c1f
			return -1;
cvsdist f476c1f
cvsdist f476c1f
	return 0;
cvsdist f476c1f
}
cvsdist f476c1f
cvsdist f476c1f
int mzp_init(int fd, long *id, long *extra)
cvsdist f476c1f
{
cvsdist f476c1f
	if (logitech_command(fd, "*X*q")) return -1;
cvsdist f476c1f
	setline(fd, CS8, B9600);
cvsdist f476c1f
	return 0;
cvsdist f476c1f
}
cvsdist f476c1f
cvsdist f476c1f
int newton_init(int fd, long *id, long *extra)
cvsdist f476c1f
{
cvsdist f476c1f
  int i;
cvsdist f476c1f
  unsigned char c;
cvsdist f476c1f
  unsigned char response[35] =
cvsdist f476c1f
  { 0x16, 0x10, 0x02, 0x64, 0x5f, 0x69, 0x64, 0x00,
cvsdist f476c1f
    0x00, 0x00, 0x0c, 0x6b, 0x79, 0x62, 0x64, 0x61,
cvsdist f476c1f
    0x70, 0x70, 0x6c, 0x00, 0x00, 0x00, 0x01, 0x6e,
cvsdist f476c1f
    0x6f, 0x66, 0x6d, 0x00, 0x00, 0x00, 0x00, 0x10,
cvsdist f476c1f
    0x03, 0xdd, 0xe7 };
cvsdist f476c1f
cvsdist f476c1f
  for (i = 0; i < 35; i++)
cvsdist f476c1f
    if (readchar(fd, &c, 400) || (c != response[i]))
cvsdist f476c1f
      return -1;
cvsdist f476c1f
cvsdist f476c1f
  return 0;
cvsdist f476c1f
}
cvsdist f476c1f
cvsdist f476c1f
int twiddler_init(int fd, long *id, long *extra)
cvsdist f476c1f
{
cvsdist f476c1f
	unsigned char c[10];
cvsdist f476c1f
	int count, line;
cvsdist f476c1f
cvsdist f476c1f
	/* Turn DTR off, otherwise the Twiddler won't send any data. */
cvsdist f476c1f
	if (ioctl(fd, TIOCMGET, &line)) return -1;
cvsdist f476c1f
	line &= ~TIOCM_DTR;
cvsdist f476c1f
	if (ioctl(fd, TIOCMSET, &line)) return -1;
cvsdist f476c1f
cvsdist f476c1f
	/* Check whether the device on the serial line is the Twiddler.
cvsdist f476c1f
	 *
cvsdist f476c1f
	 * The Twiddler sends data packets of 5 bytes which have the following
cvsdist f476c1f
	 * properties: the MSB is 0 on the first and 1 on all other bytes, and
cvsdist f476c1f
	 * the high order nibble of the last byte is always 0x8.
cvsdist f476c1f
	 *
cvsdist f476c1f
	 * We read and check two of those 5 byte packets to be sure that we
cvsdist f476c1f
	 * are indeed talking to a Twiddler. */
cvsdist f476c1f
cvsdist f476c1f
	/* Read at most 5 bytes until we find one with the MSB set to 0 */
cvsdist f476c1f
	for (count = 0; count < 5; count++) {
cvsdist f476c1f
		if (readchar(fd, c+0, 500)) return -1;
cvsdist f476c1f
		if ((c[0] & 0x80) == 0) break;
cvsdist f476c1f
	}
cvsdist f476c1f
cvsdist f476c1f
	if (count == 5) {
cvsdist f476c1f
		/* Could not find header byte in data stream */
cvsdist f476c1f
		return -1;
cvsdist f476c1f
	}
cvsdist f476c1f
cvsdist f476c1f
	/* Read remaining 4 bytes plus the full next data packet */
cvsdist f476c1f
	for (count = 1; count < 10; count++) {
cvsdist f476c1f
		if (readchar(fd, c+count, 500)) return -1;
cvsdist f476c1f
	}
cvsdist f476c1f
cvsdist f476c1f
	/* Check whether the bytes of both data packets obey the rules */
cvsdist f476c1f
	for (count = 1; count < 10; count++) {
cvsdist f476c1f
		if ((count % 5 == 0 && (c[count] & 0x80) != 0)
cvsdist f476c1f
		    || (count % 5 == 4 && (c[count] & 0xF0) != 0x80)
cvsdist f476c1f
		    || (count % 5 != 0 && (c[count] & 0x80) != 0x80)) {
cvsdist f476c1f
		    	/* Invalid byte in data packet */
cvsdist f476c1f
			return -1;
cvsdist f476c1f
		}
cvsdist f476c1f
	}
cvsdist f476c1f
cvsdist f476c1f
	return 0;
cvsdist f476c1f
}
cvsdist f476c1f
cvsdist f476c1f
int dump_init(int fd, long *id, long *extra)
cvsdist f476c1f
{
cvsdist f476c1f
	unsigned char c, o = 0;
cvsdist f476c1f
cvsdist f476c1f
	c = 0x80;
cvsdist f476c1f
cvsdist f476c1f
	if (write(fd, &c, 1) != 1)         /* Enable command */
cvsdist f476c1f
                return -1;
cvsdist f476c1f
cvsdist f476c1f
	while (1)
cvsdist f476c1f
		if (!readchar(fd, &c, 1)) {
cvsdist f476c1f
			printf("%02x (%c) ", c, ((c > 32) && (c < 127)) ? c : 'x');
cvsdist f476c1f
			o = 1;
cvsdist f476c1f
		} else {
cvsdist f476c1f
			if (o) {
cvsdist f476c1f
				printf("\n");
cvsdist f476c1f
				o = 0;
cvsdist f476c1f
			}
cvsdist f476c1f
		}
cvsdist f476c1f
}
cvsdist f476c1f
cvsdist f476c1f
struct input_types {
cvsdist f476c1f
	char name[16];
cvsdist f476c1f
	char name2[16];
cvsdist f476c1f
	int speed;
cvsdist f476c1f
	int flags;
cvsdist f476c1f
	unsigned long type;
Tomas Janousek d956636
	unsigned long id;
cvsdist f476c1f
	unsigned long extra;
cvsdist f476c1f
	int flush;
cvsdist f476c1f
	int (*init)(int fd, long *id, long *extra);
cvsdist f476c1f
};
cvsdist f476c1f
cvsdist f476c1f
struct input_types input_types[] = {
cvsdist f476c1f
Tomas Janousek d956636
{ "--sunkbd",		"-skb",		B1200, CS8,			SERIO_SUNKBD,	0,	0,	1,	NULL },
Tomas Janousek d956636
{ "--lkkbd",		"-lk",		B4800, CS8|CSTOPB,		SERIO_LKKBD,	0,	0,	1,	NULL },
Tomas Janousek d956636
{ "--vsxxx-aa",		"-vs",		B4800, CS8|CSTOPB|PARENB|PARODD,SERIO_VSXXXAA,	0,	0,	1,	NULL },
Tomas Janousek d956636
{ "--spaceorb",		"-orb",		B9600, CS8,			SERIO_SPACEORB,	0,	0,	1,	NULL },
Tomas Janousek d956636
{ "--spaceball",	"-sbl",		B9600, CS8,			SERIO_SPACEBALL,0,	0,	0,	spaceball_init },
Tomas Janousek d956636
{ "--magellan",		"-mag",		B9600, CS8 | CSTOPB | CRTSCTS,	SERIO_MAGELLAN,	0,	0,	1,	magellan_init },
Tomas Janousek d956636
{ "--warrior",		"-war",		B1200, CS7 | CSTOPB,		SERIO_WARRIOR,	0,	0,	1,	warrior_init },
Tomas Janousek d956636
{ "--stinger",		"-sting",	B1200, CS8,			SERIO_STINGER,	0,	0,	1,	stinger_init },
Tomas Janousek d956636
{ "--mousesystems",	"-msc",		B1200, CS8,			SERIO_MSC,	0,	0x01,	1,	NULL },
Tomas Janousek d956636
{ "--sunmouse",		"-sun",		B1200, CS8,			SERIO_SUN,	0,	0x01,	1,	NULL },
Tomas Janousek d956636
{ "--microsoft",	"-bare",	B1200, CS7,			SERIO_MS,	0,	0,	1,	NULL },
Tomas Janousek d956636
{ "--mshack",		"-ms",		B1200, CS7,			SERIO_MS,	0,	0x01,	1,	NULL },
Tomas Janousek d956636
{ "--mouseman",		"-mman",	B1200, CS7,			SERIO_MP,	0,	0x01,	1,	NULL },
Tomas Janousek d956636
{ "--intellimouse",	"-ms3",		B1200, CS7,			SERIO_MZ,	0,	0x11,	1,	NULL },
Tomas Janousek d956636
{ "--mmwheel",		"-mmw",		B1200, CS7 | CSTOPB,		SERIO_MZP,	0,	0x13,	1,	mzp_init },
Tomas Janousek d956636
{ "--iforce",		"-ifor",	B38400, CS8,			SERIO_IFORCE,	0,	0,	0,	NULL },
Tomas Janousek d956636
{ "--newtonkbd",        "-newt",        B9600, CS8,                     SERIO_NEWTON,	0,	0,	0,      newton_init },
Tomas Janousek d956636
{ "--h3600ts",          "-ipaq",     	B115200, CS8,                   SERIO_H3600,	0,	0,	0,      NULL },
Tomas Janousek d956636
{ "--stowawaykbd",      "-ipaqkbd",     B115200, CS8,                   SERIO_STOWAWAY, 0,	0,	0,      NULL },
Tomas Janousek d956636
{ "--ps2serkbd",	"-ps2ser",	B1200, CS8,			SERIO_PS2SER,	0,	0,	1,	NULL },
Tomas Janousek d956636
{ "--twiddler",		"-twid",	B2400, CS8,			SERIO_TWIDKBD,	0,	0,	0,	twiddler_init },
Tomas Janousek d956636
{ "--twiddler-joy",	"-twidjoy",	B2400, CS8,			SERIO_TWIDJOY,	0,	0,	0,	twiddler_init },
Tomas Janousek d956636
{ "--elotouch",		"-elo",		B9600, CS8 | CRTSCTS,		SERIO_ELO,	0,	0,	0,	NULL },
Tomas Janousek d956636
{ "--elo4002",		"-elo6b",	B9600, CS8 | CRTSCTS,		SERIO_ELO,	1,	0,	0,	NULL },
Tomas Janousek d956636
{ "--elo271-140",	"-elo4b",	B9600, CS8 | CRTSCTS,		SERIO_ELO,	2,	0,	0,	NULL },
Tomas Janousek d956636
{ "--elo261-280",	"-elo3b",	B9600, CS8 | CRTSCTS,		SERIO_ELO,	3,	0,	0,	NULL },
Tomas Janousek d956636
{ "--dump",		"-dump",	B2400, CS8, 			0,		0,	0,	0,	dump_init },
cvsdist f476c1f
{ "", "", 0, 0 }
cvsdist f476c1f
cvsdist f476c1f
};
cvsdist f476c1f
cvsdist f476c1f
int main(int argc, char **argv)
cvsdist f476c1f
{
cvsdist f476c1f
	unsigned long devt;
cvsdist f476c1f
	int ldisc;
cvsdist f476c1f
        int type;
cvsdist f476c1f
	long id, extra;
cvsdist f476c1f
        int fd;
cvsdist f476c1f
	char c;
cvsdist f476c1f
cvsdist f476c1f
        if (argc < 2 || argc > 4 || (argc == 4 && strcmp(argv[3], "--daemon")) || !strcmp("--help", argv[1])) {
cvsdist f476c1f
                puts("");
cvsdist f476c1f
                puts("Usage: inputttach <mode> <device>");
cvsdist f476c1f
                puts("");
cvsdist f476c1f
                puts("Modes:");
cvsdist f476c1f
                puts("  --sunkbd        -skb   Sun Type 4 and Type 5 keyboards");
Tomas Janousek d956636
		puts("  --lkkbd         -lk    DEC LK201 / LK401 keyboards");
Tomas Janousek d956636
		puts("  --vsxxx-aa      -vs    DEC VSXXX-AA / VSXXX-GA mouse and VSXXX-AB tablet");
cvsdist f476c1f
                puts("  --spaceorb      -orb   SpaceOrb 360 / SpaceBall Avenger");
cvsdist f476c1f
		puts("  --spaceball     -sbl   SpaceBall 2003 / 3003 / 4000 FLX");
cvsdist f476c1f
                puts("  --magellan      -mag   Magellan / SpaceMouse");
cvsdist f476c1f
                puts("  --warrior       -war   WingMan Warrior");
cvsdist f476c1f
		puts("  --stinger       -stng  Gravis Stinger");
cvsdist f476c1f
		puts("  --mousesystems  -msc   3-button Mouse Systems mice");
cvsdist f476c1f
		puts("  --sunmouse      -sun   3-button Sun mice");
cvsdist f476c1f
		puts("  --microsoft     -bare  2-button Microsoft mice");
cvsdist f476c1f
		puts("  --mshack        -ms    3-button mice in Microsoft mode");
cvsdist f476c1f
		puts("  --mouseman      -mman  3-button Logitech and Genius mice");
cvsdist f476c1f
		puts("  --intellimouse  -ms3   Microsoft IntelliMouse");
cvsdist f476c1f
		puts("  --mmwheel       -mmw   Logitech mice with 4-5 buttons or wheel");
cvsdist f476c1f
		puts("  --iforce        -ifor  I-Force joysticks and wheels");
cvsdist f476c1f
                puts("  --h3600ts       -ipaq  Ipaq h3600 touchscreen");
cvsdist f476c1f
		puts("  --stowawaykbd   -ipaqkbd  Stowaway keyboard");
cvsdist f476c1f
		puts("  --ps2serkbd     -ps2ser PS/2 via serial keyboard");
cvsdist f476c1f
		puts("  --twiddler      -twid   Handykey Twiddler chording keyboard");
cvsdist f476c1f
		puts("  --twiddler-joy  -twidjoy  Handykey Twiddler used as a joystick");
cvsdist f476c1f
		puts("");
cvsdist f476c1f
                return 1;
cvsdist f476c1f
        }
cvsdist f476c1f
cvsdist f476c1f
        for (type = 0; input_types[type].speed; type++) {
cvsdist f476c1f
                if (!strncasecmp(argv[1], input_types[type].name, 16) ||
cvsdist f476c1f
			!strncasecmp(argv[1], input_types[type].name2, 16))
cvsdist f476c1f
                        break;
cvsdist f476c1f
        }
cvsdist f476c1f
cvsdist f476c1f
	if (!input_types[type].speed) {
cvsdist f476c1f
		fprintf(stderr, "inputattach: invalid mode\n");
cvsdist f476c1f
		return 1;
cvsdist f476c1f
	}
cvsdist f476c1f
cvsdist f476c1f
	if ((fd = open(argv[2], O_RDWR | O_NOCTTY | O_NONBLOCK)) < 0) {
cvsdist f476c1f
		perror("inputattach");
cvsdist f476c1f
		return 1;
cvsdist f476c1f
	}
cvsdist f476c1f
cvsdist f476c1f
	setline(fd, input_types[type].flags, input_types[type].speed);
cvsdist f476c1f
cvsdist f476c1f
	if (input_types[type].flush)
cvsdist f476c1f
		while (!readchar(fd, &c, 100));
cvsdist f476c1f
Tomas Janousek d956636
	id = input_types[type].id;
cvsdist f476c1f
	extra = input_types[type].extra;
cvsdist f476c1f
cvsdist f476c1f
	if (input_types[type].init && input_types[type].init(fd, &id, &extra)) {
cvsdist f476c1f
		fprintf(stderr, "inputattach: device initialization failed\n");
cvsdist f476c1f
		return 1;
cvsdist f476c1f
	}
cvsdist f476c1f
cvsdist f476c1f
	ldisc = N_MOUSE;
cvsdist f476c1f
	if(ioctl(fd, TIOCSETD, &ldisc)) {
cvsdist f476c1f
		fprintf(stderr, "inputattach: can't set line discipline\n"); 
cvsdist f476c1f
		return 1;
cvsdist f476c1f
	}
cvsdist f476c1f
Tomas Janousek d956636
	devt = input_types[type].type | (id << 8) | (extra << 16);
cvsdist f476c1f
cvsdist f476c1f
	if(ioctl(fd, SPIOCSTYPE, &devt)) {
cvsdist f476c1f
		fprintf(stderr, "inputattach: can't set device type\n");
cvsdist f476c1f
		return 1;
cvsdist f476c1f
	}
cvsdist f476c1f
	
cvsdist f476c1f
	if (argc == 4 && !strcmp(argv[3],"--daemon"))
cvsdist f476c1f
		daemon(0,0);
cvsdist f476c1f
cvsdist f476c1f
	read(fd, NULL, 0);
cvsdist f476c1f
cvsdist f476c1f
	ldisc = 0;
cvsdist f476c1f
	ioctl(fd, TIOCSETD, &ldisc);
cvsdist f476c1f
	close(fd);
cvsdist f476c1f
cvsdist f476c1f
	return 0;
cvsdist f476c1f
}