Pregunta

I have an open file descriptor for "/dev/ttyS0" which used to read data from a RS232 device. I am trying to use an epoll instance to do concurrent read from file descriptor As I am getting an error (Resource temporarily unavailable) while reading data from the file descriptor. I have sample code written with epoll to do this but it is not running as expected. Program is infinitely waiting at epoll_wait() call.

Please help me to verify the way I wrote the code
fdRS232 is the opened file descriptor for /dev/ttyS0

int DeviceRS232::readDecoderData(unsigned char *dataBuffer, size_t bufferSize)
{
    unsigned char recvBuffer[251];
    unsigned char *ptrChar;
    int nBytes, portStatus;
    int inputBufSize = 0;

    // Use epoll for read and write event handling
    int fdEpoll, returnStatus;
    struct epoll_event rwEpollEvent;
    struct epoll_event *prwEpollEvent;

    fdEpoll = epoll_create1(0);
    if(fdEpoll == -1)
    {
        std::cout << "Error: " << strerror(errno);
        return 0;
    }

    rwEpollEvent.data.fd = fdRS232;
    rwEpollEvent.events = EPOLLIN | EPOLLET;

    returnStatus = epoll_ctl(fdEpoll, EPOLL_CTL_ADD, fdRS232, &rwEpollEvent);
    if(returnStatus == -1)
    {
        std::cout << "Error: " << strerror(errno);
        return 0;
    }
    prwEpollEvent = (epoll_event *)calloc(MAX_EVENTS, sizeof(rwEpollEvent));

    while(true)
    {
        std::cout << "test1" << std::endl;
        int nfd;
        nfd = epoll_wait(fdEpoll, prwEpollEvent, MAX_EVENTS, -1);
        std::cout << "ndf: " << nfd << std::endl;

        for(int x=0; x<nfd; x++)
        {
            std::cout << "test-for" << std::endl;
            if(prwEpollEvent[x].events & EPOLLERR ||
               prwEpollEvent[x].events & EPOLLHUP ||
               !(prwEpollEvent[x].events & EPOLLIN))
            {
                std::cout << "test2" << std::endl;
                std::cout << "epoll error: " << strerror(errno);
                close(prwEpollEvent[x].data.fd);
                continue;
            }
            else
            {
                std::cout << "test3" << std::endl;
                ChangeCTS(fdRS232, 0);
                ChangeRTS(fdRS232, 0);

                while(inputBufSize <= 0)
                {
                    ioctl(fdRS232, FIONREAD, &inputBufSize);
                    usleep(1);
                }


                if(inputBufSize > 0)
                {
                    int decodePacketLen = 0;
                    //unsigned char
                    memset(recvBuffer, 0x00, sizeof(recvBuffer));
                    nBytes = 0;

                    usleep(100000);
                    while(nBytes < ((int)recvBuffer[0] + 2))
                    {
                        int index = 0;
                        int recvDataLen = 0;
                        if(nBytes != 0)
                            index = nBytes - 1;

                        recvDataLen = read(fdRS232, &recvBuffer[index], 251);
                        if(recvDataLen < 0)
                        {
                            std::cout << "[INFO@DeviceRS232::receiveDecodedData]File read error: " << strerror(errno) << std::endl;
                            //sleep(1);
                        }

                        nBytes += recvDataLen;
                        if(nBytes == ((int)recvBuffer[0] + 2))
                            break;

                    }

                    if(recvBuffer[1] == DECODE_DATA)
                        sendCommandToDecoder(OPCODE_ACK);

                    std::cout << "[INFO @ DeviceRS232::receiveDecodedData]Data Lenght (without CheckSum) : " << (int)recvBuffer[0] << std::endl;

                    for(int i=0; i<nBytes; i++)
                    {
                        std::cout << "recvBuffer[" << i << "]: ";
                        printf("%x\n", recvBuffer[i]);
                    }
                    std::cout << "-----------------------------------" << std::endl;

                    //ChangeRTS(fdRS232, 1);
                    //ChangeCTS(fdRS232, 1);
                    //sleep(1);
                }

            }
        }
    }

    free(prwEpollEvent);

    //strcpy((char *)dataBuffer, (char *)recvBuffer);
    memcpy((char *)dataBuffer, recvBuffer, sizeof(recvBuffer)/sizeof(recvBuffer[0]));
    inputBufSize = 0;

    return nBytes;
}
¿Fue útil?

Solución

Program is infinitely waiting at epoll_wait() call.

This is possibly due to using EPOLLET. See man epoll, Level-triggered and edge-triggered:

the caller might end up waiting for some data that is already present inside the input buffer.

Just use

    rwEpollEvent.events = EPOLLIN;

instead.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top