Exemple #1
0
static void main_loop(struct serial_port *port)
{
	int nfds;
	struct pollfd pollfds[4];

#ifdef _DEBUG
	char dbgmsg[256];
#endif

	int serial_fd = ((struct serial_posix*)(port->chan))->fd;
	int i;

	while (1) {
		nfds = 0;

		DBG_LOG(strcpy(dbgmsg, "main_loop: wait for"));

		if (serial_port_watch_ertsr(port)) {
			pollfds[nfds++] = pipe_os_readable(port->erts);
			DBG_LOG(strcat(dbgmsg, " ertsr"));
		}

		if (serial_port_watch_ertsw(port)) {
			pollfds[nfds++] = pipe_os_writeable(port->erts);
			DBG_LOG(strcat(dbgmsg, " ertsw"));
		}

		if (serial_port_watch_serialr(port)) {
			pollfds[nfds++] = serial_os_readable(port->chan);
			DBG_LOG(strcat(dbgmsg, " serialr"));
		}

		if (serial_port_watch_serialw(port)) {
			pollfds[nfds++] = serial_os_writeable(port->chan);
			DBG_LOG(strcat(dbgmsg, " serialw"));
		}

		DBG_LOG(fprintf(debug_log_file, "%s\n", dbgmsg));

		/* If no events are enabled, we are really up a creek. Shutdown the
		 * process right now.
		 */
		if (0 == nfds) {
			serial_port_destroy(port);
			exit(1);
		}

		/* Wait for any of the above events to become true.  Break out
		 * as soon as one of them is in fact true.
		 */
		if (poll(pollfds, nfds, -1) < 0) {
			port->isDead = 1;
		}

		for (i = 0; i < nfds; i++) {
			if (pollfds[i].revents & (POLLERR | POLLHUP | POLLNVAL)) {
				port->isDead = 1;
			}

			if ((pollfds[i].fd == STDIN_FILENO) && (pollfds[i].revents & POLLIN)) {
				serial_port_ertsr(port);
			} else if ((pollfds[i].fd == STDOUT_FILENO) && (pollfds[i].revents & POLLOUT)) {
				serial_port_ertsw(port);
			} else if (pollfds[i].fd == serial_fd) {
				if (pollfds[i].revents & POLLIN) {
					serial_port_serialr(port);
				} else if (pollfds[i].revents & POLLOUT) {
					serial_port_serialw(port);
				}
			}
		}

		/* If something went horribly wrong, the generic code should
		 * have sent a message to Erlang indicating the error.  It
		 * also flagged the port dead, so we know to terminate the
		 * process.
		 */
		if (serial_port_isdead(port)) {
			serial_port_destroy(port);
			exit(1);
		}
	}
}
Exemple #2
0
struct serial_port_t*
serial_port_create(struct event_base *_base,
                   const char* _dev_name,
                   unsigned int _baudrate) {

    struct termios options;

    struct serial_port_t* sp = NULL;

    do {
        if(!(sp = (struct serial_port_t*)malloc(sizeof(struct serial_port_t))))
            break;

        memset(sp, 0, sizeof(struct serial_port_t));

        sp->fd = open(_dev_name, O_RDWR | O_NOCTTY | O_NDELAY);
        if(sp->fd < 0) {
            fprintf(stderr, "%s: Error while open \"%s\" serial port: %m\n", __FUNCTION__, _dev_name);
            fflush(stderr);
            break;
        }

        tcgetattr(sp->fd, &options);

        // ****** c_cflag field setup (Управляющие опции)

        // Поле c_cflag содержит две опции, которые всегда
        // должны быть разрешены: CLOCAL и CREAD.
        options.c_cflag |= (CLOCAL | CREAD);
        //options.c_cflag &= ~(ICANON | IEXTEN | FLUSHO | PENDIN | TOSTOP);
        //options.c_cflag |= (NOFLSH);
        options.c_cflag &= ~PARENB;	// Disable parity bit
        options.c_cflag &= ~CSTOPB;	// 1 stop bit
        options.c_cflag &= ~CSIZE;	// Маскирование битов размера символов (CS5,CS8...)
        options.c_cflag |= CS8;		// 8 data bits

    // Disable hardware flow control
#ifdef CRTSCTS
        options.c_cflag &= ~CRTSCTS;
#elif defined CNEW_RTSCTS
        options.c_cflag &= ~CNEW_RTSCTS;
#endif

        // ****** c_lflag field setup (Локальные опции)
        // Выбор неканонического (Raw) ввода:
        options.c_lflag &= ~( // Next flags will disabled:
            ICANON | 	// Разрешить канонический ввод (иначе неканонический)
            ECHO | 		// Разрешить эхо вводимых символов
            ECHOE | 	// Символ эхо стирания как BS-SP-BS
            ISIG);		// Разрешить SIGINTR, SIGSUSP, SIGDSUSP, и SIGQUIT сигналы

        // ****** c_iflag field setup (Опции ввода)
        options.c_iflag &= ~( // Next flags will disabled:
            IXON | 		// Enable software flow control (outgoing)
            IXOFF | 	// Enable software flow control (incoming)
            IXANY | 	// Allow any character to start flow again
            INPCK | 	// Enable parity check
        //	IGNPAR | 	// Ignore parity errors
            PARMRK | 	// Mark parity errors
            ISTRIP | 	// Strip parity bits
        //	IGNBRK | 	// Ignore break condition
            IMAXBEL | 	// Echo BEL on input line too long
            INLCR | 	// Map CR to NL
            IGNCR | 	// Ignore CR
            ICRNL);		// Map CR to NL

        // ****** c_oflag field setup (Опции вывода)
        // Когда опция OPOST сброшена, все остальные биты опций в поле c_oflag игнорируются.
        options.c_oflag &= ~OPOST;

        tcsetattr(sp->fd, TCSANOW, &options);

        if(serial_port_set_baudrate(sp, _baudrate)) {
            fprintf(stderr, "%s: Error with serial_port_set_baudrate() call: %m\n", __FUNCTION__);
            fflush(stderr);
            break;
        }

        sp->read_event = event_new(_base,
                                   sp->fd,
                                   EV_READ | EV_PERSIST,
                                   fd_event,
                                   sp);
        if(!sp->read_event) {
            fprintf(stderr, "%s: Error with event_new() call: %m\n", __FUNCTION__);
            fflush(stderr);
            break;
        }

        sp->write_event = event_new(_base,
                                    sp->fd,
                                    EV_WRITE | EV_PERSIST,
                                    fd_event,
                                    sp);
        if(!sp->write_event) {
            fprintf(stderr, "%s: Error with event_new() call: %m\n", __FUNCTION__);
            fflush(stderr);
            break;
        }

        if(event_add(sp->read_event, NULL)) {
            fprintf(stderr, "%s: Error with event_add() call: %m\n", __FUNCTION__);
            fflush(stderr);
            break;
        }

        return sp;

    } while(0);

    serial_port_destroy(sp);

    return NULL;
}
static void main_loop (struct serial_port* port)
{
	DWORD		wres;
	DWORD		nEvents;
	HANDLE		theEvent;
	HANDLE		wEvents[8];

#ifdef _DEBUG
	char		dbgmsg[256];
#endif

	for (;;)
	{
		nEvents = 0;

		DBG_LOG(strcpy(dbgmsg, "main_loop: wait for"));
	
		if (serial_port_watch_ertsr(port))
		{
			wEvents[nEvents++] = pipe_os_readable(port->erts);
			DBG_LOG(strcat(dbgmsg, " ertsr"));
		}

		if (serial_port_watch_ertsw(port))
		{
			wEvents[nEvents++] = pipe_os_writeable(port->erts);
			DBG_LOG(strcat(dbgmsg, " ertsw"));
		}

		if (serial_port_watch_serialr(port))
		{
			wEvents[nEvents++] = serial_os_readable(port->chan);
			DBG_LOG(strcat(dbgmsg, " serialr"));
		}
		
		if (serial_port_watch_serialw(port))
		{
			wEvents[nEvents++] = serial_os_writeable(port->chan);
			DBG_LOG(strcat(dbgmsg, " serialw"));
		}

		DBG_LOG(fprintf(debug_log_file, "%s\n", dbgmsg));

		/* If no events are enabled, we are really up a creek.  Shutdown the
		 * process right now.
		 */
		if (0 == nEvents)
		{
			serial_port_destroy(port);
			ExitProcess(1);
		}

		/* Wait for any of the above events to become true.  Break out
		 * as soon as one of them is in fact true.
		 */
		wres = WaitForMultipleObjects(nEvents, wEvents, FALSE, INFINITE);
		if (wres < WAIT_OBJECT_0)
		{
			continue;
		}

		/* Determine the event which triggered this wakeup.  Unlike on
		 * UNIX, we only know that one event in fact occurred, all of
		 * the others require us to go wait for them again.
		 */
		theEvent = wEvents[wres - WAIT_OBJECT_0];

		if (theEvent == pipe_os_readable(port->erts))
		{
			serial_port_ertsr(port);

		} else if (theEvent == pipe_os_writeable(port->erts))
		{
			serial_port_ertsw(port);

		} else if (theEvent == serial_os_readable(port->chan))
		{
			serial_port_serialr(port);

		} else if (theEvent == serial_os_writeable(port->chan))
		{
			serial_port_serialw(port);
		}

		/* If something went horribly wrong, the generic code should
		 * have sent a message to Erlang indicating the error.  It
		 * also flagged the port dead, so we know to terminate the
		 * process.
		 */
		if (serial_port_isdead(port))
		{
			serial_port_destroy(port);
			ExitProcess(1);
		}
	}
}