1118 lines
32 KiB
Diff
1118 lines
32 KiB
Diff
--- conf/gpm-silitek.conf
|
|
+++ conf/gpm-silitek.conf
|
|
@@ -0,0 +1,45 @@
|
|
+# Standard key mapping for Silitek SM-1000
|
|
+# on Linux virtual console (TERM=linux)
|
|
+key 1 1 1
|
|
+key 2 2 2
|
|
+key 3 3 3
|
|
+key 4 4 4
|
|
+key 5 5 5
|
|
+key 6 6 6
|
|
+key 7 7 7
|
|
+key 8 8 8
|
|
+key 9 9 9
|
|
+key 0 0 0
|
|
+key * * *
|
|
+key # # #
|
|
+# Ctrl+Q
|
|
+key > \021 \021
|
|
+# Ctrl+S
|
|
+key || \023 \023
|
|
+# Crtl+C
|
|
+key [] \003 \003
|
|
+# End
|
|
+key >>| \033[4~ \033[4~
|
|
+# Home
|
|
+key |<< \033[1~ \033[1~
|
|
+# Delete
|
|
+key Mute \033[3~ \033[3~
|
|
+# Cursor up
|
|
+key Vol+ \033[A \033[A
|
|
+# Cursor down
|
|
+key Vol- \033[B \033[B
|
|
+# Insert
|
|
+key Display \033[2~ \033[2~
|
|
+# Page up
|
|
+key PgUp \033[5~ \033[5~
|
|
+Page down
|
|
+key PgDn \033[6~ \033[6~
|
|
+# Cursor left
|
|
+key Back \033[D \033[D
|
|
+# Cursor right
|
|
+key Forward \033[C \033[C
|
|
+# F1 upto F4
|
|
+key CD \033[[A \033[[A
|
|
+key ShowWiz \033[[B \033[[B
|
|
+key WWW \033[[C \033[[C
|
|
+key Close \033[[D \033[[D
|
|
--- doc/README.silitek
|
|
+++ doc/README.silitek
|
|
@@ -0,0 +1,188 @@
|
|
+This README describes the support for the Silitek SM-1000 IR commander
|
|
+(also called Netshooter).
|
|
+
|
|
+This IR commander can be used with two types of mouse driver:
|
|
+
|
|
+ * Type `silicom' supports the IR receiver which is shipped the
|
|
+ SM-1000 and plugged into a serial connector.
|
|
+
|
|
+ * Type `silips2' supports the IR receiver which is shipped
|
|
+ with the Silitek IR keyboard SK-7100 (also called Airboard).
|
|
+ The mouse connector of this IR receiver should be plugged
|
|
+ into the PS/2 mouse connector (not to a serial connector).
|
|
+ You may need an adapter (9 pin serial to PS/2) to do this.
|
|
+
|
|
+Both types of mouse driver uses the system wide configuration file
|
|
+
|
|
+ /etc/gpm-silitek.conf
|
|
+
|
|
+which defines the return values of any key not being mouse button
|
|
+or mouse stick. For this keys the drag mouse button works as a
|
|
+modifier: pressed once, the last column in /etc/gpm-silitek.conf
|
|
+is used. To switch back to the normal return values, the drag mouse
|
|
+button has to be pressed again. It is allowed to use escaped
|
|
+sequences as return values. Characters other than printable can
|
|
+be coded by using the backslash, e.g. `\033' for the octal number
|
|
+of the special character ESC (Escape) of `\x0D' for the hexadecimal
|
|
+number of the special character CR (Carriage Return), for more
|
|
+codings see the manual page ascii(7).
|
|
+
|
|
+The default key mapping for the SM-1000 IR commander is on the
|
|
+virtual console is:
|
|
+
|
|
+ SM-1000 Key normal drag active
|
|
+ -------------------------------------
|
|
+ key 1 1 1
|
|
+ key 2 2 2
|
|
+ key 3 3 3
|
|
+ key 4 4 4
|
|
+ key 5 5 5
|
|
+ key 6 6 6
|
|
+ key 7 7 7
|
|
+ key 8 8 8
|
|
+ key 9 9 9
|
|
+ key 0 0 0
|
|
+ key * * *
|
|
+ key # # #
|
|
+ key > Ctrl Q Ctrl Q
|
|
+ key || Ctrl S Ctrl S
|
|
+ key [] Crtl C Crtl C
|
|
+ key >>| End End
|
|
+ key |<< Home Home
|
|
+ key Mute Delete Delete
|
|
+ key Vol+ Cursor Up Cursor Up
|
|
+ key Vol- Cursor Down Cursor Down
|
|
+ key Display Insert Insert
|
|
+ key PgUp Page Up Page Up
|
|
+ key PgDn Page Down Page Down
|
|
+ key Back Cursor Left Cursor Left
|
|
+ key Forward Cursor Right Cursor Right
|
|
+ key CD F1 F1
|
|
+ key ShowWiz F2 F2
|
|
+ key WWW F3 F3
|
|
+ key Close F4 F4
|
|
+
|
|
+Usage with the IR receiver of the Silitek Keyboard SK-7100:
|
|
+
|
|
+In comparison of the IR receiver of shipped with the SM-1000
|
|
+this IR receiver has the advantage that both mouse interface
|
|
+of the IR keyboard and the IR Netshooter can be used in parallel.
|
|
+One advantage more is that only one IR receiver is required to
|
|
+use both the IR keyboard and the IR Netshooter. Next point is
|
|
+that the IR receiver of the IR keyboard seems to more insensitive
|
|
+for other IR commanders like those from TV sets.
|
|
+
|
|
+The Multimedia keys of the IR keyboard SK-7100 can be configured
|
|
+by using setkeycodes(8) and loadkeys(8) to be usable in parallel
|
|
+to those of the IR commander SM-1000.
|
|
+
|
|
+Notice: The key 7 of the IR commander SM-1000 generates the keyboard
|
|
+scancode for KP_ENTER if the SK-7100 keyboard is used in parallel.
|
|
+This happens even if the mouse type `silicom' is used in conjunction
|
|
+with the IR receiver of the SM-1000. This because if both IR receiver
|
|
+are used, the SM-1000 and the SK-7100, both receives signals from the
|
|
+SM-1000. Therefore this key should be disabled (note that the SK-7100
|
|
+does not have a KP_ENTER):
|
|
+
|
|
+--------------------------------------------------------------------
|
|
+loadkeys <<-EOF
|
|
+keycode 96 = F39
|
|
+string F39 = ""
|
|
+EOF
|
|
+--------------------------------------------------------------------
|
|
+
|
|
+With `showkeys -s' on the virtual console and `xev' under X11 the
|
|
+the other Multimedia keys of the SK-7100 causes the following
|
|
+scancodes/keycodes:
|
|
+
|
|
+ SK-7100 Key console X11
|
|
+ --------------------------
|
|
+ Close e017 151
|
|
+ CD e025 165
|
|
+ Video e018 152
|
|
+ WWW e032 178
|
|
+ U/P e01e 158
|
|
+ |<< e010 144
|
|
+ || e012 146
|
|
+ > e022 162
|
|
+ [] e024 164
|
|
+ >>| e019 153
|
|
+ Vol- e02e 174
|
|
+ Vol+ e030 176
|
|
+ Mute e020 160
|
|
+ Display e026 166
|
|
+
|
|
+If we map for e.g. the keys
|
|
+
|
|
+ Video Switch to vc 8 where the Video Recoder Program runs (Console_8)
|
|
+ |<< Cursor Left (keycode 105)
|
|
+ >>| Cursor Right (keycode 106)
|
|
+ Display Win Menu key (keycode 127)
|
|
+
|
|
+(Compares this with `dumpkeys | less' on a virtual console).
|
|
+
|
|
+With the following command sequence (called in a script during boot):
|
|
+
|
|
+--------------------------------------------------------------------
|
|
+setkeycodes \
|
|
+ e017 85 \
|
|
+ e025 89 \
|
|
+ e018 90 \
|
|
+ e032 91 \
|
|
+ e01e 92 \
|
|
+ e010 105 \
|
|
+ e012 94 \
|
|
+ e022 95 \
|
|
+ e024 120 \
|
|
+ e019 106 \
|
|
+ e02e 122 \
|
|
+ e030 123 \
|
|
+ e020 124 \
|
|
+ e026 127
|
|
+loadkeys <<-EOF
|
|
+ keycode 85 = F50
|
|
+ keycode 89 = F51
|
|
+ keycode 90 = Console_8
|
|
+ keycode 91 = F53
|
|
+ keycode 92 = F54
|
|
+ keycode 94 = F56
|
|
+ keycode 95 = F57
|
|
+ keycode 120 = F58
|
|
+ keycode 122 = F60
|
|
+ keycode 123 = F61
|
|
+ keycode 124 = F62
|
|
+ keycode 127 = F63
|
|
+ keycode 96 = F39
|
|
+ string F50 = "\033[[Z"
|
|
+ string F51 = "\033[[Y"
|
|
+ string F53 = "\033[[W"
|
|
+ string F54 = "\033[[U"
|
|
+ string F56 = "\033[[H"
|
|
+ string F57 = "\033[[T"
|
|
+ string F58 = "\033[[F"
|
|
+ string F60 = "\033[[L"
|
|
+ string F61 = "\033[[M"
|
|
+ string F62 = "\033[[X"
|
|
+ string F63 = "\033[[R"
|
|
+ string F39 = ""
|
|
+EOF
|
|
+--------------------------------------------------------------------
|
|
+
|
|
+the Multimedia keys on IR Keyboard SK-7100 are usable (for ncurses
|
|
+based programs see below). After editing /etc/gpm-silitek.conf
|
|
+to get the similar named keys to work similar, both the IR Keyboard
|
|
+SK-7100 and the IR commander SM-1000 are usable in parallel.
|
|
+
|
|
+For ncurses based programs the added keys have to be extended
|
|
+by dumping the current terminfo entry for the virtual consoles
|
|
+for TERM=linux:
|
|
+
|
|
+ infocmp -1 linux > linux.tic
|
|
+
|
|
+and editing the file linux.tic which means adding the function
|
|
+keys kf50, kf51, kf52, kf53, kf54, kf56, kf57, kf58, kf60, kf61,
|
|
+kf62, kf63, and kf39. After that the command
|
|
+
|
|
+ tic linux.tic
|
|
+
|
|
+installs the edited terminfo entry for TERM=linux.
|
|
--- src/Makefile.in
|
|
+++ src/Makefile.in
|
|
@@ -13,7 +13,7 @@
|
|
|
|
# Main portion: regular build rules
|
|
|
|
-GSRC = main.c gpm.c gpn.c mice.c special.c twiddler.c synaptics.c \
|
|
+GSRC = main.c gpm.c gpn.c mice.c special.c twiddler.c synaptics.c silitek.c \
|
|
startup.c server_tools.c
|
|
|
|
GOBJ = $(GSRC:.c=.o) report.o tools.o
|
|
@@ -24,7 +24,7 @@
|
|
|
|
PICS = $(LOBJ:.o=.lo)
|
|
|
|
-HDRS = gpm.h gpmInt.h twiddler.h synaptics.h message.h
|
|
+HDRS = gpm.h gpmInt.h twiddler.h synaptics.h silitek.h message.h
|
|
|
|
PSRC = prog/mev.c prog/hltest.c prog/mouse-test.c prog/disable-paste.c
|
|
|
|
@@ -144,7 +144,7 @@
|
|
$(CC) -I. @CPPFLAGS@ $(CPPFLAGS) @CFLAGS@ $(CFLAGS) -c -o $@.o $<
|
|
$(CC) @LDFLAGS@ $(LDFLAGS) -o $@ $@.o @LIBS@ $(LIBS) lib/libgpm.a
|
|
|
|
-prog/mouse-test: mice.o twiddler.o synaptics.o
|
|
+prog/mouse-test: mice.o twiddler.o synaptics.o silitek.o
|
|
|
|
$(PROG): lib/libgpm.so lib/@SHLIB@ lib/libgpm.a
|
|
|
|
--- src/headers/message.h
|
|
+++ src/headers/message.h
|
|
@@ -194,6 +194,10 @@
|
|
#define GPM_MESS_INCORRECT_LINE "%s: %s :%i: Incorrect line:\"%s\""
|
|
#define GPM_MESS_FIRST_DEV "Use -m device -t protocol [-o options]!"
|
|
|
|
+#define GPM_MESS_SILIPS2_ENABLE "silips2: enable error"
|
|
+#define GPM_MESS_SILIPS2_DISABLE "silips2: disable error"
|
|
+#define GPM_MESS_SILIPS2_RESET "silips2: reset error"
|
|
+
|
|
|
|
/* warnings */
|
|
#define GPM_MESS_REQUEST_ON "Request on vc %i > %i"
|
|
--- src/headers/silitek.h
|
|
+++ src/headers/silitek.h
|
|
@@ -0,0 +1,33 @@
|
|
+/*
|
|
+ * silitek.h - support for the Silitek SM-1000 (Netshooter) with its IR
|
|
+ * receiver plugged serial connector and also with the IR
|
|
+ * receiver of the Silitek SK-7100 keyboard (Airboard)
|
|
+ * PS2 mouse connector.
|
|
+ *
|
|
+ * Copyright 2002 Werner Fink <werner@suse.de>
|
|
+ *
|
|
+ * This program is free software; you can redistribute it and/or modify
|
|
+ * it under the terms of the GNU General Public License as published by
|
|
+ * the Free Software Foundation; either version 2 of the License, or
|
|
+ * (at your option) any later version.
|
|
+ *
|
|
+ * This program is distributed in the hope that it will be useful,
|
|
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
+ * GNU General Public License for more details.
|
|
+ *
|
|
+ * You should have received a copy of the GNU General Public License
|
|
+ * along with this program; if not, write to the Free Software
|
|
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
|
|
+ *
|
|
+ */
|
|
+extern int silitek_get_check(unsigned char *data);
|
|
+extern int silitek_get_check_ps2(unsigned char *data);
|
|
+extern void silitek_keys(unsigned char *data, int *drag);
|
|
+extern void silitek_keys_ps2(unsigned char *data, int *drag);
|
|
+extern int silitek_ghost_ps2(unsigned char *data);
|
|
+extern int fd_silitek;
|
|
+#define SILI_SYSTEM_FILE SYSCONFDIR "/gpm-silitek.conf"
|
|
+#define SILISTRLEN 32
|
|
+#define SILISTRSCN "key %32s %32s %32s"
|
|
+extern void silitek_mapping(void);
|
|
--- src/mice.c
|
|
+++ src/mice.c
|
|
@@ -74,6 +74,7 @@
|
|
#include "headers/gpmInt.h"
|
|
#include "headers/twiddler.h"
|
|
#include "headers/synaptics.h"
|
|
+#include "headers/silitek.h"
|
|
#include "headers/message.h"
|
|
|
|
/*========================================================================*/
|
|
@@ -667,6 +668,86 @@
|
|
|
|
}
|
|
|
|
+#define GPM_B_BOTH (GPM_B_LEFT|GPM_B_RIGHT)
|
|
+static int M_silitek_ps2(Gpm_Event *state, unsigned char *data)
|
|
+{
|
|
+ static int drag = 0;
|
|
+
|
|
+ if (!silitek_get_check_ps2(data))
|
|
+ return -1;
|
|
+
|
|
+ /*
|
|
+ * Map some ghost mouse PS2 events caused by the other
|
|
+ * keys. Maybe there is a better initialization for the chip
|
|
+ * of the SK-7100 IR receiver which would avoid those events.
|
|
+ */
|
|
+ (void)silitek_ghost_ps2(data);
|
|
+
|
|
+ /* All none PS2 events */
|
|
+ if (data[0] & 0xc0)
|
|
+ {
|
|
+ silitek_keys_ps2(data, &drag);
|
|
+ return -1; /* Do not highlight, but success */
|
|
+ }
|
|
+
|
|
+ state->buttons = ((data[0]&0x01)<<2)|(data[0]&0x02)|((data[0]&0x04)>>2);
|
|
+
|
|
+ /* Drag is just a modifier for none mouse keys */
|
|
+ if (state->buttons&GPM_B_LEFT)
|
|
+ drag = ((!drag) ? 1 : 0);
|
|
+ else
|
|
+ drag = 0;
|
|
+
|
|
+ if(data[1]) state->dx = (data[0] & 0x10) ? data[1] - 0xFF : data[1];
|
|
+ if(data[2]) state->dy = -((data[0] & 0x20) ? data[2] - 0xFF : data[2]);
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static int M_silitek(Gpm_Event *state, unsigned char *data)
|
|
+{
|
|
+ static int drag = 0;
|
|
+
|
|
+ if (!silitek_get_check(data))
|
|
+ return -1;
|
|
+
|
|
+ /* All none mouse events */
|
|
+ if (!(data[0] & 0x40))
|
|
+ {
|
|
+ silitek_keys(data, &drag);
|
|
+ return -1; /* Do not highlight, but success */
|
|
+ }
|
|
+
|
|
+ /*
|
|
+ * Sanity check: SM-1000 mouse events do not use this bit
|
|
+ * but Keyboard SK-7100 PgUp/PgDn/`x'
|
|
+ * (0xfe5da5/0xfd5da5/0x7c845d)
|
|
+ */
|
|
+ if ((data[1] & 0x40) || (data[2] & 0x40))
|
|
+ return -1;
|
|
+
|
|
+ switch(data[0])
|
|
+ {
|
|
+ case 0xfe: state->buttons = GPM_B_LEFT; break;
|
|
+ case 0xfd: state->buttons = GPM_B_RIGHT; break;
|
|
+ case 0x7f: state->buttons = GPM_B_BOTH; break;
|
|
+ case 0x7c: state->buttons = 0; break;
|
|
+ default: return -1; /* Do not highlight */
|
|
+ break;
|
|
+ }
|
|
+
|
|
+ /* Drag is just a modifier for none mouse keys */
|
|
+ if (state->buttons&GPM_B_LEFT)
|
|
+ drag = ((!drag) ? 1 : 0);
|
|
+ else
|
|
+ drag = 0;
|
|
+
|
|
+ state->dx = (data[1] & 0x20) ? ((data[1] & 0x1f) - 0x20) : (data[1] & 0x1f);
|
|
+ state->dy = (data[2] & 0x20) ? ((data[2] & 0x1f) - 0x20) : (data[2] & 0x1f);
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
static int M_netmouse(Gpm_Event *state, unsigned char *data)
|
|
{
|
|
/* Avoid these beasts if you can. They connect to normal PS/2 port,
|
|
@@ -745,7 +826,6 @@
|
|
return type;
|
|
}
|
|
|
|
-#define GPM_B_BOTH (GPM_B_LEFT|GPM_B_RIGHT)
|
|
static int M_mman(Gpm_Event *state, unsigned char *data)
|
|
{
|
|
/*
|
|
@@ -1828,7 +1908,7 @@
|
|
*
|
|
* Returns 0 if OK, or >0 if 1 or more errors occurred.
|
|
*/
|
|
-static int write_to_mouse(int fd, unsigned char *data, size_t len)
|
|
+static int write_to_mouse(int fd, const unsigned char *data, size_t len)
|
|
{
|
|
int i;
|
|
int error = 0;
|
|
@@ -1845,6 +1925,89 @@
|
|
return(error);
|
|
}
|
|
|
|
+static Gpm_Type *I_silitek(int fd, unsigned short flags, struct Gpm_Type *type, int argc, char **argv)
|
|
+{
|
|
+ struct termios tty;
|
|
+ int speed = B1200;
|
|
+ fd_silitek = fd;
|
|
+
|
|
+ tcgetattr(fd, &tty);
|
|
+ cfmakeraw(&tty);
|
|
+ cfsetspeed(&tty, speed);
|
|
+ tty.c_cc[VMIN] = 1;
|
|
+ tty.c_cc[VTIME] = 0;
|
|
+ tty.c_cflag |= CS8;
|
|
+#if 0
|
|
+ tty.c_cflag &= ~(CRTSCTS|CSTOPB|PARODD);
|
|
+ tty.c_cflag |= flags;
|
|
+#endif
|
|
+ tcsetattr(fd, TCSAFLUSH, &tty);
|
|
+ silitek_mapping();
|
|
+
|
|
+ return type;
|
|
+}
|
|
+
|
|
+static Gpm_Type *I_silitek_ps2(int fd, unsigned short flags, struct Gpm_Type *type, int argc, char **argv)
|
|
+{
|
|
+ const unsigned char off[] = {GPM_AUX_DISABLE_DEV, };
|
|
+ const unsigned char buf[] = {GPM_AUX_SET_RES, 3,
|
|
+ GPM_AUX_SET_SCALE11,
|
|
+ GPM_AUX_SET_SAMPLE, 200,
|
|
+ GPM_AUX_ENABLE_DEV, };
|
|
+ int n, c, err, id;
|
|
+
|
|
+ fd_silitek = fd;
|
|
+
|
|
+ (void)write_to_mouse(fd, off, sizeof(off));
|
|
+
|
|
+ err=1;
|
|
+ for (n = 0; n < 3 && err; n++)
|
|
+ {
|
|
+ err=0;
|
|
+ c = GPM_AUX_RESET;
|
|
+ write(fd, &c, 1);
|
|
+ read(fd, &c, 1);
|
|
+ if (c != GPM_AUX_ACK) err++;
|
|
+ read(fd, &c, 1);
|
|
+ if (c != 0xAA) err++;
|
|
+ read(fd, &c, 1);
|
|
+ if (c != 0x00) err++;
|
|
+ if (err) usleep(50000);
|
|
+ }
|
|
+
|
|
+ (void)write_to_mouse(fd, buf, sizeof(buf));
|
|
+ usleep(50000);
|
|
+
|
|
+ if ((id = read_mouse_id(fd)) == GPM_AUX_ID_ERROR)
|
|
+ {
|
|
+ if (write_to_mouse(fd, off, sizeof(off)))
|
|
+ gpm_report(GPM_PR_ERR,GPM_MESS_SILIPS2_DISABLE);
|
|
+
|
|
+ err=1;
|
|
+ for (n = 0; n < 3 && err; n++)
|
|
+ {
|
|
+ err=0;
|
|
+ c = GPM_AUX_RESET;
|
|
+ write(fd, &c, 1);
|
|
+ read(fd, &c, 1);
|
|
+ if (c != GPM_AUX_ACK) err++;
|
|
+ read(fd, &c, 1);
|
|
+ if (c != 0xAA) err++;
|
|
+ read(fd, &c, 1);
|
|
+ if (c != 0x00) err++;
|
|
+ if (err)
|
|
+ usleep(50000);
|
|
+ }
|
|
+ if (err > 0)
|
|
+ gpm_report(GPM_PR_ERR,GPM_MESS_SILIPS2_RESET);
|
|
+ if (write_to_mouse(fd, buf, sizeof(buf)))
|
|
+ gpm_report(GPM_PR_ERR,GPM_MESS_SILIPS2_ENABLE);
|
|
+ id = 0x00;
|
|
+ }
|
|
+ silitek_mapping();
|
|
+
|
|
+ return type;
|
|
+}
|
|
|
|
/* intellimouse, ps2 version: Ben Pfaff and Colin Plumb */
|
|
/* Autodetect: Steve Bennett */
|
|
@@ -2297,6 +2460,12 @@
|
|
{"ps2", "Busmice of the ps/2 series. Most busmice, actually.",
|
|
"PS/2", M_ps2, I_ps2, STD_FLG,
|
|
{0xc0, 0x00, 0x00, 0x00}, 3, 1, 0, 0, R_ps2, 1},
|
|
+ {"silips2","Silitek SM-1000 Netshooter plugged into ps/2 mouse connector.",
|
|
+ "SiliPS/2", M_silitek_ps2, I_silitek_ps2, STD_FLG,
|
|
+ {0x00, 0x00, 0x00, 0x00}, 1, 1, 0, 0, 0, 1},
|
|
+ {"silicom","Silitek SM-1000 Netshooter plugged into serial connector.",
|
|
+ "SiliCom", M_silitek, I_silitek, STD_FLG,
|
|
+ {0x20, 0x20, 0x00, 0x00}, 1, 1, 0, 0, 0, 0},
|
|
{"sun", "'msc' protocol, but only 3 bytes per packet.",
|
|
"", M_sun, I_serial, CS8 | CSTOPB | STD_FLG,
|
|
{0xf8, 0x80, 0x00, 0x00}, 3, 1, 0, 0, 0, 0},
|
|
--- src/silitek.c
|
|
+++ src/silitek.c
|
|
@@ -0,0 +1,580 @@
|
|
+/*
|
|
+ * silitek.c - support for the Silitek SM-1000 (Netshooter) with its IR
|
|
+ * receiver plugged serial connector and also with the IR
|
|
+ * receiver of the Silitek SK-7100 keyboard (Airboard)
|
|
+ * PS2 mouse connector.
|
|
+ *
|
|
+ * Copyright 2002 Werner Fink <werner@suse.de>
|
|
+ *
|
|
+ * This program is free software; you can redistribute it and/or modify
|
|
+ * it under the terms of the GNU General Public License as published by
|
|
+ * the Free Software Foundation; either version 2 of the License, or
|
|
+ * (at your option) any later version.
|
|
+ *
|
|
+ * This program is distributed in the hope that it will be useful,
|
|
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
+ * GNU General Public License for more details.
|
|
+ *
|
|
+ * You should have received a copy of the GNU General Public License
|
|
+ * along with this program; if not, write to the Free Software
|
|
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
|
|
+ *
|
|
+ */
|
|
+
|
|
+/*
|
|
+ * Serial settings used herein: raw but I/O with baud rate 1200 and 8bit (YES!)
|
|
+ * For testing, e.g.: stty -a < /dev/ttyS1
|
|
+ * To set this, e.g.: stty raw 1200 cs8 < /dev/ttyS1
|
|
+ * For reading keycodes use, e.g.:
|
|
+ * od [-j (1|2)] -v -t x1 --width=3 < /dev/ttyS1
|
|
+ * compare with I_silitek() in mice.c.
|
|
+ * Which provides following keycodes received by the IR receiver
|
|
+ * included in the SM-1000 shipment for the SM-1000 its self:
|
|
+ *
|
|
+ * First byte: 0xbf (Key down, 8 bit striped this is 0x3f)
|
|
+ * 0x31 (Key hold down)
|
|
+ * 0x2a (Key up)
|
|
+ * 0x7c (Mouse event: move, any button up)
|
|
+ * 0x7f (Mouse event: move, l+r-mouse button down)
|
|
+ * 0xfd (Mouse event: move, r-mouse button down)
|
|
+ * 0xfe (Mouse event: move, l-mouse button down)
|
|
+ * Which provides: Any if (byte0 & 0x20) == 0x20 (for GPM protocol check)
|
|
+ * Key if (byte0 & 0x40) == 0x00
|
|
+ * Mouse if (byte0 & 0x40) == 0x40
|
|
+ * Second and third byte (unsigned char, aka 8bits):
|
|
+ * 1: 0xc1 0xfe
|
|
+ * 2: 0xc2 0xfd
|
|
+ * 3: 0x43 0x7c
|
|
+ * 4: 0xc4 0xfb
|
|
+ * 5: 0x45 0x7a
|
|
+ * 6: 0x46 0x79
|
|
+ * 7: 0xc7 0xf8
|
|
+ * 8: 0xc8 0xf7
|
|
+ * 9: 0x49 0x76
|
|
+ * 0: 0x4a 0x75
|
|
+ * *: 0xcb 0xf4
|
|
+ * #: 0x4c 0x73
|
|
+ * >: 0xcd 0xf2
|
|
+ * ||: 0xce 0xf1
|
|
+ * []: 0x4f 0x70
|
|
+ * >>|: 0xd0 0xef
|
|
+ * |<<: 0x51 0x6e
|
|
+ * Mute: 0x52 0x6d
|
|
+ * Vol+: 0xd3 0xec
|
|
+ * Vol-: 0x54 0x6b
|
|
+ * Display: 0xd5 0xea
|
|
+ * PgUp: 0xd6 0xe9
|
|
+ * PgDn: 0x57 0x68
|
|
+ * Back: 0x58 0x67
|
|
+ * Forward: 0xd9 0xe6
|
|
+ * CD: 0xda 0xe5
|
|
+ * ShowWiz: 0x5b 0x64
|
|
+ * WWW: 0xdc 0xe3
|
|
+ * Close: 0x5d 0x62
|
|
+ * Which provides: byte1 & 0x20 == 0x00, byte1 & 0x40 == 0x40
|
|
+ * (byte1 & 0x7f) & (byte2 & 0x7f) == 0x40
|
|
+ * (byte1 & 0x7f) | (byte2 & 0x7f) == 0x7f
|
|
+ * (byte1 & 0x1f) == keycode
|
|
+ *
|
|
+ * No mouse move but mouse button:
|
|
+ * 0x80 0x80
|
|
+ * Mouse move but no button:
|
|
+ * right (byte1 & 0x20) == 0x20
|
|
+ * left (byte2 & 0x20) == 0x20
|
|
+ * value (byte1 & 0x1f), (byte2 & 0x1f)
|
|
+ * Mouse move and button:
|
|
+ * OR combinations from above.
|
|
+ * In both bytes, byte1 and byte2, the 0x40 bit seeems not to be used.
|
|
+ *
|
|
+ * PS2 settings used herin: Standard PS2 mouse.
|
|
+ * For reading keycodes use, e.g.:
|
|
+ * od [-j (1|2)] -v -t x1 --width=3 < /dev/psaux
|
|
+ * compare with I_silitek_ps2() in mice.c.
|
|
+ * Which provides following keycodes received by the IR receiver
|
|
+ * included in the SK-7100 shipment for the SM-1000 keys:
|
|
+ *
|
|
+ * First byte: 0xe7 (Key down)
|
|
+ * 0xd7 (Key hold down)
|
|
+ * 0xf7 (Key up)
|
|
+ * byte0 & 0xc0 == 0x00 (PS2 mouse event)
|
|
+ * Which provides: Key if (byte0 & 0xc0) == 0xc0
|
|
+ * Mouse if (byte0 & 0xc0) == 0x00 (PS2 mouse)
|
|
+ * In other words: No GPM protocol check.
|
|
+ * Second and third byte (unsigned char, aka 8bits):
|
|
+ * 1: 0x01 0xfe
|
|
+ * 2: 0x02 0xfd
|
|
+ * 3: 0x03 0xfc
|
|
+ * 4: 0x04 0xfb
|
|
+ * 5: 0x05 0xfa
|
|
+ * 6: 0x06 0xf9
|
|
+ * 7: 0x07 0xf8
|
|
+ * 8: 0x08 0xf7
|
|
+ * 9: 0x09 0xf6
|
|
+ * 0: 0x0a 0xf5
|
|
+ * *: 0x0b 0xf4
|
|
+ * #: 0x0c 0xf3
|
|
+ * >: 0x0d 0xf2
|
|
+ * ||: 0x0e 0xf1
|
|
+ * []: 0x0f 0xf0
|
|
+ * >>|: 0x10 0xef
|
|
+ * |<<: 0x11 0xee
|
|
+ * Mute: 0x12 0xed
|
|
+ * Vol+: 0x13 0xec
|
|
+ * Vol-: 0x14 0xeb
|
|
+ * Display: 0x15 0xea
|
|
+ * PgUp: 0x16 0xe9
|
|
+ * PgDn: 0x17 0xe8
|
|
+ * Back: 0x18 0xe7
|
|
+ * Forward: 0x19 0xe6
|
|
+ * CD: 0x1a 0xe5
|
|
+ * ShowWiz: 0x1b 0xe4
|
|
+ * WWW: 0x1c 0xe3
|
|
+ * Close: 0x1d 0xe2
|
|
+ * Which provides: byte1 & byte2 == 0x00
|
|
+ * byte1 | byte2 == 0xff
|
|
+ * byte1 == keycode
|
|
+ *
|
|
+ * Mouse is standard PS2 mouse
|
|
+ */
|
|
+
|
|
+/*
|
|
+ * TODO
|
|
+ * Serial part: Find device settings which avoids changing IR sequences of other
|
|
+ * vendors like from Sony TV commanders. This because to filter
|
|
+ * them out.
|
|
+ * PS2 part: Better device settings which avoids the `ghost' mouse events
|
|
+ * caused by the other keys.
|
|
+ *
|
|
+ */
|
|
+
|
|
+#include <stdio.h>
|
|
+#include <stdlib.h>
|
|
+#include <unistd.h>
|
|
+#include <string.h>
|
|
+#include <ctype.h>
|
|
+#include <errno.h>
|
|
+#include <sys/time.h>
|
|
+#include <sys/types.h>
|
|
+#include <sys/stat.h>
|
|
+#include <fcntl.h>
|
|
+
|
|
+#include "headers/gpm.h"
|
|
+#include "headers/silitek.h"
|
|
+#include "headers/gpmInt.h"
|
|
+#include "headers/message.h"
|
|
+
|
|
+int fd_silitek = -1;
|
|
+
|
|
+struct silitek_key_struct {
|
|
+ char *key;
|
|
+ char item[32];
|
|
+ char drag[32];
|
|
+} static K_silitek[] = {
|
|
+ /* TERM=linux */
|
|
+ { NULL, "", "" },
|
|
+ {"1", "1", "1" },
|
|
+ {"2", "2", "2" },
|
|
+ {"3", "3", "3" },
|
|
+ {"4", "4", "4" },
|
|
+ {"5", "5", "5" },
|
|
+ {"6", "6", "6" },
|
|
+ {"7", "7", "7" },
|
|
+ {"8", "8", "8" },
|
|
+ {"9", "9", "9" },
|
|
+ {"0", "0", "0" },
|
|
+ {"*", "*", "*" },
|
|
+ {"#", "#", "#" },
|
|
+ {">", "\021", "\021" }, /* Ctrl+Q */
|
|
+ {"||", "\023", "\023" }, /* Ctrl+S */
|
|
+ {"[]", "\003", "\003" }, /* Ctrl+C */
|
|
+ {">>|", "\033[4~", "\033[4~"}, /* End */
|
|
+ {"|<<", "\033[1~", "\033[1~"}, /* Home */
|
|
+ {"Mute", "\033[3~", "\033[3~"}, /* Delete */
|
|
+ {"Vol+", "\033[A", "\033[A" }, /* Cursor up */
|
|
+ {"Vol-", "\033[B", "\033[B" }, /* Cursor down */
|
|
+ {"Display", "\033[2~", "\033[2~"}, /* Insert */
|
|
+ {"PgUp", "\033[5~", "\033[5~"}, /* Page up */
|
|
+ {"PgDn", "\033[6~", "\033[6~"}, /* Page down */
|
|
+ {"Back", "\033[D", "\033[D" }, /* Cursor left */
|
|
+ {"Forward", "\033[C", "\033[C" }, /* Cursor right */
|
|
+ {"CD", "\033[[A", "\033[[A"}, /* F1 */
|
|
+ {"ShowWiz", "\033[[B", "\033[[B"}, /* F2 */
|
|
+ {"WWW", "\033[[C", "\033[[C"}, /* F3 */
|
|
+ {"Close", "\033[[D", "\033[[D"}, /* F4 */
|
|
+ { NULL, "", "" }
|
|
+};
|
|
+#define SILITEK_KEYS (sizeof(K_silitek)/sizeof(struct silitek_key_struct))
|
|
+
|
|
+/* From twiddler.c: The same silly function as in gpm.c */
|
|
+static inline int open_console(const int mode)
|
|
+{
|
|
+ int fd;
|
|
+ extern struct options option;
|
|
+
|
|
+ if ((fd=open(option.consolename, mode)) < 0)
|
|
+ gpm_report(GPM_PR_OOPS,GPM_MESS_OPEN,option.consolename);
|
|
+ return fd;
|
|
+}
|
|
+
|
|
+static inline int silitek_wait(int timeout)
|
|
+{
|
|
+ fd_set Set;
|
|
+ struct timeval tv = {0, timeout};
|
|
+ int ret = 0;
|
|
+
|
|
+ do {
|
|
+ FD_ZERO(&Set);
|
|
+ FD_SET(fd_silitek, &Set);
|
|
+ ret = select(fd_silitek+1, &Set, NULL, NULL, &tv);
|
|
+
|
|
+ } while (ret < 0 && (errno == EINTR || errno == EAGAIN));
|
|
+
|
|
+ if (ret < 0 || !(FD_ISSET(fd_silitek, &Set)))
|
|
+ return 0;
|
|
+ return 1;
|
|
+}
|
|
+
|
|
+static inline int silitek_read(unsigned char *data, int timeout)
|
|
+{
|
|
+ ssize_t r = 0;
|
|
+ do {
|
|
+ if (!silitek_wait(timeout))
|
|
+ break;
|
|
+ r = read(fd_silitek, data, 1);
|
|
+
|
|
+ } while (r < 0 && (errno == EINTR || errno == EAGAIN));
|
|
+
|
|
+ if(r != 1)
|
|
+ return 0;
|
|
+ return 1;
|
|
+}
|
|
+
|
|
+int silitek_get_check(unsigned char *data)
|
|
+{
|
|
+ if ((data[0] != 0xbf) && /* key down */
|
|
+ (data[0] != 0x31) && /* key hold down */
|
|
+ (data[0] != 0x2a) && /* key up */
|
|
+ (data[0] != 0x7c) && /* mouse event and/or button up */
|
|
+ (data[0] != 0x7f) && /* mouse event and l+r-mouse button down */
|
|
+ (data[0] != 0xfd) && /* mouse event and r-mouse button down */
|
|
+ (data[0] != 0xfe)) /* mouse event and l-mouse button down */
|
|
+ return 0;
|
|
+ if (!silitek_read(&data[1], 50000))
|
|
+ return 0;
|
|
+ if (!silitek_read(&data[2], 50000))
|
|
+ return 0;
|
|
+#if 0
|
|
+ /*
|
|
+ * Sony IR
|
|
+ * various, it seems that the bit rate is to high to get stable
|
|
+ * bytes in correct order. Or the protocol of such a TV commander
|
|
+ * is more complicated than those of the SM-1000 because the IR
|
|
+ * receivers of the SM-1000 seems not read this fully correct.
|
|
+ */
|
|
+ if (data[0] == 0xfe) {
|
|
+ if (data[1] == 0x14 && data[2] == 0x8c)
|
|
+ return 0;
|
|
+ if (data[1] == 0x94 && (data[2] == 0x8c || data[2] == 0x8d))
|
|
+ return 0;
|
|
+ }
|
|
+#endif
|
|
+ return 1;
|
|
+}
|
|
+
|
|
+void silitek_keys(unsigned char *data, int *drag)
|
|
+{
|
|
+ int ret = 0, unblank = 4, cfd;
|
|
+ int but = (data[1] & 0x7f);
|
|
+ int chk = (data[2] & 0x7f);
|
|
+ int timediff = 0;
|
|
+ char *item;
|
|
+
|
|
+ if ((but & 0x20) || (but & 0x40) != 0x40)
|
|
+ return;
|
|
+ if ((but&chk) != 0x40 || (but|chk) != 0x7f)
|
|
+ return;
|
|
+ but &= 0x1f;
|
|
+ chk &= 0x1f;
|
|
+
|
|
+ if ((but|chk) != 0x1f)
|
|
+ return;
|
|
+ if (but < 1 || but > SILITEK_KEYS)
|
|
+ return;
|
|
+
|
|
+#define GET_TIME(tv) (gettimeofday(&tv, (struct timezone *)NULL))
|
|
+#define DIF_TIME(t1,t2) ((t2.tv_sec-t1.tv_sec)*1000 + (t2.tv_usec-t1.tv_usec)/1000)
|
|
+
|
|
+ switch(data[0]) {
|
|
+ static struct timeval uptv;
|
|
+ struct timeval tv;
|
|
+ case 0x2a:
|
|
+ uptv.tv_sec = 0;
|
|
+ /* fall through */
|
|
+ default:
|
|
+ return;
|
|
+ break;
|
|
+ case 0x31:
|
|
+ case 0xbf:
|
|
+ GET_TIME(tv);
|
|
+ if (!uptv.tv_sec) {
|
|
+ uptv.tv_sec = tv.tv_sec;
|
|
+ uptv.tv_usec = tv.tv_usec;
|
|
+ }
|
|
+ timediff = DIF_TIME(uptv, tv);
|
|
+ break;
|
|
+ }
|
|
+
|
|
+#undef GET_TIME
|
|
+#undef DIF_TIME
|
|
+
|
|
+ if (timediff && timediff < opt_time)
|
|
+ return;
|
|
+
|
|
+ item = K_silitek[but].item;
|
|
+ if (*drag) {
|
|
+ item = K_silitek[but].drag;
|
|
+ but = 0;
|
|
+ }
|
|
+#if 0
|
|
+ *drag = 0;
|
|
+#endif
|
|
+
|
|
+ cfd = open_console(O_WRONLY|O_NONBLOCK|O_NOCTTY);
|
|
+ if (cfd < 0)
|
|
+ return;
|
|
+ while (*item && !ret)
|
|
+ ret = ioctl(cfd, TIOCSTI, item++);
|
|
+ ioctl(cfd, TIOCLINUX, &unblank);
|
|
+ close(cfd);
|
|
+}
|
|
+
|
|
+int silitek_get_check_ps2(unsigned char *data)
|
|
+{
|
|
+#if 0
|
|
+ /*
|
|
+ * Enable this to trace foreign IR bytes sequences received by
|
|
+ * by the IR receiver of the SK-7100 keyboard.
|
|
+ */
|
|
+ FILE *log;
|
|
+ if (!(log = fopen("/tmp/log", "a")))
|
|
+ return 0;
|
|
+ fprintf(log, "TV: 0x%.2x 0x%.2x 0x%.2x\n", data[0], data[1], data[2]);
|
|
+ fclose(log);
|
|
+#endif
|
|
+ if ((data[0] != 0xe7) && /* key down */
|
|
+ (data[0] != 0xd7) && /* key hold down */
|
|
+ (data[0] != 0xf7) && /* key up */
|
|
+ (data[0]&0xc0)) /* PS2 mouse event */
|
|
+ return 0;
|
|
+ if (!silitek_read(&data[1], 50000))
|
|
+ return 0;
|
|
+ if (!silitek_read(&data[2], 50000))
|
|
+ return 0;
|
|
+ /*
|
|
+ * Other IR, current known:
|
|
+ *
|
|
+ * Sony IR
|
|
+ * 0x29 0x0c 0xf4
|
|
+ * 0x29 0x14 0xf4
|
|
+ */
|
|
+ if (data[0] == 0x29 && data[2] == 0xf4 && ((data[1] && 0x0c) || (data[1] && 0x14))) {
|
|
+ return 0;
|
|
+ }
|
|
+ return 1;
|
|
+}
|
|
+
|
|
+void silitek_keys_ps2(unsigned char *data, int *drag)
|
|
+{
|
|
+ int ret = 0, unblank = 4, cfd;
|
|
+ int but = data[1];
|
|
+ int chk = data[2];
|
|
+ int timediff = 0;
|
|
+ char *item;
|
|
+
|
|
+ if ((but&chk) && (but|chk) != 0xff)
|
|
+ return;
|
|
+
|
|
+ if (but < 1 || but > SILITEK_KEYS)
|
|
+ return;
|
|
+
|
|
+#define GET_TIME(tv) (gettimeofday(&tv, (struct timezone *)NULL))
|
|
+#define DIF_TIME(t1,t2) ((t2.tv_sec-t1.tv_sec)*1000 + (t2.tv_usec-t1.tv_usec)/1000)
|
|
+
|
|
+ switch(data[0]) {
|
|
+ static struct timeval uptv;
|
|
+ struct timeval tv;
|
|
+ case 0xe7:
|
|
+ uptv.tv_sec = 0;
|
|
+ /* fall through */
|
|
+ default:
|
|
+ return;
|
|
+ break;
|
|
+ case 0xd7:
|
|
+ case 0xf7:
|
|
+ GET_TIME(tv);
|
|
+ if (!uptv.tv_sec) {
|
|
+ uptv.tv_sec = tv.tv_sec;
|
|
+ uptv.tv_usec = tv.tv_usec;
|
|
+ }
|
|
+ timediff = DIF_TIME(uptv, tv);
|
|
+ break;
|
|
+ }
|
|
+
|
|
+#undef GET_TIME
|
|
+#undef DIF_TIME
|
|
+
|
|
+ if (timediff && timediff < opt_time)
|
|
+ return;
|
|
+
|
|
+ item = K_silitek[but].item;
|
|
+ if (*drag) {
|
|
+ item = K_silitek[but].drag;
|
|
+ but = 0;
|
|
+ }
|
|
+#if 0
|
|
+ *drag = 0;
|
|
+#endif
|
|
+
|
|
+ cfd = open_console(O_WRONLY|O_NONBLOCK|O_NOCTTY);
|
|
+ if (cfd < 0)
|
|
+ return;
|
|
+ while (*item && !ret)
|
|
+ ret = ioctl(cfd, TIOCSTI, item++);
|
|
+ ioctl(cfd, TIOCLINUX, &unblank);
|
|
+ close(cfd);
|
|
+}
|
|
+
|
|
+/*
|
|
+ * Map some ghost mouse PS2 events caused by the other
|
|
+ * keys. Maybe there is a better initialization for the chip
|
|
+ * of the SK-7100 IR receiver which would avoid those events.
|
|
+ */
|
|
+int silitek_ghost_ps2(unsigned char *data)
|
|
+{
|
|
+ if (data[0] == 0x18 || data[0] == 0x19) {
|
|
+ int but = data[1] - 0xc0;
|
|
+ int chk = data[2] - 0x01;
|
|
+
|
|
+ if ((but >= 1 && but <= SILITEK_KEYS) && (but == chk)) {
|
|
+ data[0] = 0xf7;
|
|
+ data[1] = but;
|
|
+ data[2] = 0xff - but;
|
|
+ }
|
|
+ }
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static char ansicstr_ret[SILISTRLEN+1];
|
|
+static char* ansicstr(char *string)
|
|
+{
|
|
+ int c, conv = 0, o;
|
|
+ char *ptr = string;
|
|
+ char *ret = &ansicstr_ret[0];
|
|
+
|
|
+ memset(&ansicstr_ret[0], 0, sizeof(ansicstr_ret));
|
|
+ while (ptr && *ptr) {
|
|
+ switch (c = *ptr++) {
|
|
+ case '\\':
|
|
+ if (!conv) {
|
|
+ conv = 1;
|
|
+ continue;
|
|
+ } else
|
|
+ c = '\\';
|
|
+ conv = 0; break;
|
|
+ case 'a': if (conv) c = '\a'; conv = 0; break;
|
|
+ case 'b': if (conv) c = '\b'; conv = 0; break;
|
|
+ case 't': if (conv) c = '\t'; conv = 0; break;
|
|
+ case 'n': if (conv) c = '\n'; conv = 0; break;
|
|
+ case 'v': if (conv) c = '\v'; conv = 0; break;
|
|
+ case 'f': if (conv) c = '\f'; conv = 0; break;
|
|
+ case 'r': if (conv) c = '\r'; conv = 0; break;
|
|
+ case 'e': if (conv) c = '\e'; conv = 0; break;
|
|
+ case 'E': if (conv) c = '\e'; conv = 0; break;
|
|
+ case '0': case '1': case '2': case '3':
|
|
+ case '4': case '5': case '6': case '7':
|
|
+ if (!conv) break;
|
|
+ c -= '0';
|
|
+ for (o = 2; ptr && (*ptr >= '0' && *ptr <= '7' ) && o--; ptr++)
|
|
+ c = (c * 8) + (*ptr - '0');
|
|
+ conv = 0; break;
|
|
+ case 'x':
|
|
+ if (!conv) break;
|
|
+ for (o = 3; ptr && isxdigit(*ptr) && o--; ptr++)
|
|
+ c = (c * 16) +
|
|
+ ((*ptr >= 'a' && *ptr <= 'f') ? (*ptr - 'a' + 10) :
|
|
+ ((*ptr >= 'A' && *ptr <= 'F') ? (*ptr - 'A' + 10) : (*ptr - '0')));
|
|
+ if (o == 3) {
|
|
+ *ret++ = '\\';
|
|
+ c = 'x';
|
|
+ }
|
|
+ conv = 0; break;
|
|
+ default:
|
|
+ conv = 0; break;
|
|
+ }
|
|
+ *ret++ = c;
|
|
+ }
|
|
+ return &ansicstr_ret[0];
|
|
+}
|
|
+
|
|
+void silitek_mapping()
|
|
+{
|
|
+ static int mapdone = 0;
|
|
+ FILE *conf;
|
|
+ char line[128];
|
|
+ int k = 1;
|
|
+
|
|
+ /* Just in case if called twice with -M option */
|
|
+ if (mapdone)
|
|
+ return;
|
|
+ mapdone = 1;
|
|
+
|
|
+ if (!(conf = fopen(SILI_SYSTEM_FILE, "r"))) {
|
|
+ if (errno != ENOENT)
|
|
+ gpm_report(GPM_PR_OOPS,GPM_MESS_OPEN,SILI_SYSTEM_FILE);
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ while (fgets(line, 128, conf)) {
|
|
+ int n;
|
|
+ char key[SILISTRLEN+1], item[SILISTRLEN+1], drag[SILISTRLEN+1];
|
|
+ /* Comments and empty lines */
|
|
+ if (line[0] == '\n' || line[0] == '#')
|
|
+ continue;
|
|
+
|
|
+ if (line[strlen(line) - 1] == '\n')
|
|
+ line[strlen(line) - 1] = '\0';
|
|
+ while (isspace(line[strlen(line) - 1]))
|
|
+ line[strlen(line) - 1] = '\0';
|
|
+
|
|
+ if (line[0] == '\0')
|
|
+ continue;
|
|
+
|
|
+ key[0] = item[0] = drag[0] = '\0';
|
|
+ if ((n = sscanf(line, SILISTRSCN, key, item, drag)) > 1 && n < 4) {
|
|
+ while (k < SILITEK_KEYS) {
|
|
+ if (!K_silitek[k].key) {
|
|
+ k = 1;
|
|
+ break;
|
|
+ }
|
|
+ if (!strncasecmp(key, K_silitek[k].key, SILISTRLEN)) {
|
|
+ size_t i = strlen(item), d = strlen(drag);
|
|
+ if (d) {
|
|
+ if (d > SILISTRLEN)
|
|
+ d = SILISTRLEN;
|
|
+ strncpy(K_silitek[k].drag, ansicstr(drag), d);
|
|
+ K_silitek[k].drag[d] = '\0';
|
|
+ }
|
|
+ if (i) {
|
|
+ if (i > SILISTRLEN)
|
|
+ i = SILISTRLEN;
|
|
+ strncpy(K_silitek[k].item, ansicstr(item), i);
|
|
+ K_silitek[k].item[i] = '\0';
|
|
+ }
|
|
+ break;
|
|
+ }
|
|
+ k++;
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+}
|