1e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang/*
2e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang * Author: Thomas Ingleby <thomas.c.ingleby@intel.com>
3e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang * Contributions: Jon Trulson <jtrulson@ics.com>
4e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang *                Brendan le Foll <brendan.le.foll@intel.com>
5e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang * Copyright (c) 2014 - 2015 Intel Corporation.
6e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang *
7e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang * Permission is hereby granted, free of charge, to any person obtaining
8e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang * a copy of this software and associated documentation files (the
9e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang * "Software"), to deal in the Software without restriction, including
10e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang * without limitation the rights to use, copy, modify, merge, publish,
11e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang * distribute, sublicense, and/or sell copies of the Software, and to
12e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang * permit persons to whom the Software is furnished to do so, subject to
13e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang * the following conditions:
14e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang *
15e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang * The above copyright notice and this permission notice shall be
16e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang * included in all copies or substantial portions of the Software.
17e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang *
18e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
19e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
21e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
22e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
23e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
24e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang */
26e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang
27e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang#include <stdlib.h>
28e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang#include <sys/stat.h>
29e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang#include <unistd.h>
30e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang#include <string.h>
31e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang#include <termios.h>
32e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang
33e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang#include "uart.h"
34e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang#include "mraa_internal.h"
35e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang
36e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang// This function takes an unsigned int and converts it to a B* speed_t
37e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang// that can be used with linux/posix termios
38e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhangstatic speed_t
39e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhanguint2speed(unsigned int speed)
40e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang{
41e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    switch (speed) {
42e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang        case 0:
43e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang            return B0; // hangup, not too useful otherwise
44e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang        case 50:
45e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang            return B50;
46e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang        case 75:
47e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang            return B75;
48e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang        case 110:
49e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang            return B110;
50e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang        case 150:
51e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang            return B150;
52e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang        case 200:
53e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang            return B200;
54e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang        case 300:
55e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang            return B300;
56e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang        case 600:
57e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang            return B600;
58e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang        case 1200:
59e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang            return B1200;
60e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang        case 1800:
61e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang            return B1800;
62e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang        case 2400:
63e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang            return B2400;
64e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang        case 4800:
65e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang            return B4800;
66e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang        case 9600:
67e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang            return B9600;
68e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang        case 19200:
69e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang            return B19200;
70e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang        case 38400:
71e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang            return B38400;
72e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang        case 57600:
73e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang            return B57600;
74e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang        case 115200:
75e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang            return B115200;
76e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang        case 230400:
77e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang            return B230400;
78e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang        case 460800:
79e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang            return B460800;
80e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang        case 500000:
81e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang            return B500000;
82e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang        case 576000:
83e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang            return B576000;
84e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang        case 921600:
85e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang            return B921600;
86e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang        case 1000000:
87e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang            return B1000000;
88e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang        case 1152000:
89e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang            return B1152000;
90e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang        case 1500000:
91e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang            return B1500000;
92e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang        case 2000000:
93e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang            return B2000000;
94e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang        case 2500000:
95e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang            return B2500000;
96e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang        case 3000000:
97e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang            return B3000000;
98e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang        case 3500000:
99e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang            return B3500000;
100e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang        case 4000000:
101e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang            return B4000000;
102e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang        default:
103e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang            // if we are here, then an unsupported baudrate was selected.
104e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang            // Report it via syslog and return B9600, a common default.
105e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang            syslog(LOG_ERR, "uart: unsupported baud rate, defaulting to 9600.");
106e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang            return B9600;
107e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    }
108e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang}
109e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang
110e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhangstatic mraa_uart_context
111e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhangmraa_uart_init_internal(mraa_adv_func_t* func_table)
112e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang{
113e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    mraa_uart_context dev = (mraa_uart_context) calloc(1, sizeof(struct _uart));
114e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    if (dev == NULL) {
115e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang        syslog(LOG_CRIT, "uart: Failed to allocate memory for context");
116e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang        return NULL;
117e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    }
118e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    dev->index = -1;
119e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    dev->fd = -1;
120e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    dev->advance_func = func_table;
121e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang
122e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    return dev;
123e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang}
124e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang
125e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhangmraa_uart_context
126e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhangmraa_uart_init(int index)
127e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang{
128e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    if (plat == NULL) {
129e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang        syslog(LOG_ERR, "uart: platform not initialised");
130e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang        return NULL;
131e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    }
132e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang
133e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    if (mraa_is_sub_platform_id(index)) {
1347d3978fad94b70b4cb0dba9231b30870022f8563Mihai Serban        syslog(LOG_NOTICE, "uart: Using sub platform is not supported");
135e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang        return NULL;
136e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    }
137e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang
138e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    if (plat->adv_func->uart_init_pre != NULL) {
139e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang        if (plat->adv_func->uart_init_pre(index) != MRAA_SUCCESS) {
140e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang            syslog(LOG_ERR, "uart: failure in pre-init platform hook");
141e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang            return NULL;
142e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang        }
143e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    }
144e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang
145e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    if (plat->uart_dev_count == 0) {
146e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang        syslog(LOG_ERR, "uart: platform has no UARTs defined");
147e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang        return NULL;
148e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    }
149e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang
150e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    if (plat->uart_dev_count <= index) {
151e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang        syslog(LOG_ERR, "uart: platform has only %i", plat->uart_dev_count);
152e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang        return NULL;
153e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    }
154e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang
1556b1611a178516c059b80b1fecb9bbea070a00d0dBruce Beare    if (!plat->no_bus_mux) {
1566b1611a178516c059b80b1fecb9bbea070a00d0dBruce Beare        int pos = plat->uart_dev[index].rx;
1576b1611a178516c059b80b1fecb9bbea070a00d0dBruce Beare        if (pos >= 0) {
1586b1611a178516c059b80b1fecb9bbea070a00d0dBruce Beare            if (plat->pins[pos].uart.mux_total > 0) {
1596b1611a178516c059b80b1fecb9bbea070a00d0dBruce Beare                if (mraa_setup_mux_mapped(plat->pins[pos].uart) != MRAA_SUCCESS) {
1606b1611a178516c059b80b1fecb9bbea070a00d0dBruce Beare                    syslog(LOG_ERR, "uart: failed to setup muxes for RX pin");
1616b1611a178516c059b80b1fecb9bbea070a00d0dBruce Beare                    return NULL;
1626b1611a178516c059b80b1fecb9bbea070a00d0dBruce Beare                }
163e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang            }
164e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang        }
165e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang
1666b1611a178516c059b80b1fecb9bbea070a00d0dBruce Beare        pos = plat->uart_dev[index].tx;
1676b1611a178516c059b80b1fecb9bbea070a00d0dBruce Beare        if (pos >= 0) {
1686b1611a178516c059b80b1fecb9bbea070a00d0dBruce Beare            if (plat->pins[pos].uart.mux_total > 0) {
1696b1611a178516c059b80b1fecb9bbea070a00d0dBruce Beare                if (mraa_setup_mux_mapped(plat->pins[pos].uart) != MRAA_SUCCESS) {
1706b1611a178516c059b80b1fecb9bbea070a00d0dBruce Beare                    syslog(LOG_ERR, "uart: failed to setup muxes for TX pin");
1716b1611a178516c059b80b1fecb9bbea070a00d0dBruce Beare                    return NULL;
1726b1611a178516c059b80b1fecb9bbea070a00d0dBruce Beare                }
173e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang            }
174e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang        }
175e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    }
176e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang
177e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    mraa_uart_context dev = mraa_uart_init_raw((char*)plat->uart_dev[index].device_path);
178e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    if (dev == NULL) {
179e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang        return NULL;
180e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    }
181e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    dev->index = index; //Set the board Index.
182e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang
183e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    if (IS_FUNC_DEFINED(dev, uart_init_post)) {
184e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang        mraa_result_t ret = dev->advance_func->uart_init_post(dev);
185e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang        if (ret != MRAA_SUCCESS) {
186e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang            free(dev);
187e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang            return NULL;
188e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang        }
189e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    }
190e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang
191e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    return dev;
192e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang}
193e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang
194e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhangmraa_uart_context
195e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhangmraa_uart_init_raw(const char* path)
196e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang{
197e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    mraa_uart_context dev = mraa_uart_init_internal(plat == NULL ? NULL : plat->adv_func);
198e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    if (dev == NULL) {
199e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang        syslog(LOG_ERR, "uart: Failed to allocate memory for context");
200e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang        return NULL;
201e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    }
202e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    dev->path = path;
203e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang
204e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    if (!dev->path) {
205e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang        syslog(LOG_ERR, "uart: device path undefined, open failed");
206e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang        free(dev);
207e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang        return NULL;
208e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    }
209e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang
210e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    // now open the device
211e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    if ((dev->fd = open(dev->path, O_RDWR)) == -1) {
212e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang        syslog(LOG_ERR, "uart: open() failed");
213e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang        free(dev);
214e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang        return NULL;
215e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    }
216e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang
217e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    // now setup the tty and the selected baud rate
218e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    struct termios termio;
219e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang
220e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    // get current modes
221e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    if (tcgetattr(dev->fd, &termio)) {
222e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang        syslog(LOG_ERR, "uart: tcgetattr() failed");
223e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang        close(dev->fd);
224e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang        free(dev);
225e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang        return NULL;
226e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    }
227e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang
228e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    // setup for a 'raw' mode.  8N1, no echo or special character
229e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    // handling, such as flow control or line editing semantics.
230e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    // cfmakeraw is not POSIX!
231e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    cfmakeraw(&termio);
232e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    if (tcsetattr(dev->fd, TCSAFLUSH, &termio) < 0) {
233e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang        syslog(LOG_ERR, "uart: tcsetattr() failed after cfmakeraw()");
234e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang        close(dev->fd);
235e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang        free(dev);
236e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang        return NULL;
237e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    }
238e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang
239e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    if (mraa_uart_set_baudrate(dev, 9600) != MRAA_SUCCESS) {
240e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang        close(dev->fd);
241e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang        free(dev);
242e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang        return NULL;
243e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    }
244e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang
245e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    return dev;
246e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang}
247e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang
248e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhangmraa_result_t
249e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhangmraa_uart_stop(mraa_uart_context dev)
250e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang{
251e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    if (!dev) {
252e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang        syslog(LOG_ERR, "uart: stop: context is NULL");
253e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang        return MRAA_ERROR_INVALID_HANDLE;
254e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    }
255e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang
256e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    // just close the device and reset our fd.
257e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    if (dev->fd >= 0) {
258e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang        close(dev->fd);
259e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    }
260e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang
261e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    free(dev);
262e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang
263e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    return MRAA_SUCCESS;
264e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang}
265e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang
266e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhangmraa_result_t
267e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhangmraa_uart_flush(mraa_uart_context dev)
268e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang{
269e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    if (!dev) {
270e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang        syslog(LOG_ERR, "uart: stop: context is NULL");
271e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang        return MRAA_ERROR_INVALID_HANDLE;
272e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    }
273e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang
274e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    if (tcdrain(dev->fd) == -1) {
275e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang        return MRAA_ERROR_FEATURE_NOT_SUPPORTED;
276e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    }
277e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang
278e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    return MRAA_SUCCESS;
279e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang}
280e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang
281e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhangmraa_result_t
282e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhangmraa_uart_set_baudrate(mraa_uart_context dev, unsigned int baud)
283e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang{
284e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    if (!dev) {
285e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang        syslog(LOG_ERR, "uart: stop: context is NULL");
286e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang        return MRAA_ERROR_INVALID_HANDLE;
287e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    }
288e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang
289e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    struct termios termio;
290e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    if (tcgetattr(dev->fd, &termio)) {
291e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang        syslog(LOG_ERR, "uart: tcgetattr() failed");
292e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang        return MRAA_ERROR_INVALID_HANDLE;
293e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    }
294e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang
295e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    // set our baud rates
296e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    speed_t speed = uint2speed(baud);
297e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    cfsetispeed(&termio, speed);
298e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    cfsetospeed(&termio, speed);
299e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang
300e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    // make it so
301e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    if (tcsetattr(dev->fd, TCSAFLUSH, &termio) < 0) {
302e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang        syslog(LOG_ERR, "uart: tcsetattr() failed");
303e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang        return MRAA_ERROR_FEATURE_NOT_SUPPORTED;
304e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    }
305e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    return MRAA_SUCCESS;
306e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang}
307e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang
308e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhangmraa_result_t
309e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhangmraa_uart_set_mode(mraa_uart_context dev, int bytesize, mraa_uart_parity_t parity, int stopbits)
310e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang{
311e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    if (!dev) {
312e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang        syslog(LOG_ERR, "uart: stop: context is NULL");
313e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang        return MRAA_ERROR_INVALID_HANDLE;
314e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    }
315e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang
316e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    struct termios termio;
317e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    if (tcgetattr(dev->fd, &termio)) {
318e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang        syslog(LOG_ERR, "uart: tcgetattr() failed");
319e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang        return MRAA_ERROR_INVALID_HANDLE;
320e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    }
321e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang
322e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    termio.c_cflag &= ~CSIZE;
323e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    switch (bytesize) {
324e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang        case 8:
325e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang            termio.c_cflag |= CS8;
326e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang            break;
327e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang        case 7:
328e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang            termio.c_cflag |= CS7;
329e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang            break;
330e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang        case 6:
331e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang            termio.c_cflag |= CS6;
332e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang            break;
333e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang        case 5:
334e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang            termio.c_cflag |= CS5;
335e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang            break;
336e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang        default:
337e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang            termio.c_cflag |= CS8;
338e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang            break;
339e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    }
340e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang
341e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    // POSIX & linux doesn't support 1.5 and I've got bigger fish to fry
342e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    switch (stopbits) {
343e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang        case 1:
344e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang            termio.c_cflag &= ~CSTOPB;
345e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang            break;
346e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang        case 2:
347e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang            termio.c_cflag |= CSTOPB;
348e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang        default:
349e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang            break;
350e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    }
351e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang
352e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    switch (parity) {
353e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang        case MRAA_UART_PARITY_NONE:
354e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang            termio.c_cflag &= ~(PARENB | PARODD);
355e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang            break;
356e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang        case MRAA_UART_PARITY_EVEN:
3577d3978fad94b70b4cb0dba9231b30870022f8563Mihai Serban            termio.c_cflag |= PARENB;
358e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang            termio.c_cflag &= ~PARODD;
359e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang            break;
360e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang        case MRAA_UART_PARITY_ODD:
361e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang            termio.c_cflag |= PARENB | PARODD;
362e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang            break;
363e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang        case MRAA_UART_PARITY_MARK: // not POSIX
364e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang            termio.c_cflag |= PARENB | CMSPAR | PARODD;
365e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang            break;
366e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang        case MRAA_UART_PARITY_SPACE: // not POSIX
367e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang            termio.c_cflag |= PARENB | CMSPAR;
368e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang            termio.c_cflag &= ~PARODD;
369e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang            break;
370e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    }
371e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang
372e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    if (tcsetattr(dev->fd, TCSAFLUSH, &termio) < 0) {
373e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang        syslog(LOG_ERR, "uart: tcsetattr() failed");
374e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang        return MRAA_ERROR_FEATURE_NOT_SUPPORTED;
375e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    }
376e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang
377e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    return MRAA_SUCCESS;
378e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang}
379e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang
380e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhangmraa_result_t
381e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhangmraa_uart_set_flowcontrol(mraa_uart_context dev, mraa_boolean_t xonxoff, mraa_boolean_t rtscts)
382e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang{
383e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    if (!dev) {
384e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang        syslog(LOG_ERR, "uart: stop: context is NULL");
385e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang        return MRAA_ERROR_INVALID_HANDLE;
386e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    }
387e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang
388e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    // hardware flow control
389e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    int action = TCIOFF;
390e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    if (xonxoff) {
391e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang        action = TCION;
392e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    }
393e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    if (tcflow(dev->fd, action)) {
394e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang        return MRAA_ERROR_FEATURE_NOT_SUPPORTED;
395e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    }
396e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang
397e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    // rtscts
398e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    struct termios termio;
399e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang
400e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    // get current modes
401e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    if (tcgetattr(dev->fd, &termio)) {
402e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang        syslog(LOG_ERR, "uart: tcgetattr() failed");
403e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang        return MRAA_ERROR_INVALID_HANDLE;
404e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    }
405e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang
406e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    if (rtscts) {
407e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang        termio.c_cflag |= CRTSCTS;
408e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    } else {
409e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang        termio.c_cflag &= ~CRTSCTS;
410e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    }
411e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang
412e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    if (tcsetattr(dev->fd, TCSAFLUSH, &termio) < 0) {
413e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang        syslog(LOG_ERR, "uart: tcsetattr() failed");
414e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang        return MRAA_ERROR_FEATURE_NOT_SUPPORTED;
415e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    }
416e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang
417e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    return MRAA_SUCCESS;
418e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang}
419e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang
420e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhangmraa_result_t
421e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhangmraa_uart_set_timeout(mraa_uart_context dev, int read, int write, int interchar)
422e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang{
423e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    if (!dev) {
424e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang        syslog(LOG_ERR, "uart: stop: context is NULL");
425e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang        return MRAA_ERROR_INVALID_HANDLE;
426e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    }
427e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang
4286b1611a178516c059b80b1fecb9bbea070a00d0dBruce Beare    struct termios termio;
4296b1611a178516c059b80b1fecb9bbea070a00d0dBruce Beare    // get current modes
4306b1611a178516c059b80b1fecb9bbea070a00d0dBruce Beare    if (tcgetattr(dev->fd, &termio)) {
4316b1611a178516c059b80b1fecb9bbea070a00d0dBruce Beare        syslog(LOG_ERR, "uart: tcgetattr() failed");
4326b1611a178516c059b80b1fecb9bbea070a00d0dBruce Beare        return MRAA_ERROR_FEATURE_NOT_SUPPORTED;
4336b1611a178516c059b80b1fecb9bbea070a00d0dBruce Beare    }
4346b1611a178516c059b80b1fecb9bbea070a00d0dBruce Beare    if (read > 0) {
4356b1611a178516c059b80b1fecb9bbea070a00d0dBruce Beare        read = read / 100;
4366b1611a178516c059b80b1fecb9bbea070a00d0dBruce Beare        if (read == 0)
4376b1611a178516c059b80b1fecb9bbea070a00d0dBruce Beare            read = 1;
4386b1611a178516c059b80b1fecb9bbea070a00d0dBruce Beare    }
4396b1611a178516c059b80b1fecb9bbea070a00d0dBruce Beare    termio.c_lflag &= ~ICANON; /* Set non-canonical mode */
4406b1611a178516c059b80b1fecb9bbea070a00d0dBruce Beare    termio.c_cc[VTIME] = read; /* Set timeout in tenth seconds */
4416b1611a178516c059b80b1fecb9bbea070a00d0dBruce Beare    if (tcsetattr(dev->fd, TCSANOW, &termio) < 0) {
4426b1611a178516c059b80b1fecb9bbea070a00d0dBruce Beare        syslog(LOG_ERR, "uart: tcsetattr() failed");
4436b1611a178516c059b80b1fecb9bbea070a00d0dBruce Beare        return MRAA_ERROR_FEATURE_NOT_SUPPORTED;
4446b1611a178516c059b80b1fecb9bbea070a00d0dBruce Beare    }
4456b1611a178516c059b80b1fecb9bbea070a00d0dBruce Beare
4466b1611a178516c059b80b1fecb9bbea070a00d0dBruce Beare    return MRAA_SUCCESS;
447e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang}
448e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang
449e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhangconst char*
450e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhangmraa_uart_get_dev_path(mraa_uart_context dev)
451e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang{
452e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    if (!dev) {
453e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang        syslog(LOG_ERR, "uart: get_device_path failed, context is NULL");
454e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang        return NULL;
455e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    }
456e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    if (dev->path == NULL) {
457e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang        syslog(LOG_ERR, "uart: device path undefined");
458e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang        return NULL;
459e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    }
460e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang
461e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    return dev->path;
462e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang}
463e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang
464e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhangint
465e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhangmraa_uart_read(mraa_uart_context dev, char* buf, size_t len)
466e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang{
467e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    if (!dev) {
468e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang        syslog(LOG_ERR, "uart: read: context is NULL");
469e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang        return MRAA_ERROR_INVALID_HANDLE;
470e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    }
471e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang
472e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    if (dev->fd < 0) {
473e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang        syslog(LOG_ERR, "uart: port is not open");
474e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang        return MRAA_ERROR_INVALID_RESOURCE;
475e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    }
476e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang
477e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    return read(dev->fd, buf, len);
478e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang}
479e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang
480e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhangint
481e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhangmraa_uart_write(mraa_uart_context dev, const char* buf, size_t len)
482e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang{
483e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    if (!dev) {
484e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang        syslog(LOG_ERR, "uart: write: context is NULL");
485e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang        return MRAA_ERROR_INVALID_HANDLE;
486e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    }
487e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang
488e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    if (dev->fd < 0) {
489e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang        syslog(LOG_ERR, "uart: port is not open");
490e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang        return MRAA_ERROR_INVALID_RESOURCE;
491e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    }
492e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang
493e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    return write(dev->fd, buf, len);
494e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang}
495e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang
496e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhangmraa_boolean_t
497e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhangmraa_uart_data_available(mraa_uart_context dev, unsigned int millis)
498e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang{
499e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    if (!dev) {
500e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang        syslog(LOG_ERR, "uart: data_available: write context is NULL");
501e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang        return 0;
502e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    }
503e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang
504e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    if (dev->fd < 0) {
505e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang        syslog(LOG_ERR, "uart: port is not open");
506e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang        return 0;
507e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    }
508e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang
509e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    struct timeval timeout;
510e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang
511e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    if (millis == 0) {
512e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang        // no waiting
513e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang        timeout.tv_sec = 0;
514e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang        timeout.tv_usec = 0;
515e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    } else {
516e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang        timeout.tv_sec = millis / 1000;
517e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang        timeout.tv_usec = (millis % 1000) * 1000;
518e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    }
519e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang
520e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    fd_set readfds;
521e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang
522e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    FD_ZERO(&readfds);
523e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    FD_SET(dev->fd, &readfds);
524e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang
525e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    if (select(dev->fd + 1, &readfds, NULL, NULL, &timeout) > 0) {
526e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang        return 1; // data is ready
527e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    } else {
528e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang        return 0;
529e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang    }
530e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang}
531e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang
532e595125fe2f8ed6af763b9da7cfd817f576958dcJianxun Zhang
533