You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
382 lines
9.9 KiB
382 lines
9.9 KiB
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);
|