summaryrefslogtreecommitdiff
path: root/ports/unix/unix_mphal.c
diff options
context:
space:
mode:
Diffstat (limited to 'ports/unix/unix_mphal.c')
-rw-r--r--ports/unix/unix_mphal.c199
1 files changed, 199 insertions, 0 deletions
diff --git a/ports/unix/unix_mphal.c b/ports/unix/unix_mphal.c
new file mode 100644
index 000000000..02cdbea11
--- /dev/null
+++ b/ports/unix/unix_mphal.c
@@ -0,0 +1,199 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2015 Damien P. George
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include <unistd.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/time.h>
+
+#include "py/mpstate.h"
+#include "py/mphal.h"
+#include "py/runtime.h"
+#include "extmod/misc.h"
+
+#ifndef _WIN32
+#include <signal.h>
+
+STATIC void sighandler(int signum) {
+ if (signum == SIGINT) {
+ #if MICROPY_ASYNC_KBD_INTR
+ mp_obj_exception_clear_traceback(MP_OBJ_FROM_PTR(&MP_STATE_VM(mp_kbd_exception)));
+ sigset_t mask;
+ sigemptyset(&mask);
+ // On entry to handler, its signal is blocked, and unblocked on
+ // normal exit. As we instead perform longjmp, unblock it manually.
+ sigprocmask(SIG_SETMASK, &mask, NULL);
+ nlr_raise(MP_OBJ_FROM_PTR(&MP_STATE_VM(mp_kbd_exception)));
+ #else
+ if (MP_STATE_VM(mp_pending_exception) == MP_OBJ_FROM_PTR(&MP_STATE_VM(mp_kbd_exception))) {
+ // this is the second time we are called, so die straight away
+ exit(1);
+ }
+ mp_obj_exception_clear_traceback(MP_OBJ_FROM_PTR(&MP_STATE_VM(mp_kbd_exception)));
+ MP_STATE_VM(mp_pending_exception) = MP_OBJ_FROM_PTR(&MP_STATE_VM(mp_kbd_exception));
+ #endif
+ }
+}
+#endif
+
+void mp_hal_set_interrupt_char(char c) {
+ // configure terminal settings to (not) let ctrl-C through
+ if (c == CHAR_CTRL_C) {
+ #ifndef _WIN32
+ // enable signal handler
+ struct sigaction sa;
+ sa.sa_flags = 0;
+ sa.sa_handler = sighandler;
+ sigemptyset(&sa.sa_mask);
+ sigaction(SIGINT, &sa, NULL);
+ #endif
+ } else {
+ #ifndef _WIN32
+ // disable signal handler
+ struct sigaction sa;
+ sa.sa_flags = 0;
+ sa.sa_handler = SIG_DFL;
+ sigemptyset(&sa.sa_mask);
+ sigaction(SIGINT, &sa, NULL);
+ #endif
+ }
+}
+
+#if MICROPY_USE_READLINE == 1
+
+#include <termios.h>
+
+static struct termios orig_termios;
+
+void mp_hal_stdio_mode_raw(void) {
+ // save and set terminal settings
+ tcgetattr(0, &orig_termios);
+ static struct termios termios;
+ termios = orig_termios;
+ termios.c_iflag &= ~(BRKINT | ICRNL | INPCK | ISTRIP | IXON);
+ termios.c_cflag = (termios.c_cflag & ~(CSIZE | PARENB)) | CS8;
+ termios.c_lflag = 0;
+ termios.c_cc[VMIN] = 1;
+ termios.c_cc[VTIME] = 0;
+ tcsetattr(0, TCSAFLUSH, &termios);
+}
+
+void mp_hal_stdio_mode_orig(void) {
+ // restore terminal settings
+ tcsetattr(0, TCSAFLUSH, &orig_termios);
+}
+
+#endif
+
+#if MICROPY_PY_OS_DUPTERM
+static int call_dupterm_read(void) {
+ nlr_buf_t nlr;
+ if (nlr_push(&nlr) == 0) {
+ mp_obj_t read_m[3];
+ mp_load_method(MP_STATE_PORT(term_obj), MP_QSTR_read, read_m);
+ read_m[2] = MP_OBJ_NEW_SMALL_INT(1);
+ mp_obj_t res = mp_call_method_n_kw(1, 0, read_m);
+ if (res == mp_const_none) {
+ return -2;
+ }
+ mp_buffer_info_t bufinfo;
+ mp_get_buffer_raise(res, &bufinfo, MP_BUFFER_READ);
+ if (bufinfo.len == 0) {
+ mp_printf(&mp_plat_print, "dupterm: EOF received, deactivating\n");
+ MP_STATE_PORT(term_obj) = NULL;
+ return -1;
+ }
+ nlr_pop();
+ return *(byte*)bufinfo.buf;
+ } else {
+ // Temporarily disable dupterm to avoid infinite recursion
+ mp_obj_t save_term = MP_STATE_PORT(term_obj);
+ MP_STATE_PORT(term_obj) = NULL;
+ mp_printf(&mp_plat_print, "dupterm: ");
+ mp_obj_print_exception(&mp_plat_print, nlr.ret_val);
+ MP_STATE_PORT(term_obj) = save_term;
+ }
+
+ return -1;
+}
+#endif
+
+int mp_hal_stdin_rx_chr(void) {
+ unsigned char c;
+#if MICROPY_PY_OS_DUPTERM
+ if (MP_STATE_PORT(term_obj) != MP_OBJ_NULL) {
+ int c;
+ do {
+ c = call_dupterm_read();
+ } while (c == -2);
+ if (c == -1) {
+ goto main_term;
+ }
+ if (c == '\n') {
+ c = '\r';
+ }
+ return c;
+ } else {
+ main_term:;
+#endif
+ int ret = read(0, &c, 1);
+ if (ret == 0) {
+ c = 4; // EOF, ctrl-D
+ } else if (c == '\n') {
+ c = '\r';
+ }
+ return c;
+#if MICROPY_PY_OS_DUPTERM
+ }
+#endif
+}
+
+void mp_hal_stdout_tx_strn(const char *str, size_t len) {
+ int ret = write(1, str, len);
+ mp_uos_dupterm_tx_strn(str, len);
+ (void)ret; // to suppress compiler warning
+}
+
+// cooked is same as uncooked because the terminal does some postprocessing
+void mp_hal_stdout_tx_strn_cooked(const char *str, size_t len) {
+ mp_hal_stdout_tx_strn(str, len);
+}
+
+void mp_hal_stdout_tx_str(const char *str) {
+ mp_hal_stdout_tx_strn(str, strlen(str));
+}
+
+mp_uint_t mp_hal_ticks_ms(void) {
+ struct timeval tv;
+ gettimeofday(&tv, NULL);
+ return tv.tv_sec * 1000 + tv.tv_usec / 1000;
+}
+
+mp_uint_t mp_hal_ticks_us(void) {
+ struct timeval tv;
+ gettimeofday(&tv, NULL);
+ return tv.tv_sec * 1000000 + tv.tv_usec;
+}