From e291d6b3bc86ede74e6e8c7147b65044a87f0d61 Mon Sep 17 00:00:00 2001 From: Dimitri Sokolyuk Date: Tue, 17 Mar 2009 13:15:14 +0000 Subject: telejet webresetter --- Makefile | 8 ++ crc16.c | 35 ++++++++ telejet.c | 299 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 342 insertions(+) create mode 100644 Makefile create mode 100644 crc16.c create mode 100644 telejet.c 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 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 +#include + +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 + * + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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; +} -- cgit v1.2.3