/* serial_port.h Henriks Communication Api www.eit.se/hcpips */ #ifdef WIN32 #include #include #include #include #include #include #include #include #include "serial_port.h" /* The CreateFile function can create a handle to a communications resource, such as the serial port COM1. For communications resources, the dwCreationDisposition parameter must be OPEN_EXISTING, and the hTemplate parameter must be NULL. Read, write, or read/write access can be specified, and the handle can be opened for overlapped I/O. For more information about communications, see Communications. */ /* Open a serial port dev_name chall be: COM1 COM2 etc Returns: a handle if ok, INVALID_HANDLE_VALUE if not ok. */ HANDLE serial_port_open(const char *dev_name, int baudrate) { if ((strncmp(dev_name, "COM", 3)!=0) || (strlen(dev_name)>6)) { fprintf(stderr,"Not a COM port name %.32s\n", dev_name); return NULL; } { char tmp_name[1024+128]; sprintf(tmp_name, "\\\\.\\%.1024s", dev_name); { HANDLE h = CreateFile(tmp_name, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if (h!=INVALID_HANDLE_VALUE) { DCB dcb; GetCommState(h, &dcb); dcb.BaudRate=baudrate; SetCommState(h, &dcb); /* typedef struct _COMMTIMEOUTS { DWORD ReadIntervalTimeout; DWORD ReadTotalTimeoutMultiplier; DWORD ReadTotalTimeoutConstant; DWORD WriteTotalTimeoutMultiplier; DWORD WriteTotalTimeoutConstant; } COMMTIMEOUTS, *LPCOMMTIMEOUTS; */ { COMMTIMEOUTS commTimeouts={MAXDWORD,0,1,0,0}; if (!SetCommTimeouts(h, &commTimeouts)) { fprintf(stderr,"SetCommTimeouts failed %d\n",GetLastError()); hca_close_handle(h); return NULL; } } } return h; } } } #else #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "serial_port.h" /* used for serial port, only using one at a time is supported */ /* later some day there should be an array here */ //static struct termios hca_oldtio; /*static int hca_fd = HCA_NO_FD;*/ static int baudrate_bits(int baudrate) { switch (baudrate) { case 50: return B50; case 75: return B75; case 110: return B110; case 134: return B134; case 150: return B150; case 200: return B200; case 300: return B300; case 600: return B600; case 1200: return B1200; case 1800: return B1800; case 2400: return B2400; case 4800: return B4800; case 9600: return B9600; case 19200: return B19200; case 38400: return B38400; case 57600: return B57600; case 115200: return B115200; case 230400: return B230400; default: { fprintf(stderr, "hca: baudrate %d not supported\n", baudrate); return(-1); } } } /* Open serial port and set baudrate Returns a file descriptor to be used for reading and writing. dev_name chall be: /dev/ttyS0 for COM1 /dev/ttyS1 for COM2 /dev/ttyS2 for COM3 /dev/ttyUSB0 for first USB connected serial port (most common case) read more at: http://www.faqs.org/docs/Linux-HOWTO/Serial-Programming-HOWTO.html http://www.easysw.com/~mike/serial/serial.html#advanced */ int serial_port_open(const char *dev_name, int baudrate) { int tty_fd = open(dev_name, O_RDWR | O_NOCTTY | O_NDELAY); if (tty_fd<0) { perror(dev_name); return -1; } #if 0 tcgetattr(tty_fd,&hca_oldtio); /* save current serial port settings */ #endif /* set baudrate etc */ { struct termios t; tcgetattr(tty_fd,&t); /* get current serial port settings */ /*bzero(&t, sizeof(t));*/ /* clear struct for new port settings */ /* not clearing c_cflag here since we might want to use currect baudrate */ /* enable the receiver */ t.c_cflag |= CREAD; /* local mode */ t.c_cflag |= CLOCAL; /* no hardware flow control (alias CNEW_RTSCTS) */ t.c_cflag &= ~CRTSCTS; /* No parity, 8 bits one stop bit */ t.c_cflag &= ~PARENB; t.c_cflag &= ~CSTOPB; t.c_cflag &= ~CSIZE; t.c_cflag |= CS8; /* Input Options */ t.c_iflag=0; /*t.c_iflag |= IGNPAR;*/ /* ignore parity errors */ /*t.c_iflag &= ~(IXON | IXOFF | IXANY);*/ /* disable software flow control */ /* output options, not processed */ t.c_oflag = 0; /* possibly use (OPOST | ONLCR) to Map NL to CR-NL*/ /* set line options */ t.c_lflag = 0; /*t.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);*/ /* raw input, (non-canonical, no echo,...) */ /* Control Characters */ bzero(&t.c_cc, sizeof(t.c_cc)); /* set all to zero */ /*t.c_cc[VTIME] = 0;*/ /* inter-character timer unused */ t.c_cc[VMIN] = 1; /* Minimum number of characters to read */ /* set baudrate */ if (baudrate!=0) { const int b=baudrate_bits(baudrate); if (b!=-1) { cfsetispeed(&t, b); cfsetospeed(&t, b); } } else { /* keep current baudrate */ } tcflush(tty_fd, TCIFLUSH); tcsetattr(tty_fd,TCSANOW,&t); } /* set port to non blocking mode (perhaps not needed if newtio.c_cc[VMIN] is 0) */ fcntl(tty_fd, F_SETFL, FNDELAY); return tty_fd; } // Returns number of bytes sent int serial_port_write(int fd, const char *buf, int len) { const int n=write(fd, buf, len); if (n<0) { if (errno==EWOULDBLOCK) { // Output que is full return(0); } perror("write"); fprintf(stderr,"write error %d\n", n); } return n; } // Returns number of bytes received int serial_port_read(int fd,char *buf, int len) { const int n=read(fd, buf, len); if (n>0) { // OK } else if (n==0) // Client has disconnected (I think) { printf("Client has disconnected, fd=%d\n",fd); return(-1); } else if (n<0) // Something went wrong { if (errno==EWOULDBLOCK) { // there is no data yet, try again later return(0); } perror("read"); fprintf(stderr,"hca_read: socket %d error %d\n",fd,errno); return(-2); } return(n); } int serial_port_close(const char *dev_name, int baudrate) { #if 0 if (hca_fd>=0) { /* restore the old port settings */ tcsetattr(hca_fd,TCSANOW,&hca_oldtio); } #endif } #endif