libtasks Documentation  1.6
term.cpp
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2013-2014 ADTECH GmbH
3  * Licensed under MIT (https://github.com/adtechlabs/libtasks/blob/master/COPYING)
4  *
5  * Author: Andreas Pohl
6  */
7 
8 #include <tasks/serial/term.h>
9 #include <cstring>
10 #include <fcntl.h>
11 #include <unistd.h>
12 
13 namespace tasks {
14 namespace serial {
15 
16 struct termios term::options() {
17  if (m_fd < 0) {
18  throw tasks_exception(tasks_error::TERM_NO_DEVICE, "no open device");
19  }
20  struct termios opts;
21  if (tcgetattr(m_fd, &opts)) {
22  close();
23  throw tasks_exception(tasks_error::TERM_TCGETATTR, "tcgetattr failed: " + std::string(std::strerror(errno)),
24  errno);
25  }
26  return opts;
27 }
28 
29 void term::set_options(struct termios& opts) {
30  if (m_fd < 0) {
31  throw tasks_exception(tasks_error::TERM_NO_DEVICE, "no open device");
32  }
33  if (tcsetattr(m_fd, TCSANOW, &opts)) {
34  close();
35  throw tasks_exception(tasks_error::TERM_TCSETATTR, "tcsetattr failed: " + std::string(std::strerror(errno)),
36  errno);
37  }
38 }
39 
40 void term::open(std::string port, speed_t baudrate, charsize_t charsize, parity_t parity, stopbits_t stopbits) {
41  m_fd = ::open(port.c_str(), O_RDWR | O_NOCTTY | O_NONBLOCK);
42  if (m_fd < 0) {
44  "opening " + port + std::string(" failed: ") + std::string(std::strerror(errno)), errno);
45  }
46 
47  // ensure non blocking reads
48  if (fcntl(m_fd, F_SETFL, FNDELAY)) {
49  close();
50  throw tasks_exception(tasks_error::TERM_FCNTL, "fcntl failed: " + std::string(std::strerror(errno)), errno);
51  }
52 
53  // read the current settings
54  struct termios opts = options();
55 
56  // don't take ownership of the device and enable recieving of data
57  opts.c_cflag |= (CLOCAL | CREAD);
58  // use raw input/output as a default
59  opts.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);
60  opts.c_oflag &= ~OPOST;
61 
62  // baudrate
63  if (cfsetispeed(&opts, baudrate)) {
64  close();
65  throw tasks_exception(tasks_error::TERM_CFSETISPEED, "cfsetispeed failed: " + std::string(std::strerror(errno)),
66  errno);
67  }
68  if (cfsetospeed(&opts, baudrate)) {
69  close();
70  throw tasks_exception(tasks_error::TERM_CFSETOSPEED, "cfsetospeed failed: " + std::string(std::strerror(errno)),
71  errno);
72  }
73 
74  // charachter size
75  opts.c_cflag &= ~CSIZE;
76  opts.c_cflag |= static_cast<tcflag_t>(charsize);
77 
78  // parity
79  switch (parity) {
80  case parity_t::NONE:
81  opts.c_cflag &= ~PARENB;
82  break;
83  case parity_t::EVEN:
84  opts.c_cflag |= PARENB;
85  opts.c_cflag &= ~PARODD;
86  break;
87  case parity_t::ODD:
88  opts.c_cflag |= PARENB;
89  opts.c_cflag |= PARODD;
90  break;
91  default:
92  close();
93  throw tasks_exception(tasks_error::TERM_INVALID_PARITY, "invalid parity parameter");
94  }
95 
96  // stopbits
97  switch (stopbits) {
98  case stopbits_t::_1:
99  opts.c_cflag &= ~CSTOPB;
100  break;
101  case stopbits_t::_2:
102  opts.c_cflag |= CSTOPB;
103  default:
104  close();
105  throw tasks_exception(tasks_error::TERM_INVALID_STOPBITS, "invalid stopbits parameter");
106  }
107 
108  set_options(opts);
109 }
110 
111 void term::open(std::string port, speed_t baudrate, termmode_t mode) {
112  switch (mode) {
113  case termmode_t::_8N1:
115  break;
116  case termmode_t::_7S1:
118  break;
119  case termmode_t::_7E1:
121  break;
122  case termmode_t::_7O1:
123  open(port, baudrate, charsize_t::_7, parity_t::ODD, stopbits_t::_1);
124  break;
125  default:
126  throw tasks_exception(tasks_error::TERM_INVALID_MODE, "invalid mode parameter");
127  }
128 }
129 
130 void term::close() {
131  if (m_fd > -1) {
132  ::close(m_fd);
133  m_fd = -1;
134  }
135 }
136 
137 std::streamsize term::write(const char* data, std::size_t len) {
138  if (m_fd < 0) {
139  throw tasks_exception(tasks_error::TERM_NO_DEVICE, "no open device");
140  }
141  return ::write(m_fd, data, len);
142 }
143 
144 std::streamsize term::read(char* data, std::size_t len) {
145  if (m_fd < 0) {
146  throw tasks_exception(tasks_error::TERM_NO_DEVICE, "no open device");
147  }
148  return ::read(m_fd, data, len);
149 }
150 
151 } // serial
152 } // tasks
void open(std::string port, speed_t baudrate=B9600, charsize_t charsize=charsize_t::_8, parity_t parity=parity_t::NONE, stopbits_t stopbits=stopbits_t::_1)
Open a terminal device.
Definition: term.cpp:40
int m_fd
Definition: io_base.h:32
std::streamsize write(const char *data, std::size_t len)
Write data to the terminal.
Definition: term.cpp:137
void close()
Close the terminal.
Definition: term.cpp:130
Tasks execption class.
std::streamsize read(char *data, std::size_t len)
Read data from the terminal.
Definition: term.cpp:144
struct termios options()
Access terminal options.
Definition: term.cpp:16
void set_options(struct termios &opts)
Set terminal options.
Definition: term.cpp:29
A class that allows to read and write from/to terminal devices.
Definition: term.h:35