aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDimitri Sokolyuk <demon@dim13.org>2009-03-17 13:15:14 +0000
committerDimitri Sokolyuk <demon@dim13.org>2009-03-17 13:15:14 +0000
commite291d6b3bc86ede74e6e8c7147b65044a87f0d61 (patch)
treeb41bbd8b0a5049a0fba26b2eac15bd20d1096591
telejet webresetter
-rw-r--r--Makefile8
-rw-r--r--crc16.c35
-rw-r--r--telejet.c299
3 files changed, 342 insertions, 0 deletions
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..22154f1
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,8 @@
+# $Id$
+
+PROG= telejet
+SRCS= telejet.c crc16.c
+CFLAGS+= -ggdb -Wall
+NOMAN=
+
+.include <bsd.prog.mk>
diff --git a/crc16.c b/crc16.c
new file mode 100644
index 0000000..d0b5f0f
--- /dev/null
+++ b/crc16.c
@@ -0,0 +1,35 @@
+/* $Id$ */
+/*
+ * this source code is based on Rex and Binstock which, in turn,
+ * acknowledges William James Hunt.
+ * source: http://www.darkridge.com/~jpr5/archive/alg/node191.html
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+
+unsigned int crc_16_table[16] = {
+ 0x0000, 0xcc01, 0xd801, 0x1400, 0xf001, 0x3c00, 0x2800, 0xe401,
+ 0xa001, 0x6c00, 0x7800, 0xb401, 0x5000, 0x9c01, 0x8801, 0x4400
+};
+
+unsigned short int
+get_crc_16(int start, char *p, int n)
+{
+ unsigned short int crc;
+ int r;
+
+ for (crc = start; n-- > 0; ++p) {
+ /* compute checksum of lower four bits of *p */
+ r = crc_16_table[crc & 0x0f];
+ crc = (crc >> 4) & 0x0fff;
+ crc ^= r ^ crc_16_table[*p & 0x0f];
+
+ /* compute checksum of upper four bits of *p */
+ r = crc_16_table[crc & 0x0f];
+ crc = (crc >> 4) & 0x0fff;
+ crc ^= r ^ crc_16_table[(*p >> 4) & 0x0f];
+ }
+
+ return crc;
+}
diff --git a/telejet.c b/telejet.c
new file mode 100644
index 0000000..f383de6
--- /dev/null
+++ b/telejet.c
@@ -0,0 +1,299 @@
+/* $Id$ */
+/*
+ * Copyright (c) 2009 Dimitri Sokolyuk <sokolyuk@gmail.com>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <sys/types.h>
+#include <sys/time.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <err.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <termios.h>
+#include <unistd.h>
+
+#define debug 0
+
+struct termios tio;
+
+char *device = "/dev/ttyS0";
+char to_kbd[] = "#TO_KBD";
+char to__pc[] = "#TO__PC";
+int minlen = 10; /* minimal response length (if any) */
+
+/* Ctrl-Alt-F1 */
+char caf[] = {0x14, 0x11, 0x05, 0xf0, 0x05, 0xf0, 0x11, 0xf0, 0x14};
+
+/* Ctrl-Alt-Del */
+char cad[] = {0x14, 0x11, 0x71, 0xf0, 0x71, 0xf0, 0x11, 0xf0, 0x14};
+
+enum {NONE, SOFT, HARD, QUERY};
+
+int compose(char *buf, int addr, char cmd, char *data, int dlen);
+int chkresponse(char *buf, int *addr, char *data, int *dlen);
+void usage();
+int talk(int fd, char *buf, int wlen, int rlen);
+int prstr(char *data, int len);
+int main(int argc, char **argv);
+int opendev(char *dev);
+int closedev(int fd);
+unsigned short int get_crc_16(int start, char *p, int n);
+
+int
+compose(char *buf, int addr, char cmd, char *data, int dlen)
+{
+ char *p;
+ int crc;
+
+ p = buf;
+
+ memcpy(p, to_kbd, sizeof(to_kbd) - 1);
+ p += sizeof(to_kbd) - 1;
+ *p++ = (addr >> 16) & 0xff;
+ *p++ = (addr >> 8) & 0xff;
+ *p++ = addr & 0xff;
+ *p++ = dlen + 4;
+ *p++ = cmd;
+
+ while (dlen--)
+ *p++ = *data++;
+
+ crc = get_crc_16(0, buf, p - buf);
+#if debug
+ printf("crc: 0x%x\n", crc);
+#endif
+ *p++ = (crc >> 8) & 0xff;
+ *p++ = crc & 0xff;
+
+ return p - buf;
+}
+
+int
+chkresponse(char *buf, int *addr, char *data, int *dlen)
+{
+ char *p;
+ int crc, len;
+
+ if (memcmp(buf, to__pc, sizeof(to__pc) - 1) != 0)
+ return -1;
+
+ p = buf + sizeof(to__pc) - 1;
+ *addr = (*p++ & 0xff) << 16;
+ *addr |= (*p++ & 0xff) << 8;
+ *addr |= *p++ & 0xff;
+
+ *dlen = *p++ - 3;
+ for (len = *dlen; len--; ++data)
+ *data = *p++;
+
+ crc = (*p++ & 0xff) << 8;
+ crc |= *p & 0xff;
+
+#if debug
+ printf("crc: 0x%x\n", get_crc_16(0, buf, *dlen + 11));
+#endif
+ if (get_crc_16(0, buf, *dlen + 11) != crc)
+ return -1;
+
+ return 0;
+}
+
+void
+usage()
+{
+ extern char *__progname;
+
+ fprintf(stderr, "usage: %s [-hsq] [addr]\n", __progname);
+
+ exit(1);
+}
+
+int
+talk(int fd, char *buf, int wlen, int rlen)
+{
+ fd_set readfd;
+ struct timeval tv;
+ int done = 0;
+ int expected = minlen;
+ int ret;
+ int expflag = 1;
+
+ ret = write(fd, buf, wlen);
+ if (ret == -1) {
+ perror("write");
+ return ret;
+ }
+
+ tv.tv_usec = 0;
+ tv.tv_sec = 5;
+
+ FD_ZERO(&readfd);
+ FD_SET(fd, &readfd);
+ while (done < expected) {
+ ret = select(fd + 1, &readfd, NULL, NULL, &tv);
+ if (ret == -1)
+ perror("select");
+ if (ret <= 0)
+ return ret;
+ if (FD_ISSET(fd, &readfd)) {
+ ret = read(fd, buf + done, rlen - done);
+ if (ret == -1) {
+ perror("read");
+ return ret;
+ }
+ done += ret;
+ }
+ if (expflag && done >= minlen) {
+ expflag = 0;
+ expected += (int)buf[minlen];
+ }
+#if debug
+ printf("done: %d, expected: %d\n", done, expected);
+#endif
+ }
+
+ return done;
+}
+
+int
+prstr(char *data, int len)
+{
+ data += 2;
+ len -= 2;
+
+ while (len--)
+ putchar(*data++);
+ putchar('\n');
+
+ return 0;
+}
+
+int
+main(int argc, char **argv)
+{
+ char buf[256];
+ int len, ret, fd, c;
+ char data[256];
+ int addr = 0xffffff;
+ int type = SOFT;
+ int eval = 1;
+
+ while ((c = getopt(argc, argv, "f:shq")) != -1)
+ switch (c) {
+ case 'f':
+ device = strdup(optarg);
+ break;
+ case 's':
+ type = SOFT;
+ break;
+ case 'h':
+ type = HARD;
+ break;
+ case 'q':
+ type = QUERY;
+ break;
+ }
+
+ argc -= optind;
+ argv += optind;
+
+ if (argc)
+ addr = strtol(*argv, NULL, 0x10);
+ else if (type != QUERY)
+ usage();
+
+#if debug
+ printf("addr: 0x%x\n", addr);
+#endif
+
+ fd = opendev("/dev/ttyS0");
+
+ switch (type) {
+ case SOFT:
+ /* escape from x11 to console 1 */
+ len = compose(buf, addr, 'D', caf, sizeof(caf));
+ talk(fd, buf, len, sizeof(buf));
+ /* send tree finger */
+ len = compose(buf, addr, 'D', cad, sizeof(cad));
+ break;
+ case HARD:
+ /* push the button */
+ len = compose(buf, addr, 'R', NULL, 0);
+ break;
+ case QUERY:
+ /* push the button */
+ len = compose(buf, addr, 'V', NULL, 0);
+ break;
+ }
+ ret = talk(fd, buf, len, sizeof(buf));
+ closedev(fd);
+
+ if (ret > 0) {
+ if (chkresponse(buf, &addr, data, &len) == 0) {
+ if (memcmp(data + len - 2, "OK", 2) == 0) {
+ eval = 0;
+#if debug
+ prstr(data, len);
+#endif
+ }
+#if debug
+ } else {
+ printf("chk failed, len=%d\n", ret);
+ for (p = buf; ret-- > 0; ++p)
+ printf("'%c'\t0x%.2x\n", *p & 0xff, *p & 0xff);
+#endif
+ }
+ }
+
+ return eval;
+}
+
+int
+opendev(char *dev)
+{
+ struct termios raw;
+ int fd;
+
+ fd = open(dev, O_RDWR | O_NOCTTY | O_NDELAY);
+ if (fd == -1)
+ err(1, "%s", dev);
+
+ tcgetattr(fd, &tio);
+ memcpy(&raw, &tio, sizeof(struct termios));
+
+ cfsetspeed(&raw, B2400);
+ cfmakeraw(&raw);
+#if 1
+ raw.c_cc[VMIN] = minlen; /* at least 10 bytes */
+ raw.c_cc[VTIME] = 2; /* 200 ms */
+#endif
+
+ if (tcsetattr(fd, TCSAFLUSH, &raw) < 0)
+ err(1, "can't set raw mode");
+
+ return fd;
+}
+
+int
+closedev(int fd)
+{
+ if (tcsetattr(fd, TCSAFLUSH, &tio) < 0)
+ err(1, "can't restore from raw mode");
+ close(fd);
+
+ return 0;
+}