|
|
1.1 ! root 1: /* ! 2: * QEMU System Emulator ! 3: * ! 4: * Copyright (c) 2003-2008 Fabrice Bellard ! 5: * ! 6: * Permission is hereby granted, free of charge, to any person obtaining a copy ! 7: * of this software and associated documentation files (the "Software"), to deal ! 8: * in the Software without restriction, including without limitation the rights ! 9: * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell ! 10: * copies of the Software, and to permit persons to whom the Software is ! 11: * furnished to do so, subject to the following conditions: ! 12: * ! 13: * The above copyright notice and this permission notice shall be included in ! 14: * all copies or substantial portions of the Software. ! 15: * ! 16: * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ! 17: * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ! 18: * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL ! 19: * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER ! 20: * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, ! 21: * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN ! 22: * THE SOFTWARE. ! 23: */ ! 24: #include "qemu-common.h" ! 25: #include "net.h" ! 26: #include "console.h" ! 27: #include "sysemu.h" ! 28: #include "qemu-timer.h" ! 29: #include "qemu-char.h" ! 30: #include "block.h" ! 31: #include "hw/usb.h" ! 32: #include "hw/baum.h" ! 33: #include "hw/msmouse.h" ! 34: ! 35: #include <unistd.h> ! 36: #include <fcntl.h> ! 37: #include <signal.h> ! 38: #include <time.h> ! 39: #include <errno.h> ! 40: #include <sys/time.h> ! 41: #include <zlib.h> ! 42: ! 43: #ifndef _WIN32 ! 44: #include <sys/times.h> ! 45: #include <sys/wait.h> ! 46: #include <termios.h> ! 47: #include <sys/mman.h> ! 48: #include <sys/ioctl.h> ! 49: #include <sys/resource.h> ! 50: #include <sys/socket.h> ! 51: #include <netinet/in.h> ! 52: #include <net/if.h> ! 53: #ifdef __NetBSD__ ! 54: #include <net/if_tap.h> ! 55: #endif ! 56: #ifdef __linux__ ! 57: #include <linux/if_tun.h> ! 58: #endif ! 59: #include <arpa/inet.h> ! 60: #include <dirent.h> ! 61: #include <netdb.h> ! 62: #include <sys/select.h> ! 63: #ifdef _BSD ! 64: #include <sys/stat.h> ! 65: #ifdef __FreeBSD__ ! 66: #include <libutil.h> ! 67: #include <dev/ppbus/ppi.h> ! 68: #include <dev/ppbus/ppbconf.h> ! 69: #else ! 70: #include <util.h> ! 71: #endif ! 72: #elif defined (__GLIBC__) && defined (__FreeBSD_kernel__) ! 73: #include <freebsd/stdlib.h> ! 74: #else ! 75: #ifdef __linux__ ! 76: #include <pty.h> ! 77: ! 78: #include <linux/ppdev.h> ! 79: #include <linux/parport.h> ! 80: #endif ! 81: #ifdef __sun__ ! 82: #include <sys/stat.h> ! 83: #include <sys/ethernet.h> ! 84: #include <sys/sockio.h> ! 85: #include <netinet/arp.h> ! 86: #include <netinet/in.h> ! 87: #include <netinet/in_systm.h> ! 88: #include <netinet/ip.h> ! 89: #include <netinet/ip_icmp.h> // must come after ip.h ! 90: #include <netinet/udp.h> ! 91: #include <netinet/tcp.h> ! 92: #include <net/if.h> ! 93: #include <syslog.h> ! 94: #include <stropts.h> ! 95: #endif ! 96: #endif ! 97: #endif ! 98: ! 99: #include "qemu_socket.h" ! 100: ! 101: /***********************************************************/ ! 102: /* character device */ ! 103: ! 104: static void qemu_chr_event(CharDriverState *s, int event) ! 105: { ! 106: if (!s->chr_event) ! 107: return; ! 108: s->chr_event(s->handler_opaque, event); ! 109: } ! 110: ! 111: static void qemu_chr_reset_bh(void *opaque) ! 112: { ! 113: CharDriverState *s = opaque; ! 114: qemu_chr_event(s, CHR_EVENT_RESET); ! 115: qemu_bh_delete(s->bh); ! 116: s->bh = NULL; ! 117: } ! 118: ! 119: void qemu_chr_reset(CharDriverState *s) ! 120: { ! 121: if (s->bh == NULL) { ! 122: s->bh = qemu_bh_new(qemu_chr_reset_bh, s); ! 123: qemu_bh_schedule(s->bh); ! 124: } ! 125: } ! 126: ! 127: int qemu_chr_write(CharDriverState *s, const uint8_t *buf, int len) ! 128: { ! 129: return s->chr_write(s, buf, len); ! 130: } ! 131: ! 132: int qemu_chr_ioctl(CharDriverState *s, int cmd, void *arg) ! 133: { ! 134: if (!s->chr_ioctl) ! 135: return -ENOTSUP; ! 136: return s->chr_ioctl(s, cmd, arg); ! 137: } ! 138: ! 139: int qemu_chr_can_read(CharDriverState *s) ! 140: { ! 141: if (!s->chr_can_read) ! 142: return 0; ! 143: return s->chr_can_read(s->handler_opaque); ! 144: } ! 145: ! 146: void qemu_chr_read(CharDriverState *s, uint8_t *buf, int len) ! 147: { ! 148: s->chr_read(s->handler_opaque, buf, len); ! 149: } ! 150: ! 151: void qemu_chr_accept_input(CharDriverState *s) ! 152: { ! 153: if (s->chr_accept_input) ! 154: s->chr_accept_input(s); ! 155: } ! 156: ! 157: void qemu_chr_printf(CharDriverState *s, const char *fmt, ...) ! 158: { ! 159: char buf[4096]; ! 160: va_list ap; ! 161: va_start(ap, fmt); ! 162: vsnprintf(buf, sizeof(buf), fmt, ap); ! 163: qemu_chr_write(s, (uint8_t *)buf, strlen(buf)); ! 164: va_end(ap); ! 165: } ! 166: ! 167: void qemu_chr_send_event(CharDriverState *s, int event) ! 168: { ! 169: if (s->chr_send_event) ! 170: s->chr_send_event(s, event); ! 171: } ! 172: ! 173: void qemu_chr_add_handlers(CharDriverState *s, ! 174: IOCanRWHandler *fd_can_read, ! 175: IOReadHandler *fd_read, ! 176: IOEventHandler *fd_event, ! 177: void *opaque) ! 178: { ! 179: s->chr_can_read = fd_can_read; ! 180: s->chr_read = fd_read; ! 181: s->chr_event = fd_event; ! 182: s->handler_opaque = opaque; ! 183: if (s->chr_update_read_handler) ! 184: s->chr_update_read_handler(s); ! 185: } ! 186: ! 187: static int null_chr_write(CharDriverState *chr, const uint8_t *buf, int len) ! 188: { ! 189: return len; ! 190: } ! 191: ! 192: static CharDriverState *qemu_chr_open_null(void) ! 193: { ! 194: CharDriverState *chr; ! 195: ! 196: chr = qemu_mallocz(sizeof(CharDriverState)); ! 197: chr->chr_write = null_chr_write; ! 198: return chr; ! 199: } ! 200: ! 201: /* MUX driver for serial I/O splitting */ ! 202: static int term_timestamps; ! 203: static int64_t term_timestamps_start; ! 204: #define MAX_MUX 4 ! 205: #define MUX_BUFFER_SIZE 32 /* Must be a power of 2. */ ! 206: #define MUX_BUFFER_MASK (MUX_BUFFER_SIZE - 1) ! 207: typedef struct { ! 208: IOCanRWHandler *chr_can_read[MAX_MUX]; ! 209: IOReadHandler *chr_read[MAX_MUX]; ! 210: IOEventHandler *chr_event[MAX_MUX]; ! 211: void *ext_opaque[MAX_MUX]; ! 212: CharDriverState *drv; ! 213: unsigned char buffer[MUX_BUFFER_SIZE]; ! 214: int prod; ! 215: int cons; ! 216: int mux_cnt; ! 217: int term_got_escape; ! 218: int max_size; ! 219: } MuxDriver; ! 220: ! 221: ! 222: static int mux_chr_write(CharDriverState *chr, const uint8_t *buf, int len) ! 223: { ! 224: MuxDriver *d = chr->opaque; ! 225: int ret; ! 226: if (!term_timestamps) { ! 227: ret = d->drv->chr_write(d->drv, buf, len); ! 228: } else { ! 229: int i; ! 230: ! 231: ret = 0; ! 232: for(i = 0; i < len; i++) { ! 233: ret += d->drv->chr_write(d->drv, buf+i, 1); ! 234: if (buf[i] == '\n') { ! 235: char buf1[64]; ! 236: int64_t ti; ! 237: int secs; ! 238: ! 239: ti = qemu_get_clock(rt_clock); ! 240: if (term_timestamps_start == -1) ! 241: term_timestamps_start = ti; ! 242: ti -= term_timestamps_start; ! 243: secs = ti / 1000; ! 244: snprintf(buf1, sizeof(buf1), ! 245: "[%02d:%02d:%02d.%03d] ", ! 246: secs / 3600, ! 247: (secs / 60) % 60, ! 248: secs % 60, ! 249: (int)(ti % 1000)); ! 250: d->drv->chr_write(d->drv, (uint8_t *)buf1, strlen(buf1)); ! 251: } ! 252: } ! 253: } ! 254: return ret; ! 255: } ! 256: ! 257: static const char * const mux_help[] = { ! 258: "% h print this help\n\r", ! 259: "% x exit emulator\n\r", ! 260: "% s save disk data back to file (if -snapshot)\n\r", ! 261: "% t toggle console timestamps\n\r" ! 262: "% b send break (magic sysrq)\n\r", ! 263: "% c switch between console and monitor\n\r", ! 264: "% % sends %\n\r", ! 265: NULL ! 266: }; ! 267: ! 268: int term_escape_char = 0x01; /* ctrl-a is used for escape */ ! 269: static void mux_print_help(CharDriverState *chr) ! 270: { ! 271: int i, j; ! 272: char ebuf[15] = "Escape-Char"; ! 273: char cbuf[50] = "\n\r"; ! 274: ! 275: if (term_escape_char > 0 && term_escape_char < 26) { ! 276: snprintf(cbuf, sizeof(cbuf), "\n\r"); ! 277: snprintf(ebuf, sizeof(ebuf), "C-%c", term_escape_char - 1 + 'a'); ! 278: } else { ! 279: snprintf(cbuf, sizeof(cbuf), ! 280: "\n\rEscape-Char set to Ascii: 0x%02x\n\r\n\r", ! 281: term_escape_char); ! 282: } ! 283: chr->chr_write(chr, (uint8_t *)cbuf, strlen(cbuf)); ! 284: for (i = 0; mux_help[i] != NULL; i++) { ! 285: for (j=0; mux_help[i][j] != '\0'; j++) { ! 286: if (mux_help[i][j] == '%') ! 287: chr->chr_write(chr, (uint8_t *)ebuf, strlen(ebuf)); ! 288: else ! 289: chr->chr_write(chr, (uint8_t *)&mux_help[i][j], 1); ! 290: } ! 291: } ! 292: } ! 293: ! 294: static int mux_proc_byte(CharDriverState *chr, MuxDriver *d, int ch) ! 295: { ! 296: if (d->term_got_escape) { ! 297: d->term_got_escape = 0; ! 298: if (ch == term_escape_char) ! 299: goto send_char; ! 300: switch(ch) { ! 301: case '?': ! 302: case 'h': ! 303: mux_print_help(chr); ! 304: break; ! 305: case 'x': ! 306: { ! 307: const char *term = "QEMU: Terminated\n\r"; ! 308: chr->chr_write(chr,(uint8_t *)term,strlen(term)); ! 309: exit(0); ! 310: break; ! 311: } ! 312: case 's': ! 313: { ! 314: int i; ! 315: for (i = 0; i < nb_drives; i++) { ! 316: bdrv_commit(drives_table[i].bdrv); ! 317: } ! 318: } ! 319: break; ! 320: case 'b': ! 321: qemu_chr_event(chr, CHR_EVENT_BREAK); ! 322: break; ! 323: case 'c': ! 324: /* Switch to the next registered device */ ! 325: chr->focus++; ! 326: if (chr->focus >= d->mux_cnt) ! 327: chr->focus = 0; ! 328: break; ! 329: case 't': ! 330: term_timestamps = !term_timestamps; ! 331: term_timestamps_start = -1; ! 332: break; ! 333: } ! 334: } else if (ch == term_escape_char) { ! 335: d->term_got_escape = 1; ! 336: } else { ! 337: send_char: ! 338: return 1; ! 339: } ! 340: return 0; ! 341: } ! 342: ! 343: static void mux_chr_accept_input(CharDriverState *chr) ! 344: { ! 345: int m = chr->focus; ! 346: MuxDriver *d = chr->opaque; ! 347: ! 348: while (d->prod != d->cons && ! 349: d->chr_can_read[m] && ! 350: d->chr_can_read[m](d->ext_opaque[m])) { ! 351: d->chr_read[m](d->ext_opaque[m], ! 352: &d->buffer[d->cons++ & MUX_BUFFER_MASK], 1); ! 353: } ! 354: } ! 355: ! 356: static int mux_chr_can_read(void *opaque) ! 357: { ! 358: CharDriverState *chr = opaque; ! 359: MuxDriver *d = chr->opaque; ! 360: ! 361: if ((d->prod - d->cons) < MUX_BUFFER_SIZE) ! 362: return 1; ! 363: if (d->chr_can_read[chr->focus]) ! 364: return d->chr_can_read[chr->focus](d->ext_opaque[chr->focus]); ! 365: return 0; ! 366: } ! 367: ! 368: static void mux_chr_read(void *opaque, const uint8_t *buf, int size) ! 369: { ! 370: CharDriverState *chr = opaque; ! 371: MuxDriver *d = chr->opaque; ! 372: int m = chr->focus; ! 373: int i; ! 374: ! 375: mux_chr_accept_input (opaque); ! 376: ! 377: for(i = 0; i < size; i++) ! 378: if (mux_proc_byte(chr, d, buf[i])) { ! 379: if (d->prod == d->cons && ! 380: d->chr_can_read[m] && ! 381: d->chr_can_read[m](d->ext_opaque[m])) ! 382: d->chr_read[m](d->ext_opaque[m], &buf[i], 1); ! 383: else ! 384: d->buffer[d->prod++ & MUX_BUFFER_MASK] = buf[i]; ! 385: } ! 386: } ! 387: ! 388: static void mux_chr_event(void *opaque, int event) ! 389: { ! 390: CharDriverState *chr = opaque; ! 391: MuxDriver *d = chr->opaque; ! 392: int i; ! 393: ! 394: /* Send the event to all registered listeners */ ! 395: for (i = 0; i < d->mux_cnt; i++) ! 396: if (d->chr_event[i]) ! 397: d->chr_event[i](d->ext_opaque[i], event); ! 398: } ! 399: ! 400: static void mux_chr_update_read_handler(CharDriverState *chr) ! 401: { ! 402: MuxDriver *d = chr->opaque; ! 403: ! 404: if (d->mux_cnt >= MAX_MUX) { ! 405: fprintf(stderr, "Cannot add I/O handlers, MUX array is full\n"); ! 406: return; ! 407: } ! 408: d->ext_opaque[d->mux_cnt] = chr->handler_opaque; ! 409: d->chr_can_read[d->mux_cnt] = chr->chr_can_read; ! 410: d->chr_read[d->mux_cnt] = chr->chr_read; ! 411: d->chr_event[d->mux_cnt] = chr->chr_event; ! 412: /* Fix up the real driver with mux routines */ ! 413: if (d->mux_cnt == 0) { ! 414: qemu_chr_add_handlers(d->drv, mux_chr_can_read, mux_chr_read, ! 415: mux_chr_event, chr); ! 416: } ! 417: chr->focus = d->mux_cnt; ! 418: d->mux_cnt++; ! 419: } ! 420: ! 421: static CharDriverState *qemu_chr_open_mux(CharDriverState *drv) ! 422: { ! 423: CharDriverState *chr; ! 424: MuxDriver *d; ! 425: ! 426: chr = qemu_mallocz(sizeof(CharDriverState)); ! 427: d = qemu_mallocz(sizeof(MuxDriver)); ! 428: ! 429: chr->opaque = d; ! 430: d->drv = drv; ! 431: chr->focus = -1; ! 432: chr->chr_write = mux_chr_write; ! 433: chr->chr_update_read_handler = mux_chr_update_read_handler; ! 434: chr->chr_accept_input = mux_chr_accept_input; ! 435: return chr; ! 436: } ! 437: ! 438: ! 439: #ifdef _WIN32 ! 440: int send_all(int fd, const void *buf, int len1) ! 441: { ! 442: int ret, len; ! 443: ! 444: len = len1; ! 445: while (len > 0) { ! 446: ret = send(fd, buf, len, 0); ! 447: if (ret < 0) { ! 448: errno = WSAGetLastError(); ! 449: if (errno != WSAEWOULDBLOCK) { ! 450: return -1; ! 451: } ! 452: } else if (ret == 0) { ! 453: break; ! 454: } else { ! 455: buf += ret; ! 456: len -= ret; ! 457: } ! 458: } ! 459: return len1 - len; ! 460: } ! 461: ! 462: #else ! 463: ! 464: static int unix_write(int fd, const uint8_t *buf, int len1) ! 465: { ! 466: int ret, len; ! 467: ! 468: len = len1; ! 469: while (len > 0) { ! 470: ret = write(fd, buf, len); ! 471: if (ret < 0) { ! 472: if (errno != EINTR && errno != EAGAIN) ! 473: return -1; ! 474: } else if (ret == 0) { ! 475: break; ! 476: } else { ! 477: buf += ret; ! 478: len -= ret; ! 479: } ! 480: } ! 481: return len1 - len; ! 482: } ! 483: ! 484: int send_all(int fd, const void *buf, int len1) ! 485: { ! 486: return unix_write(fd, buf, len1); ! 487: } ! 488: #endif /* !_WIN32 */ ! 489: ! 490: #ifndef _WIN32 ! 491: ! 492: typedef struct { ! 493: int fd_in, fd_out; ! 494: int max_size; ! 495: } FDCharDriver; ! 496: ! 497: #define STDIO_MAX_CLIENTS 1 ! 498: static int stdio_nb_clients = 0; ! 499: ! 500: static int fd_chr_write(CharDriverState *chr, const uint8_t *buf, int len) ! 501: { ! 502: FDCharDriver *s = chr->opaque; ! 503: return send_all(s->fd_out, buf, len); ! 504: } ! 505: ! 506: static int fd_chr_read_poll(void *opaque) ! 507: { ! 508: CharDriverState *chr = opaque; ! 509: FDCharDriver *s = chr->opaque; ! 510: ! 511: s->max_size = qemu_chr_can_read(chr); ! 512: return s->max_size; ! 513: } ! 514: ! 515: static void fd_chr_read(void *opaque) ! 516: { ! 517: CharDriverState *chr = opaque; ! 518: FDCharDriver *s = chr->opaque; ! 519: int size, len; ! 520: uint8_t buf[1024]; ! 521: ! 522: len = sizeof(buf); ! 523: if (len > s->max_size) ! 524: len = s->max_size; ! 525: if (len == 0) ! 526: return; ! 527: size = read(s->fd_in, buf, len); ! 528: if (size == 0) { ! 529: /* FD has been closed. Remove it from the active list. */ ! 530: qemu_set_fd_handler2(s->fd_in, NULL, NULL, NULL, NULL); ! 531: return; ! 532: } ! 533: if (size > 0) { ! 534: qemu_chr_read(chr, buf, size); ! 535: } ! 536: } ! 537: ! 538: static void fd_chr_update_read_handler(CharDriverState *chr) ! 539: { ! 540: FDCharDriver *s = chr->opaque; ! 541: ! 542: if (s->fd_in >= 0) { ! 543: if (nographic && s->fd_in == 0) { ! 544: } else { ! 545: qemu_set_fd_handler2(s->fd_in, fd_chr_read_poll, ! 546: fd_chr_read, NULL, chr); ! 547: } ! 548: } ! 549: } ! 550: ! 551: static void fd_chr_close(struct CharDriverState *chr) ! 552: { ! 553: FDCharDriver *s = chr->opaque; ! 554: ! 555: if (s->fd_in >= 0) { ! 556: if (nographic && s->fd_in == 0) { ! 557: } else { ! 558: qemu_set_fd_handler2(s->fd_in, NULL, NULL, NULL, NULL); ! 559: } ! 560: } ! 561: ! 562: qemu_free(s); ! 563: } ! 564: ! 565: /* open a character device to a unix fd */ ! 566: static CharDriverState *qemu_chr_open_fd(int fd_in, int fd_out) ! 567: { ! 568: CharDriverState *chr; ! 569: FDCharDriver *s; ! 570: ! 571: chr = qemu_mallocz(sizeof(CharDriverState)); ! 572: s = qemu_mallocz(sizeof(FDCharDriver)); ! 573: s->fd_in = fd_in; ! 574: s->fd_out = fd_out; ! 575: chr->opaque = s; ! 576: chr->chr_write = fd_chr_write; ! 577: chr->chr_update_read_handler = fd_chr_update_read_handler; ! 578: chr->chr_close = fd_chr_close; ! 579: ! 580: qemu_chr_reset(chr); ! 581: ! 582: return chr; ! 583: } ! 584: ! 585: static CharDriverState *qemu_chr_open_file_out(const char *file_out) ! 586: { ! 587: int fd_out; ! 588: ! 589: TFR(fd_out = open(file_out, O_WRONLY | O_TRUNC | O_CREAT | O_BINARY, 0666)); ! 590: if (fd_out < 0) ! 591: return NULL; ! 592: return qemu_chr_open_fd(-1, fd_out); ! 593: } ! 594: ! 595: static CharDriverState *qemu_chr_open_pipe(const char *filename) ! 596: { ! 597: int fd_in, fd_out; ! 598: char filename_in[256], filename_out[256]; ! 599: ! 600: snprintf(filename_in, 256, "%s.in", filename); ! 601: snprintf(filename_out, 256, "%s.out", filename); ! 602: TFR(fd_in = open(filename_in, O_RDWR | O_BINARY)); ! 603: TFR(fd_out = open(filename_out, O_RDWR | O_BINARY)); ! 604: if (fd_in < 0 || fd_out < 0) { ! 605: if (fd_in >= 0) ! 606: close(fd_in); ! 607: if (fd_out >= 0) ! 608: close(fd_out); ! 609: TFR(fd_in = fd_out = open(filename, O_RDWR | O_BINARY)); ! 610: if (fd_in < 0) ! 611: return NULL; ! 612: } ! 613: return qemu_chr_open_fd(fd_in, fd_out); ! 614: } ! 615: ! 616: ! 617: /* for STDIO, we handle the case where several clients use it ! 618: (nographic mode) */ ! 619: ! 620: #define TERM_FIFO_MAX_SIZE 1 ! 621: ! 622: static uint8_t term_fifo[TERM_FIFO_MAX_SIZE]; ! 623: static int term_fifo_size; ! 624: ! 625: static int stdio_read_poll(void *opaque) ! 626: { ! 627: CharDriverState *chr = opaque; ! 628: ! 629: /* try to flush the queue if needed */ ! 630: if (term_fifo_size != 0 && qemu_chr_can_read(chr) > 0) { ! 631: qemu_chr_read(chr, term_fifo, 1); ! 632: term_fifo_size = 0; ! 633: } ! 634: /* see if we can absorb more chars */ ! 635: if (term_fifo_size == 0) ! 636: return 1; ! 637: else ! 638: return 0; ! 639: } ! 640: ! 641: static void stdio_read(void *opaque) ! 642: { ! 643: int size; ! 644: uint8_t buf[1]; ! 645: CharDriverState *chr = opaque; ! 646: ! 647: size = read(0, buf, 1); ! 648: if (size == 0) { ! 649: /* stdin has been closed. Remove it from the active list. */ ! 650: qemu_set_fd_handler2(0, NULL, NULL, NULL, NULL); ! 651: return; ! 652: } ! 653: if (size > 0) { ! 654: if (qemu_chr_can_read(chr) > 0) { ! 655: qemu_chr_read(chr, buf, 1); ! 656: } else if (term_fifo_size == 0) { ! 657: term_fifo[term_fifo_size++] = buf[0]; ! 658: } ! 659: } ! 660: } ! 661: ! 662: /* init terminal so that we can grab keys */ ! 663: static struct termios oldtty; ! 664: static int old_fd0_flags; ! 665: static int term_atexit_done; ! 666: ! 667: static void term_exit(void) ! 668: { ! 669: tcsetattr (0, TCSANOW, &oldtty); ! 670: fcntl(0, F_SETFL, old_fd0_flags); ! 671: } ! 672: ! 673: static void term_init(void) ! 674: { ! 675: struct termios tty; ! 676: ! 677: tcgetattr (0, &tty); ! 678: oldtty = tty; ! 679: old_fd0_flags = fcntl(0, F_GETFL); ! 680: ! 681: tty.c_iflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP ! 682: |INLCR|IGNCR|ICRNL|IXON); ! 683: tty.c_oflag |= OPOST; ! 684: tty.c_lflag &= ~(ECHO|ECHONL|ICANON|IEXTEN); ! 685: /* if graphical mode, we allow Ctrl-C handling */ ! 686: if (nographic) ! 687: tty.c_lflag &= ~ISIG; ! 688: tty.c_cflag &= ~(CSIZE|PARENB); ! 689: tty.c_cflag |= CS8; ! 690: tty.c_cc[VMIN] = 1; ! 691: tty.c_cc[VTIME] = 0; ! 692: ! 693: tcsetattr (0, TCSANOW, &tty); ! 694: ! 695: if (!term_atexit_done++) ! 696: atexit(term_exit); ! 697: ! 698: fcntl(0, F_SETFL, O_NONBLOCK); ! 699: } ! 700: ! 701: static void qemu_chr_close_stdio(struct CharDriverState *chr) ! 702: { ! 703: term_exit(); ! 704: stdio_nb_clients--; ! 705: qemu_set_fd_handler2(0, NULL, NULL, NULL, NULL); ! 706: fd_chr_close(chr); ! 707: } ! 708: ! 709: static CharDriverState *qemu_chr_open_stdio(void) ! 710: { ! 711: CharDriverState *chr; ! 712: ! 713: if (stdio_nb_clients >= STDIO_MAX_CLIENTS) ! 714: return NULL; ! 715: chr = qemu_chr_open_fd(0, 1); ! 716: chr->chr_close = qemu_chr_close_stdio; ! 717: qemu_set_fd_handler2(0, stdio_read_poll, stdio_read, NULL, chr); ! 718: stdio_nb_clients++; ! 719: term_init(); ! 720: ! 721: return chr; ! 722: } ! 723: ! 724: #ifdef __sun__ ! 725: /* Once Solaris has openpty(), this is going to be removed. */ ! 726: int openpty(int *amaster, int *aslave, char *name, ! 727: struct termios *termp, struct winsize *winp) ! 728: { ! 729: const char *slave; ! 730: int mfd = -1, sfd = -1; ! 731: ! 732: *amaster = *aslave = -1; ! 733: ! 734: mfd = open("/dev/ptmx", O_RDWR | O_NOCTTY); ! 735: if (mfd < 0) ! 736: goto err; ! 737: ! 738: if (grantpt(mfd) == -1 || unlockpt(mfd) == -1) ! 739: goto err; ! 740: ! 741: if ((slave = ptsname(mfd)) == NULL) ! 742: goto err; ! 743: ! 744: if ((sfd = open(slave, O_RDONLY | O_NOCTTY)) == -1) ! 745: goto err; ! 746: ! 747: if (ioctl(sfd, I_PUSH, "ptem") == -1 || ! 748: (termp != NULL && tcgetattr(sfd, termp) < 0)) ! 749: goto err; ! 750: ! 751: if (amaster) ! 752: *amaster = mfd; ! 753: if (aslave) ! 754: *aslave = sfd; ! 755: if (winp) ! 756: ioctl(sfd, TIOCSWINSZ, winp); ! 757: ! 758: return 0; ! 759: ! 760: err: ! 761: if (sfd != -1) ! 762: close(sfd); ! 763: close(mfd); ! 764: return -1; ! 765: } ! 766: ! 767: void cfmakeraw (struct termios *termios_p) ! 768: { ! 769: termios_p->c_iflag &= ! 770: ~(IGNBRK|BRKINT|PARMRK|ISTRIP|INLCR|IGNCR|ICRNL|IXON); ! 771: termios_p->c_oflag &= ~OPOST; ! 772: termios_p->c_lflag &= ~(ECHO|ECHONL|ICANON|ISIG|IEXTEN); ! 773: termios_p->c_cflag &= ~(CSIZE|PARENB); ! 774: termios_p->c_cflag |= CS8; ! 775: ! 776: termios_p->c_cc[VMIN] = 0; ! 777: termios_p->c_cc[VTIME] = 0; ! 778: } ! 779: #endif ! 780: ! 781: #if defined(__linux__) || defined(__sun__) || defined(__FreeBSD__) \ ! 782: || defined(__NetBSD__) || defined(__OpenBSD__) ! 783: ! 784: typedef struct { ! 785: int fd; ! 786: int connected; ! 787: int polling; ! 788: int read_bytes; ! 789: QEMUTimer *timer; ! 790: } PtyCharDriver; ! 791: ! 792: static void pty_chr_update_read_handler(CharDriverState *chr); ! 793: static void pty_chr_state(CharDriverState *chr, int connected); ! 794: ! 795: static int pty_chr_write(CharDriverState *chr, const uint8_t *buf, int len) ! 796: { ! 797: PtyCharDriver *s = chr->opaque; ! 798: ! 799: if (!s->connected) { ! 800: /* guest sends data, check for (re-)connect */ ! 801: pty_chr_update_read_handler(chr); ! 802: return 0; ! 803: } ! 804: return send_all(s->fd, buf, len); ! 805: } ! 806: ! 807: static int pty_chr_read_poll(void *opaque) ! 808: { ! 809: CharDriverState *chr = opaque; ! 810: PtyCharDriver *s = chr->opaque; ! 811: ! 812: s->read_bytes = qemu_chr_can_read(chr); ! 813: return s->read_bytes; ! 814: } ! 815: ! 816: static void pty_chr_read(void *opaque) ! 817: { ! 818: CharDriverState *chr = opaque; ! 819: PtyCharDriver *s = chr->opaque; ! 820: int size, len; ! 821: uint8_t buf[1024]; ! 822: ! 823: len = sizeof(buf); ! 824: if (len > s->read_bytes) ! 825: len = s->read_bytes; ! 826: if (len == 0) ! 827: return; ! 828: size = read(s->fd, buf, len); ! 829: if ((size == -1 && errno == EIO) || ! 830: (size == 0)) { ! 831: pty_chr_state(chr, 0); ! 832: return; ! 833: } ! 834: if (size > 0) { ! 835: pty_chr_state(chr, 1); ! 836: qemu_chr_read(chr, buf, size); ! 837: } ! 838: } ! 839: ! 840: static void pty_chr_update_read_handler(CharDriverState *chr) ! 841: { ! 842: PtyCharDriver *s = chr->opaque; ! 843: ! 844: qemu_set_fd_handler2(s->fd, pty_chr_read_poll, ! 845: pty_chr_read, NULL, chr); ! 846: s->polling = 1; ! 847: /* ! 848: * Short timeout here: just need wait long enougth that qemu makes ! 849: * it through the poll loop once. When reconnected we want a ! 850: * short timeout so we notice it almost instantly. Otherwise ! 851: * read() gives us -EIO instantly, making pty_chr_state() reset the ! 852: * timeout to the normal (much longer) poll interval before the ! 853: * timer triggers. ! 854: */ ! 855: qemu_mod_timer(s->timer, qemu_get_clock(rt_clock) + 10); ! 856: } ! 857: ! 858: static void pty_chr_state(CharDriverState *chr, int connected) ! 859: { ! 860: PtyCharDriver *s = chr->opaque; ! 861: ! 862: if (!connected) { ! 863: qemu_set_fd_handler2(s->fd, NULL, NULL, NULL, NULL); ! 864: s->connected = 0; ! 865: s->polling = 0; ! 866: /* (re-)connect poll interval for idle guests: once per second. ! 867: * We check more frequently in case the guests sends data to ! 868: * the virtual device linked to our pty. */ ! 869: qemu_mod_timer(s->timer, qemu_get_clock(rt_clock) + 1000); ! 870: } else { ! 871: if (!s->connected) ! 872: qemu_chr_reset(chr); ! 873: s->connected = 1; ! 874: } ! 875: } ! 876: ! 877: static void pty_chr_timer(void *opaque) ! 878: { ! 879: struct CharDriverState *chr = opaque; ! 880: PtyCharDriver *s = chr->opaque; ! 881: ! 882: if (s->connected) ! 883: return; ! 884: if (s->polling) { ! 885: /* If we arrive here without polling being cleared due ! 886: * read returning -EIO, then we are (re-)connected */ ! 887: pty_chr_state(chr, 1); ! 888: return; ! 889: } ! 890: ! 891: /* Next poll ... */ ! 892: pty_chr_update_read_handler(chr); ! 893: } ! 894: ! 895: static void pty_chr_close(struct CharDriverState *chr) ! 896: { ! 897: PtyCharDriver *s = chr->opaque; ! 898: ! 899: qemu_set_fd_handler2(s->fd, NULL, NULL, NULL, NULL); ! 900: close(s->fd); ! 901: qemu_free(s); ! 902: } ! 903: ! 904: static CharDriverState *qemu_chr_open_pty(void) ! 905: { ! 906: CharDriverState *chr; ! 907: PtyCharDriver *s; ! 908: struct termios tty; ! 909: int slave_fd, len; ! 910: #if defined(__OpenBSD__) ! 911: char pty_name[PATH_MAX]; ! 912: #define q_ptsname(x) pty_name ! 913: #else ! 914: char *pty_name = NULL; ! 915: #define q_ptsname(x) ptsname(x) ! 916: #endif ! 917: ! 918: chr = qemu_mallocz(sizeof(CharDriverState)); ! 919: s = qemu_mallocz(sizeof(PtyCharDriver)); ! 920: ! 921: if (openpty(&s->fd, &slave_fd, pty_name, NULL, NULL) < 0) { ! 922: return NULL; ! 923: } ! 924: ! 925: /* Set raw attributes on the pty. */ ! 926: tcgetattr(slave_fd, &tty); ! 927: cfmakeraw(&tty); ! 928: tcsetattr(slave_fd, TCSAFLUSH, &tty); ! 929: close(slave_fd); ! 930: ! 931: len = strlen(q_ptsname(s->fd)) + 5; ! 932: chr->filename = qemu_malloc(len); ! 933: snprintf(chr->filename, len, "pty:%s", q_ptsname(s->fd)); ! 934: fprintf(stderr, "char device redirected to %s\n", q_ptsname(s->fd)); ! 935: ! 936: chr->opaque = s; ! 937: chr->chr_write = pty_chr_write; ! 938: chr->chr_update_read_handler = pty_chr_update_read_handler; ! 939: chr->chr_close = pty_chr_close; ! 940: ! 941: s->timer = qemu_new_timer(rt_clock, pty_chr_timer, chr); ! 942: ! 943: return chr; ! 944: } ! 945: ! 946: static void tty_serial_init(int fd, int speed, ! 947: int parity, int data_bits, int stop_bits) ! 948: { ! 949: struct termios tty; ! 950: speed_t spd; ! 951: ! 952: #if 0 ! 953: printf("tty_serial_init: speed=%d parity=%c data=%d stop=%d\n", ! 954: speed, parity, data_bits, stop_bits); ! 955: #endif ! 956: tcgetattr (fd, &tty); ! 957: ! 958: #define MARGIN 1.1 ! 959: if (speed <= 50 * MARGIN) ! 960: spd = B50; ! 961: else if (speed <= 75 * MARGIN) ! 962: spd = B75; ! 963: else if (speed <= 300 * MARGIN) ! 964: spd = B300; ! 965: else if (speed <= 600 * MARGIN) ! 966: spd = B600; ! 967: else if (speed <= 1200 * MARGIN) ! 968: spd = B1200; ! 969: else if (speed <= 2400 * MARGIN) ! 970: spd = B2400; ! 971: else if (speed <= 4800 * MARGIN) ! 972: spd = B4800; ! 973: else if (speed <= 9600 * MARGIN) ! 974: spd = B9600; ! 975: else if (speed <= 19200 * MARGIN) ! 976: spd = B19200; ! 977: else if (speed <= 38400 * MARGIN) ! 978: spd = B38400; ! 979: else if (speed <= 57600 * MARGIN) ! 980: spd = B57600; ! 981: else if (speed <= 115200 * MARGIN) ! 982: spd = B115200; ! 983: else ! 984: spd = B115200; ! 985: ! 986: cfsetispeed(&tty, spd); ! 987: cfsetospeed(&tty, spd); ! 988: ! 989: tty.c_iflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP ! 990: |INLCR|IGNCR|ICRNL|IXON); ! 991: tty.c_oflag |= OPOST; ! 992: tty.c_lflag &= ~(ECHO|ECHONL|ICANON|IEXTEN|ISIG); ! 993: tty.c_cflag &= ~(CSIZE|PARENB|PARODD|CRTSCTS|CSTOPB); ! 994: switch(data_bits) { ! 995: default: ! 996: case 8: ! 997: tty.c_cflag |= CS8; ! 998: break; ! 999: case 7: ! 1000: tty.c_cflag |= CS7; ! 1001: break; ! 1002: case 6: ! 1003: tty.c_cflag |= CS6; ! 1004: break; ! 1005: case 5: ! 1006: tty.c_cflag |= CS5; ! 1007: break; ! 1008: } ! 1009: switch(parity) { ! 1010: default: ! 1011: case 'N': ! 1012: break; ! 1013: case 'E': ! 1014: tty.c_cflag |= PARENB; ! 1015: break; ! 1016: case 'O': ! 1017: tty.c_cflag |= PARENB | PARODD; ! 1018: break; ! 1019: } ! 1020: if (stop_bits == 2) ! 1021: tty.c_cflag |= CSTOPB; ! 1022: ! 1023: tcsetattr (fd, TCSANOW, &tty); ! 1024: } ! 1025: ! 1026: static int tty_serial_ioctl(CharDriverState *chr, int cmd, void *arg) ! 1027: { ! 1028: FDCharDriver *s = chr->opaque; ! 1029: ! 1030: switch(cmd) { ! 1031: case CHR_IOCTL_SERIAL_SET_PARAMS: ! 1032: { ! 1033: QEMUSerialSetParams *ssp = arg; ! 1034: tty_serial_init(s->fd_in, ssp->speed, ssp->parity, ! 1035: ssp->data_bits, ssp->stop_bits); ! 1036: } ! 1037: break; ! 1038: case CHR_IOCTL_SERIAL_SET_BREAK: ! 1039: { ! 1040: int enable = *(int *)arg; ! 1041: if (enable) ! 1042: tcsendbreak(s->fd_in, 1); ! 1043: } ! 1044: break; ! 1045: case CHR_IOCTL_SERIAL_GET_TIOCM: ! 1046: { ! 1047: int sarg = 0; ! 1048: int *targ = (int *)arg; ! 1049: ioctl(s->fd_in, TIOCMGET, &sarg); ! 1050: *targ = 0; ! 1051: if (sarg & TIOCM_CTS) ! 1052: *targ |= CHR_TIOCM_CTS; ! 1053: if (sarg & TIOCM_CAR) ! 1054: *targ |= CHR_TIOCM_CAR; ! 1055: if (sarg & TIOCM_DSR) ! 1056: *targ |= CHR_TIOCM_DSR; ! 1057: if (sarg & TIOCM_RI) ! 1058: *targ |= CHR_TIOCM_RI; ! 1059: if (sarg & TIOCM_DTR) ! 1060: *targ |= CHR_TIOCM_DTR; ! 1061: if (sarg & TIOCM_RTS) ! 1062: *targ |= CHR_TIOCM_RTS; ! 1063: } ! 1064: break; ! 1065: case CHR_IOCTL_SERIAL_SET_TIOCM: ! 1066: { ! 1067: int sarg = *(int *)arg; ! 1068: int targ = 0; ! 1069: ioctl(s->fd_in, TIOCMGET, &targ); ! 1070: targ &= ~(CHR_TIOCM_CTS | CHR_TIOCM_CAR | CHR_TIOCM_DSR ! 1071: | CHR_TIOCM_RI | CHR_TIOCM_DTR | CHR_TIOCM_RTS); ! 1072: if (sarg & CHR_TIOCM_CTS) ! 1073: targ |= TIOCM_CTS; ! 1074: if (sarg & CHR_TIOCM_CAR) ! 1075: targ |= TIOCM_CAR; ! 1076: if (sarg & CHR_TIOCM_DSR) ! 1077: targ |= TIOCM_DSR; ! 1078: if (sarg & CHR_TIOCM_RI) ! 1079: targ |= TIOCM_RI; ! 1080: if (sarg & CHR_TIOCM_DTR) ! 1081: targ |= TIOCM_DTR; ! 1082: if (sarg & CHR_TIOCM_RTS) ! 1083: targ |= TIOCM_RTS; ! 1084: ioctl(s->fd_in, TIOCMSET, &targ); ! 1085: } ! 1086: break; ! 1087: default: ! 1088: return -ENOTSUP; ! 1089: } ! 1090: return 0; ! 1091: } ! 1092: ! 1093: static CharDriverState *qemu_chr_open_tty(const char *filename) ! 1094: { ! 1095: CharDriverState *chr; ! 1096: int fd; ! 1097: ! 1098: TFR(fd = open(filename, O_RDWR | O_NONBLOCK)); ! 1099: tty_serial_init(fd, 115200, 'N', 8, 1); ! 1100: chr = qemu_chr_open_fd(fd, fd); ! 1101: if (!chr) { ! 1102: close(fd); ! 1103: return NULL; ! 1104: } ! 1105: chr->chr_ioctl = tty_serial_ioctl; ! 1106: qemu_chr_reset(chr); ! 1107: return chr; ! 1108: } ! 1109: #else /* ! __linux__ && ! __sun__ */ ! 1110: static CharDriverState *qemu_chr_open_pty(void) ! 1111: { ! 1112: return NULL; ! 1113: } ! 1114: #endif /* __linux__ || __sun__ */ ! 1115: ! 1116: #if defined(__linux__) ! 1117: typedef struct { ! 1118: int fd; ! 1119: int mode; ! 1120: } ParallelCharDriver; ! 1121: ! 1122: static int pp_hw_mode(ParallelCharDriver *s, uint16_t mode) ! 1123: { ! 1124: if (s->mode != mode) { ! 1125: int m = mode; ! 1126: if (ioctl(s->fd, PPSETMODE, &m) < 0) ! 1127: return 0; ! 1128: s->mode = mode; ! 1129: } ! 1130: return 1; ! 1131: } ! 1132: ! 1133: static int pp_ioctl(CharDriverState *chr, int cmd, void *arg) ! 1134: { ! 1135: ParallelCharDriver *drv = chr->opaque; ! 1136: int fd = drv->fd; ! 1137: uint8_t b; ! 1138: ! 1139: switch(cmd) { ! 1140: case CHR_IOCTL_PP_READ_DATA: ! 1141: if (ioctl(fd, PPRDATA, &b) < 0) ! 1142: return -ENOTSUP; ! 1143: *(uint8_t *)arg = b; ! 1144: break; ! 1145: case CHR_IOCTL_PP_WRITE_DATA: ! 1146: b = *(uint8_t *)arg; ! 1147: if (ioctl(fd, PPWDATA, &b) < 0) ! 1148: return -ENOTSUP; ! 1149: break; ! 1150: case CHR_IOCTL_PP_READ_CONTROL: ! 1151: if (ioctl(fd, PPRCONTROL, &b) < 0) ! 1152: return -ENOTSUP; ! 1153: /* Linux gives only the lowest bits, and no way to know data ! 1154: direction! For better compatibility set the fixed upper ! 1155: bits. */ ! 1156: *(uint8_t *)arg = b | 0xc0; ! 1157: break; ! 1158: case CHR_IOCTL_PP_WRITE_CONTROL: ! 1159: b = *(uint8_t *)arg; ! 1160: if (ioctl(fd, PPWCONTROL, &b) < 0) ! 1161: return -ENOTSUP; ! 1162: break; ! 1163: case CHR_IOCTL_PP_READ_STATUS: ! 1164: if (ioctl(fd, PPRSTATUS, &b) < 0) ! 1165: return -ENOTSUP; ! 1166: *(uint8_t *)arg = b; ! 1167: break; ! 1168: case CHR_IOCTL_PP_DATA_DIR: ! 1169: if (ioctl(fd, PPDATADIR, (int *)arg) < 0) ! 1170: return -ENOTSUP; ! 1171: break; ! 1172: case CHR_IOCTL_PP_EPP_READ_ADDR: ! 1173: if (pp_hw_mode(drv, IEEE1284_MODE_EPP|IEEE1284_ADDR)) { ! 1174: struct ParallelIOArg *parg = arg; ! 1175: int n = read(fd, parg->buffer, parg->count); ! 1176: if (n != parg->count) { ! 1177: return -EIO; ! 1178: } ! 1179: } ! 1180: break; ! 1181: case CHR_IOCTL_PP_EPP_READ: ! 1182: if (pp_hw_mode(drv, IEEE1284_MODE_EPP)) { ! 1183: struct ParallelIOArg *parg = arg; ! 1184: int n = read(fd, parg->buffer, parg->count); ! 1185: if (n != parg->count) { ! 1186: return -EIO; ! 1187: } ! 1188: } ! 1189: break; ! 1190: case CHR_IOCTL_PP_EPP_WRITE_ADDR: ! 1191: if (pp_hw_mode(drv, IEEE1284_MODE_EPP|IEEE1284_ADDR)) { ! 1192: struct ParallelIOArg *parg = arg; ! 1193: int n = write(fd, parg->buffer, parg->count); ! 1194: if (n != parg->count) { ! 1195: return -EIO; ! 1196: } ! 1197: } ! 1198: break; ! 1199: case CHR_IOCTL_PP_EPP_WRITE: ! 1200: if (pp_hw_mode(drv, IEEE1284_MODE_EPP)) { ! 1201: struct ParallelIOArg *parg = arg; ! 1202: int n = write(fd, parg->buffer, parg->count); ! 1203: if (n != parg->count) { ! 1204: return -EIO; ! 1205: } ! 1206: } ! 1207: break; ! 1208: default: ! 1209: return -ENOTSUP; ! 1210: } ! 1211: return 0; ! 1212: } ! 1213: ! 1214: static void pp_close(CharDriverState *chr) ! 1215: { ! 1216: ParallelCharDriver *drv = chr->opaque; ! 1217: int fd = drv->fd; ! 1218: ! 1219: pp_hw_mode(drv, IEEE1284_MODE_COMPAT); ! 1220: ioctl(fd, PPRELEASE); ! 1221: close(fd); ! 1222: qemu_free(drv); ! 1223: } ! 1224: ! 1225: static CharDriverState *qemu_chr_open_pp(const char *filename) ! 1226: { ! 1227: CharDriverState *chr; ! 1228: ParallelCharDriver *drv; ! 1229: int fd; ! 1230: ! 1231: TFR(fd = open(filename, O_RDWR)); ! 1232: if (fd < 0) ! 1233: return NULL; ! 1234: ! 1235: if (ioctl(fd, PPCLAIM) < 0) { ! 1236: close(fd); ! 1237: return NULL; ! 1238: } ! 1239: ! 1240: drv = qemu_mallocz(sizeof(ParallelCharDriver)); ! 1241: drv->fd = fd; ! 1242: drv->mode = IEEE1284_MODE_COMPAT; ! 1243: ! 1244: chr = qemu_mallocz(sizeof(CharDriverState)); ! 1245: chr->chr_write = null_chr_write; ! 1246: chr->chr_ioctl = pp_ioctl; ! 1247: chr->chr_close = pp_close; ! 1248: chr->opaque = drv; ! 1249: ! 1250: qemu_chr_reset(chr); ! 1251: ! 1252: return chr; ! 1253: } ! 1254: #endif /* __linux__ */ ! 1255: ! 1256: #if defined(__FreeBSD__) ! 1257: static int pp_ioctl(CharDriverState *chr, int cmd, void *arg) ! 1258: { ! 1259: int fd = (int)chr->opaque; ! 1260: uint8_t b; ! 1261: ! 1262: switch(cmd) { ! 1263: case CHR_IOCTL_PP_READ_DATA: ! 1264: if (ioctl(fd, PPIGDATA, &b) < 0) ! 1265: return -ENOTSUP; ! 1266: *(uint8_t *)arg = b; ! 1267: break; ! 1268: case CHR_IOCTL_PP_WRITE_DATA: ! 1269: b = *(uint8_t *)arg; ! 1270: if (ioctl(fd, PPISDATA, &b) < 0) ! 1271: return -ENOTSUP; ! 1272: break; ! 1273: case CHR_IOCTL_PP_READ_CONTROL: ! 1274: if (ioctl(fd, PPIGCTRL, &b) < 0) ! 1275: return -ENOTSUP; ! 1276: *(uint8_t *)arg = b; ! 1277: break; ! 1278: case CHR_IOCTL_PP_WRITE_CONTROL: ! 1279: b = *(uint8_t *)arg; ! 1280: if (ioctl(fd, PPISCTRL, &b) < 0) ! 1281: return -ENOTSUP; ! 1282: break; ! 1283: case CHR_IOCTL_PP_READ_STATUS: ! 1284: if (ioctl(fd, PPIGSTATUS, &b) < 0) ! 1285: return -ENOTSUP; ! 1286: *(uint8_t *)arg = b; ! 1287: break; ! 1288: default: ! 1289: return -ENOTSUP; ! 1290: } ! 1291: return 0; ! 1292: } ! 1293: ! 1294: static CharDriverState *qemu_chr_open_pp(const char *filename) ! 1295: { ! 1296: CharDriverState *chr; ! 1297: int fd; ! 1298: ! 1299: fd = open(filename, O_RDWR); ! 1300: if (fd < 0) ! 1301: return NULL; ! 1302: ! 1303: chr = qemu_mallocz(sizeof(CharDriverState)); ! 1304: chr->opaque = (void *)fd; ! 1305: chr->chr_write = null_chr_write; ! 1306: chr->chr_ioctl = pp_ioctl; ! 1307: return chr; ! 1308: } ! 1309: #endif ! 1310: ! 1311: #else /* _WIN32 */ ! 1312: ! 1313: typedef struct { ! 1314: int max_size; ! 1315: HANDLE hcom, hrecv, hsend; ! 1316: OVERLAPPED orecv, osend; ! 1317: BOOL fpipe; ! 1318: DWORD len; ! 1319: } WinCharState; ! 1320: ! 1321: #define NSENDBUF 2048 ! 1322: #define NRECVBUF 2048 ! 1323: #define MAXCONNECT 1 ! 1324: #define NTIMEOUT 5000 ! 1325: ! 1326: static int win_chr_poll(void *opaque); ! 1327: static int win_chr_pipe_poll(void *opaque); ! 1328: ! 1329: static void win_chr_close(CharDriverState *chr) ! 1330: { ! 1331: WinCharState *s = chr->opaque; ! 1332: ! 1333: if (s->hsend) { ! 1334: CloseHandle(s->hsend); ! 1335: s->hsend = NULL; ! 1336: } ! 1337: if (s->hrecv) { ! 1338: CloseHandle(s->hrecv); ! 1339: s->hrecv = NULL; ! 1340: } ! 1341: if (s->hcom) { ! 1342: CloseHandle(s->hcom); ! 1343: s->hcom = NULL; ! 1344: } ! 1345: if (s->fpipe) ! 1346: qemu_del_polling_cb(win_chr_pipe_poll, chr); ! 1347: else ! 1348: qemu_del_polling_cb(win_chr_poll, chr); ! 1349: } ! 1350: ! 1351: static int win_chr_init(CharDriverState *chr, const char *filename) ! 1352: { ! 1353: WinCharState *s = chr->opaque; ! 1354: COMMCONFIG comcfg; ! 1355: COMMTIMEOUTS cto = { 0, 0, 0, 0, 0}; ! 1356: COMSTAT comstat; ! 1357: DWORD size; ! 1358: DWORD err; ! 1359: ! 1360: s->hsend = CreateEvent(NULL, TRUE, FALSE, NULL); ! 1361: if (!s->hsend) { ! 1362: fprintf(stderr, "Failed CreateEvent\n"); ! 1363: goto fail; ! 1364: } ! 1365: s->hrecv = CreateEvent(NULL, TRUE, FALSE, NULL); ! 1366: if (!s->hrecv) { ! 1367: fprintf(stderr, "Failed CreateEvent\n"); ! 1368: goto fail; ! 1369: } ! 1370: ! 1371: s->hcom = CreateFile(filename, GENERIC_READ|GENERIC_WRITE, 0, NULL, ! 1372: OPEN_EXISTING, FILE_FLAG_OVERLAPPED, 0); ! 1373: if (s->hcom == INVALID_HANDLE_VALUE) { ! 1374: fprintf(stderr, "Failed CreateFile (%lu)\n", GetLastError()); ! 1375: s->hcom = NULL; ! 1376: goto fail; ! 1377: } ! 1378: ! 1379: if (!SetupComm(s->hcom, NRECVBUF, NSENDBUF)) { ! 1380: fprintf(stderr, "Failed SetupComm\n"); ! 1381: goto fail; ! 1382: } ! 1383: ! 1384: ZeroMemory(&comcfg, sizeof(COMMCONFIG)); ! 1385: size = sizeof(COMMCONFIG); ! 1386: GetDefaultCommConfig(filename, &comcfg, &size); ! 1387: comcfg.dcb.DCBlength = sizeof(DCB); ! 1388: CommConfigDialog(filename, NULL, &comcfg); ! 1389: ! 1390: if (!SetCommState(s->hcom, &comcfg.dcb)) { ! 1391: fprintf(stderr, "Failed SetCommState\n"); ! 1392: goto fail; ! 1393: } ! 1394: ! 1395: if (!SetCommMask(s->hcom, EV_ERR)) { ! 1396: fprintf(stderr, "Failed SetCommMask\n"); ! 1397: goto fail; ! 1398: } ! 1399: ! 1400: cto.ReadIntervalTimeout = MAXDWORD; ! 1401: if (!SetCommTimeouts(s->hcom, &cto)) { ! 1402: fprintf(stderr, "Failed SetCommTimeouts\n"); ! 1403: goto fail; ! 1404: } ! 1405: ! 1406: if (!ClearCommError(s->hcom, &err, &comstat)) { ! 1407: fprintf(stderr, "Failed ClearCommError\n"); ! 1408: goto fail; ! 1409: } ! 1410: qemu_add_polling_cb(win_chr_poll, chr); ! 1411: return 0; ! 1412: ! 1413: fail: ! 1414: win_chr_close(chr); ! 1415: return -1; ! 1416: } ! 1417: ! 1418: static int win_chr_write(CharDriverState *chr, const uint8_t *buf, int len1) ! 1419: { ! 1420: WinCharState *s = chr->opaque; ! 1421: DWORD len, ret, size, err; ! 1422: ! 1423: len = len1; ! 1424: ZeroMemory(&s->osend, sizeof(s->osend)); ! 1425: s->osend.hEvent = s->hsend; ! 1426: while (len > 0) { ! 1427: if (s->hsend) ! 1428: ret = WriteFile(s->hcom, buf, len, &size, &s->osend); ! 1429: else ! 1430: ret = WriteFile(s->hcom, buf, len, &size, NULL); ! 1431: if (!ret) { ! 1432: err = GetLastError(); ! 1433: if (err == ERROR_IO_PENDING) { ! 1434: ret = GetOverlappedResult(s->hcom, &s->osend, &size, TRUE); ! 1435: if (ret) { ! 1436: buf += size; ! 1437: len -= size; ! 1438: } else { ! 1439: break; ! 1440: } ! 1441: } else { ! 1442: break; ! 1443: } ! 1444: } else { ! 1445: buf += size; ! 1446: len -= size; ! 1447: } ! 1448: } ! 1449: return len1 - len; ! 1450: } ! 1451: ! 1452: static int win_chr_read_poll(CharDriverState *chr) ! 1453: { ! 1454: WinCharState *s = chr->opaque; ! 1455: ! 1456: s->max_size = qemu_chr_can_read(chr); ! 1457: return s->max_size; ! 1458: } ! 1459: ! 1460: static void win_chr_readfile(CharDriverState *chr) ! 1461: { ! 1462: WinCharState *s = chr->opaque; ! 1463: int ret, err; ! 1464: uint8_t buf[1024]; ! 1465: DWORD size; ! 1466: ! 1467: ZeroMemory(&s->orecv, sizeof(s->orecv)); ! 1468: s->orecv.hEvent = s->hrecv; ! 1469: ret = ReadFile(s->hcom, buf, s->len, &size, &s->orecv); ! 1470: if (!ret) { ! 1471: err = GetLastError(); ! 1472: if (err == ERROR_IO_PENDING) { ! 1473: ret = GetOverlappedResult(s->hcom, &s->orecv, &size, TRUE); ! 1474: } ! 1475: } ! 1476: ! 1477: if (size > 0) { ! 1478: qemu_chr_read(chr, buf, size); ! 1479: } ! 1480: } ! 1481: ! 1482: static void win_chr_read(CharDriverState *chr) ! 1483: { ! 1484: WinCharState *s = chr->opaque; ! 1485: ! 1486: if (s->len > s->max_size) ! 1487: s->len = s->max_size; ! 1488: if (s->len == 0) ! 1489: return; ! 1490: ! 1491: win_chr_readfile(chr); ! 1492: } ! 1493: ! 1494: static int win_chr_poll(void *opaque) ! 1495: { ! 1496: CharDriverState *chr = opaque; ! 1497: WinCharState *s = chr->opaque; ! 1498: COMSTAT status; ! 1499: DWORD comerr; ! 1500: ! 1501: ClearCommError(s->hcom, &comerr, &status); ! 1502: if (status.cbInQue > 0) { ! 1503: s->len = status.cbInQue; ! 1504: win_chr_read_poll(chr); ! 1505: win_chr_read(chr); ! 1506: return 1; ! 1507: } ! 1508: return 0; ! 1509: } ! 1510: ! 1511: static CharDriverState *qemu_chr_open_win(const char *filename) ! 1512: { ! 1513: CharDriverState *chr; ! 1514: WinCharState *s; ! 1515: ! 1516: chr = qemu_mallocz(sizeof(CharDriverState)); ! 1517: s = qemu_mallocz(sizeof(WinCharState)); ! 1518: chr->opaque = s; ! 1519: chr->chr_write = win_chr_write; ! 1520: chr->chr_close = win_chr_close; ! 1521: ! 1522: if (win_chr_init(chr, filename) < 0) { ! 1523: free(s); ! 1524: free(chr); ! 1525: return NULL; ! 1526: } ! 1527: qemu_chr_reset(chr); ! 1528: return chr; ! 1529: } ! 1530: ! 1531: static int win_chr_pipe_poll(void *opaque) ! 1532: { ! 1533: CharDriverState *chr = opaque; ! 1534: WinCharState *s = chr->opaque; ! 1535: DWORD size; ! 1536: ! 1537: PeekNamedPipe(s->hcom, NULL, 0, NULL, &size, NULL); ! 1538: if (size > 0) { ! 1539: s->len = size; ! 1540: win_chr_read_poll(chr); ! 1541: win_chr_read(chr); ! 1542: return 1; ! 1543: } ! 1544: return 0; ! 1545: } ! 1546: ! 1547: static int win_chr_pipe_init(CharDriverState *chr, const char *filename) ! 1548: { ! 1549: WinCharState *s = chr->opaque; ! 1550: OVERLAPPED ov; ! 1551: int ret; ! 1552: DWORD size; ! 1553: char openname[256]; ! 1554: ! 1555: s->fpipe = TRUE; ! 1556: ! 1557: s->hsend = CreateEvent(NULL, TRUE, FALSE, NULL); ! 1558: if (!s->hsend) { ! 1559: fprintf(stderr, "Failed CreateEvent\n"); ! 1560: goto fail; ! 1561: } ! 1562: s->hrecv = CreateEvent(NULL, TRUE, FALSE, NULL); ! 1563: if (!s->hrecv) { ! 1564: fprintf(stderr, "Failed CreateEvent\n"); ! 1565: goto fail; ! 1566: } ! 1567: ! 1568: snprintf(openname, sizeof(openname), "\\\\.\\pipe\\%s", filename); ! 1569: s->hcom = CreateNamedPipe(openname, PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED, ! 1570: PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | ! 1571: PIPE_WAIT, ! 1572: MAXCONNECT, NSENDBUF, NRECVBUF, NTIMEOUT, NULL); ! 1573: if (s->hcom == INVALID_HANDLE_VALUE) { ! 1574: fprintf(stderr, "Failed CreateNamedPipe (%lu)\n", GetLastError()); ! 1575: s->hcom = NULL; ! 1576: goto fail; ! 1577: } ! 1578: ! 1579: ZeroMemory(&ov, sizeof(ov)); ! 1580: ov.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL); ! 1581: ret = ConnectNamedPipe(s->hcom, &ov); ! 1582: if (ret) { ! 1583: fprintf(stderr, "Failed ConnectNamedPipe\n"); ! 1584: goto fail; ! 1585: } ! 1586: ! 1587: ret = GetOverlappedResult(s->hcom, &ov, &size, TRUE); ! 1588: if (!ret) { ! 1589: fprintf(stderr, "Failed GetOverlappedResult\n"); ! 1590: if (ov.hEvent) { ! 1591: CloseHandle(ov.hEvent); ! 1592: ov.hEvent = NULL; ! 1593: } ! 1594: goto fail; ! 1595: } ! 1596: ! 1597: if (ov.hEvent) { ! 1598: CloseHandle(ov.hEvent); ! 1599: ov.hEvent = NULL; ! 1600: } ! 1601: qemu_add_polling_cb(win_chr_pipe_poll, chr); ! 1602: return 0; ! 1603: ! 1604: fail: ! 1605: win_chr_close(chr); ! 1606: return -1; ! 1607: } ! 1608: ! 1609: ! 1610: static CharDriverState *qemu_chr_open_win_pipe(const char *filename) ! 1611: { ! 1612: CharDriverState *chr; ! 1613: WinCharState *s; ! 1614: ! 1615: chr = qemu_mallocz(sizeof(CharDriverState)); ! 1616: s = qemu_mallocz(sizeof(WinCharState)); ! 1617: chr->opaque = s; ! 1618: chr->chr_write = win_chr_write; ! 1619: chr->chr_close = win_chr_close; ! 1620: ! 1621: if (win_chr_pipe_init(chr, filename) < 0) { ! 1622: free(s); ! 1623: free(chr); ! 1624: return NULL; ! 1625: } ! 1626: qemu_chr_reset(chr); ! 1627: return chr; ! 1628: } ! 1629: ! 1630: static CharDriverState *qemu_chr_open_win_file(HANDLE fd_out) ! 1631: { ! 1632: CharDriverState *chr; ! 1633: WinCharState *s; ! 1634: ! 1635: chr = qemu_mallocz(sizeof(CharDriverState)); ! 1636: s = qemu_mallocz(sizeof(WinCharState)); ! 1637: s->hcom = fd_out; ! 1638: chr->opaque = s; ! 1639: chr->chr_write = win_chr_write; ! 1640: qemu_chr_reset(chr); ! 1641: return chr; ! 1642: } ! 1643: ! 1644: static CharDriverState *qemu_chr_open_win_con(const char *filename) ! 1645: { ! 1646: return qemu_chr_open_win_file(GetStdHandle(STD_OUTPUT_HANDLE)); ! 1647: } ! 1648: ! 1649: static CharDriverState *qemu_chr_open_win_file_out(const char *file_out) ! 1650: { ! 1651: HANDLE fd_out; ! 1652: ! 1653: fd_out = CreateFile(file_out, GENERIC_WRITE, FILE_SHARE_READ, NULL, ! 1654: OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); ! 1655: if (fd_out == INVALID_HANDLE_VALUE) ! 1656: return NULL; ! 1657: ! 1658: return qemu_chr_open_win_file(fd_out); ! 1659: } ! 1660: #endif /* !_WIN32 */ ! 1661: ! 1662: /***********************************************************/ ! 1663: /* UDP Net console */ ! 1664: ! 1665: typedef struct { ! 1666: int fd; ! 1667: struct sockaddr_in daddr; ! 1668: uint8_t buf[1024]; ! 1669: int bufcnt; ! 1670: int bufptr; ! 1671: int max_size; ! 1672: } NetCharDriver; ! 1673: ! 1674: static int udp_chr_write(CharDriverState *chr, const uint8_t *buf, int len) ! 1675: { ! 1676: NetCharDriver *s = chr->opaque; ! 1677: ! 1678: return sendto(s->fd, buf, len, 0, ! 1679: (struct sockaddr *)&s->daddr, sizeof(struct sockaddr_in)); ! 1680: } ! 1681: ! 1682: static int udp_chr_read_poll(void *opaque) ! 1683: { ! 1684: CharDriverState *chr = opaque; ! 1685: NetCharDriver *s = chr->opaque; ! 1686: ! 1687: s->max_size = qemu_chr_can_read(chr); ! 1688: ! 1689: /* If there were any stray characters in the queue process them ! 1690: * first ! 1691: */ ! 1692: while (s->max_size > 0 && s->bufptr < s->bufcnt) { ! 1693: qemu_chr_read(chr, &s->buf[s->bufptr], 1); ! 1694: s->bufptr++; ! 1695: s->max_size = qemu_chr_can_read(chr); ! 1696: } ! 1697: return s->max_size; ! 1698: } ! 1699: ! 1700: static void udp_chr_read(void *opaque) ! 1701: { ! 1702: CharDriverState *chr = opaque; ! 1703: NetCharDriver *s = chr->opaque; ! 1704: ! 1705: if (s->max_size == 0) ! 1706: return; ! 1707: s->bufcnt = recv(s->fd, s->buf, sizeof(s->buf), 0); ! 1708: s->bufptr = s->bufcnt; ! 1709: if (s->bufcnt <= 0) ! 1710: return; ! 1711: ! 1712: s->bufptr = 0; ! 1713: while (s->max_size > 0 && s->bufptr < s->bufcnt) { ! 1714: qemu_chr_read(chr, &s->buf[s->bufptr], 1); ! 1715: s->bufptr++; ! 1716: s->max_size = qemu_chr_can_read(chr); ! 1717: } ! 1718: } ! 1719: ! 1720: static void udp_chr_update_read_handler(CharDriverState *chr) ! 1721: { ! 1722: NetCharDriver *s = chr->opaque; ! 1723: ! 1724: if (s->fd >= 0) { ! 1725: qemu_set_fd_handler2(s->fd, udp_chr_read_poll, ! 1726: udp_chr_read, NULL, chr); ! 1727: } ! 1728: } ! 1729: ! 1730: static CharDriverState *qemu_chr_open_udp(const char *def) ! 1731: { ! 1732: CharDriverState *chr = NULL; ! 1733: NetCharDriver *s = NULL; ! 1734: int fd = -1; ! 1735: struct sockaddr_in saddr; ! 1736: ! 1737: chr = qemu_mallocz(sizeof(CharDriverState)); ! 1738: s = qemu_mallocz(sizeof(NetCharDriver)); ! 1739: ! 1740: fd = socket(PF_INET, SOCK_DGRAM, 0); ! 1741: if (fd < 0) { ! 1742: perror("socket(PF_INET, SOCK_DGRAM)"); ! 1743: goto return_err; ! 1744: } ! 1745: ! 1746: if (parse_host_src_port(&s->daddr, &saddr, def) < 0) { ! 1747: printf("Could not parse: %s\n", def); ! 1748: goto return_err; ! 1749: } ! 1750: ! 1751: if (bind(fd, (struct sockaddr *)&saddr, sizeof(saddr)) < 0) ! 1752: { ! 1753: perror("bind"); ! 1754: goto return_err; ! 1755: } ! 1756: ! 1757: s->fd = fd; ! 1758: s->bufcnt = 0; ! 1759: s->bufptr = 0; ! 1760: chr->opaque = s; ! 1761: chr->chr_write = udp_chr_write; ! 1762: chr->chr_update_read_handler = udp_chr_update_read_handler; ! 1763: return chr; ! 1764: ! 1765: return_err: ! 1766: if (chr) ! 1767: free(chr); ! 1768: if (s) ! 1769: free(s); ! 1770: if (fd >= 0) ! 1771: closesocket(fd); ! 1772: return NULL; ! 1773: } ! 1774: ! 1775: /***********************************************************/ ! 1776: /* TCP Net console */ ! 1777: ! 1778: typedef struct { ! 1779: int fd, listen_fd; ! 1780: int connected; ! 1781: int max_size; ! 1782: int do_telnetopt; ! 1783: int do_nodelay; ! 1784: int is_unix; ! 1785: } TCPCharDriver; ! 1786: ! 1787: static void tcp_chr_accept(void *opaque); ! 1788: ! 1789: static int tcp_chr_write(CharDriverState *chr, const uint8_t *buf, int len) ! 1790: { ! 1791: TCPCharDriver *s = chr->opaque; ! 1792: if (s->connected) { ! 1793: return send_all(s->fd, buf, len); ! 1794: } else { ! 1795: /* XXX: indicate an error ? */ ! 1796: return len; ! 1797: } ! 1798: } ! 1799: ! 1800: static int tcp_chr_read_poll(void *opaque) ! 1801: { ! 1802: CharDriverState *chr = opaque; ! 1803: TCPCharDriver *s = chr->opaque; ! 1804: if (!s->connected) ! 1805: return 0; ! 1806: s->max_size = qemu_chr_can_read(chr); ! 1807: return s->max_size; ! 1808: } ! 1809: ! 1810: #define IAC 255 ! 1811: #define IAC_BREAK 243 ! 1812: static void tcp_chr_process_IAC_bytes(CharDriverState *chr, ! 1813: TCPCharDriver *s, ! 1814: uint8_t *buf, int *size) ! 1815: { ! 1816: /* Handle any telnet client's basic IAC options to satisfy char by ! 1817: * char mode with no echo. All IAC options will be removed from ! 1818: * the buf and the do_telnetopt variable will be used to track the ! 1819: * state of the width of the IAC information. ! 1820: * ! 1821: * IAC commands come in sets of 3 bytes with the exception of the ! 1822: * "IAC BREAK" command and the double IAC. ! 1823: */ ! 1824: ! 1825: int i; ! 1826: int j = 0; ! 1827: ! 1828: for (i = 0; i < *size; i++) { ! 1829: if (s->do_telnetopt > 1) { ! 1830: if ((unsigned char)buf[i] == IAC && s->do_telnetopt == 2) { ! 1831: /* Double IAC means send an IAC */ ! 1832: if (j != i) ! 1833: buf[j] = buf[i]; ! 1834: j++; ! 1835: s->do_telnetopt = 1; ! 1836: } else { ! 1837: if ((unsigned char)buf[i] == IAC_BREAK && s->do_telnetopt == 2) { ! 1838: /* Handle IAC break commands by sending a serial break */ ! 1839: qemu_chr_event(chr, CHR_EVENT_BREAK); ! 1840: s->do_telnetopt++; ! 1841: } ! 1842: s->do_telnetopt++; ! 1843: } ! 1844: if (s->do_telnetopt >= 4) { ! 1845: s->do_telnetopt = 1; ! 1846: } ! 1847: } else { ! 1848: if ((unsigned char)buf[i] == IAC) { ! 1849: s->do_telnetopt = 2; ! 1850: } else { ! 1851: if (j != i) ! 1852: buf[j] = buf[i]; ! 1853: j++; ! 1854: } ! 1855: } ! 1856: } ! 1857: *size = j; ! 1858: } ! 1859: ! 1860: static void tcp_chr_read(void *opaque) ! 1861: { ! 1862: CharDriverState *chr = opaque; ! 1863: TCPCharDriver *s = chr->opaque; ! 1864: uint8_t buf[1024]; ! 1865: int len, size; ! 1866: ! 1867: if (!s->connected || s->max_size <= 0) ! 1868: return; ! 1869: len = sizeof(buf); ! 1870: if (len > s->max_size) ! 1871: len = s->max_size; ! 1872: size = recv(s->fd, buf, len, 0); ! 1873: if (size == 0) { ! 1874: /* connection closed */ ! 1875: s->connected = 0; ! 1876: if (s->listen_fd >= 0) { ! 1877: qemu_set_fd_handler(s->listen_fd, tcp_chr_accept, NULL, chr); ! 1878: } ! 1879: qemu_set_fd_handler(s->fd, NULL, NULL, NULL); ! 1880: closesocket(s->fd); ! 1881: s->fd = -1; ! 1882: } else if (size > 0) { ! 1883: if (s->do_telnetopt) ! 1884: tcp_chr_process_IAC_bytes(chr, s, buf, &size); ! 1885: if (size > 0) ! 1886: qemu_chr_read(chr, buf, size); ! 1887: } ! 1888: } ! 1889: ! 1890: static void tcp_chr_connect(void *opaque) ! 1891: { ! 1892: CharDriverState *chr = opaque; ! 1893: TCPCharDriver *s = chr->opaque; ! 1894: ! 1895: s->connected = 1; ! 1896: qemu_set_fd_handler2(s->fd, tcp_chr_read_poll, ! 1897: tcp_chr_read, NULL, chr); ! 1898: qemu_chr_reset(chr); ! 1899: } ! 1900: ! 1901: #define IACSET(x,a,b,c) x[0] = a; x[1] = b; x[2] = c; ! 1902: static void tcp_chr_telnet_init(int fd) ! 1903: { ! 1904: char buf[3]; ! 1905: /* Send the telnet negotion to put telnet in binary, no echo, single char mode */ ! 1906: IACSET(buf, 0xff, 0xfb, 0x01); /* IAC WILL ECHO */ ! 1907: send(fd, (char *)buf, 3, 0); ! 1908: IACSET(buf, 0xff, 0xfb, 0x03); /* IAC WILL Suppress go ahead */ ! 1909: send(fd, (char *)buf, 3, 0); ! 1910: IACSET(buf, 0xff, 0xfb, 0x00); /* IAC WILL Binary */ ! 1911: send(fd, (char *)buf, 3, 0); ! 1912: IACSET(buf, 0xff, 0xfd, 0x00); /* IAC DO Binary */ ! 1913: send(fd, (char *)buf, 3, 0); ! 1914: } ! 1915: ! 1916: static void socket_set_nodelay(int fd) ! 1917: { ! 1918: int val = 1; ! 1919: setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, (char *)&val, sizeof(val)); ! 1920: } ! 1921: ! 1922: static void tcp_chr_accept(void *opaque) ! 1923: { ! 1924: CharDriverState *chr = opaque; ! 1925: TCPCharDriver *s = chr->opaque; ! 1926: struct sockaddr_in saddr; ! 1927: #ifndef _WIN32 ! 1928: struct sockaddr_un uaddr; ! 1929: #endif ! 1930: struct sockaddr *addr; ! 1931: socklen_t len; ! 1932: int fd; ! 1933: ! 1934: for(;;) { ! 1935: #ifndef _WIN32 ! 1936: if (s->is_unix) { ! 1937: len = sizeof(uaddr); ! 1938: addr = (struct sockaddr *)&uaddr; ! 1939: } else ! 1940: #endif ! 1941: { ! 1942: len = sizeof(saddr); ! 1943: addr = (struct sockaddr *)&saddr; ! 1944: } ! 1945: fd = accept(s->listen_fd, addr, &len); ! 1946: if (fd < 0 && errno != EINTR) { ! 1947: return; ! 1948: } else if (fd >= 0) { ! 1949: if (s->do_telnetopt) ! 1950: tcp_chr_telnet_init(fd); ! 1951: break; ! 1952: } ! 1953: } ! 1954: socket_set_nonblock(fd); ! 1955: if (s->do_nodelay) ! 1956: socket_set_nodelay(fd); ! 1957: s->fd = fd; ! 1958: qemu_set_fd_handler(s->listen_fd, NULL, NULL, NULL); ! 1959: tcp_chr_connect(chr); ! 1960: } ! 1961: ! 1962: static void tcp_chr_close(CharDriverState *chr) ! 1963: { ! 1964: TCPCharDriver *s = chr->opaque; ! 1965: if (s->fd >= 0) ! 1966: closesocket(s->fd); ! 1967: if (s->listen_fd >= 0) ! 1968: closesocket(s->listen_fd); ! 1969: qemu_free(s); ! 1970: } ! 1971: ! 1972: static CharDriverState *qemu_chr_open_tcp(const char *host_str, ! 1973: int is_telnet, ! 1974: int is_unix) ! 1975: { ! 1976: CharDriverState *chr = NULL; ! 1977: TCPCharDriver *s = NULL; ! 1978: int fd = -1, offset = 0; ! 1979: int is_listen = 0; ! 1980: int is_waitconnect = 1; ! 1981: int do_nodelay = 0; ! 1982: const char *ptr; ! 1983: ! 1984: ptr = host_str; ! 1985: while((ptr = strchr(ptr,','))) { ! 1986: ptr++; ! 1987: if (!strncmp(ptr,"server",6)) { ! 1988: is_listen = 1; ! 1989: } else if (!strncmp(ptr,"nowait",6)) { ! 1990: is_waitconnect = 0; ! 1991: } else if (!strncmp(ptr,"nodelay",6)) { ! 1992: do_nodelay = 1; ! 1993: } else if (!strncmp(ptr,"to=",3)) { ! 1994: /* nothing, inet_listen() parses this one */; ! 1995: } else if (!strncmp(ptr,"ipv4",4)) { ! 1996: /* nothing, inet_connect() and inet_listen() parse this one */; ! 1997: } else if (!strncmp(ptr,"ipv6",4)) { ! 1998: /* nothing, inet_connect() and inet_listen() parse this one */; ! 1999: } else { ! 2000: printf("Unknown option: %s\n", ptr); ! 2001: goto fail; ! 2002: } ! 2003: } ! 2004: if (!is_listen) ! 2005: is_waitconnect = 0; ! 2006: ! 2007: chr = qemu_mallocz(sizeof(CharDriverState)); ! 2008: s = qemu_mallocz(sizeof(TCPCharDriver)); ! 2009: ! 2010: if (is_listen) { ! 2011: chr->filename = qemu_malloc(256); ! 2012: if (is_unix) { ! 2013: pstrcpy(chr->filename, 256, "unix:"); ! 2014: } else if (is_telnet) { ! 2015: pstrcpy(chr->filename, 256, "telnet:"); ! 2016: } else { ! 2017: pstrcpy(chr->filename, 256, "tcp:"); ! 2018: } ! 2019: offset = strlen(chr->filename); ! 2020: } ! 2021: if (is_unix) { ! 2022: if (is_listen) { ! 2023: fd = unix_listen(host_str, chr->filename + offset, 256 - offset); ! 2024: } else { ! 2025: fd = unix_connect(host_str); ! 2026: } ! 2027: } else { ! 2028: if (is_listen) { ! 2029: fd = inet_listen(host_str, chr->filename + offset, 256 - offset, ! 2030: SOCK_STREAM, 0); ! 2031: } else { ! 2032: fd = inet_connect(host_str, SOCK_STREAM); ! 2033: } ! 2034: } ! 2035: if (fd < 0) ! 2036: goto fail; ! 2037: ! 2038: if (!is_waitconnect) ! 2039: socket_set_nonblock(fd); ! 2040: ! 2041: s->connected = 0; ! 2042: s->fd = -1; ! 2043: s->listen_fd = -1; ! 2044: s->is_unix = is_unix; ! 2045: s->do_nodelay = do_nodelay && !is_unix; ! 2046: ! 2047: chr->opaque = s; ! 2048: chr->chr_write = tcp_chr_write; ! 2049: chr->chr_close = tcp_chr_close; ! 2050: ! 2051: if (is_listen) { ! 2052: s->listen_fd = fd; ! 2053: qemu_set_fd_handler(s->listen_fd, tcp_chr_accept, NULL, chr); ! 2054: if (is_telnet) ! 2055: s->do_telnetopt = 1; ! 2056: } else { ! 2057: s->connected = 1; ! 2058: s->fd = fd; ! 2059: socket_set_nodelay(fd); ! 2060: tcp_chr_connect(chr); ! 2061: } ! 2062: ! 2063: if (is_listen && is_waitconnect) { ! 2064: printf("QEMU waiting for connection on: %s\n", ! 2065: chr->filename ? chr->filename : host_str); ! 2066: tcp_chr_accept(chr); ! 2067: socket_set_nonblock(s->listen_fd); ! 2068: } ! 2069: ! 2070: return chr; ! 2071: fail: ! 2072: if (fd >= 0) ! 2073: closesocket(fd); ! 2074: qemu_free(s); ! 2075: qemu_free(chr); ! 2076: return NULL; ! 2077: } ! 2078: ! 2079: static TAILQ_HEAD(CharDriverStateHead, CharDriverState) chardevs ! 2080: = TAILQ_HEAD_INITIALIZER(chardevs); ! 2081: ! 2082: CharDriverState *qemu_chr_open(const char *label, const char *filename, void (*init)(struct CharDriverState *s)) ! 2083: { ! 2084: const char *p; ! 2085: CharDriverState *chr; ! 2086: ! 2087: if (!strcmp(filename, "vc")) { ! 2088: chr = text_console_init(0); ! 2089: } else ! 2090: if (strstart(filename, "vc:", &p)) { ! 2091: chr = text_console_init(p); ! 2092: } else ! 2093: if (!strcmp(filename, "null")) { ! 2094: chr = qemu_chr_open_null(); ! 2095: } else ! 2096: if (strstart(filename, "tcp:", &p)) { ! 2097: chr = qemu_chr_open_tcp(p, 0, 0); ! 2098: } else ! 2099: if (strstart(filename, "telnet:", &p)) { ! 2100: chr = qemu_chr_open_tcp(p, 1, 0); ! 2101: } else ! 2102: if (strstart(filename, "udp:", &p)) { ! 2103: chr = qemu_chr_open_udp(p); ! 2104: } else ! 2105: if (strstart(filename, "mon:", &p)) { ! 2106: chr = qemu_chr_open(label, p, NULL); ! 2107: if (chr) { ! 2108: chr = qemu_chr_open_mux(chr); ! 2109: monitor_init(chr, !nographic); ! 2110: } else { ! 2111: printf("Unable to open driver: %s\n", p); ! 2112: } ! 2113: } else if (!strcmp(filename, "msmouse")) { ! 2114: chr = qemu_chr_open_msmouse(); ! 2115: } else ! 2116: #ifndef _WIN32 ! 2117: if (strstart(filename, "unix:", &p)) { ! 2118: chr = qemu_chr_open_tcp(p, 0, 1); ! 2119: } else if (strstart(filename, "file:", &p)) { ! 2120: chr = qemu_chr_open_file_out(p); ! 2121: } else if (strstart(filename, "pipe:", &p)) { ! 2122: chr = qemu_chr_open_pipe(p); ! 2123: } else if (!strcmp(filename, "pty")) { ! 2124: chr = qemu_chr_open_pty(); ! 2125: } else if (!strcmp(filename, "stdio")) { ! 2126: chr = qemu_chr_open_stdio(); ! 2127: } else ! 2128: #if defined(__linux__) ! 2129: if (strstart(filename, "/dev/parport", NULL)) { ! 2130: chr = qemu_chr_open_pp(filename); ! 2131: } else ! 2132: #elif defined(__FreeBSD__) ! 2133: if (strstart(filename, "/dev/ppi", NULL)) { ! 2134: chr = qemu_chr_open_pp(filename); ! 2135: } else ! 2136: #endif ! 2137: #if defined(__linux__) || defined(__sun__) || defined(__FreeBSD__) \ ! 2138: || defined(__NetBSD__) || defined(__OpenBSD__) ! 2139: if (strstart(filename, "/dev/", NULL)) { ! 2140: chr = qemu_chr_open_tty(filename); ! 2141: } else ! 2142: #endif ! 2143: #else /* !_WIN32 */ ! 2144: if (strstart(filename, "COM", NULL)) { ! 2145: chr = qemu_chr_open_win(filename); ! 2146: } else ! 2147: if (strstart(filename, "pipe:", &p)) { ! 2148: chr = qemu_chr_open_win_pipe(p); ! 2149: } else ! 2150: if (strstart(filename, "con:", NULL)) { ! 2151: chr = qemu_chr_open_win_con(filename); ! 2152: } else ! 2153: if (strstart(filename, "file:", &p)) { ! 2154: chr = qemu_chr_open_win_file_out(p); ! 2155: } else ! 2156: #endif ! 2157: #ifdef CONFIG_BRLAPI ! 2158: if (!strcmp(filename, "braille")) { ! 2159: chr = chr_baum_init(); ! 2160: } else ! 2161: #endif ! 2162: { ! 2163: chr = NULL; ! 2164: } ! 2165: ! 2166: if (chr) { ! 2167: if (!chr->filename) ! 2168: chr->filename = qemu_strdup(filename); ! 2169: chr->init = init; ! 2170: chr->label = qemu_strdup(label); ! 2171: TAILQ_INSERT_TAIL(&chardevs, chr, next); ! 2172: } ! 2173: return chr; ! 2174: } ! 2175: ! 2176: void qemu_chr_close(CharDriverState *chr) ! 2177: { ! 2178: TAILQ_REMOVE(&chardevs, chr, next); ! 2179: if (chr->chr_close) ! 2180: chr->chr_close(chr); ! 2181: qemu_free(chr->filename); ! 2182: qemu_free(chr->label); ! 2183: qemu_free(chr); ! 2184: } ! 2185: ! 2186: void qemu_chr_info(void) ! 2187: { ! 2188: CharDriverState *chr; ! 2189: ! 2190: TAILQ_FOREACH(chr, &chardevs, next) { ! 2191: term_printf("%s: filename=%s\n", chr->label, chr->filename); ! 2192: } ! 2193: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.