Go to the documentation of this file.00001
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031 #include <sys/socket.h>
00032 #include <netinet/in.h>
00033 #include <netinet/tcp.h>
00034 #include <arpa/inet.h>
00035 #include <netdb.h>
00036 #include <unistd.h>
00037 #include <string.h>
00038 #include <errno.h>
00039 #include <sys/ioctl.h>
00040 #include <stdlib.h>
00041
00042 #include "tm_reader.h"
00043
00044 #ifdef TMR_ENABLE_SERIAL_TRANSPORT_NATIVE
00045 static TMR_Status
00046 tcp_open(TMR_SR_SerialTransport *this)
00047 {
00048 int sock;
00049 const char *port;
00050 char hostCopy[256];
00051 TMR_Status ret;
00052 int portNum = 0;
00053 TMR_SR_SerialPortNativeContext *c;
00054
00055 c = this->cookie;
00056 port = strchr(c->devicename, ':');
00057 strcpy(hostCopy, c->devicename + 1);
00058 portNum = atoi(port + 1);
00059 hostCopy[port - c->devicename -1 ] = '\0';
00060
00061 static const struct addrinfo addrInfoMask =
00062 {
00063 0,
00064 AF_INET,
00065 SOCK_STREAM,
00066 0,
00067 0,
00068 NULL,
00069 NULL,
00070 NULL
00071 };
00072 struct addrinfo * hostAddress;
00073 int flag;
00074 struct sockaddr_in sin;
00075 int rc;
00076
00077
00078
00079
00080
00081
00082
00083 if(0 != getaddrinfo(hostCopy, NULL, &addrInfoMask, &hostAddress))
00084 {
00085 return TMR_ERROR_INVALID;
00086 }
00087
00088
00089
00090
00091 memset(&sin, 0, sizeof sin);
00092 sin.sin_family = AF_INET;
00093 sin.sin_addr = ((struct sockaddr_in *)(hostAddress->ai_addr))->sin_addr;
00094 sin.sin_port = htons(portNum);
00095
00096
00097
00098
00099 freeaddrinfo(hostAddress);
00100
00101
00102
00103
00104 sock = socket(AF_INET, SOCK_STREAM, 0);
00105 if(0 > sock)
00106 {
00107 return TMR_ERROR_INVALID;
00108 }
00109
00110
00111
00112
00113 rc = connect(sock, (struct sockaddr *)&sin, sizeof sin);
00114 if(0 > rc)
00115 {
00116
00117 close(sock);
00118 return TMR_ERROR_INVALID;
00119 }
00120
00121
00122
00123
00124
00125 flag = 1;
00126 setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, (void*)&flag, sizeof flag);
00127
00128
00129
00130
00131 c->handle = sock;
00132
00133 ret = TMR_SUCCESS;
00134
00135 return ret;
00136 }
00137
00138
00139 static TMR_Status
00140 tcp_sendBytes(TMR_SR_SerialTransport *this, uint32_t length,
00141 uint8_t* message, const uint32_t timeoutMs)
00142 {
00143 TMR_SR_SerialPortNativeContext *c;
00144 int ret;
00145
00146 c = this->cookie;
00147 do
00148 {
00149 ret = write(c->handle, message, length);
00150 if (ret == -1)
00151 {
00152 return TMR_ERROR_COMM_ERRNO(errno);
00153 }
00154 length -= ret;
00155 message += ret;
00156 }
00157 while (length > 0);
00158
00159 return TMR_SUCCESS;
00160 }
00161
00162
00163 static TMR_Status
00164 tcp_receiveBytes(TMR_SR_SerialTransport *this, uint32_t length,
00165 uint32_t* messageLength, uint8_t* message, const uint32_t timeoutMs)
00166 {
00167 TMR_SR_SerialPortNativeContext *c;
00168 int ret;
00169 struct timeval tv;
00170 fd_set set;
00171 int status = 0;
00172
00173 *messageLength = 0;
00174 c = this->cookie;
00175
00176 do
00177 {
00178 FD_ZERO(&set);
00179 FD_SET(c->handle, &set);
00180 tv.tv_sec = timeoutMs/1000;
00181 tv.tv_usec = (timeoutMs % 1000) * 1000;
00182
00183 ret = select(c->handle + 1, &set, NULL, NULL, &tv);
00184 if (ret < 1)
00185 {
00186 return TMR_ERROR_TIMEOUT;
00187 }
00188 ret = read(c->handle, message, length);
00189 if (ret == -1)
00190 {
00191 return TMR_ERROR_COMM_ERRNO(errno);
00192 }
00193
00194 if (0 == ret)
00195 {
00201 ret = ioctl(c->handle, TIOCMGET, &status);
00202 if (-1 == ret)
00203 {
00204
00205 if (EIO == errno)
00206 {
00211 return TMR_ERROR_TIMEOUT;
00212 }
00213 }
00214 }
00215
00216 length -= ret;
00217 *messageLength += ret;
00218 message += ret;
00219 }
00220 while (length > 0);
00221
00222 return TMR_SUCCESS;
00223 }
00224
00225 #if 0
00226 static TMR_Status
00227 tcp_setBaudRate(TMR_SR_SerialTransport *this, uint32_t rate)
00228 {
00229
00230
00231
00232
00233
00234
00235 return TMR_ERROR_UNIMPLEMENTED;
00236 }
00237 #endif
00238
00239 static TMR_Status
00240 tcp_shutdown(TMR_SR_SerialTransport *this)
00241 {
00242 TMR_Status ret = TMR_SUCCESS;
00243 TMR_SR_SerialPortNativeContext *c;
00244
00245 c = this->cookie;
00246
00247 if (0 > c->handle)
00248 {
00249 ret = TMR_ERROR_INVALID;
00250 }
00251
00252 close(c->handle);
00253
00254 c->handle = -1;
00255
00256 return ret;
00257
00258 }
00259
00260 static TMR_Status
00261 tcp_flush(TMR_SR_SerialTransport *this)
00262 {
00263
00264
00265
00266
00267
00268
00269 return TMR_SUCCESS;
00270 }
00271
00279 TMR_Status
00280 TMR_SR_SerialTransportTcpNativeInit(TMR_SR_SerialTransport *transport,
00281 TMR_SR_SerialPortNativeContext *context,
00282 const char *device)
00283 {
00284
00285 if (strlen(device) + 1 > TMR_MAX_READER_NAME_LENGTH)
00286 {
00287 return TMR_ERROR_INVALID;
00288 }
00289 strcpy(context->devicename, device);
00290
00291 transport->cookie = context;
00292 transport->open = tcp_open;
00293 transport->sendBytes = tcp_sendBytes;
00294 transport->receiveBytes = tcp_receiveBytes;
00295 transport->setBaudRate = NULL;
00296 transport->shutdown = tcp_shutdown;
00297 transport->flush = tcp_flush;
00298
00299 return TMR_SUCCESS;
00300 }
00301 #endif