当我发现串行卡的驱动程序不支持通过 ioctl 调用(例如 ioctl(fd, TIOCMGET, &arg);)的 TIOCMGET 时,我一直在使用带有串行 I/O 的旧 SVR4 盒子进行一些工作。拥有驱动程序的源代码并查看它 - 添加对呼叫的应答似乎并不难。然而,我遇到了一些障碍,因为我所做的事情似乎不起作用。查看驱动程序,它有以下代码来服务 TCGETS:
case TCGETS:
{ /* immediate parm retrieve */
register struct termios *cb;
if (mp->b_cont) /* Bad user supplied parameter */
freemsg(mp->b_cont);
if (!(bp1 = allocb(sizeof(struct termios), BPRI_MED)))
{
putbq(q, mp);
bufcall(sizeof(struct termios), BPRI_MED, getoblk, (long)tp);
return;
}
mp->b_cont = bp1;
cb = (struct termios *)mp->b_cont->b_rptr;
cb->c_iflag = tp->t_iflag;
cb->c_oflag = tp->t_oflag;
cb->c_cflag = tp->t_cflag;
mp->b_cont->b_wptr += sizeof(struct termios);
mp->b_datap->db_type = M_IOCACK;
iocbp->ioc_count = sizeof(struct termios);
putnext(RD(q), mp);
break;
}
我的想法是简单地复制这段代码,而不是返回 termios 结构,只需返回 int 。因此,我的代码类似:
case TIOCMGET:
{ /* immediate parm retrieve */
register int *cb;
if (mp->b_cont) /* Bad user supplied parameter */
freemsg(mp->b_cont);
if (!(bp1 = allocb(sizeof(int), BPRI_MED)))
{
putbq(q, mp);
bufcall(sizeof(int), BPRI_MED, getoblk, (long)tp);
return;
}
mp->b_cont = bp1;
cb = (int *)mp->b_cont->b_rptr;
/* my original attempt to get some bits */
*cb = (ql->carrier * TIOCM_CAR | ql->rts * TIOCM_RTS | (ql->lp->command & 1) * TIOCM_DTR)
/* Tried this to debug:
*cb = 0;
Doesn't seem to change the variable I pass in */
/* Tried this, compiles fine,
*(int *)mp->b_cont->b_rptr = 0;
but I get an improper argument passed error while running */
/* qreply(q, mp); not in my code, was a note to try it */
mp->b_cont->b_wptr += sizeof(int);
mp->b_datap->db_type = M_IOCACK;
iocbp->ioc_count = sizeof(int);
putnext(RD(q), mp);
break;
}
如前所示进行调用,ioctl(fd, TIOCMGET, &arg),arg 值似乎没有改变。我尝试了几次不同的尝试来返回 0 值,以防问题出在我的位分配代码中。然而,我没有任何运气。
我确实编写了一个程序来确保 TCGETS 按其应有的方式工作 - 并且确实如此。所以我不确定我哪里出了问题——可能是一些极其愚蠢的事情就在我面前。希望 SVR4 和 STREAMS 不会那么神秘,让答案遥不可及。
感谢所有寻求并尝试提供帮助的人。
马克