int open_seriport(const char *ttypath,int uart_speed) { int fd = open(ttypath,O_RDWR|O_NOCTTY|O_NONBLOCK); struct termios tios; memset(&tios,0,sizeof(struct termios)); /* 将串口设置为原始模式 */ cfmakeraw(&tios); /* baud rate */ cfsetospeed(&tios,look_up_uart_speed(uart_speed)); cfsetispeed(&tios,look_up_uart_speed(uart_speed)); /* 流控制选项 */ tios.c_iflag &= ~IXOFF; tios.c_cflag &= ~CRTSCTS; tios.c_cflag |= CS8; //控制模式 parity check tios.c_cflag &= ~PARENB; //no parity check tios.c_cflag &= ~CSTOPB; //1 stop bits /* 设置串口缓冲队列 */ tios.c_cc[VTIME] = 0; tios.c_cc[VMIN] = 0; /* 使串口设置生效 */ if(tcsetattr(fd,TCSADRAIN,&tios) < 0){ return fd; } return fd; }
int main(int argc, char *argv[]) { char *tty = NULL; char const *devprefix = "/dev/"; char *name = NULL; char buf[IFNAMSIZ+1]; struct termios tios; speed_t old_ispeed; speed_t old_ospeed; int opt; int send_open = 0; int send_close = 0; int send_read_status_flags = 0; char *speed = NULL; char *uart_speed_str = NULL; long int uart_speed = 0; int flow_type = FLOW_NONE; char *btr = NULL; int run_as_daemon = 1; char *pch; int ldisc = N_SLCAN; int fd; ttypath[0] = '\0'; while ((opt = getopt(argc, argv, "ocfs:S:t:b:?hF")) != -1) { switch (opt) { case 'o': send_open = 1; break; case 'c': send_close = 1; break; case 'f': send_read_status_flags = 1; break; case 's': speed = optarg; if (strlen(speed) > 1) print_usage(argv[0]); break; case 'S': uart_speed_str = optarg; errno = 0; uart_speed = strtol(uart_speed_str, NULL, 10); if (errno) print_usage(argv[0]); if (look_up_uart_speed(uart_speed) == -1) { fprintf(stderr, "Unsupported UART speed (%lu)\n", uart_speed); exit(EXIT_FAILURE); } break; case 't': if (!strcmp(optarg, "hw")) { flow_type = FLOW_HW; } else if (!strcmp(optarg, "sw")) { flow_type = FLOW_SW; } else { fprintf(stderr, "Unsupported flow type (%s)\n", optarg); exit(EXIT_FAILURE); } break; case 'b': btr = optarg; if (strlen(btr) > 6) print_usage(argv[0]); break; case 'F': run_as_daemon = 0; break; case 'h': case '?': default: print_usage(argv[0]); break; } } /* Initialize the logging interface */ openlog(DAEMON_NAME, LOG_PID, LOG_LOCAL5); /* Parse serial device name and optional can interface name */ tty = argv[optind]; if (NULL == tty) print_usage(argv[0]); name = argv[optind + 1]; /* Prepare the tty device name string */ pch = strstr(tty, devprefix); if (pch != tty) snprintf(ttypath, TTYPATH_LENGTH, "%s%s", devprefix, tty); else snprintf(ttypath, TTYPATH_LENGTH, "%s", tty); syslog(LOG_INFO, "starting on TTY device %s", ttypath); /* Daemonize */ if (run_as_daemon) { if (daemon(0, 0)) { syslog(LOG_ERR, "failed to daemonize"); exit(EXIT_FAILURE); } } else { /* Trap signals that we expect to receive */ signal(SIGINT, child_handler); signal(SIGTERM, child_handler); } /* */ slcand_running = 1; /* Now we are a daemon -- do the work for which we were paid */ fd = open(ttypath, O_RDWR | O_NONBLOCK | O_NOCTTY); if (fd < 0) { syslog(LOG_NOTICE, "failed to open TTY device %s\n", ttypath); perror(ttypath); exit(EXIT_FAILURE); } /* Configure baud rate */ memset(&tios, 0, sizeof(struct termios)); if (tcgetattr(fd, &tios) < 0) { syslog(LOG_NOTICE, "failed to get attributes for TTY device %s: %s\n", ttypath, strerror(errno)); exit(EXIT_FAILURE); } /* Get old values for later restore */ old_ispeed = cfgetispeed(&tios); old_ospeed = cfgetospeed(&tios); /* Reset UART settings */ cfmakeraw(&tios); tios.c_iflag &= ~IXOFF; tios.c_cflag &= ~CRTSCTS; /* Baud Rate */ cfsetispeed(&tios, look_up_uart_speed(uart_speed)); cfsetospeed(&tios, look_up_uart_speed(uart_speed)); /* Flow control */ if (flow_type == FLOW_HW) tios.c_cflag |= CRTSCTS; else if (flow_type == FLOW_SW) tios.c_iflag |= (IXON | IXOFF); /* apply changes */ if (tcsetattr(fd, TCSADRAIN, &tios) < 0) syslog(LOG_NOTICE, "Cannot set attributes for device \"%s\": %s!\n", ttypath, strerror(errno)); if (speed) { sprintf(buf, "C\rS%s\r", speed); write(fd, buf, strlen(buf)); } if (btr) { sprintf(buf, "C\rs%s\r", btr); write(fd, buf, strlen(buf)); } if (send_read_status_flags) { sprintf(buf, "F\r"); write(fd, buf, strlen(buf)); } if (send_open) { sprintf(buf, "O\r"); write(fd, buf, strlen(buf)); } /* set slcan like discipline on given tty */ if (ioctl(fd, TIOCSETD, &ldisc) < 0) { perror("ioctl TIOCSETD"); exit(EXIT_FAILURE); } /* retrieve the name of the created CAN netdevice */ if (ioctl(fd, SIOCGIFNAME, buf) < 0) { perror("ioctl SIOCGIFNAME"); exit(EXIT_FAILURE); } syslog(LOG_NOTICE, "attached TTY %s to netdevice %s\n", ttypath, buf); /* try to rename the created netdevice */ if (name) { struct ifreq ifr; int s = socket(PF_INET, SOCK_DGRAM, 0); if (s < 0) perror("socket for interface rename"); else { strncpy(ifr.ifr_name, buf, IFNAMSIZ); strncpy(ifr.ifr_newname, name, IFNAMSIZ); if (ioctl(s, SIOCSIFNAME, &ifr) < 0) { syslog(LOG_NOTICE, "netdevice %s rename to %s failed\n", buf, name); perror("ioctl SIOCSIFNAME rename"); exit(EXIT_FAILURE); } else syslog(LOG_NOTICE, "netdevice %s renamed to %s\n", buf, name); close(s); } } /* The Big Loop */ while (slcand_running) sleep(1); /* wait 1 second */ /* Reset line discipline */ syslog(LOG_INFO, "stopping on TTY device %s", ttypath); ldisc = N_TTY; if (ioctl(fd, TIOCSETD, &ldisc) < 0) { perror("ioctl TIOCSETD"); exit(EXIT_FAILURE); } if (send_close) { sprintf(buf, "C\r"); write(fd, buf, strlen(buf)); } /* Reset old rates */ cfsetispeed(&tios, old_ispeed); cfsetospeed(&tios, old_ospeed); /* apply changes */ if (tcsetattr(fd, TCSADRAIN, &tios) < 0) syslog(LOG_NOTICE, "Cannot set attributes for device \"%s\": %s!\n", ttypath, strerror(errno)); /* Finish up */ syslog(LOG_NOTICE, "terminated on %s", ttypath); closelog(); return exit_code; }