1/*
2 * Author: Jon Trulson <jtrulson@ics.com>
3 * Copyright (c) 2014 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 "ublox6.h"
30
31using namespace upm;
32using namespace std;
33
34Ublox6::Ublox6(int uart)
35{
36  m_ttyFd = -1;
37
38  if ( !(m_uart = mraa_uart_init(uart)) )
39    {
40      throw std::invalid_argument(std::string(__FUNCTION__) +
41                                  ": mraa_uart_init() failed");
42      return;
43    }
44
45  // This requires a recent MRAA (1/2015)
46  const char *devPath = mraa_uart_get_dev_path(m_uart);
47
48  if (!devPath)
49    {
50      throw std::runtime_error(std::string(__FUNCTION__) +
51                               ": mraa_uart_get_dev_path() failed");
52      return;
53    }
54
55  // now open the tty
56  if ( (m_ttyFd = open(devPath, O_RDWR)) == -1)
57    {
58      string err = __FUNCTION__;
59      err += ": open of " + std::string(devPath) + " failed: " +
60        std::string(strerror(errno));
61
62      throw std::runtime_error(err);
63      return;
64    }
65}
66
67Ublox6::~Ublox6()
68{
69  if (m_ttyFd != -1)
70    close(m_ttyFd);
71}
72
73bool Ublox6::dataAvailable()
74{
75  if (m_ttyFd == -1)
76    return false;
77
78  struct timeval timeout;
79
80  // no waiting
81  timeout.tv_sec = 0;
82  timeout.tv_usec = 0;
83
84  int nfds;
85  fd_set readfds;
86
87  FD_ZERO(&readfds);
88
89  FD_SET(m_ttyFd, &readfds);
90
91  if (select(m_ttyFd + 1, &readfds, NULL, NULL, &timeout) > 0)
92    return true;                // data is ready
93  else
94    return false;
95}
96
97int Ublox6::readData(char *buffer, int len)
98{
99  if (m_ttyFd == -1)
100    return(-1);
101
102  int rv = read(m_ttyFd, buffer, len);
103
104  if (rv < 0)
105    {
106      string err = string(__FUNCTION__) + ": read failed: " +
107        string(strerror(errno));
108
109      throw std::runtime_error(err);
110      return rv;
111    }
112
113  return rv;
114}
115
116int Ublox6::writeData(char * buffer, int len)
117{
118  if (m_ttyFd == -1)
119    return(-1);
120
121  int rv = write(m_ttyFd, buffer, len);
122
123  if (rv < 0)
124    {
125      string err = string(__FUNCTION__) + ": write failed: " +
126        string(strerror(errno));
127
128      throw std::runtime_error(err);
129      return rv;
130    }
131
132  tcdrain(m_ttyFd);
133
134  return rv;
135}
136
137bool Ublox6::setupTty(speed_t baud)
138{
139  if (m_ttyFd == -1)
140    return(false);
141
142  struct termios termio;
143
144  // get current modes
145  tcgetattr(m_ttyFd, &termio);
146
147  // setup for a 'raw' mode.  81N, no echo or special character
148  // handling, such as flow control.
149  cfmakeraw(&termio);
150
151  // set our baud rates
152  cfsetispeed(&termio, baud);
153  cfsetospeed(&termio, baud);
154
155  // make it so
156  int rv;
157  if ( (rv = tcsetattr(m_ttyFd, TCSAFLUSH, &termio)) < 0)
158    {
159      string err = string(__FUNCTION__) + ": tcsetattr failed: " +
160        string(strerror(errno));
161
162      throw std::runtime_error(err);
163      return false;
164    }
165
166  return true;
167}
168