/* * send.c * * A hack to send a message to an RCX. * * Under IRIX and Linux, you should be able to compile this program with * cc send.c -o send. I don'k know about other versions of Unix, although * I'd be interested in hearing about compatibility issues that you are * able to fix. * * Set DEFAULTTTY to the serial device you want to use. * Set the RCXTTY environment variable to override DEFAULTTTY. * * Some additional documentation is available at: * * http://graphics.stanford.edu/~kekoa/rcx/tools.html * * Acknowledgements: * * Ray Kelm sent word that send.c compiles successfully under Linux, * and he passed on info about the names of the serial devices. * * Copyright (C) 1998, Kekoa Proudfoot. All Rights Reserved. * * License to copy, use, and modify this software is granted provided that * these notices are retained in any copies of any part of this software. * * The author makes no guarantee that this software will compile or work * properly. Also, if you use this software, you do so at your own risk. * * Kekoa Proudfoot * kekoa@graphics.stanford.edu * 9/10/98 */ #include #include #include #include #include #include #include #include #include #include #ifdef LINUX #define DEFAULTTTY "/dev/ttyS0" /* Linux - COM1 */ #else #define DEFAULTTTY "/dev/ttyd2" /* IRIX - second serial port */ #endif #define RATE B2400 #define CFLAGS CREAD | CLOCAL | CS8 | PARENB | PARODD #define BUFFERSIZE 4096 /* Hexdump routine - a very handy snippet from my Quake hacking days */ #define LINE_SIZE 16 #define GROUP_SIZE 4 #define UNPRINTABLE '.' void hexdump(void *buf, int len, char *prefix) { unsigned char *b = (unsigned char *)buf; char p[100] = ""; int i, j; if (prefix && prefix[0] != '\0') { strcat(p, prefix); strcat(p, " "); } for (i = 0; i < len / LINE_SIZE; i++) { printf("%s%04x: ", p, i * LINE_SIZE); for (j = 0; j < LINE_SIZE; j++, b++) { printf("%02x %s", *b, ((j + 1) % GROUP_SIZE) ? "" : " "); } b -= LINE_SIZE; printf(" "); for (j = 0; j < LINE_SIZE; j++, b++) { if (isprint(*b)) putchar(*b); else putchar(UNPRINTABLE); } printf("\n"); } if (len % LINE_SIZE != 0) { printf("%s%04x: ", p, i * LINE_SIZE); for (j = 0; j < len % LINE_SIZE; j++, b++) { printf("%02x %s", *b, ((j + 1) % GROUP_SIZE) ? "" : " "); } b -= len % LINE_SIZE; while (j < LINE_SIZE) { printf(" %s", ((j + 1) % GROUP_SIZE) ? "" : " "); j++; } printf(" "); for (j = 0; j < len % LINE_SIZE; j++, b++) { if (isprint(*b)) putchar(*b); else putchar(UNPRINTABLE); } printf("\n"); } } main(int argc, char **argv) { char *tty; int fd, fl; fd_set fds; struct termios ios; unsigned char buf[BUFFERSIZE]; unsigned char *bp = buf; int i, count, sum = 0; struct timeval tv; if ((tty = getenv("RCXTTY")) == NULL) tty = DEFAULTTTY; /* Print usage if nothing on command line */ if (argc == 1) { fprintf(stderr, "usage: %s byte [byte ...]\n", argv[0]); exit(1); } /* Open the tty and configure it */ if ((fd = open(tty, O_RDWR)) == -1) { perror("open"); exit(1); } if (!isatty(fd)) { close(fd); fprintf(stderr, "%s: not a tty\n", tty); exit(1); } memset(&ios, 0, sizeof(ios)); ios.c_cflag = CFLAGS; cfsetispeed(&ios, RATE); cfsetospeed(&ios, RATE); if (tcsetattr(fd, TCSANOW, &ios) == -1) { perror("tcsetattr"); exit(1); } /* Assemble the message */ *bp++ = 0x55; *bp++ = 0xff; *bp++ = 0x00; for (i = 1; i < argc; i++) { unsigned char byte = strtol(argv[i], NULL, 16); *bp++ = byte; *bp++ = (~byte) & 0xff; sum += byte; } *bp++ = sum; *bp++ = ~sum; /* Send it */ write(fd, buf, bp - buf); /* Wait for input */ bp = buf; while (1) { FD_ZERO(&fds); FD_SET(fd, &fds); tv.tv_sec = 0; tv.tv_usec = 300000; if (select(FD_SETSIZE, &fds, NULL, NULL, &tv) == -1) { perror("select"); exit(1); } if (!FD_ISSET(fd, &fds)) break; if ((count = read(fd, bp, BUFFERSIZE - (bp - buf))) == -1) { perror("read"); exit(1); } bp += count; } /* Dump output and close tty file descriptor */ hexdump(buf, bp - buf, ""); close(fd); }