Click to See Complete Forum and Search --> : cfmakeraw tricks? putting modem to raw mode...


registering
06-06-2003, 03:27 PM
Hi all,
I am trying to put my modem into raw mode, so it manipulates no data sent thru it, however it seems to be echoing. I can't be certain, because there's a device on the other end I don't know enough about. I've looked through the cfmakeraw settings, and my code is below. I know it's a lot to look at, but maybe someone knows any tricks for Linux? This is 2.4.18-4. Thanks for any help.



/************************************************** ****************************
Procedure: open_client_serial_port(...)

Purpose: Attempts to open the serial port passed-in as parameter 'port'

Returns: int: 1 if the serial device could not be opened

Notes: This might also 'exit' and not just 'return' if we could not open our
serial device!
************************************************** ****************************/
int open_client_serial_port(comm_data_t* port,
const comm_connection_t* environment,
FILE* logfile)
{
int retval = 0; /* our return value */

port->fd = open(port->dev, O_RDWR | O_NOCTTY | O_NDELAY);
if (port->fd < 0)
{
logger(logfile, "ERROR -- 2 Could not open our serial device");
perror(port->dev);
retval = 1;
port->comm_status = COMM_DOWN;
}
else
{
/* we could open our serial port */

logger(logfile," -- Debug: 2 Successfully opened our serial device");

tcgetattr(port->fd,&port->ser_oldtio); // save the current modem setting so we can restore them
tcgetattr(port->fd,&port->ser_newtio); // save the current modem settings to the new settings structure
cfmakeraw(&port->ser_newtio); // set struct for new term settings to raw. See man 'cfmakeraw'
port->ser_newtio.c_cflag &= ~CRTSCTS; // make sure rts/cts flow control is turned off
port->ser_newtio.c_cflag |= (CLOCAL | CREAD); // make sure receiver is enabled and port owner not changed
port->ser_newtio.c_iflag &= ~(IXON | IXOFF | IXANY);// make sure software flow control is off
cfsetispeed(&port->ser_newtio, port->ser_speed); // set the input baudrate for new terminal settings
cfsetospeed(&port->ser_newtio, port->ser_speed); // set the output baudrate for new terminal settings
tcflush(port->fd, TCIOFLUSH); // clear the input and output port buffers
tcsetattr(port->fd,TCSANOW,&port->ser_newtio); // set the new attributes for the serial port immediately
tcgetattr(1,&port->ser_old_stdout_tio); // we gotta do this - there is a Linux bug
tcsetattr(1,TCSANOW,&port->ser_newtio); // make stdout settings like modem settings
tcgetattr(0,&port->ser_oldstdtio); // get stdin settings for restoration ...
tcgetattr(0,&port->ser_newstdtio); // ... and use them as a basis for changes
port->ser_newstdtio.c_lflag &= ~(ICANON | ECHO); // make them raw
tcsetattr(0,TCSANOW,&port->ser_newstdtio); // set the new attributes immediately

port->comm_status = COMM_OK; //we really need some error checing on all of the above calls ...
}

if (port->fd < 0)
{
logger(logfile, "ERROR -- 2b Could not open our serial device");
perror(port->dev);
exit(-1);
}

//set the serial port to return immediately after a read
fcntl(port->fd, F_SETFL, O_NONBLOCK);

//if we are using an RF95A the RTS line must be disabled (low)
if (environment->RF_MODEM_95A == 1)
{
ioctl(port->fd, TIOCMGET, &port->modem_line);
port->modem_line &= ~TIOCM_RTS;
ioctl(port->fd, TIOCMSET, &port->modem_line);
} /* end if */

return(retval);

} /* end open_client_serial_port */

registering
06-06-2003, 07:25 PM
Okay, I'm not sure if my serial port is set properly, but for the life of me I
can't figure out what's wrong. The algorithm I'm using to send the data is very
simple, it just reads from PASSTHRU socket, sends it to INST socket, and vice
versa. However I'm also new to sockets programming so I might be doing something
very stupid.

The weird thing, is if I display the data RIGHT BEFORE I send it, it looks great!
However if I telnet to my socket, I can clearly see it's not arriving properly.
:( For example, a '+' sign might be stripped, or some characters might be missing.

If I shove data to a socket, should I tcdrain() before writing to it again? Should
I see if anything's in that buffer before I write to it again? Wouldn't that block?

Anyway, I'm going to try the above but I don't have much confidence it will work.
Any suggestions are welcome, and as always, thanks for the outstanding help I get
some everyone on this board.

Josh





listening procedure(...)

unsigned int passthruClientLen;
int maxfd = (port[REMORA].fd) + 1;
int i, a, k, p;
char input;
int select_value;
char head[4096];
char tempbuf[4096];
int num_bytes;
fd_set watchset;
struct timeval loopdelay;
FILE* comm_file;


/* all sockets are open */

while (TRUE)
{
strcpy(tempbuf, "");
strcpy(head, "");
.
.
.
loopdelay.tv_sec = 0; //SELECTDELAY;
loopdelay.tv_usec = 0; /* must reset this for each call - select diddles it */
FD_ZERO(&watchset); /* clear all bits in this set */
FD_SET(port[INST].fd, &watchset); /* watch our data instrument */
FD_SET(port[PASSTHRU].fd, &watchset); /* watch the passthru */

if ((select_value = select(maxfd, &watchset, NULL, NULL, &loopdelay)) > 0)
{
if (FD_ISSET(port[PASSTHRU].fd, &watchset))
{
//logger(logfile, " -- Debug 13 Someone is passing through....");

/* we received something from our passthru */
/* this should only happen upon the first connection */

/* first set our flag that passthru has priority until released */
passthruActive = 1;

/* we could open and close the client socket each time but this has two */
/* big drawbacks: 1) lots of kernel traffic; 2) only 1 client will ever */
/* be able to speak thru the PASSTHRU at a time, which might be a problem */
/* for future features */
if (port[PASSTHRU].clientSocket == -1)
{
/* this is our first client connection */

/* Set the size of the in-out parameter */
passthruClientLen = sizeof(port[PASSTHRU].clientAddress);

/* we've received data from the passthru port */
if ((port[PASSTHRU].clientSocket = accept(port[PASSTHRU].fd,
(struct sockaddr *) &port[PASSTHRU].clientAddress,
&passthruClientLen)) < 0)
{
;//logger(logfile, "ERROR -- 9 We could not accept the call from the passthru socket");
} /* end if accept... */
else
{
/* now that we've accepted the connection, listen */
FD_SET(port[PASSTHRU].clientSocket, &watchset);

/* must increase maxfd to listen to new client socket */
if (port[PASSTHRU].clientSocket >= maxfd)
{
maxfd = port[PASSTHRU].clientSocket + 1;
} /* end if */

/* now read from new client socket */
num_bytes = read(port[PASSTHRU].clientSocket, head, port[PASSTHRU].size - (port[PASSTHRU].buf_idx + 1));

if (num_bytes > 0)
{
strncpy(tempbuf, head, num_bytes);
tempbuf[num_bytes] = 0x00; //add NULL

/* we got our newly assigned socket from accept */
/* printf("Handling client %s\n", inet_ntoa(echoClntAddr.sin_addr)); */
send_passthru_data_to_modem(head, port[INST].fd);
} /* end if */

else
{
/* we couldn't find any data on client socket?? */
;
} /* end else */

} /* end else we could accept() */

} /* end if clientSocket == -1 */

else
{
/* we've been here before, client is waiting... */
/* now read from new client socket */
num_bytes = read(port[PASSTHRU].clientSocket, head, port[PASSTHRU].size - (port[PASSTHRU].buf_idx + 1));

if (num_bytes > 0)
{
strncpy(tempbuf, head, num_bytes);
tempbuf[num_bytes] = 0x00; //add NULL

/* our client socket was previously established */
send_passthru_data_to_modem(head, port[INST].fd);

} /* end if */

} /* end else */

} /* end if PASSTHRU */


if (FD_ISSET(port[INST].fd, &watchset))
{
/* we're told something is waiting from the data device */
num_bytes = read(port[INST].fd, head, port[INST].size - (port[INST].buf_idx - 1));

/* see if we have any data to read */
if (num_bytes > 0)
{
strncpy(tempbuf, head, num_bytes);
tempbuf[num_bytes] = 0x00; //add NULL

/* test to see if must transfer the data untouched, or we can modify it */
if (passthruActive == 1)
{
/* passthru is active, so just send whatever modem sent us */
/* back out thru passthru */
for (a = 0; a < strlen(tempbuf); a++)
{
printf("[%i]:%i ", a, tempbuf[a]);
}
printf(" TO PASTHRU:\n%s\n", tempbuf);
send_modem_data_to_passthru(head, port[PASSTHRU].clientSocket);
} /* end if passthruActive */

else if (passthruActive == 0)
{
/* write the data we received to our traffic file */
;

} /* end else if passthruActive == 0 */

else
{
/* passthruActive is neither 0 nor 1, which should never happen!! */
;
} /* end else */

} /* end if num_bytes > 0 */

} /* end if FD_ISSET [INST] */

} /* end if select */

} /* end while loop */

} /* end init_data_device() loop */

else
{
logger(logfile, "ERROR -- 8 We could not initialize our data device");
return (FALSE);
} /* end else if data device returned FALSE */

return (TRUE);

} /* end listening(...) */





int send_passthru_data_to_modem(char *input_buffer, int modem_fd)
{
/* take everything we got from the passthru socket and give it to modem */
return (write(modem_fd, input_buffer, sizeof(input_buffer)));

} /* end send_passthru_data_to_modem(...) */

int send_modem_data_to_passthru(char *input_buffer, int passthruSocket)
{
return (write(passthruSocket, input_buffer, sizeof(input_buffer)));
} /* end send_modem_data_to_passthru(...) */