blob: 23f15fd8f9c5491d6821197d3844d72520e01746 [file] [log] [blame]
diff -ru a/core/src/common.h b/core/src/common.h
--- a/core/src/common.h 2013-01-11 06:35:35.000000000 +0200
+++ b/core/src/common.h 2013-01-11 06:34:08.000000000 +0200
@@ -34,6 +34,10 @@
#define PATH_PROC FBSPLASH_DIR"/proc"
#endif
+/* Maximum number of keyboard connected to a machine.
+ * The number is big (8) to be on the safe side */
+#define MAX_KBDS 8
+
/* Useful short-named types */
typedef u_int8_t u8;
typedef u_int16_t u16;
diff -ru a/core/src/daemon.c b/core/src/daemon.c
--- a/core/src/daemon.c 2013-01-11 06:35:35.000000000 +0200
+++ b/core/src/daemon.c 2013-01-11 06:34:08.000000000 +0200
@@ -20,6 +20,7 @@
#include <sys/ioctl.h>
#include <sys/wait.h>
#include <sys/mman.h>
+#include <sys/select.h>
#include <pthread.h>
#include <errno.h>
#include <dirent.h>
@@ -29,6 +30,8 @@
#include "common.h"
#include "daemon.h"
+#define EV_BUF_SIZE 8
+
/* Threading structures */
pthread_mutex_t mtx_tty = PTHREAD_MUTEX_INITIALIZER;
pthread_mutex_t mtx_paint = PTHREAD_MUTEX_INITIALIZER;
@@ -41,7 +44,8 @@
int ctty = CTTY_VERBOSE;
/* File descriptors */
-int fd_evdev = -1;
+int fd_evdevs[MAX_KBDS];
+int evdev_count = 0;
#ifdef CONFIG_GPM
int fd_gpm = -1;
#endif
@@ -51,7 +55,6 @@
/* Misc settings */
char *notify[2];
-char *evdev = NULL;
/* Service list */
list svcs = { NULL, NULL };
@@ -400,56 +403,83 @@
}
}
+__u16 get_ev_key_pressed(int fd_evdev, int ev_buf_size,
+ struct input_event *ev_buf) {
+ size_t rb;
+ int i;
+ rb = read(fd_evdev, ev_buf, sizeof(struct input_event) * ev_buf_size);
+ if (rb < (int) sizeof(struct input_event))
+ return 0;
+
+ for (i = 0; i < (int) (rb / sizeof(struct input_event)); i++) {
+ if (ev_buf[i].type != EV_KEY || ev_buf[i].value != 0)
+ continue;
+ return ev_buf[i].code;
+ }
+}
+
/*
* Event device monitor thread.
*/
void* thf_switch_evdev(void *unused)
{
- int i, h, oldstate;
- size_t rb;
- struct input_event ev[8];
+ int i, h, oldstate, nfds, retval, fd_evdev;
+ fd_set rfds;
+ struct input_event ev_buf[EV_BUF_SIZE];
+ __u16 key_pressed = 0;
while (1) {
- rb = read(fd_evdev, ev, sizeof(struct input_event)*8);
- if (rb < (int) sizeof(struct input_event))
- continue;
+ nfds = 0, fd_evdev = -1;
+ FD_ZERO(&rfds);
+ for (i = 0;i < evdev_count;i++) {
+ FD_SET(fd_evdevs[i], &rfds);
+ nfds = max(nfds, fd_evdevs[i]);
+ }
- for (i = 0; i < (int) (rb / sizeof(struct input_event)); i++) {
- if (ev[i].type != EV_KEY || ev[i].value != 0)
- continue;
+ nfds++;
- switch (ev[i].code) {
- case KEY_F2:
- pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &oldstate);
- pthread_mutex_lock(&mtx_paint);
- if (ctty == CTTY_SILENT) {
- h = config.tty_v;
- } else {
- h = config.tty_s;
+ retval = select(nfds, &rfds, NULL, NULL, NULL);
+ if (retval == -1)
+ perror("select()");
+ else if (retval) {
+ for (i = 0;i < evdev_count;i++) {
+ if (FD_ISSET(fd_evdevs[i], &rfds)) {
+ fd_evdev = fd_evdevs[i];
+ break;
}
- pthread_mutex_unlock(&mtx_paint);
- pthread_setcancelstate(oldstate, NULL);
+ }
+ key_pressed = get_ev_key_pressed(fd_evdev, EV_BUF_SIZE, ev_buf);
+ if (key_pressed == -1)
+ continue;
+ switch (key_pressed) {
+ case KEY_F2:
+ pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &oldstate);
+ pthread_mutex_lock(&mtx_paint);
+ h = (ctty == CTTY_SILENT) ? config.tty_v : config.tty_s;
+ pthread_mutex_unlock(&mtx_paint);
+ pthread_setcancelstate(oldstate, NULL);
+
+ /* Switch to the new tty. This ioctl has to be done on
+ * the silent tty. Sometimes init will mess with the
+ * settings of the verbose console which will prevent
+ * console switching from working properly.
+ *
+ * Don't worry about fd_tty[config.tty_s]
+ * not being protected by a mutex --
+ * this thread is always killed before any changes
+ * are made to fd_tty[config.tty_s].
+ */
+ ioctl(fd_tty[config.tty_s], VT_ACTIVATE, h);
+ break;
- /* Switch to the new tty. This ioctl has to be done on
- * the silent tty. Sometimes init will mess with the
- * settings of the verbose console which will prevent
- * console switching from working properly.
- *
- * Don't worry about fd_tty[config.tty_s] not being protected by a
- * mutex -- this thread is always killed before any changes
- * are made to fd_tty[config.tty_s].
- */
- ioctl(fd_tty[config.tty_s], VT_ACTIVATE, h);
- break;
-
- case KEY_F3:
- config.textbox_visible = !config.textbox_visible;
- invalidate_textbox(theme, config.textbox_visible);
- cmd_paint(NULL);
- break;
+ case KEY_F3:
+ config.textbox_visible = !config.textbox_visible;
+ invalidate_textbox(theme, config.textbox_visible);
+ cmd_paint(NULL);
+ break;
}
- }
- }
+ } /* end of else if (retval) */
+ } /* end of while(1) */
pthread_exit(NULL);
}
@@ -519,7 +549,7 @@
/* Do we have to start a monitor thread? */
if (update & UPD_MON) {
- if (fd_evdev != -1) {
+ if (evdev_count >= 0) {
if (pthread_create(&th_switchmon, NULL, &thf_switch_evdev, NULL)) {
iprint(MSG_ERROR, "Evdev monitor thread creation failed.\n");
exit(3);
diff -ru a/core/src/daemon.h b/core/src/daemon.h
--- a/core/src/daemon.h 2013-01-11 06:35:35.000000000 +0200
+++ b/core/src/daemon.h 2013-01-11 06:34:08.000000000 +0200
@@ -40,13 +40,13 @@
extern int fd_tty_s, fd_tty1, fd_tty0;
/*
- * Event device on which the daemon listens for F2 keypresses.
- * The proper device has to be detected by an external program and
+ * Event devices on which the daemon listens for F2 keypresses.
+ * The proper devices have to be detected by an external program and
* then enabled by sending an appropriate command to the splash
* daemon.
*/
-extern int fd_evdev;
-extern char *evdev;
+extern int fd_evdevs[];
+extern int evdev_count;
#ifdef CONFIG_GPM
#include <gpm.h>
diff -ru a/core/src/daemon_cmd.c b/core/src/daemon_cmd.c
--- a/core/src/daemon_cmd.c 2013-01-11 06:35:35.000000000 +0200
+++ b/core/src/daemon_cmd.c 2013-01-11 06:34:08.000000000 +0200
@@ -239,18 +239,35 @@
*/
int cmd_set_event_dev(void **args)
{
- if (evdev)
- free(evdev);
-
- evdev = strdup(args[0]);
+ char *evdevs;
+ char *evdev;
+ int i, j, fd_evdev = -1;
pthread_cancel(th_switchmon);
+ for (i = 0;i < evdev_count;i++) {
+ close(fd_evdevs[i]);
+ }
+ evdevs = strdup(args[1]);
+ evdev_count = *(int*)args[0];
+ j = 0;
+ for (i = 0;i < evdev_count;i++, evdevs = NULL) {
+ evdev = strtok(evdevs, ",");
+ fd_evdev = open(evdev, O_RDONLY);
+ if (fd_evdev != -1) {
+ fd_evdevs[j] = fd_evdev;
+ j++;
+ } else {
+ perror("failed to open event device");
+ }
+ }
+ if (j == 0) { /* all input devices failed to open */
+ evdev_count = -1;
+ free(evdevs);
+ return -1;
+ }
- if (fd_evdev != -1)
- close(fd_evdev);
-
- fd_evdev = open(evdev, O_RDONLY);
-
+ evdev_count = j;
+ free(evdevs);
switchmon_start(UPD_MON, config.tty_s);
return 0;
@@ -524,8 +541,8 @@
{ .cmd = "set event dev",
.handler = cmd_set_event_dev,
- .args = 1,
- .specs = "s"
+ .args = 2,
+ .specs = "ds"
},
{ .cmd = "set message",
@@ -628,7 +645,7 @@
continue;
for (j = 0; j < known_cmds[i].args; j++) {
- for (; buf[k] == ' '; buf[k] = 0, k++);
+ for (; buf[k] == ' '; buf[k] = '\0', k++);
if (!buf[k]) {
args[j] = NULL;
continue;
diff -ru a/core/src/libfbsplash.c b/core/src/libfbsplash.c
--- a/core/src/libfbsplash.c 2013-01-11 06:35:35.000000000 +0200
+++ b/core/src/libfbsplash.c 2013-01-11 06:34:08.000000000 +0200
@@ -588,6 +588,8 @@
return -1;
}
+#define EVDV_BUF_LEN 128
+
/**
* Try to set the event device for the splash daemon.
*
@@ -595,10 +597,14 @@
*/
int fbsplash_set_evdev(void)
{
- char buf[128];
+ char buf[EVDV_BUF_LEN];
+ char evdev_devs[EVDV_BUF_LEN * MAX_KBDS];
FILE *fp;
int i, j;
-
+ int kbd_count;
+ int max_chars, chars_left, dev_path_len;
+ char dev_path[] = PATH_DEV "/input/";
+ dev_path_len = strlen(dev_path);
char *evdev_cmds[] = {
"/bin/grep -Hsi keyboard " PATH_SYS "/class/input/input*/name | /bin/sed -e 's#.*input\\([0-9]*\\)/name.*#event\\1#'",
"/bin/grep -Hsi keyboard " PATH_SYS "/class/input/event*/device/driver/description | /bin/grep -o 'event[0-9]\\+'",
@@ -608,22 +614,43 @@
/* Try to activate the event device interface so that F2 can
* be used to switch from verbose to silent. */
- buf[0] = 0;
- for (i = 0; i < sizeof(evdev_cmds)/sizeof(char*); i++) {
+ buf[0] = '\0';
+ kbd_count = 0;
+ max_chars = sizeof(evdev_devs) / sizeof(char*);
+ chars_left = max_chars - 1;
+ evdev_devs[0] = '\0';
+ for (i = 0; i < sizeof(evdev_cmds) / sizeof(char*); i++) {
fp = popen(evdev_cmds[i], "r");
if (fp) {
- fgets(buf, 128, fp);
- if ((j = strlen(buf)) > 0) {
- if (buf[j-1] == '\n')
- buf[j-1] = 0;
- break;
+ while (fgets(buf, 128, fp) && kbd_count < MAX_KBDS) {
+ if ((j = strlen(buf)) > 0) {
+ if (buf[j-1] == '\n')
+ buf[j-1] = ',';
+ if (chars_left < (j + dev_path_len)) {
+ break;
+ }
+ kbd_count++;
+ strncat(evdev_devs, dev_path, chars_left);
+ chars_left -= dev_path_len;
+ strncat(evdev_devs, buf, chars_left);
+ chars_left -= j;
+ }
+ }
+ /* replace the last ',' with '\n' */
+ if (chars_left > 0 && evdev_devs[0] != '\0') {
+ j = strlen(evdev_devs);
+ if (j > 2) {
+ evdev_devs[j - 1] = '\n';
+ }
}
pclose(fp);
}
+ if (kbd_count > 0)
+ break;
}
- if (buf[0] != 0) {
- fbsplash_send("set event dev " PATH_DEV "/input/%s\n", buf);
+ if (evdev_devs[0] != '\0') {
+ fbsplash_send("set event dev %d %s", kbd_count, evdev_devs);
return 0;
} else {
return -1;
@@ -661,6 +688,8 @@
return 0;
}
+#define MAX_CMD 2048
+
/**
* Send stuff to the splash daemon using the splash FIFO.
*
@@ -668,7 +697,7 @@
*/
int fbsplash_send(const char *fmt, ...)
{
- char cmd[256];
+ char cmd[MAX_CMD];
va_list ap;
if (!fp_fifo) {
@@ -690,7 +719,7 @@
}
va_start(ap, fmt);
- vsnprintf(cmd, 256, fmt, ap);
+ vsnprintf(cmd, MAX_CMD, fmt, ap);
va_end(ap);
fprintf(fp_fifo, cmd);