分享

tty线路规程(discipline)设置

 astrotycoon 2014-09-21

1. tty线路设置用户空间接口
可以调用用户空间的termios库函数,改变tty线路设置,或者获取当前线路设置。
用户空间应用程序需引用 termios.h 头文件,该头文件包含了终端设备的I/O接口。

termios结构体 描述了终端设备的操作模式

  1. typedef unsigned char    cc_t;  
  2. typedef unsigned int    speed_t;  
  3. typedef unsigned int    tcflag_t;  
  4.   
  5. #define NCCS 19   
  6. struct termios {  
  7.     tcflag_t c_iflag;        /* input mode flags */  
  8.     tcflag_t c_oflag;        /* output mode flags */  
  9.     tcflag_t c_cflag;        /* control mode flags */  
  10.     tcflag_t c_lflag;        /* local mode flags */  
  11.     cc_t c_line;            /* line discipline */  
  12.     cc_t c_cc[NCCS];        /* control characters */  
  13. };  

c_cflag --- 控制标志,包含了如下位域信息:
CSIZE ---- 字长
CSTOPB ---- 两个停止位
PARENB ---- 奇偶校验位使能
PARODD ---- 奇校验位,当PARENB被使能时。
CREAD ---- 字符接收使能,如果没有使能,仍能从端口接收字符,但这些字符都要被丢弃。
CRTSCTS ---- 如果被置位,CTS 状态改变时将发送报告。
CLOCAL ---- 如果没有置位,调制解调器状态改变时将发送报告。
c_iflag --- 输入标志,包含如下位信息:
INPCK ---- 使能帧和奇偶校验错误检查。
BRKINT ---- break 将清除终端输入/输出队列,向终端上前台程序发出 SIGINT 信号。
PARMRK ---- 奇偶校验和帧错误被标记,在INPCK 被设置且IGNPAR未被设置的情况下才有效。
IGNPAR ---- 忽略奇偶校验和帧错误。
IGNBRK ---- 忽略 break 。
2. 用户空间中有如下函数:
2.1 设置和获取终端设备的操作模式:
int tcgetattr(int fd, struct termios *termios_p);
int tcsetattr(int fd, int optional_actions, struct termios *termios_p );
2.2 设置和获取输入/输出波特率:
speed_t cfgetospeed(struct termios *termios_p); //获得输出波特率
speed_t cfgetispeed(struct termios *termios_p); //获得输入波特率

int cfsetospeed(struct termios *termios_p); //设置输出波特率
int cfsetispeed(struct termios *termios_p); //设置输入波特率

2.3 下面一组函数完成线路控制:
int tcdrain(int fd); //等待所有输出都被发送
int tcflush(int fd, int queue_selector);   //flush输入输出缓存
int tcflow(int fd, int action);  //对输入输出流进行控制
int tcsendback(int fd, int duration); //发送break。

3. tty驱动的set_termios()函数

大部分termios用户空间的函数,被库转换为对驱动节点的ioctl()调用,而tty_ioctl()中的大部分命令会被tty核心转换为对tty驱动的set_termios()成员函数的调用。
set_termios()函数,需要根据用户对termiosde 设置要求, 完成实际的硬件设置。如字长,奇偶校验位,停止位,波特率等。

下面是 set_termios()成员函数的范例:

  1. static void xxx_set_termios(struct tty_struct *tty, struct termios *old_termios)  
  2. {  
  3.     struct xxx_tty *info = (struct cyclades_port *)tty->driver_data;  
  4.   
  5.     //新设置=旧设置   
  6.     if (tty->termios->c_cflags == old_termios->cflag)  
  7.         return;  
  8.     ...  
  9.     //关闭CRTSCTS硬件流控制   
  10.     if ((old_termios->c_cflag & CRTSCTS) && !(cflag & CRTSCTS))  
  11.     {  
  12.         ...  
  13.     }  
  14.   
  15.     //打开CRTSCTS 硬件流控制   
  16.     if (!(old_termios->c_cflag & CRTSCTS) && (cflag & CRTSCTS))  
  17.     {  
  18.         ...  
  19.     }  
  20.   
  21.     //设置字节大小   
  22.     switch (tty->termios->c_cflag & CSIZE)  
  23.     {  
  24.         case CS5:  
  25.             ...  
  26.         case CS6:  
  27.             ...  
  28.         case CS7:  
  29.             ...  
  30.         case CS8:  
  31.             ...  
  32.     }  
  33.   
  34.     //设置奇偶校验位   
  35.     if (tty->termios->c_cflag & PARENB)  
  36.         if(tty->termios->c_cflag & PARODD)   //奇校验   
  37.             ...  
  38.         else      //偶校验   
  39.             ...  
  40. }  

3.1 tty_register_ldisc() ---
注册线路规程函数

  1. /** 
  2.  *    tty_register_ldisc    -    install a line discipline 
  3.  *    @disc: ldisc number 
  4.  *    @new_ldisc: pointer to the ldisc object 
  5.  * 
  6.  *    Installs a new line discipline into the kernel. The discipline 
  7.  *    is set up as unreferenced and then made available to the kernel 
  8.  *    from this point onwards. 
  9.  * 
  10.  *    Locking: 
  11.  *        takes tty_ldisc_lock to guard against ldisc races 
  12.  */  
  13. int tty_register_ldisc(int disc, struct tty_ldisc_ops *new_ldisc)  
  14. {  
  15.     unsigned long flags;  
  16.     int ret = 0;  
  17.   
  18.     if (disc < N_TTY || disc >= NR_LDISCS)  
  19.         return -EINVAL;  
  20.   
  21.     spin_lock_irqsave(&tty_ldisc_lock, flags);  
  22.     tty_ldiscs[disc] = new_ldisc;  
  23.     new_ldisc->num = disc;  
  24.     new_ldisc->refcount = 0;  
  25.     spin_unlock_irqrestore(&tty_ldisc_lock, flags);  
  26.   
  27.     return ret;  
  28. }  
  29. EXPORT_SYMBOL(tty_register_ldisc);  

3.2  tty_disc_ops --- tty 线路规程操作函数

  1. struct tty_ldisc_ops tty_ldisc_N_TTY = {  
  2.     .magic = TTY_LDISC_MAGIC,  
  3.     .name = "n_tty",  
  4.     .open = n_tty_open,  
  5.     .close = n_tty_close,  
  6.     .flush_buffer = n_tty_flush_buffer,  
  7.     .chars_in_buffer = n_tty_chars_in_buffer,  
  8.     .read = n_tty_read,  
  9.     .write = n_tty_write,  
  10.     .ioctl = n_tty_ioctl,  
  11.     .set_termios = n_tty_set_termios,  
  12.     .poll = n_tty_poll,  
  13.     .receive_buf = n_tty_receive_buf,  
  14.     .write_wakeup = n_tty_write_wakeup  
  15. };  

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多