From owner-freebsd-hackers@FreeBSD.ORG Thu Dec 16 08:53:24 2004 Return-Path: Delivered-To: freebsd-hackers@freebsd.org Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125]) by hub.freebsd.org (Postfix) with ESMTP id CA24516A4CE for ; Thu, 16 Dec 2004 08:53:24 +0000 (GMT) Received: from server.absolute-media.de (server.absolute-media.de [213.239.231.9]) by mx1.FreeBSD.org (Postfix) with ESMTP id E5C8B43D41 for ; Thu, 16 Dec 2004 08:53:23 +0000 (GMT) (envelope-from NKoch@demig.de) Received: from localhost (unknown [127.0.0.1]) by server.absolute-media.de (Postfix) with ESMTP id C07FB27A8E for ; Thu, 16 Dec 2004 09:49:21 +0100 (CET) Received: from server.absolute-media.de ([127.0.0.1]) by localhost (server [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id 17022-10 for ; Thu, 16 Dec 2004 09:49:21 +0100 (CET) Received: from mailhost.demig (p50929A81.dip0.t-ipconnect.de [80.146.154.129]) by server.absolute-media.de (Postfix) with ESMTP id B5A0C29BC5 for ; Thu, 16 Dec 2004 09:49:20 +0100 (CET) Received: from ws-ew-3 (ws-ew-3 [192.168.1.72]) by mailhost.demig (8.13.1/8.12.11) with SMTP id iBG8q8gt088527 for ; Thu, 16 Dec 2004 09:52:09 +0100 (CET) (envelope-from NKoch@demig.de) From: "Norbert Koch" To: Date: Thu, 16 Dec 2004 09:52:08 +0100 Message-ID: <001401c4e34c$86868900$4801a8c0@ws-ew-3.W2KDEMIG> MIME-Version: 1.0 Content-Type: text/plain; charset="iso-8859-1" Content-Transfer-Encoding: 7bit X-Priority: 3 (Normal) X-MSMail-Priority: Normal X-Mailer: Microsoft Outlook 8.5, Build 4.71.2173.0 X-MimeOLE: Produced By Microsoft MimeOLE V4.72.2120.0 Importance: Normal X-Virus-Scanned: by amavisd-new at absolute-media.de Subject: using two keyboards at the same time X-BeenThere: freebsd-hackers@freebsd.org X-Mailman-Version: 2.1.1 Precedence: list List-Id: Technical Discussions relating to FreeBSD List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 16 Dec 2004 08:53:24 -0000 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 #include #include #include #include #include #include #include #include #include #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 ] ... ]\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); } } } }