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