00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00028
00029
00030
00031
00032
00033 #ifdef HAVE_CONFIG_H
00034 #include "config.h"
00035 #endif // HAVE_CONFIG_H
00036
00037 #include "uart.h"
00038
00039 #include <nfc/nfc-messages.h>
00040
00041
00042 #ifndef _WIN32
00043
00044 #include <sys/select.h>
00045 #include <termios.h>
00046 typedef struct termios term_info;
00047 typedef struct {
00048 int fd;
00049 term_info tiOld;
00050 term_info tiNew;
00051 } serial_port_unix;
00052
00053
00054 const struct timeval timeout = {
00055 .tv_sec = 0,
00056 .tv_usec = 30000
00057 };
00058
00059
00060 #define CCLAIMED 0x80000000
00061
00062 serial_port uart_open(const char* pcPortName)
00063 {
00064 serial_port_unix* sp = malloc(sizeof(serial_port_unix));
00065
00066 if (sp == 0) return INVALID_SERIAL_PORT;
00067
00068 sp->fd = open(pcPortName, O_RDWR | O_NOCTTY | O_NONBLOCK);
00069 if(sp->fd == -1)
00070 {
00071 uart_close(sp);
00072 return INVALID_SERIAL_PORT;
00073 }
00074
00075 if(tcgetattr(sp->fd,&sp->tiOld) == -1)
00076 {
00077 uart_close(sp);
00078 return INVALID_SERIAL_PORT;
00079 }
00080
00081
00082 if (sp->tiOld.c_iflag & CCLAIMED)
00083 {
00084 uart_close(sp);
00085 return CLAIMED_SERIAL_PORT;
00086 }
00087
00088
00089 sp->tiNew = sp->tiOld;
00090
00091 sp->tiNew.c_cflag = CS8 | CLOCAL | CREAD;
00092 sp->tiNew.c_iflag = CCLAIMED | IGNPAR;
00093 sp->tiNew.c_oflag = 0;
00094 sp->tiNew.c_lflag = 0;
00095
00096 sp->tiNew.c_cc[VMIN] = 0;
00097 sp->tiNew.c_cc[VTIME] = 0;
00098
00099 if(tcsetattr(sp->fd,TCSANOW,&sp->tiNew) == -1)
00100 {
00101 uart_close(sp);
00102 return INVALID_SERIAL_PORT;
00103 }
00104
00105 tcflush(sp->fd, TCIFLUSH);
00106 return sp;
00107 }
00108
00109 void uart_set_speed(serial_port sp, const uint32_t uiPortSpeed)
00110 {
00111 DBG("Serial port speed requested to be set to %d bauds.", uiPortSpeed);
00112
00113
00114
00115
00116 speed_t stPortSpeed = B9600;
00117 switch(uiPortSpeed) {
00118 case 9600: stPortSpeed = B9600;
00119 break;
00120 case 19200: stPortSpeed = B19200;
00121 break;
00122 case 38400: stPortSpeed = B38400;
00123 break;
00124 #ifdef B57600
00125 case 57600: stPortSpeed = B57600;
00126 break;
00127 #endif
00128 #ifdef B115200
00129 case 115200: stPortSpeed = B115200;
00130 break;
00131 #endif
00132 #ifdef B230400
00133 case 230400: stPortSpeed = B230400;
00134 break;
00135 #endif
00136 #ifdef B460800
00137 case 460800: stPortSpeed = B460800;
00138 break;
00139 #endif
00140 default:
00141 ERR("Unable to set serial port speed to %d bauds. Speed value must be one of those defined in termios(3).", uiPortSpeed);
00142 };
00143 const serial_port_unix* spu = (serial_port_unix*)sp;
00144 cfsetispeed((struct termios*)&spu->tiNew, stPortSpeed);
00145 cfsetospeed((struct termios*)&spu->tiNew, stPortSpeed);
00146 if( tcsetattr(spu->fd, TCSADRAIN, &spu->tiNew) == -1)
00147 {
00148 ERR("%s", "Unable to apply new speed settings.");
00149 }
00150 }
00151
00152 uint32_t uart_get_speed(const serial_port sp)
00153 {
00154 uint32_t uiPortSpeed = 0;
00155 const serial_port_unix* spu = (serial_port_unix*)sp;
00156 switch (cfgetispeed(&spu->tiNew))
00157 {
00158 case B9600: uiPortSpeed = 9600;
00159 break;
00160 case B19200: uiPortSpeed = 19200;
00161 break;
00162 case B38400: uiPortSpeed = 38400;
00163 break;
00164 #ifdef B57600
00165 case B57600: uiPortSpeed = 57600;
00166 break;
00167 #endif
00168 #ifdef B115200
00169 case B115200: uiPortSpeed = 115200;
00170 break;
00171 #endif
00172 #ifdef B230400
00173 case B230400: uiPortSpeed = 230400;
00174 break;
00175 #endif
00176 #ifdef B460800
00177 case B460800: uiPortSpeed = 460800;
00178 break;
00179 #endif
00180 }
00181
00182 return uiPortSpeed;
00183 }
00184
00185 void uart_close(const serial_port sp)
00186 {
00187 if (((serial_port_unix*)sp)->fd >= 0) {
00188 tcsetattr(((serial_port_unix*)sp)->fd,TCSANOW,&((serial_port_unix*)sp)->tiOld);
00189 close(((serial_port_unix*)sp)->fd);
00190 }
00191 free(sp);
00192 }
00193
00194 bool uart_cts(const serial_port sp)
00195 {
00196 char status;
00197 if (ioctl(((serial_port_unix*)sp)->fd,TIOCMGET,&status) < 0) return false;
00198 return (status & TIOCM_CTS);
00199 }
00200
00201 bool uart_receive(const serial_port sp, byte_t* pbtRx, size_t* pszRxLen)
00202 {
00203 int res;
00204 int byteCount;
00205 fd_set rfds;
00206 struct timeval tv;
00207
00208
00209 *pszRxLen = 0;
00210
00211 do {
00212
00213 FD_ZERO(&rfds);
00214 FD_SET(((serial_port_unix*)sp)->fd,&rfds);
00215 tv = timeout;
00216 res = select(((serial_port_unix*)sp)->fd+1, &rfds, NULL, NULL, &tv);
00217
00218
00219 if (res < 0) {
00220 DBG("%s", "RX error.");
00221 return false;
00222 }
00223
00224
00225 if (res == 0) {
00226 if (*pszRxLen == 0) {
00227
00228 DBG("%s", "RX time-out, buffer empty.");
00229 return false;
00230 } else {
00231
00232 return true;
00233 }
00234 }
00235
00236
00237 res = ioctl(((serial_port_unix*)sp)->fd, FIONREAD, &byteCount);
00238 if (res < 0) return false;
00239
00240
00241 res = read(((serial_port_unix*)sp)->fd,pbtRx+(*pszRxLen),byteCount);
00242
00243
00244 if (res <= 0) return false;
00245
00246 *pszRxLen += res;
00247
00248 } while (byteCount);
00249
00250 return true;
00251 }
00252
00253 bool uart_send(const serial_port sp, const byte_t* pbtTx, const size_t szTxLen)
00254 {
00255 int32_t res;
00256 size_t szPos = 0;
00257 fd_set rfds;
00258 struct timeval tv;
00259
00260 while (szPos < szTxLen)
00261 {
00262
00263 FD_ZERO(&rfds);
00264 FD_SET(((serial_port_unix*)sp)->fd,&rfds);
00265 tv = timeout;
00266 res = select(((serial_port_unix*)sp)->fd+1, NULL, &rfds, NULL, &tv);
00267
00268
00269 if (res < 0) {
00270 DBG("%s", "TX error.");
00271 return false;
00272 }
00273
00274
00275 if (res == 0) {
00276 DBG("%s", "TX time-out.");
00277 return false;
00278 }
00279
00280
00281 res = write(((serial_port_unix*)sp)->fd,pbtTx+szPos,szTxLen-szPos);
00282
00283
00284 if (res <= 0) return false;
00285
00286 szPos += res;
00287 }
00288 return true;
00289 }
00290
00291 #else
00292
00293
00294 typedef struct {
00295 HANDLE hPort;
00296 DCB dcb;
00297 COMMTIMEOUTS ct;
00298 } serial_port_windows;
00299
00300 serial_port uart_open(const char* pcPortName)
00301 {
00302 char acPortName[255];
00303 serial_port_windows* sp = malloc(sizeof(serial_port_windows));
00304
00305
00306 sprintf(acPortName,"\\\\.\\%s",pcPortName);
00307 _strupr(acPortName);
00308
00309
00310 sp->hPort = CreateFileA(acPortName,GENERIC_READ|GENERIC_WRITE,0,NULL,OPEN_EXISTING,0,NULL);
00311 if (sp->hPort == INVALID_HANDLE_VALUE)
00312 {
00313 uart_close(sp);
00314 return INVALID_SERIAL_PORT;
00315 }
00316
00317
00318 memset(&sp->dcb, 0, sizeof(DCB));
00319 sp->dcb.DCBlength = sizeof(DCB);
00320 if(!BuildCommDCBA("baud=9600 data=8 parity=N stop=1",&sp->dcb))
00321 {
00322 uart_close(sp);
00323 return INVALID_SERIAL_PORT;
00324 }
00325
00326
00327 if(!SetCommState(sp->hPort,&sp->dcb))
00328 {
00329 uart_close(sp);
00330 return INVALID_SERIAL_PORT;
00331 }
00332
00333 sp->ct.ReadIntervalTimeout = 0;
00334 sp->ct.ReadTotalTimeoutMultiplier = 0;
00335 sp->ct.ReadTotalTimeoutConstant = 30;
00336 sp->ct.WriteTotalTimeoutMultiplier = 0;
00337 sp->ct.WriteTotalTimeoutConstant = 30;
00338
00339 if(!SetCommTimeouts(sp->hPort,&sp->ct))
00340 {
00341 uart_close(sp);
00342 return INVALID_SERIAL_PORT;
00343 }
00344
00345 PurgeComm(sp->hPort, PURGE_RXABORT | PURGE_RXCLEAR);
00346
00347 return sp;
00348 }
00349
00350 void uart_close(const serial_port sp)
00351 {
00352 if (((serial_port_windows*)sp)->hPort != INVALID_HANDLE_VALUE) {
00353 CloseHandle(((serial_port_windows*)sp)->hPort);
00354 }
00355 free(sp);
00356 }
00357
00358 void uart_set_speed(serial_port sp, const uint32_t uiPortSpeed)
00359 {
00360 serial_port_windows* spw;
00361
00362 DBG("Serial port speed requested to be set to %d bauds.", uiPortSpeed);
00363
00364 switch(uiPortSpeed) {
00365 case 9600:
00366 case 19200:
00367 case 38400:
00368 case 57600:
00369 case 115200:
00370 case 230400:
00371 case 460800:
00372 break;
00373 default:
00374 ERR("Unable to set serial port speed to %d bauds. Speed value must be one of these constants: 9600 (default), 19200, 38400, 57600, 115200, 230400 or 460800.", uiPortSpeed);
00375 };
00376
00377 spw = (serial_port_windows*)sp;
00378 spw->dcb.BaudRate = uiPortSpeed;
00379 if (!SetCommState(spw->hPort, &spw->dcb))
00380 {
00381 ERR("Unable to apply new speed settings.");
00382 }
00383 }
00384
00385 uint32_t uart_get_speed(const serial_port sp)
00386 {
00387 const serial_port_windows* spw = (serial_port_windows*)sp;
00388 if (!GetCommState(spw->hPort, (serial_port)&spw->dcb))
00389 return spw->dcb.BaudRate;
00390
00391 return 0;
00392 }
00393
00394 bool uart_cts(const serial_port sp)
00395 {
00396 DWORD ModemStat;
00397 const serial_port_windows* spw = (serial_port_windows*)sp;
00398 if (!GetCommModemStatus(spw->hPort,&ModemStat)) return false;
00399 return (ModemStat & MS_CTS_ON);
00400 }
00401
00402 bool uart_receive(const serial_port sp, byte_t* pbtRx, size_t* pszRxLen)
00403 {
00404 ReadFile(((serial_port_windows*)sp)->hPort,pbtRx,*pszRxLen,(LPDWORD)pszRxLen,NULL);
00405 return (*pszRxLen != 0);
00406 }
00407
00408 bool uart_send(const serial_port sp, const byte_t* pbtTx, const size_t szTxLen)
00409 {
00410 DWORD dwTxLen = 0;
00411 return WriteFile(((serial_port_windows*)sp)->hPort,pbtTx,szTxLen,&dwTxLen,NULL);
00412 return (dwTxLen != 0);
00413 }
00414
00415 #endif