ttyACM0只读取64个字节

时间:2013-08-17 12:30:24

标签: linux termios

我有点新手,但我有一个遗留应用程序,使用ttyACM0从设备读取64字节的AES加密数据。我现在需要读取128个字节。听起来很简单;增加缓冲区的大小等。但无论我尝试什么,我仍然只能读取64个字节。之后它只是挂起。我使用终端和cdc-acm驱动程序验证了Windows中的通信。设备不使用流量控制。我无法上传代码,因为它的专有但下面是一些片段:

初始化:         CACS_RefID ::初始化()     {         int iRet = 1;         struct termios dev_settings;

    if(( m_fdRefdev = open("/dev/ttyACM0", O_RDWR))<0)
    {
        g_dbg->debug("CACS_RefID::Failed to open device\n");
        return 0;
    }


    g_dbg->debug("CACS_RefID::Initialse completed\n");
    // Configure the port
    tcgetattr(m_fdRefdev, &dev_settings);
    cfmakeraw(&dev_settings);

    //*tcflush 
    //tcflush(m_fdRefdev, TCIOFLUSH);   
     tcsetattr(m_fdRefdev, TCSANOW, &dev_settings);
    return iRet;
}

实施:

    int CACS_RefID::Readport_Refid(int ilen, char* buf)
{
    int ierr=0, iret = 0, ictr=0;
    fd_set  fdrefid;      
        struct timeval porttime_refrd;

    FD_ZERO(&fdrefid);
    FD_SET(m_fdRefdev,&fdrefid); 

    porttime_refrd.tv_sec = 1;
    porttime_refrd.tv_usec = 0; //10 Seconds wait time for read port

    do
    {
        iret = select(m_fdRefdev + 1, &fdrefid, NULL, NULL, &porttime_refrd);
        switch(iret)
        {
            case READ_TIMEOUT:
                g_dbg->debug("Refid portread: Select timeout:readlen=%d \n",ilen);
                ierr = -1;
                break;

            case READ_ERROR:
                g_dbg->debug("Refid portread: Select error:readlen=%d \n",ilen);
                ierr = -1; 
                break;

            default:
                iret = read(m_fdRefdev, buf, ilen); 
                g_dbg->debug("Refid portread: Read len(%d):%d\n",ilen,iret);
                break;
        }
    }while((ierr == 0) && (iret<ilen) );          

    //Flush terminal content at Input and Output after every read completion
//  tcflush(m_fdRefdev, TCIOFLUSH); 

    return ierr;

}

如果我在运行实现之前每次初始化,我得到128个字节但数据在64字节后损坏。即使在开始工作之前,我也会得到很多READ_ERROR。看起来原作者希望设备使用select()进行阻止,但事实并非如此 系统中的ttyACM0缓冲区大小是否存在某种类型的限制?波特率是否与ttyACM驱动程序有关?读取所有字节后read()是否停止读取(认为前64个可用,然后为空,然后是更多数据)?

通过手册页但我陷入了困境。非常感谢任何帮助。

继承我的最新消息:

   int CACS_RefID::Get_GasTest_Result(int ilen)
{
    int ierr=0, iret = 0, ictr=0, iread=0;
    fd_set  fdrefid;      
        struct timeval porttime_refrd;

    porttime_refrd.tv_sec = 5;
    porttime_refrd.tv_usec = 0; //10 Seconds wait time for read port


    if (Get_GasTest_FirstPass == 0)
    {
        g_dbg->debug("GasTest_Result_firstPass\n");
        memset(strresult, 0, sizeof(strresult));        //SLY clear out result buffer
        iread=0;
        Get_GasTest_FirstPass = 1;
    }

    do
    {
        iread = strlen(strresult);

        FD_ZERO(&fdrefid);
        FD_SET(m_fdRefdev,&fdrefid); 

        iret = select(m_fdRefdev + 1, &fdrefid, NULL, NULL, &porttime_refrd);
        switch(iret)
        {
            case READ_TIMEOUT:      //0
                g_dbg->debug("Get_GasTest_Result: Select timeout\n");
                ierr = -1;
                break;

            case READ_ERROR:        //-1
                g_dbg->debug("Get_GasTest_Result: Select error=%d %s \n", errno,strerror(errno)) ;
                ierr = -1; 
                break;

        }
        iret = read(m_fdRefdev, (&strresult[0] + iread), (ilen-iread)); 
        g_dbg->debug("Get_GasTest_Result: ilen=%d,iret=%d,iread=%d \n",ilen,iret,iread);

    }while((ierr == 0) && (iread<ilen) );


    return ierr;

注意:我现在正在读取数据,无论选择错误如何,STILL只能获得64字节。我联系了我的设备制造商。一定是奇怪的事情。

2 个答案:

答案 0 :(得分:1)

以下是您的代码可能存在的一个问题;这可能不会导致你只获得64个字节,但它可以解释你所看到的。假设您使用128字节的缓冲区调用函数Readport_Refid()。换句话说,您的调用类似于:

char buffer[128];

Readport_Refid(128, buffer);

假设无论出于何种原因,第一次调用select()会使返回值为1(因为设置了一位)。你的代码只设置了一位,所以你去了,你读()

iret = read(m_fdRefdev, buf, ilen); 
g_dbg->debug("Refid portread: Read len(%d):%d\n",ilen,iret);
break;

IRET返回64(这意味着64个字节被读出)和程序打印好的消息,并且因为IERR仍为0和IRET(64)小于艾朗(128)你轮再次去调用select()。< / p>

假设您获得更多数据,而select()再次返回1。然后你将使用相同的ilen在相同的缓冲区上再次读取并覆盖读取的前64个字节。

至少,您应该执行以下操作。我只在改变的行下面显示了。首先添加一个iread变量,并确保使用它来保存已经读过的数据。然后使用iread确定您是否阅读了足够的内容。

int CACS_RefID::Readport_Refid(int ilen, char* buf)
{
    int ierr=0, iret = 0, ictr=0, iread = 0;

    [...]
            default:
                iret = read(m_fdRefdev, buf + iread, ilen - iread); 
                if (iret > 0)
                    iread += iret;

                g_dbg->debug("Refid portread: Read len(%d):%d\n",ilen,iret);
                break;
        }
    }while((ierr == 0) && (iread<ilen) );          

    [...]

****已编辑2013-08-19 ****

我想重申@wildplasser

发表的评论

你应该在循环周围的每次旅行中设置FD_SET。很棒的。

关于您的新代码,它是否有效或者您是否还有问题?

****再次编辑2013-08-19 ****

获得EINTR无需担心。您应该计划重置FD_SET并再次尝试。

答案 1 :(得分:0)

我不能说我知道为什么但是修复是在实现开始时调用初始化代码,即使它之前被调用过。如果我再次调用它,我可以读取128个字节。如果不这样做,我最多只能读取64个字节。