Changeset 47d060d in mainline
- Timestamp:
- 2024-10-04T19:23:16Z (8 weeks ago)
- Branches:
- master
- Children:
- c7ecd290
- Parents:
- 5132379
- Location:
- uspace
- Files:
-
- 7 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/lib/vt/include/vt/vt100.h
r5132379 r47d060d 157 157 extern vt100_t *vt100_create(void *, sysarg_t, sysarg_t, 158 158 vt100_cb_t *); 159 extern void vt100_resize(vt100_t *, sysarg_t, sysarg_t); 159 160 extern void vt100_destroy(vt100_t *); 160 161 -
uspace/lib/vt/src/vt100.c
r5132379 r47d060d 206 206 } 207 207 208 /** Resize VT instance. 209 * 210 * @param vt VT instance 211 * @param cols New number of columns 212 * @param rows New number of rows 213 */ 214 void vt100_resize(vt100_t *vt, sysarg_t cols, sysarg_t rows) 215 { 216 vt->cols = cols; 217 vt->rows = rows; 218 219 if (vt->cur_col > cols - 1) 220 vt->cur_col = cols - 1; 221 if (vt->cur_row > rows - 1) 222 vt->cur_row = rows - 1; 223 } 224 208 225 /** Destroy VT instance. 209 226 * -
uspace/srv/hid/remcons/remcons.c
r5132379 r47d060d 144 144 }; 145 145 146 static void remcons_telnet_ws_update(void *, unsigned, unsigned); 147 148 static telnet_cb_t remcons_telnet_cb = { 149 .ws_update = remcons_telnet_ws_update 150 }; 151 146 152 static loc_srv_t *remcons_srv; 147 153 static bool no_ctl; … … 260 266 261 267 if (remcons->enable_ctl) { 262 *cols = 80;263 *rows = 25;268 *cols = remcons->vt->cols; 269 *rows = remcons->vt->rows; 264 270 } else { 265 271 *cols = 100; … … 352 358 { 353 359 remcons_event_t *event = malloc(sizeof(remcons_event_t)); 354 assert(event); 360 if (event == NULL) { 361 fprintf(stderr, "Out of memory.\n"); 362 return NULL; 363 } 355 364 356 365 link_initialize(&event->link); 357 event->kbd.type = type; 358 event->kbd.mods = mods; 359 event->kbd.key = key; 360 event->kbd.c = c; 366 event->cev.type = CEV_KEY; 367 event->cev.ev.key.type = type; 368 event->cev.ev.key.mods = mods; 369 event->cev.ev.key.key = key; 370 event->cev.ev.key.c = c; 371 372 return event; 373 } 374 375 /** Creates new console resize event. 376 */ 377 static remcons_event_t *new_resize_event(void) 378 { 379 remcons_event_t *event = malloc(sizeof(remcons_event_t)); 380 if (event == NULL) { 381 fprintf(stderr, "Out of memory.\n"); 382 return NULL; 383 } 384 385 link_initialize(&event->link); 386 event->cev.type = CEV_RESIZE; 361 387 362 388 return event; … … 385 411 remcons_event_t *tmp = list_get_instance(link, remcons_event_t, link); 386 412 387 event->type = CEV_KEY; 388 event->ev.key = tmp->kbd; 389 413 *event = tmp->cev; 390 414 free(tmp); 391 415 … … 590 614 591 615 remcons_event_t *down = new_kbd_event(KEY_PRESS, mods, key, c); 616 if (down == NULL) 617 return; 618 592 619 remcons_event_t *up = new_kbd_event(KEY_RELEASE, mods, key, c); 593 assert(down); 594 assert(up); 620 if (up == NULL) { 621 free(down); 622 return; 623 } 624 595 625 list_append(&down->link, &remcons->in_events); 596 626 list_append(&up->link, &remcons->in_events); 627 } 628 629 /** Window size update callback. 630 * 631 * @param arg Argument (remcons_t *) 632 * @param cols New number of columns 633 * @param rows New number of rows 634 */ 635 static void remcons_telnet_ws_update(void *arg, unsigned cols, unsigned rows) 636 { 637 remcons_t *remcons = (remcons_t *)arg; 638 639 vt100_resize(remcons->vt, cols, rows); 640 telnet_user_resize(remcons->user, cols, rows); 641 642 remcons_event_t *resize = new_resize_event(); 643 if (resize == NULL) 644 return; 645 646 list_append(&resize->link, &remcons->in_events); 597 647 } 598 648 … … 605 655 { 606 656 char_attrs_t attrs; 607 remcons_t *remcons = calloc(1, sizeof(remcons_t)); 608 assert(remcons != NULL); // XXX 609 telnet_user_t *user = telnet_user_create(conn); 610 assert(user); 657 remcons_t *remcons = NULL; 658 telnet_user_t *user = NULL; 659 660 remcons = calloc(1, sizeof(remcons_t)); 661 if (remcons == NULL) { 662 fprintf(stderr, "Out of memory.\n"); 663 goto error; 664 } 665 666 user = telnet_user_create(conn, &remcons_telnet_cb, 667 (void *)remcons); 668 if (user == NULL) { 669 fprintf(stderr, "Out of memory.\n"); 670 goto error; 671 } 611 672 612 673 remcons->enable_ctl = !no_ctl; … … 626 687 627 688 remcons->vt = vt100_create((void *)remcons, 80, 25, &remcons_vt_cb); 628 assert(remcons->vt != NULL); // XXX 689 if (remcons->vt == NULL) { 690 fprintf(stderr, "Error creating VT100 driver instance.\n"); 691 goto error; 692 } 693 629 694 remcons->vt->enable_rgb = remcons->enable_rgb; 630 695 … … 649 714 telnet_user_error(user, "Unable to register %s with loc: %s.", 650 715 user->service_name, str_error(rc)); 651 return;716 goto error; 652 717 } 653 718 … … 656 721 657 722 fid_t spawn_fibril = fibril_create(spawn_task_fibril, user); 658 assert(spawn_fibril); 723 if (spawn_fibril == 0) { 724 fprintf(stderr, "Failed creating fibril.\n"); 725 goto error; 726 } 659 727 fibril_add_ready(spawn_fibril); 660 728 … … 685 753 telnet_user_log(user, "Destroying..."); 686 754 telnet_user_destroy(user); 755 return; 756 error: 757 if (user != NULL && user->service_id != 0) 758 loc_service_unregister(remcons_srv, user->service_id); 759 if (user != NULL) 760 free(user); 761 if (remcons != NULL && remcons->vt != NULL) 762 vt100_destroy(remcons->vt); 763 if (remcons != NULL) 764 free(remcons); 687 765 } 688 766 -
uspace/srv/hid/remcons/remcons.h
r5132379 r47d060d 38 38 39 39 #include <adt/list.h> 40 #include <io/ kbd_event.h>40 #include <io/cons_event.h> 41 41 #include <stdbool.h> 42 42 #include <vt/vt100.h> … … 64 64 typedef struct { 65 65 link_t link; /**< link to list of events */ 66 kbd_event_t kbd; /**< keyboardevent */66 cons_event_t cev; /**< console event */ 67 67 } remcons_event_t; 68 68 -
uspace/srv/hid/remcons/telnet.h
r5132379 r47d060d 1 1 /* 2 * Copyright (c) 2024 Jiri Svoboda 2 3 * Copyright (c) 2012 Vojtech Horky 3 4 * All rights reserved. … … 44 45 */ 45 46 47 #define TELNET_SE 240 48 #define TELNET_SB 250 46 49 #define TELNET_IAC 255 47 50 … … 55 58 #define TELNET_ECHO 1 56 59 #define TELNET_SUPPRESS_GO_AHEAD 3 60 #define TELNET_NAWS 31 57 61 #define TELNET_LINEMODE 34 58 62 -
uspace/srv/hid/remcons/user.c
r5132379 r47d060d 58 58 static LIST_INITIALIZE(users); 59 59 60 static errno_t telnet_user_send_raw_locked(telnet_user_t *, const void *, 61 size_t); 62 static errno_t telnet_user_flush_locked(telnet_user_t *); 63 60 64 /** Create new telnet user. 61 65 * 62 66 * @param conn Incoming connection. 67 * @param cb Callback functions 68 * @param arg Argument to callback functions 63 69 * @return New telnet user or NULL when out of memory. 64 70 */ 65 telnet_user_t *telnet_user_create(tcp_conn_t *conn )71 telnet_user_t *telnet_user_create(tcp_conn_t *conn, telnet_cb_t *cb, void *arg) 66 72 { 67 73 static int telnet_user_id_counter = 0; … … 72 78 } 73 79 80 user->cb = cb; 81 user->arg = arg; 74 82 user->id = ++telnet_user_id_counter; 75 83 … … 216 224 * @return EOK on success or an error code 217 225 */ 218 static errno_t telnet_user_recv_next_byte_locked(telnet_user_t *user, char *byte) 226 static errno_t telnet_user_recv_next_byte_locked(telnet_user_t *user, 227 uint8_t *byte) 219 228 { 220 229 errno_t rc; … … 227 236 } 228 237 229 *byte = user->socket_buffer[user->socket_buffer_pos++];238 *byte = (uint8_t)user->socket_buffer[user->socket_buffer_pos++]; 230 239 return EOK; 231 240 } … … 241 250 } 242 251 243 /** Process telnet command (currently only print to screen). 252 static errno_t telnet_user_send_opt(telnet_user_t *user, telnet_cmd_t cmd, 253 telnet_cmd_t opt) 254 { 255 uint8_t cmdb[3]; 256 257 cmdb[0] = TELNET_IAC; 258 cmdb[1] = cmd; 259 cmdb[2] = opt; 260 261 return telnet_user_send_raw_locked(user, (char *)cmdb, sizeof(cmdb)); 262 } 263 264 /** Process telnet WILL NAWS command. 265 * 266 * @param user Telnet user structure. 267 * @param cmd Telnet command. 268 */ 269 static void process_telnet_will_naws(telnet_user_t *user) 270 { 271 telnet_user_log(user, "WILL NAWS"); 272 /* Send DO NAWS */ 273 (void) telnet_user_send_opt(user, TELNET_DO, TELNET_NAWS); 274 (void) telnet_user_flush_locked(user); 275 } 276 277 /** Process telnet SB NAWS command. 278 * 279 * @param user Telnet user structure. 280 * @param cmd Telnet command. 281 */ 282 static void process_telnet_sb_naws(telnet_user_t *user) 283 { 284 uint8_t chi, clo; 285 uint8_t rhi, rlo; 286 uint16_t cols; 287 uint16_t rows; 288 uint8_t iac; 289 uint8_t se; 290 errno_t rc; 291 292 telnet_user_log(user, "SB NAWS..."); 293 294 rc = telnet_user_recv_next_byte_locked(user, &chi); 295 if (rc != EOK) 296 return; 297 rc = telnet_user_recv_next_byte_locked(user, &clo); 298 if (rc != EOK) 299 return; 300 301 rc = telnet_user_recv_next_byte_locked(user, &rhi); 302 if (rc != EOK) 303 return; 304 rc = telnet_user_recv_next_byte_locked(user, &rlo); 305 if (rc != EOK) 306 return; 307 308 rc = telnet_user_recv_next_byte_locked(user, &iac); 309 if (rc != EOK) 310 return; 311 rc = telnet_user_recv_next_byte_locked(user, &se); 312 if (rc != EOK) 313 return; 314 315 cols = (chi << 8) | clo; 316 rows = (rhi << 8) | rlo; 317 318 telnet_user_log(user, "cols=%u rows=%u\n", cols, rows); 319 320 if (cols < 1 || rows < 1) { 321 telnet_user_log(user, "Ignoring invalid window size update."); 322 return; 323 } 324 325 user->cb->ws_update(user->arg, cols, rows); 326 } 327 328 /** Process telnet WILL command. 329 * 330 * @param user Telnet user structure. 331 * @param opt Option code. 332 */ 333 static void process_telnet_will(telnet_user_t *user, telnet_cmd_t opt) 334 { 335 telnet_user_log(user, "WILL"); 336 switch (opt) { 337 case TELNET_NAWS: 338 process_telnet_will_naws(user); 339 return; 340 } 341 342 telnet_user_log(user, "Ignoring telnet command %u %u %u.", 343 TELNET_IAC, TELNET_WILL, opt); 344 } 345 346 /** Process telnet SB command. 347 * 348 * @param user Telnet user structure. 349 * @param opt Option code. 350 */ 351 static void process_telnet_sb(telnet_user_t *user, telnet_cmd_t opt) 352 { 353 telnet_user_log(user, "SB"); 354 switch (opt) { 355 case TELNET_NAWS: 356 process_telnet_sb_naws(user); 357 return; 358 } 359 360 telnet_user_log(user, "Ignoring telnet command %u %u %u.", 361 TELNET_IAC, TELNET_SB, opt); 362 } 363 364 /** Process telnet command. 244 365 * 245 366 * @param user Telnet user structure. … … 250 371 telnet_cmd_t option_code, telnet_cmd_t cmd) 251 372 { 373 switch (option_code) { 374 case TELNET_SB: 375 process_telnet_sb(user, cmd); 376 return; 377 case TELNET_WILL: 378 process_telnet_will(user, cmd); 379 return; 380 } 381 252 382 if (option_code != 0) { 253 383 telnet_user_log(user, "Ignoring telnet command %u %u %u.", … … 277 407 278 408 do { 279 charnext_byte = 0;409 uint8_t next_byte = 0; 280 410 bool inside_telnet_command = false; 281 411 … … 290 420 return rc; 291 421 } 292 uint8_t byte = (uint8_t)next_byte;422 uint8_t byte = next_byte; 293 423 294 424 /* Skip telnet commands. */ … … 296 426 inside_telnet_command = false; 297 427 next_byte = 0; 298 if (TELNET_IS_OPTION_CODE(byte)) { 428 if (TELNET_IS_OPTION_CODE(byte) || 429 byte == TELNET_SB) { 299 430 telnet_option_code = byte; 300 431 inside_telnet_command = true; … … 430 561 } 431 562 563 static errno_t telnet_user_flush_locked(telnet_user_t *user) 564 { 565 errno_t rc; 566 567 rc = tcp_conn_send(user->conn, user->send_buf, user->send_buf_used); 568 if (rc != EOK) 569 return rc; 570 571 user->send_buf_used = 0; 572 return EOK; 573 } 574 432 575 errno_t telnet_user_flush(telnet_user_t *user) 433 576 { … … 435 578 436 579 fibril_mutex_lock(&user->guard); 437 rc = tcp_conn_send(user->conn, user->send_buf, user->send_buf_used); 438 439 if (rc != EOK) { 440 fibril_mutex_unlock(&user->guard); 441 return rc; 442 } 443 444 user->send_buf_used = 0; 580 rc = telnet_user_flush_locked(user); 445 581 fibril_mutex_unlock(&user->guard); 446 return EOK;582 return rc; 447 583 } 448 584 … … 467 603 } 468 604 605 /** Resize telnet session. 606 * 607 * @param user Telnet user 608 * @param cols New number of columns 609 * @param rows New number of rows 610 */ 611 void telnet_user_resize(telnet_user_t *user, unsigned cols, unsigned rows) 612 { 613 user->cols = cols; 614 user->rows = rows; 615 if ((unsigned)user->cursor_x > cols - 1) 616 user->cursor_x = cols - 1; 617 if ((unsigned)user->cursor_y > rows - 1) 618 user->cursor_y = rows - 1; 619 } 620 469 621 /** 470 622 * @} -
uspace/srv/hid/remcons/user.h
r5132379 r47d060d 45 45 #define SEND_BUF_SIZE 512 46 46 47 /** Telnet callbacks */ 48 typedef struct { 49 void (*ws_update)(void *, unsigned, unsigned); 50 } telnet_cb_t; 51 47 52 /** Representation of a connected (human) user. */ 48 53 typedef struct { 49 54 /** Mutex guarding the whole structure. */ 50 55 fibril_mutex_t guard; 56 /** Callback functions */ 57 telnet_cb_t *cb; 58 /** Argument to callback functions */ 59 void *arg; 51 60 52 61 /** Internal id, used for creating locfs entries. */ … … 87 96 } telnet_user_t; 88 97 89 extern telnet_user_t *telnet_user_create(tcp_conn_t * );98 extern telnet_user_t *telnet_user_create(tcp_conn_t *, telnet_cb_t *, void *); 90 99 extern void telnet_user_add(telnet_user_t *); 91 100 extern void telnet_user_destroy(telnet_user_t *); … … 99 108 extern errno_t telnet_user_recv(telnet_user_t *, void *, size_t, size_t *); 100 109 extern void telnet_user_update_cursor_x(telnet_user_t *, int); 110 extern void telnet_user_resize(telnet_user_t *, unsigned, unsigned); 101 111 102 112 /** Print informational message about connected user. */
Note:
See TracChangeset
for help on using the changeset viewer.