/** * Initialize the driver. * Open com port and set baud correctly... * \param drvthis Pointer to driver structure. * \retval 0 Success. * \retval <0 Error. */ MODULE_EXPORT int lcterm_init (Driver *drvthis) { char device[200]; int speed=B9600; struct termios portset; PrivateData *p; debug(RPT_INFO, "LCTERM: init(%p)", drvthis); // Alocate and store private data p = (PrivateData *) calloc(1, sizeof(PrivateData)); if (p == NULL) return -1; if (drvthis->store_private_ptr(drvthis, p)) return -1; // initialize private data p->fd = -1; p->ccmode = p->last_ccmode = standard; // READ CONFIG FILE: // which serial device should be used strncpy(device, drvthis->config_get_string(drvthis->name , "Device" , 0 , DEFAULT_DEVICE), sizeof(device)); device[sizeof(device)-1] = '\0'; report(RPT_INFO, "%s: using Device %s", drvthis->name, device); /* Get and parse size */ { int w, h; const char *s = drvthis->config_get_string(drvthis->name, "Size", 0, "16x2"); debug(RPT_DEBUG, "%s: reading size: %s", __FUNCTION__, s); if ((sscanf(s, "%dx%d", &w, &h) != 2) || (w <= 0) || (w > LCD_MAX_WIDTH) || (h <= 0) || (h > LCD_MAX_HEIGHT)) { report(RPT_WARNING, "%s: cannot read Size: %s; using default %s", drvthis->name, s, "16x2"); sscanf("16x2", "%dx%d", &w, &h); } p->width = w; p->height = h; } report(RPT_INFO, "%s: using Size: %dx%d", drvthis->name, p->width, p->height); p->framebuf = malloc(p->width * p->height); p->last_framebuf = malloc(p->width * p->height); if ((p->framebuf == NULL) || (p->last_framebuf == NULL)) { report(RPT_ERR, "%s: unable to create framebuffer", drvthis->name); return -1; } memset(p->framebuf, ' ', p->width * p->height); memset(p->last_framebuf, ' ', p->width * p->height); // Set up io port correctly, and open it... debug(RPT_DEBUG, "%s: Opening serial device: %s", drvthis->name, device); p->fd = open(device, O_RDWR | O_NOCTTY | O_NDELAY); if (p->fd == -1) { report(RPT_ERR, "%s: open(%) failed (%s)", drvthis->name, device, strerror(errno)); if (errno == EACCES) report(RPT_ERR, "%s: make sure you have rw access to %s!", drvthis->name, device); return -1; } report(RPT_INFO, "%s: opened display on %s", drvthis->name, device); tcgetattr(p->fd, &portset); #ifdef HAVE_CFMAKERAW /* The easy way: */ cfmakeraw(&portset); #else /* The hard way: */ portset.c_iflag &= ~( IGNBRK | BRKINT | PARMRK | ISTRIP | INLCR | IGNCR | ICRNL | IXON ); portset.c_oflag &= ~OPOST; portset.c_lflag &= ~( ECHO | ECHONL | ICANON | ISIG | IEXTEN ); portset.c_cflag &= ~( CSIZE | PARENB | CRTSCTS ); portset.c_cflag |= CS8 | CREAD | CLOCAL ; #endif cfsetospeed(&portset, speed); cfsetispeed(&portset, speed); tcsetattr(p->fd, TCSANOW, &portset); tcflush(p->fd, TCIOFLUSH); // clear the display, disable cursor, disable key scanning write(p->fd, "\x1a\x16\x1bK", 4); report(RPT_DEBUG, "%s: init() done", drvthis->name); return 0; }
EIF_INTEGER posix_cfsetospeed(struct termios *ptr, EIF_INTEGER speed) { return cfsetospeed(ptr, speed); }
static int serial_setup(serial_control_t *ctrl) { /* just setup serial at debug level= 0, 1, 4, for debug level = 2, 3 is reserved for simulation test locally */ if ((debug <2) || (debug >3)) { struct termios newtio, oldtio; /* * Here we setup the standard input tty settings. We have to do it here, * because we need to restore them when this application exits (so that the Linux * shell continues to work as expected.) * The tty settings of the external tty are set in the remote build. */ if (tcgetattr(ctrl->fd, &oldtio) != 0) { error_printf("tcgetattr failed: %s\n", strerror(errno)); return EXIT_FAILURE; } memset(&newtio, 0, sizeof(newtio)); memcpy(&newtio, &oldtio, sizeof(struct termios)); if (ctrl->mode == RAW_MODE) { /* Set raw mode: the remote application will handle all terminal characters */ cfmakeraw(&newtio); } switch (ctrl->bits) { case 7: newtio.c_cflag |= CS7; break; case 8: newtio.c_cflag |= CS8; break; } switch (ctrl->parity) { case 'O': newtio.c_cflag |= PARENB; newtio.c_cflag |= PARODD; newtio.c_iflag |= (INPCK | ISTRIP); break; case 'E': newtio.c_iflag |= (INPCK | ISTRIP); newtio.c_cflag |= PARENB; newtio.c_cflag &= ~PARODD; break; case 'N': newtio.c_cflag &= ~PARENB; break; } switch (ctrl->speed) { case 2400: cfsetispeed(&newtio, B2400); cfsetospeed(&newtio, B2400); break; case 4800: cfsetispeed(&newtio, B4800); cfsetospeed(&newtio, B4800); break; case 9600: cfsetispeed(&newtio, B9600); cfsetospeed(&newtio, B9600); break; case 115200: cfsetispeed(&newtio, B115200); cfsetospeed(&newtio, B115200); break; default: cfsetispeed(&newtio, B9600); cfsetospeed(&newtio, B9600); break; } if (ctrl->stop == 1) newtio.c_cflag &= ~CSTOPB; else if (ctrl->stop == 2) newtio.c_cflag |= CSTOPB; // important newtio.c_cflag |= CLOCAL | CREAD; newtio.c_cflag &= ~CSIZE; if (ctrl->mode == RAW_MODE) { newtio.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG); newtio.c_oflag &= ~OPOST; newtio.c_iflag &= ~(BRKINT | ICRNL | INPCK | ISTRIP | IXON); } newtio.c_cc[VTIME] = 0; newtio.c_cc[VMIN] = 0; tcflush(ctrl->fd, TCIFLUSH); if (tcsetattr(ctrl->fd, TCSANOW, &newtio) < 0) { error_printf("tcsetattr failed: %s\n", strerror(errno)); return EXIT_FAILURE; } debug_printf("serial_control: setting has done!\n"); } return EXIT_SUCCESS; }
void serialport_set_baudrate(unsigned int baudrate) { switch(baudrate) { case 2400: cfsetispeed(&term,B2400); cfsetospeed(&term,B2400); break; case 4800: cfsetispeed(&term,B4800); cfsetospeed(&term,B4800); break; case 9600: cfsetispeed(&term,B9600); cfsetospeed(&term,B9600); break; case 19200: cfsetispeed(&term,B19200); cfsetospeed(&term,B19200); break; case 38400: cfsetispeed(&term,B38400); cfsetospeed(&term,B38400); break; case 57600: cfsetispeed(&term,B57600); cfsetospeed(&term,B57600); break; case 115200: cfsetispeed(&term,B115200); cfsetospeed(&term,B115200); break; case 230400: cfsetispeed(&term,B230400); cfsetospeed(&term,B230400); break; #ifndef __APPLE__ case 460800: cfsetispeed(&term,B460800); cfsetospeed(&term,B460800); break; case 921600: cfsetispeed(&term,B921600); cfsetospeed(&term,B921600); break; #endif default: LOGWARN("serialport_set_baudrate: baud rate %d may not work", baudrate); cfsetispeed(&term,baudrate); cfsetospeed(&term,baudrate); break; } }
/* Sets up a serial port for RTU communications */ static int _modbus_rtu_connect(modbus_t *ctx) { #if defined(_WIN32) DCB dcb; #else struct termios tios; speed_t speed; int flags; #endif modbus_rtu_t *ctx_rtu = ctx->backend_data; if (ctx->debug) { printf("Opening %s at %d bauds (%c, %d, %d)\n", ctx_rtu->device, ctx_rtu->baud, ctx_rtu->parity, ctx_rtu->data_bit, ctx_rtu->stop_bit); } #if defined(_WIN32) /* Some references here: * http://msdn.microsoft.com/en-us/library/aa450602.aspx */ win32_ser_init(&ctx_rtu->w_ser); /* ctx_rtu->device should contain a string like "COMxx:" xx being a decimal * number */ ctx_rtu->w_ser.fd = CreateFileA(ctx_rtu->device, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL); /* Error checking */ if (ctx_rtu->w_ser.fd == INVALID_HANDLE_VALUE) { if (ctx->debug) { fprintf(stderr, "ERROR Can't open the device %s (LastError %d)\n", ctx_rtu->device, (int)GetLastError()); } return -1; } /* Save params */ ctx_rtu->old_dcb.DCBlength = sizeof(DCB); if (!GetCommState(ctx_rtu->w_ser.fd, &ctx_rtu->old_dcb)) { if (ctx->debug) { fprintf(stderr, "ERROR Error getting configuration (LastError %d)\n", (int)GetLastError()); } CloseHandle(ctx_rtu->w_ser.fd); ctx_rtu->w_ser.fd = INVALID_HANDLE_VALUE; return -1; } /* Build new configuration (starting from current settings) */ dcb = ctx_rtu->old_dcb; /* Speed setting */ switch (ctx_rtu->baud) { case 110: dcb.BaudRate = CBR_110; break; case 300: dcb.BaudRate = CBR_300; break; case 600: dcb.BaudRate = CBR_600; break; case 1200: dcb.BaudRate = CBR_1200; break; case 2400: dcb.BaudRate = CBR_2400; break; case 4800: dcb.BaudRate = CBR_4800; break; case 9600: dcb.BaudRate = CBR_9600; break; case 14400: dcb.BaudRate = CBR_14400; break; case 19200: dcb.BaudRate = CBR_19200; break; case 38400: dcb.BaudRate = CBR_38400; break; case 57600: dcb.BaudRate = CBR_57600; break; case 115200: dcb.BaudRate = CBR_115200; break; case 230400: /* CBR_230400 - not defined */ dcb.BaudRate = 230400; break; case 250000: dcb.BaudRate = 250000; break; case 460800: dcb.BaudRate = 460800; break; case 500000: dcb.BaudRate = 500000; break; case 921600: dcb.BaudRate = 921600; break; case 1000000: dcb.BaudRate = 1000000; break; default: dcb.BaudRate = CBR_9600; if (ctx->debug) { fprintf(stderr, "WARNING Unknown baud rate %d for %s (B9600 used)\n", ctx_rtu->baud, ctx_rtu->device); } } /* Data bits */ switch (ctx_rtu->data_bit) { case 5: dcb.ByteSize = 5; break; case 6: dcb.ByteSize = 6; break; case 7: dcb.ByteSize = 7; break; case 8: default: dcb.ByteSize = 8; break; } /* Stop bits */ if (ctx_rtu->stop_bit == 1) dcb.StopBits = ONESTOPBIT; else /* 2 */ dcb.StopBits = TWOSTOPBITS; /* Parity */ if (ctx_rtu->parity == 'N') { dcb.Parity = NOPARITY; dcb.fParity = FALSE; } else if (ctx_rtu->parity == 'E') { dcb.Parity = EVENPARITY; dcb.fParity = TRUE; } else { /* odd */ dcb.Parity = ODDPARITY; dcb.fParity = TRUE; } /* Hardware handshaking left as default settings retrieved */ /* No software handshaking */ dcb.fTXContinueOnXoff = TRUE; dcb.fOutX = FALSE; dcb.fInX = FALSE; /* Binary mode (it's the only supported on Windows anyway) */ dcb.fBinary = TRUE; /* Don't want errors to be blocking */ dcb.fAbortOnError = FALSE; /* Setup port */ if (!SetCommState(ctx_rtu->w_ser.fd, &dcb)) { if (ctx->debug) { fprintf(stderr, "ERROR Error setting new configuration (LastError %d)\n", (int)GetLastError()); } CloseHandle(ctx_rtu->w_ser.fd); ctx_rtu->w_ser.fd = INVALID_HANDLE_VALUE; return -1; } #else /* The O_NOCTTY flag tells UNIX that this program doesn't want to be the "controlling terminal" for that port. If you don't specify this then any input (such as keyboard abort signals and so forth) will affect your process Timeouts are ignored in canonical input mode or when the NDELAY option is set on the file via open or fcntl */ flags = O_RDWR | O_NOCTTY | O_NDELAY | O_EXCL; #ifdef O_CLOEXEC flags |= O_CLOEXEC; #endif ctx->s = open(ctx_rtu->device, flags); if (ctx->s == -1) { if (ctx->debug) { fprintf(stderr, "ERROR Can't open the device %s (%s)\n", ctx_rtu->device, strerror(errno)); } return -1; } /* Save */ tcgetattr(ctx->s, &(ctx_rtu->old_tios)); memset(&tios, 0, sizeof(struct termios)); /* C_ISPEED Input baud (new interface) C_OSPEED Output baud (new interface) */ switch (ctx_rtu->baud) { case 110: speed = B110; break; case 300: speed = B300; break; case 600: speed = B600; break; case 1200: speed = B1200; break; case 2400: speed = B2400; break; case 4800: speed = B4800; break; case 9600: speed = B9600; break; case 19200: speed = B19200; break; case 38400: speed = B38400; break; #ifdef B57600 case 57600: speed = B57600; break; #endif #ifdef B115200 case 115200: speed = B115200; break; #endif #ifdef B230400 case 230400: speed = B230400; break; #endif #ifdef B460800 case 460800: speed = B460800; break; #endif #ifdef B500000 case 500000: speed = B500000; break; #endif #ifdef B576000 case 576000: speed = B576000; break; #endif #ifdef B921600 case 921600: speed = B921600; break; #endif #ifdef B1000000 case 1000000: speed = B1000000; break; #endif #ifdef B1152000 case 1152000: speed = B1152000; break; #endif #ifdef B1500000 case 1500000: speed = B1500000; break; #endif #ifdef B2500000 case 2500000: speed = B2500000; break; #endif #ifdef B3000000 case 3000000: speed = B3000000; break; #endif #ifdef B3500000 case 3500000: speed = B3500000; break; #endif #ifdef B4000000 case 4000000: speed = B4000000; break; #endif default: speed = B9600; if (ctx->debug) { fprintf(stderr, "WARNING Unknown baud rate %d for %s (B9600 used)\n", ctx_rtu->baud, ctx_rtu->device); } } /* Set the baud rate */ if ((cfsetispeed(&tios, speed) < 0) || (cfsetospeed(&tios, speed) < 0)) { close(ctx->s); ctx->s = -1; return -1; } /* C_CFLAG Control options CLOCAL Local line - do not change "owner" of port CREAD Enable receiver */ tios.c_cflag |= (CREAD | CLOCAL); /* CSIZE, HUPCL, CRTSCTS (hardware flow control) */ /* Set data bits (5, 6, 7, 8 bits) CSIZE Bit mask for data bits */ tios.c_cflag &= ~CSIZE; switch (ctx_rtu->data_bit) { case 5: tios.c_cflag |= CS5; break; case 6: tios.c_cflag |= CS6; break; case 7: tios.c_cflag |= CS7; break; case 8: default: tios.c_cflag |= CS8; break; } /* Stop bit (1 or 2) */ if (ctx_rtu->stop_bit == 1) tios.c_cflag &=~ CSTOPB; else /* 2 */ tios.c_cflag |= CSTOPB; /* PARENB Enable parity bit PARODD Use odd parity instead of even */ if (ctx_rtu->parity == 'N') { /* None */ tios.c_cflag &=~ PARENB; } else if (ctx_rtu->parity == 'E') { /* Even */ tios.c_cflag |= PARENB; tios.c_cflag &=~ PARODD; } else { /* Odd */ tios.c_cflag |= PARENB; tios.c_cflag |= PARODD; } /* Read the man page of termios if you need more information. */ /* This field isn't used on POSIX systems tios.c_line = 0; */ /* C_LFLAG Line options ISIG Enable SIGINTR, SIGSUSP, SIGDSUSP, and SIGQUIT signals ICANON Enable canonical input (else raw) XCASE Map uppercase \lowercase (obsolete) ECHO Enable echoing of input characters ECHOE Echo erase character as BS-SP-BS ECHOK Echo NL after kill character ECHONL Echo NL NOFLSH Disable flushing of input buffers after interrupt or quit characters IEXTEN Enable extended functions ECHOCTL Echo control characters as ^char and delete as ~? ECHOPRT Echo erased character as character erased ECHOKE BS-SP-BS entire line on line kill FLUSHO Output being flushed PENDIN Retype pending input at next read or input char TOSTOP Send SIGTTOU for background output Canonical input is line-oriented. Input characters are put into a buffer which can be edited interactively by the user until a CR (carriage return) or LF (line feed) character is received. Raw input is unprocessed. Input characters are passed through exactly as they are received, when they are received. Generally you'll deselect the ICANON, ECHO, ECHOE, and ISIG options when using raw input */ /* Raw input */ tios.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG); /* C_IFLAG Input options Constant Description INPCK Enable parity check IGNPAR Ignore parity errors PARMRK Mark parity errors ISTRIP Strip parity bits IXON Enable software flow control (outgoing) IXOFF Enable software flow control (incoming) IXANY Allow any character to start flow again IGNBRK Ignore break condition BRKINT Send a SIGINT when a break condition is detected INLCR Map NL to CR IGNCR Ignore CR ICRNL Map CR to NL IUCLC Map uppercase to lowercase IMAXBEL Echo BEL on input line too long */ if (ctx_rtu->parity == 'N') { /* None */ tios.c_iflag &= ~INPCK; } else { tios.c_iflag |= INPCK; } /* Software flow control is disabled */ tios.c_iflag &= ~(IXON | IXOFF | IXANY); /* C_OFLAG Output options OPOST Postprocess output (not set = raw output) ONLCR Map NL to CR-NL ONCLR ant others needs OPOST to be enabled */ /* Raw ouput */ tios.c_oflag &=~ OPOST; /* C_CC Control characters VMIN Minimum number of characters to read VTIME Time to wait for data (tenths of seconds) UNIX serial interface drivers provide the ability to specify character and packet timeouts. Two elements of the c_cc array are used for timeouts: VMIN and VTIME. Timeouts are ignored in canonical input mode or when the NDELAY option is set on the file via open or fcntl. VMIN specifies the minimum number of characters to read. If it is set to 0, then the VTIME value specifies the time to wait for every character read. Note that this does not mean that a read call for N bytes will wait for N characters to come in. Rather, the timeout will apply to the first character and the read call will return the number of characters immediately available (up to the number you request). If VMIN is non-zero, VTIME specifies the time to wait for the first character read. If a character is read within the time given, any read will block (wait) until all VMIN characters are read. That is, once the first character is read, the serial interface driver expects to receive an entire packet of characters (VMIN bytes total). If no character is read within the time allowed, then the call to read returns 0. This method allows you to tell the serial driver you need exactly N bytes and any read call will return 0 or N bytes. However, the timeout only applies to the first character read, so if for some reason the driver misses one character inside the N byte packet then the read call could block forever waiting for additional input characters. VTIME specifies the amount of time to wait for incoming characters in tenths of seconds. If VTIME is set to 0 (the default), reads will block (wait) indefinitely unless the NDELAY option is set on the port with open or fcntl. */ /* Unused because we use open with the NDELAY option */ tios.c_cc[VMIN] = 0; tios.c_cc[VTIME] = 0; if (tcsetattr(ctx->s, TCSANOW, &tios) < 0) { close(ctx->s); ctx->s = -1; return -1; } #endif return 0; }
bool RawChannel::Open() { #ifndef WIN32 sp = open(port, O_RDWR | O_NOCTTY | O_NDELAY); fcntl(sp, F_SETFL, 0); //fcntl(sp, F_SETFL, FNDELAY); if(sp < 0) { printf("RawChannel::Open: open(): %s: %d: %s\n", port, errno, strerror(errno)); return false; } if(tcgetattr(sp, &tty) != 0) { printf("RawChannel::Open: Tcgetattr: %d: %s\n", errno, strerror(errno)); return false; } cfsetospeed(&tty, baud_rate); cfsetispeed(&tty, baud_rate); tty.c_oflag &= ~(OCRNL | ONLCR | ONLRET | ONOCR | OFILL | OPOST); tty.c_lflag &= ~(ECHO | ECHONL | ICANON | IEXTEN | ISIG); tty.c_iflag &= ~(IGNBRK | BRKINT | ICRNL | INLCR | PARMRK| INPCK| ISTRIP | IXON| IXOFF | IXANY); tty.c_cflag &= ~(PARENB | CSIZE); tty.c_cflag |= CS8; tty.c_cc[VMIN] = 0; tty.c_cc[VTIME] =50; if(tcsetattr(sp, TCSANOW, &tty) !=0) { printf("RawChannel::Open: tcsetattr: %d: %s\n", errno, strerror(errno)); return false; } printf("RawChannel::Open: %s opened\n", port); #else hComm = ::CreateFile(port, GENERIC_READ|GENERIC_WRITE, 0,NULL,OPEN_EXISTING, 0, NULL); if(hComm == INVALID_HANDLE_VALUE) { printf("Error opening serial port: %s\n", port); return false; } if(!::GetCommState(hComm, &dcb)) { printf("Could not setup comm port: %s\n", port); return false; } dcb.BaudRate = CBR_57600; dcb.ByteSize = 8; dcb.Parity = NOPARITY; dcb.fRtsControl = ONESTOPBIT; //dcb.EofChar = '\r'; if(!::SetCommState(hComm, &dcb)) { printf("Could not setup comm port: %s\n", port); return false; } COMMTIMEOUTS cto; cto.ReadIntervalTimeout = 100000; cto.ReadTotalTimeoutConstant = 100; cto.ReadTotalTimeoutMultiplier = 256; cto.WriteTotalTimeoutConstant = 0; cto.WriteTotalTimeoutMultiplier = 0; ::SetCommTimeouts(hComm, &cto); return true; #endif return true; }
ASerial::ASerial(std::string serialport, int baudrate) throw (std::string){ std::string exc; this->error = 0; this->serialport = serialport; this->baudrate = baudrate; this->fd = open(this->serialport.c_str(), O_RDWR | O_NONBLOCK); if(this->fd == -1){ this->error = 1; exc = "ASerial: Could not open serialport: " + serialport + "."; throw exc; } if (tcgetattr(fd, &this->toptions) < 0){ this->error = 2; exc = "ASerial: Could not get term attributes."; throw exc; } speed_t brate = this->baudrate; // let you override switch below if needed switch(baudrate) { case 4800: brate=B4800; break; case 9600: brate=B9600; break; #ifdef B14400 case 14400: brate=B14400; break; #endif case 19200: brate=B19200; break; #ifdef B28800 case 28800: brate=B28800; break; #endif case 38400: brate=B38400; break; case 57600: brate=B57600; break; case 115200: brate=B115200; break; #ifdef B230400 case 230400: brate = B230400; break; #endif } cfsetispeed(&this->toptions, brate); cfsetospeed(&this->toptions, brate); // 8N1 toptions.c_cflag &= ~PARENB; toptions.c_cflag &= ~CSTOPB; toptions.c_cflag &= ~CSIZE; toptions.c_cflag |= CS8; // no flow control toptions.c_cflag &= ~CRTSCTS; toptions.c_cflag |= CREAD | CLOCAL; // turn on READ & ignore ctrl lines toptions.c_iflag &= ~(IXON | IXOFF | IXANY); // turn off s/w flow ctrl toptions.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG); // make raw toptions.c_oflag &= ~OPOST; // make raw toptions.c_cc[VMIN] = 0; toptions.c_cc[VTIME] = 0; tcsetattr(fd, TCSANOW, &this->toptions); if(tcsetattr(fd, TCSAFLUSH, &this->toptions) < 0){ this->error = 3; exc = "ASerial: Couldn't set term attributes."; throw exc; } }
COMMNG cmserial_create(UINT port, BYTE param, UINT32 speed) { static const int cmserial_cflag[10] = { B110, B300, B1200, B2400, B4800, B9600, B19200, B38400, B57600, B115200 }; static const int csize[] = { CS5, CS6, CS7, CS8 }; struct termios options, origopt; COMMNG ret; CMSER serial; int hdl; UINT i; VERBOSE(("cmserial_create: port = %d, param = %02x, speed = %d", port, param, speed)); if (port == 0 || port > MAX_SERIAL_PORT_NUM) { VERBOSE(("cmserial_create: port is invalid")); goto cscre_failure; } port--; if (np2oscfg.com[port].mout[0] == '\0') { VERBOSE(("cmserial_create: com device file is disable")); goto cscre_failure; } hdl = open(np2oscfg.com[port].mout, O_RDWR | O_NOCTTY | O_NDELAY); if (hdl == -1) { VERBOSE(("cmserial_create: open failure %s, %s", np2oscfg.com[port].mout, strerror(errno))); goto cscre_failure; } if (!isatty(hdl)) { VERBOSE(("cmserial_create: not terminal file descriptor (%s)", strerror(errno))); goto cscre_close; } /* get current options for the port */ tcgetattr(hdl, &options); origopt = options; /* baud rates */ for (i = 0; i < NELEMENTS(cmserial_speed); i++) { if (cmserial_speed[i] >= speed) { VERBOSE(("cmserial_create: spped = %d", cmserial_speed[i])); break; } } if (i >= NELEMENTS(cmserial_speed)) { VERBOSE(("cmserial_create: speed is invaild")); goto cscre_close; } cfsetispeed(&options, cmserial_cflag[i]); cfsetospeed(&options, cmserial_cflag[i]); /* character size bits */ options.c_cflag &= ~CSIZE; options.c_cflag |= csize[(param >> 2) & 3]; VERBOSE(("cmserial_create: charactor size = %d", csize[(param >> 2) & 3])); /* parity check */ switch (param & 0x30) { case 0x10: VERBOSE(("cmserial_create: odd parity")); options.c_cflag |= PARENB | PARODD; options.c_iflag |= INPCK | ISTRIP; break; case 0x30: VERBOSE(("cmserial_create: even parity")); options.c_cflag |= PARENB; options.c_cflag &= ~PARODD; options.c_iflag |= INPCK | ISTRIP; break; default: VERBOSE(("cmserial_create: non parity")); options.c_cflag &= ~PARENB; options.c_iflag &= ~(INPCK | ISTRIP); break; } /* stop bits */ switch (param & 0xc0) { case 0x80: VERBOSE(("cmserial_create: stop bits: 1.5")); break; case 0xc0: VERBOSE(("cmserial_create: stop bits: 2")); options.c_cflag |= CSTOPB; break; default: VERBOSE(("cmserial_create: stop bits: 1")); options.c_cflag &= ~CSTOPB; break; } /* set misc flag */ cfmakeraw(&options); options.c_cflag |= CLOCAL | CREAD; options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG); #if defined(SERIAL_DEBUG) print_status(&options); #endif ret = (COMMNG)_MALLOC(sizeof(_COMMNG) + sizeof(_CMSER), "SERIAL"); if (ret == NULL) { VERBOSE(("cmserial_create: memory alloc failure")); goto cscre_close; } /* set the new options for the port */ tcsetattr(hdl, TCSANOW, &options); #if 1 ret->connect = COMCONNECT_MIDI; #else ret->connect = COMCONNECT_SERIAL; #endif ret->read = serialread; ret->write = serialwrite; ret->getstat = serialgetstat; ret->msg = serialmsg; ret->release = serialrelease; serial = (CMSER)(ret + 1); serial->hdl = hdl; serial->tio = origopt; return ret; cscre_close: close(hdl); cscre_failure: return NULL; }
int serialOpen (char *device, int baud) { struct termios options ; speed_t myBaud ; int status, fd ; switch (baud) { case 50: myBaud = B50 ; break ; case 75: myBaud = B75 ; break ; case 110: myBaud = B110 ; break ; case 134: myBaud = B134 ; break ; case 150: myBaud = B150 ; break ; case 200: myBaud = B200 ; break ; case 300: myBaud = B300 ; break ; case 600: myBaud = B600 ; break ; case 1200: myBaud = B1200 ; break ; case 1800: myBaud = B1800 ; break ; case 2400: myBaud = B2400 ; break ; case 4800: myBaud = B4800 ; break ; case 9600: myBaud = B9600 ; break ; case 19200: myBaud = B19200 ; break ; case 38400: myBaud = B38400 ; break ; case 57600: myBaud = B57600 ; break ; case 115200: myBaud = B115200 ; break ; case 230400: myBaud = B230400 ; break ; default: return -2 ; } if ((fd = open (device, O_RDWR | O_NOCTTY | O_NDELAY | O_NONBLOCK)) == -1) return -1 ; fcntl (fd, F_SETFL, O_RDWR) ; // Get and modify current options: tcgetattr (fd, &options) ; cfmakeraw (&options) ; cfsetispeed (&options, myBaud) ; cfsetospeed (&options, myBaud) ; options.c_cflag |= (CLOCAL | CREAD) ; options.c_cflag &= ~PARENB ; options.c_cflag &= ~CSTOPB ; options.c_cflag &= ~CSIZE ; options.c_cflag |= CS8 ; options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG) ; options.c_oflag &= ~OPOST ; options.c_cc [VMIN] = 0 ; options.c_cc [VTIME] = 100 ; // Ten seconds (100 deciseconds) tcsetattr (fd, TCSANOW | TCSAFLUSH, &options) ; ioctl (fd, TIOCMGET, &status); status |= TIOCM_DTR ; status |= TIOCM_RTS ; ioctl (fd, TIOCMSET, &status); usleep (10000) ; // 10mS return fd ; }
int csr_open_bcsp(char *device) { struct termios ti; uint8_t delay, activity = 0x00; int timeout = 0; if (!device) device = "/dev/ttyS0"; fd = open(device, O_RDWR | O_NOCTTY); if (fd < 0) { fprintf(stderr, "Can't open serial port: %s (%d)\n", strerror(errno), errno); return -1; } tcflush(fd, TCIOFLUSH); if (tcgetattr(fd, &ti) < 0) { fprintf(stderr, "Can't get port settings: %s (%d)\n", strerror(errno), errno); close(fd); return -1; } cfmakeraw(&ti); ti.c_cflag |= CLOCAL; ti.c_cflag &= ~CRTSCTS; ti.c_cflag |= PARENB; ti.c_cflag &= ~PARODD; ti.c_cflag &= ~CSIZE; ti.c_cflag |= CS8; ti.c_cflag &= ~CSTOPB; ti.c_cc[VMIN] = 1; ti.c_cc[VTIME] = 0; cfsetospeed(&ti, B38400); if (tcsetattr(fd, TCSANOW, &ti) < 0) { fprintf(stderr, "Can't change port settings: %s (%d)\n", strerror(errno), errno); close(fd); return -1; } tcflush(fd, TCIOFLUSH); if (fcntl(fd, F_SETFL, fcntl(fd, F_GETFL, 0) | O_NONBLOCK) < 0) { fprintf(stderr, "Can't set non blocking mode: %s (%d)\n", strerror(errno), errno); close(fd); return -1; } memset(&send_packet, 0, sizeof(send_packet)); memset(&receive_packet, 0, sizeof(receive_packet)); ubcsp_initialize(); send_packet.length = 512; send_packet.payload = send_buffer; receive_packet.length = 512; receive_packet.payload = receive_buffer; ubcsp_receive_packet(&receive_packet); while (1) { delay = ubcsp_poll(&activity); if (activity & UBCSP_PACKET_RECEIVED) break; if (delay) { usleep(delay * 100); if (timeout++ > 5000) { fprintf(stderr, "Initialization timed out\n"); return -1; } } } return 0; }
int CComDev::set_opt(int nSpeed, int nBits, char nEvent, int nStop) { struct termios newtio, oldtio; /*保存测试现有串口参数设置,在这里如果串口号等出错,会有相关的出错信息*/ if (tcgetattr(m_nFd, &oldtio) != 0) { perror("SetupSerial 1"); return FALSE; } bzero(&newtio, sizeof(newtio)); /*步骤一,设置字符大小*/ newtio.c_cflag |= CLOCAL | CREAD; newtio.c_cflag &= ~CSIZE; /*设置停止位*/ switch (nBits) { case 7: newtio.c_cflag |= CS7; break; case 8: newtio.c_cflag |= CS8; break; } /*设置奇偶校验位*/ switch (nEvent) { case 'O': //奇数 newtio.c_cflag |= PARENB; newtio.c_cflag |= PARODD; newtio.c_iflag |= (INPCK | ISTRIP); break; case 'E': //偶数 newtio.c_iflag |= (INPCK | ISTRIP); newtio.c_cflag |= PARENB; newtio.c_cflag &= ~PARODD; break; case 'N': //无奇偶校验位 newtio.c_cflag &= ~PARENB; break; } /*设置波特率*/ switch (nSpeed) { case 2400: cfsetispeed(&newtio, B2400); cfsetospeed(&newtio, B2400); break; case 4800: cfsetispeed(&newtio, B4800); cfsetospeed(&newtio, B4800); break; case 9600: cfsetispeed(&newtio, B9600); cfsetospeed(&newtio, B9600); break; case 115200: cfsetispeed(&newtio, B115200); cfsetospeed(&newtio, B115200); break; case 460800: cfsetispeed(&newtio, B460800); cfsetospeed(&newtio, B460800); break; default: cfsetispeed(&newtio, B9600); cfsetospeed(&newtio, B9600); break; } /*设置停止位*/ if (nStop == 1) newtio.c_cflag &= ~CSTOPB; else if (nStop == 2) newtio.c_cflag |= CSTOPB; /*设置等待时间和最小接收字符*/ newtio.c_cc[VTIME] = 0; newtio.c_cc[VMIN] = 0; /*处理未接收字符*/ tcflush(m_nFd, TCIFLUSH); /*激活新配置*/ if ((tcsetattr(m_nFd, TCSANOW, &newtio)) != 0) { perror("Com set error"); return FALSE; } printf("Com set done!\n"); return TRUE; }
/* * Arguments: fd_udata, [options ...: * reset (string: "reset"), * baud_rate (number), * character_size (string: "cs5".."cs8"), * parity (string: "parno", "parodd", "pareven"), * stop_bits (string: "sb1", "sb2"), * flow_controls (string: "foff", "frtscts", "fxio")] * Returns: [fd_udata] */ static int comm_init (lua_State *L) { const fd_t fd = (fd_t) lua_unboxinteger(L, 1, FD_TYPENAME); const int narg = lua_gettop(L); int i; #ifndef _WIN32 struct termios tio; if (tcgetattr(fd, &tio) == -1) goto err; #else DCB dcb; dcb.DCBlength = sizeof(DCB); if (!GetCommState(fd, &dcb)) goto err; #endif for (i = 2; i <= narg; ++i) { #ifndef _WIN32 tcflag_t mask = 0, flag = 0; #endif if (lua_isnumber(L, i)) { const int baud_rate = lua_tointeger(L, i); #ifndef _WIN32 switch (baud_rate) { case 9600: flag = B9600; break; case 19200: flag = B19200; break; case 38400: flag = B38400; break; case 57600: flag = B57600; break; case 115200: flag = B115200; break; } if (cfsetispeed(&tio, flag) == -1 || cfsetospeed(&tio, flag) == -1) goto err; #else dcb.BaudRate = baud_rate; #endif } else { const char *opt = lua_tostring(L, i); const char *endp = opt + lua_rawlen(L, i) - 1; if (!opt) continue; switch (*opt) { case 'r': /* reset */ #ifndef _WIN32 memset(&tio, 0, sizeof(struct termios)); #else memset(&dcb, 0, sizeof(DCB)); #endif continue; case 'c': /* character size */ #ifndef _WIN32 switch (*endp) { case '5': flag = CS5; break; case '6': flag = CS6; break; case '7': flag = CS7; break; default: flag = CS8; } mask = CSIZE; #else dcb.ByteSize = (char) (*endp - '0'); #endif break; case 'p': /* parity */ #ifndef _WIN32 switch (*endp) { case 'd': flag = PARODD; case 'n': flag |= PARENB; break; default: flag = 0; /* no parity */ } mask = PARENB | PARODD; #else { int parity; switch (*endp) { case 'd': parity = ODDPARITY; break; case 'n': parity = EVENPARITY; break; default: parity = 0; /* no parity */ } dcb.Parity = (char) parity; dcb.fParity = (parity != 0); } #endif break; case 's': /* stop bits */ #ifndef _WIN32 if (*endp == '2') flag = CSTOPB; /* else: one stop bit */ mask = CSTOPB; #else dcb.StopBits = (char) (*endp == '2' ? TWOSTOPBITS : ONESTOPBIT); #endif break; case 'f': /* flow controls */ /* off */ #ifndef _WIN32 mask = CRTSCTS; tio.c_iflag &= ~(IXON | IXOFF | IXANY); #else dcb.fOutX = dcb.fInX = 0; dcb.fRtsControl = RTS_CONTROL_DISABLE; dcb.fOutxCtsFlow = 0; #endif switch (opt[1]) { case 'x': /* XON/XOFF */ #ifndef _WIN32 tio.c_iflag |= (IXON | IXOFF | IXANY); #else dcb.fOutX = dcb.fInX = 1; #endif break; case 'r': /* RTS/CTS */ #ifndef _WIN32 flag = CRTSCTS; #else dcb.fRtsControl = RTS_CONTROL_HANDSHAKE; dcb.fOutxCtsFlow = 1; #endif break; } break; } } #ifndef _WIN32 tio.c_cflag &= ~mask; tio.c_cflag |= flag; #endif } #ifndef _WIN32 tio.c_cflag |= CLOCAL | CREAD; if (!tcsetattr(fd, TCSANOW, &tio)) { #else if (SetCommState(fd, &dcb)) { #endif lua_settop(L, 1); return 1; } err: return sys_seterror(L, 0); } /* * Arguments: fd_udata, [controls (string: "dtr", "dsr", "rts", "cts") ...] * Returns: [fd_udata] */ static int comm_control (lua_State *L) { const fd_t fd = (fd_t) lua_unboxinteger(L, 1, FD_TYPENAME); const int narg = lua_gettop(L); int i; #ifndef _WIN32 int flags; if (ioctl(fd, TIOCMGET, &flags) == -1) goto err; flags &= ~(TIOCM_DTR | TIOCM_DSR | TIOCM_RTS | TIOCM_CTS | TIOCM_ST | TIOCM_SR | TIOCM_CAR | TIOCM_RNG); #else DCB dcb; dcb.DCBlength = sizeof(DCB); if (!GetCommState(fd, &dcb)) goto err; dcb.fDtrControl = dcb.fOutxDsrFlow = dcb.fRtsControl = dcb.fOutxCtsFlow = 0; #endif for (i = 2; i <= narg; ++i) { const char *s = lua_tostring(L, i); if (!s) continue; switch (*s) { case 'd': /* DTR/DSR */ #ifndef _WIN32 flags |= (s[1] == 't') ? TIOCM_DTR : TIOCM_DSR; #else if (s[1] == 't') dcb.fDtrControl = 1; else dcb.fOutxDsrFlow = 1; #endif break; case 'r': /* RTS */ #ifndef _WIN32 flags |= TIOCM_RTS; #else dcb.fRtsControl = 1; #endif break; case 'c': /* CTS */ #ifndef _WIN32 flags |= TIOCM_CTS; #else dcb.fOutxCtsFlow = 1; #endif break; } } #ifndef _WIN32 if (!ioctl(fd, TIOCMSET, &flags)) { #else if (SetCommState(fd, &dcb)) { #endif lua_settop(L, 1); return 1; } err: return sys_seterror(L, 0); } /* * Arguments: fd_udata, [read_timeout (milliseconds)] * Returns: [fd_udata] */ static int comm_timeout (lua_State *L) { const fd_t fd = (fd_t) lua_unboxinteger(L, 1, FD_TYPENAME); const int rtime = lua_tointeger(L, 2); #ifndef _WIN32 struct termios tio; if (tcgetattr(fd, &tio) == -1) goto err; tio.c_cc[VTIME] = rtime / 100; tio.c_cc[VMIN] = 0; if (!tcsetattr(fd, TCSANOW, &tio)) { #else COMMTIMEOUTS timeouts; memset(&timeouts, 0, sizeof(COMMTIMEOUTS)); timeouts.ReadIntervalTimeout = rtime ? (DWORD) rtime : MAXDWORD; timeouts.ReadTotalTimeoutMultiplier = timeouts.ReadTotalTimeoutConstant = rtime; if (SetCommTimeouts(fd, &timeouts)) { #endif lua_settop(L, 1); return 1; } #ifndef _WIN32 err: #endif return sys_seterror(L, 0); } /* * Arguments: fd_udata, in_buffer_size (number), out_buffer_size (number) * Returns: [fd_udata] */ static int comm_queues (lua_State *L) { #ifndef _WIN32 if (1) { #else const fd_t fd = (fd_t) lua_unboxinteger(L, 1, FD_TYPENAME); const int rqueue = lua_tointeger(L, 2); const int wqueue = lua_tointeger(L, 3); if (SetupComm(fd, rqueue, wqueue)) { #endif lua_settop(L, 1); return 1; } #ifdef _WIN32 return sys_seterror(L, 0); #endif } /* * Arguments: fd_udata, [mode (string: "rw", "r", "w")] * Returns: [fd_udata] */ static int comm_purge (lua_State *L) { const fd_t fd = (fd_t) lua_unboxinteger(L, 1, FD_TYPENAME); const char *mode = lua_tostring(L, 2); int flags; flags = TCIOFLUSH; if (mode) switch (mode[0]) { case 'w': flags = TCOFLUSH; break; case 'r': if (!mode[1]) flags = TCIFLUSH; } #ifndef _WIN32 if (!tcflush(fd, flags)) { #else if (PurgeComm(fd, flags)) { #endif lua_settop(L, 1); return 1; } return sys_seterror(L, 0); } /* * Arguments: fd_udata, options (string: "car", "cts", "dsr", "ring") ... * Returns: [boolean ...] */ static int comm_wait (lua_State *L) { const fd_t fd = (fd_t) lua_unboxinteger(L, 1, FD_TYPENAME); const int narg = lua_gettop(L); unsigned long status = 0; int flags = 0; int i, res; for (i = 2; i <= narg; ++i) { const char *s = lua_tostring(L, i); if (!s) continue; switch (*s) { case 'c': /* CAR/CTS */ flags |= (s[1] == 'a') ? TIOCM_CAR : TIOCM_CTS; break; case 'd': /* DSR */ flags |= TIOCM_DSR; break; case 'r': /* RING */ flags |= TIOCM_RNG; break; } } sys_vm_leave(); #ifndef _WIN32 do { #ifdef TIOCMIWAIT res = !(ioctl(fd, TIOCMIWAIT, flags) || ioctl(fd, TIOCMGET, &status)); #else while ((res = !ioctl(fd, TIOCMGET, &status)) && !(status & flags)) usleep(10000); /* 10 msec polling */ #endif } while (!res && sys_eintr()); #else res = SetCommMask(fd, flags) && WaitCommEvent(fd, &status, NULL); #endif sys_vm_enter(); if (res) { if (flags & TIOCM_CAR) lua_pushboolean(L, status & TIOCM_CAR); if (flags & TIOCM_CTS) lua_pushboolean(L, status & TIOCM_CTS); if (flags & TIOCM_DSR) lua_pushboolean(L, status & TIOCM_DSR); if (flags & TIOCM_RNG) lua_pushboolean(L, status & TIOCM_RNG); return narg - 1; } return sys_seterror(L, 0); }
/* * Decodes terminal modes for the terminal referenced by fd in a portable * manner from a packet being read. */ void ssh_tty_parse_modes(struct ssh *ssh, int fd) { struct termios tio; struct sshbuf *buf; const u_char *data; u_char opcode; u_int baud, u; int r, failure = 0; size_t len; if ((r = sshpkt_get_string_direct(ssh, &data, &len)) != 0) fatal("%s: packet error: %s", __func__, ssh_err(r)); if (len == 0) return; if ((buf = sshbuf_from(data, len)) == NULL) { error("%s: sshbuf_from failed", __func__); return; } /* * Get old attributes for the terminal. We will modify these * flags. I am hoping that if there are any machine-specific * modes, they will initially have reasonable values. */ if (tcgetattr(fd, &tio) == -1) { logit("tcgetattr: %.100s", strerror(errno)); failure = -1; } while (sshbuf_len(buf) > 0) { if ((r = sshbuf_get_u8(buf, &opcode)) != 0) fatal("%s: packet error: %s", __func__, ssh_err(r)); switch (opcode) { case TTY_OP_END: goto set; case TTY_OP_ISPEED: if ((r = sshbuf_get_u32(buf, &baud)) != 0) fatal("%s: packet error: %s", __func__, ssh_err(r)); if (failure != -1 && cfsetispeed(&tio, baud_to_speed(baud)) == -1) error("cfsetispeed failed for %d", baud); break; case TTY_OP_OSPEED: if ((r = sshbuf_get_u32(buf, &baud)) != 0) fatal("%s: packet error: %s", __func__, ssh_err(r)); if (failure != -1 && cfsetospeed(&tio, baud_to_speed(baud)) == -1) error("cfsetospeed failed for %d", baud); break; #define TTYCHAR(NAME, OP) \ case OP: \ if ((r = sshbuf_get_u32(buf, &u)) != 0) \ fatal("%s: packet error: %s", __func__, \ ssh_err(r)); \ tio.c_cc[NAME] = u; \ break; #define TTYMODE(NAME, FIELD, OP) \ case OP: \ if ((r = sshbuf_get_u32(buf, &u)) != 0) \ fatal("%s: packet error: %s", __func__, \ ssh_err(r)); \ if (u) \ tio.FIELD |= NAME; \ else \ tio.FIELD &= ~NAME; \ break; #include "ttymodes.h" #undef TTYCHAR #undef TTYMODE default: debug("Ignoring unsupported tty mode opcode %d (0x%x)", opcode, opcode); /* * SSH2: * Opcodes 1 to 159 are defined to have a uint32 * argument. * Opcodes 160 to 255 are undefined and cause parsing * to stop. */ if (opcode > 0 && opcode < 160) { if ((r = sshbuf_get_u32(buf, NULL)) != 0) fatal("%s: packet error: %s", __func__, ssh_err(r)); break; } else { logit("%s: unknown opcode %d", __func__, opcode); goto set; } } } set: len = sshbuf_len(buf); sshbuf_free(buf); if (len > 0) { logit("%s: %zu bytes left", __func__, len); return; /* Don't process bytes passed */ } if (failure == -1) return; /* Packet parsed ok but tcgetattr() failed */ /* Set the new modes for the terminal. */ if (tcsetattr(fd, TCSANOW, &tio) == -1) logit("Setting tty modes failed: %.100s", strerror(errno)); }
int OpenConnection(void) { /* UART_Start(); */ int speed; if (serial_port == NULL) { if ((serial_port = strdup(MODEMDEV)) == NULL) { printf("[ERROR] malloc failed\n"); return(CYRET_ERR_FILE); } } // tty_fd=open(argv[1], O_RDWR | O_NONBLOCK); tty_fd=open(serial_port, O_RDWR | O_NOCTTY | O_SYNC); if ( tty_fd == -1) { printf("[ERROR] opening %s : %s\n",serial_port,strerror(errno)); exit(1); // return (CYRET_ERR_FILE); } memset(&tio,0,sizeof(tio)); tio.c_iflag=0; tio.c_oflag=0; tio.c_cflag=CS8|CREAD|CLOCAL; // 8n1, see termios.h for more information tio.c_lflag=0; tio.c_cc[VMIN]=1; tio.c_cc[VTIME]=5; switch(serial_speed) { case 9600: speed = B9600; break; case 19200: speed = B19200; break; case 38400: speed = B38400; break; case 57600: speed = B57600; break; case 115200: speed = B115200; break; default: speed = COMSPEED; printf("[INFO] unsupported speed %d, defaulting to %d\n",serial_speed,speed); break; } if ( cfsetospeed(&tio,speed) == -1) { // 115200 baud printf("[ERROR] %s\n",strerror(errno)); return (CYRET_ERR_FILE); } if (cfsetispeed(&tio,speed) == -1) { // 115200 baud printf("[ERROR] %s\n",strerror(errno)); return (CYRET_ERR_FILE); } if (tcsetattr(tty_fd,TCSANOW,&tio) == -1) { printf("[ERROR] %s\n",strerror(errno)); return (CYRET_ERR_FILE); } return(CYRET_SUCCESS); }
// ------------------------------------------------------------------------------ // Helper Function - Setup Serial Port // ------------------------------------------------------------------------------ // Sets configuration, flags, and baud rate bool Serial_Port:: _setup_port(int baud, int data_bits, int stop_bits, bool parity, bool hardware_control) { // Check file descriptor if(!isatty(fd)) { fprintf(stderr, "\nERROR: file descriptor %d is NOT a serial port\n", fd); return false; } // Read file descritor configuration struct termios config; if(tcgetattr(fd, &config) < 0) { fprintf(stderr, "\nERROR: could not read configuration of fd %d\n", fd); return false; } // Input flags - Turn off input processing // convert break to null byte, no CR to NL translation, // no NL to CR translation, don't mark parity errors or breaks // no input parity check, don't strip high bit off, // no XON/XOFF software flow control config.c_iflag &= ~(IGNBRK | BRKINT | ICRNL | INLCR | PARMRK | INPCK | ISTRIP | IXON); // Output flags - Turn off output processing // no CR to NL translation, no NL to CR-NL translation, // no NL to CR translation, no column 0 CR suppression, // no Ctrl-D suppression, no fill characters, no case mapping, // no local output processing config.c_oflag &= ~(OCRNL | ONLCR | ONLRET | ONOCR | OFILL | OPOST); #ifdef OLCUC config.c_oflag &= ~OLCUC; #endif #ifdef ONOEOT config.c_oflag &= ~ONOEOT; #endif // No line processing: // echo off, echo newline off, canonical mode off, // extended input processing off, signal chars off config.c_lflag &= ~(ECHO | ECHONL | ICANON | IEXTEN | ISIG); // Turn off character processing // clear current char size mask, no parity checking, // no output processing, force 8 bit input config.c_cflag &= ~(CSIZE | PARENB); config.c_cflag |= CS8; // One input byte is enough to return from read() // Inter-character timer off config.c_cc[VMIN] = 1; config.c_cc[VTIME] = 10; // was 0 // Get the current options for the port ////struct termios options; ////tcgetattr(fd, &options); // Apply baudrate switch (baud) { case 1200: if (cfsetispeed(&config, B1200) < 0 || cfsetospeed(&config, B1200) < 0) { fprintf(stderr, "\nERROR: Could not set desired baud rate of %d Baud\n", baud); return false; } break; case 1800: cfsetispeed(&config, B1800); cfsetospeed(&config, B1800); break; case 9600: cfsetispeed(&config, B9600); cfsetospeed(&config, B9600); break; case 19200: cfsetispeed(&config, B19200); cfsetospeed(&config, B19200); break; case 38400: if (cfsetispeed(&config, B38400) < 0 || cfsetospeed(&config, B38400) < 0) { fprintf(stderr, "\nERROR: Could not set desired baud rate of %d Baud\n", baud); return false; } break; case 57600: if (cfsetispeed(&config, B57600) < 0 || cfsetospeed(&config, B57600) < 0) { fprintf(stderr, "\nERROR: Could not set desired baud rate of %d Baud\n", baud); return false; } break; case 115200: if (cfsetispeed(&config, B115200) < 0 || cfsetospeed(&config, B115200) < 0) { fprintf(stderr, "\nERROR: Could not set desired baud rate of %d Baud\n", baud); return false; } break; // These two non-standard (by the 70'ties ) rates are fully supported on // current Debian and Mac OS versions (tested since 2010). case 460800: if (cfsetispeed(&config, B460800) < 0 || cfsetospeed(&config, B460800) < 0) { fprintf(stderr, "\nERROR: Could not set desired baud rate of %d Baud\n", baud); return false; } break; case 921600: if (cfsetispeed(&config, B921600) < 0 || cfsetospeed(&config, B921600) < 0) { fprintf(stderr, "\nERROR: Could not set desired baud rate of %d Baud\n", baud); return false; } break; default: fprintf(stderr, "ERROR: Desired baud rate %d could not be set, aborting.\n", baud); return false; break; } // Finally, apply the configuration if(tcsetattr(fd, TCSAFLUSH, &config) < 0) { fprintf(stderr, "\nERROR: could not set configuration of fd %d\n", fd); return false; } // Done! return true; }
int GPS::setBaudrate(unsigned baud) { #if __PX4_QURT // TODO: currently QURT does not support configuration with termios. dspal_serial_ioctl_data_rate data_rate; switch (baud) { case 9600: data_rate.bit_rate = DSPAL_SIO_BITRATE_9600; break; case 19200: data_rate.bit_rate = DSPAL_SIO_BITRATE_19200; break; case 38400: data_rate.bit_rate = DSPAL_SIO_BITRATE_38400; break; case 57600: data_rate.bit_rate = DSPAL_SIO_BITRATE_57600; break; case 115200: data_rate.bit_rate = DSPAL_SIO_BITRATE_115200; break; default: PX4_ERR("ERR: unknown baudrate: %d", baud); return -EINVAL; } int ret = ::ioctl(_serial_fd, SERIAL_IOCTL_SET_DATA_RATE, (void *)&data_rate); if (ret != 0) { return ret; } #else /* process baud rate */ int speed; switch (baud) { case 9600: speed = B9600; break; case 19200: speed = B19200; break; case 38400: speed = B38400; break; case 57600: speed = B57600; break; case 115200: speed = B115200; break; default: PX4_ERR("ERR: unknown baudrate: %d", baud); return -EINVAL; } struct termios uart_config; int termios_state; /* fill the struct for the new configuration */ tcgetattr(_serial_fd, &uart_config); /* properly configure the terminal (see also https://en.wikibooks.org/wiki/Serial_Programming/termios ) */ // // Input flags - Turn off input processing // // convert break to null byte, no CR to NL translation, // no NL to CR translation, don't mark parity errors or breaks // no input parity check, don't strip high bit off, // no XON/XOFF software flow control // uart_config.c_iflag &= ~(IGNBRK | BRKINT | ICRNL | INLCR | PARMRK | INPCK | ISTRIP | IXON); // // Output flags - Turn off output processing // // no CR to NL translation, no NL to CR-NL translation, // no NL to CR translation, no column 0 CR suppression, // no Ctrl-D suppression, no fill characters, no case mapping, // no local output processing // // config.c_oflag &= ~(OCRNL | ONLCR | ONLRET | // ONOCR | ONOEOT| OFILL | OLCUC | OPOST); uart_config.c_oflag = 0; // // No line processing // // echo off, echo newline off, canonical mode off, // extended input processing off, signal chars off // uart_config.c_lflag &= ~(ECHO | ECHONL | ICANON | IEXTEN | ISIG); /* no parity, one stop bit */ uart_config.c_cflag &= ~(CSTOPB | PARENB); /* set baud rate */ if ((termios_state = cfsetispeed(&uart_config, speed)) < 0) { GPS_ERR("ERR: %d (cfsetispeed)", termios_state); return -1; } if ((termios_state = cfsetospeed(&uart_config, speed)) < 0) { GPS_ERR("ERR: %d (cfsetospeed)", termios_state); return -1; } if ((termios_state = tcsetattr(_serial_fd, TCSANOW, &uart_config)) < 0) { GPS_ERR("ERR: %d (tcsetattr)", termios_state); return -1; } #endif return 0; }
/* * Class: cedric_serial_SerialPort * Method: open * Signature: (Ljava/lang/String;)V */ JNIEXPORT jobject JNICALL Java_com_erobbing_mcutool_SerialPort_open(JNIEnv *env, jobject thiz, jstring path,jint baudrate) { int fd; speed_t speed; jobject mFileDescriptor; LOGD("init native Check arguments"); /* Check arguments */ { speed = getBaudrate(baudrate); if (speed == -1) { /* TODO: throw an exception */ LOGE("Invalid baudrate"); return NULL; } } LOGD("init native Opening device!"); /* Opening device */ { jboolean iscopy; const char *path_utf = env->GetStringUTFChars(path, &iscopy); LOGD("Opening serial port %s", path_utf); // fd = open(path_utf, O_RDWR | O_DIRECT | O_SYNC); fd = open(path_utf, O_RDWR | O_NOCTTY | O_NONBLOCK | O_NDELAY); LOGD("open() fd = %d", fd); env->ReleaseStringUTFChars(path, path_utf); if (fd == -1) { /* Throw an exception */ LOGE("Cannot open port %d",baudrate); /* TODO: throw an exception */ return NULL; } } LOGD("init native Configure device!"); /* Configure device */ { struct termios cfg; if (tcgetattr(fd, &cfg)) { LOGE("Configure device tcgetattr() failed 1"); close(fd); return NULL; } cfmakeraw(&cfg); cfsetispeed(&cfg, speed); cfsetospeed(&cfg, speed); if (tcsetattr(fd, TCSANOW, &cfg)) { LOGE("Configure device tcsetattr() failed 2"); close(fd); /* TODO: throw an exception */ return NULL; } } /* Create a corresponding file descriptor */ { jclass cFileDescriptor = env->FindClass("java/io/FileDescriptor"); jmethodID iFileDescriptor = env->GetMethodID(cFileDescriptor,"<init>", "()V"); jfieldID descriptorID = env->GetFieldID(cFileDescriptor,"descriptor", "I"); mFileDescriptor = env->NewObject(cFileDescriptor,iFileDescriptor); env->SetIntField(mFileDescriptor, descriptorID, (jint) fd); } return mFileDescriptor; }
int main(int argc, char *argv[]) { struct info i; enum FMT fmt; int ch; const char *file; fmt = NOTSET; i.fd = STDIN_FILENO; file = "stdin"; opterr = 0; while (optind < argc && strspn(argv[optind], "-aefg") == strlen(argv[optind]) && (ch = getopt(argc, argv, "aef:g")) != -1) switch(ch) { case 'a': /* undocumented: POSIX compatibility */ fmt = POSIX; break; case 'e': fmt = BSD; break; case 'f': if ((i.fd = open(optarg, O_RDONLY | O_NONBLOCK)) < 0) err(1, "%s", optarg); file = optarg; break; case 'g': fmt = GFLAG; break; case '?': default: goto args; } args: argc -= optind; argv += optind; if (tcgetattr(i.fd, &i.t) < 0) errx(1, "%s isn't a terminal", file); if (ioctl(i.fd, TIOCGETD, &i.ldisc) < 0) err(1, "TIOCGETD"); if (ioctl(i.fd, TIOCGWINSZ, &i.win) < 0) warn("TIOCGWINSZ"); checkredirect(); /* conversion aid */ switch(fmt) { case NOTSET: if (*argv) break; /* FALLTHROUGH */ case BSD: case POSIX: print(&i.t, &i.win, i.ldisc, fmt); break; case GFLAG: gprint(&i.t, &i.win, i.ldisc); break; } for (i.set = i.wset = 0; *argv; ++argv) { if (ksearch(&argv, &i)) continue; if (csearch(&argv, &i)) continue; if (msearch(&argv, &i)) continue; if (isdigit(**argv)) { speed_t speed; speed = atoi(*argv); cfsetospeed(&i.t, speed); cfsetispeed(&i.t, speed); i.set = 1; continue; } if (!strncmp(*argv, "gfmt1", sizeof("gfmt1") - 1)) { gread(&i.t, *argv + sizeof("gfmt1") - 1); i.set = 1; continue; } warnx("illegal option -- %s", *argv); usage(); } if (i.set && tcsetattr(i.fd, 0, &i.t) < 0) err(1, "tcsetattr"); if (i.wset && ioctl(i.fd, TIOCSWINSZ, &i.win) < 0) warn("TIOCSWINSZ"); exit(0); }
/***@brief 设置串口通信速率 *param fd 类型 int 打开串口的文件句柄 *param speed 类型 int 串口速度,波特率 *param nEvent :奇偶校验设置,0:无校验,1:奇校验,2:偶校验 *param nStop : 停止位,设置为0,或者1 *return void*/ int set_opt(int fd,int nSpeed,int nBits,int nEvent,int nStop) { struct termios newtio,oldtio; if(tcgetattr(fd,&oldtio)) { printf("tcgetattr in set_opt"); return -1; } bzero(&newtio,sizeof(newtio)); newtio.c_cflag |= CLOCAL|CREAD; newtio.c_cflag &= ~CSIZE; //newtio.c_oflag |= OPOST; switch(nBits) { case 0: newtio.c_cflag |= CS5; break; case 1: newtio.c_cflag |= CS6; break; case 2: newtio.c_cflag |= CS7; break; case 3: newtio.c_cflag |= CS8; break; default: break; } switch(nEvent) { case 0: newtio.c_cflag &= ~PARENB; break; case 1: //奇校验。 // odd newtio.c_cflag |= PARENB; newtio.c_cflag |= PARODD; //newtio.c_iflag |= (INPCK|ISTRIP); newtio.c_iflag |= (INPCK); break; case 2: //偶校验。 // even newtio.c_cflag |= PARENB; newtio.c_cflag &= ~PARODD; //newtio.c_iflag |= (INPCK|ISTRIP); newtio.c_iflag |= (INPCK); break; } //newtio.c_iflag |= (IGNPAR); //newtio.c_iflag |= (PARMRK | IGNPAR); //newtio.c_iflag |= (PARMRK); switch(nSpeed) { case 1200: cfsetispeed(&newtio,B1200); cfsetospeed(&newtio,B1200); break; case 2400: cfsetispeed(&newtio,B2400); cfsetospeed(&newtio,B2400); break; case 4800: cfsetispeed(&newtio,B4800); cfsetospeed(&newtio,B4800); break; case 9600: cfsetispeed(&newtio,B9600); cfsetospeed(&newtio,B9600); break; case 19200: cfsetispeed(&newtio,B19200); cfsetospeed(&newtio,B19200); break; case 38400: cfsetispeed(&newtio,B38400); cfsetospeed(&newtio,B38400); break; case 57600: cfsetispeed(&newtio,B57600); cfsetospeed(&newtio,B57600); break; case 115200: cfsetispeed(&newtio,B115200); cfsetospeed(&newtio,B115200); break; default: break; } //停止位:1,2。 if(nStop==0) { newtio.c_cflag &=~CSTOPB; } else if(nStop==1) { newtio.c_cflag |=CSTOPB; } //navy add //newtio.c_oflag &= ~OPOST; //newtio.c_lflag &= ~(ICANON|ECHO|ECHOE|ISIG); //tcflush(fd, TCIOFLUSH); //navy add //end navy newtio.c_cc[VTIME]=0; newtio.c_cc[VMIN]=0; if(0!=(tcsetattr(fd,TCSANOW,&newtio))) { printf("com set error\n"); return -1; } return 0; }
int init_uart (const char *port) { int r; info ("Opening serial device: %s\n", port); tty_file_desc = open (port, O_RDWR | /*O_NONBLOCK | */O_NOCTTY, 0); if (tty_file_desc < 1) { error ("FATAL: Could not open serial device\n"); goto serial_device_open_fail; } printf ("File descriptor :: %d\n", tty_file_desc); // get the current attributes memset (&termios, 0, sizeof(struct termios)); r = tcgetattr (tty_file_desc, &termios); if (r != 0) { error ("Failed to get attribute"); goto attribute_change_fail; } /* termios.c_iflag &= ~(IGNBRK | BRKINT | PARMRK | ISTRIP | INLCR | IGNCR | ICRNL | IXON); termios.c_oflag &= ~OPOST; termios.c_lflag &= ~(ECHO | ECHONL | ICANON | ISIG | IEXTEN); termios.c_cflag &= ~(CSIZE | PARENB); termios.c_cflag |= CS8; */ /* makeraw does this termios_p->c_iflag &= ~(IGNBRK | BRKINT | PARMRK | ISTRIP | INLCR | IGNCR | ICRNL | IXON); termios_p->c_oflag &= ~OPOST; termios_p->c_lflag &= ~(ECHO | ECHONL | ICANON | ISIG | IEXTEN); termios_p->c_cflag &= ~(CSIZE | PARENB); termios_p->c_cflag |= CS8; */ // set the attributes //termios.c_iflag &= //~(IGNBRK | /* ignore break */ // INPCK | /* enable input parity check */ // termios.c_oflag = 0; // termios.c_cflag = B115200 | CS8 | CLOCAL | CREAD; cfmakeraw (&termios); // set the baud rate cfsetispeed (&termios, B115200); cfsetospeed (&termios, B115200); termios.c_cflag |= B115200 | CS8 | CLOCAL | CREAD; // additional for hawkboard termios.c_iflag |= IGNPAR; termios.c_iflag &= ~INPCK; // ~hawkboard r = tcsetattr (tty_file_desc, TCSANOW, &termios); if (r != 0) { error ("Failed to set attribute"); goto attribute_change_fail; } if (verify_settingschange (tty_file_desc, &termios) != 0) goto attribute_change_fail; #if 0 char uc = 'X', rc = 'Y'; const char string[]="Kaustubh Satish Ashtekar"; char readstring[sizeof(string)+10]; int wi,ri, t; #if 1 ri = 0; while (1) { // write (tty_file_desc, &uc, 1); if (read (tty_file_desc, &rc, 1) == 1) { printf ("%c\n", rc); } } #endif for (t = sizeof(string), ri = 0, wi = 0;;) { if (wi < (sizeof(string)-1)) { write (tty_file_desc, &string[wi], 1); wi++; } if (ri < sizeof(string)) { 1 if (read (tty_file_desc, &rc, 1) == 1) { printf ("%c", rc); readstring[ri]=rc; ri++; } } if (ri == (sizeof(string)-1)) break; }
bool MLTTYDevice::open(QIODevice::OpenMode mode) { int flags=O_NONBLOCK|O_NOCTTY; struct termios term; tty_mode=mode; if((mode&QIODevice::ReadWrite)==QIODevice::ReadWrite) { flags|=O_RDWR; } else { if(((mode&QIODevice::WriteOnly)!=0)) { flags|=O_WRONLY; } if(((mode&QIODevice::ReadOnly)!=0)) { flags|=O_RDONLY; } } if((mode&QIODevice::Append)!=0) { flags|=O_APPEND; } if((mode&QIODevice::Truncate)!=0) { flags|=O_TRUNC; } if((tty_fd=::open(tty_name.toAscii(),flags))<0) { return false; } tty_open=true; tcgetattr(tty_fd,&term); // // Set Speed // //cfsetispeed(&term,B0); cfsetispeed(&term,tty_speed); cfsetospeed(&term,tty_speed); // // Set Mode // cfmakeraw(&term); term.c_iflag |= IGNBRK; // // Set Parity // switch(tty_parity) { case MLTTYDevice::None: term.c_iflag |= IGNPAR; break; case MLTTYDevice::Even: term.c_cflag |= PARENB; break; case MLTTYDevice::Odd: term.c_cflag |= PARENB|PARODD; break; } // // Set Word Length // //term.c_cflag &= ~CSIZE; switch(tty_length) { case 5: term.c_cflag |= CS5; break; case 6: term.c_cflag |= CS6; break; case 7: term.c_cflag |= CS7; break; case 8: term.c_cflag |= CS8; break; } // // Set Flow Control // switch(tty_flow_control) { case MLTTYDevice::FlowNone: term.c_cflag &= ~CRTSCTS; term.c_iflag &= ~IXON; term.c_iflag &= ~IXOFF; break; case MLTTYDevice::FlowRtsCts: term.c_cflag |= CRTSCTS; term.c_iflag &= ~IXON; term.c_iflag &= ~IXOFF; break; case MLTTYDevice::FlowXonXoff: term.c_cflag &= ~CRTSCTS; term.c_iflag |= IXON; term.c_iflag |= IXOFF; break; } tcsetattr(tty_fd,TCSADRAIN,&term); tty_notifier=new QSocketNotifier(tty_fd,QSocketNotifier::Read,this); connect(tty_notifier,SIGNAL(activated(int)),this,SLOT(readTtyData(int))); tty_write_timer->start(10); return true; }
/********************************************************************** * sio_open * * Open and initiate serial port * default open port in noncanonical mode * * Arguments: * port a string point to the name of serial device, * such as "/dev/ttyS0" * baud B0, B50... B9600, B19200, B38400... * data Data bit(s), unsigned char * parity Parity, unsigned char * stop Stop bit(s), unsigned char * * Returned: * This function returns int port descriptor for the port opened * successfully. Return value ERR_PORT_OPEN if failed. * **********************************************************************/ int sio_open(const char *port, speed_t baud, tcflag_t data, tcflag_t parity, tcflag_t stop) { struct sio *sio; /* point to current sio structure */ int fd; /* file descriptor for current port */ int r; struct termios *options; /* options for current port */ PDEBUG("sio_open: start\n"); /*************** * open port * ***************/ fd = _sio_device(port); if (fd == 0) { /* device is not yet opened, so, open it */ // fd = open(port, O_RDWR | O_NOCTTY | O_NDELAY); //printf("%s ... open %s\n",__FUNCTION__, port); fd = open(port, O_RDWR | O_NOCTTY); } PDEBUG(" fd = %u\n", fd); if (fd == -1) { /* Could not open the port */ PDEBUG("sio_open: Unable to open %s - %s\n", strerror(errno), port); return (ERR_PORT_OPEN); } /******************************** * allocate new sio structure * ********************************/ sio = _sio_follow(fd); if (!sio) { /* out of memory */ close(fd); return (ERR_PORT_OPEN); } sio->fd = fd; sio->name = port; // fcntl(fd, F_SETFL, FNDELAY); /* nonblocking */ tcgetattr(fd, sio->old_options); /* save the original options */ tcgetattr(fd, sio->options); /* Get the current options */ options = sio->options; /* * printf("\nsio_open\n"); printf("name : %s\n", sio->name); * printf("fd : %d\n", fd); printf("sio : %lx\n", sio); * printf("sio->options : %lx\n", sio->options); * printf("sio->old_options : %lx\n", sio->old_options); * printf("options : %lx\n", options); printf("\n"); */ /********************* * select Baudrate * *********************/ r = cfsetispeed(options, baud); /* input */ if (r) { PDEBUG("sio_open: fails to set input baudrate!\n", r); close(fd); return (r); } r = cfsetospeed(options, baud); /* output */ if (r) { PDEBUG("sio_open: fails to set output baudrate!\n", r); close(fd); return (r); } /********************** * select data bits * **********************/ options->c_cflag &= ~CSIZE; /* bit mask for data bits */ options->c_cflag |= data; /* * close(fd); PDEBUG("undefined data bits number %d, port %s * closed.\n", data, port); return (ERR_PORT_OPEN); */ /******************* * select parity * *******************/ switch (parity) { case NO_PARITY: options->c_cflag &= ~(PARENB | PARODD); break; case ODD_PARITY: options->c_cflag |= PARODD; break; case EVEN_PARITY: options->c_cflag |= PARENB; break; default: tcsetattr(fd, TCSANOW, sio->old_options); close(fd); _sio_trim(fd); PDEBUG("undefined parity code %d, port %s closed.\n", parity, port); return (ERR_PORT_OPEN); } /************************ * select stop bit(s) * ************************/ switch (stop) { case ONE_STOP_BIT: options->c_cflag &= ~CSTOPB; break; case TWO_STOP_BITS: options->c_cflag |= CSTOPB; break; default: tcsetattr(fd, TCSANOW, sio->old_options); close(fd); _sio_trim(fd); PDEBUG("undefined stop bits code %d, port %s closed.\n", stop, port); return (ERR_PORT_OPEN); } /********************** * other parameterm * **********************/ /* * posix input mode flags */ options->c_iflag &= ~ICRNL; /* disable map CR to NL for noncanonical */ options->c_iflag &= ~INLCR; options->c_iflag &= ~IXON; /* disable software flow control * (outgoing) */ options->c_iflag &= ~IXOFF; /* disable software flow control * (incoming) */ /* * posix output mode flags */ options->c_oflag &= ~OPOST; /* raw output */ options->c_oflag &= ~OLCUC; /* do not transfer the case */ options->c_oflag &= ~ONLCR; /* do not translate the CR and NL */ options->c_oflag &= ~OCRNL; options->c_oflag &= ~NLDLY; /* no delay for NL */ options->c_oflag &= ~CRDLY; /* no delay for CR */ options->c_oflag &= ~TABDLY; /* no delay for TAB */ options->c_oflag &= ~BSDLY; /* no delay for BS */ options->c_oflag &= ~VTDLY; /* no delay for VT */ options->c_oflag &= ~FFDLY; /* no delay for FF */ /* * posix control mode flags */ options->c_cflag |= CLOCAL; /* Local line */ /* * do not change "owner" of port */ options->c_cflag |= CREAD; /* Enable receiver */ options->c_cflag &= ~CRTSCTS; /* Disable hardware flow control */ /* * posix local mode flags */ options->c_lflag &= ~ICANON; /* default for noncanonical mode */ options->c_lflag &= ~ECHO; /* Disable echoing of input characters */ options->c_lflag &= ~ISIG; /* disable signals */ /* * posix control characters */ options->c_cc[VINTR] = 0; options->c_cc[VQUIT] = 0; options->c_cc[VERASE] = 0; options->c_cc[VKILL] = 0; options->c_cc[VEOF] = 4; options->c_cc[VTIME] = 0; /* Time to wait for data (tenths of * seconds) */ options->c_cc[VMIN] = 1; options->c_cc[VSWTC] = 0; options->c_cc[VSTART] = 0; options->c_cc[VSTOP] = 0; options->c_cc[VSUSP] = 0; options->c_cc[VEOL] = 0; options->c_cc[VREPRINT] = 0; options->c_cc[VDISCARD] = 0; options->c_cc[VWERASE] = 0; options->c_cc[VLNEXT] = 0; options->c_cc[VEOL2] = 0; /************************************** * set the new options for the port * **************************************/ // tcsetattr(fd, TCSANOW, options); tcsetattr(fd, TCSAFLUSH, options); /* flush input and output buffers, * and make the change */ # ifdef I7K_DEBUG _sio_poptions(fd); # endif /* I7K_DEBUG */ return (fd); }
int Mavlink::mavlink_open_uart(int baud, const char *uart_name, struct termios *uart_config_original, bool *is_usb) { /* process baud rate */ int speed; switch (baud) { case 0: speed = B0; break; case 50: speed = B50; break; case 75: speed = B75; break; case 110: speed = B110; break; case 134: speed = B134; break; case 150: speed = B150; break; case 200: speed = B200; break; case 300: speed = B300; break; case 600: speed = B600; break; case 1200: speed = B1200; break; case 1800: speed = B1800; break; case 2400: speed = B2400; break; case 4800: speed = B4800; break; case 9600: speed = B9600; break; case 19200: speed = B19200; break; case 38400: speed = B38400; break; case 57600: speed = B57600; break; case 115200: speed = B115200; break; case 230400: speed = B230400; break; case 460800: speed = B460800; break; case 921600: speed = B921600; break; default: warnx("ERROR: Unsupported baudrate: %d\n\tsupported examples:\n\t9600, 19200, 38400, 57600\t\n115200\n230400\n460800\n921600\n", baud); return -EINVAL; } /* open uart */ _uart_fd = ::open(uart_name, O_RDWR | O_NOCTTY); if (_uart_fd < 0) { return _uart_fd; } /* Try to set baud rate */ struct termios uart_config; int termios_state; *is_usb = false; /* Back up the original uart configuration to restore it after exit */ if ((termios_state = tcgetattr(_uart_fd, uart_config_original)) < 0) { warnx("ERR GET CONF %s: %d\n", uart_name, termios_state); ::close(_uart_fd); return -1; } /* Fill the struct for the new configuration */ tcgetattr(_uart_fd, &uart_config); /* Clear ONLCR flag (which appends a CR for every LF) */ uart_config.c_oflag &= ~ONLCR; /* USB serial is indicated by /dev/ttyACM0*/ if (strcmp(uart_name, "/dev/ttyACM0") != OK && strcmp(uart_name, "/dev/ttyACM1") != OK) { /* Set baud rate */ if (cfsetispeed(&uart_config, speed) < 0 || cfsetospeed(&uart_config, speed) < 0) { warnx("ERR SET BAUD %s: %d\n", uart_name, termios_state); ::close(_uart_fd); return -1; } } if ((termios_state = tcsetattr(_uart_fd, TCSANOW, &uart_config)) < 0) { warnx("ERR SET CONF %s\n", uart_name); ::close(_uart_fd); return -1; } if (!_is_usb_uart) { /* * Setup hardware flow control. If the port has no RTS pin this call will fail, * which is not an issue, but requires a separate call so we can fail silently. */ (void)tcgetattr(_uart_fd, &uart_config); #ifdef CRTS_IFLOW uart_config.c_cflag |= CRTS_IFLOW; #else uart_config.c_cflag |= CRTSCTS; #endif (void)tcsetattr(_uart_fd, TCSANOW, &uart_config); /* setup output flow control */ if (enable_flow_control(true)) { warnx("hardware flow control not supported"); } } else { _flow_control_enabled = false; } return _uart_fd; }
/* * Open the serial port. * Return -1 on error. */ dyio_t *_dyio_serial_open(const char *devname, int baud_rate) { #if defined(__WIN32__) || defined(WIN32) DCB new_mode; COMMTIMEOUTS ctmo; #else struct termios new_mode; #endif dyio_serial_t *s; s = calloc(1, sizeof(dyio_serial_t)); if (! s) { fprintf(stderr, "dyio: Out of memory\n"); return 0; } #if defined(__WIN32__) || defined(WIN32) /* Open port */ s->fd = CreateFile(devname, GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_EXISTING, 0, 0); if (s->fd == INVALID_HANDLE_VALUE) { fprintf(stderr, "%s: Cannot open\n", devname); free(s); return 0; } /* Set serial attributes */ memset(&s->saved_mode, 0, sizeof(s->saved_mode)); if (! GetCommState(s->fd, &s->saved_mode)) { fprintf(stderr, "%s: Cannot get state\n", devname); CloseHandle(s->fd); free(s); return 0; } new_mode = s->saved_mode; new_mode.BaudRate = baud_encode(baud_rate); new_mode.ByteSize = 8; new_mode.StopBits = ONESTOPBIT; new_mode.Parity = 0; new_mode.fParity = FALSE; new_mode.fOutX = FALSE; new_mode.fInX = FALSE; new_mode.fOutxCtsFlow = FALSE; new_mode.fOutxDsrFlow = FALSE; new_mode.fRtsControl = RTS_CONTROL_ENABLE; new_mode.fNull = FALSE; new_mode.fAbortOnError = FALSE; new_mode.fBinary = TRUE; if (! SetCommState(s->fd, &new_mode)) { fprintf(stderr, "%s: Cannot set state\n", devname); CloseHandle(s->fd); free(s); return 0; } memset(&ctmo, 0, sizeof(ctmo)); ctmo.ReadIntervalTimeout = 0; ctmo.ReadTotalTimeoutMultiplier = 0; ctmo.ReadTotalTimeoutConstant = 5000; if (! SetCommTimeouts(s->fd, &ctmo)) { fprintf(stderr, "%s: Cannot set timeouts\n", devname); CloseHandle(s->fd); free(s); return 0; } #else /* Encode baud rate. */ int baud_code = baud_encode(baud_rate); if (baud_code < 0) { fprintf(stderr, "%s: Bad baud rate %d\n", devname, baud_rate); free(s); return 0; } /* Open port */ s->fd = open(devname, O_RDWR | O_NOCTTY | O_NONBLOCK); if (s->fd < 0) { perror(devname); free(s); return 0; } /* Set serial attributes */ memset(&s->saved_mode, 0, sizeof(s->saved_mode)); tcgetattr(s->fd, &s->saved_mode); /* 8n1, ignore parity */ memset(&new_mode, 0, sizeof(new_mode)); new_mode.c_cflag = CS8 | CLOCAL | CREAD; new_mode.c_iflag = IGNBRK; new_mode.c_oflag = 0; new_mode.c_lflag = 0; new_mode.c_cc[VTIME] = 0; new_mode.c_cc[VMIN] = 1; cfsetispeed(&new_mode, baud_code); cfsetospeed(&new_mode, baud_code); tcflush(s->fd, TCIFLUSH); tcsetattr(s->fd, TCSANOW, &new_mode); /* Clear O_NONBLOCK flag. */ int flags = fcntl(s->fd, F_GETFL, 0); if (flags >= 0) fcntl(s->fd, F_SETFL, flags & ~O_NONBLOCK); #endif return &s->generic; }
/*! \fn void Posix_QextSerialPort::setBaudRate(BaudRateType baudRate) Sets the baud rate of the serial port. Note that not all rates are applicable on all platforms. The following table shows translations of the various baud rate constants on Windows(including NT/2000) and POSIX platforms. Speeds marked with an * are speeds that are usable on both Windows and POSIX. \note BAUD76800 may not be supported on all POSIX systems. SGI/IRIX systems do not support BAUD1800. \verbatim RATE Windows Speed POSIX Speed ----------- ------------- ----------- BAUD50 110 50 BAUD75 110 75 *BAUD110 110 110 BAUD134 110 134.5 BAUD150 110 150 BAUD200 110 200 *BAUD300 300 300 *BAUD600 600 600 *BAUD1200 1200 1200 BAUD1800 1200 1800 *BAUD2400 2400 2400 *BAUD4800 4800 4800 *BAUD9600 9600 9600 BAUD14400 14400 9600 *BAUD19200 19200 19200 *BAUD38400 38400 38400 BAUD56000 56000 38400 *BAUD57600 57600 57600 BAUD76800 57600 76800 *BAUD115200 115200 115200 BAUD128000 128000 115200 BAUD256000 256000 115200 \endverbatim */ void Posix_QextSerialPort::setBaudRate(BaudRateType baudRate) { LOCK_MUTEX(); if (Settings.BaudRate!=baudRate) { switch (baudRate) { case BAUD14400: Settings.BaudRate=BAUD9600; break; case BAUD56000: Settings.BaudRate=BAUD38400; break; case BAUD76800: #ifndef B76800 Settings.BaudRate=BAUD57600; #else Settings.BaudRate=baudRate; #endif break; case BAUD128000: case BAUD256000: Settings.BaudRate=BAUD115200; break; default: Settings.BaudRate=baudRate; break; } } if (isOpen()) { switch (baudRate) { /*50 baud*/ case BAUD50: TTY_PORTABILITY_WARNING("Posix_QextSerialPort Portability Warning: Windows does not support 50 baud operation."); #ifdef CBAUD Posix_CommConfig.c_cflag&=(~CBAUD); Posix_CommConfig.c_cflag|=B50; #else cfsetispeed(&Posix_CommConfig, B50); cfsetospeed(&Posix_CommConfig, B50); #endif break; /*75 baud*/ case BAUD75: TTY_PORTABILITY_WARNING("Posix_QextSerialPort Portability Warning: Windows does not support 75 baud operation."); #ifdef CBAUD Posix_CommConfig.c_cflag&=(~CBAUD); Posix_CommConfig.c_cflag|=B75; #else cfsetispeed(&Posix_CommConfig, B75); cfsetospeed(&Posix_CommConfig, B75); #endif break; /*110 baud*/ case BAUD110: #ifdef CBAUD Posix_CommConfig.c_cflag&=(~CBAUD); Posix_CommConfig.c_cflag|=B110; #else cfsetispeed(&Posix_CommConfig, B110); cfsetospeed(&Posix_CommConfig, B110); #endif break; /*134.5 baud*/ case BAUD134: TTY_PORTABILITY_WARNING("Posix_QextSerialPort Portability Warning: Windows does not support 134.5 baud operation."); #ifdef CBAUD Posix_CommConfig.c_cflag&=(~CBAUD); Posix_CommConfig.c_cflag|=B134; #else cfsetispeed(&Posix_CommConfig, B134); cfsetospeed(&Posix_CommConfig, B134); #endif break; /*150 baud*/ case BAUD150: TTY_PORTABILITY_WARNING("Posix_QextSerialPort Portability Warning: Windows does not support 150 baud operation."); #ifdef CBAUD Posix_CommConfig.c_cflag&=(~CBAUD); Posix_CommConfig.c_cflag|=B150; #else cfsetispeed(&Posix_CommConfig, B150); cfsetospeed(&Posix_CommConfig, B150); #endif break; /*200 baud*/ case BAUD200: TTY_PORTABILITY_WARNING("Posix_QextSerialPort Portability Warning: Windows does not support 200 baud operation."); #ifdef CBAUD Posix_CommConfig.c_cflag&=(~CBAUD); Posix_CommConfig.c_cflag|=B200; #else cfsetispeed(&Posix_CommConfig, B200); cfsetospeed(&Posix_CommConfig, B200); #endif break; /*300 baud*/ case BAUD300: #ifdef CBAUD Posix_CommConfig.c_cflag&=(~CBAUD); Posix_CommConfig.c_cflag|=B300; #else cfsetispeed(&Posix_CommConfig, B300); cfsetospeed(&Posix_CommConfig, B300); #endif break; /*600 baud*/ case BAUD600: #ifdef CBAUD Posix_CommConfig.c_cflag&=(~CBAUD); Posix_CommConfig.c_cflag|=B600; #else cfsetispeed(&Posix_CommConfig, B600); cfsetospeed(&Posix_CommConfig, B600); #endif break; /*1200 baud*/ case BAUD1200: #ifdef CBAUD Posix_CommConfig.c_cflag&=(~CBAUD); Posix_CommConfig.c_cflag|=B1200; #else cfsetispeed(&Posix_CommConfig, B1200); cfsetospeed(&Posix_CommConfig, B1200); #endif break; /*1800 baud*/ case BAUD1800: TTY_PORTABILITY_WARNING("Posix_QextSerialPort Portability Warning: Windows and IRIX do not support 1800 baud operation."); #ifdef CBAUD Posix_CommConfig.c_cflag&=(~CBAUD); Posix_CommConfig.c_cflag|=B1800; #else cfsetispeed(&Posix_CommConfig, B1800); cfsetospeed(&Posix_CommConfig, B1800); #endif break; /*2400 baud*/ case BAUD2400: #ifdef CBAUD Posix_CommConfig.c_cflag&=(~CBAUD); Posix_CommConfig.c_cflag|=B2400; #else cfsetispeed(&Posix_CommConfig, B2400); cfsetospeed(&Posix_CommConfig, B2400); #endif break; /*4800 baud*/ case BAUD4800: #ifdef CBAUD Posix_CommConfig.c_cflag&=(~CBAUD); Posix_CommConfig.c_cflag|=B4800; #else cfsetispeed(&Posix_CommConfig, B4800); cfsetospeed(&Posix_CommConfig, B4800); #endif break; /*9600 baud*/ case BAUD9600: #ifdef CBAUD Posix_CommConfig.c_cflag&=(~CBAUD); Posix_CommConfig.c_cflag|=B9600; #else cfsetispeed(&Posix_CommConfig, B9600); cfsetospeed(&Posix_CommConfig, B9600); #endif break; /*14400 baud*/ case BAUD14400: TTY_WARNING("Posix_QextSerialPort: POSIX does not support 14400 baud operation. Switching to 9600 baud."); #ifdef CBAUD Posix_CommConfig.c_cflag&=(~CBAUD); Posix_CommConfig.c_cflag|=B9600; #else cfsetispeed(&Posix_CommConfig, B9600); cfsetospeed(&Posix_CommConfig, B9600); #endif break; /*19200 baud*/ case BAUD19200: #ifdef CBAUD Posix_CommConfig.c_cflag&=(~CBAUD); Posix_CommConfig.c_cflag|=B19200; #else cfsetispeed(&Posix_CommConfig, B19200); cfsetospeed(&Posix_CommConfig, B19200); #endif break; /*38400 baud*/ case BAUD38400: #ifdef CBAUD Posix_CommConfig.c_cflag&=(~CBAUD); Posix_CommConfig.c_cflag|=B38400; #else cfsetispeed(&Posix_CommConfig, B38400); cfsetospeed(&Posix_CommConfig, B38400); #endif break; /*56000 baud*/ case BAUD56000: TTY_WARNING("Posix_QextSerialPort: POSIX does not support 56000 baud operation. Switching to 38400 baud."); #ifdef CBAUD Posix_CommConfig.c_cflag&=(~CBAUD); Posix_CommConfig.c_cflag|=B38400; #else cfsetispeed(&Posix_CommConfig, B38400); cfsetospeed(&Posix_CommConfig, B38400); #endif break; /*57600 baud*/ case BAUD57600: #ifdef CBAUD Posix_CommConfig.c_cflag&=(~CBAUD); Posix_CommConfig.c_cflag|=B57600; #else cfsetispeed(&Posix_CommConfig, B57600); cfsetospeed(&Posix_CommConfig, B57600); #endif break; /*76800 baud*/ case BAUD76800: TTY_PORTABILITY_WARNING("Posix_QextSerialPort Portability Warning: Windows and some POSIX systems do not support 76800 baud operation."); #ifdef CBAUD Posix_CommConfig.c_cflag&=(~CBAUD); #ifdef B76800 Posix_CommConfig.c_cflag|=B76800; #else TTY_WARNING("Posix_QextSerialPort: Posix_QextSerialPort was compiled without 76800 baud support. Switching to 57600 baud."); Posix_CommConfig.c_cflag|=B57600; #endif //B76800 #else //CBAUD #ifdef B76800 cfsetispeed(&Posix_CommConfig, B76800); cfsetospeed(&Posix_CommConfig, B76800); #else TTY_WARNING("Posix_QextSerialPort: Posix_QextSerialPort was compiled without 76800 baud support. Switching to 57600 baud."); cfsetispeed(&Posix_CommConfig, B57600); cfsetospeed(&Posix_CommConfig, B57600); #endif //B76800 #endif //CBAUD break; /*115200 baud*/ case BAUD115200: #ifdef CBAUD Posix_CommConfig.c_cflag&=(~CBAUD); Posix_CommConfig.c_cflag|=B115200; #else cfsetispeed(&Posix_CommConfig, B115200); cfsetospeed(&Posix_CommConfig, B115200); #endif break; /*128000 baud*/ case BAUD128000: TTY_WARNING("Posix_QextSerialPort: POSIX does not support 128000 baud operation. Switching to 115200 baud."); #ifdef CBAUD Posix_CommConfig.c_cflag&=(~CBAUD); Posix_CommConfig.c_cflag|=B115200; #else cfsetispeed(&Posix_CommConfig, B115200); cfsetospeed(&Posix_CommConfig, B115200); #endif break; /*256000 baud*/ case BAUD256000: TTY_WARNING("Posix_QextSerialPort: POSIX does not support 256000 baud operation. Switching to 115200 baud."); #ifdef CBAUD Posix_CommConfig.c_cflag&=(~CBAUD); Posix_CommConfig.c_cflag|=B115200; #else cfsetispeed(&Posix_CommConfig, B115200); cfsetospeed(&Posix_CommConfig, B115200); #endif break; } tcsetattr(Posix_File->handle(), TCSAFLUSH, &Posix_CommConfig); } UNLOCK_MUTEX(); }
void xf86OpenConsole(void) { int i, fd = -1; struct vt_mode VT; struct vt_stat vts; MessageType from = X_PROBED; char *tty0[] = { "/dev/tty0", "/dev/vc/0", NULL }; char *vcs[] = { "/dev/vc/%d", "/dev/tty%d", NULL }; if (serverGeneration == 1) { /* when KeepTty check if we're run with euid==0 */ if (KeepTty && geteuid() != 0) FatalError("xf86OpenConsole:" " Server must be suid root for option \"KeepTTY\"\n"); /* * setup the virtual terminal manager */ if (VTnum != -1) { xf86Info.vtno = VTnum; from = X_CMDLINE; } else { i=0; while (tty0[i] != NULL) { if ((fd = open(tty0[i],O_WRONLY,0)) >= 0) break; i++; } if (fd < 0) FatalError( "xf86OpenConsole: Cannot open /dev/tty0 (%s)\n", strerror(errno)); if (ShareVTs) { if (ioctl(fd, VT_GETSTATE, &vts) == 0) xf86Info.vtno = vts.v_active; else FatalError("xf86OpenConsole: Cannot find the current" " VT (%s)\n", strerror(errno)); } else { if ((ioctl(fd, VT_OPENQRY, &xf86Info.vtno) < 0) || (xf86Info.vtno == -1)) FatalError("xf86OpenConsole: Cannot find a free VT: %s\n", strerror(errno)); } close(fd); } xf86Msg(from, "using VT number %d\n\n", xf86Info.vtno); if (!KeepTty) { pid_t ppid = getppid(); pid_t ppgid; ppgid = getpgid(ppid); /* * change to parent process group that pgid != pid so * that setsid() doesn't fail and we become process * group leader */ if (setpgid(0,ppgid) < 0) xf86Msg(X_WARNING, "xf86OpenConsole: setpgid failed: %s\n", strerror(errno)); /* become process group leader */ if ((setsid() < 0)) xf86Msg(X_WARNING, "xf86OpenConsole: setsid failed: %s\n", strerror(errno)); } i=0; while (vcs[i] != NULL) { sprintf(vtname, vcs[i], xf86Info.vtno); /* /dev/tty1-64 */ if ((xf86Info.consoleFd = open(vtname, O_RDWR|O_NDELAY, 0)) >= 0) break; i++; } if (xf86Info.consoleFd < 0) FatalError("xf86OpenConsole: Cannot open virtual console" " %d (%s)\n", xf86Info.vtno, strerror(errno)); if (!ShareVTs) { /* * Grab the vt ownership before we overwrite it. * Hard coded /dev/tty0 into this function as well for below. */ if (!saveVtPerms()) xf86Msg(X_WARNING, "xf86OpenConsole: Could not save ownership of VT\n"); if (geteuid() == 0) { /* change ownership of the vt */ if (chown(vtname, getuid(), getgid()) < 0) xf86Msg(X_WARNING,"xf86OpenConsole: chown %s failed: %s\n", vtname, strerror(errno)); /* * the current VT device we're running on is not * "console", we want to grab all consoles too * * Why is this needed?? */ if (chown("/dev/tty0", getuid(), getgid()) < 0) xf86Msg(X_WARNING,"xf86OpenConsole: chown /dev/tty0 failed: %s\n", strerror(errno)); } } /* * Linux doesn't switch to an active vt after the last close of a vt, * so we do this ourselves by remembering which is active now. */ if (ioctl(xf86Info.consoleFd, VT_GETSTATE, &vts) < 0) xf86Msg(X_WARNING,"xf86OpenConsole: VT_GETSTATE failed: %s\n", strerror(errno)); else activeVT = vts.v_active; #if 0 if (!KeepTty) { /* * Detach from the controlling tty to avoid char loss */ if ((i = open("/dev/tty",O_RDWR)) >= 0) { ioctl(i, TIOCNOTTY, 0); close(i); } } #endif if (!ShareVTs) { struct termios nTty; /* * now get the VT. This _must_ succeed, or else fail completely. */ if (ioctl(xf86Info.consoleFd, VT_ACTIVATE, xf86Info.vtno) < 0) FatalError("xf86OpenConsole: VT_ACTIVATE failed: %s\n", strerror(errno)); if (ioctl(xf86Info.consoleFd, VT_WAITACTIVE, xf86Info.vtno) < 0) FatalError("xf86OpenConsole: VT_WAITACTIVE failed: %s\n", strerror(errno)); if (ioctl(xf86Info.consoleFd, VT_GETMODE, &VT) < 0) FatalError("xf86OpenConsole: VT_GETMODE failed %s\n", strerror(errno)); signal(SIGUSR1, xf86VTRequest); VT.mode = VT_PROCESS; VT.relsig = SIGUSR1; VT.acqsig = SIGUSR1; if (ioctl(xf86Info.consoleFd, VT_SETMODE, &VT) < 0) FatalError("xf86OpenConsole: VT_SETMODE VT_PROCESS failed: %s\n", strerror(errno)); if (ioctl(xf86Info.consoleFd, KDSETMODE, KD_GRAPHICS) < 0) FatalError("xf86OpenConsole: KDSETMODE KD_GRAPHICS failed %s\n", strerror(errno)); tcgetattr(xf86Info.consoleFd, &tty_attr); ioctl(xf86Info.consoleFd, KDGKBMODE, &tty_mode); if (ioctl(xf86Info.consoleFd, KDSKBMODE, K_RAW) < 0) FatalError("xf86OpenConsole: KDSKBMODE K_RAW failed %s\n", strerror(errno)); nTty = tty_attr; nTty.c_iflag = (IGNPAR | IGNBRK) & (~PARMRK) & (~ISTRIP); nTty.c_oflag = 0; nTty.c_cflag = CREAD | CS8; nTty.c_lflag = 0; nTty.c_cc[VTIME]=0; nTty.c_cc[VMIN]=1; cfsetispeed(&nTty, 9600); cfsetospeed(&nTty, 9600); tcsetattr(xf86Info.consoleFd, TCSANOW, &nTty); /* need to keep the buffer clean, else the kernel gets angry */ if (xf86Info.allowEmptyInput) console_handler = xf86AddGeneralHandler(xf86Info.consoleFd, drain_console, NULL); /* we really should have a InitOSInputDevices() function instead * of Init?$#*&Device(). So I just place it here */ } } else { /* serverGeneration != 1 */ if (!ShareVTs && VTSwitch) { /* * now get the VT */ if (ioctl(xf86Info.consoleFd, VT_ACTIVATE, xf86Info.vtno) < 0) xf86Msg(X_WARNING, "xf86OpenConsole: VT_ACTIVATE failed %s\n", strerror(errno)); if (ioctl(xf86Info.consoleFd, VT_WAITACTIVE, xf86Info.vtno) < 0) xf86Msg(X_WARNING, "xf86OpenConsole: VT_WAITACTIVE failed %s\n", strerror(errno)); } } }
int main( int argc, char **argv ) { int sig; int rc; int opt; char devName[ 40 ]; const char *baudStr = NULL; const char *portStr = "ttyS2"; speed_t baudRate; sigset_t termSig; pthread_t readSerialThreadId; pthread_t readStdinThreadId; struct termios stdin_tio; struct termios stdin_tio_org; struct termios attr; // Parse the command line options while (( opt = getopt_long( argc, argv, "b:dhp:v", gLongOption, NULL )) > 0 ) { switch ( opt ) { case 'b': { baudStr = optarg; break; } case 'd': { gDebug = 1; break; } case 'p': { portStr = optarg; break; } case 'v': { gVerbose = 1; break; } case '?': case 'h': { Usage(); return 1; } } } devName[ 0 ] = '\0'; if ( portStr[ 0 ] != '/' ) { StrMaxCpy( devName, "/dev/", sizeof( devName )); } StrMaxCat( devName, portStr, sizeof( devName )); baudRate = B0; if ( baudStr == NULL ) { baudRate = B9600; } else { int baudIdx; int testBaud = atoi( baudStr ); for ( baudIdx = 0; baudIdx < ARRAY_LEN( gBaudTable ); baudIdx++ ) { if ( gBaudTable[ baudIdx ].baudRate == testBaud ) { baudRate = gBaudTable[ baudIdx ].speed; break; } } if ( baudRate == B0 ) { fprintf( stderr, "Unrecognized baud rate: '%s'\n", baudStr ); exit( 1 ); } } if (( gPortFd = open( devName, O_RDWR | O_EXCL )) < 0 ) { fprintf( stderr, "Unable to open serial port '%s': %s\n", devName, strerror( errno )); exit( 2 ); } if ( tcgetattr( gPortFd, &attr ) < 0 ) { fprintf( stderr, "Call to tcgetattr failed: %s\n", strerror( errno )); exit( 3 ); } cfmakeraw( &attr ); // CLOCAL - Disable modem control lines // CREAD - Enable Receiver attr.c_cflag |= ( CLOCAL | CREAD ); cfsetispeed( &attr, baudRate ); cfsetospeed( &attr, baudRate ); if ( tcsetattr( gPortFd, TCSAFLUSH, &attr ) < 0 ) { fprintf( stderr, "Call to tcsetattr failed: %s\n", strerror( errno )); exit( 4 ); } // Put stdin & stdout in unbuffered mode. setbuf( stdin, NULL ); setbuf( stdout, NULL ); sigemptyset( &termSig ); sigaddset( &termSig, SIGINT ); sigaddset( &termSig, SIGTERM ); pthread_sigmask( SIG_BLOCK, &termSig, NULL ); // Put stdin in raw mode (i.e. turn off canonical mode). Canonical mode // causes the driver to wait for the RETURN character so that line editing // can take place. We also want to turn off ECHO. if ( tcgetattr( fileno( stdin ), &stdin_tio_org ) < 0 ) { fprintf( stderr, "Unable to retrieve terminal settings: %s\n", strerror( errno )); exit( 5 ); } stdin_tio = stdin_tio_org; stdin_tio.c_lflag &= ~( ICANON | ECHO ); stdin_tio.c_cc[VTIME] = 0; stdin_tio.c_cc[VMIN] = 1; if ( tcsetattr( fileno( stdin ), TCSANOW, &stdin_tio ) < 0 ) { fprintf( stderr, "Unable to update terminal settings: %s\n", strerror( errno )); exit( 6 ); } // Kick off the serial port reader thread. rc = pthread_create( &readSerialThreadId, NULL, ReadSerialThread, NULL ); if ( rc != 0 ) { fprintf( stderr, "Error creating ReadSerialThread: %s\n", strerror( rc )); exit( 7 ); } // Kick off the stdin reader thread rc = pthread_create( &readStdinThreadId, NULL, ReadStdinThread, NULL ); if ( rc != 0 ) { fprintf( stderr, "Error creating ReadStdinThread: %s\n", strerror( rc )); exit( 7 ); } // Wait for a termmination signal if (( rc = sigwait( &termSig, &sig )) != 0 ) { fprintf( stderr, "sigwait failed\n" ); } else { fprintf( stderr, "Exiting...\n" ); } pthread_cancel( readSerialThreadId ); pthread_cancel( readStdinThreadId ); // Restore stdin back to the way it was when we started if ( tcsetattr( fileno( stdin ), TCSANOW, &stdin_tio_org ) < 0 ) { fprintf( stderr, "Unable to update terminal settings: %s\n", strerror( errno )); exit( 6 ); } // Unblock the termination signals so the user can kill us if we hang up // waiting for the reader threads to exit. pthread_sigmask( SIG_UNBLOCK, &termSig, NULL ); pthread_join( readSerialThreadId, NULL ); pthread_join( readStdinThreadId, NULL ); close( gPortFd ); if ( gVerbose ) { fprintf( stderr, "Done\n" ); } exit( 0 ); return 0; // Get rid of warning about not returning anything }
//--------------------------------------------------------------------------- void OpenComms(void) { const char *device = CommPortString.c_str(); fd = open(device, O_RDWR | O_NOCTTY | O_NDELAY); if (fd == -1) { LoggingFile.mLogFile << "failed to open port:" << endl; ShowMessage(device); CloseComms(); return; } if (!isatty(fd)) { LoggingFile.mLogFile << "not a tty:" << endl; ShowMessage(device); CloseComms(); return; } if (tcgetattr(fd, &config) < 0) { LoggingFile.mLogFile << "failed to get port info" << endl; CloseComms(); return; } // // Input flags - Turn off input processing // convert break to null byte, no CR to NL translation, // no NL to CR translation, don't mark parity errors or breaks // no input parity check, don't strip high bit off, // no XON/XOFF software flow control // config.c_iflag &= ~(IGNBRK | BRKINT | ICRNL | INLCR | PARMRK | INPCK | ISTRIP | IXON); // // Output flags - Turn off output processing // no CR to NL translation, no NL to CR-NL translation, // no NL to CR translation, no column 0 CR suppression, // no Ctrl-D suppression, no fill characters, no case mapping, // no local output processing // // config.c_oflag &= ~(OCRNL | ONLCR | ONLRET | // ONOCR | ONOEOT| OFILL | OLCUC | OPOST); config.c_oflag = 0; // // No line processing: // echo off, echo newline off, canonical mode off, // extended input processing off, signal chars off // config.c_lflag &= ~(ECHO | ECHONL | ICANON | IEXTEN | ISIG); // // Turn off character processing // clear current char size mask, no parity checking, // no output processing, force 8 bit input // config.c_cflag &= ~(CSIZE | PARENB | CSTOPB); config.c_cflag |= CS8; // // One input byte is enough to return from read() // Inter-character timer off // config.c_cc[VMIN] = 1; config.c_cc[VTIME] = 0; // // Communication speed (simple version, using the predefined // constants) // if (cfsetispeed(&config, B19200) < 0 || cfsetospeed(&config, B19200) < 0) { LoggingFile.mLogFile << "failed to set port speed" << endl; CloseComms(); return; } // // Finally, apply the configuration // if (tcsetattr(fd, TCSAFLUSH, &config) < 0) { LoggingFile.mLogFile << "failed to configure port" << endl; CloseComms(); return; } LoggingFile.mLogFile << "Opened port " << device << endl; }
int set_baudrate_length_parity_stopbits(int fd, unsigned int new_baudrate, int length, char parity_c, int stopbits) { struct termios uart_cfg_opt; speed_t speed; struct serial_struct ss; char using_custom_speed = 0; if(-1==fd) return -1; /* Get current uart configure option */ if(-1 == tcgetattr(fd, &uart_cfg_opt)) return -1; tcflush(fd, TCIOFLUSH); /* Baud rate setting section */ speed = get_speed(new_baudrate); if(CBAUDEX != speed){ /*set standard buadrate setting*/ cfsetospeed(&uart_cfg_opt, speed); cfsetispeed(&uart_cfg_opt, speed); printf("Standard baud\r\n"); }else{ printf("Custom baud\r\n"); using_custom_speed = 1; } /* Apply baudrate settings */ if(-1==tcsetattr(fd, TCSANOW, &uart_cfg_opt)) return -1; /* Set time out */ uart_cfg_opt.c_cc[VTIME] = 1; uart_cfg_opt.c_cc[VMIN] = 0; /*if((ioctl(fd,TIOCGSERIAL,&ss)) < 0) return -1; if(using_custom_speed){ ss.flags |= ASYNC_SPD_CUST; ss.custom_divisor = 1<<31|new_baudrate; }else ss.flags &= ~ASYNC_SPD_CUST; if((ioctl(fd, TIOCSSERIAL, &ss)) < 0) return -1;//*/ /* Data length setting section */ uart_cfg_opt.c_cflag &= ~CSIZE; switch(length) { default: case 8: uart_cfg_opt.c_cflag |= CS8; break; case 5: uart_cfg_opt.c_cflag |= CS5; break; case 6: uart_cfg_opt.c_cflag |= CS6; break; case 7: uart_cfg_opt.c_cflag |= CS7; break; } /* Parity setting section */ uart_cfg_opt.c_cflag &= ~(PARENB|PARODD); switch(parity_c) { default: case 'N': case 'n': uart_cfg_opt.c_iflag &= ~INPCK; break; case 'O': case 'o': uart_cfg_opt.c_cflag |= (PARENB|PARODD); uart_cfg_opt.c_iflag |= INPCK; break; case 'E': case 'e': uart_cfg_opt.c_cflag |= PARENB; uart_cfg_opt.c_iflag |= INPCK; break; } /* Stop bits setting section */ if(2==stopbits) uart_cfg_opt.c_cflag |= CSTOPB; else uart_cfg_opt.c_cflag &= ~CSTOPB; /* Using raw data mode */ uart_cfg_opt.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG); uart_cfg_opt.c_iflag &= ~(INLCR | IGNCR | ICRNL | IXON | IXOFF); uart_cfg_opt.c_oflag &=~(INLCR|IGNCR|ICRNL); uart_cfg_opt.c_oflag &=~(ONLCR|OCRNL); /* Apply new settings */ if(-1==tcsetattr(fd, TCSANOW, &uart_cfg_opt)) return -1; tcflush(fd,TCIOFLUSH); /* All setting applied successful */ printf("setting apply done\r\n"); return 0; }
//---------------------------------------------------------------- bool ofSerial::setup(string portName, int baud){ bInited = false; //--------------------------------------------- #if defined( TARGET_OSX ) || defined( TARGET_LINUX ) //--------------------------------------------- ofLog(OF_NOTICE,"ofSerialInit: opening port %s @ %d bps", portName.c_str(), baud); fd = open(portName.c_str(), O_RDWR | O_NOCTTY | O_NONBLOCK); if(fd == -1){ ofLog(OF_ERROR,"ofSerial: unable to open port"); return false; } struct termios options; tcgetattr(fd,&oldoptions); options = oldoptions; switch(baud){ case 300: cfsetispeed(&options,B300); cfsetospeed(&options,B300); break; case 1200: cfsetispeed(&options,B1200); cfsetospeed(&options,B1200); break; case 2400: cfsetispeed(&options,B2400); cfsetospeed(&options,B2400); break; case 4800: cfsetispeed(&options,B4800); cfsetospeed(&options,B4800); break; case 9600: cfsetispeed(&options,B9600); cfsetospeed(&options,B9600); break; case 14400: cfsetispeed(&options,B14400); cfsetospeed(&options,B14400); break; case 19200: cfsetispeed(&options,B19200); cfsetospeed(&options,B19200); break; case 28800: cfsetispeed(&options,B28800); cfsetospeed(&options,B28800); break; case 38400: cfsetispeed(&options,B38400); cfsetospeed(&options,B38400); break; case 57600: cfsetispeed(&options,B57600); cfsetospeed(&options,B57600); break; case 115200: cfsetispeed(&options,B115200); cfsetospeed(&options,B115200); break; default: cfsetispeed(&options,B9600); cfsetospeed(&options,B9600); ofLog(OF_ERROR,"ofSerialInit: cannot set %i baud setting baud to 9600\n", baud); break; } options.c_cflag |= (CLOCAL | CREAD); options.c_cflag &= ~PARENB; options.c_cflag &= ~CSTOPB; options.c_cflag &= ~CSIZE; options.c_cflag |= CS8; tcsetattr(fd,TCSANOW,&options); bInited = true; ofLog(OF_NOTICE,"sucess in opening serial connection"); return true; //--------------------------------------------- #endif //--------------------------------------------- //--------------------------------------------- #ifdef TARGET_WIN32 //--------------------------------------------- // open the serial port: // "COM4", etc... hComm=CreateFileA(portName.c_str(),GENERIC_READ|GENERIC_WRITE,0,0, OPEN_EXISTING,0,0); if(hComm==INVALID_HANDLE_VALUE){ ofLog(OF_ERROR,"ofSerial: unable to open port"); return false; } // now try the settings: COMMCONFIG cfg; DWORD cfgSize; char buf[80]; cfgSize=sizeof(cfg); GetCommConfig(hComm,&cfg,&cfgSize); int bps = baud; sprintf(buf,"baud=%d parity=N data=8 stop=1",bps); #if (_MSC_VER) // microsoft visual studio // msvc doesn't like BuildCommDCB, //so we need to use this version: BuildCommDCBA if(!BuildCommDCBA(buf,&cfg.dcb)){ ofLog(OF_ERROR,"ofSerial: unable to build comm dcb; (%s)",buf); } #else if(!BuildCommDCB(buf,&cfg.dcb)){ ofLog(OF_ERROR,"ofSerial: Can't build comm dcb; %s",buf); } #endif // Set baudrate and bits etc. // Note that BuildCommDCB() clears XON/XOFF and hardware control by default if(!SetCommState(hComm,&cfg.dcb)){ ofLog(OF_ERROR,"ofSerial: Can't set comm state"); } //ofLog(OF_NOTICE,buf,"bps=%d, xio=%d/%d",cfg.dcb.BaudRate,cfg.dcb.fOutX,cfg.dcb.fInX); // Set communication timeouts (NT) COMMTIMEOUTS tOut; GetCommTimeouts(hComm,&oldTimeout); tOut = oldTimeout; // Make timeout so that: // - return immediately with buffered characters tOut.ReadIntervalTimeout=MAXDWORD; tOut.ReadTotalTimeoutMultiplier=0; tOut.ReadTotalTimeoutConstant=0; SetCommTimeouts(hComm,&tOut); bInited = true; return true; //--------------------------------------------- #endif //--------------------------------------------- }