Commit 20d8a3edb062c96f9a08ccf0637f76ae2563c5e1

Authored by ths
1 parent 925fd0f2

Monitor multiplexing, by Jason Wessel.


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2434 c046a42c-6fe2-441c-8c8c-71466251a162
monitor.c
... ... @@ -54,7 +54,8 @@ typedef struct term_cmd_t {
54 54 const char *help;
55 55 } term_cmd_t;
56 56  
57   -static CharDriverState *monitor_hd;
  57 +#define MAX_MON 4
  58 +static CharDriverState *monitor_hd[MAX_MON];
58 59 static int hide_banner;
59 60  
60 61 static term_cmd_t term_cmds[];
... ... @@ -69,8 +70,11 @@ CPUState *mon_cpu = NULL;
69 70  
70 71 void term_flush(void)
71 72 {
  73 + int i;
72 74 if (term_outbuf_index > 0) {
73   - qemu_chr_write(monitor_hd, term_outbuf, term_outbuf_index);
  75 + for (i = 0; i < MAX_MON; i++)
  76 + if (monitor_hd[i] && monitor_hd[i]->focus == 0)
  77 + qemu_chr_write(monitor_hd[i], term_outbuf, term_outbuf_index);
74 78 term_outbuf_index = 0;
75 79 }
76 80 }
... ... @@ -2452,9 +2456,25 @@ static void term_event(void *opaque, int event)
2452 2456 monitor_start_input();
2453 2457 }
2454 2458  
  2459 +static int is_first_init = 1;
  2460 +
2455 2461 void monitor_init(CharDriverState *hd, int show_banner)
2456 2462 {
2457   - monitor_hd = hd;
  2463 + int i;
  2464 +
  2465 + if (is_first_init) {
  2466 + for (i = 0; i < MAX_MON; i++) {
  2467 + monitor_hd[i] = NULL;
  2468 + }
  2469 + is_first_init = 0;
  2470 + }
  2471 + for (i = 0; i < MAX_MON; i++) {
  2472 + if (monitor_hd[i] == NULL) {
  2473 + monitor_hd[i] = hd;
  2474 + break;
  2475 + }
  2476 + }
  2477 +
2458 2478 hide_banner = !show_banner;
2459 2479  
2460 2480 qemu_chr_add_handlers(hd, term_can_read, term_read, term_event, NULL);
... ... @@ -2475,8 +2495,12 @@ static void monitor_readline_cb(void *opaque, const char *input)
2475 2495 void monitor_readline(const char *prompt, int is_password,
2476 2496 char *buf, int buf_size)
2477 2497 {
  2498 + int i;
  2499 +
2478 2500 if (is_password) {
2479   - qemu_chr_send_event(monitor_hd, CHR_EVENT_FOCUS);
  2501 + for (i = 0; i < MAX_MON; i++)
  2502 + if (monitor_hd[i] && monitor_hd[i]->focus == 0)
  2503 + qemu_chr_send_event(monitor_hd[i], CHR_EVENT_FOCUS);
2480 2504 }
2481 2505 readline_start(prompt, is_password, monitor_readline_cb, NULL);
2482 2506 monitor_readline_buf = buf;
... ...
qemu-doc.texi
... ... @@ -610,6 +610,18 @@ A unix domain socket is used instead of a tcp socket. The option works the
610 610 same as if you had specified @code{-serial tcp} except the unix domain socket
611 611 @var{path} is used for connections.
612 612  
  613 +@item mon:dev_string
  614 +This is a special option to allow the monitor to be multiplexed onto
  615 +another serial port. The monitor is accessed with key sequence of
  616 +@key{Control-a} and then pressing @key{c}. See monitor access
  617 +@ref{pcsys_keys} in the -nographic section for more keys.
  618 +@var{dev_string} should be any one of the serial devices specified
  619 +above. An example to multiplex the monitor onto a telnet server
  620 +listening on port 4444 would be:
  621 +@table @code
  622 +@item -serial mon:telnet::4444,server,nowait
  623 +@end table
  624 +
613 625 @end table
614 626  
615 627 @item -parallel dev
... ... @@ -629,6 +641,19 @@ serial port).
629 641 The default device is @code{vc} in graphical mode and @code{stdio} in
630 642 non graphical mode.
631 643  
  644 +@item -echr numeric_ascii_value
  645 +Change the escape character used for switching to the monitor when using
  646 +monitor and serial sharing. The default is @code{0x01} when using the
  647 +@code{-nographic} option. @code{0x01} is equal to pressing
  648 +@code{Control-a}. You can select a different character from the ascii
  649 +control keys where 1 through 26 map to Control-a through Control-z. For
  650 +instance you could use the either of the following to change the escape
  651 +character to Control-t.
  652 +@table @code
  653 +@item -echr 0x14
  654 +@item -echr 20
  655 +@end table
  656 +
632 657 @item -s
633 658 Wait gdb connection to port 1234 (@pxref{gdb_usage}).
634 659 @item -p port
... ... @@ -711,6 +736,8 @@ Print this help
711 736 Exit emulator
712 737 @item Ctrl-a s
713 738 Save disk data back to file (if -snapshot)
  739 +@item Ctrl-a t
  740 +toggle console timestamps
714 741 @item Ctrl-a b
715 742 Send break (magic sysrq in Linux)
716 743 @item Ctrl-a c
... ...
... ... @@ -1228,6 +1228,218 @@ static CharDriverState *qemu_chr_open_null(void)
1228 1228 return chr;
1229 1229 }
1230 1230  
  1231 +/* MUX driver for serial I/O splitting */
  1232 +static int term_timestamps;
  1233 +static int64_t term_timestamps_start;
  1234 +#define MAX_MUX 2
  1235 +typedef struct {
  1236 + IOCanRWHandler *chr_can_read[MAX_MUX];
  1237 + IOReadHandler *chr_read[MAX_MUX];
  1238 + IOEventHandler *chr_event[MAX_MUX];
  1239 + void *ext_opaque[MAX_MUX];
  1240 + CharDriverState *drv;
  1241 + int mux_cnt;
  1242 + int term_got_escape;
  1243 + int max_size;
  1244 +} MuxDriver;
  1245 +
  1246 +
  1247 +static int mux_chr_write(CharDriverState *chr, const uint8_t *buf, int len)
  1248 +{
  1249 + MuxDriver *d = chr->opaque;
  1250 + int ret;
  1251 + if (!term_timestamps) {
  1252 + ret = d->drv->chr_write(d->drv, buf, len);
  1253 + } else {
  1254 + int i;
  1255 +
  1256 + ret = 0;
  1257 + for(i = 0; i < len; i++) {
  1258 + ret += d->drv->chr_write(d->drv, buf+i, 1);
  1259 + if (buf[i] == '\n') {
  1260 + char buf1[64];
  1261 + int64_t ti;
  1262 + int secs;
  1263 +
  1264 + ti = get_clock();
  1265 + if (term_timestamps_start == -1)
  1266 + term_timestamps_start = ti;
  1267 + ti -= term_timestamps_start;
  1268 + secs = ti / 1000000000;
  1269 + snprintf(buf1, sizeof(buf1),
  1270 + "[%02d:%02d:%02d.%03d] ",
  1271 + secs / 3600,
  1272 + (secs / 60) % 60,
  1273 + secs % 60,
  1274 + (int)((ti / 1000000) % 1000));
  1275 + d->drv->chr_write(d->drv, buf1, strlen(buf1));
  1276 + }
  1277 + }
  1278 + }
  1279 + return ret;
  1280 +}
  1281 +
  1282 +static char *mux_help[] = {
  1283 + "% h print this help\n\r",
  1284 + "% x exit emulator\n\r",
  1285 + "% s save disk data back to file (if -snapshot)\n\r",
  1286 + "% t toggle console timestamps\n\r"
  1287 + "% b send break (magic sysrq)\n\r",
  1288 + "% c switch between console and monitor\n\r",
  1289 + "% % sends %\n\r",
  1290 + NULL
  1291 +};
  1292 +
  1293 +static int term_escape_char = 0x01; /* ctrl-a is used for escape */
  1294 +static void mux_print_help(CharDriverState *chr)
  1295 +{
  1296 + int i, j;
  1297 + char ebuf[15] = "Escape-Char";
  1298 + char cbuf[50] = "\n\r";
  1299 +
  1300 + if (term_escape_char > 0 && term_escape_char < 26) {
  1301 + sprintf(cbuf,"\n\r");
  1302 + sprintf(ebuf,"C-%c", term_escape_char - 1 + 'a');
  1303 + } else {
  1304 + sprintf(cbuf,"\n\rEscape-Char set to Ascii: 0x%02x\n\r\n\r", term_escape_char);
  1305 + }
  1306 + chr->chr_write(chr, cbuf, strlen(cbuf));
  1307 + for (i = 0; mux_help[i] != NULL; i++) {
  1308 + for (j=0; mux_help[i][j] != '\0'; j++) {
  1309 + if (mux_help[i][j] == '%')
  1310 + chr->chr_write(chr, ebuf, strlen(ebuf));
  1311 + else
  1312 + chr->chr_write(chr, &mux_help[i][j], 1);
  1313 + }
  1314 + }
  1315 +}
  1316 +
  1317 +static int mux_proc_byte(CharDriverState *chr, MuxDriver *d, int ch)
  1318 +{
  1319 + if (d->term_got_escape) {
  1320 + d->term_got_escape = 0;
  1321 + if (ch == term_escape_char)
  1322 + goto send_char;
  1323 + switch(ch) {
  1324 + case '?':
  1325 + case 'h':
  1326 + mux_print_help(chr);
  1327 + break;
  1328 + case 'x':
  1329 + {
  1330 + char *term = "QEMU: Terminated\n\r";
  1331 + chr->chr_write(chr,term,strlen(term));
  1332 + exit(0);
  1333 + break;
  1334 + }
  1335 + case 's':
  1336 + {
  1337 + int i;
  1338 + for (i = 0; i < MAX_DISKS; i++) {
  1339 + if (bs_table[i])
  1340 + bdrv_commit(bs_table[i]);
  1341 + }
  1342 + }
  1343 + break;
  1344 + case 'b':
  1345 + if (chr->chr_event)
  1346 + chr->chr_event(chr->opaque, CHR_EVENT_BREAK);
  1347 + break;
  1348 + case 'c':
  1349 + /* Switch to the next registered device */
  1350 + chr->focus++;
  1351 + if (chr->focus >= d->mux_cnt)
  1352 + chr->focus = 0;
  1353 + break;
  1354 + case 't':
  1355 + term_timestamps = !term_timestamps;
  1356 + term_timestamps_start = -1;
  1357 + break;
  1358 + }
  1359 + } else if (ch == term_escape_char) {
  1360 + d->term_got_escape = 1;
  1361 + } else {
  1362 + send_char:
  1363 + return 1;
  1364 + }
  1365 + return 0;
  1366 +}
  1367 +
  1368 +static int mux_chr_can_read(void *opaque)
  1369 +{
  1370 + CharDriverState *chr = opaque;
  1371 + MuxDriver *d = chr->opaque;
  1372 + if (d->chr_can_read[chr->focus])
  1373 + return d->chr_can_read[chr->focus](d->ext_opaque[chr->focus]);
  1374 + return 0;
  1375 +}
  1376 +
  1377 +static void mux_chr_read(void *opaque, const uint8_t *buf, int size)
  1378 +{
  1379 + CharDriverState *chr = opaque;
  1380 + MuxDriver *d = chr->opaque;
  1381 + int i;
  1382 + for(i = 0; i < size; i++)
  1383 + if (mux_proc_byte(chr, d, buf[i]))
  1384 + d->chr_read[chr->focus](d->ext_opaque[chr->focus], &buf[i], 1);
  1385 +}
  1386 +
  1387 +static void mux_chr_event(void *opaque, int event)
  1388 +{
  1389 + CharDriverState *chr = opaque;
  1390 + MuxDriver *d = chr->opaque;
  1391 + int i;
  1392 +
  1393 + /* Send the event to all registered listeners */
  1394 + for (i = 0; i < d->mux_cnt; i++)
  1395 + if (d->chr_event[i])
  1396 + d->chr_event[i](d->ext_opaque[i], event);
  1397 +}
  1398 +
  1399 +static void mux_chr_update_read_handler(CharDriverState *chr)
  1400 +{
  1401 + MuxDriver *d = chr->opaque;
  1402 +
  1403 + if (d->mux_cnt >= MAX_MUX) {
  1404 + fprintf(stderr, "Cannot add I/O handlers, MUX array is full\n");
  1405 + return;
  1406 + }
  1407 + d->ext_opaque[d->mux_cnt] = chr->handler_opaque;
  1408 + d->chr_can_read[d->mux_cnt] = chr->chr_can_read;
  1409 + d->chr_read[d->mux_cnt] = chr->chr_read;
  1410 + d->chr_event[d->mux_cnt] = chr->chr_event;
  1411 + /* Fix up the real driver with mux routines */
  1412 + if (d->mux_cnt == 0) {
  1413 + qemu_chr_add_handlers(d->drv, mux_chr_can_read, mux_chr_read,
  1414 + mux_chr_event, chr);
  1415 + }
  1416 + chr->focus = d->mux_cnt;
  1417 + d->mux_cnt++;
  1418 +}
  1419 +
  1420 +CharDriverState *qemu_chr_open_mux(CharDriverState *drv)
  1421 +{
  1422 + CharDriverState *chr;
  1423 + MuxDriver *d;
  1424 +
  1425 + chr = qemu_mallocz(sizeof(CharDriverState));
  1426 + if (!chr)
  1427 + return NULL;
  1428 + d = qemu_mallocz(sizeof(MuxDriver));
  1429 + if (!d) {
  1430 + free(chr);
  1431 + return NULL;
  1432 + }
  1433 +
  1434 + chr->opaque = d;
  1435 + d->drv = drv;
  1436 + chr->focus = -1;
  1437 + chr->chr_write = mux_chr_write;
  1438 + chr->chr_update_read_handler = mux_chr_update_read_handler;
  1439 + return chr;
  1440 +}
  1441 +
  1442 +
1231 1443 #ifdef _WIN32
1232 1444  
1233 1445 static void socket_cleanup(void)
... ... @@ -1319,10 +1531,8 @@ typedef struct {
1319 1531 int max_size;
1320 1532 } FDCharDriver;
1321 1533  
1322   -#define STDIO_MAX_CLIENTS 2
1323   -
1324   -static int stdio_nb_clients;
1325   -static CharDriverState *stdio_clients[STDIO_MAX_CLIENTS];
  1534 +#define STDIO_MAX_CLIENTS 1
  1535 +static int stdio_nb_clients = 0;
1326 1536  
1327 1537 static int fd_chr_write(CharDriverState *chr, const uint8_t *buf, int len)
1328 1538 {
... ... @@ -1435,162 +1645,45 @@ static CharDriverState *qemu_chr_open_pipe(const char *filename)
1435 1645 /* for STDIO, we handle the case where several clients use it
1436 1646 (nographic mode) */
1437 1647  
1438   -#define TERM_ESCAPE 0x01 /* ctrl-a is used for escape */
1439   -
1440 1648 #define TERM_FIFO_MAX_SIZE 1
1441 1649  
1442   -static int term_got_escape, client_index;
1443 1650 static uint8_t term_fifo[TERM_FIFO_MAX_SIZE];
1444 1651 static int term_fifo_size;
1445   -static int term_timestamps;
1446   -static int64_t term_timestamps_start;
1447   -
1448   -void term_print_help(void)
1449   -{
1450   - printf("\n"
1451   - "C-a h print this help\n"
1452   - "C-a x exit emulator\n"
1453   - "C-a s save disk data back to file (if -snapshot)\n"
1454   - "C-a b send break (magic sysrq)\n"
1455   - "C-a t toggle console timestamps\n"
1456   - "C-a c switch between console and monitor\n"
1457   - "C-a C-a send C-a\n"
1458   - );
1459   -}
1460   -
1461   -/* called when a char is received */
1462   -static void stdio_received_byte(int ch)
1463   -{
1464   - if (term_got_escape) {
1465   - term_got_escape = 0;
1466   - switch(ch) {
1467   - case 'h':
1468   - term_print_help();
1469   - break;
1470   - case 'x':
1471   - exit(0);
1472   - break;
1473   - case 's':
1474   - {
1475   - int i;
1476   - for (i = 0; i < MAX_DISKS; i++) {
1477   - if (bs_table[i])
1478   - bdrv_commit(bs_table[i]);
1479   - }
1480   - }
1481   - break;
1482   - case 'b':
1483   - if (client_index < stdio_nb_clients) {
1484   - CharDriverState *chr;
1485   - FDCharDriver *s;
1486   -
1487   - chr = stdio_clients[client_index];
1488   - s = chr->opaque;
1489   - qemu_chr_event(chr, CHR_EVENT_BREAK);
1490   - }
1491   - break;
1492   - case 'c':
1493   - client_index++;
1494   - if (client_index >= stdio_nb_clients)
1495   - client_index = 0;
1496   - if (client_index == 0) {
1497   - /* send a new line in the monitor to get the prompt */
1498   - ch = '\r';
1499   - goto send_char;
1500   - }
1501   - break;
1502   - case 't':
1503   - term_timestamps = !term_timestamps;
1504   - term_timestamps_start = -1;
1505   - break;
1506   - case TERM_ESCAPE:
1507   - goto send_char;
1508   - }
1509   - } else if (ch == TERM_ESCAPE) {
1510   - term_got_escape = 1;
1511   - } else {
1512   - send_char:
1513   - if (client_index < stdio_nb_clients) {
1514   - uint8_t buf[1];
1515   - CharDriverState *chr;
1516   -
1517   - chr = stdio_clients[client_index];
1518   - if (qemu_chr_can_read(chr) > 0) {
1519   - buf[0] = ch;
1520   - qemu_chr_read(chr, buf, 1);
1521   - } else if (term_fifo_size == 0) {
1522   - term_fifo[term_fifo_size++] = ch;
1523   - }
1524   - }
1525   - }
1526   -}
1527 1652  
1528 1653 static int stdio_read_poll(void *opaque)
1529 1654 {
1530   - CharDriverState *chr;
  1655 + CharDriverState *chr = opaque;
1531 1656  
1532   - if (client_index < stdio_nb_clients) {
1533   - chr = stdio_clients[client_index];
1534   - /* try to flush the queue if needed */
1535   - if (term_fifo_size != 0 && qemu_chr_can_read(chr) > 0) {
1536   - qemu_chr_read(chr, term_fifo, 1);
1537   - term_fifo_size = 0;
1538   - }
1539   - /* see if we can absorb more chars */
1540   - if (term_fifo_size == 0)
1541   - return 1;
1542   - else
1543   - return 0;
1544   - } else {
1545   - return 1;
  1657 + /* try to flush the queue if needed */
  1658 + if (term_fifo_size != 0 && qemu_chr_can_read(chr) > 0) {
  1659 + qemu_chr_read(chr, term_fifo, 1);
  1660 + term_fifo_size = 0;
1546 1661 }
  1662 + /* see if we can absorb more chars */
  1663 + if (term_fifo_size == 0)
  1664 + return 1;
  1665 + else
  1666 + return 0;
1547 1667 }
1548 1668  
1549 1669 static void stdio_read(void *opaque)
1550 1670 {
1551 1671 int size;
1552 1672 uint8_t buf[1];
1553   -
  1673 + CharDriverState *chr = opaque;
  1674 +
1554 1675 size = read(0, buf, 1);
1555 1676 if (size == 0) {
1556 1677 /* stdin has been closed. Remove it from the active list. */
1557 1678 qemu_set_fd_handler2(0, NULL, NULL, NULL, NULL);
1558 1679 return;
1559 1680 }
1560   - if (size > 0)
1561   - stdio_received_byte(buf[0]);
1562   -}
1563   -
1564   -static int stdio_write(CharDriverState *chr, const uint8_t *buf, int len)
1565   -{
1566   - FDCharDriver *s = chr->opaque;
1567   - if (!term_timestamps) {
1568   - return unix_write(s->fd_out, buf, len);
1569   - } else {
1570   - int i;
1571   - char buf1[64];
1572   -
1573   - for(i = 0; i < len; i++) {
1574   - unix_write(s->fd_out, buf + i, 1);
1575   - if (buf[i] == '\n') {
1576   - int64_t ti;
1577   - int secs;
1578   -
1579   - ti = get_clock();
1580   - if (term_timestamps_start == -1)
1581   - term_timestamps_start = ti;
1582   - ti -= term_timestamps_start;
1583   - secs = ti / 1000000000;
1584   - snprintf(buf1, sizeof(buf1),
1585   - "[%02d:%02d:%02d.%03d] ",
1586   - secs / 3600,
1587   - (secs / 60) % 60,
1588   - secs % 60,
1589   - (int)((ti / 1000000) % 1000));
1590   - unix_write(s->fd_out, buf1, strlen(buf1));
1591   - }
  1681 + if (size > 0) {
  1682 + if (qemu_chr_can_read(chr) > 0) {
  1683 + qemu_chr_read(chr, buf, 1);
  1684 + } else if (term_fifo_size == 0) {
  1685 + term_fifo[term_fifo_size++] = buf[0];
1592 1686 }
1593   - return len;
1594 1687 }
1595 1688 }
1596 1689  
... ... @@ -1635,24 +1728,13 @@ static CharDriverState *qemu_chr_open_stdio(void)
1635 1728 {
1636 1729 CharDriverState *chr;
1637 1730  
1638   - if (nographic) {
1639   - if (stdio_nb_clients >= STDIO_MAX_CLIENTS)
1640   - return NULL;
1641   - chr = qemu_chr_open_fd(0, 1);
1642   - chr->chr_write = stdio_write;
1643   - if (stdio_nb_clients == 0)
1644   - qemu_set_fd_handler2(0, stdio_read_poll, stdio_read, NULL, NULL);
1645   - client_index = stdio_nb_clients;
1646   - } else {
1647   - if (stdio_nb_clients != 0)
1648   - return NULL;
1649   - chr = qemu_chr_open_fd(0, 1);
1650   - }
1651   - stdio_clients[stdio_nb_clients++] = chr;
1652   - if (stdio_nb_clients == 1) {
1653   - /* set the terminal in raw mode */
1654   - term_init();
1655   - }
  1731 + if (stdio_nb_clients >= STDIO_MAX_CLIENTS)
  1732 + return NULL;
  1733 + chr = qemu_chr_open_fd(0, 1);
  1734 + qemu_set_fd_handler2(0, stdio_read_poll, stdio_read, NULL, chr);
  1735 + stdio_nb_clients++;
  1736 + term_init();
  1737 +
1656 1738 return chr;
1657 1739 }
1658 1740  
... ... @@ -2815,6 +2897,16 @@ CharDriverState *qemu_chr_open(const char *filename)
2815 2897 if (strstart(filename, "udp:", &p)) {
2816 2898 return qemu_chr_open_udp(p);
2817 2899 } else
  2900 + if (strstart(filename, "mon:", &p)) {
  2901 + CharDriverState *drv = qemu_chr_open(p);
  2902 + if (drv) {
  2903 + drv = qemu_chr_open_mux(drv);
  2904 + monitor_init(drv, !nographic);
  2905 + return drv;
  2906 + }
  2907 + printf("Unable to open driver: %s\n", p);
  2908 + return 0;
  2909 + } else
2818 2910 #ifndef _WIN32
2819 2911 if (strstart(filename, "unix:", &p)) {
2820 2912 return qemu_chr_open_tcp(p, 0, 1);
... ... @@ -6416,6 +6508,7 @@ enum {
6416 6508 QEMU_OPTION_cirrusvga,
6417 6509 QEMU_OPTION_g,
6418 6510 QEMU_OPTION_std_vga,
  6511 + QEMU_OPTION_echr,
6419 6512 QEMU_OPTION_monitor,
6420 6513 QEMU_OPTION_serial,
6421 6514 QEMU_OPTION_parallel,
... ... @@ -6497,6 +6590,7 @@ const QEMUOption qemu_options[] = {
6497 6590 #endif
6498 6591 { "localtime", 0, QEMU_OPTION_localtime },
6499 6592 { "std-vga", 0, QEMU_OPTION_std_vga },
  6593 + { "echr", 1, QEMU_OPTION_echr },
6500 6594 { "monitor", 1, QEMU_OPTION_monitor },
6501 6595 { "serial", 1, QEMU_OPTION_serial },
6502 6596 { "parallel", 1, QEMU_OPTION_parallel },
... ... @@ -6932,8 +7026,8 @@ int main(int argc, char **argv)
6932 7026 }
6933 7027 break;
6934 7028 case QEMU_OPTION_nographic:
6935   - pstrcpy(monitor_device, sizeof(monitor_device), "stdio");
6936 7029 pstrcpy(serial_devices[0], sizeof(serial_devices[0]), "stdio");
  7030 + pstrcpy(monitor_device, sizeof(monitor_device), "stdio");
6937 7031 nographic = 1;
6938 7032 break;
6939 7033 case QEMU_OPTION_kernel:
... ... @@ -7094,6 +7188,14 @@ int main(int argc, char **argv)
7094 7188 graphic_depth = depth;
7095 7189 }
7096 7190 break;
  7191 + case QEMU_OPTION_echr:
  7192 + {
  7193 + char *r;
  7194 + term_escape_char = strtol(optarg, &r, 0);
  7195 + if (r == optarg)
  7196 + printf("Bad argument to echr\n");
  7197 + break;
  7198 + }
7097 7199 case QEMU_OPTION_monitor:
7098 7200 pstrcpy(monitor_device, sizeof(monitor_device), optarg);
7099 7201 break;
... ... @@ -7384,12 +7486,27 @@ int main(int argc, char **argv)
7384 7486 #endif
7385 7487 }
7386 7488  
7387   - monitor_hd = qemu_chr_open(monitor_device);
7388   - if (!monitor_hd) {
7389   - fprintf(stderr, "qemu: could not open monitor device '%s'\n", monitor_device);
7390   - exit(1);
  7489 + /* Maintain compatibility with multiple stdio monitors */
  7490 + if (!strcmp(monitor_device,"stdio")) {
  7491 + for (i = 0; i < MAX_SERIAL_PORTS; i++) {
  7492 + if (!strcmp(serial_devices[i],"mon:stdio")) {
  7493 + monitor_device[0] = '\0';
  7494 + break;
  7495 + } else if (!strcmp(serial_devices[i],"stdio")) {
  7496 + monitor_device[0] = '\0';
  7497 + pstrcpy(serial_devices[0], sizeof(serial_devices[0]), "mon:stdio");
  7498 + break;
  7499 + }
  7500 + }
  7501 + }
  7502 + if (monitor_device[0] != '\0') {
  7503 + monitor_hd = qemu_chr_open(monitor_device);
  7504 + if (!monitor_hd) {
  7505 + fprintf(stderr, "qemu: could not open monitor device '%s'\n", monitor_device);
  7506 + exit(1);
  7507 + }
  7508 + monitor_init(monitor_hd, !nographic);
7391 7509 }
7392   - monitor_init(monitor_hd, !nographic);
7393 7510  
7394 7511 for(i = 0; i < MAX_SERIAL_PORTS; i++) {
7395 7512 const char *devname = serial_devices[i];
... ...
... ... @@ -303,6 +303,7 @@ typedef struct CharDriverState {
303 303 void (*chr_send_event)(struct CharDriverState *chr, int event);
304 304 void (*chr_close)(struct CharDriverState *chr);
305 305 void *opaque;
  306 + int focus;
306 307 QEMUBH *bh;
307 308 } CharDriverState;
308 309  
... ...