TinySerial on macOS

우분투에서 사용한 시리얼 프로그램인 Tiny Serial이 macOS에선 동작하지 않는 문제가 있었다.

컴파일할 때 Baud Rate 말고는 큰 문제가 없는데, 왜 안되는지 확인을 하려고 하였으나 macOS의 screen 커맨드로 당장 시리얼을 사용 못하는 것이 아니여서 그냥저냥 쓰고 있었다.

 

하지만, screen 명령어로 시리얼을 확인할 경우 몇몇 캐랙터가 이빨 빠지는 현상이 은근히 신경이 쓰여, TinySerial을 macOS에서 동작시키는 것이 정신 건강에 좋을 것 같아 오늘 잠깐 짬을 내어 수정하였다.

 

 

GitHub - highgon2/TinySerial: Tiny Serial on Ubuntu

Tiny Serial on Ubuntu. Contribute to highgon2/TinySerial development by creating an account on GitHub.

github.com

 

macOS도 BSD 기반이라 기존 소스 코드로 시리얼 출력이 안될 이유가 없기 때문에 원인을 찾은 결과, macOS에선 baudrate 설정시 추가적인 ioctl 및 cfsetispeed() / cfsetospeed() 함수를 추가적으로 실행해야 동작하는 것을 확인했다. 기존 GitHub에 올려놓은 TinySerial 소스를 아래와 같이 수정하면 정상 동작하는 것을 확인 할 수 있다.

diff --git a/com.c b/com.c
index f8f2407..d090e21 100644
--- a/com.c
+++ b/com.c
@@ -46,6 +46,10 @@
 #include <fcntl.h>
 #include <errno.h>
 
+#ifdef __APPLE__
+  #include <IOKit/serial/ioss.h>
+#endif
+
 int transfer_byte(int from, int to, int is_control);
 
 typedef struct {char *name; int flag; } speed_spec;
@@ -83,11 +87,13 @@ int main(int argc, char *argv[])
                {"38400", B38400},
                {"57600", B57600},
                {"115200", B115200},
+         #ifdef __linux__
                {"230400", B230400},
                {"460800", B460800},
                {"500000", B500000},
                {"576000", B576000},
                {"921600", B921600},
+         #endif
                {NULL, 0}
        };
        int speed = B9600;
@@ -135,6 +141,19 @@ int main(int argc, char *argv[])
        newkey.c_cc[VMIN]=1;
        newkey.c_cc[VTIME]=0;
        tcflush(STDIN_FILENO, TCIFLUSH);
+  #ifdef __APPLE__
+       if (ioctl(comfd, IOSSIOSPEED, &speed) == -1) {
+               printf("Error %d calling ioctl( ..., IOSSIOSPEED, ... )\n", errno);
+       }
+       if (cfsetispeed(&newtio, speed) < 0) {
+               perror("cfsetispeed");
+               exit(1);
+       }
+       if (cfsetospeed(&newtio, speed) < 0) {
+               perror("cfsetospeed");
+               exit(1);
+       }
+  #endif
        tcsetattr(STDIN_FILENO,TCSANOW,&newkey);

screen 명령어로 시리얼을 확인할 때, 몇몇 캐랙터가 이빨 빠지는 문제에서 해방될 수 있다. ㅎㅎ