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:

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, &amp;org_termios_s) == -1) {
    perror("get serial original termios");
    close(fd);
    exit(EXIT_FAILURE);
  }

  if(tcgetattr(fileno(stdin), &amp;org_termios_c) == -1) {
    perror("get console original termios");
    close(fd);
    exit(EXIT_FAILURE);
  }

  // Make my termios
  my_termios_s = org_termios_s;
  cfmakeraw(&amp;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 &amp;= ~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(&amp;my_termios_s, B19200);

  my_termios_c = org_termios_c;
  cfmakeraw(&amp;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 &amp;= ~CSTOPB;
  my_termios_c.c_cc[VMIN] = 0;
  my_termios_c.c_cc[VTIME] = 0;

  // Change terminal settings
  if(tcsetattr(fd, TCSANOW, &amp;my_termios_s) == -1) {
    perror("set my serial termios");
    close(fd);
    exit(EXIT_FAILURE);
  }
  if(tcsetattr(fileno(stdin), TCSANOW, &amp;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), &amp;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, &amp;buf_s[i], 1); //unrecommended use of write
      }
    }
  }

  // Revert orginal terminal settings
  if(tcsetattr(fd, TCSANOW, &amp;org_termios_s) == -1) {
    perror("revert serial terminal settings");
    close(fd);
    exit(EXIT_FAILURE);
  }
  if(tcsetattr(fileno(stdin), TCSANOW, &amp;org_termios_c) == -1) {
    perror("revert console terminal settings");
    close(fd);
    exit(EXIT_FAILURE);
  }

  printf("n"); // just cleanup
  close(fd);
  return 0;
}

Enjoy!

Trackback URL

2 Responses to “iPhone/iPod Touch Serial Communication How-To”

  1. blogring.org Says:

    serial-でつながるブログリング

    serialに関するブログをまとめています。

  2. Tipset » Blog Archive » MapKitを使ってみた Says:

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

Leave a Reply