Reputation: 111
I am writing an application that is supposed to control a projector from the desktop of a Mac Mini. I am writing the application in Objective-C using Xcode and termios.h to talk to the serial port. I am connecting from a USB-to-Serial adapter and I know the drivers are installed correctly because I can send HEX commands to the projector to control its functions.
I have code written that I believe should open the serial port, connect to the projector, send codes, and disconnect:
@implementation Projector
@synthesize helpUrl = _helpUrl;
@synthesize projectorConnected;
- (id)init {
//[self connectProjector];
if (TRUE == projectorConnected) {
// Success!
}
else {
// Error!
}
return self;
}
- (id)initWithHelpUrl:(NSString *)helpUrlString {
[self setHelpUrl:helpUrlString];
return [self init];
}
- (void)connectProjector {
[self setProjectorConnected:FALSE];
NSString *deviceNameString = @"/dev/tty.usbserial";
speed_t baudRate = B19200;
serialFileDescriptor = [self openSerialPort:[deviceNameString cStringUsingEncoding:NSASCIIStringEncoding] baud:baudRate];
if (serialFileDescriptor == -1) {
NSLog(@"Error opening serial port file!");
}
_fileHandle = [[NSFileHandle alloc] initWithFileDescriptor: serialFileDescriptor];
//[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(receiveSerialMessage:) name:NSFileHandleReadCompletionNotification object:_fileHandle];
//[_fileHandle readInBackgroundAndNotify];
// [self closeSerialPort];
}
- (int)openSerialPort:(const char *)serialPortFile baud:(speed_t)baudRate {
struct termios toptions;
int fd;
fd = open(serialPortFile, O_RDWR | O_NOCTTY | O_NDELAY);
if (fd == -1) {
perror("init_serialport: Unable to open port ");
return -1;
}
if (tcgetattr(fd, &gOriginalTTYAttrs) < 0) {
perror("init_serialport: Couldn't get term attributes");
return -1;
}
toptions = gOriginalTTYAttrs;
cfsetispeed(&toptions, baudRate);
cfsetospeed(&toptions, baudRate);
toptions.c_cflag &= PARENB;
toptions.c_cflag &= CSTOPB;
toptions.c_cflag &= CSIZE;
toptions.c_cflag |= CS8;
toptions.c_cflag &= CRTSCTS;
toptions.c_cflag |= CREAD | CLOCAL;
toptions.c_iflag &= (IXON | IXOFF | IXANY);
toptions.c_lflag &= (ICANON | ECHO | ECHOE | ISIG);
toptions.c_oflag &= OPOST;
// see: http://unixwiz.net/techtips/termios-vmin-vtime.html
toptions.c_cc[VMIN] = 0;
toptions.c_cc[VTIME] = 20;
if( tcsetattr(fd, TCSANOW, &toptions) < 0) {
perror("init_serialport: Couldn't set term attributes");
return -1;
}
return fd;
}
- (void)sendSerialMessage:(NSString *)message {
NSString *deviceNameString = @"/dev/tty.usbserial";
speed_t baudRate = B19200;
serialFileDescriptor = [self openSerialPort:[deviceNameString cStringUsingEncoding:NSASCIIStringEncoding] baud:baudRate];
if (serialFileDescriptor == -1) {
NSLog(@"Error opening serial port file!");
}
_fileHandle = [[NSFileHandle alloc] initWithFileDescriptor: serialFileDescriptor];
//[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(receiveSerialMessage:) name:NSFileHandleReadCompletionNotification object:_fileHandle];
//[_fileHandle readInBackgroundAndNotify];
// convert message string into NSData
NSString *dataString = [message stringByReplacingOccurrencesOfString:@" " withString:@""];
NSMutableData *dataToSend = [[NSMutableData alloc] init];
unsigned char whole_byte;
char byte_chars[3] = {'\0','\0','\0'};
int i;
for (i=0; i < 6; i++) {
byte_chars[0] = [dataString characterAtIndex:i*2];
byte_chars[1] = [dataString characterAtIndex:i*2+1];
whole_byte = strtol(byte_chars, NULL, 16);
[dataToSend appendBytes:&whole_byte length:1];
}
// write to the serial port file
[_fileHandle writeData:dataToSend];
sleep(10);
[self closeSerialPort];
}
- (void)receiveSerialMessage:(NSNotification *)notification {
NSData* messageData = [[notification userInfo] objectForKey:NSFileHandleNotificationDataItem];
if ( [messageData length] == 0 ) {
[_fileHandle readInBackgroundAndNotify];
return;
}
NSString* receivedMessage = [[NSString alloc] initWithData:messageData encoding:NSASCIIStringEncoding];
[[NSNotificationCenter defaultCenter] postNotificationName:@"serialMessageReceived" object:receivedMessage];
[_fileHandle readInBackgroundAndNotify];
}
// Given the file descriptor for a serial device, close that device.
- (void)closeSerialPort {
///*
// Block until all written output has been sent from the device.
// Note that this call is simply passed on to the serial device driver.
// See tcsendbreak(3) ("man 3 tcsendbreak") for details.
if (tcdrain(serialFileDescriptor) == -1) {
NSLog(@"Error waiting for drain - %s(%d).", strerror(errno), errno);
}
// Traditionally it is good practice to reset a serial port back to
// the state in which you found it. This is why the original termios struct
// was saved.
if (tcsetattr(serialFileDescriptor, TCSANOW, &gOriginalTTYAttrs) == -1) {
NSLog(@"Error resetting tty attributes - %s(%d).\n", strerror(errno), errno);
}
//*/
close(serialFileDescriptor);
serialFileDescriptor = -1;
_fileHandle = nil;
}
- (BOOL)powerOn {
[self sendSerialMessage:@"02 00 00 00 00 02"];
// TODO: change to success/failure
return TRUE;
}
- (BOOL)powerOff {
[self sendSerialMessage:@"02 01 00 00 00 03"];
// TODO: change to success/failure
return TRUE;
}
- (BOOL)blankScreen {
[self sendSerialMessage:@"02 10 00 00 00 12"];
// TODO: change to success/failure
return TRUE;
}
- (BOOL)showScreen {
[self sendSerialMessage:@"02 11 00 00 00 13"];
// TODO: change to success/failure
return TRUE;
}
- (BOOL)requestHelp {
NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:_helpUrl]];
// Perform request and get data back
NSData *responseData = [NSURLConnection sendSynchronousRequest:request returningResponse:nil error:nil];
if (nil != responseData) {
// TODO change this to check for response code is 200?
return TRUE;
/*
// get String value of response
NSString *returnString = [[NSString alloc] initWithData:responseData encoding:NSUTF8StringEncoding];
// DEBUG
NSLog(@"Return string: %@", returnString);
// TODO: better way to do this?
NSString *successString = @"{\"status\":true}";
if ([returnString isEqualToString:successString]) {
// success
NSLog(@"Success!");
return TRUE;
}
else {
NSLog(@"Error bad response");
}
*/
}
else {
NSLog(@"Error: no response");
}
// return faliure!
return FALSE;
}
@end
I was wondering where I am going wrong though because when I run the program it hangs.
Upvotes: 2
Views: 1919
Reputation: 21373
I've seen serious problems with Prolific's USB to serial adapter driver, particularly under Mac OS X Lion. You can try this alternative driver It's based on the osx-pl2303 open source driver code.
Personally, I would recommend getting a different USB to serial adapter. I like Keyspan's USA-19HS adapter and have never had a problem with their drivers on any version of Mac OS X. I've heard good things about FTDI too, but don't have personal experience with adapters based on that chipset.
See my earlier question for more info about this problem.
Upvotes: 1