libcsdbg  1.28
C++ exception (and generic) stack trace debug library
sttybuf.cpp
Go to the documentation of this file.
1 #include "../include/sttybuf.hpp"
2 #include "../include/util.hpp"
3 #if !defined CSDBG_WITH_PLUGIN && !defined CSDBG_WITH_HIGHLIGHT
4 #include "../include/exception.hpp"
5 #endif
6 
13 namespace csdbg {
14 
23 {
24  __D_ASSERT(m_handle >= 0);
25  if ( unlikely(m_handle < 0) )
26  return const_cast<sttybuf&> (*this);
27 
28  u32 real_baud = translate_baud(m_baud);
29 
30  struct termios conf;
31  util::memset(&conf, 0, sizeof(struct termios));
32  conf.c_cflag = real_baud | CS8 | CRTSCTS | CREAD | CLOCAL;
33  conf.c_iflag = IGNPAR;
34  conf.c_cc[VMIN] = 1;
35 
36  i32 retval;
37  do {
38  retval = tcsetattr(m_handle, TCSANOW, &conf);
39  }
40  while ( unlikely(retval < 0 && errno == EINTR) );
41 
42  if ( unlikely(retval < 0) )
43  throw exception(
44  "failed to configure serial interface '%s' (errno %d - %s)",
45  m_devnode,
46  errno,
47  strerror(errno)
48  );
49 
50  /* Discard all pending data */
51  return discard();
52 }
53 
54 
67 sttybuf::sttybuf(const i8 *port, u32 baud)
68 try:
69 streambuf(),
70 m_devnode(NULL),
71 m_baud(baud)
72 {
73  if ( unlikely(port == NULL) )
74  throw exception("invalid argument: port (=%p)", port);
75 
76  m_devnode = new i8[strlen(port) + 1];
77  strcpy(m_devnode, port);
78 }
79 
80 catch (...) {
81  delete[] m_data;
82  m_data = NULL;
83  m_devnode = NULL;
84 }
85 
86 
96 try:
97 streambuf(src),
98 m_devnode(NULL),
99 m_baud(src.m_baud)
100 {
101  m_devnode = new i8[strlen(src.m_devnode) + 1];
102  strcpy(m_devnode, src.m_devnode);
103 }
104 
105 catch (...) {
106  close();
107 
108  delete[] m_data;
109  m_data = NULL;
110  m_devnode = NULL;
111 }
112 
113 
118 {
119  delete[] m_devnode;
120  m_devnode = NULL;
121 }
122 
123 
132 inline sttybuf* sttybuf::clone() const
133 {
134  return new sttybuf(*this);
135 }
136 
137 
143 inline const i8* sttybuf::devnode() const
144 {
145  return m_devnode;
146 }
147 
148 
154 inline u32 sttybuf::baud() const
155 {
156  return m_baud;
157 }
158 
159 
170 {
171  if ( unlikely(m_baud == baud) )
172  return *this;
173 
174  m_baud = baud;
175  if ( unlikely(m_handle < 0) )
176  return *this;
177 
178  return config();
179 }
180 
181 
193 {
194  if ( unlikely(this == &rval) )
195  return *this;
196 
197  /* Copy the buffer and duplicate the stream descriptor */
198  streambuf::operator=(rval);
199 
200  u32 len = strlen(rval.m_devnode);
201  if (len > strlen(m_devnode)) {
202  delete[] m_devnode;
203  m_devnode = NULL;
204  m_devnode = new i8[len + 1];
205  }
206 
207  strcpy(m_devnode, rval.m_devnode);
208  return set_baud(rval.m_baud);
209 }
210 
211 
217 inline bool sttybuf::is_tty() const
218 {
219  if ( likely(m_handle >= 0) )
220  return isatty(m_handle);
221 
222  return false;
223 }
224 
225 
234 {
235  return open(false);
236 }
237 
238 
251 {
252  if ( unlikely(m_handle >= 0) )
253  close();
254 
255  /* Stat the device node path and make some preliminary checks */
256  fileinfo_t inf;
257  i32 retval = stat(m_devnode, &inf);
258  if ( unlikely(errno == ENOENT) )
259  throw exception("device node '%s' does not exist", m_devnode);
260 
261  else if ( unlikely(retval < 0) )
262  throw exception(
263  "failed to stat path '%s' (errno %d - %s)",
264  m_devnode,
265  errno,
266  strerror(errno)
267  );
268 
269  else if ( unlikely(!util::is_chardev(inf)) )
270  throw exception("'%s' is not a character device", m_devnode);
271 
272  else if ( unlikely(!util::is_writable(inf)) )
273  throw exception("serial interface '%s' is not writable", m_devnode);
274 
275  u32 flags = O_WRONLY;
276  if ( likely(!ctty) )
277  flags |= O_NOCTTY;
278 
279  /* Open the device node */
280  do {
281  m_handle = ::open(m_devnode, flags);
282  }
283  while ( unlikely(m_handle < 0 && errno == EINTR) );
284 
285  if ( unlikely(m_handle < 0) )
286  throw exception(
287  "failed to open serial interface '%s' (errno %d - %s)",
288  m_devnode,
289  errno,
290  strerror(errno)
291  );
292 
293  return config();
294 }
295 
296 
305 {
306  try {
308  return sync();
309  }
310 
311  catch (i32 err) {
312  discard();
313  throw exception(
314  "failed to send data to serial interface '%s' (errno %d - %s)",
315  m_devnode,
316  err,
317  strerror(err)
318  );
319  }
320 }
321 
322 
331 {
332  i32 retval;
333  do {
334  retval = tcdrain(m_handle);
335  }
336  while ( unlikely(retval < 0 && errno == EINTR) );
337 
338  if ( unlikely(retval < 0) )
339  throw exception(
340  "failed to flush serial interface '%s' (errno %d - %s)",
341  m_devnode,
342  errno,
343  strerror(errno)
344  );
345 
346  return const_cast<sttybuf&> (*this);
347 }
348 
349 
356 {
357  i32 retval;
358  do {
359  retval = tcflush(m_handle, TCIOFLUSH);
360  }
361  while ( unlikely(retval < 0 && errno == EINTR) );
362 
363 #if CSDBG_DBG_LEVEL & CSDBG_DBGL_WARNING
364  if ( unlikely(retval < 0) )
366  "failed to clear the buffers of serial interface '%s' (errno %d - %s)",
367  m_devnode,
368  errno,
369  strerror(errno)
370  );
371 #endif
372 
373  return const_cast<sttybuf&> (*this);
374 }
375 
376 
391 {
392  switch (rate) {
393  case 9600:
394  return B9600;
395 
396  case 19200:
397  return B19200;
398 
399  case 38400:
400  return B38400;
401 
402  case 57600:
403  return B57600;
404 
405  case 115200:
406  return B115200;
407 
408  case 230400:
409  return B230400;
410 
411  case 460800:
412  return B460800;
413 
414  default:
415  throw exception("invalid argument: rate (=%d)", rate);
416  }
417 }
418 
419 }
420 
u32 m_baud
Baud rate.
Definition: sttybuf.hpp:36
sttybuf(const i8 *, u32=9600)
Object constructor.
Definition: sttybuf.cpp:67
A buffered output stream for serial interfaces.
Definition: sttybuf.hpp:28
virtual streambuf & flush()=0
To be implemented.
Definition: streambuf.cpp:156
static bool is_writable(const fileinfo_t &)
Check if the process has write access to a file.
Definition: util.cpp:464
static u32 translate_baud(u32)
Translate a number to a baud rate as defined in termios.h.
Definition: sttybuf.cpp:390
virtual sttybuf & sync() const
Commit cached data to the serial interface line.
Definition: sttybuf.cpp:330
This abstract class is the base for all buffered output stream types (for files, sockets, serial interfaces e.t.c)
Definition: streambuf.hpp:37
static void * memset(void *, u8, u32)
Fill a memory block with a constant byte.
Definition: util.cpp:320
char i8
8-bit signed integer
Definition: config.hpp:72
struct stat fileinfo_t
File metadata.
Definition: config.hpp:112
i32 m_handle
Stream handle (descriptor)
Definition: streambuf.hpp:43
virtual const i8 * devnode() const
Get the path of the serial interface device node.
Definition: sttybuf.cpp:143
virtual sttybuf * clone() const
Object virtual copy constructor.
Definition: sttybuf.cpp:132
#define likely(expr)
Offer a hint (positive) to the pipeline branch predictor.
Definition: config.hpp:344
static void dbg_warn(const i8 *,...)
Print a warning debug message on the standard error stream.
Definition: util.cpp:703
virtual sttybuf & open()
Open the serial interface for output.
Definition: sttybuf.cpp:233
virtual sttybuf & flush()
Flush the buffered data to the serial interface.
Definition: sttybuf.cpp:304
virtual streambuf & operator=(const streambuf &)
Assignment operator.
Definition: streambuf.cpp:96
virtual ~sttybuf()
Object destructor.
Definition: sttybuf.cpp:117
static bool is_chardev(const fileinfo_t &)
Check if a file is a character device node.
Definition: util.cpp:432
virtual sttybuf & discard() const
Discard the data cached in the serial interface (in-kernel) buffers.
Definition: sttybuf.cpp:355
i8 * m_devnode
Device node file (devfs)
Definition: sttybuf.hpp:34
virtual sttybuf & set_baud(u32)
Set the baud rate.
Definition: sttybuf.cpp:169
unsigned int u32
32-bit unsigned integer
Definition: config.hpp:102
int i32
32-bit signed integer
Definition: config.hpp:82
virtual sttybuf & config() const
Configure the serial interface.
Definition: sttybuf.cpp:22
virtual u32 baud() const
Get the baud rate.
Definition: sttybuf.cpp:154
virtual bool is_tty() const
Check if the device node is a terminal.
Definition: sttybuf.cpp:217
This class is a throwable with a textual description of an error.
Definition: exception.hpp:26
#define unlikely(expr)
Offer a hint (negative) to the pipeline branch predictor.
Definition: config.hpp:349
virtual streambuf & close()
Close the stream.
Definition: streambuf.cpp:130
virtual sttybuf & operator=(const sttybuf &)
Assignment operator.
Definition: sttybuf.cpp:192
#define __D_ASSERT(x)
Assertion macro.
Definition: config.hpp:268