Date: Thu, 16 Dec 2004 09:52:08 +0100 From: "Norbert Koch" <NKoch@demig.de> To: <freebsd-hackers@freebsd.org> Subject: using two keyboards at the same time Message-ID: <001401c4e34c$86868900$4801a8c0@ws-ew-3.W2KDEMIG>
next in thread | raw e-mail | index | archive | help
Hello. I know, the syscons driver does not allow to have two keyboards attached at the same time. So my idea was to have a userland application which polls the keyboard(s) currently _not_ attached to syscons using select(2) or poll(2) and then switching to an active keyboard. >From reading the source code under /sys/dev/kbd I thought this should work. I made this simple test: I attached syscons to /dev/kbd1 and ran "cat /dev/kbd0". As expected I saw characters coming from both keyboards. Then I wrote a program to do the selecting and switching. Well, it does not work (under FreeBSD 4.10). Select never returns. As I understand it a device driver should return immediately if it does not support poll. Does anyone have an idea? May be I just made some stupid mistake. Thank you. >-------------------------------------------- #include <fcntl.h> #include <sys/types.h> #include <sys/stat.h> #include <sys/time.h> #include <machine/console.h> #include <unistd.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <errno.h> #define MAX_DEVICES 5 #define TEST #define STR(x) #x #define XSTR(x) STR (x) static void usage (void) { fprintf (stderr, "usage: autosw [ -D ] [ -d ] [ [ -f <device>] ... ]\n" " -D : do not detach\n" " -d : enable debug output\n" " -f : specify keyboard device (up to " XSTR (MAX_DEVICES) ")\n" " if no keyboard devices specified\n" " /dev/kbd0 and /dev/kbd1 are polled\n"); exit (1); } /* * borrowed from /usr/src/usr.sbin/kbdcontrol/kbdcontrol.c */ static int set_keyboard_fd (int fd) { keyboard_info_t info; if (ioctl (fd, KDGKBINFO, & info) == -1) { close (fd); return -1; }; ioctl (fd, CONS_RELKBD, 0); close (fd); if (ioctl (0, CONS_SETKBD, info.kb_index) == -1) { return -1; }; return 0; } static int set_keyboard (char * device) { int fd; fd = open (device, O_RDONLY); if (fd < 0) { return -1; }; return set_keyboard_fd (fd); } int main (int argc, char ** argv) { char * devices[MAX_DEVICES]; fd_set ifds, ofds; int ch, i, fd, maxfd, no_devices = 0, debug = 0, detach = 1, detached = 0; struct stat sb; while ((ch = getopt (argc, argv, "Ddf:h")) != -1) { switch (ch) { case 'D': detach = 0; break; case 'd': ++ debug; break; case 'f': if (no_devices >= MAX_DEVICES) { fprintf (stderr, "too many devices\n"); exit (1); }; if (stat (optarg, & sb) < 0) { fprintf (stderr, "cannot stat %s: %s\n", optarg, strerror (errno)); exit (1); }; if ((sb.st_mode & S_IFCHR) == 0) { fprintf (stderr, "not a character device: %s\n", optarg); exit (1); }; devices[no_devices ++] = strdup (optarg); continue; case 'h': case '?': default: usage (); } }; /* * no devices specified, use default */ if (no_devices == 0) { devices[0] = "/dev/kbd0"; devices[1] = "/dev/kbd1"; no_devices = 2; if (debug) { fprintf (stderr, "using default devices\n"); }; }; /* * switch syscons to first keyboard */ #ifndef TEST for (i = -1; ++ i < no_devices;) #else for (i = 1; i == 1; ++ i) #endif { if (set_keyboard (devices[i]) == 0) { if (debug) { fprintf (stderr, "selecting keyboard %s\n", devices[i]); }; break; } }; for (;;) { /* * try to open all devices for select */ FD_ZERO (& ifds); maxfd = -1; #ifndef TEST for (i = -1; ++ i < no_devices;) #else for (i = 0; i == 0; ++ i) #endif { fd = open (devices[i], O_RDONLY|O_NONBLOCK); if (fd >= 0) { if (debug) { fprintf (stderr, "polling %s", devices[i]); }; if (debug >= 2) { fprintf (stderr, " fd=%u", fd); }; if (debug) { fprintf (stderr, "\n"); }; FD_SET (fd, & ifds); if (fd > maxfd) { maxfd = fd; } } }; if (maxfd < 0) { fprintf (stderr, "could not open any device\n"); exit (1); }; if (detach && ! detached && ! debug) { daemon (0, 0); detached = 1; }; ofds = ifds; if (debug >= 2) { fprintf (stderr, "polling maxfd=%u\n", maxfd); }; /* ***** !!! never returns !!! */ if (select (maxfd, & ofds, NULL, NULL, NULL) == -1) { /* * got signal */ exit (0); }; if (debug) { fprintf (stderr, "polled successfully\n"); }; /* * find first keyboard where select returned some activity */ for (fd = -1; ++ fd < maxfd; ++ fd) { if (FD_ISSET (fd, & ofds)) { if (debug) { fprintf (stderr, "switching keyboard\n"); }; if (debug >= 2) { fprintf (stderr, " fd=%u", fd); }; if (debug) { fprintf (stderr, "\n"); }; /* * switch to keyboard with activity */ set_keyboard_fd (fd); FD_ZERO (& ofds); } else if (FD_ISSET (fd, & ifds)) { if (debug >= 2) { fprintf (stderr, "closing fd=%u\n", fd); }; close (fd); } } } }
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?001401c4e34c$86868900$4801a8c0>