Date: Sat, 14 Aug 2010 18:30:55 +0100 From: Paul Thornton <prt@prt.org> To: freebsd-hackers@freebsd.org Subject: Problem detecting and reacting to serial break Message-ID: <4C66D2CF.9040408@prt.org>
next in thread | raw e-mail | index | archive | help
Hi, I'm working on a small piece of code that reads a data stream from the serial port, putting it into a buffer for processing later - for those interested, it is receiving DMX512 lighting control data - but I'm having trouble with the detection of a break condition on the serial line. I'd appreciate any suggestions from anyone. I'm using 8.0-RELEASE with uftdi and ucom driving the serial port. The format of this data is very simple - a break is sent, followed by 513 bytes of useful information; then after some arbitrary delay another break, and the next 513 bytes. So, I think, easy to do this - just wait for a break and read away. My problem is that despite setting the port up (as I think) correctly, the break seems to be ignored at a driver level and it appears as data byte of 0x00 (what I'd expect to see if IGNBRK was set). This is no good as I have no way to know where I am in the chunk of 513 bytes of data, so can't synchronize at all. I have the following code setting up my serial port: tcgetattr(fd, &options); printf("before: c_iflag=%x c_oflag=%x c_cflag=%x c_lflag=%x\n", options.c_iflag, options.c_oflag, options.c_cflag, options.c_lflag); options.c_iflag = (BRKINT | IGNPAR); options.c_oflag = 0; options.c_cflag = (CLOCAL | CREAD | CS8 | CSTOPB); options.c_lflag = 0; options.c_cc[VMIN] = 513; options.c_cc[VTIME] = 0; if (cfsetispeed(&options, BAUDRATE) < 0) { perror("cfsetispeed"); exit(1); } if (cfsetospeed(&options, BAUDRATE) < 0) { perror("cfsetospeed"); exit(1); } if (tcsetattr(fd, TCSANOW, &options) < 0) { perror("tcsetattr"); exit(1); } /* debug test - did anything change? */ tcgetattr(fd, &options); printf("after: c_iflag=%x c_oflag=%x c_cflag=%x c_lflag=%x\n", options.c_iflag, options.c_oflag, options.c_cflag, options.c_lflag); The debug output shows my set is doing what I expect it to: before: c_iflag=2005 c_oflag=3 c_cflag=cf00 c_lflag=443 after: c_iflag=6 c_oflag=0 c_cflag=8f00 c_lflag=0 So according to the documentation, the effect of the break should be to flush the input and output buffers, and send a SIGINT to my process. The buffer doesn't seem to get flushed, and I don't get sent the SIGINT. The data I'm getting in my buffer is valid, apart from the fact that I can't tell where byte 1 is - and every time I run the test program the location of byte 1 changes arbitrarily depending on what was in the receive buffer. Have I missed something here, or is there any other way that I can detect the presence of the break out-of-band? I cannot make any assumptions about the 513 bytes that I'm receiving and any combination of data may be present in there. Many thanks, Paul.
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?4C66D2CF.9040408>