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.