void init_serial_port(serial_info_t &sio) { // Variable declarations struct termios options; // Open the serial port sio.serial_fd = open(sio.deviceName, O_RDWR | O_NOCTTY | O_NDELAY); //If the port was successfully opened, configure it if (sio.serial_fd != -1) { /* Ref: http://www.easysw.com/~mike/serial/serial.html#config * First, get the current port attributes */ tcgetattr(sio.serial_fd, &options); // Set input and output baud rates cfsetispeed(&options, sio.baud); cfsetospeed(&options, sio.baud); /* The c_cflag member contains two options that should always be enabled, * CLOCAL and CREAD. These will ensure that your program does not become * the 'owner' of the port subject to sporatic job control and hangup * signals, and also that the serial interface driver will read incoming * data bytes. */ options.c_cflag |= (CLOCAL | CREAD); // Configure 8 bits, no parity, 1 stop bit options.c_cflag &= ~PARENB; options.c_cflag &= ~CSTOPB; options.c_cflag &= ~CSIZE; options.c_cflag |= CS8; // Disable hardware flow control options.c_cflag &= ~(IHFLOW | OHFLOW); // Disable software flow control options.c_iflag &= ~(IXON | IXOFF | IXANY); // Choose raw input options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG); // Choose raw output options.c_oflag &= ~OPOST; options.c_cc[VMIN] = sio.minRecordSize; options.c_cc[VTIME] = sio.maxCharWait; // Apply changes now, do not wait for data to complete tcsetattr(sio.serial_fd, TCSANOW, &options); } // end of if sio.emptyReadB4=0; // TODO: remove when not needed sio.emptyReadAft=0; } // end of init_serial_port void clear_and_arm_serial_port(int32 fd, struct sigevent * event) { int32 flags; // ionotify flags int32 nbytes; // number of bytes read char buf[STD_STR_LEN]; // buffer to write into // As long as there is data on the port, grab it flags = ionotify (fd, _NOTIFY_ACTION_POLLARM, _NOTIFY_COND_INPUT, event); while (flags & _NOTIFY_COND_INPUT) { nbytes = read(fd, buf, sizeof(buf)-1); flags = arm_serial_port(fd, event); } // end of while } // end of clear_and_arm_serial_port void open_and_arm_serial_port(serial_info_t &sio) { // Initialize the serial port log_print(LOG_INFO, 0, "Opening serial device (%s) %s.\n", sio.serialName, sio.deviceName); init_serial_port(sio); if (sio.serial_fd == -1) { // log Error opening device (%s).\n", sio.deviceName kill_the_app(EXIT_FAILURE); } log_print(LOG_INFO, 0, "Initialize the serial event pulse (%d).\n", sio.pulseID); // Initialize the serial event pulse SIGEV_PULSE_INIT(&sio.serial_event, self.coid, getprio(0), sio.pulseID, 0); log_print(LOG_INFO, 0, "First clear and arm.\n"); // Clear and arm the serial port clear_and_arm_serial_port(sio.serial_fd, &sio.serial_event); } // end of open_and_arm_serial_port uint16 receiveSerialData(serial_info_t &sio, unsigned char buf[]) { int32 flags; int16 bytes_read=0; uint16 bufNdx=0; uint16 spaceLeft; uint16 readAttempt=0; // used to detect and track errors sio.pulseCount++; // we got a pulse to get here. // Check the serial port flags = ionotify (sio.serial_fd, _NOTIFY_ACTION_POLLARM, _NOTIFY_COND_INPUT, &sio.serial_event); // As long as data is on the port, read it while (flags & _NOTIFY_COND_INPUT) { spaceLeft = sio.bufferSize-bufNdx; if (spaceLeft > 0) { // TIMEOUT is not used because (1) not part of POSIX standard (2) not a good idea readAttempt++; bytes_read = read(sio.serial_fd, &buf[bufNdx], spaceLeft); if(bytes_read>0) { bufNdx += bytes_read; } else { // error statistics accumulation } // end of else on bytes_read <= 0 flags = ionotify (sio.serial_fd, _NOTIFY_ACTION_POLLARM, _NOTIFY_COND_INPUT, &sio.serial_event); } else { // log attempted buffer overflow flags=0; } // end of else on spaceLeft <= 0 } // end of outer while return bufNdx; } // end of receiveSerialData int main(int argc, char *argv[]) { // setup and initial of process, then open_and_arm_serial_port( sioDev ); log_print(LOG_INFO, 0, "%s %d.\n", sioDev.serialName, sioDev.baud); while (1) { // Wait here until some messge is received rcvid = MsgReceive(self.chid, &msg, sizeof(msg), &msg_info); if (rcvid == 0) // Pulse? { // Received a pulse switch (msg.pulse.code) { case SS_SERIAL_PUL: // Got a serial pulse bufNdx = receiveSerialData(sioDev, sioBuf); break; // end case SERIAL_PUL // et al. default: // log error break; } // end of switch handle_pulse(msg, msg_info); } // end of pulse else { // Message or error // handle_message(rcvid, msg, msg_info); } // end of Message or error } // end of while return 0; } // end of main