cdlCOM.cpp
Go to the documentation of this file.
1 /*
2  * Katana Native Interface - A C++ interface to the robot arm Katana.
3  * Copyright (C) 2005 Neuronics AG
4  * Check out the AUTHORS file for detailed contact information.
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19  */
20 
21 
22 #include "KNI/cdlCOM.h"
23 
24 #include "common/Timer.h"
25 
26 #include <unistd.h>
27 
28 #ifdef WIN32
29 
30 CCdlCOM::CCdlCOM(TCdlCOMDesc ccd) : _deviceName(""), _ccd(), _prtHdl(INVALID_HANDLE_VALUE), _oto() {
31 
32  DCB commDCB; //COM port parameters
33  COMMTIMEOUTS nto; //new timeouts
34  char comX[5];
35  char dcb[35];
36  int i, d;
37 
38  std::string deviceName;
39  HANDLE prtHdl;
40  COMMTIMEOUTS oto;
41 
42  strncpy_s(comX, "COM ", 5);
43  comX[3] = digit(ccd.port);
44  deviceName = comX;
45  prtHdl = CreateFile(comX,
46  GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_EXISTING,
47  FILE_ATTRIBUTE_NORMAL | FILE_FLAG_WRITE_THROUGH | FILE_FLAG_NO_BUFFERING, 0
48  );
49 
50  if (prtHdl == INVALID_HANDLE_VALUE) {
51  throw CannotOpenPortException(_deviceName, "info from win32-system not yet available");
52  }
53 
54  FillMemory(&commDCB, sizeof(commDCB), 0);
55  commDCB.DCBlength = sizeof(commDCB);
56  strncpy_s(dcb, "baud= parity= data= stop= ", 35);
57  for(i=5,d=100000; d>=1; d=d/10) {
58  if(d <= ccd.baud) {
59  dcb[i++] = digit((ccd.baud/d) % 10);
60  }
61  }
62  dcb[19] = ccd.parity;
63  dcb[26] = digit(ccd.data);
64  dcb[33] = digit(ccd.stop);
65  if (!BuildCommDCB(dcb, &commDCB)) {
66  CloseHandle(prtHdl);
67  throw CannotGetSetPortAttributesException(_deviceName);
68  }
69 
70  commDCB.fAbortOnError = false;
71  commDCB.fInX = false;
72  commDCB.fOutX = false;
73  commDCB.fOutxCtsFlow = false;
74  if (!SetCommState(prtHdl, &commDCB)) {
75  CloseHandle(prtHdl);
76  throw CannotGetSetPortAttributesException(_deviceName);
77  }
78 
79  PurgeComm( prtHdl, PURGE_TXABORT | PURGE_RXABORT | PURGE_TXCLEAR | PURGE_RXCLEAR);
80 
81  GetCommTimeouts(prtHdl, &oto);
82  nto.ReadIntervalTimeout = MAXDWORD;
83  nto.ReadTotalTimeoutMultiplier = 0;
84  nto.ReadTotalTimeoutConstant = ccd.rttc;
85  nto.WriteTotalTimeoutMultiplier = 0;
86  nto.WriteTotalTimeoutConstant = ccd.wttc;
87  if (!SetCommTimeouts(prtHdl, &nto)) {
88  CloseHandle(prtHdl);
89  throw CannotGetSetPortAttributesException(_deviceName);
90  }
91 
92  // Everything done, now we can change the state
93  _prtHdl = prtHdl;
94  _deviceName = deviceName;
95  _ccd = ccd;
96  _oto = oto;
97 }
98 
100  if(_prtHdl == INVALID_HANDLE_VALUE)
101  return;
102 
103  FlushFileBuffers(_prtHdl);
104  SetCommTimeouts(_prtHdl, &_oto);
105 
106  CloseHandle(_prtHdl);
107 
108 }
109 
110 int CCdlCOM::send(const void* buf, int size) {
111 
112  if (_prtHdl == INVALID_HANDLE_VALUE) {
113  throw PortNotOpenException(_deviceName);
114  }
115 
116  if(PurgeComm(_prtHdl, PURGE_TXABORT | PURGE_TXCLEAR) == 0) {
117  throw DeviceWriteException(_deviceName, "PurgeComm failed");
118  }
119 
120  unsigned long readsz;
121  if (WriteFile(_prtHdl, buf, size, &readsz, 0) == 0) {
122  throw DeviceWriteException(_deviceName, "WriteFile failed");
123  }
124 
125  if(readsz != static_cast<long>(size)) {
126  throw WriteNotCompleteException(_deviceName);
127  }
128 
129  return (int)readsz;
130 }
131 
132 int CCdlCOM::recv(void* buf, int size) {
133 
134  if (_prtHdl == INVALID_HANDLE_VALUE) {
135  throw PortNotOpenException(_deviceName);
136  }
137 
138  unsigned char* tmp = static_cast<unsigned char*>(buf);
139  unsigned long readsz = 0, readsz_temp = 0;
140  KNI::Timer timeout(_ccd.rttc);
141  timeout.Start();
142  while (readsz<(unsigned long)size && !timeout.Elapsed()) {
143  if(ReadFile(_prtHdl, &tmp[readsz], size, &readsz_temp, 0) == 0) {
144  DeviceReadException( _deviceName, "ReadFile failed" );
145  } else {
146  readsz += readsz_temp;
147  }
148  }
149 
150  if((unsigned)size != readsz) {
151  throw ReadNotCompleteException(_deviceName);
152  }
153 
154  if(PurgeComm(_prtHdl, PURGE_RXABORT | PURGE_RXCLEAR) == 0) {
155  throw DeviceReadException(_deviceName, "PurgeComm failed");
156  }
157  return (int)readsz;
158 }
159 
160 
161 #else //LINUX
162 
163 CCdlCOM::CCdlCOM(TCdlCOMDesc ccd) : _deviceName(""), _ccd(), _prtHdl(-1), _oto() {
164 
165  int prtHdl = -1;
166 
167  std::string deviceName;
168  struct termios nto, oto;
169  char name[11];
170 
171  errno = 0;
172 
173  strncpy(name, "/dev/ttyS ", 11);
174  name[9] = digit(ccd.port);
175  prtHdl = ::open(name, O_RDWR | O_NOCTTY | O_NDELAY| O_NONBLOCK);
176 
177  _deviceName = name;
178 
179  if (prtHdl < 0) {
180  throw CannotOpenPortException(_deviceName, strerror(errno));
181  }
182 
183  tcgetattr(prtHdl, &oto);
184  bzero(&nto, sizeof(nto));
185  nto.c_cc[VTIME] = 0;
186  nto.c_cc[VMIN] = 0;
187  nto.c_oflag = 0;
188  nto.c_lflag = 0;
189  nto.c_cflag = CLOCAL | CREAD;
190  nto.c_iflag = 0;
191 
192  switch (ccd.baud) {
193  case 50:
194  nto.c_cflag |= B50;
195  break;
196  case 75:
197  nto.c_cflag |= B75;
198  break;
199  case 110:
200  nto.c_cflag |= B110;
201  break;
202  case 134:
203  nto.c_cflag |= B134;
204  break;
205  case 150:
206  nto.c_cflag |= B150;
207  break;
208  case 200:
209  nto.c_cflag |= B200;
210  break;
211  case 300:
212  nto.c_cflag |= B300;
213  break;
214  case 600:
215  nto.c_cflag |= B600;
216  break;
217  case 1200:
218  nto.c_cflag |= B1200;
219  break;
220  case 1800:
221  nto.c_cflag |= B1800;
222  break;
223  case 2400:
224  nto.c_cflag |= B2400;
225  break;
226  case 4800:
227  nto.c_cflag |= B4800;
228  break;
229  case 9600:
230  nto.c_cflag |= B9600;
231  break;
232  case 19200:
233  nto.c_cflag |= B19200;
234  break;
235  case 38400:
236  nto.c_cflag |= B38400;
237  break;
238  case 57600:
239  nto.c_cflag |= B57600;
240  break;
241  case 115200:
242  nto.c_cflag |= B115200;
243  break;
244  case 230400:
245  nto.c_cflag |= B230400;
246  break;
247  }
248 
249  switch (ccd.data) {
250  case 5:
251  nto.c_cflag |= CS5;
252  break;
253  case 6:
254  nto.c_cflag |= CS6;
255  break;
256  case 7:
257  nto.c_cflag |= CS7;
258  break;
259  case 8:
260  nto.c_cflag |= CS8;
261  break;
262  }
263 
264  switch (ccd.parity) {
265  case 'N':
266  case 'n':
267  break;
268  case 'O':
269  case 'o':
270  nto.c_cflag |= PARENB | PARODD;
271  break;
272  case 'E':
273  case 'e':
274  nto.c_cflag |= PARENB;
275  break;
276  }
277 
278  switch (ccd.stop) {
279  case 1:
280  break;
281  case 2:
282  nto.c_cflag |= CSTOPB;
283  break;
284  }
285 
286  tcflush(prtHdl,TCIFLUSH);
287  if (tcsetattr(prtHdl, TCSANOW, &nto) != 0) {
288  ::close(prtHdl);
290  }
291 
292  _prtHdl = prtHdl;
293  _deviceName = deviceName;
294  _ccd = ccd;
295  _oto = oto;
296 }
297 
299 
300  if (_prtHdl < 0) {
301  return;
302  }
303 
304  tcflush(_prtHdl, TCIFLUSH);
305  tcsetattr(_prtHdl, TCSANOW, &_oto);
306 
307  ::close(_prtHdl); // there's nothing we can do about failing
308 
309 }
310 
311 int CCdlCOM::send(const void* buf, int size) {
312 
313  if (_prtHdl < 0)
315 
316  errno = 0;
317 
318  int tcflush_return = tcflush(_prtHdl,TCIFLUSH);
319  if(tcflush_return < 0)
320  throw DeviceWriteException( _deviceName, strerror(errno) );
321 
322  int writesz = write(_prtHdl, buf, size);
323 
324  if(writesz < 0)
325  throw DeviceWriteException( _deviceName, strerror(errno) );
326 
327  if(writesz != size)
329 
330  return writesz;
331 }
332 
333 int CCdlCOM::recv(void* buf, int size) {
334  unsigned char* tmp = static_cast<unsigned char*>(buf);
335  register int readsz = 0;
336 
337  if (_prtHdl < 0)
339 
340  errno = 0;
341 
342  int read_return;
343  KNI::Timer timeout(_ccd.rttc);
344  timeout.Start();
345  while (readsz<size && !timeout.Elapsed()) {
346  read_return = read(_prtHdl, &tmp[readsz], size-readsz);
347  if(read_return < 0) {
348  if(errno != EAGAIN)
349  throw DeviceReadException( _deviceName, strerror(errno));
350  } else {
351  readsz += read_return;
352  }
353  }
354 
355  if (readsz != size)
357 
358  int tcflush_return = tcflush(_prtHdl,TCIFLUSH);
359  if(tcflush_return < 0)
360  throw DeviceReadException( _deviceName, strerror(errno));
361 
362  return readsz;
363 
364 }
365 
366 
367 
368 #endif //WIN32 else LINUX
369 
CCdlCOM(TCdlCOMDesc ccd)
Construct a CCdlCOM class.
Definition: cdlCOM.cpp:163
static char digit(const int _val)
Converts an integer to a char.
Definition: cdlCOM.h:101
int data
data bit
Definition: cdlCOM.h:58
int stop
stop bit
Definition: cdlCOM.h:60
bool Elapsed() const
Definition: Timer.cpp:69
std::string _deviceName
Definition: cdlCOM.h:77
virtual int send(const void *buf, int size)
Sends data to the device.
Definition: cdlCOM.cpp:311
int wttc
write total timeout
Definition: cdlCOM.h:62
int baud
baud rate of port
Definition: cdlCOM.h:57
#define HANDLE
Definition: pthread.h:297
virtual ~CCdlCOM()
Destructs the class.
Definition: cdlCOM.cpp:298
int writesz
Definition: cdlSocket.cpp:26
FloatVector * d
int port
serial port number
Definition: cdlCOM.h:56
This structrue stores the attributes for a serial port device.
Definition: cdlCOM.h:55
TCdlCOMDesc _ccd
Stores the attributes of the serial port device.
Definition: cdlCOM.h:81
void Start()
Definition: Timer.cpp:51
struct termios _oto
old timeouts
Definition: cdlCOM.h:92
int _prtHdl
port handle
Definition: cdlCOM.h:91
int rttc
read total timeout
Definition: cdlCOM.h:61
byte size
Definition: kni_wrapper.cpp:35
int parity
parity bit
Definition: cdlCOM.h:59
virtual int recv(void *buf, int size)
Receives data from the device.
Definition: cdlCOM.cpp:333


kni
Author(s): Martin Günther
autogenerated on Fri Jan 3 2020 04:01:16