This is MiscSerialPort.m in view mode; [Download] [Up]
//
// MiscSerialPort.m -- Serial port I/O support
// Written by W. Eric Norum Copyright (c) 1997 by W. Eric Norum.
// $Revision: 2.1 $ $Date: 1997/04/02 15:32:59 $
// All rights reserved.
// This notice may not be removed from this source code.
//
// This object is included in the MiscKit by permission from the author
// and its use is governed by the MiscKit license, found in the file
// "LICENSE.rtf" in the MiscKit distribution. Please refer to that file
// for a list of all applicable permissions and restrictions.
//
#import "MiscSerialPort.h"
#import <libc.h>
#import <string.h>
#import <errno.h>
#import <sys/fcntl.h>
#import <sys/ioctl.h>
#ifdef USE_TERMIOS
#import <termios.h>
#endif
NSString *MiscSerialPortReadCompletionNotification = @"MiscSerialPortReadCompletionNotification";
NSString *MiscSerialPortNotificationDataItem;
@implementation MiscSerialPort
+ (void)initialize
{
MiscSerialPortNotificationDataItem = NSFileHandleNotificationDataItem;
}
- (NSString *)errorString
{
return [[errorString copy] autorelease];
}
- (void)_setErrorString:(NSString *)format, ...
{
va_list args;
va_start (args, format);
[errorString autorelease];
errorString = [[NSString alloc] initWithFormat:format arguments:args];
va_end (args);
}
- (void)_serialDataArrived:(NSNotification *)notification
{
/*
* Pass on the notification
*/
[[NSNotificationCenter defaultCenter]
postNotificationName:MiscSerialPortReadCompletionNotification
object:self
userInfo:[notification userInfo]];
/*
* Continue reading
*/
[fileHandle readInBackgroundAndNotify];
}
- (BOOL)setParameters
{
int ratecode;
#ifdef USE_TERMIOS
struct termios termios;
#else
struct sgttyb sgttyb;
struct tchars tchars;
struct ltchars ltchars;
int linediscipline, localmode;
#endif
switch (baud) {
default: return NO;
case 38400: case EXTB: ratecode = EXTB; break;
case 19200: case EXTA: ratecode = EXTA; break;
case 9600: case B9600: ratecode = B9600; break;
case 4800: case B4800: ratecode = B4800; break;
case 2400: case B2400: ratecode = B2400; break;
case 1200: case B1200: ratecode = B1200; break;
case 300: case B300: ratecode = B300; break;
}
#ifdef USE_TERMIOS
switch (characterLength) {
case 5: termios.c_cflag = CS5; break;
case 6: termios.c_cflag = CS6; break;
case 7: termios.c_cflag = CS7; break;
case 8: termios.c_cflag = CS8; break;
default:
[self _setErrorString:@"Illegal character length"];
return NO;
}
switch (parity) {
case MiscSerialPortNoParity:
break;
case MiscSerialPortEvenParity:
termios.c_cflag |= PARENB;
break;
case MiscSerialPortOddParity:
termios.c_cflag |= PARENB | PARODD;
break;
default:
[self _setErrorString:@"Illegal parity type"];
return NO;
}
termios.c_cflag |= CREAD | HUPCL;
termios.c_iflag = 0;
termios.c_oflag = 0;
termios.c_lflag = 0;
termios.c_cc[VMIN] = 10;
termios.c_cc[VTIME] = 1;
cfsetispeed (&termios, ratecode);
cfsetospeed (&termios, ratecode);
if (tcsetattr (fd, TCSADRAIN, &termios) < 0) {
#else
if (characterLength != ((parity == MiscSerialPortNoParity) ? 8 : 7)) {
[self _setErrorString:@"Illegal combination of parity type and character length"];
return NO;
}
linediscipline = OTTYDISC;
sgttyb.sg_ispeed = sgttyb.sg_ospeed = ratecode;
sgttyb.sg_erase = sgttyb.sg_kill = -1;
switch (parity) {
case MiscSerialPortNoParity:
sgttyb.sg_flags = RAW;
break;
case MiscSerialPortEvenParity:
sgttyb.sg_flags = EVENP | CBREAK;
break;
case MiscSerialPortOddParity:
sgttyb.sg_flags = ODDP | CBREAK;
break;
default:
[self _setErrorString:@"Illegal parity type"];
return NO;
}
tchars.t_intrc = tchars.t_quitc = tchars.t_eofc = -1;
tchars.t_startc = tchars.t_stopc = tchars.t_brkc = -1;
localmode = 0;
ltchars.t_suspc = ltchars.t_dsuspc = ltchars.t_rprntc = -1;
ltchars.t_flushc = ltchars.t_werasc = ltchars.t_lnextc = -1;
if ((ioctl (fd, TIOCSETD, &linediscipline) < 0)
|| (ioctl (fd, TIOCSETP, &sgttyb) < 0)
|| (ioctl (fd, TIOCSETC, &tchars) < 0)
|| (ioctl (fd, TIOCLSET, &localmode) < 0)
|| (ioctl (fd, TIOCSLTC, <chars) < 0)) {
#endif
[self _setErrorString:@"Can't set `%@' parameters: %s", portName, strerror (errno)];
return NO;
}
return YES;
}
- (BOOL)setCharacterLength:(int)clen parity:(int)par
{
int oldCharacterLength = characterLength;
enum MiscSerialPortParity oldParity = parity;
characterLength = clen;
parity = par;
if (![self setParameters]) {
characterLength = oldCharacterLength;
parity = oldParity;
return NO;
}
return YES;
}
- initWithPort:(NSString *)aString baud:(int)anInt
{
fd = open ([aString cString], O_RDWR | O_EXCL);
if (fd < 0) {
[self _setErrorString:@"Can't open `%@': %s", aString, strerror(errno)];
return nil;
}
if (ioctl (fd, TIOCEXCL, NULL) < 0) {
[self _setErrorString:@"Can't make `%@' exclusive-use: %s", portName, strerror (errno)];
close (fd);
return nil;
}
baud = anInt;
characterLength = 8;
parity = MiscSerialPortNoParity;
if (![self setParameters]) {
close (fd);
return nil;
}
isOpen = YES;
portName = [aString copy];
fileHandle = [[NSFileHandle alloc] initWithFileDescriptor:fd closeOnDealloc:YES];
[fileHandle readInBackgroundAndNotify];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(_serialDataArrived:)
name:NSFileHandleReadCompletionNotification
object:fileHandle];
return self;
}
- (void)dealloc
{
if (isOpen) {
[[NSNotificationCenter defaultCenter] removeObserver:self
name:NSFileHandleReadCompletionNotification
object:fileHandle];
[portName release];
[fileHandle release];
}
[errorString release];
[super dealloc];
}
- (BOOL)_writeRawBuffer:(const void *)buf length:(unsigned int)length
{
if (write (fd, buf, length) < 0) {
[self _setErrorString:@"Write failed: %s", strerror (errno)];
return NO;
}
return YES;
}
- (BOOL)writeData:(NSData *)data
{
return [self _writeRawBuffer:[data bytes] length:[data length]];
}
- (BOOL)writeString:(NSString *)aString
{
return [self _writeRawBuffer:[aString cString] length:[aString length]];
}
@end
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.