/*! \file rcxtty.c \brief Basic RCX communication \author Markus L. Noga */ /* * The contents of this file are subject to the Mozilla Public License * Version 1.0 (the "License"); you may not use this file except in * compliance with the License. You may obtain a copy of the License at * http://www.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS IS" * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the * License for the specific language governing rights and limitations * under the License. * * The Original Code is legOS code, released October 2, 1999. * * The Initial Developer of the Original Code is Markus L. Noga. * Portions created by Markus L. Noga are Copyright (C) 1999 * Markus L. Noga. All Rights Reserved. * * Contributor(s): Kekoa Proudfoot */ /* 2002.04.01 * * Modifications to the original loader.c file in LegOS 0.2.4 include: * * Hary D. Mahesan's update to support USB IR firmware downloading * using RCX 2.0's USB tower under WIN32 on Cygwin. * * * * CVS inclusion, revision and modification by Paolo Masetti. * * */ #include #include #include #include #if defined(_WIN32) #include #else #include #include #include #endif #include "rcxtty.h" extern int tty_usb; //! the one and only RCX file descriptor static FILEDESCR rcxFd = BADFILE; //! get RCX file descriptor FILEDESCR rcxFD(void) { return rcxFd; } void myperror(char *str) { #if defined(_WIN32) fprintf(stderr, "Error %lu: %s\n", (unsigned long) GetLastError(), str); #else perror(str); #endif } int mywrite(FILEDESCR fd, const void *buf, size_t len) { #if defined(_WIN32) DWORD nBytesWritten=0; if (WriteFile(fd, buf, len, &nBytesWritten, NULL)) return nBytesWritten; else return -1; #else /* For usb tower, the driver, legousbtower, uses interrupt */ /* urb which can only carry up to 8 bytes at a time. To */ /* transmit more we have to check and send the rest. It is */ /* a good thing to check, so I'll make it general. */ int actual = 0; int rc; char * cptr; int retry = 1000; if (len < 1) return len; cptr = (char *) buf; while (actual < len) { rc = (long) write(fd, cptr+actual, len-actual); if (rc == -1) { if ((errno == EINTR) || (errno == EAGAIN)) { rc = 0; usleep(10); retry --; } else return -1; } actual += rc; if (retry < 1) return actual; } return len; #endif } //! initialize RCX communications port int rcxInit(const char *tty, int highspeed) { /* * Copyright (C) 1998, 1999, Kekoa Proudfoot. All Rights Reserved. * * License to copy, use, and modify this software is granted provided that * this notice is retained in any copies of any part of this software. * * The author makes no guarantee that this software will compile or * function correctly. Also, if you use this software, you do so at your * own risk. * * Kekoa Proudfoot * kekoa@graphics.stanford.edu * 10/3/98 */ // char *tty; FILEDESCR fd; #if defined(_WIN32) DCB dcb; COMMTIMEOUTS CommTimeouts; #else struct termios ios; #endif if (*tty == '-' && !*(tty + 1)) // read from standard input if tty="-" fd = 0; #if defined(_WIN32) else if ((fd = CreateFile(tty, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL)) == INVALID_HANDLE_VALUE) { fprintf(stderr, "Error %lu: Opening %s\n", (unsigned long) GetLastError(), tty); #else else if ((fd = open(tty, O_RDWR | O_EXCL)) < 0) { fprintf(stderr,"Error opening tty=%s, ",tty); perror("open"); #endif return -1; } #if !defined(_WIN32) if (tty_usb == 0 && !isatty(fd)) { close(fd); fprintf(stderr, "%s: not a tty\n", tty); return -1; } #endif #if defined(_WIN32) // These settings below definitely do not apply to the USB IR Tower, so if() them out. if(tty_usb==0) { // Serial settings FillMemory(&dcb, sizeof(dcb), 0); if (!GetCommState(fd, &dcb)) { // get current DCB // Error in GetCommState myperror("GetCommState"); return -1; } else { dcb.ByteSize = 8; dcb.Parity = (highspeed ? 0 : 1); // 0-4=no,odd,even,mark,space dcb.StopBits = 0; // 0,1,2 = 1, 1.5, 2 dcb.fBinary = TRUE ; dcb.fParity = FALSE ; dcb.fAbortOnError = FALSE ; dcb.BaudRate = (highspeed ? CBR_4800 : CBR_2400); // Update DCB rate. // Set new state. if (!SetCommState(fd, &dcb)) { // Error in SetCommState. Possibly a problem with the communications // port handle or a problem with the DCB structure itself. myperror("SetCommState"); return -1; } if (!GetCommTimeouts (fd, &CommTimeouts)) myperror("GetCommTimeouts"); // Change the COMMTIMEOUTS structure settings. CommTimeouts.ReadIntervalTimeout = MAXDWORD; CommTimeouts.ReadTotalTimeoutMultiplier = 0; CommTimeouts.ReadTotalTimeoutConstant = 0; CommTimeouts.WriteTotalTimeoutMultiplier = 10; CommTimeouts.WriteTotalTimeoutConstant = 1000; // Set the time-out parameters for all read and write operations // on the port. if (!SetCommTimeouts(fd, &CommTimeouts)) myperror("SetCommTimeouts"); } } rcxFd=fd; #else if (tty_usb == 0) { memset(&ios, 0, sizeof(ios)); ios.c_cflag = CREAD | CLOCAL | CS8 | (highspeed ? 0 : PARENB | PARODD); cfsetispeed(&ios, highspeed ? B4800 : B2400); cfsetospeed(&ios, highspeed ? B4800 : B2400); if (tcsetattr(fd, TCSANOW, &ios) == -1) { perror("tcsetattr"); exit(1); } } rcxFd=fd; #endif return 0; } //! shutdown RCX communications port void rcxShutdown() { #if defined(_WIN32) CloseHandle(rcxFd); #else close(rcxFd); #endif rcxFd=BADFILE; }