iPhone/iPod Touch Serial Communication How-To
iPhone and iPod Touch has an UART interface for serial communication, and the device file of serial port on iPhone/iPod Touch is /dev/tty.iap.
Since iPhone OS is based on Mac OS X, 4.4 BSD extensions are available.
You should note that index numbers of c_cc array declared in termios.h doesn’t much termios(4) explanations in 4th Berkeley Distribution man page on Leopard.
Collin Meyer wrote a good tutorial “iPhone/iPod Touch Serial Port Tutorial” about non-canonical serial communication on iPhone.
His code is almost all right, but I can’t agree in some points:
- unnecessary definition after cfmakeraw
- doesn’t revert original terminal settings
- enables obsolete hacks c_oflag (cf. Unix Programming Frequently Asked Question)
Accessing via UART interface may damage your iPhone/iPod Touch, so try at your own risk.
Basic termios settings for non-canonical mode may be as follows:
cfmakeraw(struct termios*); c_iflag = 0; c_oflag = 0; c_cflag |= (CREAD|HUPCL); c_cflag &= ~CSTOPB; c_cc[VMIN] = ???>1; (cf. http://www.sbin.org/doc/unix-faq/programmer/faq_4.html#SEC60) c_cc[VTIME] = ???; cfsetspeed(struct terios*, speed_t);
The following is a simple chat program with non-canonical mode communication.
#include <stdio.h>
#include <stdlib.h>
#include <termios.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
int main (int argc, const char * argv[]) {
struct termios org_termios_s;
struct termios my_termios_s;
struct termios org_termios_c;
struct termios my_termios_c;
int fd = -1;
char buf_r[128], buf_s[128];
int i, j;
// Open serial port
if((fd = open("/dev/tty.iap", O_RDWR | O_NOCTTY | O_NONBLOCK)) == -1) {
perror("open");
exit(EXIT_FAILURE);
}
if(ioctl(fd, TIOCEXCL) == -1) {
perror("TIOCEXCL");
close(fd);
exit(EXIT_FAILURE);
}
if(fcntl(fd, F_SETFL, 0) == -1) {
perror("clear O_NONBLOCK");
close(fd);
exit(EXIT_FAILURE);
}
// Get original termios
if(tcgetattr(fd, &org_termios_s) == -1) {
perror("get serial original termios");
close(fd);
exit(EXIT_FAILURE);
}
if(tcgetattr(fileno(stdin), &org_termios_c) == -1) {
perror("get console original termios");
close(fd);
exit(EXIT_FAILURE);
}
// Make my termios
my_termios_s = org_termios_s;
cfmakeraw(&my_termios_s);
my_termios_s.c_iflag = 0;
my_termios_s.c_oflag = 0;
my_termios_s.c_cflag |= (CREAD|HUPCL);
my_termios_s.c_cflag &= ~CSTOPB;
my_termios_s.c_cc[VMIN] = 0; //can't detect modem hungups (cf. http://www.sbin.org/doc/unix-faq/programmer/faq_4.html#SEC60)
my_termios_s.c_cc[VTIME] = 0;
cfsetspeed(&my_termios_s, B19200);
my_termios_c = org_termios_c;
cfmakeraw(&my_termios_c);
my_termios_c.c_iflag = 0;
my_termios_c.c_oflag = 0;
my_termios_c.c_cflag |= (CREAD|HUPCL);
my_termios_c.c_cflag &= ~CSTOPB;
my_termios_c.c_cc[VMIN] = 0;
my_termios_c.c_cc[VTIME] = 0;
// Change terminal settings
if(tcsetattr(fd, TCSANOW, &my_termios_s) == -1) {
perror("set my serial termios");
close(fd);
exit(EXIT_FAILURE);
}
if(tcsetattr(fileno(stdin), TCSANOW, &my_termios_c) == -1) {
perror("set my console termios");
close(fd);
exit(EXIT_FAILURE);
}
// Main loop
while(1) {
j=read(fd, buf_r, 128);
if(j > 0) {
for(i=0; i<j; i++) {
write(fileno(stdout), &buf_r[i], 1); //unrecommended use of write
}
}
j=read(fileno(stdin), buf_s, 128);
if (j > 0) {
if(buf_s[0] == 'Q') {
break;
}
for(i=0; i<j; i++) {
write(fd, &buf_s[i], 1); //unrecommended use of write
}
}
}
// Revert orginal terminal settings
if(tcsetattr(fd, TCSANOW, &org_termios_s) == -1) {
perror("revert serial terminal settings");
close(fd);
exit(EXIT_FAILURE);
}
if(tcsetattr(fileno(stdin), TCSANOW, &org_termios_c) == -1) {
perror("revert console terminal settings");
close(fd);
exit(EXIT_FAILURE);
}
printf("n"); // just cleanup
close(fd);
return 0;
}
Enjoy!
2件のコメント »
RSS feed for comments on this post. TrackBack URL

serial-でつながるブログリング
serialに関するブログをまとめています。
[...] これまでオフライン用に地図を取り込んでDBを作ったり,UARTでGPSモジュールをつないだりしてきたけど,MapKitが公開されたことでiPod Touchをナビにするめどはついた [...]