1 /* 2 * Author: Jon Trulson <jtrulson (at) 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 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 68 HM11::~HM11() 69 { 70 if (m_ttyFd != -1) 71 close(m_ttyFd); 72 } 73 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 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 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 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