1 /*
2 * Author: Jon Trulson <jtrulson@ics.com>
3 * Copyright (c) 2015 Intel Corporation.
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining
6 * a copy of this software and associated documentation files (the
7 * "Software"), to deal in the Software without restriction, including
8 * without limitation the rights to use, copy, modify, merge, publish,
9 * distribute, sublicense, and/or sell copies of the Software, and to
10 * permit persons to whom the Software is furnished to do so, subject to
11 * the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be
14 * included in all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23 */
24
25 #include <iostream>
26 #include <string>
27 #include <stdexcept>
28
29 #include "hm11.h"
30
31 using namespace upm;
32 using namespace std;
33
34 static const int defaultDelay = 100; // max wait time for read
35
HM11(int uart)36 HM11::HM11(int uart)
37 {
38 m_ttyFd = -1;
39
40 if ( !(m_uart = mraa_uart_init(uart)) )
41 {
42 throw std::invalid_argument(std::string(__FUNCTION__) +
43 ": mraa_uart_init() failed");
44 return;
45 }
46
47 // This requires a recent MRAA (1/2015)
48 const char *devPath = mraa_uart_get_dev_path(m_uart);
49
50 if (!devPath)
51 {
52 throw std::runtime_error(std::string(__FUNCTION__) +
53 ": mraa_uart_get_dev_path() failed");
54 return;
55 }
56
57 // now open the tty
58 if ( (m_ttyFd = open(devPath, O_RDWR)) == -1)
59 {
60 throw std::runtime_error(std::string(__FUNCTION__) +
61 ": open of " +
62 string(devPath) + " failed:" +
63 string(strerror(errno)));
64 return;
65 }
66 }
67
~HM11()68 HM11::~HM11()
69 {
70 if (m_ttyFd != -1)
71 close(m_ttyFd);
72 }
73
dataAvailable(unsigned int millis)74 bool HM11::dataAvailable(unsigned int millis)
75 {
76 if (m_ttyFd == -1)
77 return false;
78
79 struct timeval timeout;
80
81 // no waiting
82 timeout.tv_sec = 0;
83 timeout.tv_usec = millis * 1000;
84
85 int nfds;
86 fd_set readfds;
87
88 FD_ZERO(&readfds);
89
90 FD_SET(m_ttyFd, &readfds);
91
92 if (select(m_ttyFd + 1, &readfds, NULL, NULL, &timeout) > 0)
93 return true; // data is ready
94 else
95 return false;
96 }
97
readData(char * buffer,int len)98 int HM11::readData(char *buffer, int len)
99 {
100 if (m_ttyFd == -1)
101 return(-1);
102
103 int rv = read(m_ttyFd, buffer, len);
104
105 if (rv < 0)
106 {
107 throw std::runtime_error(std::string(__FUNCTION__) +
108 ": read() failed: " +
109 string(strerror(errno)));
110 return rv;
111 }
112
113 return rv;
114 }
115
writeData(char * buffer,int len)116 int HM11::writeData(char *buffer, int len)
117 {
118 if (m_ttyFd == -1)
119 return(-1);
120
121 // first, flush any pending but unread input
122
123 tcflush(m_ttyFd, TCIFLUSH);
124
125 int rv = write(m_ttyFd, buffer, len);
126
127 if (rv < 0)
128 {
129 throw std::runtime_error(std::string(__FUNCTION__) +
130 ": write() failed: " +
131 string(strerror(errno)));
132 return rv;
133 }
134
135 tcdrain(m_ttyFd);
136
137 return rv;
138 }
139
setupTty(speed_t baud)140 bool HM11::setupTty(speed_t baud)
141 {
142 if (m_ttyFd == -1)
143 return(false);
144
145 struct termios termio;
146
147 // get current modes
148 tcgetattr(m_ttyFd, &termio);
149
150 // setup for a 'raw' mode. 81N, no echo or special character
151 // handling, such as flow control.
152 cfmakeraw(&termio);
153
154 // set our baud rates
155 cfsetispeed(&termio, baud);
156 cfsetospeed(&termio, baud);
157
158 // make it so
159 if (tcsetattr(m_ttyFd, TCSAFLUSH, &termio) < 0)
160 {
161 throw std::runtime_error(std::string(__FUNCTION__) +
162 ": tcsetattr() failed: " +
163 string(strerror(errno)));
164 return false;
165 }
166
167 return true;
168 }
169
170