forked from RIOT-OS/RIOT
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request RIOT-OS#4443 from Yonezawa-T2/native_tty_uart
native: add UART driver based on /dev/tty
- Loading branch information
Showing
13 changed files
with
637 additions
and
87 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,160 @@ | ||
/** | ||
* Multiple asynchronus read on file descriptors | ||
* | ||
* Copyright (C) 2015 Ludwig Knüpfer <[email protected]>, | ||
* Martine Lenders <[email protected]> | ||
* Kaspar Schleiser <[email protected]> | ||
* Ell-i open source co-operative | ||
* Takuo Yonezawa <[email protected]> | ||
* | ||
* This file is subject to the terms and conditions of the GNU Lesser | ||
* General Public License v2.1. See the file LICENSE in the top level | ||
* directory for more details. | ||
* | ||
* @ingroup native_cpu | ||
* @{ | ||
* @file | ||
* @author Takuo Yonezawa <[email protected]> | ||
*/ | ||
|
||
#include <err.h> | ||
#include <signal.h> | ||
#include <stdlib.h> | ||
#include <unistd.h> | ||
#include <fcntl.h> | ||
|
||
#include "async_read.h" | ||
#include "native_internal.h" | ||
|
||
static int _next_index; | ||
static int _fds[ASYNC_READ_NUMOF]; | ||
static native_async_read_callback_t _native_async_read_callbacks[ASYNC_READ_NUMOF]; | ||
|
||
#ifdef __MACH__ | ||
static pid_t _sigio_child_pids[ASYNC_READ_NUMOF]; | ||
static void _sigio_child(int fd); | ||
#endif | ||
|
||
static void _async_io_isr(void) { | ||
fd_set rfds; | ||
|
||
FD_ZERO(&rfds); | ||
|
||
int max_fd = 0; | ||
|
||
for (int i = 0; i < _next_index; i++) { | ||
FD_SET(_fds[i], &rfds); | ||
|
||
if (max_fd < _fds[i]) { | ||
max_fd = _fds[i]; | ||
} | ||
} | ||
|
||
if (real_select(max_fd + 1, &rfds, NULL, NULL, NULL) > 0) { | ||
for (int i = 0; i < _next_index; i++) { | ||
if (FD_ISSET(_fds[i], &rfds)) { | ||
_native_async_read_callbacks[i](_fds[i]); | ||
} | ||
} | ||
} | ||
} | ||
|
||
void native_async_read_setup(void) { | ||
register_interrupt(SIGIO, _async_io_isr); | ||
} | ||
|
||
void native_async_read_cleanup(void) { | ||
unregister_interrupt(SIGIO); | ||
|
||
#ifdef __MACH__ | ||
for (int i = 0; i < _next_index; i++) { | ||
kill(_sigio_child_pids[i], SIGKILL); | ||
} | ||
#endif | ||
} | ||
|
||
void native_async_read_continue(int fd) { | ||
(void) fd; | ||
#ifdef __MACH__ | ||
for (int i = 0; i < _next_index; i++) { | ||
if (_fds[i] == fd) { | ||
kill(_sigio_child_pids[i], SIGCONT); | ||
} | ||
} | ||
#endif | ||
} | ||
|
||
void native_async_read_add_handler(int fd, native_async_read_callback_t handler) { | ||
if (_next_index >= ASYNC_READ_NUMOF) { | ||
err(EXIT_FAILURE, "native_async_read_add_handler(): too many callbacks"); | ||
} | ||
|
||
_fds[_next_index] = fd; | ||
_native_async_read_callbacks[_next_index] = handler; | ||
|
||
#ifdef __MACH__ | ||
/* tuntap signalled IO is not working in OSX, | ||
* * check http://sourceforge.net/p/tuntaposx/bugs/17/ */ | ||
_sigio_child(_next_index); | ||
#else | ||
/* configure fds to send signals on io */ | ||
if (fcntl(fd, F_SETOWN, _native_pid) == -1) { | ||
err(EXIT_FAILURE, "native_async_read_add_handler(): fcntl(F_SETOWN)"); | ||
} | ||
/* set file access mode to non-blocking */ | ||
if (fcntl(fd, F_SETFL, O_NONBLOCK | O_ASYNC) == -1) { | ||
err(EXIT_FAILURE, "native_async_read_add_handler(): fcntl(F_SETFL)"); | ||
} | ||
#endif /* not OSX */ | ||
|
||
_next_index++; | ||
} | ||
|
||
#ifdef __MACH__ | ||
static void _sigio_child(int index) | ||
{ | ||
int fd = _fds[index]; | ||
pid_t parent = _native_pid; | ||
pid_t child; | ||
if ((child = real_fork()) == -1) { | ||
err(EXIT_FAILURE, "sigio_child: fork"); | ||
} | ||
if (child > 0) { | ||
_sigio_child_pids[index] = child; | ||
|
||
/* return in parent process */ | ||
return; | ||
} | ||
|
||
sigset_t sigmask; | ||
|
||
sigemptyset(&sigmask); | ||
sigaddset(&sigmask, SIGCONT); | ||
sigprocmask(SIG_BLOCK, &sigmask, NULL); | ||
|
||
/* watch tap interface and signal parent process if data is | ||
* available */ | ||
fd_set rfds; | ||
while (1) { | ||
FD_ZERO(&rfds); | ||
FD_SET(fd, &rfds); | ||
if (real_select(fd + 1, &rfds, NULL, NULL, NULL) == 1) { | ||
kill(parent, SIGIO); | ||
} | ||
else { | ||
kill(parent, SIGKILL); | ||
err(EXIT_FAILURE, "osx_sigio_child: select"); | ||
} | ||
|
||
/* If SIGCONT is sent before calling pause(), the process stops | ||
* forever, so using sigwait instead. */ | ||
|
||
int sig; | ||
|
||
sigemptyset(&sigmask); | ||
sigaddset(&sigmask, SIGCONT); | ||
sigwait(&sigmask, &sig); | ||
} | ||
} | ||
#endif | ||
/** @} */ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,74 @@ | ||
/* | ||
* Copyright (C) 2015 Takuo Yonezawa <[email protected]> | ||
* | ||
* This file is subject to the terms and conditions of the GNU Lesser General | ||
* Public License v2.1. See the file LICENSE in the top level directory for | ||
* more details. | ||
*/ | ||
|
||
/** | ||
* @ingroup native_cpu | ||
* @{ | ||
* | ||
* @file | ||
* @brief Multiple asynchronus read on file descriptors | ||
* | ||
* @author Takuo Yonezawa <[email protected]> | ||
*/ | ||
#ifndef ASYNC_READ_H | ||
#define ASYNC_READ_H | ||
|
||
#ifdef __cplusplus | ||
extern "C" { | ||
#endif | ||
|
||
/** | ||
* @brief Maximum number of file descriptors | ||
*/ | ||
#ifndef ASYNC_READ_NUMOF | ||
#define ASYNC_READ_NUMOF 2 | ||
#endif | ||
|
||
/** | ||
* @brief asynchronus read callback type | ||
*/ | ||
typedef void (*native_async_read_callback_t)(int fd); | ||
|
||
/** | ||
* @brief initialize asynchronus read system | ||
* | ||
* This registers SIGIO signal handler. | ||
*/ | ||
void native_async_read_setup(void); | ||
|
||
/** | ||
* @brief shutdown asynchronus read system | ||
* | ||
* This deregisters SIGIO signal handler. | ||
*/ | ||
void native_async_read_cleanup(void); | ||
|
||
/** | ||
* @brief resume monitoring of file descriptors | ||
* | ||
* Call this function after reading file descriptors. | ||
* | ||
* @param[in] fd The file descriptor to monitor | ||
*/ | ||
void native_async_read_continue(int fd); | ||
|
||
/** | ||
* @brief start monitoring of file descriptor | ||
* | ||
* @param[in] fd The file descriptor to monitor | ||
* @param[in] handler The callback function to be called when the file | ||
* descriptor is ready to read. | ||
*/ | ||
void native_async_read_add_handler(int fd, native_async_read_callback_t handler); | ||
|
||
#ifdef __cplusplus | ||
} | ||
#endif | ||
|
||
#endif | ||
/** @} */ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
/* | ||
* Copyright (C) 2015 Takuo Yonezawa <[email protected]> | ||
* | ||
* This file is subject to the terms and conditions of the GNU Lesser General | ||
* Public License v2.1. See the file LICENSE in the top level directory for | ||
* more details. | ||
*/ | ||
|
||
/** | ||
* @ingroup native_cpu | ||
* @{ | ||
* | ||
* @file | ||
* @brief UART implementation based on /dev/tty devices on host | ||
* | ||
* @author Takuo Yonezawa <[email protected]> | ||
*/ | ||
|
||
#ifndef TTY_UART_H | ||
#define TTY_UART_H | ||
|
||
#include "periph/uart.h" | ||
|
||
#ifdef __cplusplus | ||
extern "C" { | ||
#endif | ||
|
||
/** | ||
* @brief register /dev/tty device to be used for UART | ||
* | ||
* @param[in] uart UART id | ||
* @param[in] name path name for /dev/tty device | ||
*/ | ||
void tty_uart_setup(uart_t uart, const char *name); | ||
|
||
/** | ||
* @brief closes files opened | ||
*/ | ||
void uart_cleanup(void); | ||
|
||
#ifdef __cplusplus | ||
} | ||
#endif | ||
|
||
#endif | ||
/** @} */ |
Oops, something went wrong.