1 | /* |
2 | * This file is part of the MicroPython project, http://micropython.org/ |
3 | * |
4 | * The MIT License (MIT) |
5 | * |
6 | * Copyright (c) 2014-2015 Paul Sokolovsky |
7 | * |
8 | * Permission is hereby granted, free of charge, to any person obtaining a copy |
9 | * of this software and associated documentation files (the "Software"), to deal |
10 | * in the Software without restriction, including without limitation the rights |
11 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
12 | * copies of the Software, and to permit persons to whom the Software is |
13 | * furnished to do so, subject to the following conditions: |
14 | * |
15 | * The above copyright notice and this permission notice shall be included in |
16 | * all copies or substantial portions of the Software. |
17 | * |
18 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
19 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
20 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
21 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
22 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
23 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN |
24 | * THE SOFTWARE. |
25 | */ |
26 | |
27 | #include <sys/types.h> |
28 | #include <termios.h> |
29 | #include <unistd.h> |
30 | #include <errno.h> |
31 | |
32 | #include "py/objlist.h" |
33 | #include "py/runtime.h" |
34 | #include "py/mphal.h" |
35 | |
36 | STATIC mp_obj_t mod_termios_tcgetattr(mp_obj_t fd_in) { |
37 | struct termios term; |
38 | int fd = mp_obj_get_int(fd_in); |
39 | |
40 | int res = tcgetattr(fd, &term); |
41 | RAISE_ERRNO(res, errno); |
42 | |
43 | mp_obj_list_t *r = MP_OBJ_TO_PTR(mp_obj_new_list(7, NULL)); |
44 | r->items[0] = MP_OBJ_NEW_SMALL_INT(term.c_iflag); |
45 | r->items[1] = MP_OBJ_NEW_SMALL_INT(term.c_oflag); |
46 | r->items[2] = MP_OBJ_NEW_SMALL_INT(term.c_cflag); |
47 | r->items[3] = MP_OBJ_NEW_SMALL_INT(term.c_lflag); |
48 | r->items[4] = MP_OBJ_NEW_SMALL_INT(cfgetispeed(&term)); |
49 | r->items[5] = MP_OBJ_NEW_SMALL_INT(cfgetospeed(&term)); |
50 | |
51 | mp_obj_list_t *cc = MP_OBJ_TO_PTR(mp_obj_new_list(NCCS, NULL)); |
52 | r->items[6] = MP_OBJ_FROM_PTR(cc); |
53 | for (int i = 0; i < NCCS; i++) { |
54 | if (i == VMIN || i == VTIME) { |
55 | cc->items[i] = MP_OBJ_NEW_SMALL_INT(term.c_cc[i]); |
56 | } else { |
57 | // https://docs.python.org/3/library/termios.html says value is *string*, |
58 | // but no way unicode chars could be there, if c_cc is defined to be a |
59 | // a "char". But it's type is actually cc_t, which can be anything. |
60 | // TODO: For now, we still deal with it like that. |
61 | cc->items[i] = mp_obj_new_bytes((byte *)&term.c_cc[i], 1); |
62 | } |
63 | } |
64 | return MP_OBJ_FROM_PTR(r); |
65 | } |
66 | STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_termios_tcgetattr_obj, mod_termios_tcgetattr); |
67 | |
68 | STATIC mp_obj_t mod_termios_tcsetattr(mp_obj_t fd_in, mp_obj_t when_in, mp_obj_t attrs_in) { |
69 | struct termios term; |
70 | int fd = mp_obj_get_int(fd_in); |
71 | int when = mp_obj_get_int(when_in); |
72 | if (when == 0) { |
73 | // We don't export TCSANOW and friends to save on code space. Then |
74 | // common lazy sense says that passing 0 should be godo enough, and |
75 | // it is e.g. for glibc. But for other libc's it's not, so set just |
76 | // treat 0 as defauling to TCSANOW. |
77 | when = TCSANOW; |
78 | } |
79 | |
80 | assert(mp_obj_is_type(attrs_in, &mp_type_list)); |
81 | mp_obj_list_t *attrs = MP_OBJ_TO_PTR(attrs_in); |
82 | |
83 | term.c_iflag = mp_obj_get_int(attrs->items[0]); |
84 | term.c_oflag = mp_obj_get_int(attrs->items[1]); |
85 | term.c_cflag = mp_obj_get_int(attrs->items[2]); |
86 | term.c_lflag = mp_obj_get_int(attrs->items[3]); |
87 | |
88 | mp_obj_list_t *cc = MP_OBJ_TO_PTR(attrs->items[6]); |
89 | for (int i = 0; i < NCCS; i++) { |
90 | if (i == VMIN || i == VTIME) { |
91 | term.c_cc[i] = mp_obj_get_int(cc->items[i]); |
92 | } else { |
93 | term.c_cc[i] = *mp_obj_str_get_str(cc->items[i]); |
94 | } |
95 | } |
96 | |
97 | int res = cfsetispeed(&term, mp_obj_get_int(attrs->items[4])); |
98 | RAISE_ERRNO(res, errno); |
99 | res = cfsetospeed(&term, mp_obj_get_int(attrs->items[5])); |
100 | RAISE_ERRNO(res, errno); |
101 | |
102 | res = tcsetattr(fd, when, &term); |
103 | RAISE_ERRNO(res, errno); |
104 | return mp_const_none; |
105 | } |
106 | STATIC MP_DEFINE_CONST_FUN_OBJ_3(mod_termios_tcsetattr_obj, mod_termios_tcsetattr); |
107 | |
108 | STATIC mp_obj_t mod_termios_setraw(mp_obj_t fd_in) { |
109 | struct termios term; |
110 | int fd = mp_obj_get_int(fd_in); |
111 | int res = tcgetattr(fd, &term); |
112 | RAISE_ERRNO(res, errno); |
113 | |
114 | term.c_iflag &= ~(BRKINT | ICRNL | INPCK | ISTRIP | IXON); |
115 | term.c_oflag = 0; |
116 | term.c_cflag = (term.c_cflag & ~(CSIZE | PARENB)) | CS8; |
117 | term.c_lflag = 0; |
118 | term.c_cc[VMIN] = 1; |
119 | term.c_cc[VTIME] = 0; |
120 | res = tcsetattr(fd, TCSAFLUSH, &term); |
121 | RAISE_ERRNO(res, errno); |
122 | return mp_const_none; |
123 | } |
124 | STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_termios_setraw_obj, mod_termios_setraw); |
125 | |
126 | STATIC const mp_rom_map_elem_t mp_module_termios_globals_table[] = { |
127 | { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_termios) }, |
128 | { MP_ROM_QSTR(MP_QSTR_tcgetattr), MP_ROM_PTR(&mod_termios_tcgetattr_obj) }, |
129 | { MP_ROM_QSTR(MP_QSTR_tcsetattr), MP_ROM_PTR(&mod_termios_tcsetattr_obj) }, |
130 | { MP_ROM_QSTR(MP_QSTR_setraw), MP_ROM_PTR(&mod_termios_setraw_obj) }, |
131 | |
132 | #define C(name) { MP_ROM_QSTR(MP_QSTR_##name), MP_ROM_INT(name) } |
133 | C(TCSANOW), |
134 | |
135 | C(B9600), |
136 | #ifdef B57600 |
137 | C(B57600), |
138 | #endif |
139 | #ifdef B115200 |
140 | C(B115200), |
141 | #endif |
142 | #undef C |
143 | }; |
144 | |
145 | STATIC MP_DEFINE_CONST_DICT(mp_module_termios_globals, mp_module_termios_globals_table); |
146 | |
147 | const mp_obj_module_t mp_module_termios = { |
148 | .base = { &mp_type_module }, |
149 | .globals = (mp_obj_dict_t *)&mp_module_termios_globals, |
150 | }; |
151 | |