Mail Archives: cygwin/2006/09/05/07:47:17
--------------040609070706000004070603
Content-Type: text/plain; charset=ISO-8859-1; format=flowed
Content-Transfer-Encoding: 7bit
Hello Igor,
Sorry for my incomplete question.
I attach to you the following file that could be compiled with gcc in
CYGWIN.
Accepted commands start by '?' character, and when the device is not
connected on the serial line the function read(...) blocks:
DEVICE test program
-------------------
Type your commands ('.' to quit):
>> Enter command: ?ver
Then, blocked....:-((
Note that in our computers the serial line name is COMn not /dev/ttySn.
I tried before with /dev/ttySn and I receive file not found as answer.
Thank you for your help,
Ernesto.
PS.: more details about CYGWIN
PAISER AT tenerife ~
$ uname -a
CYGWIN_NT-5.1 tenerife 1.5.21(0.156/4/2) 2006-07-30 14:21 i686 Cygwin
Igor Peshansky wrote:
> On Tue, 22 Aug 2006, Ernesto Paiser wrote:
>
>> Hello Corinna,
>
> FYI, this is a mailing list, and unless you're replying to a specific
> message, you're actually talking to many people.
>
>> I have problems with read() function blocking and
>> waiting for characters on serial line with cygwin:
>>
>> Here are some code fragments:
>> ========================================================
>> fd = open(sl, O_RDWR | O_NOCTTY | O_NONBLOCK | O_NDELAY)
>>
>> newpio.c_cflag = brate | CS8 | CLOCAL | CREAD;
>> newpio.c_iflag = IGNPAR | ICRNL;
>> newpio.c_oflag = 0;
>> newpio.c_lflag = 0;
>> newpio.c_cc[VTIME] = 1;
>> newpio.c_cc[VMIN] = 0;
>> ...
>>
>> n = ioctl(fd, TIOCINQ, &n); //It gives me an error (return -1) why??!!!
>>
>> and
>>
>> n = read(fd, buffer, 1); <<< HERE IS BLOCKING!!!
>> ========================================================
>>
>> TIOCINQ is working on CYGWIN,
>>
>> Is there another way to solve this problem???
>
> Please post a complete compilable test case that reproduces the problem.
> For example, in the above code, it's unclear what the variable sl contains
> (and I suspect it contains "COM1", which is a no-no -- you should be using
> "/dev/ttyS0").
> Igor
--
Ernesto PAISER ____________________ paiser AT esrf DOT fr
E.S.R.F. - European Synchrotron Radiation Facility
6 rue Jules Horowitz BP 220 Grenoble CEDEX France
phone +33 4 76 88 23 48 fax +33 4 76 88 23 25
--------------040609070706000004070603
Content-Type: text/plain;
name="serial_tiocinq.c"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline;
filename="serial_tiocinq.c"
#include <stdio.h> /* Standard input/output definitions */
#include <string.h> /* String function definitions */
#include <unistd.h> /* UNIX standard function definitions */
#include <fcntl.h> /* File control definitions */
#include <errno.h> /* Error number definitions */
#include <termios.h> /* POSIX terminal control definitions */
#include <ctype.h>
#include <stdlib.h>
#include <sys/select.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/time.h>
// ............................................................................
// function declarations
int serial_init (int portn, long baudrate);
int serial_getchar(int fd, char *buffer);
int serial_putnchar(int fd, char *data, int n);
void serial_flush(int fd);
void serial_close(int fd);
char *device_get(int fd);
char *device_comm(int fd, char *comm);
int device_getchar(int fd, char *buffer);
char *device_getline(int fd);
size_t check_rxbuffer(void);
int is_a_query(char *comm);
// ............................................................................
# ifndef TEMP_FAILURE_RETRY
# define TEMP_FAILURE_RETRY(expression) \
(__extension__ \
({ long int __result; \
do __result = (long int) (expression); \
while (__result == -1L && errno == EINTR); \
__result; }))
# endif /* TEMP_FAILURE_RETRY */
# define TFR TEMP_FAILURE_RETRY
//#define SLNAME_FORMAT "/dev/ttyS%d" // It doesn't work on Windows XP
#define SLNAME_FORMAT "COM%d" // I'm using CYGWIN on Windows XP
#define INBUFF_SZ 1024
#define NO_ANSWER ((char *)-1)
#define COMM_PREFIX "COM"
#define BAUDRATE_CHAR '@'
#define DEF_BAUDRATE 9600
#define CR_STR "\r"
#define CR_CHAR '\r'
#define NL_CHAR '\n'
#define ACKN_CHAR '#'
#define QUERY_CHAR '?'
#define MIN_RXBUFSIZE 1024
#define MAX_RXBUFSIZE (128 * 1024)
#define COM1 1
#define COM2 2
#define COM3 3
#define COM4 4
struct termios oldpio; // placeholder for original port settings
size_t rxbuffsize;
char *rxbuff;
char *rxbuffend;
int rxlines;
// ............................................................................
int main(void) {
char inbuff[INBUFF_SZ];
char *comm;
char *answ;
int fd;
fd = serial_init(COM1, 9600L);
if (fd < 0) {
printf("ERROR: %s\n", "serial_init()");
exit(EXIT_FAILURE);
}
printf(" DEVICE test program\n");
printf(" -------------------\n\n");
printf("Type your commands ('.' to quit):\n");
while(1) {
printf(">> Enter command: ");
comm = fgets(inbuff, INBUFF_SZ, stdin);
while(isspace(*comm))
comm++;
if (!*comm)
continue;
if (*comm == '.')
break;
answ = device_comm(fd, comm);
if (answ == NO_ANSWER)
;
else if (answ)
printf("Answer: [%s]\n", answ);
else
printf("ERROR: %s\n", "device_comm()");
}
return(EXIT_SUCCESS);
}
int serial_init(int portn, long baudrate) {
struct termios newpio; // placeholder for new port settings
long brate; // baudrate value
int fd;
char sl[sizeof(SLNAME_FORMAT)];
if (portn < 0 || portn > 99) {
fprintf(stderr, "serial_init(): Bad port number\n");
return (-1);
}
sprintf(sl, SLNAME_FORMAT, portn);
if ((fd = open(sl, O_RDWR | O_NOCTTY | O_NONBLOCK | O_NDELAY)) < 0) {
perror("serial_init()");
return (-1);
}
tcgetattr(fd, &oldpio); // save current port settings
bzero(&newpio, sizeof(newpio)); // clear struct for new port settings
switch (baudrate) {
case 38400:
brate = B38400;
break;
case 19200:
brate = B19200;
break;
case 9600:
brate = B9600;
break;
case 4800:
brate = B4800;
break;
case 2400:
brate = B2400;
break;
}
// in a more general case one could select
// newpio.c_cflag = brate | DATABITS | STOPBITS | PARITY | CLOCAL | CREAD;
newpio.c_cflag = brate | CS8 | CLOCAL | CREAD;
newpio.c_iflag = IGNPAR | ICRNL;
newpio.c_oflag = 0;
newpio.c_lflag = 0;//ICANON;
newpio.c_cc[VTIME] = 1; // inter-character timer unused
newpio.c_cc[VMIN] = 0; // blocking read until 1 character arrives
tcflush(fd, TCIOFLUSH); // flush data in internal buffers
tcsetattr(fd, TCSANOW, &newpio);
rxbuff = NULL;
rxbuffsize = 0;
return fd;
}
int input_timeout (int fd)
{
fd_set set;
struct timeval timeout;
/* Initialize the file descriptor set. */
FD_ZERO (&set);
FD_SET (fd, &set);
/* Initialize the timeout data structure. */
timeout.tv_sec = 0;
timeout.tv_usec = 0;
// select should return 0 if timeout, 1 if input available, -1 if error.
return TFR(select(fd + 1, &set, NULL, NULL, &timeout));
}
int serial_getchar(int fd, char *buffer) {
ssize_t n;
n = input_timeout (fd); // it doesn't work...
// n = ioctl(fd, FIONBIO , &optval); //
// n = ioctl(fd, FIONREAD, &optval); // FIONREAD not defined on CYGWIN!!!!
n = ioctl(fd, TIOCINQ, &n); // It gives me an error (return -1)
if (n)
n = read(fd, buffer, 1);
if (n == EINTR || n == EAGAIN || n == 0) { // read interrupted or not data available
n = 0;
} else if (n != 1) {
perror("serial_getchar()");
return(-1);
}
return(n);
}
int serial_putnchar(int fd, char *data, int n) {
n = write (fd, data, (ssize_t)n);
if (n < 0) {
perror("serial_putnchar()");
return(-1);
}
return(n);
}
void serial_flush(int fd) {
tcflush(fd, TCIOFLUSH); // flush data in internal buffers
}
void serial_close(int fd) {
close(fd);
tcsetattr(fd, TCSANOW, &oldpio);
}
char *device_comm(int fd, char *comm)
{
char *answer;
serial_flush(fd);
if (serial_putnchar(fd, comm, strlen(comm)) < 0) {
return(NULL);
} else if (serial_putnchar(fd, CR_STR, sizeof(CR_STR) - 1) < 0) {
return(NULL);
}
if (is_a_query(comm))
answer = device_get(fd);
else
answer = NO_ANSWER;
return(answer);
}
char *device_get(int fd)
{
char *line;
int nlines;
rxbuffend = rxbuff;
line = device_getline(fd);
if (!line) {
nlines = -1;
} else
nlines = 1;
rxlines = nlines;
return (nlines < 0 ? NULL : rxbuff);
}
char *device_getline(int fd)
{
int remsize;
time_t tout;
int nloffset;
if (!(remsize = check_rxbuffer())) {
return(NULL);
}
nloffset = rxbuffend - rxbuff;
tout = time(NULL) + 2; // crappy 2 sec timeout
while(time(NULL) < tout) {
int c;
c = device_getchar(fd, rxbuffend);
if (c) {
if (c < 0) {
return(NULL);
} else {
rxbuffend++;
remsize--;
if (c == NL_CHAR)
return(rxbuff + nloffset);
else if (!remsize) {
if (!(remsize = check_rxbuffer()))
return(NULL);
}
}
}
}
printf("ERROR: %s\n", "device_getline()");
return(NULL);
}
size_t check_rxbuffer(void)
{
size_t buffsize;
size_t newsize;
char *newbuff;
buffsize = rxbuffend - rxbuff;
if (!rxbuffsize) {
newsize = MIN_RXBUFSIZE;
} else if (rxbuffsize == buffsize) {
if (rxbuffsize < MAX_RXBUFSIZE)
newsize = 2 * rxbuffsize;
else
return(0);
} else {
return(rxbuffsize - buffsize);
}
if (!(newbuff = realloc(rxbuff, newsize)))
return(0);
rxbuffsize = newsize;
rxbuff = newbuff;
rxbuffend = newbuff + buffsize;
return(newsize - buffsize);
}
int device_getchar(int fd, char *buffer)
{
int nchar;
int c;
nchar = serial_getchar(fd, buffer);
if (nchar == 0) {
return(0);
} else if (nchar < 0) {
printf("ERROR: %s\n", "device_getchar()");
return(-1);
}
c = *buffer;
if (c == NL_CHAR) {
*buffer = 0;
return(NL_CHAR);
} else if (c < ' ')
return(0);
else
return(c);
}
int is_a_query(char *comm)
{
char firstc;
// skip whitespaces
while((firstc = *comm) != 0 && isspace(firstc))
comm++;
if (isdigit(firstc)) {
comm++;
while((firstc = *comm) != ':')
comm++;
return(is_a_query(++comm));
} else if (firstc == '>')
return(is_a_query(++comm));
else if (firstc == ACKN_CHAR || firstc == QUERY_CHAR)
return(1);
else
return(0);
}
--------------040609070706000004070603
Content-Type: text/plain; charset=us-ascii
--
Unsubscribe info: http://cygwin.com/ml/#unsubscribe-simple
Problem reports: http://cygwin.com/problems.html
Documentation: http://cygwin.com/docs.html
FAQ: http://cygwin.com/faq/
--------------040609070706000004070603--
- Raw text -