int SerialPortMacOS::convertBaudRateFlag(int baudrate) { int baudRateFlag = 0; // Set termios baudrate flag if (baudrate > 0) { // Try an exact match baudRateFlag = rate_to_constant(baudrate); if (baudRateFlag != 0) { TRACE_1(SERIAL, "convertBaudRateFlag(%i) has been set to %i (exact match)\n", baudrate, baudrate); } else { int speeds[20] = {2400, 4800, 9600, 19200, 38400, 57600, 115200, 230400, 460800, 500000, 576000, 921600, 1000000, 1152000, 1500000, 2000000, 2500000, 3000000, 3500000, 4000000}; // Try a "close enough" match (we allow ±1.5% mismatch) for (int i = 0; i < 20; i++) { if ((baudrate > (static_cast<double>(speeds[i]) * 98.5 / 100.0)) && (baudrate < (static_cast<double>(speeds[i]) * 101.5 / 100.0))) { baudRateFlag = rate_to_constant(speeds[i]); TRACE_WARNING(SERIAL, "convertBaudRateFlag(%i) has been set to B%i (close enough match, ±1.5%)\n", baudrate, speeds[i]); break; } } // Try a custom speed if (baudRateFlag == 0) { ttyCustomSpeed = true; baudRateFlag = B38400; TRACE_WARNING(SERIAL, "convertBaudRateFlag(%i) has been set to B38400 (custom speed will be used)\n", baudrate); } } } else { TRACE_ERROR(SERIAL, "Invalid baudrate, using default value of: B1000000\n"); } // Fallback if (baudRateFlag == 0) { baudRateFlag = B1000000; TRACE_ERROR(SERIAL, "Unable to set baud speed at %i: too slow!\n", baudrate); TRACE_ERROR(SERIAL, "Invalid baudrate, using default value of: B1000000\n"); } return baudRateFlag; }
/* Open serial port in raw mode, with custom baudrate if necessary */ int serial_open(const char *device, int rate, int stopbits) { struct termios options; int fd; int speed = 0; if ((fd = open(device, O_RDWR | O_NOCTTY)) == -1) return -1; speed = rate_to_constant(rate); if (speed == 0) { return -1; /* Custom divisor */ /* struct serial_struct serinfo; * * * serinfo.reserved_char[0] = 0; if (ioctl(fd, TIOCGSERIAL, &serinfo) < 0) return -1; serinfo.flags &= ~ASYNC_SPD_MASK; serinfo.flags |= ASYNC_SPD_CUST; serinfo.custom_divisor = (serinfo.baud_base + (rate / 2)) / rate; if (serinfo.custom_divisor < 1) serinfo.custom_divisor = 1; if (ioctl(fd, TIOCSSERIAL, &serinfo) < 0) return -1; if (ioctl(fd, TIOCGSERIAL, &serinfo) < 0) return -1; if (serinfo.custom_divisor * rate != serinfo.baud_base) { warnx("actual baudrate is %d / %d = %f", serinfo.baud_base, serinfo.custom_divisor, (float)serinfo.baud_base / serinfo.custom_divisor); }*/ } fcntl(fd, F_SETFL, 0); tcgetattr(fd, &options); cfsetispeed(&options, speed ?: B38400); cfsetospeed(&options, speed ?: B38400); cfmakeraw(&options); options.c_cflag |= (CLOCAL | CREAD); // No hardware flow control, no parity, clear size, no hangup on close options.c_cflag &= ~(PARENB | CRTSCTS | CSIZE | HUPCL); options.c_cflag |= CS8; //8 bits if (stopbits >= 2) { options.c_cflag |= CSTOPB; } else { options.c_cflag &= ~CSTOPB; } if (tcsetattr(fd, TCSANOW, &options) != 0) return -1; return fd; }
static int serialOpen(const char *device, int rate) { struct termios options; struct serial_struct serinfo; int fd; int speed = 0; /* Open and configure serial port */ if ((fd = open(device,O_RDWR|O_NOCTTY)) == -1) return -1; speed = rate_to_constant(rate); if (speed == 0) { /* Custom divisor */ serinfo.reserved_char[0] = 0; if (ioctl(fd, TIOCGSERIAL, &serinfo) < 0) { perror("TIOCGSERIAL"); return -1; } serinfo.flags &= ~ASYNC_SPD_MASK; serinfo.flags |= ASYNC_SPD_CUST; serinfo.custom_divisor = (serinfo.baud_base + (rate / 2)) / rate; if (serinfo.custom_divisor < 1) serinfo.custom_divisor = 1; if (ioctl(fd, TIOCSSERIAL, &serinfo) < 0) { perror("TIOCSSERIAL"); return -1; } if (ioctl(fd, TIOCGSERIAL, &serinfo) < 0) { perror("TIOCGSERIAL"); return -1; } if (1 || serinfo.custom_divisor * rate != serinfo.baud_base) { warnx("actual baudrate is %d / %d = %f", serinfo.baud_base, serinfo.custom_divisor, (float)serinfo.baud_base / serinfo.custom_divisor); } } fcntl(fd, F_SETFL, 0); tcgetattr(fd, &options); cfsetispeed(&options, speed ? speed : B38400); cfsetospeed(&options, speed ? speed : B38400); cfmakeraw(&options); options.c_cflag |= (CLOCAL | CREAD); options.c_cflag &= ~CRTSCTS; if (tcsetattr(fd, TCSANOW, &options) != 0) return -1; return fd; }
/* Open serial port in raw mode, with custom baudrate if necessary */ int mmCommInit(const char *device, int rate) { struct termios options; struct serial_struct serinfo; int fd; int speed = 0; /* Open and configure serial port */ if ((fd = open(device,O_RDWR|O_NOCTTY/*|O_NONBLOCK*/)) == -1) return -1; speed = rate_to_constant(rate); if (speed == 0) { /* Custom divisor */ serinfo.reserved_char[0] = 0; if (ioctl(fd, TIOCGSERIAL, &serinfo) < 0) return -1; serinfo.flags &= ~ASYNC_SPD_MASK; serinfo.flags |= ASYNC_SPD_CUST; serinfo.custom_divisor = (serinfo.baud_base + (rate / 2)) / rate; if (serinfo.custom_divisor < 1) serinfo.custom_divisor = 1; if (ioctl(fd, TIOCSSERIAL, &serinfo) < 0) return -1; if (ioctl(fd, TIOCGSERIAL, &serinfo) < 0) return -1; if (serinfo.custom_divisor * rate != serinfo.baud_base) { warnx("actual baudrate is %d / %d = %f", serinfo.baud_base, serinfo.custom_divisor, (float)serinfo.baud_base / serinfo.custom_divisor); } } //fcntl(fd, F_SETFL, O_NONBLOCK); tcgetattr(fd, &options); cfsetispeed(&options, speed ?: B38400); cfsetospeed(&options, speed ?: B38400); cfmakeraw(&options); options.c_lflag &= ~(ICANON|ECHO); options.c_cflag |= (CLOCAL | CREAD); options.c_cflag &= ~CRTSCTS; options.c_cc[VMIN] = 0; //options.c_cc[VTIME] = 200; if (tcsetattr(fd, TCSANOW, &options) != 0) return -1; tcflush(fd, TCIFLUSH); return fd; }