sercom.c

00001 /*
00002  * @(#)sercom.c       07/07/28
00003  * 
00004  * Description  : Library to simplify the serial communication.
00005  *      Inspired by:
00006  *      http://tldp.org/HOWTO/Serial-Programming-HOWTO/x115.html
00007  *
00008  * License      : GNU GPL v.2
00009  * Contacts     : Tran Duy Khanh (www.tran.cz)
00010  */
00011 
00012 #include <sys/signal.h>
00013 #include <termios.h>
00014 #include <stdio.h>
00015 #include <unistd.h>
00016 #include <fcntl.h>
00017 #include <sys/types.h>
00018 #include <string.h>
00019 #include <stdlib.h>
00020 #include <asm-x86_64/types.h>
00021 #include "sercom.h"
00022 
00023 unsigned char sercom_wait_flag = 1;
00024 
00025 void sercom_sighandler(int status)
00026 {
00027         /*printf("received SIGIO signal.\n");*/
00028         sercom_wait_flag = 0;
00029 }
00030 
00037 long sercom_get_baudrate(unsigned int baudrate)
00038 {
00039         long br;
00040         switch (baudrate) {
00041                 case 38400:
00042                         br  = B38400;
00043                         break;
00044                 case 19200:
00045                         br  = B19200;
00046                         break;
00047                 case 9600:
00048                         br  = B9600;
00049                         break;
00050                 case 4800:
00051                         br  = B4800;
00052                         break;
00053                 case 2400:
00054                         br  = B2400;
00055                         break;
00056                 case 1800:
00057                         br  = B1800;
00058                         break;
00059                 case 1200:
00060                         br  = B1200;
00061                         break;
00062                 case 600:
00063                         br  = B600;
00064                         break;
00065                 case 300:
00066                         br  = B300;
00067                         break;
00068                 case 200:
00069                         br  = B200;
00070                         break;
00071                 case 150:
00072                         br  = B150;
00073                         break;
00074                 case 134:
00075                         br  = B134;
00076                         break;
00077                 case 110:
00078                         br  = B110;
00079                         break;
00080                 case 75:
00081                         br  = B75;
00082                         break;
00083                 case 50:
00084                         br  = B50;
00085                         break;
00086                 default:
00087                         br = B19200;
00088         }
00089 
00090         return br;
00091 }
00092 
00099 long sercom_get_databits(int databits)
00100 {
00101         long db;
00102         switch (databits) {
00103                 case 8:
00104                 default:
00105                         db = CS8;
00106                         break;
00107                 case 7:
00108                         db = CS7;
00109                         break;
00110                 case 6:
00111                         db = CS6;
00112                         break;
00113                 case 5:
00114                         db = CS5;
00115                         break;
00116         }
00117         return db;
00118 }
00119 
00126 long sercom_get_stopbits(int stopbits)
00127 {
00128         long sb;
00129         switch (stopbits) {
00130                 case 1:
00131                 default:
00132                         sb = 0;
00133                         break;
00134                 case 2:
00135                         sb = CSTOPB;
00136                         break;
00137         }
00138         return sb;
00139 }
00140 
00147 long sercom_get_parity(int parity)
00148 {
00149         long par, paron;
00150         switch (parity) {
00151                 /* none */
00152                 case 0:
00153                 default:
00154                         paron = 0;
00155                         par = 0;
00156                         break;
00157                 /* odd */
00158                 case 1:
00159                         paron = PARENB;
00160                         par = PARODD;
00161                         break;
00162                 /* even */
00163                 case 2:
00164                         paron = PARENB;
00165                         par = 0;
00166                         break;
00167         }
00168         return (par|paron);
00169 }
00170 
00176 void sercom_open(struct sercom_data *sercom)
00177 {
00178 
00179         /* open the device(com port) to be non-blocking (read will return 
00180          * immediately) */
00181         if (sercom->devname[0] == 0)
00182                 strcpy((char *)&sercom->devname, SERCOM_DEFAULT_DEV);
00183         sercom->fd = open(sercom->devname, O_RDWR | O_NOCTTY | O_NONBLOCK);
00184         if (sercom->fd < 0) {
00185                 perror(sercom->devname);
00186                 exit(-1);
00187         }
00188 
00189         /* install the serial handler before making the device asynchronous */
00190         sercom->saio.sa_handler = sercom_sighandler;
00191         sercom->saio.sa_flags = 0;
00192         sercom->saio.sa_restorer = NULL;
00193         sigemptyset(&sercom->saio.sa_mask);   
00194         sigaction(SIGIO, &sercom->saio, NULL);
00195         
00196         /* allow the process to receive SIGIO */
00197         fcntl(sercom->fd, F_SETOWN, getpid());
00198         /* Make the file descriptor asynchronous (the manual page says only
00199          * O_APPEND and O_NONBLOCK, will work with F_SETFL...) */
00200         fcntl(sercom->fd, F_SETFL, FASYNC);
00201         /* save current serial port settings */
00202         tcgetattr(sercom->fd, &sercom->oldtio);
00203         memset(&sercom->newtio, 0, sizeof(sercom->newtio));
00204 
00205         sercom->newtio.c_cflag = sercom_get_baudrate(sercom->baudrate) |
00206                         sercom_get_databits(sercom->databits) |
00207                         sercom_get_stopbits(sercom->stopbits) |
00208                         sercom_get_parity(sercom->parity) |
00209                         CRTSCTS | CLOCAL | CREAD;
00210         sercom->newtio.c_iflag = IGNPAR | ICRNL;
00211         sercom->newtio.c_oflag = 0;
00212         sercom->newtio.c_lflag = ICANON;
00213         /* blocking read until one character arrives */
00214         sercom->newtio.c_cc[VMIN] = 1;
00215         sercom->newtio.c_cc[VTIME] = 0; /* inter-character timer unused */
00216         /* clean the modem line and activate the settings for the port */
00217         tcflush(sercom->fd, TCIFLUSH);
00218         tcsetattr(sercom->fd, TCSANOW, &sercom->newtio);
00219 }
00220 
00229 ssize_t sercom_read(struct sercom_data *sercom, char *buf, ssize_t buflen)
00230 {
00231         ssize_t len = -1;
00232 
00233         if (sercom_wait_flag == 0) {
00234                 len = read(sercom->fd, buf, buflen);
00235                 buf[len] = 0;
00236                 sercom_wait_flag = 1;
00237         }
00238 
00239         return len;
00240 }
00241 
00247 void sercom_close(struct sercom_data *sercom)
00248 {
00249         /* restore the old port settings */
00250         tcsetattr(sercom->fd, TCSANOW, &sercom->oldtio);
00251         close(sercom->fd);
00252 }

Generated on Thu Sep 13 11:28:28 2007 for DCE-Eurobot by  doxygen 1.5.3