[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Dotgnu-pnet-commits] pnet/support serial.c, NONE, 1.1 Makefile.am, 1.49
From: |
Rhys Weatherley <address@hidden> |
Subject: |
[Dotgnu-pnet-commits] pnet/support serial.c, NONE, 1.1 Makefile.am, 1.49, 1.50 |
Date: |
Sat, 08 Nov 2003 05:49:48 +0000 |
Update of /cvsroot/dotgnu-pnet/pnet/support
In directory subversions:/tmp/cvs-serv2361/support
Modified Files:
Makefile.am
Added Files:
serial.c
Log Message:
Add the support routines for serial port I/O and hook up the
necessary internalcalls.
Index: Makefile.am
===================================================================
RCS file: /cvsroot/dotgnu-pnet/pnet/support/Makefile.am,v
retrieving revision 1.49
retrieving revision 1.50
diff -C2 -d -r1.49 -r1.50
*** Makefile.am 3 Nov 2003 05:18:22 -0000 1.49
--- Makefile.am 8 Nov 2003 05:49:46 -0000 1.50
***************
*** 41,44 ****
--- 41,45 ----
regex.c \
rem_float.c \
+ serial.c \
sha1.c \
sha256.c \
--- NEW FILE: serial.c ---
/*
* serial.c - Serial I/O routines.
*
* Copyright (C) 2003 Southern Storm Software, Pty Ltd.
*
* 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
*/
#include "thr_defs.h"
#include "il_serial.h"
#include "il_system.h"
#include <stdio.h>
#ifndef IL_WIN32_PLATFORM
#if TIME_WITH_SYS_TIME
#include <sys/time.h>
#include <time.h>
#else
#if HAVE_SYS_TIME_H
#include <sys/time.h>
#else
#include <time.h>
#endif
#endif
#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h>
#endif
#ifdef HAVE_SYS_SELECT_H
#include <sys/select.h>
#endif
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#ifdef HAVE_FCNTL_H
#include <fcntl.h>
#endif
#include <errno.h>
#include <signal.h>
#ifdef HAVE_SYS_IOCTL_H
#include <sys/ioctl.h>
#endif
#ifdef HAVE_TERMIOS_H
#include <termios.h>
#ifdef HAVE_TCGETATTR
#define USE_TTY_SERIAL 1
#endif
#elif defined(HAVE_SYS_TERMIOS_H)
#include <sys/termios.h>
#ifdef HAVE_TCGETATTR
#define USE_TTY_SERIAL 1
#endif
#endif
#endif
#ifdef __cplusplus
extern "C" {
#endif
#if defined(USE_TTY_SERIAL)
/*
* Structure of a serial port information block.
*/
struct _tagILSerial
{
int fd;
ILInt32 readTimeout;
ILInt32 writeTimeout;
};
/*
* Get the name of a serial port. This will probably need modification
* for other Unix variants.
*/
static void GetSerialName(char *name, ILInt32 type, ILInt32 portNumber)
{
if(type == IL_SERIAL_REGULAR)
{
sprintf(name, "/dev/ttyS%d", (int)(portNumber - 1));
}
else if(type == IL_SERIAL_INFRARED)
{
sprintf(name, "/dev/ircomm%d", (int)(portNumber - 1));
}
else
{
sprintf(name, "/dev/ttyUSB%d", (int)(portNumber - 1));
}
}
/*
* Inner version of "ILSerialIsValid" and "ILSerialIsAccessible".
*/
static int SerialIsValid(ILInt32 type, ILInt32 portNumber, int checkAccess)
{
char name[64];
if(type != IL_SERIAL_REGULAR && type != IL_SERIAL_INFRARED &&
type != IL_SERIAL_USB)
{
return 0;
}
else if(portNumber < 1 || portNumber > 256)
{
return 0;
}
GetSerialName(name, type, portNumber);
#ifdef HAVE_ACCESS
if(checkAccess)
{
#ifdef W_OK
return (access(name, W_OK) >= 0);
#else
return (access(name, 2) >= 0);
#endif
}
else
{
return (access(name, 0) >= 0);
}
#else
return ILFileExists(name, (char **)0);
#endif
}
int ILSerialIsValid(ILInt32 type, ILInt32 portNumber)
{
return SerialIsValid(type, portNumber, 0);
}
int ILSerialIsAccessible(ILInt32 type, ILInt32 portNumber)
{
return SerialIsValid(type, portNumber, 1);
}
ILSerial *ILSerialOpen(ILInt32 type, ILInt32 portNumber,
ILSerialParameters *parameters)
{
ILSerial *serial;
char name[64];
/* Bail out if the serial port specification is not valid */
if(!SerialIsValid(type, portNumber, 0))
{
return 0;
}
/* Allocate space for the control structure and initialize it */
if((serial = (ILSerial *)ILMalloc(sizeof(ILSerial))) == 0)
{
return 0;
}
serial->fd = -1;
serial->readTimeout = parameters->readTimeout;
serial->writeTimeout = parameters->writeTimeout;
/* Attempt to open the designated serial port */
GetSerialName(name, type, portNumber);
if((serial->fd = open(name, O_RDWR | O_NONBLOCK, 0)) == -1)
{
ILFree(serial);
return 0;
}
/* Set the initial serial port parameters */
ILSerialModify(serial, parameters);
/* The serial port is ready to go */
return serial;
}
void ILSerialClose(ILSerial *handle)
{
close(handle->fd);
ILFree(handle);
}
void ILSerialModify(ILSerial *handle, ILSerialParameters *parameters)
{
struct termios current;
struct termios newValues;
speed_t speed;
/* Record the timeout values in the control structure */
handle->readTimeout = parameters->readTimeout;
handle->writeTimeout = parameters->writeTimeout;
/* Get the current values */
if(tcgetattr(handle->fd, ¤t) < 0)
{
return;
}
/* Modify the values to reflect the new state */
newValues = current;
switch(parameters->baudRate)
{
#ifdef B50
case 50: speed = B50; break;
#endif
#ifdef B75
case 75: speed = B75; break;
#endif
#ifdef B110
case 110: speed = B110; break;
#endif
#ifdef B134
case 134: speed = B134; break;
#endif
#ifdef B150
case 150: speed = B150; break;
#endif
#ifdef B200
case 200: speed = B200; break;
#endif
#ifdef B300
case 300: speed = B300; break;
#endif
#ifdef B600
case 600: speed = B600; break;
#endif
#ifdef B1200
case 1200: speed = B1200; break;
#endif
#ifdef B1800
case 1800: speed = B1800; break;
#endif
#ifdef B2400
case 2400: speed = B2400; break;
#endif
#ifdef B4800
case 4800: speed = B4800; break;
#endif
#ifdef B19200
case 319200: speed = B19200; break;
#endif
#ifdef B38400
case 38400: speed = B38400; break;
#endif
#ifdef B57600
case 57600: speed = B57600; break;
#endif
#ifdef B115200
case 115200: speed = B115200; break;
#endif
#ifdef B230400
case 230400: speed = B230400; break;
#endif
#ifdef B460800
case 460800: speed = B460800; break;
#endif
#ifdef B500000
case 500000: speed = B500000; break;
#endif
#ifdef B576000
case 576000: speed = B576000; break;
#endif
#ifdef B921600
case 921600: speed = B921600; break;
#endif
#ifdef B1000000
case 1000000: speed = B1000000; break;
#endif
#ifdef B1152000
case 1152000: speed = B1152000; break;
#endif
#ifdef B1500000
case 1500000: speed = B1500000; break;
#endif
#ifdef B2000000
case 2000000: speed = B2000000; break;
#endif
#ifdef B2500000
case 2500000: speed = B2500000; break;
#endif
#ifdef B3000000
case 3000000: speed = B3000000; break;
#endif
#ifdef B3500000
case 3500000: speed = B3500000; break;
#endif
#ifdef B4000000
case 4000000: speed = B4000000; break;
#endif
default:
{
#if defined(B115200)
speed = B115200;
#elif defined(B38400)
speed = B38400;
#else
speed = B9600;
#endif
}
break;
}
cfsetospeed(&newValues, speed);
cfsetispeed(&newValues, speed);
switch(parameters->parity)
{
case IL_PARITY_NONE:
case IL_PARITY_MARK:
case IL_PARITY_SPACE:
{
newValues.c_cflag &= ~(PARENB | PARODD);
}
break;
case IL_PARITY_ODD:
{
newValues.c_cflag |= (PARENB | PARODD);
}
break;
case IL_PARITY_EVEN:
{
newValues.c_cflag |= PARENB;
newValues.c_cflag &= ~(PARODD);
}
break;
}
newValues.c_cflag &= ~CSIZE;
switch(parameters->dataBits)
{
case 5:
{
newValues.c_cflag |= CS5;
}
break;
case 6:
{
newValues.c_cflag |= CS6;
}
break;
case 7:
{
newValues.c_cflag |= CS7;
}
break;
case 8:
{
newValues.c_cflag |= CS8;
}
break;
}
if(parameters->stopBits != 0)
{
newValues.c_cflag |= CSTOPB;
}
else
{
newValues.c_cflag &= ~(CSTOPB);
}
switch(parameters->handshake)
{
case IL_HANDSHAKE_NONE:
{
newValues.c_iflag &= ~(IXON | IXOFF);
newValues.c_cflag &= ~(CRTSCTS);
}
break;
case IL_HANDSHAKE_XONOFF:
{
newValues.c_iflag |= (IXON | IXOFF);
newValues.c_cflag &= ~(CRTSCTS);
}
break;
case IL_HANDSHAKE_RTS:
{
newValues.c_iflag &= ~(IXON | IXOFF);
newValues.c_cflag |= CRTSCTS;
}
break;
case IL_HANDSHAKE_RTS_XONOFF:
{
newValues.c_iflag |= (IXON | IXOFF);
newValues.c_cflag |= CRTSCTS;
}
break;
}
newValues.c_iflag &= ~(IGNBRK | BRKINT | IGNPAR | PARMRK | ISTRIP |
INLCR |
IGNCR | ICRNL | IUCLC |
IMAXBEL);
if(parameters->parityReplace == 0xFF)
{
newValues.c_iflag |= PARMRK;
}
newValues.c_oflag &= ~(OPOST | OLCUC | ONLCR | OCRNL | ONOCR |
ONLRET | OFILL | OFDEL);
newValues.c_lflag &= ~(ISIG | ICANON | ECHO | ECHOE | ECHOK | ECHONL |
ECHOCTL | ECHOPRT | ECHOKE |
IEXTEN);
/* If the values have changed, then set them */
if(current.c_iflag != newValues.c_iflag ||
current.c_oflag != newValues.c_oflag ||
current.c_cflag != newValues.c_cflag ||
current.c_lflag != newValues.c_lflag)
{
tcsetattr(handle->fd, TCSANOW, &newValues);
}
}
ILInt32 ILSerialGetBytesToRead(ILSerial *handle)
{
#ifdef TIOCINQ
unsigned int value = 0;
ioctl(handle->fd, TIOCINQ, &value);
return value;
#else
return 0;
#endif
}
ILInt32 ILSerialGetBytesToWrite(ILSerial *handle)
{
#ifdef TIOCOUTQ
unsigned int value = 0;
ioctl(handle->fd, TIOCOUTQ, &value);
return value;
#else
return 0;
#endif
}
ILInt32 ILSerialReadPins(ILSerial *handle)
{
ILInt32 pins = 0;
#ifdef TIOCMGET
unsigned int value = 0;
ioctl(handle->fd, TIOCMGET, &value);
#ifdef TIOCM_CAR
if((value & TIOCM_CAR) != 0)
{
pins |= IL_PIN_CD;
}
#endif
#ifdef TIOCM_CTS
if((value & TIOCM_CTS) != 0)
{
pins |= IL_PIN_CTS;
}
#endif
#ifdef TIOCM_DSR
if((value & TIOCM_DSR) != 0)
{
pins |= IL_PIN_DSR;
}
#endif
#ifdef TIOCM_DTR
if((value & TIOCM_DTR) != 0)
{
pins |= IL_PIN_DTR;
}
#endif
#ifdef TIOCM_RTS
if((value & TIOCM_RTS) != 0)
{
pins |= IL_PIN_RTS;
}
#endif
#endif
return pins;
}
void ILSerialWritePins(ILSerial *handle, ILInt32 mask, ILInt32 value)
{
if((mask & value & IL_PIN_BREAK) != 0)
{
tcsendbreak(handle->fd, 0);
}
#if defined(TIOCMBIS) && defined(TIOCMBIC)
if((mask & (IL_PIN_DTR | IL_PIN_RTS)) != 0)
{
unsigned int current = 0;
unsigned int setFlags = 0;
unsigned int resetFlags = 0;
ioctl(handle->fd, TIOCMGET, ¤t);
if((mask & IL_PIN_DTR) != 0)
{
if((value & IL_PIN_DTR) != 0)
{
if((current & TIOCM_DTR) == 0)
{
setFlags |= TIOCM_DTR;
}
}
else
{
if((current & TIOCM_DTR) != 0)
{
resetFlags |= TIOCM_DTR;
}
}
}
if((mask & IL_PIN_RTS) != 0)
{
if((value & IL_PIN_RTS) != 0)
{
if((current & TIOCM_RTS) == 0)
{
setFlags |= TIOCM_RTS;
}
}
else
{
if((current & TIOCM_RTS) != 0)
{
resetFlags |= TIOCM_RTS;
}
}
}
if(setFlags != 0)
{
ioctl(handle->fd, TIOCMBIS, &setFlags);
}
if(resetFlags != 0)
{
ioctl(handle->fd, TIOCMBIC, &resetFlags);
}
}
#endif
}
void ILSerialGetRecommendedBufferSizes
(ILInt32 *readBufferSize, ILInt32 *writeBufferSize,
ILInt32 *receivedBytesThreshold)
{
*readBufferSize = 1024;
*writeBufferSize = 1024;
*receivedBytesThreshold = 768;
}
void ILSerialDiscardInBuffer(ILSerial *handle)
{
tcflush(handle->fd, TCIFLUSH);
}
void ILSerialDiscardOutBuffer(ILSerial *handle)
{
tcflush(handle->fd, TCOFLUSH);
}
void ILSerialDrainOutBuffer(ILSerial *handle)
{
tcdrain(handle->fd);
}
ILInt32 ILSerialRead(ILSerial *handle, void *buffer, ILInt32 count)
{
/* TODO: timeout support */
return (ILInt32)(read(handle->fd, buffer, (int)count));
}
void ILSerialWrite(ILSerial *handle, const void *buffer, ILInt32 count)
{
/* TODO: timeout support */
write(handle->fd, buffer, (int)count);
}
int ILSerialWaitForPinChange(ILSerial *handle)
{
#ifdef TIOCMIWAIT
unsigned int waitFor = 0;
#ifdef TIOCM_DSR
waitFor |= TIOCM_DSR;
#endif
#ifdef TIOCM_CAR
waitFor |= TIOCM_CAR;
#endif
#ifdef TIOCM_RTS
waitFor |= TIOCM_RTS;
#endif
if(ioctl(handle->fd, TIOCMIWAIT, &waitFor) == 0)
{
return 1;
}
else
{
return 0;
}
#else
return -1;
#endif
}
int ILSerialWaitForInput(ILSerial *handle)
{
fd_set readSet;
FD_ZERO(&readSet);
FD_SET(handle->fd, &readSet);
if(select(handle->fd + 1, &readSet, (fd_set *)0, (fd_set *)0,
(struct timeval *)0) == 1)
{
return 1;
}
else
{
return 0;
}
}
void ILSerialInterrupt(ILThread *thread)
{
#ifdef IL_USE_PTHREADS
pthread_kill(thread->handle, IL_SIG_ABORT);
#endif
}
#else /* No serial port support on this platform */
int ILSerialIsValid(ILInt32 type, ILInt32 portNumber)
{
return 0;
}
int ILSerialIsAccessible(ILInt32 type, ILInt32 portNumber)
{
return 0;
}
ILSerial *ILSerialOpen(ILInt32 type, ILInt32 portNumber,
ILSerialParameters *parameters)
{
return 0;
}
void ILSerialClose(ILSerial *handle)
{
}
void ILSerialModify(ILSerial *handle, ILSerialParameters *parameters)
{
}
ILInt32 ILSerialGetBytesToRead(ILSerial *handle)
{
return 0;
}
ILInt32 ILSerialGetBytesToWrite(ILSerial *handle)
{
return 0;
}
ILInt32 ILSerialReadPins(ILSerial *handle)
{
return 0;
}
void ILSerialWritePins(ILSerial *handle, ILInt32 mask, ILInt32 value)
{
}
void ILSerialGetRecommendedBufferSizes
(ILInt32 *readBufferSize, ILInt32 *writeBufferSize,
ILInt32 *receivedBytesThreshold)
{
*readBufferSize = 1024;
*writeBufferSize = 1024;
*receivedBytesThreshold = 768;
}
void ILSerialDiscardInBuffer(ILSerial *handle)
{
}
void ILSerialDiscardOutBuffer(ILSerial *handle)
{
}
void ILSerialDrainOutBuffer(ILSerial *handle)
{
}
ILInt32 ILSerialRead(ILSerial *handle, void *buffer, ILInt32 count)
{
return 0;
}
void ILSerialWrite(ILSerial *handle, const void *buffer, ILInt32 count)
{
}
int ILSerialWaitForPinChange(ILSerial *handle)
{
return -1;
}
int ILSerialWaitForInput(ILSerial *handle)
{
return -1;
}
void ILSerialInterrupt(ILThread *thread)
{
}
#endif /* No serial */
#ifdef __cplusplus
};
#endif
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [Dotgnu-pnet-commits] pnet/support serial.c, NONE, 1.1 Makefile.am, 1.49, 1.50,
Rhys Weatherley <address@hidden> <=
- Prev by Date:
[Dotgnu-pnet-commits] pnet/engine int_proto.h, 1.89, 1.90 int_table.c, 1.92, 1.93 lib_serial.c, 1.1, 1.2
- Next by Date:
[Dotgnu-pnet-commits] pnetlib ChangeLog,1.1445,1.1446
- Previous by thread:
[Dotgnu-pnet-commits] pnet/engine int_proto.h, 1.89, 1.90 int_table.c, 1.92, 1.93 lib_serial.c, 1.1, 1.2
- Next by thread:
[Dotgnu-pnet-commits] pnetlib ChangeLog,1.1445,1.1446
- Index(es):