Changes in uspace/srv/hid/remcons/remcons.c [902f0906:03e0a244] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/srv/hid/remcons/remcons.c
r902f0906 r03e0a244 34 34 35 35 #include <async.h> 36 #include <stdio.h> 37 #include <adt/prodcons.h> 38 #include <ipc/input.h> 39 #include <ipc/console.h> 40 #include <ipc/vfs.h> 36 41 #include <errno.h> 37 #include <io/con_srv.h>38 #include <stdio.h>39 #include <stdlib.h>40 42 #include <str_error.h> 41 43 #include <loc.h> … … 43 45 #include <io/keycode.h> 44 46 #include <align.h> 47 #include <malloc.h> 48 #include <as.h> 45 49 #include <fibril_synch.h> 46 50 #include <task.h> … … 67 71 TELNET_IAC, TELNET_WONT, TELNET_LINEMODE 68 72 }; 69 70 73 static const size_t telnet_force_character_mode_command_count = 71 74 sizeof(telnet_force_character_mode_command) / sizeof(telnet_cmd_t); 72 75 73 static int remcons_open(con_srvs_t *, con_srv_t *); 74 static int remcons_close(con_srv_t *); 75 static int remcons_write(con_srv_t *, void *, size_t); 76 static void remcons_sync(con_srv_t *); 77 static void remcons_clear(con_srv_t *); 78 static void remcons_set_pos(con_srv_t *, sysarg_t col, sysarg_t row); 79 static int remcons_get_pos(con_srv_t *, sysarg_t *, sysarg_t *); 80 static int remcons_get_size(con_srv_t *, sysarg_t *, sysarg_t *); 81 static int remcons_get_color_cap(con_srv_t *, console_caps_t *); 82 static int remcons_get_event(con_srv_t *, cons_event_t *); 83 84 static con_ops_t con_ops = { 85 .open = remcons_open, 86 .close = remcons_close, 87 .read = NULL, 88 .write = remcons_write, 89 .sync = remcons_sync, 90 .clear = remcons_clear, 91 .set_pos = remcons_set_pos, 92 .get_pos = remcons_get_pos, 93 .get_size = remcons_get_size, 94 .get_color_cap = remcons_get_color_cap, 95 .set_style = NULL, 96 .set_color = NULL, 97 .set_rgb_color = NULL, 98 .set_cursor_visibility = NULL, 99 .get_event = remcons_get_event 100 }; 101 102 static telnet_user_t *srv_to_user(con_srv_t *srv) 103 { 104 return srv->srvs->sarg; 105 } 106 107 static int remcons_open(con_srvs_t *srvs, con_srv_t *srv) 108 { 109 telnet_user_t *user = srv_to_user(srv); 110 111 telnet_user_log(user, "New client connected (%p).", srv); 112 113 /* Force character mode. */ 114 send(user->socket, (void *)telnet_force_character_mode_command, 115 telnet_force_character_mode_command_count, 0); 116 117 return EOK; 118 } 119 120 static int remcons_close(con_srv_t *srv) 121 { 122 telnet_user_t *user = srv_to_user(srv); 123 124 telnet_user_notify_client_disconnected(user); 125 telnet_user_log(user, "Client disconnected (%p).", srv); 126 127 return EOK; 128 } 129 130 static int remcons_write(con_srv_t *srv, void *data, size_t size) 131 { 132 telnet_user_t *user = srv_to_user(srv); 133 int rc; 134 135 rc = telnet_user_send_data(user, data, size); 136 if (rc != EOK) 137 return rc; 138 139 return size; 140 } 141 142 static void remcons_sync(con_srv_t *srv) 143 { 144 (void) srv; 145 } 146 147 static void remcons_clear(con_srv_t *srv) 148 { 149 (void) srv; 150 } 151 152 static void remcons_set_pos(con_srv_t *srv, sysarg_t col, sysarg_t row) 153 { 154 telnet_user_t *user = srv_to_user(srv); 155 156 telnet_user_update_cursor_x(user, col); 157 } 158 159 static int remcons_get_pos(con_srv_t *srv, sysarg_t *col, sysarg_t *row) 160 { 161 telnet_user_t *user = srv_to_user(srv); 162 163 *col = user->cursor_x; 164 *row = 0; 165 166 return EOK; 167 } 168 169 static int remcons_get_size(con_srv_t *srv, sysarg_t *cols, sysarg_t *rows) 170 { 171 (void) srv; 172 173 *cols = 100; 174 *rows = 1; 175 176 return EOK; 177 } 178 179 static int remcons_get_color_cap(con_srv_t *srv, console_caps_t *ccaps) 180 { 181 (void) srv; 182 *ccaps = CONSOLE_CAP_NONE; 183 184 return EOK; 185 } 186 187 static int remcons_get_event(con_srv_t *srv, cons_event_t *event) 188 { 189 telnet_user_t *user = srv_to_user(srv); 190 kbd_event_t kevent; 191 int rc; 192 193 rc = telnet_user_get_next_keyboard_event(user, &kevent); 194 if (rc != EOK) { 195 /* XXX What? */ 196 memset(event, 0, sizeof(*event)); 197 return EOK; 198 } 199 200 event->type = CEV_KEY; 201 event->ev.key = kevent; 202 203 return EOK; 76 77 /** Handling client requests (VFS and console interface). 78 * 79 * @param user Telnet user the requests belong to. 80 */ 81 static void client_connection_message_loop(telnet_user_t *user) 82 { 83 while (true) { 84 ipc_call_t call; 85 ipc_callid_t callid = 0; 86 87 /* 88 * The getterm task might terminate while we are here, 89 * waiting for a call. Also, the socket might be closed 90 * meanwhile. 91 * We want to detect this situation early, so we use a 92 * timeout variant of async_get_call(). 93 */ 94 while (callid == 0) { 95 callid = async_get_call_timeout(&call, 1000); 96 97 if (telnet_user_is_zombie(user)) { 98 if (callid != 0) { 99 async_answer_0(callid, EINTR); 100 } 101 return; 102 } 103 } 104 105 if (!IPC_GET_IMETHOD(call)) { 106 return; 107 } 108 109 switch (IPC_GET_IMETHOD(call)) { 110 case CONSOLE_GET_SIZE: 111 async_answer_2(callid, EOK, 100, 1); 112 break; 113 case CONSOLE_GET_POS: 114 fibril_mutex_lock(&user->guard); 115 async_answer_2(callid, EOK, user->cursor_x, 0); 116 fibril_mutex_unlock(&user->guard); 117 break; 118 case CONSOLE_GET_EVENT: { 119 kbd_event_t event; 120 int rc = telnet_user_get_next_keyboard_event(user, &event); 121 if (rc != EOK) { 122 /* Silently ignore. */ 123 async_answer_0(callid, EOK); 124 break; 125 } 126 async_answer_4(callid, EOK, event.type, event.key, event.mods, event.c); 127 break; 128 } 129 case CONSOLE_GOTO: { 130 int new_x = IPC_GET_ARG1(call); 131 telnet_user_update_cursor_x(user, new_x); 132 async_answer_0(callid, ENOTSUP); 133 break; 134 } 135 case VFS_OUT_READ: 136 async_answer_0(callid, ENOTSUP); 137 break; 138 case VFS_OUT_WRITE: { 139 uint8_t *buf; 140 size_t size; 141 int rc = async_data_write_accept((void **)&buf, false, 0, 0, 0, &size); 142 143 if (rc != EOK) { 144 async_answer_0(callid, rc); 145 break; 146 } 147 148 rc = telnet_user_send_data(user, buf, size); 149 free(buf); 150 151 if (rc != EOK) { 152 async_answer_0(callid, rc); 153 break; 154 } 155 156 async_answer_1(callid, EOK, size); 157 break; 158 } 159 case VFS_OUT_SYNC: 160 async_answer_0(callid, EOK); 161 break; 162 case CONSOLE_CLEAR: 163 async_answer_0(callid, EOK); 164 break; 165 166 case CONSOLE_GET_COLOR_CAP: 167 async_answer_1(callid, EOK, CONSOLE_CAP_NONE); 168 break; 169 case CONSOLE_SET_STYLE: 170 async_answer_0(callid, ENOTSUP); 171 break; 172 case CONSOLE_SET_COLOR: 173 async_answer_0(callid, ENOTSUP); 174 break; 175 case CONSOLE_SET_RGB_COLOR: 176 async_answer_0(callid, ENOTSUP); 177 break; 178 179 case CONSOLE_CURSOR_VISIBILITY: 180 async_answer_0(callid, ENOTSUP); 181 break; 182 183 default: 184 async_answer_0(callid, EINVAL); 185 break; 186 } 187 } 204 188 } 205 189 … … 213 197 return; 214 198 } 199 async_answer_0(iid, EOK); 200 201 telnet_user_log(user, "New client connected (%" PRIxn").", iid); 202 203 /* Force character mode. */ 204 send(user->socket, (void *)telnet_force_character_mode_command, 205 telnet_force_character_mode_command_count, 0); 215 206 216 207 /* Handle messages. */ 217 con_conn(iid, icall, &user->srvs); 208 client_connection_message_loop(user); 209 210 telnet_user_notify_client_disconnected(user); 211 telnet_user_log(user, "Client disconnected (%" PRIxn").", iid); 218 212 } 219 213 … … 237 231 fibril_mutex_lock(&user->guard); 238 232 user->task_finished = true; 239 user->srvs.aborted = true;240 233 fibril_condvar_signal(&user->refcount_cv); 241 234 fibril_mutex_unlock(&user->guard); … … 257 250 fibril_mutex_lock(&user->guard); 258 251 user->task_finished = true; 259 user->srvs.aborted = true;260 252 fibril_condvar_signal(&user->refcount_cv); 261 253 fibril_mutex_unlock(&user->guard); … … 280 272 static int network_user_fibril(void *arg) 281 273 { 274 int rc; 282 275 telnet_user_t *user = arg; 283 276 284 intrc = loc_service_register(user->service_name, &user->service_id);277 rc = loc_service_register(user->service_name, &user->service_id); 285 278 if (rc != EOK) { 286 279 telnet_user_error(user, "Unable to register %s with loc: %s.", … … 291 284 telnet_user_log(user, "Service %s registerd with id %" PRIun ".", 292 285 user->service_name, user->service_id); 293 286 294 287 fid_t spawn_fibril = fibril_create(spawn_task_fibril, user); 295 288 assert(spawn_fibril); 296 289 fibril_add_ready(spawn_fibril); 297 290 298 291 /* Wait for all clients to exit. */ 299 292 fibril_mutex_lock(&user->guard); … … 302 295 closesocket(user->socket); 303 296 user->socket_closed = true; 304 user->srvs.aborted = true;305 297 continue; 306 298 } else if (user->socket_closed) { … … 312 304 } 313 305 fibril_mutex_unlock(&user->guard); 314 306 315 307 rc = loc_service_unregister(user->service_id); 316 308 if (rc != EOK) { … … 330 322 int port = 2223; 331 323 332 async_set_client_connection(client_connection);333 i nt rc = loc_server_register(NAME);334 if (rc != EOK) {335 fprintf(stderr, "%s: Unable to register server\n", NAME);336 return rc;337 } 338 324 int rc = loc_server_register(NAME, client_connection); 325 if (rc < 0) { 326 fprintf(stderr, NAME ": Unable to register server: %s.\n", 327 str_error(rc)); 328 return 1; 329 } 330 339 331 struct sockaddr_in addr; 340 332 341 333 addr.sin_family = AF_INET; 342 334 addr.sin_port = htons(port); 343 335 344 336 rc = inet_pton(AF_INET, "127.0.0.1", (void *) 345 337 &addr.sin_addr.s_addr); … … 371 363 372 364 printf("%s: HelenOS Remote console service\n", NAME); 373 task_retval(0);374 365 375 366 while (true) { … … 388 379 assert(user); 389 380 390 con_srvs_init(&user->srvs);391 user->srvs.ops = &con_ops;392 user->srvs.sarg = user;393 user->srvs.abort_timeout = 1000;394 395 telnet_user_add(user);396 397 381 fid_t fid = fibril_create(network_user_fibril, user); 398 382 assert(fid);
Note:
See TracChangeset
for help on using the changeset viewer.