Exemplo n.º 1
0
/**
 * Configures serial port to use raw 8-bit mode and given baud
 * rate. This function also supports non-standard baud rates if the
 * underlying hardware is capable. If it fails, -1 is returned and
 * errno is set. Otherwise, zero is returned.
 */
int init_serial_port(int fd, int speed)
{
	// Check if speed preset is found or do we need to set a custom speed
	tcflag_t speed_preset = to_speed(speed);
	if (speed_preset == B0) {
		// Find current configuration
		struct serial_struct serial;
		if(ioctl(fd, TIOCGSERIAL, &serial) == -1) return -1;
		serial.flags = (serial.flags & ~ASYNC_SPD_MASK) | ASYNC_SPD_CUST;
		serial.custom_divisor = (serial.baud_base + (speed / 2)) / speed;

		// Check that the serial timing error is no more than 2%
		int real_speed = serial.baud_base / serial.custom_divisor;
		if (real_speed < speed * 98 / 100 ||
		    real_speed > speed * 102 / 100) {
			errno = ENOTSUP;
			return -1;
		}

		// Activate
		if(ioctl(fd, TIOCSSERIAL, &serial) == -1) return -1;

		// Custom baudrate only works with this magic value
		speed_preset = B38400;
	}

	// Start with raw values
	struct termios term;
	term.c_cflag = speed_preset | CS8 | CLOCAL | CREAD;
	cfmakeraw(&term);
	if (tcsetattr(fd,TCSANOW,&term) == -1) return -1;

	return 0;
}
Exemplo n.º 2
0
static int set_com_state(int fd, uart_com_state_t* com)
{
    struct termios tio;

    // read current state
    if (tcgetattr(fd, &tio) < 0) {
	DEBUGF("unable to read com state: %s", strerror(errno));
	return -1;
    }

    // On Mac os X IOSSIOSPEED can be used to set "non-traditional baud rate"
    // From "IOKit/serial/ioss.h"

    cfsetispeed(&tio, to_speed(com->ibaud));
    cfsetospeed(&tio, to_speed(com->obaud));

    // update from state
    switch(com->parity) {
    case UART_PARITY_NONE:
	tio.c_iflag &= ~PARMRK;
	tio.c_cflag &= ~PARENB;
	break;
    case UART_PARITY_ODD: // odd 
	tio.c_iflag &= ~PARMRK;
	tio.c_cflag  |= PARODD;
	tio.c_cflag |= PARENB;
	break;
    case UART_PARITY_EVEN: // even
	tio.c_iflag &= ~PARMRK;
	tio.c_cflag &= ~PARODD;
	tio.c_cflag |= PARENB;
	break;
    case UART_PARITY_MARK:  // mark (FIXME)
	tio.c_iflag |= PARMRK;
	tio.c_cflag |= PARENB;
	break;
    case UART_PARITY_SPACE:  // space (FIXME) 
	tio.c_iflag &= ~PARMRK;
	tio.c_cflag &= ~PARENB;
	break;
    default:
	break;
    }

    if (com->stopb == 1)
	tio.c_cflag &= ~CSTOPB;
    else if (com->stopb == 2)
	tio.c_cflag |= CSTOPB;

    tio.c_cflag &= ~CSIZE;
    switch(com->csize) {
    case 5: tio.c_cflag |= CS5; break;
    case 6: tio.c_cflag |= CS6; break;
    case 7: tio.c_cflag |= CS7; break;
    case 8: tio.c_cflag |= CS8; break;
    default: break;
    }
    // Set the buffer number of bytes buffered before interrupt
    if (com->bufsz > 255)
	tio.c_cc[VMIN] = 255;
    else
	tio.c_cc[VMIN] = com->bufsz;
    // Set the max time to buffer bytes 
    if (com->buftm > 25500)  // 25500 ms = 25.5 sec
	tio.c_cc[VTIME] = 255;
    else
	tio.c_cc[VTIME] = com->buftm / 100;
    tio.c_cc[VSTART] = com->xonchar;
    tio.c_cc[VSTOP] = com->xoffchar;

    // input flow control
    UPD_BIT(tio.c_iflag, IXOFF, (com->iflow & UART_SW));
#if defined(CRTS_IFLOW)
    UPD_BIT(tio.c_cflag, CRTS_IFLOW, (com->iflow & UART_RTS));
#endif
#if defined(CDTR_IFLOW)
    UPD_BIT(tio.c_cflag, CDTR_IFLOW, (com->iflow & UART_DTR));
#endif

    // output flow control
    UPD_BIT(tio.c_iflag, IXON, (com->oflow & UART_SW));
#if defined(CCTS_OFLOW)
    UPD_BIT(tio.c_cflag, CCTS_OFLOW, (com->oflow & UART_CTS));
#endif
#if defined(CDSR_OFLOW)
    UPD_BIT(tio.c_cflag, CDSR_OFLOW, (com->oflow & UART_DSR));
#endif
#if defined(CCAR_OFLOW)
    UPD_BIT(tio.c_cflag, CCAR_OFLOW, (com->oflow & UART_CD));
#endif
#if defined(CRTSCTS)
    if ((com->iflow & UART_RTS) && (com->oflow & UART_CTS))
	tio.c_cflag |= CRTSCTS;
    else if (!(com->iflow & UART_RTS) && !(com->oflow & UART_CTS))
	tio.c_cflag &= ~CRTSCTS;
#endif
    // ignore break condition
    tio.c_iflag |= IGNBRK;

    // local line + enable receiver
    tio.c_cflag |= (CLOCAL | CREAD);

    // raw input processing
    tio.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG | IEXTEN);
    // no output processing
    tio.c_oflag &= ~(OPOST);
    // do NOT hangup-on-close, need? we keep one slave open
    tio.c_cflag &= ~HUPCL;   
    
    tcflush(fd, TCIFLUSH);
    return tcsetattr(fd, TCSANOW, &tio);
}
Exemplo n.º 3
0
static int set_com_state(HANDLE fh, uart_com_state_t* com)
{
    DCB          dcb;
    COMMTIMEOUTS tmo;
    int baud;

    memset(&dcb, 0, sizeof(dcb));
    if (!GetCommState(fh, &dcb)) {
	DEBUG_ERROR("GetCommState: error %d", GetLastError());
	return -1;
    }

    baud = (com->ibaud > com->obaud) ? com->ibaud : com->obaud;
    dcb.BaudRate = to_speed(baud);

    switch(com->parity) {
    case UART_PARITY_NONE:
	dcb.fParity = FALSE;
	dcb.Parity = NOPARITY; 
	break;
    case UART_PARITY_ODD: 
	dcb.fParity = TRUE;
	dcb.Parity = ODDPARITY; 
	break;
    case UART_PARITY_EVEN: 
	dcb.fParity = TRUE;
	dcb.Parity = EVENPARITY; 
	break;
    case UART_PARITY_MARK:
	dcb.fParity = TRUE;
	dcb.Parity = MARKPARITY; 
	break;
    case UART_PARITY_SPACE:
	dcb.fParity = TRUE;
	dcb.Parity = SPACEPARITY; 
	break;
    default:
	dcb.fParity = FALSE;
	dcb.Parity = NOPARITY; 
	break;	
    }

    if (com->stopb == 1)
	dcb.StopBits = ONESTOPBIT;
    else if (com->stopb == 2)
	dcb.StopBits = TWOSTOPBITS;
    else if (com->stopb == 3)
	dcb.StopBits = ONE5STOPBITS;

    dcb.ByteSize = com->csize;

    dcb.XonChar          = com->xonchar;
    dcb.XoffChar         = com->xoffchar;

    // FIXME better flow handling!
    // {flow,[xoff|dtr|rts],[xoff|cts|dsr]} ?
    //
    dcb.fInX  = (com->iflow & UART_SW) != 0;
    dcb.fDtrControl = (com->iflow & UART_DTR) != 0;
    dcb.fRtsControl = (com->iflow & UART_RTS) != 0;

    dcb.fOutX = (com->oflow & UART_SW) != 0;
    dcb.fOutxCtsFlow = (com->oflow & UART_CTS) != 0;
    dcb.fOutxDsrFlow = (com->oflow & UART_DSR) != 0;

    dcb.fNull            = FALSE;
    
    dcb.DCBlength = sizeof(DCB);
    if (!SetCommState(fh, &dcb)) {
	DEBUG_ERROR("SetCommState: error %d", GetLastError());
	return -1;
    }

    // Setup harware buffer and timers
    if (com->bufsz > 255)
	SetupComm(fh, 255, DEFAULT_OUT_QUEUE);
    else
	SetupComm(fh, com->bufsz, DEFAULT_OUT_QUEUE);

    tmo.ReadIntervalTimeout = com->buftm;
    tmo.ReadTotalTimeoutMultiplier  =    0;
    tmo.ReadTotalTimeoutConstant    =    0;
    tmo.WriteTotalTimeoutMultiplier =    0;
    tmo.WriteTotalTimeoutConstant   =    0;
    if (!SetCommTimeouts(fh, &tmo)) {
	DEBUG_ERROR("GetCommTimeouts: error %d", GetLastError());
	return -1;
    }
    return 0;
}