1 /** 2 * Copyright © 2016 IBM Corporation 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #pragma once 18 19 #include <poll.h> 20 #include <stdbool.h> 21 #include <stdint.h> 22 #include <termios.h> /* for speed_t */ 23 #include <time.h> 24 #include <systemd/sd-bus.h> 25 #include <sys/time.h> 26 #include <sys/un.h> 27 28 struct console; 29 struct config; 30 31 /* Handler API. 32 * 33 * Console data handlers: these implement the functions that process 34 * data coming out of the main tty device. 35 * 36 * Handlers are registered at link time using the console_handler_register() 37 * macro. We call each handler's ->init() function at startup, and ->fini() at 38 * exit. 39 * 40 * Handlers will almost always want to register a ringbuffer consumer, which 41 * provides data coming from the tty. Use cosole_register_ringbuffer_consumer() 42 * for this. To send data to the tty, use console_data_out(). 43 * 44 * If a handler needs to monitor a separate file descriptor for events, use the 45 * poller API, through console_poller_register(). 46 */ 47 struct handler; 48 49 struct handler_type { 50 const char *name; 51 struct handler *(*init)(const struct handler_type *type, 52 struct console *console, struct config *config); 53 void (*fini)(struct handler *handler); 54 int (*baudrate)(struct handler *handler, speed_t baudrate); 55 void (*deselect)(struct handler *handler); 56 }; 57 58 struct handler { 59 const struct handler_type *type; 60 }; 61 62 /* NOLINTBEGIN(bugprone-reserved-identifier,cert-dcl37-c,cert-dcl51-cpp) */ 63 #define __handler_name(n) __handler_##n 64 #define _handler_name(n) __handler_name(n) 65 66 #ifndef __clang__ 67 #define handler_type_check(h) BUILD_ASSERT_OR_ZERO((h)->init && (h)->fini) 68 #else 69 /* clang doesn't seem to be able to constify the type ops */ 70 #define handler_type_check(h) 0 71 #endif 72 73 #define console_handler_register(h) \ 74 static const __attribute__((section("handlers"))) \ 75 __attribute__((used)) struct handler_type * \ 76 _handler_name(__COUNTER__) = (h) + handler_type_check(h) 77 /* NOLINTEND(bugprone-reserved-identifier,cert-dcl37-c,cert-dcl51-cpp) */ 78 79 int console_data_out(struct console *console, const uint8_t *data, size_t len); 80 81 enum poller_ret { 82 POLLER_OK = 0, 83 POLLER_REMOVE, 84 POLLER_EXIT, 85 }; 86 87 typedef char(socket_path_t)[sizeof(((struct sockaddr_un *)NULL)->sun_path)]; 88 89 typedef enum poller_ret (*poller_event_fn_t)(struct handler *handler, 90 int revents, void *data); 91 typedef enum poller_ret (*poller_timeout_fn_t)(struct handler *handler, 92 void *data); 93 94 enum tty_device { 95 TTY_DEVICE_UNDEFINED = 0, 96 TTY_DEVICE_VUART, 97 TTY_DEVICE_UART, 98 TTY_DEVICE_PTY, 99 }; 100 101 struct console_server { 102 struct { 103 const char *kname; 104 char *dev; 105 int fd; 106 enum tty_device type; 107 union { 108 struct { 109 char *sysfs_devnode; 110 int sirq; 111 uint16_t lpc_addr; 112 } vuart; 113 struct { 114 speed_t baud; 115 } uart; 116 }; 117 } tty; 118 119 // All the pollfds are stored here, 120 // so 'poll' can operate on them. 121 // The other 'pollfd*' are just pointers to this array. 122 struct pollfd *pollfds; 123 size_t capacity_pollfds; 124 125 // index into pollfds 126 size_t tty_pollfd_index; 127 128 struct config *config; 129 130 // the currently active console 131 struct console *active; 132 133 struct console **consoles; 134 size_t n_consoles; 135 136 // index into (struct console_server)->pollfds 137 size_t dbus_pollfd_index; 138 139 struct sd_bus *bus; 140 141 // may be NULL in case there is no mux 142 struct console_mux *mux; 143 }; 144 145 struct console { 146 // point back to the console server 147 // which we are a member of 148 struct console_server *server; 149 150 const char *console_id; 151 152 /* Socket name starts with null character hence we need length */ 153 socket_path_t socket_name; 154 ssize_t socket_name_len; 155 156 struct ringbuffer *rb; 157 158 struct handler **handlers; 159 long n_handlers; 160 161 struct poller **pollers; 162 long n_pollers; 163 164 // values to configure the mux 165 unsigned long mux_index; 166 }; 167 168 /* poller API */ 169 struct poller { 170 struct handler *handler; 171 void *data; 172 poller_event_fn_t event_fn; 173 poller_timeout_fn_t timeout_fn; 174 struct timeval timeout; 175 bool remove; 176 177 // index into (struct console_server)->pollfds 178 size_t pollfd_index; 179 }; 180 181 struct poller *console_poller_register(struct console *console, 182 struct handler *handler, 183 poller_event_fn_t poller_fn, 184 poller_timeout_fn_t timeout_fn, int fd, 185 int events, void *data); 186 187 void console_poller_unregister(struct console *console, struct poller *poller); 188 189 void console_poller_set_events(struct console *console, struct poller *poller, 190 int events); 191 192 void console_poller_set_timeout(struct console *console, struct poller *poller, 193 const struct timeval *tv); 194 195 /* ringbuffer API */ 196 197 enum ringbuffer_poll_ret { 198 RINGBUFFER_POLL_OK = 0, 199 RINGBUFFER_POLL_REMOVE, 200 }; 201 202 typedef enum ringbuffer_poll_ret (*ringbuffer_poll_fn_t)(void *data, 203 size_t force_len); 204 205 struct ringbuffer_consumer; 206 207 struct ringbuffer { 208 uint8_t *buf; 209 size_t size; 210 size_t tail; 211 struct ringbuffer_consumer **consumers; 212 int n_consumers; 213 }; 214 215 struct ringbuffer_consumer { 216 struct ringbuffer *rb; 217 ringbuffer_poll_fn_t poll_fn; 218 void *poll_data; 219 size_t pos; 220 }; 221 222 struct ringbuffer *ringbuffer_init(size_t size); 223 void ringbuffer_fini(struct ringbuffer *rb); 224 225 struct ringbuffer_consumer * 226 ringbuffer_consumer_register(struct ringbuffer *rb, 227 ringbuffer_poll_fn_t poll_fn, void *data); 228 229 void ringbuffer_consumer_unregister(struct ringbuffer_consumer *rbc); 230 231 int ringbuffer_queue(struct ringbuffer *rb, uint8_t *data, size_t len); 232 233 size_t ringbuffer_dequeue_peek(struct ringbuffer_consumer *rbc, size_t offset, 234 uint8_t **data); 235 236 int ringbuffer_dequeue_commit(struct ringbuffer_consumer *rbc, size_t len); 237 238 size_t ringbuffer_len(struct ringbuffer_consumer *rbc); 239 240 /* console wrapper around ringbuffer consumer registration */ 241 struct ringbuffer_consumer * 242 console_ringbuffer_consumer_register(struct console *console, 243 ringbuffer_poll_fn_t poll_fn, void *data); 244 245 /* Console server API */ 246 void tty_init_termios(struct console_server *server); 247 248 /* socket paths */ 249 ssize_t console_socket_path(socket_path_t path, const char *id); 250 ssize_t console_socket_path_readable(const struct sockaddr_un *addr, 251 size_t addrlen, socket_path_t path); 252 253 /* utils */ 254 int write_buf_to_fd(int fd, const uint8_t *buf, size_t len); 255 256 /* console_server dbus */ 257 int dbus_server_init(struct console_server *server); 258 void dbus_server_fini(struct console_server *server); 259 260 /* console-dbus API */ 261 int dbus_init(struct console *console, 262 struct config *config __attribute__((unused))); 263 264 /* socket-handler API */ 265 int dbus_create_socket_consumer(struct console *console); 266 267 #ifndef offsetof 268 #define offsetof(type, member) ((unsigned long)&((type *)NULL)->member) 269 #endif 270 271 #define container_of(ptr, type, member) \ 272 ((type *)((void *)((ptr) - offsetof(type, member)))) 273 274 #define BUILD_ASSERT(c) \ 275 do { \ 276 char __c[(c) ? 1 : -1] __attribute__((unused)); \ 277 } while (0) 278 279 #define BUILD_ASSERT_OR_ZERO(c) (sizeof(char[(c) ? 1 : -1]) - 1) 280 281 // returns the index of that pollfd in server->pollfds 282 // we cannot return a pointer because 'realloc' may move server->pollfds 283 ssize_t console_server_request_pollfd(struct console_server *server, int fd, 284 short int events); 285 286 int console_server_release_pollfd(struct console_server *server, 287 size_t pollfd_index); 288