Commits

Jody McAdams committed f16e28d

added some accelerometer code and did some cleanup/reorganization

  • Participants
  • Parent commits 0096d73

Comments (0)

Files changed (70)

File ArduinoSerialXcode/ArduinoSerial/AMSDKCompatibility.h

-//
-//  AMSDKCompatibility.h
-//
-//  Created by Nick Zitzmann on 2007-10-22.
-//
-
-// AMSerialPort uses types that were introduced with the 10.5 SDK.
-// This allows older SDKs to be used.
-
-#import <Foundation/Foundation.h>
-
-#ifndef NSINTEGER_DEFINED
-	#ifdef NS_BUILD_32_LIKE_64
-		typedef long NSInteger;
-		typedef unsigned long NSUInteger;
-	#else
-		typedef int NSInteger;
-		typedef unsigned int NSUInteger;
-	#endif
-	#define NSIntegerMax    LONG_MAX
-	#define NSIntegerMin    LONG_MIN
-	#define NSUIntegerMax   ULONG_MAX
-	#define NSINTEGER_DEFINED 1
-#endif
-
-#ifndef CGFLOAT_DEFINED
-	typedef float CGFloat;
-	#define CGFLOAT_MIN FLT_MIN
-	#define CGFLOAT_MAX FLT_MAX
-	#define CGFLOAT_IS_DOUBLE 0
-	#define CGFLOAT_DEFINED 1
-#endif
-
-#ifndef _SUSECONDS_T
-#define _SUSECONDS_T
-typedef int suseconds_t;
-#endif

File ArduinoSerialXcode/ArduinoSerial/AMSerialErrors.h

-/*
- *  AMSerialErrors.h
- *
- *  Created by Andreas on 27.07.06.
- *  Copyright 2006 Andreas Mayer. All rights reserved.
- *
- */
-
-
-enum {
-	kAMSerialErrorNone = 0,
-	kAMSerialErrorFatal = 99,
-	
-	// reading only
-	kAMSerialErrorTimeout = 100,
-	kAMSerialErrorInternalBufferFull = 101,
-	
-	// writing only
-	kAMSerialErrorNoDataToWrite = 200,
-	kAMSerialErrorOnlySomeDataWritten = 201,
-};
-
-enum {
-	// reading only
-	kAMSerialEndOfStream = 0,
-	kAMSerialStopCharReached = 1,
-	kAMSerialStopLengthReached = 2,
-	kAMSerialStopLengthExceeded = 3,
-};

File ArduinoSerialXcode/ArduinoSerial/AMSerialPort.h

-//
-//  AMSerialPort.h
-//
-//  Created by Andreas on 2002-04-24.
-//  Copyright (c) 2001 Andreas Mayer. All rights reserved.
-//
-//
-//
-//  2002-09-18 Andreas Mayer
-//  - added available & owner
-//  2002-10-17 Andreas Mayer
-//	- countWriteInBackgroundThreads and countWriteInBackgroundThreadsLock added
-//  2002-10-25 Andreas Mayer
-//	- more additional instance variables for reading and writing in background
-//  2004-02-10 Andreas Mayer
-//    - added delegate for background reading/writing
-//  2005-04-04 Andreas Mayer
-//	- added setDTR and clearDTR
-//  2006-07-28 Andreas Mayer
-//	- added -canonicalMode, -endOfLineCharacter and friends
-//	  (code contributed by Randy Bradley)
-//	- cleaned up accessor methods; moved deprecated methods to "Deprecated" category
-//	- -setSpeed: does support arbitrary values on 10.4 and later; returns YES on success, NO otherwiese
-//  2006-08-16 Andreas Mayer
-//	- cleaned up the code and removed some (presumably) unnecessary locks
-//  2007-10-26 Sean McBride
-//  - made code 64 bit and garbage collection clean
-//	2009-3-20 Pat O'Keefe
-//	- fixed setSpeed method
-
-
-/*
- * Standard speeds defined in termios.h
- *
-#define B0	0
-#define B50	50
-#define B75	75
-#define B110	110
-#define B134	134
-#define B150	150
-#define B200	200
-#define B300	300
-#define B600	600
-#define B1200	1200
-#define	B1800	1800
-#define B2400	2400
-#define B4800	4800
-#define B7200	7200
-#define B9600	9600
-#define B14400	14400
-#define B19200	19200
-#define B28800	28800
-#define B38400	38400
-#define B57600	57600
-#define B76800	76800
-#define B115200	115200
-#define B230400	230400
- */
-
-#import "AMSDKCompatibility.h"
-
-#include <stdio.h>
-#include <string.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <errno.h>
-#include <paths.h>
-#include <termios.h>
-#include <sys/time.h>
-#include <sysexits.h>
-#include <sys/param.h>
-
-#import <Foundation/Foundation.h>
-
-#define	AMSerialOptionServiceName @"AMSerialOptionServiceName"
-#define	AMSerialOptionSpeed @"AMSerialOptionSpeed"
-#define	AMSerialOptionDataBits @"AMSerialOptionDataBits"
-#define	AMSerialOptionParity @"AMSerialOptionParity"
-#define	AMSerialOptionStopBits @"AMSerialOptionStopBits"
-#define	AMSerialOptionInputFlowControl @"AMSerialOptionInputFlowControl"
-#define	AMSerialOptionOutputFlowControl @"AMSerialOptionOutputFlowControl"
-#define	AMSerialOptionEcho @"AMSerialOptionEcho"
-#define	AMSerialOptionCanonicalMode @"AMSerialOptionCanonicalMode"
-
-// By default, debug code is preprocessed out.  If you would like to compile with debug code enabled,
-// "#define AMSerialDebug" before including any AMSerialPort headers, as in your prefix header
-
-typedef enum {	
-	kAMSerialParityNone = 0,
-	kAMSerialParityOdd = 1,
-	kAMSerialParityEven = 2
-} AMSerialParity;
-
-typedef enum {	
-	kAMSerialStopBitsOne = 1,
-	kAMSerialStopBitsTwo = 2
-} AMSerialStopBits;
-
-// Private constant
-#define AMSER_MAXBUFSIZE  512UL//4096UL
-
-extern NSString *const AMSerialErrorDomain;
-
-@interface NSObject (AMSerialDelegate)
-- (void)serialPortReadData:(NSDictionary *)dataDictionary;
-- (void)serialPortWriteProgress:(NSDictionary *)dataDictionary;
-@end
-
-@interface AMSerialPort : NSObject
-{
-@private
-	NSString *bsdPath;
-	NSString *serviceName;
-	NSString *serviceType;
-	int fileDescriptor;
-	struct termios * __strong options;
-	struct termios * __strong originalOptions;
-	NSMutableDictionary *optionsDictionary;
-	NSFileHandle *fileHandle;
-	BOOL gotError;
-	int	lastError;
-	id owner;
-	// used by AMSerialPortAdditions only:
-	char * __strong buffer;
-	id am_readTarget;
-	SEL am_readSelector;
-	NSTimeInterval readTimeout; // for public blocking read methods and doRead
-	fd_set * __strong readfds;
-	id delegate;
-	BOOL delegateHandlesReadInBackground;
-	BOOL delegateHandlesWriteInBackground;
-	
-	NSLock *writeLock;
-	BOOL stopWriteInBackground;
-	int countWriteInBackgroundThreads;
-	NSLock *readLock;
-	BOOL stopReadInBackground;
-	int countReadInBackgroundThreads;
-	NSLock *closeLock;
-}
-
-- (id)init:(NSString *)path withName:(NSString *)name type:(NSString *)serialType;
-// initializes port
-// path is a bsdPath
-// name is an IOKit service name
-// type is an IOKit service type
-
-- (NSString *)bsdPath;
-// bsdPath (e.g. '/dev/cu.modem')
-
-- (NSString *)name;
-// IOKit service name (e.g. 'modem')
-
-- (NSString *)type;
-// IOKit service type (e.g. kIOSerialBSDRS232Type)
-
-- (NSDictionary *)properties;
-// IORegistry entry properties - see IORegistryEntryCreateCFProperties()
-
-
-- (BOOL)isOpen;
-// YES if port is open
-
-- (AMSerialPort *)obtainBy:(id)sender;
-// get this port exclusively; NULL if it's not free
-
-- (void)free;
-// give it back (and close the port if still open)
-
-- (BOOL)available;
-// check if port is free and can be obtained
-
-- (id)owner;
-// who obtained the port?
-
-
-- (NSFileHandle *)open;
-// opens port for read and write operations
-// to actually read or write data use the methods provided by NSFileHandle
-// (alternatively you may use those from AMSerialPortAdditions)
-
-- (void)close;
-// close port - no more read or write operations allowed
-
-- (BOOL)drainInput;
-- (BOOL)flushInput:(BOOL)fIn Output:(BOOL)fOut;	// (fIn or fOut) must be YES
-- (BOOL)sendBreak;
-
-- (BOOL)setDTR;
-// set DTR - not yet tested!
-
-- (BOOL)clearDTR;
-// clear DTR - not yet tested!
-
-// read and write serial port settings through a dictionary
-
-- (NSDictionary *)options;
-// will open the port to get options if neccessary
-
-- (void)setOptions:(NSDictionary *)options;
-// AMSerialOptionServiceName HAS to match! You may NOT switch ports using this
-// method.
-
-// reading and setting parameters is only useful if the serial port is already open
-- (long)speed;
-- (BOOL)setSpeed:(long)speed;
-
-- (unsigned long)dataBits;
-- (void)setDataBits:(unsigned long)bits;	// 5 to 8 (5 may not work)
-
-- (AMSerialParity)parity;
-- (void)setParity:(AMSerialParity)newParity;
-
-- (AMSerialStopBits)stopBits;
-- (void)setStopBits:(AMSerialStopBits)numBits;
-
-- (BOOL)echoEnabled;
-- (void)setEchoEnabled:(BOOL)echo;
-
-- (BOOL)RTSInputFlowControl;
-- (void)setRTSInputFlowControl:(BOOL)rts;
-
-- (BOOL)DTRInputFlowControl;
-- (void)setDTRInputFlowControl:(BOOL)dtr;
-
-- (BOOL)CTSOutputFlowControl;
-- (void)setCTSOutputFlowControl:(BOOL)cts;
-
-- (BOOL)DSROutputFlowControl;
-- (void)setDSROutputFlowControl:(BOOL)dsr;
-
-- (BOOL)CAROutputFlowControl;
-- (void)setCAROutputFlowControl:(BOOL)car;
-
-- (BOOL)hangupOnClose;
-- (void)setHangupOnClose:(BOOL)hangup;
-
-- (BOOL)localMode;
-- (void)setLocalMode:(BOOL)local;	// YES = ignore modem status lines
-
-- (BOOL)canonicalMode;
-- (void)setCanonicalMode:(BOOL)flag;
-
-- (char)endOfLineCharacter;
-- (void)setEndOfLineCharacter:(char)eol;
-
-- (void)clearError;			// call this before changing any settings
-- (BOOL)commitChanges;	// call this after using any of the above set... functions
-- (int)errorCode;				// if -commitChanges returns NO, look here for further info
-
-// setting the delegate (for background reading/writing)
-
-- (id)delegate;
-- (void)setDelegate:(id)newDelegate;
-
-// time out for blocking reads in seconds
-- (NSTimeInterval)readTimeout;
-- (void)setReadTimeout:(NSTimeInterval)aReadTimeout;
-
-- (void)readTimeoutAsTimeval:(struct timeval*)timeout;
-
-
-@end

File ArduinoSerialXcode/ArduinoSerial/AMSerialPort.m

-//
-//  AMSerialPort.m
-//
-//  Created by Andreas on 2002-04-24.
-//  Copyright (c) 2001 Andreas Mayer. All rights reserved.
-//
-//  2002-09-18 Andreas Mayer
-//  - added available & owner
-//  2002-10-10 Andreas Mayer
-//	- some log messages changed
-//  2002-10-25 Andreas Mayer
-//	- additional locks and other changes for reading and writing in background
-//  2003-11-26 James Watson
-//	- in dealloc [self close] reordered to execute before releasing closeLock
-//  2007-05-22 Nick Zitzmann
-//  - added -hash and -isEqual: methods
-//  2007-07-18 Sean McBride
-//  - behaviour change: -open and -close must now always be matched, -dealloc checks this
-//  - added -debugDescription so gdb's 'po' command gives something useful
-//  2007-07-25 Andreas Mayer
-// - replaced -debugDescription by -description; works for both, gdb's 'po' and NSLog()
-//  2007-10-26 Sean McBride
-//  - made code 64 bit and garbage collection clean
-//	2009-3-20 Pat O'Keefe
-//	- fixed setSpeed method
-
-
-#import "AMSDKCompatibility.h"
-
-#include <stdio.h>
-#include <string.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <errno.h>
-#include <paths.h>
-#include <termios.h>
-#include <sys/time.h>
-#include <sysexits.h>
-#include <sys/param.h>
-#include <sys/ioctl.h>
-
-#import "AMSerialPort.h"
-#import "AMSerialErrors.h"
-
-#import <IOKit/serial/IOSerialKeys.h>
-#if defined(MAC_OS_X_VERSION_10_4) && (MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_4)
-	#import <IOKit/serial/ioss.h>
-#endif
-
-NSString *const AMSerialErrorDomain = @"de.harmless.AMSerial.ErrorDomain";
-
-
-@implementation AMSerialPort
-
-- (id)init:(NSString *)path withName:(NSString *)name type:(NSString *)type
-	// path is a bsdPath
-	// name is an IOKit service name
-{
-	if ((self = [super init])) {
-		bsdPath = [path copy];
-		serviceName = [name copy];
-		serviceType = [type copy];
-		optionsDictionary = [[NSMutableDictionary dictionaryWithCapacity:8] retain];
-#ifndef __OBJC_GC__
-		options = (struct termios*)malloc(sizeof(*options));
-		originalOptions = (struct termios*)malloc(sizeof(*originalOptions));
-		buffer = (char*)malloc(AMSER_MAXBUFSIZE);
-		readfds = (fd_set*)malloc(sizeof(*readfds));
-#else
-		options = (struct termios*)NSAllocateCollectable(sizeof(*options), 0);
-		originalOptions = (struct termios*)NSAllocateCollectable(sizeof(*originalOptions), 0);
-		buffer = (char*)NSAllocateCollectable(AMSER_MAXBUFSIZE, 0);
-		readfds = (fd_set*)NSAllocateCollectable(sizeof(*readfds), 0);
-#endif
-		fileDescriptor = -1;
-		
-		writeLock = [[NSLock alloc] init];
-		readLock = [[NSLock alloc] init];
-		closeLock = [[NSLock alloc] init];
-		
-		// By default blocking read attempts will timeout after 1 second
-		[self setReadTimeout:1.0];
-	}
-	return self;
-}
-
-#ifndef __OBJC_GC__
-
-- (void)dealloc
-{
-#ifdef AMSerialDebug
-	if (fileDescriptor != -1)
-		NSLog(@"It is a programmer error to have not called -close on an AMSerialPort you have opened");
-#endif
-	
-	[readLock release];
-	[writeLock release];
-	[closeLock release];
-	[am_readTarget release];
-	
-	free(readfds);
-	free(buffer);
-	free(originalOptions);
-	free(options);
-	[optionsDictionary release];
-	[serviceName release];
-	[serviceType release];
-	[bsdPath release];
-	[super dealloc];
-}
-
-#else
-
-- (void)finalize
-{
-#ifdef AMSerialDebug
-	if (fileDescriptor != -1)
-		NSLog(@"It is a programmer error to have not called -close on an AMSerialPort you have opened");
-#endif
-	assert (fileDescriptor == -1);
-
-	[super finalize];
-}
-
-#endif
-
-// So NSLog and gdb's 'po' command give something useful
-- (NSString *)description
-{
-	NSString *result= [NSString stringWithFormat:@"<%@: %x = name: %@, path: %@, type: %@, fileHandle: %@, fileDescriptor: %d>", NSStringFromClass([self class]), (long unsigned)self, serviceName, bsdPath, serviceType, fileHandle, fileDescriptor];
-	return result;
-}
-
-- (NSUInteger)hash
-{
-	return [[self bsdPath] hash];
-}
-
-- (BOOL)isEqual:(id)otherObject
-{
-	if ([otherObject isKindOfClass:[AMSerialPort class]])
-		return [[self bsdPath] isEqualToString:[otherObject bsdPath]];
-	return NO;
-}
-
-
-- (id)delegate
-{
-	return delegate;
-}
-
-- (void)setDelegate:(id)newDelegate
-{
-	id old = nil;
-	
-	if (newDelegate != delegate) {
-		old = delegate;
-		delegate = [newDelegate retain];
-		[old release];
-		delegateHandlesReadInBackground = [delegate respondsToSelector:@selector(serialPortReadData:)];
-		delegateHandlesWriteInBackground = [delegate respondsToSelector:@selector(serialPortWriteProgress:)];
-	}
-}
-
-
-- (NSString *)bsdPath
-{
-	return bsdPath;
-}
-
-- (NSString *)name
-{
-	return serviceName;
-}
-
-- (NSString *)type
-{
-	return serviceType;
-}
-
-- (NSDictionary *)properties
-{
-	NSDictionary *result = nil;
-	kern_return_t kernResult; 
-	CFMutableDictionaryRef matchingDictionary;
-	io_service_t serialService;
-	
-	matchingDictionary = IOServiceMatching(kIOSerialBSDServiceValue);
-	CFDictionarySetValue(matchingDictionary, CFSTR(kIOTTYDeviceKey), (CFStringRef)[self name]);
-	if (matchingDictionary != NULL) {
-		CFRetain(matchingDictionary);
-		// This function decrements the refcount of the dictionary passed it
-		serialService = IOServiceGetMatchingService(kIOMasterPortDefault, matchingDictionary);
-		
-		if (serialService) {
-			NSMutableDictionary *propertiesDict;
-			kernResult = IORegistryEntryCreateCFProperties(serialService, (CFMutableDictionaryRef *)&propertiesDict, kCFAllocatorDefault, 0);
-			if (kernResult == KERN_SUCCESS) {
-				result = [propertiesDict autorelease];
-			}
-		} else {
-#ifdef AMSerialDebug
-			NSLog(@"properties: no matching service for %@", matchingDictionary);
-#endif
-		}
-		CFRelease(matchingDictionary);
-		// We have sucked this service dry of information so release it now.
-		(void)IOObjectRelease(serialService);
-	}
-	return result;
-}
-
-
-- (BOOL)isOpen
-{
-	// YES if port is open
-	return (fileDescriptor >= 0);
-}
-
-- (AMSerialPort *)obtainBy:(id)sender
-{
-	// get this port exclusively; NULL if it's not free
-	if (owner == nil) {
-		owner = sender;
-		return self;
-	} else
-		return nil;
-}
-
-- (void)free
-{
-	// give it back
-	owner = nil;
-	[self close];	// you never know ...
-}
-
-- (BOOL)available
-{
-	// check if port is free and can be obtained
-	return (owner == nil);
-}
-
-- (id)owner
-{
-	// who obtained the port?
-	return owner;
-}
-
-
-- (NSFileHandle *)open // use returned file handle to read and write
-{
-	NSFileHandle *result = nil;
-	
-	const char *path = [bsdPath fileSystemRepresentation];
-	fileDescriptor = open(path, O_RDWR | O_NOCTTY); // | O_NONBLOCK);
-
-#ifdef AMSerialDebug
-	NSLog(@"open %@ (%d)\n", bsdPath, fileDescriptor);
-#endif
-	
-	if (fileDescriptor < 0)	{
-#ifdef AMSerialDebug
-		NSLog(@"Error opening serial port %@ - %s(%d).\n", bsdPath, strerror(errno), errno);
-#endif
-	} else {
-		/*
-		 if (fcntl(fileDescriptor, F_SETFL, fcntl(fileDescriptor, F_GETFL, 0) & !O_NONBLOCK) == -1)
-		 {
-			 NSLog(@"Error clearing O_NDELAY %@ - %s(%d).\n", bsdPath, strerror(errno), errno);
-		 } // ... else
-		 */
-		// get the current options and save them for later reset
-		if (tcgetattr(fileDescriptor, originalOptions) == -1) {
-#ifdef AMSerialDebug
-			NSLog(@"Error getting tty attributes %@ - %s(%d).\n", bsdPath, strerror(errno), errno);
-#endif
-		} else {
-			// Make an exact copy of the options
-			*options = *originalOptions;
-			
-			// This object owns the fileDescriptor and must dispose it later
-			// In other words, you must balance calls to -open with -close
-			fileHandle = [[NSFileHandle alloc] initWithFileDescriptor:fileDescriptor];
-			result = fileHandle;
-		}
-	}
-	if (!result) { // failure
-		if (fileDescriptor >= 0) {
-			close(fileDescriptor);
-		}
-		fileDescriptor = -1;
-	}
-	return result;
-}
-
-
-- (void)close
-{
-	// Traditionally it is good to reset a serial port back to
-	// the state in which you found it.  Let's continue that tradition.
-	if (fileDescriptor >= 0) {
-		//NSLog(@"close - attempt closeLock");
-		[closeLock lock];
-		//NSLog(@"close - closeLock locked");
-		
-		// kill pending read by setting O_NONBLOCK
-		if (fcntl(fileDescriptor, F_SETFL, fcntl(fileDescriptor, F_GETFL, 0) | O_NONBLOCK) == -1) {
-#ifdef AMSerialDebug
-			NSLog(@"Error clearing O_NONBLOCK %@ - %s(%d).\n", bsdPath, strerror(errno), errno);
-#endif
-		}
-		if (tcsetattr(fileDescriptor, TCSANOW, originalOptions) == -1) {
-#ifdef AMSerialDebug
-			NSLog(@"Error resetting tty attributes - %s(%d).\n", strerror(errno), errno);
-#endif
-		}
-		
-		// Disallows further access to the communications channel
-		[fileHandle closeFile];
-
-		// Release the fileHandle
-		[fileHandle release];
-		fileHandle = nil;
-		
-#ifdef AMSerialDebug
-		NSLog(@"close (%d)\n", fileDescriptor);
-#endif
-		// Close the fileDescriptor, that is our responsibility since the fileHandle does not own it
-		close(fileDescriptor);
-		fileDescriptor = -1;
-		
-		[closeLock unlock];
-		//NSLog(@"close - closeLock unlocked");
-	}
-}
-
-- (BOOL)drainInput
-{
-	BOOL result = (tcdrain(fileDescriptor) != -1);
-	return result;
-}
-
-- (BOOL)flushInput:(BOOL)fIn Output:(BOOL)fOut	// (fIn or fOut) must be YES
-{
-	int mode = 0;
-	if (fIn == YES)
-		mode = TCIFLUSH;
-	if (fOut == YES)
-		mode = TCOFLUSH;
-	if (fIn && fOut)
-		mode = TCIOFLUSH;
-	
-	BOOL result = (tcflush(fileDescriptor, mode) != -1);
-	return result;
-}
-
-- (BOOL)sendBreak
-{
-	BOOL result = (tcsendbreak(fileDescriptor, 0) != -1);
-	return result;
-}
-
-- (BOOL)setDTR
-{
-	BOOL result = (ioctl(fileDescriptor, TIOCSDTR) != -1);
-	return result;
-}
-
-- (BOOL)clearDTR
-{
-	BOOL result = (ioctl(fileDescriptor, TIOCCDTR) != -1);
-	return result;
-}
-
-
-// read and write serial port settings through a dictionary
-
-- (void)buildOptionsDictionary
-{
-	[optionsDictionary removeAllObjects];
-	[optionsDictionary setObject:[self name] forKey:AMSerialOptionServiceName];
-	[optionsDictionary setObject:[NSString stringWithFormat:@"%d", [self speed]] forKey:AMSerialOptionSpeed];
-	[optionsDictionary setObject:[NSString stringWithFormat:@"%ul", [self dataBits]] forKey:AMSerialOptionDataBits];
-	switch ([self parity]) {
-		case kAMSerialParityOdd: {
-			[optionsDictionary setObject:@"Odd" forKey:AMSerialOptionParity];
-			break;
-		}
-		case kAMSerialParityEven: {
-			[optionsDictionary setObject:@"Even" forKey:AMSerialOptionParity];
-			break;
-		}
-		default:;
-	}
-	
-	[optionsDictionary setObject:[NSString stringWithFormat:@"%d", [self stopBits]] forKey:AMSerialOptionStopBits];
-	if ([self RTSInputFlowControl])
-		[optionsDictionary setObject:@"RTS" forKey:AMSerialOptionInputFlowControl];
-	if ([self DTRInputFlowControl])
-		[optionsDictionary setObject:@"DTR" forKey:AMSerialOptionInputFlowControl];
-	
-	if ([self CTSOutputFlowControl])
-		[optionsDictionary setObject:@"CTS" forKey:AMSerialOptionOutputFlowControl];
-	if ([self DSROutputFlowControl])
-		[optionsDictionary setObject:@"DSR" forKey:AMSerialOptionOutputFlowControl];
-	if ([self CAROutputFlowControl])
-		[optionsDictionary setObject:@"CAR" forKey:AMSerialOptionOutputFlowControl];
-	
-	if ([self echoEnabled])
-		[optionsDictionary setObject:@"YES" forKey:AMSerialOptionEcho];
-
-	if ([self canonicalMode])
-		[optionsDictionary setObject:@"YES" forKey:AMSerialOptionCanonicalMode];
-
-}
-
-
-- (NSDictionary *)options
-{
-	// will open the port to get options if neccessary
-	if ([optionsDictionary objectForKey:AMSerialOptionServiceName] == nil) {
-		if (fileDescriptor < 0) {
-			[self open];
-			[self close];
-		}
-		[self buildOptionsDictionary];
-	}
-	return [NSMutableDictionary dictionaryWithDictionary:optionsDictionary];
-}
-
-- (void)setOptions:(NSDictionary *)newOptions
-{
-	// AMSerialOptionServiceName HAS to match! You may NOT switch ports using this
-	// method.
-	NSString *temp;
-	
-	if ([(NSString *)[newOptions objectForKey:AMSerialOptionServiceName] isEqualToString:[self name]]) {
-		[self clearError];
-		[optionsDictionary addEntriesFromDictionary:newOptions];
-		// parse dictionary
-		temp = (NSString *)[optionsDictionary objectForKey:AMSerialOptionSpeed];
-		[self setSpeed:[temp intValue]];
-		temp = (NSString *)[optionsDictionary objectForKey:AMSerialOptionDataBits];
-		[self setDataBits:[temp intValue]];
-		
-		temp = (NSString *)[optionsDictionary objectForKey:AMSerialOptionParity];
-		if (temp == nil)
-			[self setParity:kAMSerialParityNone];
-		else if ([temp isEqualToString:@"Odd"])
-			[self setParity:kAMSerialParityOdd];
-		else
-			[self setParity:kAMSerialParityEven];
-		
-		temp = (NSString *)[optionsDictionary objectForKey:AMSerialOptionStopBits];
-		int		numStopBits = [temp intValue];
-		[self setStopBits:(AMSerialStopBits)numStopBits];
-		
-		temp = (NSString *)[optionsDictionary objectForKey:AMSerialOptionInputFlowControl];
-		[self setRTSInputFlowControl:[temp isEqualToString:@"RTS"]];
-		[self setDTRInputFlowControl:[temp isEqualToString:@"DTR"]];
-		
-		temp = (NSString *)[optionsDictionary objectForKey:AMSerialOptionOutputFlowControl];
-		[self setCTSOutputFlowControl:[temp isEqualToString:@"CTS"]];
-		[self setDSROutputFlowControl:[temp isEqualToString:@"DSR"]];
-		[self setCAROutputFlowControl:[temp isEqualToString:@"CAR"]];
-		
-		temp = (NSString *)[optionsDictionary objectForKey:AMSerialOptionEcho];
-		[self setEchoEnabled:(temp != nil)];
-
-		temp = (NSString *)[optionsDictionary objectForKey:AMSerialOptionCanonicalMode];
-		[self setCanonicalMode:(temp != nil)];
-
-		[self commitChanges];
-	} else {
-#ifdef AMSerialDebug
-		NSLog(@"Error setting options for port %s (wrong port name: %s).\n", [self name], [newOptions objectForKey:AMSerialOptionServiceName]);
-#endif
-	}
-}
-
-
-- (long)speed
-{
-	return cfgetospeed(options);	// we should support cfgetispeed too
-}
-
-- (BOOL)setSpeed:(long)speed
-{
-	BOOL result = YES;
-	int errorCode = 0;
-	
-	options->c_ospeed = speed;
-	options->c_ispeed = speed;
-	
-#if defined(MAC_OS_X_VERSION_10_4) && (MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_4)
-	// Starting with Tiger, the IOSSIOSPEED ioctl can be used to set arbitrary baud rates
-	// other than those specified by POSIX. The driver for the underlying serial hardware
-	// ultimately determines which baud rates can be used. This ioctl sets both the input
-	// and output speed. 
-	
-	speed_t newSpeed = speed;
-	if (fileDescriptor >= 0) {
-		errorCode = ioctl(fileDescriptor, IOSSIOSPEED, &newSpeed);
-	} else {
-		result = NO;
-		gotError = YES;
-		lastError = EBADF; // Bad file descriptor
-	}
-#else
-	// set both the input and output speed
-	errorCode = cfsetospeed(options, speed);
-	errorCode = cfsetispeed(options, speed);
-#endif
-	if (errorCode == -1) {
-		result = NO;
-		gotError = YES;
-		lastError = errno;
-	}
-	return result;
-}
-
-
-- (unsigned long)dataBits
-{
-	return 5 + ((options->c_cflag & CSIZE) >> 8);
-	// man ... I *hate* C syntax ...
-}
-
-- (void)setDataBits:(unsigned long)bits	// 5 to 8 (5 is marked as "(pseudo)")
-{
-	// ?? options->c_oflag &= ~OPOST;
-	options->c_cflag &= ~CSIZE;
-	switch (bits) {
-		case 5:	options->c_cflag |= CS5;	// redundant since CS5 == 0
-			break;
-		case 6:	options->c_cflag |= CS6;
-			break;
-		case 7:	options->c_cflag |= CS7;
-			break;
-		case 8:	options->c_cflag |= CS8;
-			break;
-	}
-}
-
-
-- (AMSerialParity)parity
-{
-	AMSerialParity result;
-	if (options->c_cflag & PARENB) {
-		if (options->c_cflag & PARODD) {
-			result = kAMSerialParityOdd;
-		} else {
-			result = kAMSerialParityEven;
-		}
-	} else {
-		result = kAMSerialParityNone;
-	}
-	return result;
-}
-
-- (void)setParity:(AMSerialParity)newParity
-{
-	switch (newParity) {
-		case kAMSerialParityNone: {
-			options->c_cflag &= ~PARENB;
-			break;
-		}
-		case kAMSerialParityOdd: {
-			options->c_cflag |= PARENB;
-			options->c_cflag |= PARODD;
-			break;
-		}
-		case kAMSerialParityEven: {
-			options->c_cflag |= PARENB;
-			options->c_cflag &= ~PARODD;
-			break;
-		}
-	}
-}
-
-
-- (AMSerialStopBits)stopBits
-{
-	if (options->c_cflag & CSTOPB)
-		return kAMSerialStopBitsTwo;
-	else
-		return kAMSerialStopBitsOne;
-}
-
-- (void)setStopBits:(AMSerialStopBits)numBits
-{
-	if (numBits == kAMSerialStopBitsOne)
-		options->c_cflag &= ~CSTOPB;
-	else if (numBits == kAMSerialStopBitsTwo)
-		options->c_cflag |= CSTOPB;
-}
-
-
-- (BOOL)echoEnabled
-{
-	return (options->c_lflag & ECHO);
-}
-
-- (void)setEchoEnabled:(BOOL)echo
-{
-	if (echo == YES)
-		options->c_lflag |= ECHO;
-	else
-		options->c_lflag &= ~ECHO;
-}
-
-
-- (BOOL)RTSInputFlowControl
-{
-	return (options->c_cflag & CRTS_IFLOW);
-}
-
-- (void)setRTSInputFlowControl:(BOOL)rts
-{
-	if (rts == YES)
-		options->c_cflag |= CRTS_IFLOW;
-	else
-		options->c_cflag &= ~CRTS_IFLOW;
-}
-
-
-- (BOOL)DTRInputFlowControl
-{
-	return (options->c_cflag & CDTR_IFLOW);
-}
-
-- (void)setDTRInputFlowControl:(BOOL)dtr
-{
-	if (dtr == YES)
-		options->c_cflag |= CDTR_IFLOW;
-	else
-		options->c_cflag &= ~CDTR_IFLOW;
-}
-
-
-- (BOOL)CTSOutputFlowControl
-{
-	return (options->c_cflag & CCTS_OFLOW);
-}
-
-- (void)setCTSOutputFlowControl:(BOOL)cts
-{
-	if (cts == YES)
-		options->c_cflag |= CCTS_OFLOW;
-	else
-		options->c_cflag &= ~CCTS_OFLOW;
-}
-
-
-- (BOOL)DSROutputFlowControl
-{
-	return (options->c_cflag & CDSR_OFLOW);
-}
-
-- (void)setDSROutputFlowControl:(BOOL)dsr
-{
-	if (dsr == YES)
-		options->c_cflag |= CDSR_OFLOW;
-	else
-		options->c_cflag &= ~CDSR_OFLOW;
-}
-
-
-- (BOOL)CAROutputFlowControl
-{
-	return (options->c_cflag & CCAR_OFLOW);
-}
-
-- (void)setCAROutputFlowControl:(BOOL)car
-{
-	if (car == YES)
-		options->c_cflag |= CCAR_OFLOW;
-	else
-		options->c_cflag &= ~CCAR_OFLOW;
-}
-
-
-- (BOOL)hangupOnClose
-{
-	return (options->c_cflag & HUPCL);
-}
-
-- (void)setHangupOnClose:(BOOL)hangup
-{
-	if (hangup == YES)
-		options->c_cflag |= HUPCL;
-	else
-		options->c_cflag &= ~HUPCL;
-}
-
-- (BOOL)localMode
-{
-	return (options->c_cflag & CLOCAL);
-}
-
-- (void)setLocalMode:(BOOL)local
-{
-	// YES = ignore modem status lines
-	if (local == YES)
-		options->c_cflag |= CLOCAL;
-	else
-		options->c_cflag &= ~CLOCAL;
-}
-
-- (BOOL)canonicalMode
-{
-	return (options->c_lflag & ICANON);
-}
-
-- (void)setCanonicalMode:(BOOL)flag
-{
-	if (flag == YES)
-		options->c_lflag |= ICANON;
-	else
-		options->c_lflag &= ~ICANON;
-}
-
-- (char)endOfLineCharacter
-{
-	return options->c_cc[VEOL];
-}
-
-- (void)setEndOfLineCharacter:(char)eol
-{
-	options->c_cc[VEOL] = eol;
-}
-
-- (void)clearError
-{
-	// call this before changing any settings
-	gotError = NO;
-}
-
-- (BOOL)commitChanges
-{
-	// call this after using any of the setters above
-	if (gotError)
-		return NO;
-	
-	if (tcsetattr(fileDescriptor, TCSANOW, options) == -1) {
-		// something went wrong
-		gotError = YES;
-		lastError = errno;
-		return NO;
-	} else {
-		[self buildOptionsDictionary];
-		return YES;
-	}
-}
-
-- (int)errorCode
-{
-	// if -commitChanges returns NO, look here for further info
-	return lastError;
-}
-
-- (NSTimeInterval)readTimeout
-{
-    return readTimeout;
-}
-
-- (void)setReadTimeout:(NSTimeInterval)aReadTimeout
-{
-    readTimeout = aReadTimeout;
-}
-
-// private methods
-
-- (void)readTimeoutAsTimeval:(struct timeval*)timeout
-{
-	NSTimeInterval timeoutInterval = [self readTimeout];
-	double numSecs = trunc(timeoutInterval);
-	double numUSecs = (timeoutInterval-numSecs)*1000000.0;
-	timeout->tv_sec = (time_t)lrint(numSecs);
-	timeout->tv_usec = (suseconds_t)lrint(numUSecs);
-}
-
-
-@end

File ArduinoSerialXcode/ArduinoSerial/AMSerialPortAdditions.h

-//
-//  AMSerialPortAdditions.h
-//
-//  Created by Andreas on Thu May 02 2002.
-//  Copyright (c) 2001 Andreas Mayer. All rights reserved.
-//
-//  2002-10-04 Andreas Mayer
-//  - readDataInBackgroundWithTarget:selector: and writeDataInBackground: added
-//  2002-10-10 Andreas Mayer
-//	- stopWriteInBackground added
-//  2002-10-17 Andreas Mayer
-//	- numberOfWriteInBackgroundThreads added
-//  2002-10-25 Andreas Mayer
-//	- readDataInBackground and stopReadInBackground added
-//  2004-02-10 Andreas Mayer
-//    - replaced notifications for background reading/writing with direct messages to delegate
-//      see informal protocol
-//  2004-08-18 Andreas Mayer
-//	- readStringOfLength: added (suggested by Michael Beck)
-//  2006-08-16 Andreas Mayer / Sean McBride
-//	- changed interface for blocking read/write access significantly
-//	- fixed -checkRead and renamed it to -bytesAvailable
-//	- see AMSerialPort_Deprecated for old interfaces
-//  2007-10-26 Sean McBride
-//  - made code 64 bit and garbage collection clean
-
-#import "AMSDKCompatibility.h"
-
-#import <Foundation/Foundation.h>
-#import "AMSerialPort.h"
-
-
-@interface AMSerialPort (AMSerialPortAdditions)
-
-// returns the number of bytes available in the input buffer
-// Be careful how you use this information, it may be out of date just after you get it
-- (int)bytesAvailable;
-
-- (void)waitForInput:(id)target selector:(SEL)selector;
-
-
-// all blocking reads returns after [self readTimout] seconds elapse, at the latest
-- (NSData *)readAndReturnError:(NSError **)error;
-
-// returns after 'bytes' bytes are read
-- (NSData *)readBytes:(NSUInteger)bytes error:(NSError **)error;
-
-// returns when 'stopChar' is encountered
-- (NSData *)readUpToChar:(char)stopChar error:(NSError **)error;
-
-// returns after 'bytes' bytes are read or if 'stopChar' is encountered, whatever comes first
-- (NSData *)readBytes:(NSUInteger)bytes upToChar:(char)stopChar error:(NSError **)error;
-
-// data read will be converted into an NSString, using the given encoding
-// NOTE: encodings that take up more than one byte per character may fail if only a part of the final string was received
-- (NSString *)readStringUsingEncoding:(NSStringEncoding)encoding error:(NSError **)error;
-
-- (NSString *)readBytes:(NSUInteger)bytes usingEncoding:(NSStringEncoding)encoding error:(NSError **)error;
-
-// NOTE: 'stopChar' has to be a byte value, using the given encoding; you can not wait for an arbitrary character from a multi-byte encoding
-- (NSString *)readUpToChar:(char)stopChar usingEncoding:(NSStringEncoding)encoding error:(NSError **)error;
-
-- (NSString *)readBytes:(NSUInteger)bytes upToChar:(char)stopChar usingEncoding:(NSStringEncoding)encoding error:(NSError **)error;
-
-// write to the serial port; NO if an error occured
-- (BOOL)writeData:(NSData *)data error:(NSError **)error;
-
-- (BOOL)writeString:(NSString *)string usingEncoding:(NSStringEncoding)encoding error:(NSError **)error;
-
-
-- (void)readDataInBackground;
-//
-// Will send serialPortReadData: to delegate
-// the dataDictionary object will contain these entries:
-// 1. "serialPort": the AMSerialPort object that sent the message
-// 2. "data": (NSData *)data - received data
-
-- (void)stopReadInBackground;
-
-- (void)writeDataInBackground:(NSData *)data;
-//
-// Will send serialPortWriteProgress: to delegate if task lasts more than
-// approximately three seconds.
-// the dataDictionary object will contain these entries:
-// 1. "serialPort": the AMSerialPort object that sent the message
-// 2. "value": (NSNumber *)value - bytes sent
-// 3. "total": (NSNumber *)total - bytes total
-
-- (void)stopWriteInBackground;
-
-- (int)numberOfWriteInBackgroundThreads;
-
-
-@end

File ArduinoSerialXcode/ArduinoSerial/AMSerialPortAdditions.m

-//
-//  AMSerialPortAdditions.m
-//
-//  Created by Andreas on Thu May 02 2002.
-//  Copyright (c) 2001 Andreas Mayer. All rights reserved.
-//
-//  2002-07-02 Andreas Mayer
-//	- initialize buffer in readString
-//  2002-10-04 Andreas Mayer
-//  - readDataInBackgroundWithTarget:selector: and writeDataInBackground: added
-//  2002-10-10 Andreas Mayer
-//	- stopWriteInBackground added
-//	- send notifications about sent data through distributed notification center
-//  2002-10-17 Andreas Mayer
-//	- numberOfWriteInBackgroundThreads added
-//	- if total write time will exceed 3 seconds, send
-//		CommXWriteInBackgroundProgressNotification without delay
-//  2002-10-25 Andreas Mayer
-//	- readDataInBackground and stopReadInBackground added
-//  2004-08-18 Andreas Mayer
-//	- readStringOfLength: added (suggested by Michael Beck)
-//  2005-04-11 Andreas Mayer
-//	-  attempt at a fix for readDataInBackgroundThread - fileDescriptor could already be closed
-//		(thanks to David Bainbridge for the bug report) does not work as of yet
-//  2007-10-26 Sean McBride
-//  - made code 64 bit and garbage collection clean
-
-
-#import "AMSDKCompatibility.h"
-
-#import <sys/ioctl.h>
-#import <sys/filio.h>
-
-#import "AMSerialPortAdditions.h"
-#import "AMSerialErrors.h"
-
-
-@interface AMSerialPort (AMSerialPortAdditionsPrivate)
-- (void)readDataInBackgroundThread;
-- (void)writeDataInBackgroundThread:(NSData *)data;
-- (id)am_readTarget;
-- (void)am_setReadTarget:(id)newReadTarget;
-- (NSData *)readAndStopAfterBytes:(BOOL)stopAfterBytes bytes:(NSUInteger)bytes stopAtChar:(BOOL)stopAtChar stopChar:(char)stopChar error:(NSError **)error;
-- (void)reportProgress:(NSUInteger)progress dataLen:(NSUInteger)dataLen;
-@end
-
-
-@implementation AMSerialPort (AMSerialPortAdditions)
-
-
-// ============================================================
-#pragma mark -
-#pragma mark blocking IO
-// ============================================================
-
-- (void)doRead:(NSTimer *)timer
-{
-	(void)timer;
-	
-#ifdef AMSerialDebug
-	NSLog(@"doRead");
-#endif
-	int res;
-	struct timeval timeout;
-	if (fileDescriptor >= 0) {
-		FD_ZERO(readfds);
-		FD_SET(fileDescriptor, readfds);
-		[self readTimeoutAsTimeval:&timeout];
-		res = select(fileDescriptor+1, readfds, nil, nil, &timeout);
-		if (res >= 1) {
-			NSString *readStr = [self readStringUsingEncoding:NSUTF8StringEncoding error:NULL];
-			[[self am_readTarget] performSelector:am_readSelector withObject:readStr];
-			[self am_setReadTarget:nil];
-		} else {
-			[NSTimer scheduledTimerWithTimeInterval:0.1 target:self selector:@selector(doRead:) userInfo:self repeats:NO];
-		}
-	} else {
-		// file already closed
-		[self am_setReadTarget:nil];
-	}
-}
-
-// all blocking reads returns after [self readTimout] seconds elapse, at the latest
-- (NSData *)readAndReturnError:(NSError **)error
-{
-	NSData *result = [self readAndStopAfterBytes:NO bytes:0 stopAtChar:NO stopChar:0 error:error];
-	return result;
-}
-
-// returns after 'bytes' bytes are read
-- (NSData *)readBytes:(NSUInteger)bytes error:(NSError **)error
-{
-	NSData *result = [self readAndStopAfterBytes:YES bytes:bytes stopAtChar:NO stopChar:0 error:error];
-	return result;
-}
-
-// returns when 'stopChar' is encountered
-- (NSData *)readUpToChar:(char)stopChar error:(NSError **)error
-{
-	NSData *result = [self readAndStopAfterBytes:NO bytes:0 stopAtChar:YES stopChar:stopChar error:error];
-	return result;
-}
-
-// returns after 'bytes' bytes are read or if 'stopChar' is encountered, whatever comes first
-- (NSData *)readBytes:(NSUInteger)bytes upToChar:(char)stopChar error:(NSError **)error
-{
-	NSData *result = [self readAndStopAfterBytes:YES bytes:bytes stopAtChar:YES stopChar:stopChar error:error];
-	return result;
-}
-
-// data read will be converted into an NSString, using the given encoding
-// NOTE: encodings that take up more than one byte per character may fail if only a part of the final string was received
-- (NSString *)readStringUsingEncoding:(NSStringEncoding)encoding error:(NSError **)error
-{
-	NSString *result = nil;
-	NSData *data = [self readAndStopAfterBytes:NO bytes:0 stopAtChar:NO stopChar:0 error:error];
-	if (data) {
-		result = [[[NSString alloc] initWithData:data encoding:encoding] autorelease];
-	}
-	return result;
-}
-
-- (NSString *)readBytes:(NSUInteger)bytes usingEncoding:(NSStringEncoding)encoding error:(NSError **)error
-{
-	NSString *result = nil;
-	NSData *data = [self readAndStopAfterBytes:YES bytes:bytes stopAtChar:NO stopChar:0 error:error];
-	if (data) {
-		result = [[[NSString alloc] initWithData:data encoding:encoding] autorelease];
-	}
-	return result;
-}
-
-// NOTE: 'stopChar' has to be a byte value, using the given encoding; you can not wait for an arbitrary character from a multi-byte encoding
-- (NSString *)readUpToChar:(char)stopChar usingEncoding:(NSStringEncoding)encoding error:(NSError **)error
-{
-	NSString *result = nil;
-	NSData *data = [self readAndStopAfterBytes:NO bytes:0 stopAtChar:YES stopChar:stopChar error:error];
-	if (data) {
-		result = [[[NSString alloc] initWithData:data encoding:encoding] autorelease];
-	}
-	return result;
-}
-
-- (NSString *)readBytes:(NSUInteger)bytes upToChar:(char)stopChar usingEncoding:(NSStringEncoding)encoding error:(NSError **)error
-{
-	NSString *result = nil;
-	NSData *data = [self readAndStopAfterBytes:YES bytes:bytes stopAtChar:YES stopChar:stopChar error:error];
-	if (data) {
-		result = [[[NSString alloc] initWithData:data encoding:encoding] autorelease];
-	}
-	return result;
-}
-
-
-// write to the serial port; NO if an error occured
-- (BOOL)writeData:(NSData *)data error:(NSError **)error
-{
-	BOOL result = NO;
-
-	const char *dataBytes = (const char*)[data bytes];
-	NSUInteger dataLen = [data length];
-	ssize_t bytesWritten = 0;
-	int errorCode = kAMSerialErrorNone;
-	if (dataBytes && (dataLen > 0)) {
-		bytesWritten = write(fileDescriptor, dataBytes, dataLen);
-		if (bytesWritten < 0) {
-			errorCode = kAMSerialErrorFatal;
-		} else if ((NSUInteger)bytesWritten == dataLen) {
-			result = YES;
-		} else {
-			errorCode = kAMSerialErrorOnlySomeDataWritten;
-		}
-	} else {
-		errorCode = kAMSerialErrorNoDataToWrite;
-	}
-	if (error) {
-		NSDictionary *userInfo = nil;
-		if (bytesWritten > 0) {
-			NSNumber* bytesWrittenNum = [NSNumber numberWithUnsignedLongLong:bytesWritten];
-			userInfo = [NSDictionary dictionaryWithObject:bytesWrittenNum forKey:@"bytesWritten"];
-		}
-		*error = [NSError errorWithDomain:AMSerialErrorDomain code:errorCode userInfo:userInfo];
-	}
-		
-	return result;
-}
-
-- (BOOL)writeString:(NSString *)string usingEncoding:(NSStringEncoding)encoding error:(NSError **)error
-{
-	NSData *data = [string dataUsingEncoding:encoding];
-	return [self writeData:data error:error];
-}
-
-- (int)bytesAvailable
-{
-#ifdef AMSerialDebug
-	NSLog(@"bytesAvailable");
-#endif
-
-	// yes, that cast is correct.  ioctl() is declared to take a char* but should be void* as really it
-	// depends on the 2nd parameter.  Ahhh, I love crappy old UNIX APIs :)
-	int result = 0;
-	int err = ioctl(fileDescriptor, FIONREAD, (char *)&result);
-	if (err != 0) {
-		result = -1;
-	}
-	return result;
-}
-
-
-- (void)waitForInput:(id)target selector:(SEL)selector
-{
-#ifdef AMSerialDebug
-	NSLog(@"waitForInput");
-#endif
-	[self am_setReadTarget:target];
-	am_readSelector = selector;
-	[NSTimer scheduledTimerWithTimeInterval:0.1 target:self selector:@selector(doRead:) userInfo:self repeats:NO];
-}
-
-// ============================================================
-#pragma mark -
-#pragma mark threaded IO
-// ============================================================
-
-- (void)readDataInBackground
-{
-#ifdef AMSerialDebug
-	NSLog(@"readDataInBackground");
-#endif
-	if (delegateHandlesReadInBackground) {
-		countReadInBackgroundThreads++;
-		[NSThread detachNewThreadSelector:@selector(readDataInBackgroundThread) toTarget:self withObject:nil];
-	} else {
-		// ... throw exception?
-	}
-}
-
-- (void)stopReadInBackground
-{
-#ifdef AMSerialDebug
-	NSLog(@"stopReadInBackground");
-#endif
-	stopReadInBackground = YES;
-}
-
-- (void)writeDataInBackground:(NSData *)data
-{
-#ifdef AMSerialDebug
-	NSLog(@"writeDataInBackground");
-#endif
-	if (delegateHandlesWriteInBackground) {
-		countWriteInBackgroundThreads++;
-		[NSThread detachNewThreadSelector:@selector(writeDataInBackgroundThread:) toTarget:self withObject:data];
-	} else {
-		// ... throw exception?
-	}
-}
-
-- (void)stopWriteInBackground
-{
-#ifdef AMSerialDebug
-	NSLog(@"stopWriteInBackground");
-#endif
-	stopWriteInBackground = YES;
-}
-
-- (int)numberOfWriteInBackgroundThreads
-{
-	return countWriteInBackgroundThreads;
-}
-
-
-@end
-
-#pragma mark -
-
-@implementation AMSerialPort (AMSerialPortAdditionsPrivate)
-
-// ============================================================
-#pragma mark -
-#pragma mark threaded methods
-// ============================================================
-
-- (void)readDataInBackgroundThread
-{
-	NSData *data = nil;
-	void *localBuffer;
-	ssize_t bytesRead = 0;
-	fd_set *localReadFDs = NULL;
-
-	[readLock lock];	// read in sequence
-	//NSLog(@"readDataInBackgroundThread - [readLock lock]");
-
-	localBuffer = malloc(AMSER_MAXBUFSIZE);
-	stopReadInBackground = NO;
-	NSAutoreleasePool *localAutoreleasePool = [[NSAutoreleasePool alloc] init];
-	[closeLock lock];
-	if ((fileDescriptor >= 0) && (!stopReadInBackground)) {
-		//NSLog(@"readDataInBackgroundThread - [closeLock lock]");
-		localReadFDs = (fd_set*)malloc(sizeof(fd_set));
-		FD_ZERO(localReadFDs);
-		FD_SET(fileDescriptor, localReadFDs);
-		[closeLock unlock];
-		//NSLog(@"readDataInBackgroundThread - [closeLock unlock]");
-		int res = select(fileDescriptor+1, localReadFDs, nil, nil, nil); // timeout);
-		if ((res >= 1) && (fileDescriptor >= 0)) {
-			//bytesRead = read(fileDescriptor, localBuffer, AMSER_MAXBUFSIZE);
-		}
-		//FIXME: This was modified on 3-20-09 by Pat O'Keefe for a particular application...swap comments for normal operation
-		//data = [NSData dataWithBytes:localBuffer length:bytesRead];
-		data = [self readUpToChar:'\n' error:NULL];
-		[delegate performSelectorOnMainThread:@selector(serialPortReadData:) withObject:[NSDictionary dictionaryWithObjectsAndKeys: self, @"serialPort", data, @"data", nil] waitUntilDone:YES];//was NO
-	} else {
-		[closeLock unlock];
-	}
-	[localAutoreleasePool release];
-	if (localReadFDs)
-		free(localReadFDs);
-	if (localBuffer)
-		free(localBuffer);
-
-	countReadInBackgroundThreads--;
-
-	[readLock unlock];
-	//NSLog(@"readDataInBackgroundThread - [readLock unlock]");
-
-}
-
-/* new version - does not work yet
-- (void)readDataInBackgroundThread
-{
-	NSData *data = nil;
-	void *localBuffer;
-	int bytesRead = 0;
-	fd_set *localReadFDs;
-
-#ifdef AMSerialDebug
-	NSLog(@"readDataInBackgroundThread: %@", [NSThread currentThread]);
-#endif
-	localBuffer = malloc(AMSER_MAXBUFSIZE);
-	[stopReadInBackgroundLock lock];
-	stopReadInBackground = NO;
-	//NSLog(@"stopReadInBackground set to NO: %@", [NSThread currentThread]);
-	[stopReadInBackgroundLock unlock];
-	//NSLog(@"attempt readLock: %@", [NSThread currentThread]);
-	[readLock lock];	// write in sequence
-	//NSLog(@"readLock locked: %@", [NSThread currentThread]);
-	//NSLog(@"attempt closeLock: %@", [NSThread currentThread]);
-	[closeLock lock];
-	//NSLog(@"closeLock locked: %@", [NSThread currentThread]);
-	if (!stopReadInBackground && (fileDescriptor >= 0)) {
-		NSAutoreleasePool *localAutoreleasePool = [[NSAutoreleasePool alloc] init];
-		localReadFDs = malloc(sizeof(*localReadFDs));
-		FD_ZERO(localReadFDs);
-		FD_SET(fileDescriptor, localReadFDs);
-		int res = select(fileDescriptor+1, localReadFDs, nil, nil, nil); // timeout);
-		if (res >= 1) {
-#ifdef AMSerialDebug
-			NSLog(@"attempt read: %@", [NSThread currentThread]);
-#endif
-			bytesRead = read(fileDescriptor, localBuffer, AMSER_MAXBUFSIZE);
-		}
-#ifdef AMSerialDebug
-		NSLog(@"data read: %@", [NSThread currentThread]);
-#endif
-		data = [NSData dataWithBytes:localBuffer length:bytesRead];
-#ifdef AMSerialDebug
-		NSLog(@"send AMSerialReadInBackgroundDataMessage");
-#endif
-		[delegate performSelectorOnMainThread:@selector(serialPortReadData:) withObject:[NSDictionary dictionaryWithObjectsAndKeys: self, @"serialPort", data, @"data", nil] waitUntilDone:NO];
-		free(localReadFDs);
-		[localAutoreleasePool release];
-	} else {
-#ifdef AMSerialDebug
-		NSLog(@"read stopped: %@", [NSThread currentThread]);
-#endif
-	}
-
-	[closeLock unlock];
-	//NSLog(@"closeLock unlocked: %@", [NSThread currentThread]);
-	[readLock unlock];
-	//NSLog(@"readLock unlocked: %@", [NSThread currentThread]);
-	[countReadInBackgroundThreadsLock lock];
-	countReadInBackgroundThreads--;
-	[countReadInBackgroundThreadsLock unlock];
-	
-	free(localBuffer);
-}
-*/
-
-- (void)writeDataInBackgroundThread:(NSData *)data
-{
-	
-#ifdef AMSerialDebug
-	NSLog(@"writeDataInBackgroundThread");
-#endif
-	void *localBuffer;
-	NSUInteger pos;
-	NSUInteger bufferLen;
-	NSUInteger dataLen;
-	ssize_t written;
-	NSDate *nextNotificationDate;
-	BOOL notificationSent = NO;
-	long speed;
-	long estimatedTime;
-	BOOL error = NO;
-	
-	NSAutoreleasePool *localAutoreleasePool = [[NSAutoreleasePool alloc] init];
-
-	[data retain];
-	localBuffer = malloc(AMSER_MAXBUFSIZE);
-	stopWriteInBackground = NO;
-	[writeLock lock];	// write in sequence
-	pos = 0;
-	dataLen = [data length];
-	speed = [self speed];
-	estimatedTime = (dataLen*8)/speed;
-	if (estimatedTime > 3) { // will take more than 3 seconds
-		notificationSent = YES;
-		[self reportProgress:pos dataLen:dataLen];
-		nextNotificationDate = [NSDate dateWithTimeIntervalSinceNow:1.0];
-	} else {
-		nextNotificationDate = [NSDate dateWithTimeIntervalSinceNow:2.0];
-	}
-	while (!stopWriteInBackground && (pos < dataLen) && !error) {
-		bufferLen = MIN(AMSER_MAXBUFSIZE, dataLen-pos);
-
-		[data getBytes:localBuffer range:NSMakeRange(pos, bufferLen)];
-		written = write(fileDescriptor, localBuffer, bufferLen);
-		error = (written == 0); // error condition
-		if (error)
-			break;
-		pos += written;
-
-		if ([(NSDate *)[NSDate date] compare:nextNotificationDate] == NSOrderedDescending) {
-			if (notificationSent || (pos < dataLen)) { // not for last block only
-				notificationSent = YES;
-				[self reportProgress:pos dataLen:dataLen];
-				nextNotificationDate = [NSDate dateWithTimeIntervalSinceNow:1.0];
-			}
-		}
-	}
-	if (notificationSent) {
-		[self reportProgress:pos dataLen:dataLen];
-	}
-	stopWriteInBackground = NO;
-	[writeLock unlock];
-	countWriteInBackgroundThreads--;
-	
-	free(localBuffer);
-	[data release];
-	[localAutoreleasePool release];
-}
-
-- (id)am_readTarget
-{
-	return am_readTarget; 
-}
-
-- (void)am_setReadTarget:(id)newReadTarget
-{
-	if (am_readTarget != newReadTarget) {
-		[newReadTarget retain];
-		[am_readTarget release];
-		am_readTarget = newReadTarget;
-	}
-}
-
-// Low-level blocking read method.
-// This method reads from the serial port and blocks as necessary, it returns when:
-//  - [self readTimeout] seconds has elapsed
-//  - if stopAfterBytes is YES, when 'bytesToRead' bytes have been read
-//  - if stopAtChar is YES, when 'stopChar' is found at the end of the read buffer
-//  - a fatal error occurs
-//
-// Upon return: as long as some data was actually read, and no serious error occured, an autoreleased NSData
-// object with that data is created and returned, otherwise nil is.
-- (NSData *)readAndStopAfterBytes:(BOOL)stopAfterBytes bytes:(NSUInteger)bytesToRead stopAtChar:(BOOL)stopAtChar stopChar:(char)stopChar error:(NSError **)error
-{
-	NSData *result = nil;
-	
-	struct timeval timeout;
-	NSUInteger bytesRead = 0;
-	BOOL stop = NO;
-	int errorCode = kAMSerialErrorNone;
-	int endCode = kAMSerialEndOfStream;
-	NSError *underlyingError = nil;
-	
-	// Note the time that we start
-	NSDate *startTime = [NSDate date];
-	
-	// How long, in total, do we block before timing out?
-	NSTimeInterval totalTimeout = [self readTimeout];
-
-	// This value will be decreased each time through the loop
-	NSTimeInterval remainingTimeout = totalTimeout;
-	
-	while (!stop) {
-		if (remainingTimeout <= 0.0) {
-			stop = YES;
-			errorCode = kAMSerialErrorTimeout;
-			break;
-		} else {
-			// Convert from NSTimeInterval to struct timeval
-			double numSecs = trunc(remainingTimeout);
-			double numUSecs = (remainingTimeout-numSecs)*1000000.0;
-			timeout.tv_sec = (time_t)lrint(numSecs);
-			timeout.tv_usec = (suseconds_t)lrint(numUSecs);
-#ifdef AMSerialDebug
-			NSLog(@"timeout: %fs = %ds and %dus", remainingTimeout, timeout.tv_sec, timeout.tv_usec);
-#endif
-			
-			// If the remaining time is so small that it has rounded to zero, bump it up to 1 microsec.
-			// Why?  Because passing a zeroed timeval to select() indicates that we want to poll, but we don't.
-			if ((timeout.tv_sec == 0) && (timeout.tv_usec == 0)) {
-				timeout.tv_usec = 1;
-			}
-			FD_ZERO(readfds);
-			FD_SET(fileDescriptor, readfds);
-			[self readTimeoutAsTimeval:&timeout];
-			int selectResult = select(fileDescriptor+1, readfds, NULL, NULL, &timeout);
-			if (selectResult == -1) {
-				stop = YES;
-				errorCode = kAMSerialErrorFatal;
-				break;
-			} else if (selectResult == 0) {
-				stop = YES;
-				errorCode = kAMSerialErrorTimeout;
-				break;
-			} else {
-				size_t	sizeToRead;
-				if (stopAfterBytes) {
-					sizeToRead = (MIN(bytesToRead, AMSER_MAXBUFSIZE))-bytesRead;
-				} else {
-					sizeToRead = AMSER_MAXBUFSIZE-bytesRead;
-				}
-				ssize_t	readResult = read(fileDescriptor, buffer+bytesRead, sizeToRead);
-				if (readResult > 0) {
-					bytesRead += readResult;
-					if (stopAfterBytes) {
-						if (bytesRead == bytesToRead) {
-							stop = YES;
-							endCode = kAMSerialStopLengthReached;
-							break;
-						} else if (bytesRead > bytesToRead) {
-							stop = YES;
-							endCode = kAMSerialStopLengthExceeded;
-							break;
-						}
-					}
-					if (stopAtChar && (buffer[bytesRead-1] == stopChar)) {
-						stop = YES;
-						endCode = kAMSerialStopCharReached;
-						break;
-					}
-					if (bytesRead >= AMSER_MAXBUFSIZE) {
-						stop = YES;
-						errorCode = kAMSerialErrorInternalBufferFull;
-						break;
-					}
-				} else if (readResult == 0) {
-					// Should not be possible since select() has indicated data is available
-					stop = YES;
-					errorCode = kAMSerialErrorFatal;
-					break;
-				} else {
-					stop = YES;
-					// Make underlying error
-					underlyingError = [NSError errorWithDomain:NSPOSIXErrorDomain code:readResult userInfo:nil];
-					errorCode = kAMSerialErrorFatal;
-					break;
-				}
-			}
-			
-			// Reduce the timeout value by the amount of time actually spent so far
-			remainingTimeout = totalTimeout - [[NSDate date] timeIntervalSinceDate:startTime];
-		}
-	}
-	
-	if (error) {
-		NSMutableDictionary *userInfo = [NSMutableDictionary dictionary];
-		[userInfo setObject:[NSNumber numberWithUnsignedLongLong:bytesRead] forKey:@"bytesRead"];
-		if (underlyingError) {
-			[userInfo setObject:underlyingError forKey:NSUnderlyingErrorKey];
-		}
-		if (errorCode == kAMSerialErrorNone) {
-			[userInfo setObject:[NSNumber numberWithInt:endCode] forKey:@"endCode"];
-		}
-		*error = [NSError errorWithDomain:AMSerialErrorDomain code:errorCode userInfo:userInfo];
-	}
-	if ((bytesRead > 0) && (errorCode != kAMSerialErrorFatal)) {
-		result = [NSData dataWithBytes:buffer length:bytesRead];
-	}
-	
-	return result;
-}
-
-- (void)reportProgress:(NSUInteger)progress dataLen:(NSUInteger)dataLen
-{
-#ifdef AMSerialDebug
-	NSLog(@"send AMSerialWriteInBackgroundProgressMessage");
-#endif
-	[delegate performSelectorOnMainThread:@selector(serialPortWriteProgress:) withObject:
-		[NSDictionary dictionaryWithObjectsAndKeys:
-			self, @"serialPort",
-			[NSNumber numberWithUnsignedLongLong:progress], @"value",
-			[NSNumber numberWithUnsignedLongLong:dataLen], @"total", nil]
-		waitUntilDone:NO];
-}
-
-@end

File ArduinoSerialXcode/ArduinoSerial/AMSerialPortList.h

-//