
                      The Linux Serial Programming HOWTO
                                       
by Peter H. Baumann, [1]Peter.Baumann@dlr.de
Ķ:  [2]yytseng@ms16.hinet.net

   v1.0, 22 @ 1998
     _________________________________________________________________
   
   Nԭzpb Linux ҤUgǦC𪺳qT{.
     _________________________________________________________________
   
1. ²

     * 1.1 v
     * 1.2 ̷s
     * 1.3 ^X
       
2. }l

     * 2.1 
     * 2.2 s]w
     * 2.3 ǦC˸mJ[
       
3. {d

     * 3.1 зǿJ{
     * 3.2 DзǿJ{
     * 3.3 DPBJ
     * 3.4 ݨӦۦhӰTӷJ
       
4. 䥦귽

5. ^m
     _________________________________________________________________
   
1. ²

   O Linux ǦC{g HOWTO. gbQצpb Linux ҤU,
   HǦCPL ˸m/q qT{gk. Ҹ޳N]t: зǪ I/O
   (u ǰe/ u), DPB I/O,  ݨӦۦhHJT g
   k.
   
   夣|ԭzp]wǦC, ]ob Greg Hankins  Serial-HOWTO wg
   F.
   
   ڥݱjէڨëD줤Ma, ӬObMפJLoqTD. b
   oҴ쪺dҵ{Olͦ miniterm {X. ib LDP {]pvn
   o
   (ftp://sunsite.unc.edu/pub/Linux/docs/LDP/programmers-guide/lpg-0.4.ta
   r.gz ΨLMg) bdҨӥؿU.
   
   ڶ}lgoOb 1997 ~ , {bڤwg WinNT HȤ᪺
   ݨD, HPڨSǱo`J. pGHN, ګַܼN⥦
   \io (Ѧ ^X @`). pGH౵ou@å[Hi, 
   e-mail .
   
   Ҧdҳb i386 Linux Kernel 2.0.29 UչL.
   
1.1 v

   Linux Serial-Programming-HOWTO v(C) 1997 O Peter Baumann Ҧ.
   Linux HOWTO iHγHکιqlsδG, unvŧi
   OdbҦGƥ. ӷ~ʪsGO\ióQy; L, pG
   HG  i@.
   
   Ҧ½Ķ, lͪu@, ξXX֥ Linux HOWTO ҥb
   vŧiWdU. ]NO, AiH HOWTO ҭlͪu@, GW
   [B~. FoǳWh~ҥibYر󪺱»P; p Linux
   HOWTO խ: pHUҵ}.
   
   ²Ө, ڭ̧Ʊ澨iozLUغ޹DPioTyq, L, ڱjP
   ƱNvŧim HOWTO W,  Q sG HOWTO H, 
   zા|ڭ̤@U.
   
   pGAD, иg email P Tim Bynum, Linux HOWTO խs,
   [3]linux-howto@sunsite.unc.edu.
   
1.2 ̷s

   Serial-Programming-HOWTO ̷sNb
   [4]ftp://sunsite.unc.edu:/pub/Linux/docs/HOWTO/Serial-Programming-HOWT
   O ΨLM]x. \h榡, p PostScript  DVI b
   other-formats ؿU. Serial-Programming-HOWTO ]b
   [5]http://sunsite.unc.edu/LDP/HOWTO/Serial-Programming-HOWTO.html ÷|
   CӤ\@ [6]comp.os.linux.answers.
   
1.3 ^X

   Чץ, D, N, ĳ, Ψ䥦[Dǰe. Hڧio
    HOWTO! øԲӧiDڭӳOzF, ΤM. AiH
   email s [7]Peter.Baumann@dlr.de. Ч Serial-Programming-HOWTO 
   XW, 媩XO 0.3.
   
2. }l

2.1 

   ̦nA{XkOغct@x Linux box, çxq
   null-modem lus.  miniterm (ib LDP {]pvno
   (ftp://sunsite.unc.edu/pub/Linux/docs/LDP/programmers-guide/lpg-0.4.ta
   r.gz bdҨӥؿU) HǰerA Linux box. Miniterm ܮesĶ
   ӥ|ҦJLrzLǦCǰe. uoӫŧiwq|Qˬd
   #define MODEMDEVICE "/dev/ttyS0". pGO COM1 ]w ttyS0, pGO
   COM2 ]w ttyS1 .. eլOn, Ҧ rNH raw 覡
   (gBz) ǰe. լO_sT, bxqWҰ miniterm
   MHKbLWë. b䤤@xWJrӷ|ܦbt@xqW
   P. Jr|^P۳sùW.
   
   nۻs null-modem ql, Aݭn TxD (ǰe)  RxD () u
   . ԲӪb Serial-HOWTO  7 q.
   
   M]iHuΤ@xqӧ@ۦP, unqWӥϥΪǦC.
   MA]Nn miniterm ӷx. pGAOǥѩޥhƹӨ
   ot@ӧǦC, Oon /dev/mouse ˸msɦV, pGsb. pG
   AϥΦh𪺧ǦC𱱨d, нTww]wT. ڦbڪqWծɤ]
   g]]w~ӥXLl. ڳst@xq, qT}lǰer. N]
   noO㪺DPBǿ, ҥHibP@xqWӵ{.
   
2.2 s]w

   /dev/ttyS* ˸m|QsA Linux box ׺ݾ, åBbҰʫN]
   wnF. o[bAg raw ˸mqT{ɥݰO. ]NOoӳs
   Q]w^Ҧ۳oӸ˸meXr, ӥΦbƶǿɳq`oحnܳo
   ؤu@Ҧ.
   
   ҦѼƥiHѤ@Ӥp{²檺. ]wѼƳQb@ӵc餺
   struct termios, Lwqɦb <asm/termbits.h>:
   
#define NCCS 19
struct termios {
        tcflag_t c_iflag;               /* JҦX */
        tcflag_t c_oflag;               /* XҦX */
        tcflag_t c_cflag;               /* ҦX */
        tcflag_t c_lflag;               /* ϰҦX */
        cc_t c_line;                    /* 汱 (line discipline) */
        cc_t c_cc[NCCS];                /* S */
};

   oɮפ]]tҦXЩwq. JҦXЦb c_iflag xީҦJB
   z, oNN׵ۥѸ˸mWǨӪrb٨S read \ŪeiHBzL.
   Pz c_oflag xީҦXBz. c_cflag ]ts𪺳]w, p jv, C
   rh֦줸, 줸, .. ϰҦXЩb c_lflag ΨӰrO
   _^, ӰT|eA{, .. ̫ c_cc }CwqFɮײפF
   r, , .. w]rȩb <asm/termios.h>. XЪӸ`
   \bϥΤU termios(3). termios c餺 c_line 汱 (line
   discipline) , b POSIX ۮetΤUϥ Ķ̵:o̩һ line
   discipline M½ 汱 ٬OXO. pGQDЬݬ
   kernel :( .
   
2.3 ǦC˸mJ[

   TӿJ[n. өҭngε{ξAX[. qקK
   ΰjŪ@rAզr. ڴo˰L, |r, B read 
   |ܥ~.
   
  зǿJ{
  
   oO׺ݾзǳBz{, ΨӻPL dl H欰쪺JqT]
   ܦ, ]NO read |Ǧ^@槹㪺J. w]פrO NL
   (ASCII LF), ɮ׵, Φפr. w]ҤU, CR (O DOS/Windows w
   ]פ) |פ@檺ԭz.
   
   зǪJBz{٥iHBz M, Rr, Lr, ഫ CR  NL 
   \..
   
  DзǿJ{
  
   DзǿJ{ǥiHΦbݭnCŪTwƶqrp, ä\ϥΦr
   Jɶpɾ. oؼҦiHΦbŪTwrƶqε{, Ϊ̩ҳs
   ˸m|MeXjqrp.
   
  DPBJ
  
   HWұԭzؼҦiHΦbDPBPPBǿҦ. w]ObPB
   Uu@, ]NOb|Ūe, read A|Q_. ӫDPBҦU
   read A|^ðeXTҥsΪ{짹u@. oӰTiH
   ѰTBz{ handler...ӱ.
   
  ݨӦۦhӰTӷJ
  
   oäO@Ӥ@˪JҦ. pGAnzLǦCsóBzhӸ˸m
   , OΪ. bڪε{ڥݦbXGP@ɶ, zL TCP/IP
   socket ΧǦCBzӦۨLqJT. Uoӽdҵ{NݨӦۨ
   ӤPJT. pG䤤@ӫHX{, LN|QBz, ӵ{|~
   ݷsJT.
   
   HUoӤkݰ_Ӭ۷, аO Linux O@Ӧhu@~t.
   select oӨtΩIsä|bݿJTɧ CPU t[, ӦpGAΰj
   覡ӵݿJTNϱo䥦Pɰ檺{QC.
   
3. {d

   ҦdҨӷ miniterm.c. The type ahead ȦsQb 255 Ӧr,
   NзǿJ{Ǫ̤jr׬ۦP (<linux/limits.h> 
   <posix1_lim.h>).
   
   Ѧҵ{Xѥ|PJҦϥ. ڧƱoǵ{XQF
   . зǿJ{Ǫ{dҪѼgo̦n, 䥦dҳubP䥦d
   Ҫa谵.
   
   ԭzOܧ, iHEyAodҰ, HͥXXAһε{
   ̨θ.
   
   OѰOnǦCv]wT (]NO: chmod a+rw /dev/ttyS1)!
   
3.1 зǿJ{

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <termios.h>
#include <stdio.h>

/* jv]wQwqb <asm/termbits.h>, ob <termios.h> QޤJ */
#define BAUDRATE B38400
/* wqTǦC */
#define MODEMDEVICE "/dev/ttyS1"
#define _POSIX_SOURCE 1 /* POSIX tάۮe */

#define FALSE 0
#define TRUE 1

volatile int STOP=FALSE;

main()
{
  int fd,c, res;
  struct termios oldtio,newtio;
  char buf[255];
/*
  }Ҽƾھ˸mHŪügJӤH tty Ҧ
  ]ڭ̤Q{beX CTRL-C NQ.
*/
 fd = open(MODEMDEVICE, O_RDWR | O_NOCTTY );
 if (fd <0) {perror(MODEMDEVICE); exit(-1); }

 tcgetattr(fd,&oldtio); /* xsثeǦC]w */
 bzero(&newtio, sizeof(newtio)); /* McHJsǦC]w */

/*
  BAUDRATE: ]w bps t. A]iH cfsetispeed  cfsetospeed ӳ]w.
  CRTSCTS : Xƪwyq (ub㧹uluUu@
            Ѧ Serial-HOWTO ĤC`)
  CS8     : 8n1 (8 줸, P줸ˬd,1 Ӳפ줸)
  CLOCAL  : asu, ƾھ\
  CREAD   : P౵r
*/
 newtio.c_cflag = BAUDRATE | CRTSCTS | CS8 | CLOCAL | CREAD;

/*
  IGNPAR  : gP줸ˬd, ~줸
  ICRNL   :  CR  NL (_hJT CR ɤ|פJ)
            bM˸m]w raw Ҧ(S䥦JBz)
*/
 newtio.c_iflag = IGNPAR | ICRNL;

/*
 Raw ҦX.
*/
 newtio.c_oflag = 0;

/*
  ICANON  : PзǿJ, ϩҦ^ఱ, äeXHHsε{
*/
 newtio.c_lflag = ICANON;

/*
  lƩҦS
  w]ȥiHb /usr/include/termios.h , bѤ],
  ڭ̦boݭnݥ
*/
 newtio.c_cc[VINTR]    = 0;     /* Ctrl-c */
 newtio.c_cc[VQUIT]    = 0;     /* Ctrl-\ */
 newtio.c_cc[VERASE]   = 0;     /* del */
 newtio.c_cc[VKILL]    = 0;     /* @ */
 newtio.c_cc[VEOF]     = 4;     /* Ctrl-d */
 newtio.c_cc[VTIME]    = 0;     /* ϥΤΦrժpɾ */
 newtio.c_cc[VMIN]     = 1;     /* bŪ 1 Ӧre */
 newtio.c_cc[VSWTC]    = 0;     /* '\0' */
 newtio.c_cc[VSTART]   = 0;     /* Ctrl-q */
 newtio.c_cc[VSTOP]    = 0;     /* Ctrl-s */
 newtio.c_cc[VSUSP]    = 0;     /* Ctrl-z */
 newtio.c_cc[VEOL]     = 0;     /* '\0' */
 newtio.c_cc[VREPRINT] = 0;     /* Ctrl-r */
 newtio.c_cc[VDISCARD] = 0;     /* Ctrl-u */
 newtio.c_cc[VWERASE]  = 0;     /* Ctrl-w */
 newtio.c_cc[VLNEXT]   = 0;     /* Ctrl-v */
 newtio.c_cc[VEOL2]    = 0;     /* '\0' */

/*
  {bMƾھuñҰʧǦC𪺳]w
*/
 tcflush(fd, TCIFLUSH);
 tcsetattr(fd,TCSANOW,&newtio);

/*
  ׺ݾ]w, {bBzJT
  boӽd, b@檺}lBJ 'z' |hX{.
*/
 while (STOP==FALSE) {     /* j|bڭ̵oXפTX */
 /* YϿJWL 255 Ӧr, Ū{q٬O|@׵ťX{~.
    pGŪ쪺rէC󥿽Tsbr, hҳѪr|bU@Ūɨo.
    res ΨӦsuŪ쪺rխӼ */
    res = read(fd,buf,255);
    buf[res]=0;             /* ]wrפr, ҥHڭ̯ printf */
    printf(":%s:%d\n", buf, res);
    if (buf[0]=='z') STOP=TRUE;
 }
 /* ^sªǦC]w */
 tcsetattr(fd,TCSANOW,&oldtio);
}

3.2 DзǿJ{

   bDзǪJ{ǼҦU, JƤ|QզX@ӿJ᪺Bz\
   (M, , R, .) ϥ. oӼҦӥ\౱Ѽ:
   c_cc[VTIME] ]wrJɶpɾ,  c_cc[VMIN] ]wŪ\઺
   CrӼ.
   
   pG MIN > 0 B TIME = 0, MIN ]wŪ\઺̧CrӼ. 
    TIME O s, ҥHpɾNQϥ.
   
   pG MIN = 0 B TIME > 0, TIME NQOɳ]w. Ū\઺p
   Ū@r, Ϊ̶WL TIME ҩwqɶ (t = TIME *0.1 s). pGWL
   TIME ҩwqɶ, h|Ǧ^r.
   
   pG MIN > 0 B TIME > 0, TIME NQ@ӤΦrժpɾ. Ū
   \઺  MIN Ӽƪr, ΨӦrjɶWL TIME ҩw
   q. pɾ|bCŪ@Ӧr᭫sp, Bu|bĤ@Ӧr~
   |Ұ.
   
   pG MIN = 0 B TIME = 0, Ū\NWQ. ثeҦsbrխ
   , Ϊ N^ǪrխӼ. ھ Antonino (Ѧ ^m) һ, AiH
   fcntl(fd, F_SETFL, FNDELAY); bŪeoۦPG.
   
   ǥѭק newtio.c_cc[VTIME]  newtio.c_cc[VMIN] WzҦNiH
   F.
   
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <termios.h>
#include <stdio.h>

#define BAUDRATE B38400
#define MODEMDEVICE "/dev/ttyS1"
#define _POSIX_SOURCE 1 /* POSIX tάۮe */
#define FALSE 0
#define TRUE 1

volatile int STOP=FALSE;

main()
{
  int fd,c, res;
  struct termios oldtio,newtio;
  char buf[255];

 fd = open(MODEMDEVICE, O_RDWR | O_NOCTTY );
 if (fd <0) {perror(MODEMDEVICE); exit(-1); }

 tcgetattr(fd,&oldtio); /* xsثeǦC]w */

 bzero(&newtio, sizeof(newtio));
 newtio.c_cflag = BAUDRATE | CRTSCTS | CS8 | CLOCAL | CREAD;
 newtio.c_iflag = IGNPAR;
 newtio.c_oflag = 0;

 /* ]wJҦ (Dзǫ, ^,...) */
 newtio.c_lflag = 0;

 newtio.c_cc[VTIME]    = 0;   /* ϥΤΦrխpɾ */
 newtio.c_cc[VMIN]     = 5;   /* bŪ 5 Ӧre */

 tcflush(fd, TCIFLUSH);
 tcsetattr(fd,TCSANOW,&newtio);


 while (STOP==FALSE) {       /* Jj */
   res = read(fd,buf,255);   /* bJ 5 ӦrYj */
   buf[res]=0;               /* ҥHڭ̯ printf... */
   printf(":%s:%d\n", buf, res);
   if (buf[0]=='z') STOP=TRUE;
 }
 tcsetattr(fd,TCSANOW,&oldtio);
}

3.3 DPBJ

#include <termios.h>
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/signal.h>
#include <sys/types.h>

#define BAUDRATE B38400
#define MODEMDEVICE "/dev/ttyS1"
#define _POSIX_SOURCE 1 /* POSIX tάۮe */
#define FALSE 0
#define TRUE 1

volatile int STOP=FALSE;

void signal_handler_IO (int status);   /* wqTBz{ */
int wait_flag=TRUE;                    /* STܴN|O TRUE */

main()
{
  int fd,c, res;
  struct termios oldtio,newtio;
  struct sigaction saio;           /* definition of signal action */
  char buf[255];

  /* }Ҹ˸m non-blocking (Ū\|W^) */
  fd = open(MODEMDEVICE, O_RDWR | O_NOCTTY | O_NONBLOCK);
  if (fd <0) {perror(MODEMDEVICE); exit(-1); }

  /* bϸ˸mDPBƫe, w˰TBz{ */
  saio.sa_handler = signal_handler_IO;
  saio.sa_mask = 0;
  saio.sa_flags = 0;
  saio.sa_restorer = NULL;
  sigaction(SIGIO,&saio,NULL);

  /* \{h SIGIO T*/
  fcntl(fd, F_SETOWN, getpid());
  /* ɮake the file descriptor DPB (ϥΤUWu O_APPEND 
  O_NONBLOCK,  F_SETFL ]iH...) */
  fcntl(fd, F_SETFL, FASYNC);

  tcgetattr(fd,&oldtio); /* xsثeǦC]w */
  /* ]wsǦC𬰼зǿJ{ */
  newtio.c_cflag = BAUDRATE | CRTSCTS | CS8 | CLOCAL | CREAD;
  newtio.c_iflag = IGNPAR | ICRNL;
  newtio.c_oflag = 0;
  newtio.c_lflag = ICANON;
  newtio.c_cc[VMIN]=1;
  newtio.c_cc[VTIME]=0;
  tcflush(fd, TCIFLUSH);
  tcsetattr(fd,TCSANOW,&newtio);

  /* ݿJTj. ܦhΪƧڭ̱Nbo */
  while (STOP==FALSE) {
    printf(".\n");usleep(100000);
    /* b SIGIO , wait_flag = FALSE, JTsbhiHQŪ */
    if (wait_flag==FALSE) {
      res = read(fd,buf,255);
      buf[res]=0;
      printf(":%s:%d\n", buf, res);
      if (res==1) STOP=TRUE; /* pGuJ CR hj */
      wait_flag = TRUE;      /* ݷsJT */
    }
  }
  /* ^sªǦC]w */
  tcsetattr(fd,TCSANOW,&oldtio);
}

/***************************************************************************
* TBz{. ]w wait_flag  FALSE, HϤWzj౵r          *
***************************************************************************/

void signal_handler_IO (int status)
{
  printf("received SIGIO signal.\n");
  wait_flag = FALSE;
}

3.4 ݨӦۦhӰTӷJ

   o@qܵu. uQӷg{ɪ, Gdҵ{]²u. o
   dҤuΦbǦCW, ٥iHΦbQɮרӨϥΪ˸mW.
   
   select IsΦHҤ޵o@ fd_set. fd_set hO@ 줸}C,
   Ө䤤C@Ӧ줸N@ӦĪɮױԭzc. select Is@ӦĪ
   ױԭzcöǦ^ fd_set 줸}C, ӸӦ줸}CYY@Ӧ줸 1, N
   ܬ۹Mɮױԭzcɮ׵oͤFJ, XΦҥ~ƥ. ӳoǥ
   ѤFҦBz fd_set \. iѦҤU select(2).
   
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>

main()
{
   int    fd1, fd2;  /* J 1  2 */
   fd_set readfs;    /* ɮױԭzc]w */
   int    maxfd;     /* ̤jiΪɮױԭzc */
   int    loop=1;    /* jb TRUE ɦ */

   /* open_input_source }Ҥ@Ӹ˸m, T]wnǦC,
      æ^Ǧ^ɮױԭzc */
   fd1 = open_input_source("/dev/ttyS1");   /* COM2 */
   if (fd1<0) exit(0);
   fd2 = open_input_source("/dev/ttyS2");   /* COM3 */
   if (fd2<0) exit(0);
   maxfd = MAX (fd1, fd2)+1;  /* ճ̤j줸J (fd) */

   /* Jj */
   while (loop) {
     FD_SET(fd1, &readfs);  /* տJ 1 */
     FD_SET(fd2, &readfs);  /* տJ 2 */
     /* block until input becomes available */
     select(maxfd, &readfs, NULL, NULL, NULL);
     if (FD_ISSET(fd1))         /* pGJ 1 T */
       handle_input_from_source1();
     if (FD_ISSET(fd2))         /* pGJ 2 T */
       handle_input_from_source2();
   }

}

   oӽdҵ{bݿJTX{e, Tw|yU. pGAݭnb
   Jɥ[JOɥ\, uݧ select Is:
   
int res;
struct timeval Timeout;

/* ]wJj骺Oɭ */
Timeout.tv_usec = 0;  /* @ */
Timeout.tv_sec  = 1;  /*  */
res = select(maxfd, &readfs, NULL, NULL, &Timeout);
if (res==0)
/* ɮױԭzcƦb input = 0 , |oͿJO. */

   oӵ{|b 1 O. pGWLɶ, select |Ǧ^ 0, OӯdN
   Timeout ɶO select ҵݿJTɶ. pGOɪ
   O 0, select |W^.
   
4. 䥦귽

     * Linux Serial-HOWTO ԭzp]wǦCΩҦwT.
     *  Michael Sweet Ҽg [8]Serial Programming Guide for POSIX
       Compliant Operating Systems. oӳswgoFڧ䤣쥦s
       }. HDb쥦? OܴΪ!
     * termios(3) ϥΤU. ԭzҦ termios c骺X.
       
5. ^m

   N²һ@, ڨëDbo즳ұM, ڦۤvJD, ózLL
   HU쵪. P¨Ӧ European Transonic Windtunnel  Strudthoff
   , Cologne, Michael Carter (mcarter@rocke.electro.swri.edu), 
   Peter Waltenberg (p.waltenberg@karaka.chch.cri.nz)
   
   PڦPɷǳƳo Antonino Ianella (antonino@usa.net ҽfg
   Serial-Port-Programming Mini HOWTO. Greg Hankins nDڧ Antonino's
   Mini-HOWTO @֩Jo.
   
   o󪺵c SGML 榡O Greg Hankins  Serial-HOWTO. P
   Dave Pfaltzgraff (Dave_Pfaltzgraff@patapsco.com), Sean Lincolne
   (slincol@tpgi.com.au), Michael Wiedmann (mw@miwie.in-berlin.de), 
   Adrey Bonar (andy@tipas.lt) U譱U.

References

   1. mailto:Peter.Baumann@dlr.de
   2. mailto:yytseng@ms16.hinet.net
   3. mailto:linux-howto@sunsite.unc.edu
   4. ftp://sunsite.unc.edu/pub/Linux/docs/HOWTO/Serial-Programming-HOWTO
   5. http://sunsite.unc.edu/LDP/HOWTO/Serial-Programming-HOWTO.html
   6. news:comp.os.linux.answers
   7. mailto:Peter.Baumann@dlr.de
   8. http://www.easysw.com/~mike/serial
