00001
00025 #include "stdint.h"
00026 #include <stdio.h>
00027 #include <string.h>
00028
00029 #if defined(_USE_WIN_API)
00030 #include <windows.h>
00031 #elif defined(_USE_LINUX_API)
00032 #include <errno.h>
00033 #include <fcntl.h>
00034 #include <sys/ioctl.h>
00035 #include <termios.h>
00036 #include <unistd.h>
00037 #define _BAUD_MAX (15)
00038 #define _BAUD_PAIR(val) {val, B ## val}
00039 static const unsigned int BAUD_RATE[_BAUD_MAX][2] =
00040 { _BAUD_PAIR(50), _BAUD_PAIR(75), _BAUD_PAIR(110), _BAUD_PAIR(134), _BAUD_PAIR(150),
00041 _BAUD_PAIR(200), _BAUD_PAIR(300), _BAUD_PAIR(600), _BAUD_PAIR(1200), _BAUD_PAIR(1800),
00042 _BAUD_PAIR(2400), _BAUD_PAIR(4800), _BAUD_PAIR(9600), _BAUD_PAIR(19200), _BAUD_PAIR(38400)};
00043 #else
00044 #include "dn_additional.h"
00045 #endif
00046
00047 #include "dn_common.h"
00048 #include "dn_device.h"
00049 #include "dn_com.h"
00050
00051 #define _COM_PORT_MAX (256)
00052
00053 #define _FLOW_XINOUT (1)
00054 #define _FLOW_HARDWARE (2)
00055
00056 #if defined(_USE_WIN_API)
00057 static HRESULT _com_open(const struct CONN_PARAM_COM *com_param, int *sock)
00058 {
00059 char szName[16];
00060 COM_STATE state;
00061 HRESULT hr;
00062
00063 sprintf(szName, "//./COM%d", com_param->port);
00064 *sock = (int)CreateFileA(szName, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
00065
00066 if(*sock < 0) {
00067 *sock = 0;
00068 hr = DNGetLastError();
00069 return OSERR2HRESULT(hr);
00070 }
00071
00072
00073 com_clear(*sock, 0);
00074
00075 hr = com_get_state(*sock, &state);
00076 if(SUCCEEDED(hr)) {
00077 state.BaudRate = com_param->baud_rate;
00078 state.ByteSize = com_param->data_bits;
00079 state.Parity = com_param->parity;
00080 state.StopBits = com_param->stop_bits;
00081
00082 if(com_param->flow & _FLOW_XINOUT) {
00083 state.fOutX = 1;
00084 state.fInX = 1;
00085 } else {
00086 state.fOutX = 0;
00087 state.fInX = 0;
00088 }
00089
00090 if(com_param->flow & _FLOW_HARDWARE) {
00091 state.fOutxCtsFlow = 1;
00092 state.fRtsControl = RTS_CONTROL_HANDSHAKE;
00093 } else {
00094 state.fOutxCtsFlow = 0;
00095 state.fRtsControl = RTS_CONTROL_ENABLE;
00096 }
00097 state.fOutxDsrFlow = 0;
00098 state.fDtrControl = DTR_CONTROL_ENABLE;
00099 state.fDsrSensitivity = 0;
00100
00101 hr = com_set_state(*sock, &state);
00102 }
00103
00104 return hr;
00105 }
00106
00107 static int _com_close(int sock)
00108 {
00109 return CloseHandle((HANDLE)sock);
00110 }
00111
00112 static int _com_send(int sock, const char *buf, uint32_t len_send, uint32_t *len_sended, void *arg)
00113 {
00114 return WriteFile((HANDLE)sock, buf, len_send, (LPDWORD)len_sended, NULL);
00115 }
00116
00117 static int _com_recv(int sock, char *buf, uint32_t len_recv, uint32_t *len_recved, uint32_t timeout, void *arg)
00118 {
00119 int ret;
00120
00121 *len_recved = 0;
00122 ret = ReadFile((HANDLE)sock, buf, len_recv, (LPDWORD)len_recved, NULL);
00123
00124 return ret;
00125 }
00126
00127 static HRESULT _com_set_timeout(int sock, uint32_t timeout)
00128 {
00129 int ret;
00130 COMMTIMEOUTS stTimeOut;
00131 HRESULT hr = S_OK;
00132
00133 stTimeOut.ReadIntervalTimeout = MAXDWORD;
00134 stTimeOut.ReadTotalTimeoutMultiplier = MAXDWORD;
00135 stTimeOut.ReadTotalTimeoutConstant = timeout;
00136 stTimeOut.WriteTotalTimeoutMultiplier = 1;
00137 stTimeOut.WriteTotalTimeoutConstant = timeout;
00138 ret = SetCommTimeouts((HANDLE)sock, &stTimeOut);
00139 if(OSFAILED(ret)) {
00140 ret = DNGetLastError();
00141 hr = OSERR2HRESULT(ret);
00142 }
00143
00144 return hr;
00145 }
00146
00147 static HRESULT _com_clear(int sock, uint32_t timeout)
00148 {
00149 int ret;
00150 DWORD err;
00151 HRESULT hr = S_OK;
00152
00153 ret = ClearCommError((HANDLE)sock, &err, NULL);
00154 if(OSSUCCEEDED(ret)) {
00155 ret = PurgeComm((HANDLE)sock, (PURGE_TXABORT | PURGE_RXABORT| PURGE_TXCLEAR | PURGE_RXCLEAR));
00156 }
00157 if(OSFAILED(ret)) {
00158 ret = DNGetLastError();
00159 hr = OSERR2HRESULT(ret);
00160 }
00161
00162 return hr;
00163 }
00164
00165 static int _com_get_state(int sock, COM_STATE *state)
00166 {
00167 return GetCommState((HANDLE)sock, state);
00168 }
00169
00170 static int _com_set_state(int sock, COM_STATE *state)
00171 {
00172 return SetCommState((HANDLE)sock, state);
00173 }
00174
00175 static int _com_get_modem_state(int sock, uint32_t *state)
00176 {
00177 return GetCommModemStatus((HANDLE)sock, (DWORD *)state);
00178 }
00179 #elif defined(_USE_LINUX_API)
00180 static HRESULT _com_open(const struct CONN_PARAM_COM *com_param, int *sock)
00181 {
00182 int i;
00183 char szName[16];
00184 COM_STATE state;
00185 HRESULT hr;
00186
00187 sprintf(szName, "/dev/ttyS%d", com_param->port);
00188 *sock = open(szName, O_RDWR | O_NOCTTY | O_NONBLOCK);
00189
00190 if(*sock < 0) {
00191 *sock = 0;
00192 hr = DNGetLastError();
00193 return OSERR2HRESULT(hr);
00194 }
00195
00196
00197 com_clear(*sock, 0);
00198
00199 memset(&state, 0, sizeof(COM_STATE));
00200
00201 state.c_cflag = (CLOCAL | CREAD);
00202
00203 for(i = 0; i < _BAUD_MAX; i++) {
00204 if(com_param->baud_rate == BAUD_RATE[i][0]) {
00205 state.c_cflag |= BAUD_RATE[i][1];
00206 break;
00207 }
00208 }
00209
00210 switch(com_param->data_bits) {
00211 case 5:
00212 state.c_cflag |= CS5;
00213 break;
00214 case 6:
00215 state.c_cflag |= CS6;
00216 break;
00217 case 7:
00218 state.c_cflag |= CS7;
00219 break;
00220 case 8:
00221 state.c_cflag |= CS8;
00222 break;
00223 default:
00224 break;
00225 }
00226
00227 switch(com_param->parity) {
00228 case NOPARITY:
00229 state.c_cflag &= ~PARENB;
00230 break;
00231 case ODDPARITY:
00232 state.c_cflag |= PARENB;
00233 state.c_cflag |= PARODD;
00234 break;
00235 case EVENPARITY:
00236 state.c_cflag |= PARENB;
00237 state.c_cflag &= ~PARODD;
00238 break;
00239 default:
00240 break;
00241 }
00242
00243 switch(com_param->stop_bits) {
00244 case ONESTOPBIT:
00245 state.c_cflag &= ~CSTOPB;
00246 break;
00247 case TWOSTOPBITS:
00248 state.c_cflag |= CSTOPB;
00249 break;
00250 default:
00251 break;
00252 }
00253
00254 if(com_param->flow & _FLOW_XINOUT) {
00255 state.c_iflag |= IXON;
00256 state.c_iflag |= IXOFF;
00257 } else {
00258 state.c_iflag &= ~IXON;
00259 state.c_iflag &= ~IXOFF;
00260 }
00261
00262 if(com_param->flow & _FLOW_HARDWARE) {
00263 state.c_cflag |= CRTSCTS;
00264 } else {
00265 state.c_cflag &= ~CRTSCTS;
00266 }
00267
00268 hr = com_set_state(*sock, &state);
00269
00270 return hr;
00271 }
00272
00273 static int _com_close(int sock)
00274 {
00275 return close(sock);
00276 }
00277
00278 static int _com_send(int sock, const char *buf, uint32_t len_send, uint32_t *len_sended, void *arg)
00279 {
00280 int ret;
00281 ret = write(sock, buf, len_send);
00282 *len_sended = ret;
00283 return ret;
00284 }
00285
00286 static int _com_recv(int sock, char *buf, uint32_t len_recv, uint32_t *len_recved, uint32_t timeout, void *arg)
00287 {
00288 int ret = 0;
00289 HRESULT hr;
00290
00291 *len_recved = 0;
00292 hr = check_timeout(sock, timeout);
00293 if(SUCCEEDED(hr)) {
00294 ret = read(sock, buf, len_recv);
00295 *len_recved = ret;
00296 }
00297
00298 return ret;
00299 }
00300
00301 static HRESULT _com_set_timeout(int sock, uint32_t timeout)
00302 {
00303 COM_STATE state;
00304 HRESULT hr;
00305
00306 hr = com_get_state(sock, &state);
00307 if(SUCCEEDED(hr)) {
00308 state.c_cc[VMIN] = 0;
00309 state.c_cc[VTIME] = timeout * 10 / 1000;
00310
00311 hr = com_set_state(sock, &state);
00312 }
00313
00314 return hr;
00315 }
00316
00317 static HRESULT _com_clear(int sock, uint32_t timeout)
00318 {
00319 int ret;
00320 HRESULT hr = S_OK;
00321
00322 ret = tcflush(sock, TCIFLUSH);
00323 if(OSFAILED(ret)) {
00324 ret = DNGetLastError();
00325 return OSERR2HRESULT(ret);
00326 }
00327
00328 ret = tcflush(sock, TCOFLUSH);
00329 if(OSFAILED(ret)) {
00330 ret = DNGetLastError();
00331 return OSERR2HRESULT(ret);
00332 }
00333
00334 return hr;
00335 }
00336
00337 static int _com_get_state(int sock, COM_STATE *state)
00338 {
00339 return tcgetattr(sock, state);
00340 }
00341
00342 static int _com_set_state(int sock, COM_STATE *state)
00343 {
00344 return tcsetattr(sock, TCSAFLUSH, state);
00345 }
00346
00347 static int _com_get_modem_state(int sock, uint32_t *state)
00348 {
00349 return ioctl(sock, TIOCMGET, (int *)state);
00350 }
00351 #endif
00352
00359 HRESULT
00360 com_open(void *param, int *sock)
00361 {
00362 int port;
00363 HRESULT hr;
00364 const struct CONN_PARAM_COM *com_param = (const struct CONN_PARAM_COM *) param;
00365
00366 if (param == NULL || sock == NULL)
00367 return E_INVALIDARG;
00368
00369
00370 port = com_param->port;
00371 if (port < 0 || _COM_PORT_MAX < port)
00372 return E_INVALIDARG;
00373
00374 hr = _com_open(com_param, sock);
00375
00376 return hr;
00377 }
00378
00384 HRESULT
00385 com_close(int *sock)
00386 {
00387 int ret;
00388
00389 if (sock == NULL || *sock <= 0)
00390 return E_HANDLE;
00391
00392 ret = _com_close(*sock);
00393 if (OSFAILED(ret)) {
00394 ret = DNGetLastError();
00395 return OSERR2HRESULT(ret);
00396 }
00397
00398 *sock = 0;
00399
00400 return S_OK;
00401 }
00402
00411 HRESULT
00412 com_send(int sock, const char *buf, uint32_t len_buf, void *arg)
00413 {
00414 int ret;
00415 uint32_t len_send, len_sended;
00416
00417 if (sock <= 0)
00418 return E_HANDLE;
00419 if (buf == NULL || strlen(buf) == 0)
00420 return E_INVALIDARG;
00421
00422 len_send = (len_buf != 0) ? len_buf : strlen(buf);
00423 ret = _com_send(sock, buf, len_send, &len_sended, arg);
00424
00425 if (OSFAILED(ret)) {
00426 ret = DNGetLastError();
00427 #if defined(_USE_WIN_API)
00428 {
00429 DWORD err_flag;
00430 ClearCommError((HANDLE)sock, &err_flag, NULL);
00431 }
00432 #endif
00433 return OSERR2HRESULT(ret);
00434 }
00435
00436 if (len_send > len_sended) {
00437 return E_TIMEOUT;
00438 }
00439
00440 return S_OK;
00441 }
00442
00452 HRESULT
00453 com_recv(int sock, char *buf, uint32_t len_buf, uint32_t *len_recved,
00454 uint32_t timeout, void *arg)
00455 {
00456 int ret;
00457
00458 if (sock <= 0)
00459 return E_HANDLE;
00460 if (buf == NULL || len_recved == NULL)
00461 return E_INVALIDARG;
00462
00463 ret = _com_recv(sock, buf, len_buf, len_recved, timeout, arg);
00464
00465 if (OSFAILED(ret)) {
00466 ret = DNGetLastError();
00467 #if defined(_USE_WIN_API)
00468 {
00469 DWORD err_flag;
00470 ClearCommError((HANDLE)sock, &err_flag, NULL);
00471 }
00472 #endif
00473 return OSERR2HRESULT(ret);
00474 }
00475
00476 if (*len_recved == 0)
00477 return E_TIMEOUT;
00478
00479 return S_OK;
00480 }
00481
00488 HRESULT
00489 com_set_timeout(int sock, uint32_t timeout)
00490 {
00491 HRESULT hr = S_OK;
00492
00493 if (sock <= 0)
00494 return E_HANDLE;
00495
00496 hr = _com_set_timeout(sock, timeout);
00497
00498 return hr;
00499 }
00500
00507 HRESULT
00508 com_clear(int sock, uint32_t timeout)
00509 {
00510 HRESULT hr = S_OK;
00511
00512 if (sock <= 0)
00513 return E_HANDLE;
00514
00515 hr = _com_clear(sock, timeout);
00516
00517 return hr;
00518 }
00519
00526 HRESULT
00527 com_get_state(int sock, COM_STATE *state)
00528 {
00529 int ret;
00530 HRESULT hr = S_OK;
00531
00532 if (sock <= 0)
00533 return E_HANDLE;
00534 if (state == NULL)
00535 return E_INVALIDARG;
00536
00537 ret = _com_get_state(sock, state);
00538
00539 if (OSFAILED(ret)) {
00540 ret = DNGetLastError();
00541 hr = OSERR2HRESULT(ret);
00542 }
00543
00544 return hr;
00545 }
00546
00553 HRESULT
00554 com_set_state(int sock, COM_STATE *state)
00555 {
00556 int ret;
00557 HRESULT hr = S_OK;
00558
00559 if (sock <= 0)
00560 return E_HANDLE;
00561 if (state == NULL)
00562 return E_INVALIDARG;
00563
00564 ret = _com_set_state(sock, state);
00565
00566 if (OSFAILED(ret)) {
00567 ret = DNGetLastError();
00568 hr = OSERR2HRESULT(ret);
00569 }
00570
00571 return hr;
00572 }
00573
00580 HRESULT
00581 com_get_modem_state(int sock, uint32_t *state)
00582 {
00583 int ret;
00584 HRESULT hr = S_OK;
00585
00586 if (sock <= 0)
00587 return E_HANDLE;
00588 if (state == NULL)
00589 return E_INVALIDARG;
00590
00591 ret = _com_get_modem_state(sock, state);
00592
00593 if (OSFAILED(ret)) {
00594 ret = DNGetLastError();
00595 hr = OSERR2HRESULT(ret);
00596 }
00597
00598 return hr;
00599 }