[ERROR:Resource temporarily unavailable!] Serial writing by termios library

Hello,
I am using the termios library to write data that I get from a Bluetooth device to a modem via serial.
The data arrive from the Bluetooth device correctly every 50ms and I have to bypass them on the serial ttyUSB3 where it is connected to a modem connected to a socket with static IP.
The writing is successful until I get the following message:

write error 11 Resource temporarily unavailable

I open the door in non-blocking ( OpenPort(0) )mode and the class that I use is as follows:

#include "cclassseriallib_modem.h"
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <termios.h>
#include <string.h>
#include <errno.h>


cClassSerialLIB_modem::cClassSerialLIB_modem()
{
}

bool cClassSerialLIB_modem::OpenPort(bool bloccante)
{
// make sure port is closed
ClosePort();

fd = open("/dev/ttyUSB3", O_RDWR |
O_NOCTTY | /* tells UNIX that this program doesn't want to be the "controlling terminal" for that port*/
O_NDELAY); /* tells UNIX that this program doesn't care what state the DCD signal line is in */

if (fd < 0)
{
printf("open error %d %s\n", errno, strerror(errno));
return false;
}
else
{
struct termios options;

/* The FNDELAY option causes the read function to return 0 if no
characters are available on the port. To restore normal (blocking) behavior,
call fcntl() without the FNDELAY option: */

if(bloccante)
{
printf("bloccante\n");
fcntl(fd, F_SETFL, 0);
}
else
{
printf("NON bloccante");
fcntl(fd, F_SETFL, FNDELAY);
}

tcgetattr(fd, &options);

//set port speed
cfsetispeed(&options, B115200);
cfsetospeed(&options, B115200);

options.c_cflag |= (CLOCAL | CREAD);

//set 8n1
options.c_cflag &= ~PARENB; /* Enable parity bit */
options.c_cflag &= ~CSTOPB; /* 2 stop bits (1 otherwise) */
options.c_cflag &= ~CSIZE; /* Mask the character size bits */
options.c_cflag |= CS8; /* Select 8 data bits */

/*options.c_cflag &= ~CRTSCTS;
options.c_iflag &= ~IXON; //RIMUOVE X0N/XOFF control
options.c_iflag &= ~IXOFF;
options.c_iflag &= ~IGNCR;
*/

//set raw input
options.c_lflag &= ~(ICANON | /* Enable canonical input (else raw) */
ECHO | /*Enable echoing of input characters */
ECHOE | /*Echo erase character as BS-SP-BS*/
ISIG); /*Enable SIGINTR, SIGSUSP, SIGDSUSP, and SIGQUIT signals*/

tcsetattr(fd, TCSANOW, &options); /*Make changes now without waiting for data to complete*/
}
return true;
}

int cClassSerialLIB_modem::WritePort(QString psOutput)
{
int iOut;
QByteArray ba = psOutput.toLocal8Bit();

if (fd < 1)
{
printf(" port is not open\n");
return -1;
} // end if

iOut = write(fd, ba.data(), strlen(ba.data()));
if (iOut < 0)
{
printf("write error %d %s\n", errno, strerror(errno));
}
else
{
printf("wrote %d chars: %s\n", iOut, ba.data());
} // end if
return iOut;
}

int cClassSerialLIB_modem::ReadPort(QString * Response)
{

int iIn;
char psResponse[254];

if (fd < 1)
{
printf(" port is not open\n");
return -1;
} // end if

iIn = read(fd, psResponse, 254);

if (iIn < 0)
{
if (errno == EAGAIN)
{
return 0; // assume that command generated no response
}
else
{
printf("read error %d %s\n", errno, strerror(errno));
} // end if
}
else
{
psResponse[iIn<254?iIn:254] = '\0';
printf("read %d chars: %s\n", iIn, psResponse);
} // end if

*Response=QString::fromLocal8Bit(psResponse);

return iIn;
}

void cClassSerialLIB_modem::ClosePort()
{
// you may want to restore the saved port attributes
if (fd > 0)
{
close(fd);
} // end if
}

thanks for help.

It's connected to a modem that's already connected to a static IP? Is this a SLIP setup? Is the port already grabbed by the driver? You may need to communicate over the network, not over the raw port.

i write At command on serial port for connect modem at server!

I still suspect there's something wrong with how you're using the port.

I wrote an example program to use termios in Linux, see tcgets.c and tcgets.h

why? it work correctly.. is a problem with FIFO memory...

EAGAIN is returned by a write on a blocked socket that opened non-blocking.

This means you are trying to write to a socket that cannot take more data right now.

So, in light of what we are saying what do you think?

Obviously not, or you wouldn't have made this thread...

Have you tried my code?

no, your code is very complicated!

It's a library, you can just use it without modifying. It's the same one I use for nearly all my serial code(i.e. I use it quite a lot -- both serial ports and three USB serial converters on our server are occupied already).

Why not try it. It even included example code. I'll make it plainer:

You do this:

$ cat <<EOF >mycode.c
#include <stdio.h>
#include <unistd.h>
#include "tcgets.h"

int main(void)
{
        int fd=termios_open("/dev/ttyUSB3", "115200N81");
        ssize_t bw;

        if(fd<0)
        {
                perror("Couldn't open ttyUSB3");
                return(1);
        }

        bw=write(fd, "TEST", 4);
        fprintf(stderr, "Wrote %d bytes\n", bw);
        if(bw <= 0)
        {
                perror("Couldn't write");
                return(1);
        }
        return(0);
}

EOF

$ gcc mycode.c tcgets.c -o mycode
$ ./mycode

ah ok tomorrow i try.. now good night and thanks

i was having the same trouble as you: was able to send, but not read from the serial terminal. After some hackery, i figured out i was missing a settings:

i had to enable hardware flow control, and match the correct speed.

tcgetattr(fdInputStream, &options);

//set port speed
cfsetispeed(&options, B230400);
cfsetospeed(&options, B230400);

//enable reader, indicate that hw-flow-control is active
options.c_cflag |= (CLOCAL | CREAD | CRTSCTS);

//set 8n1
options.c_cflag &= ~PARENB; /* Enable parity bit /
options.c_cflag &= ~CSTOPB; /
2 stop bits (1 otherwise) /
options.c_cflag &= ~CSIZE; /
Mask the character size bits /
options.c_cflag |= CS8; /
Select 8 data bits /
//set raw input
options.c_lflag &= ~(ICANON | /
Enable canonical input (else raw) */
ECHO | /*Enable echoing of input characters */
ECHOE | /Echo erase character as BS-SP-BS/
ISIG); /Enable SIGINTR, SIGSUSP, SIGDSUSP, and SIGQUIT signals/

Also, if you have another program that can read from the same serial port (e.g. demo program) you can always check the current settings for the serial device

e.g.
stty -f /dev/tty.mydevice