15796c8dcSSimon Schubert /* Generic serial interface routines 25796c8dcSSimon Schubert 35796c8dcSSimon Schubert Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 4*cf7f2e2dSJohn Marino 2002, 2004, 2005, 2006, 2007, 2008, 2009, 2010 5*cf7f2e2dSJohn Marino Free Software Foundation, Inc. 65796c8dcSSimon Schubert 75796c8dcSSimon Schubert This file is part of GDB. 85796c8dcSSimon Schubert 95796c8dcSSimon Schubert This program is free software; you can redistribute it and/or modify 105796c8dcSSimon Schubert it under the terms of the GNU General Public License as published by 115796c8dcSSimon Schubert the Free Software Foundation; either version 3 of the License, or 125796c8dcSSimon Schubert (at your option) any later version. 135796c8dcSSimon Schubert 145796c8dcSSimon Schubert This program is distributed in the hope that it will be useful, 155796c8dcSSimon Schubert but WITHOUT ANY WARRANTY; without even the implied warranty of 165796c8dcSSimon Schubert MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 175796c8dcSSimon Schubert GNU General Public License for more details. 185796c8dcSSimon Schubert 195796c8dcSSimon Schubert You should have received a copy of the GNU General Public License 205796c8dcSSimon Schubert along with this program. If not, see <http://www.gnu.org/licenses/>. */ 215796c8dcSSimon Schubert 225796c8dcSSimon Schubert #include "defs.h" 235796c8dcSSimon Schubert #include <ctype.h> 245796c8dcSSimon Schubert #include "serial.h" 255796c8dcSSimon Schubert #include "gdb_string.h" 265796c8dcSSimon Schubert #include "gdbcmd.h" 275796c8dcSSimon Schubert 285796c8dcSSimon Schubert extern void _initialize_serial (void); 295796c8dcSSimon Schubert 305796c8dcSSimon Schubert /* Is serial being debugged? */ 315796c8dcSSimon Schubert 325796c8dcSSimon Schubert static int global_serial_debug_p; 335796c8dcSSimon Schubert 345796c8dcSSimon Schubert /* Linked list of serial I/O handlers */ 355796c8dcSSimon Schubert 365796c8dcSSimon Schubert static struct serial_ops *serial_ops_list = NULL; 375796c8dcSSimon Schubert 385796c8dcSSimon Schubert /* This is the last serial stream opened. Used by connect command. */ 395796c8dcSSimon Schubert 405796c8dcSSimon Schubert static struct serial *last_serial_opened = NULL; 415796c8dcSSimon Schubert 425796c8dcSSimon Schubert /* Pointer to list of scb's. */ 435796c8dcSSimon Schubert 445796c8dcSSimon Schubert static struct serial *scb_base; 455796c8dcSSimon Schubert 465796c8dcSSimon Schubert /* Non-NULL gives filename which contains a recording of the remote session, 475796c8dcSSimon Schubert suitable for playback by gdbserver. */ 485796c8dcSSimon Schubert 495796c8dcSSimon Schubert static char *serial_logfile = NULL; 505796c8dcSSimon Schubert static struct ui_file *serial_logfp = NULL; 515796c8dcSSimon Schubert 525796c8dcSSimon Schubert static struct serial_ops *serial_interface_lookup (char *); 535796c8dcSSimon Schubert static void serial_logchar (struct ui_file *stream, int ch_type, int ch, int timeout); 545796c8dcSSimon Schubert static const char logbase_hex[] = "hex"; 555796c8dcSSimon Schubert static const char logbase_octal[] = "octal"; 565796c8dcSSimon Schubert static const char logbase_ascii[] = "ascii"; 575796c8dcSSimon Schubert static const char *logbase_enums[] = 585796c8dcSSimon Schubert {logbase_hex, logbase_octal, logbase_ascii, NULL}; 595796c8dcSSimon Schubert static const char *serial_logbase = logbase_ascii; 605796c8dcSSimon Schubert 615796c8dcSSimon Schubert 625796c8dcSSimon Schubert static int serial_current_type = 0; 635796c8dcSSimon Schubert 645796c8dcSSimon Schubert /* Log char CH of type CHTYPE, with TIMEOUT */ 655796c8dcSSimon Schubert 665796c8dcSSimon Schubert /* Define bogus char to represent a BREAK. Should be careful to choose a value 675796c8dcSSimon Schubert that can't be confused with a normal char, or an error code. */ 685796c8dcSSimon Schubert #define SERIAL_BREAK 1235 695796c8dcSSimon Schubert 705796c8dcSSimon Schubert static void 715796c8dcSSimon Schubert serial_logchar (struct ui_file *stream, int ch_type, int ch, int timeout) 725796c8dcSSimon Schubert { 735796c8dcSSimon Schubert if (ch_type != serial_current_type) 745796c8dcSSimon Schubert { 755796c8dcSSimon Schubert fprintf_unfiltered (stream, "\n%c ", ch_type); 765796c8dcSSimon Schubert serial_current_type = ch_type; 775796c8dcSSimon Schubert } 785796c8dcSSimon Schubert 795796c8dcSSimon Schubert if (serial_logbase != logbase_ascii) 805796c8dcSSimon Schubert fputc_unfiltered (' ', stream); 815796c8dcSSimon Schubert 825796c8dcSSimon Schubert switch (ch) 835796c8dcSSimon Schubert { 845796c8dcSSimon Schubert case SERIAL_TIMEOUT: 855796c8dcSSimon Schubert fprintf_unfiltered (stream, "<Timeout: %d seconds>", timeout); 865796c8dcSSimon Schubert return; 875796c8dcSSimon Schubert case SERIAL_ERROR: 885796c8dcSSimon Schubert fprintf_unfiltered (stream, "<Error: %s>", safe_strerror (errno)); 895796c8dcSSimon Schubert return; 905796c8dcSSimon Schubert case SERIAL_EOF: 915796c8dcSSimon Schubert fputs_unfiltered ("<Eof>", stream); 925796c8dcSSimon Schubert return; 935796c8dcSSimon Schubert case SERIAL_BREAK: 945796c8dcSSimon Schubert fputs_unfiltered ("<Break>", stream); 955796c8dcSSimon Schubert return; 965796c8dcSSimon Schubert default: 975796c8dcSSimon Schubert if (serial_logbase == logbase_hex) 985796c8dcSSimon Schubert fprintf_unfiltered (stream, "%02x", ch & 0xff); 995796c8dcSSimon Schubert else if (serial_logbase == logbase_octal) 1005796c8dcSSimon Schubert fprintf_unfiltered (stream, "%03o", ch & 0xff); 1015796c8dcSSimon Schubert else 1025796c8dcSSimon Schubert switch (ch) 1035796c8dcSSimon Schubert { 1045796c8dcSSimon Schubert case '\\': 1055796c8dcSSimon Schubert fputs_unfiltered ("\\\\", stream); 1065796c8dcSSimon Schubert break; 1075796c8dcSSimon Schubert case '\b': 1085796c8dcSSimon Schubert fputs_unfiltered ("\\b", stream); 1095796c8dcSSimon Schubert break; 1105796c8dcSSimon Schubert case '\f': 1115796c8dcSSimon Schubert fputs_unfiltered ("\\f", stream); 1125796c8dcSSimon Schubert break; 1135796c8dcSSimon Schubert case '\n': 1145796c8dcSSimon Schubert fputs_unfiltered ("\\n", stream); 1155796c8dcSSimon Schubert break; 1165796c8dcSSimon Schubert case '\r': 1175796c8dcSSimon Schubert fputs_unfiltered ("\\r", stream); 1185796c8dcSSimon Schubert break; 1195796c8dcSSimon Schubert case '\t': 1205796c8dcSSimon Schubert fputs_unfiltered ("\\t", stream); 1215796c8dcSSimon Schubert break; 1225796c8dcSSimon Schubert case '\v': 1235796c8dcSSimon Schubert fputs_unfiltered ("\\v", stream); 1245796c8dcSSimon Schubert break; 1255796c8dcSSimon Schubert default: 1265796c8dcSSimon Schubert fprintf_unfiltered (stream, isprint (ch) ? "%c" : "\\x%02x", ch & 0xFF); 1275796c8dcSSimon Schubert break; 1285796c8dcSSimon Schubert } 1295796c8dcSSimon Schubert } 1305796c8dcSSimon Schubert } 1315796c8dcSSimon Schubert 1325796c8dcSSimon Schubert void 1335796c8dcSSimon Schubert serial_log_command (const char *cmd) 1345796c8dcSSimon Schubert { 1355796c8dcSSimon Schubert if (!serial_logfp) 1365796c8dcSSimon Schubert return; 1375796c8dcSSimon Schubert 1385796c8dcSSimon Schubert serial_current_type = 'c'; 1395796c8dcSSimon Schubert 1405796c8dcSSimon Schubert fputs_unfiltered ("\nc ", serial_logfp); 1415796c8dcSSimon Schubert fputs_unfiltered (cmd, serial_logfp); 1425796c8dcSSimon Schubert 1435796c8dcSSimon Schubert /* Make sure that the log file is as up-to-date as possible, 1445796c8dcSSimon Schubert in case we are getting ready to dump core or something. */ 1455796c8dcSSimon Schubert gdb_flush (serial_logfp); 1465796c8dcSSimon Schubert } 1475796c8dcSSimon Schubert 1485796c8dcSSimon Schubert 1495796c8dcSSimon Schubert static struct serial_ops * 1505796c8dcSSimon Schubert serial_interface_lookup (char *name) 1515796c8dcSSimon Schubert { 1525796c8dcSSimon Schubert struct serial_ops *ops; 1535796c8dcSSimon Schubert 1545796c8dcSSimon Schubert for (ops = serial_ops_list; ops; ops = ops->next) 1555796c8dcSSimon Schubert if (strcmp (name, ops->name) == 0) 1565796c8dcSSimon Schubert return ops; 1575796c8dcSSimon Schubert 1585796c8dcSSimon Schubert return NULL; 1595796c8dcSSimon Schubert } 1605796c8dcSSimon Schubert 1615796c8dcSSimon Schubert void 1625796c8dcSSimon Schubert serial_add_interface (struct serial_ops *optable) 1635796c8dcSSimon Schubert { 1645796c8dcSSimon Schubert optable->next = serial_ops_list; 1655796c8dcSSimon Schubert serial_ops_list = optable; 1665796c8dcSSimon Schubert } 1675796c8dcSSimon Schubert 1685796c8dcSSimon Schubert /* Open up a device or a network socket, depending upon the syntax of NAME. */ 1695796c8dcSSimon Schubert 1705796c8dcSSimon Schubert struct serial * 1715796c8dcSSimon Schubert serial_open (const char *name) 1725796c8dcSSimon Schubert { 1735796c8dcSSimon Schubert struct serial *scb; 1745796c8dcSSimon Schubert struct serial_ops *ops; 1755796c8dcSSimon Schubert const char *open_name = name; 1765796c8dcSSimon Schubert 1775796c8dcSSimon Schubert for (scb = scb_base; scb; scb = scb->next) 1785796c8dcSSimon Schubert if (scb->name && strcmp (scb->name, name) == 0) 1795796c8dcSSimon Schubert { 1805796c8dcSSimon Schubert scb->refcnt++; 1815796c8dcSSimon Schubert return scb; 1825796c8dcSSimon Schubert } 1835796c8dcSSimon Schubert 1845796c8dcSSimon Schubert if (strcmp (name, "pc") == 0) 1855796c8dcSSimon Schubert ops = serial_interface_lookup ("pc"); 1865796c8dcSSimon Schubert else if (strncmp (name, "lpt", 3) == 0) 1875796c8dcSSimon Schubert ops = serial_interface_lookup ("parallel"); 1885796c8dcSSimon Schubert else if (strncmp (name, "|", 1) == 0) 1895796c8dcSSimon Schubert { 1905796c8dcSSimon Schubert ops = serial_interface_lookup ("pipe"); 1915796c8dcSSimon Schubert /* Discard ``|'' and any space before the command itself. */ 1925796c8dcSSimon Schubert ++open_name; 1935796c8dcSSimon Schubert while (isspace (*open_name)) 1945796c8dcSSimon Schubert ++open_name; 1955796c8dcSSimon Schubert } 1965796c8dcSSimon Schubert /* Check for a colon, suggesting an IP address/port pair. 1975796c8dcSSimon Schubert Do this *after* checking for all the interesting prefixes. We 1985796c8dcSSimon Schubert don't want to constrain the syntax of what can follow them. */ 1995796c8dcSSimon Schubert else if (strchr (name, ':')) 2005796c8dcSSimon Schubert ops = serial_interface_lookup ("tcp"); 2015796c8dcSSimon Schubert else 2025796c8dcSSimon Schubert ops = serial_interface_lookup ("hardwire"); 2035796c8dcSSimon Schubert 2045796c8dcSSimon Schubert if (!ops) 2055796c8dcSSimon Schubert return NULL; 2065796c8dcSSimon Schubert 2075796c8dcSSimon Schubert scb = XMALLOC (struct serial); 2085796c8dcSSimon Schubert 2095796c8dcSSimon Schubert scb->ops = ops; 2105796c8dcSSimon Schubert 2115796c8dcSSimon Schubert scb->bufcnt = 0; 2125796c8dcSSimon Schubert scb->bufp = scb->buf; 2135796c8dcSSimon Schubert scb->error_fd = -1; 2145796c8dcSSimon Schubert 2155796c8dcSSimon Schubert /* `...->open (...)' would get expanded by an the open(2) syscall macro. */ 2165796c8dcSSimon Schubert if ((*scb->ops->open) (scb, open_name)) 2175796c8dcSSimon Schubert { 2185796c8dcSSimon Schubert xfree (scb); 2195796c8dcSSimon Schubert return NULL; 2205796c8dcSSimon Schubert } 2215796c8dcSSimon Schubert 2225796c8dcSSimon Schubert scb->name = xstrdup (name); 2235796c8dcSSimon Schubert scb->next = scb_base; 2245796c8dcSSimon Schubert scb->refcnt = 1; 2255796c8dcSSimon Schubert scb->debug_p = 0; 2265796c8dcSSimon Schubert scb->async_state = 0; 2275796c8dcSSimon Schubert scb->async_handler = NULL; 2285796c8dcSSimon Schubert scb->async_context = NULL; 2295796c8dcSSimon Schubert scb_base = scb; 2305796c8dcSSimon Schubert 2315796c8dcSSimon Schubert last_serial_opened = scb; 2325796c8dcSSimon Schubert 2335796c8dcSSimon Schubert if (serial_logfile != NULL) 2345796c8dcSSimon Schubert { 2355796c8dcSSimon Schubert serial_logfp = gdb_fopen (serial_logfile, "w"); 2365796c8dcSSimon Schubert if (serial_logfp == NULL) 2375796c8dcSSimon Schubert perror_with_name (serial_logfile); 2385796c8dcSSimon Schubert } 2395796c8dcSSimon Schubert 2405796c8dcSSimon Schubert return scb; 2415796c8dcSSimon Schubert } 2425796c8dcSSimon Schubert 2435796c8dcSSimon Schubert /* Return the open serial device for FD, if found, or NULL if FD 2445796c8dcSSimon Schubert is not already opened. */ 2455796c8dcSSimon Schubert 2465796c8dcSSimon Schubert struct serial * 2475796c8dcSSimon Schubert serial_for_fd (int fd) 2485796c8dcSSimon Schubert { 2495796c8dcSSimon Schubert struct serial *scb; 2505796c8dcSSimon Schubert 2515796c8dcSSimon Schubert for (scb = scb_base; scb; scb = scb->next) 2525796c8dcSSimon Schubert if (scb->fd == fd) 2535796c8dcSSimon Schubert return scb; 2545796c8dcSSimon Schubert 2555796c8dcSSimon Schubert return NULL; 2565796c8dcSSimon Schubert } 2575796c8dcSSimon Schubert 2585796c8dcSSimon Schubert struct serial * 2595796c8dcSSimon Schubert serial_fdopen (const int fd) 2605796c8dcSSimon Schubert { 2615796c8dcSSimon Schubert struct serial *scb; 2625796c8dcSSimon Schubert struct serial_ops *ops; 2635796c8dcSSimon Schubert 2645796c8dcSSimon Schubert for (scb = scb_base; scb; scb = scb->next) 2655796c8dcSSimon Schubert if (scb->fd == fd) 2665796c8dcSSimon Schubert { 2675796c8dcSSimon Schubert scb->refcnt++; 2685796c8dcSSimon Schubert return scb; 2695796c8dcSSimon Schubert } 2705796c8dcSSimon Schubert 2715796c8dcSSimon Schubert ops = serial_interface_lookup ("terminal"); 2725796c8dcSSimon Schubert if (!ops) 2735796c8dcSSimon Schubert ops = serial_interface_lookup ("hardwire"); 2745796c8dcSSimon Schubert 2755796c8dcSSimon Schubert if (!ops) 2765796c8dcSSimon Schubert return NULL; 2775796c8dcSSimon Schubert 2785796c8dcSSimon Schubert scb = XCALLOC (1, struct serial); 2795796c8dcSSimon Schubert 2805796c8dcSSimon Schubert scb->ops = ops; 2815796c8dcSSimon Schubert 2825796c8dcSSimon Schubert scb->bufcnt = 0; 2835796c8dcSSimon Schubert scb->bufp = scb->buf; 2845796c8dcSSimon Schubert 2855796c8dcSSimon Schubert scb->fd = fd; 2865796c8dcSSimon Schubert 2875796c8dcSSimon Schubert scb->name = NULL; 2885796c8dcSSimon Schubert scb->next = scb_base; 2895796c8dcSSimon Schubert scb->refcnt = 1; 2905796c8dcSSimon Schubert scb->debug_p = 0; 2915796c8dcSSimon Schubert scb->async_state = 0; 2925796c8dcSSimon Schubert scb->async_handler = NULL; 2935796c8dcSSimon Schubert scb->async_context = NULL; 2945796c8dcSSimon Schubert scb_base = scb; 2955796c8dcSSimon Schubert 2965796c8dcSSimon Schubert last_serial_opened = scb; 2975796c8dcSSimon Schubert 2985796c8dcSSimon Schubert return scb; 2995796c8dcSSimon Schubert } 3005796c8dcSSimon Schubert 3015796c8dcSSimon Schubert static void 3025796c8dcSSimon Schubert do_serial_close (struct serial *scb, int really_close) 3035796c8dcSSimon Schubert { 3045796c8dcSSimon Schubert struct serial *tmp_scb; 3055796c8dcSSimon Schubert 3065796c8dcSSimon Schubert last_serial_opened = NULL; 3075796c8dcSSimon Schubert 3085796c8dcSSimon Schubert if (serial_logfp) 3095796c8dcSSimon Schubert { 3105796c8dcSSimon Schubert fputs_unfiltered ("\nEnd of log\n", serial_logfp); 3115796c8dcSSimon Schubert serial_current_type = 0; 3125796c8dcSSimon Schubert 3135796c8dcSSimon Schubert /* XXX - What if serial_logfp == gdb_stdout or gdb_stderr? */ 3145796c8dcSSimon Schubert ui_file_delete (serial_logfp); 3155796c8dcSSimon Schubert serial_logfp = NULL; 3165796c8dcSSimon Schubert } 3175796c8dcSSimon Schubert 3185796c8dcSSimon Schubert /* This is bogus. It's not our fault if you pass us a bad scb...! Rob, you 3195796c8dcSSimon Schubert should fix your code instead. */ 3205796c8dcSSimon Schubert 3215796c8dcSSimon Schubert if (!scb) 3225796c8dcSSimon Schubert return; 3235796c8dcSSimon Schubert 3245796c8dcSSimon Schubert scb->refcnt--; 3255796c8dcSSimon Schubert if (scb->refcnt > 0) 3265796c8dcSSimon Schubert return; 3275796c8dcSSimon Schubert 3285796c8dcSSimon Schubert /* ensure that the FD has been taken out of async mode */ 3295796c8dcSSimon Schubert if (scb->async_handler != NULL) 3305796c8dcSSimon Schubert serial_async (scb, NULL, NULL); 3315796c8dcSSimon Schubert 3325796c8dcSSimon Schubert if (really_close) 3335796c8dcSSimon Schubert scb->ops->close (scb); 3345796c8dcSSimon Schubert 3355796c8dcSSimon Schubert if (scb->name) 3365796c8dcSSimon Schubert xfree (scb->name); 3375796c8dcSSimon Schubert 3385796c8dcSSimon Schubert if (scb_base == scb) 3395796c8dcSSimon Schubert scb_base = scb_base->next; 3405796c8dcSSimon Schubert else 3415796c8dcSSimon Schubert for (tmp_scb = scb_base; tmp_scb; tmp_scb = tmp_scb->next) 3425796c8dcSSimon Schubert { 3435796c8dcSSimon Schubert if (tmp_scb->next != scb) 3445796c8dcSSimon Schubert continue; 3455796c8dcSSimon Schubert 3465796c8dcSSimon Schubert tmp_scb->next = tmp_scb->next->next; 3475796c8dcSSimon Schubert break; 3485796c8dcSSimon Schubert } 3495796c8dcSSimon Schubert 3505796c8dcSSimon Schubert xfree (scb); 3515796c8dcSSimon Schubert } 3525796c8dcSSimon Schubert 3535796c8dcSSimon Schubert void 3545796c8dcSSimon Schubert serial_close (struct serial *scb) 3555796c8dcSSimon Schubert { 3565796c8dcSSimon Schubert do_serial_close (scb, 1); 3575796c8dcSSimon Schubert } 3585796c8dcSSimon Schubert 3595796c8dcSSimon Schubert void 3605796c8dcSSimon Schubert serial_un_fdopen (struct serial *scb) 3615796c8dcSSimon Schubert { 3625796c8dcSSimon Schubert do_serial_close (scb, 0); 3635796c8dcSSimon Schubert } 3645796c8dcSSimon Schubert 3655796c8dcSSimon Schubert int 3665796c8dcSSimon Schubert serial_readchar (struct serial *scb, int timeout) 3675796c8dcSSimon Schubert { 3685796c8dcSSimon Schubert int ch; 3695796c8dcSSimon Schubert 3705796c8dcSSimon Schubert /* FIXME: cagney/1999-10-11: Don't enable this check until the ASYNC 3715796c8dcSSimon Schubert code is finished. */ 3725796c8dcSSimon Schubert if (0 && serial_is_async_p (scb) && timeout < 0) 3735796c8dcSSimon Schubert internal_error (__FILE__, __LINE__, 3745796c8dcSSimon Schubert _("serial_readchar: blocking read in async mode")); 3755796c8dcSSimon Schubert 3765796c8dcSSimon Schubert ch = scb->ops->readchar (scb, timeout); 3775796c8dcSSimon Schubert if (serial_logfp != NULL) 3785796c8dcSSimon Schubert { 3795796c8dcSSimon Schubert serial_logchar (serial_logfp, 'r', ch, timeout); 3805796c8dcSSimon Schubert 3815796c8dcSSimon Schubert /* Make sure that the log file is as up-to-date as possible, 3825796c8dcSSimon Schubert in case we are getting ready to dump core or something. */ 3835796c8dcSSimon Schubert gdb_flush (serial_logfp); 3845796c8dcSSimon Schubert } 3855796c8dcSSimon Schubert if (serial_debug_p (scb)) 3865796c8dcSSimon Schubert { 3875796c8dcSSimon Schubert fprintf_unfiltered (gdb_stdlog, "["); 3885796c8dcSSimon Schubert serial_logchar (gdb_stdlog, 'r', ch, timeout); 3895796c8dcSSimon Schubert fprintf_unfiltered (gdb_stdlog, "]"); 3905796c8dcSSimon Schubert gdb_flush (gdb_stdlog); 3915796c8dcSSimon Schubert } 3925796c8dcSSimon Schubert 3935796c8dcSSimon Schubert return (ch); 3945796c8dcSSimon Schubert } 3955796c8dcSSimon Schubert 3965796c8dcSSimon Schubert int 3975796c8dcSSimon Schubert serial_write (struct serial *scb, const char *str, int len) 3985796c8dcSSimon Schubert { 3995796c8dcSSimon Schubert if (serial_logfp != NULL) 4005796c8dcSSimon Schubert { 4015796c8dcSSimon Schubert int count; 4025796c8dcSSimon Schubert 4035796c8dcSSimon Schubert for (count = 0; count < len; count++) 4045796c8dcSSimon Schubert serial_logchar (serial_logfp, 'w', str[count] & 0xff, 0); 4055796c8dcSSimon Schubert 4065796c8dcSSimon Schubert /* Make sure that the log file is as up-to-date as possible, 4075796c8dcSSimon Schubert in case we are getting ready to dump core or something. */ 4085796c8dcSSimon Schubert gdb_flush (serial_logfp); 4095796c8dcSSimon Schubert } 410*cf7f2e2dSJohn Marino if (serial_debug_p (scb)) 411*cf7f2e2dSJohn Marino { 412*cf7f2e2dSJohn Marino int count; 413*cf7f2e2dSJohn Marino 414*cf7f2e2dSJohn Marino for (count = 0; count < len; count++) 415*cf7f2e2dSJohn Marino { 416*cf7f2e2dSJohn Marino fprintf_unfiltered (gdb_stdlog, "["); 417*cf7f2e2dSJohn Marino serial_logchar (gdb_stdlog, 'w', str[count] & 0xff, 0); 418*cf7f2e2dSJohn Marino fprintf_unfiltered (gdb_stdlog, "]"); 419*cf7f2e2dSJohn Marino } 420*cf7f2e2dSJohn Marino gdb_flush (gdb_stdlog); 421*cf7f2e2dSJohn Marino } 4225796c8dcSSimon Schubert 4235796c8dcSSimon Schubert return (scb->ops->write (scb, str, len)); 4245796c8dcSSimon Schubert } 4255796c8dcSSimon Schubert 4265796c8dcSSimon Schubert void 4275796c8dcSSimon Schubert serial_printf (struct serial *desc, const char *format,...) 4285796c8dcSSimon Schubert { 4295796c8dcSSimon Schubert va_list args; 4305796c8dcSSimon Schubert char *buf; 4315796c8dcSSimon Schubert va_start (args, format); 4325796c8dcSSimon Schubert 4335796c8dcSSimon Schubert buf = xstrvprintf (format, args); 4345796c8dcSSimon Schubert serial_write (desc, buf, strlen (buf)); 4355796c8dcSSimon Schubert 4365796c8dcSSimon Schubert xfree (buf); 4375796c8dcSSimon Schubert va_end (args); 4385796c8dcSSimon Schubert } 4395796c8dcSSimon Schubert 4405796c8dcSSimon Schubert int 4415796c8dcSSimon Schubert serial_drain_output (struct serial *scb) 4425796c8dcSSimon Schubert { 4435796c8dcSSimon Schubert return scb->ops->drain_output (scb); 4445796c8dcSSimon Schubert } 4455796c8dcSSimon Schubert 4465796c8dcSSimon Schubert int 4475796c8dcSSimon Schubert serial_flush_output (struct serial *scb) 4485796c8dcSSimon Schubert { 4495796c8dcSSimon Schubert return scb->ops->flush_output (scb); 4505796c8dcSSimon Schubert } 4515796c8dcSSimon Schubert 4525796c8dcSSimon Schubert int 4535796c8dcSSimon Schubert serial_flush_input (struct serial *scb) 4545796c8dcSSimon Schubert { 4555796c8dcSSimon Schubert return scb->ops->flush_input (scb); 4565796c8dcSSimon Schubert } 4575796c8dcSSimon Schubert 4585796c8dcSSimon Schubert int 4595796c8dcSSimon Schubert serial_send_break (struct serial *scb) 4605796c8dcSSimon Schubert { 4615796c8dcSSimon Schubert if (serial_logfp != NULL) 4625796c8dcSSimon Schubert serial_logchar (serial_logfp, 'w', SERIAL_BREAK, 0); 4635796c8dcSSimon Schubert 4645796c8dcSSimon Schubert return (scb->ops->send_break (scb)); 4655796c8dcSSimon Schubert } 4665796c8dcSSimon Schubert 4675796c8dcSSimon Schubert void 4685796c8dcSSimon Schubert serial_raw (struct serial *scb) 4695796c8dcSSimon Schubert { 4705796c8dcSSimon Schubert scb->ops->go_raw (scb); 4715796c8dcSSimon Schubert } 4725796c8dcSSimon Schubert 4735796c8dcSSimon Schubert serial_ttystate 4745796c8dcSSimon Schubert serial_get_tty_state (struct serial *scb) 4755796c8dcSSimon Schubert { 4765796c8dcSSimon Schubert return scb->ops->get_tty_state (scb); 4775796c8dcSSimon Schubert } 4785796c8dcSSimon Schubert 4795796c8dcSSimon Schubert int 4805796c8dcSSimon Schubert serial_set_tty_state (struct serial *scb, serial_ttystate ttystate) 4815796c8dcSSimon Schubert { 4825796c8dcSSimon Schubert return scb->ops->set_tty_state (scb, ttystate); 4835796c8dcSSimon Schubert } 4845796c8dcSSimon Schubert 4855796c8dcSSimon Schubert void 4865796c8dcSSimon Schubert serial_print_tty_state (struct serial *scb, 4875796c8dcSSimon Schubert serial_ttystate ttystate, 4885796c8dcSSimon Schubert struct ui_file *stream) 4895796c8dcSSimon Schubert { 4905796c8dcSSimon Schubert scb->ops->print_tty_state (scb, ttystate, stream); 4915796c8dcSSimon Schubert } 4925796c8dcSSimon Schubert 4935796c8dcSSimon Schubert int 4945796c8dcSSimon Schubert serial_noflush_set_tty_state (struct serial *scb, 4955796c8dcSSimon Schubert serial_ttystate new_ttystate, 4965796c8dcSSimon Schubert serial_ttystate old_ttystate) 4975796c8dcSSimon Schubert { 4985796c8dcSSimon Schubert return scb->ops->noflush_set_tty_state (scb, new_ttystate, old_ttystate); 4995796c8dcSSimon Schubert } 5005796c8dcSSimon Schubert 5015796c8dcSSimon Schubert int 5025796c8dcSSimon Schubert serial_setbaudrate (struct serial *scb, int rate) 5035796c8dcSSimon Schubert { 5045796c8dcSSimon Schubert return scb->ops->setbaudrate (scb, rate); 5055796c8dcSSimon Schubert } 5065796c8dcSSimon Schubert 5075796c8dcSSimon Schubert int 5085796c8dcSSimon Schubert serial_setstopbits (struct serial *scb, int num) 5095796c8dcSSimon Schubert { 5105796c8dcSSimon Schubert return scb->ops->setstopbits (scb, num); 5115796c8dcSSimon Schubert } 5125796c8dcSSimon Schubert 5135796c8dcSSimon Schubert int 5145796c8dcSSimon Schubert serial_can_async_p (struct serial *scb) 5155796c8dcSSimon Schubert { 5165796c8dcSSimon Schubert return (scb->ops->async != NULL); 5175796c8dcSSimon Schubert } 5185796c8dcSSimon Schubert 5195796c8dcSSimon Schubert int 5205796c8dcSSimon Schubert serial_is_async_p (struct serial *scb) 5215796c8dcSSimon Schubert { 5225796c8dcSSimon Schubert return (scb->ops->async != NULL) && (scb->async_handler != NULL); 5235796c8dcSSimon Schubert } 5245796c8dcSSimon Schubert 5255796c8dcSSimon Schubert void 5265796c8dcSSimon Schubert serial_async (struct serial *scb, 5275796c8dcSSimon Schubert serial_event_ftype *handler, 5285796c8dcSSimon Schubert void *context) 5295796c8dcSSimon Schubert { 5305796c8dcSSimon Schubert int changed = ((scb->async_handler == NULL) != (handler == NULL)); 531*cf7f2e2dSJohn Marino 5325796c8dcSSimon Schubert scb->async_handler = handler; 5335796c8dcSSimon Schubert scb->async_context = context; 5345796c8dcSSimon Schubert /* Only change mode if there is a need. */ 5355796c8dcSSimon Schubert if (changed) 5365796c8dcSSimon Schubert scb->ops->async (scb, handler != NULL); 5375796c8dcSSimon Schubert } 5385796c8dcSSimon Schubert 5395796c8dcSSimon Schubert int 5405796c8dcSSimon Schubert deprecated_serial_fd (struct serial *scb) 5415796c8dcSSimon Schubert { 5425796c8dcSSimon Schubert /* FIXME: should this output a warning that deprecated code is being 5435796c8dcSSimon Schubert called? */ 5445796c8dcSSimon Schubert if (scb->fd < 0) 5455796c8dcSSimon Schubert { 5465796c8dcSSimon Schubert internal_error (__FILE__, __LINE__, 5475796c8dcSSimon Schubert _("serial: FD not valid")); 5485796c8dcSSimon Schubert } 5495796c8dcSSimon Schubert return scb->fd; /* sigh */ 5505796c8dcSSimon Schubert } 5515796c8dcSSimon Schubert 5525796c8dcSSimon Schubert void 5535796c8dcSSimon Schubert serial_debug (struct serial *scb, int debug_p) 5545796c8dcSSimon Schubert { 5555796c8dcSSimon Schubert scb->debug_p = debug_p; 5565796c8dcSSimon Schubert } 5575796c8dcSSimon Schubert 5585796c8dcSSimon Schubert int 5595796c8dcSSimon Schubert serial_debug_p (struct serial *scb) 5605796c8dcSSimon Schubert { 5615796c8dcSSimon Schubert return scb->debug_p || global_serial_debug_p; 5625796c8dcSSimon Schubert } 5635796c8dcSSimon Schubert 5645796c8dcSSimon Schubert #ifdef USE_WIN32API 5655796c8dcSSimon Schubert void 5665796c8dcSSimon Schubert serial_wait_handle (struct serial *scb, HANDLE *read, HANDLE *except) 5675796c8dcSSimon Schubert { 5685796c8dcSSimon Schubert if (scb->ops->wait_handle) 5695796c8dcSSimon Schubert scb->ops->wait_handle (scb, read, except); 5705796c8dcSSimon Schubert else 5715796c8dcSSimon Schubert { 5725796c8dcSSimon Schubert *read = (HANDLE) _get_osfhandle (scb->fd); 5735796c8dcSSimon Schubert *except = NULL; 5745796c8dcSSimon Schubert } 5755796c8dcSSimon Schubert } 5765796c8dcSSimon Schubert 5775796c8dcSSimon Schubert void 5785796c8dcSSimon Schubert serial_done_wait_handle (struct serial *scb) 5795796c8dcSSimon Schubert { 5805796c8dcSSimon Schubert if (scb->ops->done_wait_handle) 5815796c8dcSSimon Schubert scb->ops->done_wait_handle (scb); 5825796c8dcSSimon Schubert } 5835796c8dcSSimon Schubert #endif 5845796c8dcSSimon Schubert 5855796c8dcSSimon Schubert #if 0 5865796c8dcSSimon Schubert /* The connect command is #if 0 because I hadn't thought of an elegant 5875796c8dcSSimon Schubert way to wait for I/O on two `struct serial *'s simultaneously. Two 5885796c8dcSSimon Schubert solutions came to mind: 5895796c8dcSSimon Schubert 5905796c8dcSSimon Schubert 1) Fork, and have have one fork handle the to user direction, 5915796c8dcSSimon Schubert and have the other hand the to target direction. This 5925796c8dcSSimon Schubert obviously won't cut it for MSDOS. 5935796c8dcSSimon Schubert 5945796c8dcSSimon Schubert 2) Use something like select. This assumes that stdin and 5955796c8dcSSimon Schubert the target side can both be waited on via the same 5965796c8dcSSimon Schubert mechanism. This may not be true for DOS, if GDB is 5975796c8dcSSimon Schubert talking to the target via a TCP socket. 5985796c8dcSSimon Schubert -grossman, 8 Jun 93 */ 5995796c8dcSSimon Schubert 6005796c8dcSSimon Schubert /* Connect the user directly to the remote system. This command acts just like 6015796c8dcSSimon Schubert the 'cu' or 'tip' command. Use <CR>~. or <CR>~^D to break out. */ 6025796c8dcSSimon Schubert 6035796c8dcSSimon Schubert static struct serial *tty_desc; /* Controlling terminal */ 6045796c8dcSSimon Schubert 6055796c8dcSSimon Schubert static void 6065796c8dcSSimon Schubert cleanup_tty (serial_ttystate ttystate) 6075796c8dcSSimon Schubert { 6085796c8dcSSimon Schubert printf_unfiltered ("\r\n[Exiting connect mode]\r\n"); 6095796c8dcSSimon Schubert serial_set_tty_state (tty_desc, ttystate); 6105796c8dcSSimon Schubert xfree (ttystate); 6115796c8dcSSimon Schubert serial_close (tty_desc); 6125796c8dcSSimon Schubert } 6135796c8dcSSimon Schubert 6145796c8dcSSimon Schubert static void 6155796c8dcSSimon Schubert connect_command (char *args, int fromtty) 6165796c8dcSSimon Schubert { 6175796c8dcSSimon Schubert int c; 6185796c8dcSSimon Schubert char cur_esc = 0; 6195796c8dcSSimon Schubert serial_ttystate ttystate; 6205796c8dcSSimon Schubert struct serial *port_desc; /* TTY port */ 6215796c8dcSSimon Schubert 6225796c8dcSSimon Schubert dont_repeat (); 6235796c8dcSSimon Schubert 6245796c8dcSSimon Schubert if (args) 6255796c8dcSSimon Schubert fprintf_unfiltered (gdb_stderr, "This command takes no args. They have been ignored.\n"); 6265796c8dcSSimon Schubert 6275796c8dcSSimon Schubert printf_unfiltered ("[Entering connect mode. Use ~. or ~^D to escape]\n"); 6285796c8dcSSimon Schubert 6295796c8dcSSimon Schubert tty_desc = serial_fdopen (0); 6305796c8dcSSimon Schubert port_desc = last_serial_opened; 6315796c8dcSSimon Schubert 6325796c8dcSSimon Schubert ttystate = serial_get_tty_state (tty_desc); 6335796c8dcSSimon Schubert 6345796c8dcSSimon Schubert serial_raw (tty_desc); 6355796c8dcSSimon Schubert serial_raw (port_desc); 6365796c8dcSSimon Schubert 6375796c8dcSSimon Schubert make_cleanup (cleanup_tty, ttystate); 6385796c8dcSSimon Schubert 6395796c8dcSSimon Schubert while (1) 6405796c8dcSSimon Schubert { 6415796c8dcSSimon Schubert int mask; 6425796c8dcSSimon Schubert 6435796c8dcSSimon Schubert mask = serial_wait_2 (tty_desc, port_desc, -1); 6445796c8dcSSimon Schubert 6455796c8dcSSimon Schubert if (mask & 2) 6465796c8dcSSimon Schubert { /* tty input */ 6475796c8dcSSimon Schubert char cx; 6485796c8dcSSimon Schubert 6495796c8dcSSimon Schubert while (1) 6505796c8dcSSimon Schubert { 6515796c8dcSSimon Schubert c = serial_readchar (tty_desc, 0); 6525796c8dcSSimon Schubert 6535796c8dcSSimon Schubert if (c == SERIAL_TIMEOUT) 6545796c8dcSSimon Schubert break; 6555796c8dcSSimon Schubert 6565796c8dcSSimon Schubert if (c < 0) 6575796c8dcSSimon Schubert perror_with_name (_("connect")); 6585796c8dcSSimon Schubert 6595796c8dcSSimon Schubert cx = c; 6605796c8dcSSimon Schubert serial_write (port_desc, &cx, 1); 6615796c8dcSSimon Schubert 6625796c8dcSSimon Schubert switch (cur_esc) 6635796c8dcSSimon Schubert { 6645796c8dcSSimon Schubert case 0: 6655796c8dcSSimon Schubert if (c == '\r') 6665796c8dcSSimon Schubert cur_esc = c; 6675796c8dcSSimon Schubert break; 6685796c8dcSSimon Schubert case '\r': 6695796c8dcSSimon Schubert if (c == '~') 6705796c8dcSSimon Schubert cur_esc = c; 6715796c8dcSSimon Schubert else 6725796c8dcSSimon Schubert cur_esc = 0; 6735796c8dcSSimon Schubert break; 6745796c8dcSSimon Schubert case '~': 6755796c8dcSSimon Schubert if (c == '.' || c == '\004') 6765796c8dcSSimon Schubert return; 6775796c8dcSSimon Schubert else 6785796c8dcSSimon Schubert cur_esc = 0; 6795796c8dcSSimon Schubert } 6805796c8dcSSimon Schubert } 6815796c8dcSSimon Schubert } 6825796c8dcSSimon Schubert 6835796c8dcSSimon Schubert if (mask & 1) 6845796c8dcSSimon Schubert { /* Port input */ 6855796c8dcSSimon Schubert char cx; 6865796c8dcSSimon Schubert 6875796c8dcSSimon Schubert while (1) 6885796c8dcSSimon Schubert { 6895796c8dcSSimon Schubert c = serial_readchar (port_desc, 0); 6905796c8dcSSimon Schubert 6915796c8dcSSimon Schubert if (c == SERIAL_TIMEOUT) 6925796c8dcSSimon Schubert break; 6935796c8dcSSimon Schubert 6945796c8dcSSimon Schubert if (c < 0) 6955796c8dcSSimon Schubert perror_with_name (_("connect")); 6965796c8dcSSimon Schubert 6975796c8dcSSimon Schubert cx = c; 6985796c8dcSSimon Schubert 6995796c8dcSSimon Schubert serial_write (tty_desc, &cx, 1); 7005796c8dcSSimon Schubert } 7015796c8dcSSimon Schubert } 7025796c8dcSSimon Schubert } 7035796c8dcSSimon Schubert } 7045796c8dcSSimon Schubert #endif /* 0 */ 7055796c8dcSSimon Schubert 7065796c8dcSSimon Schubert /* Serial set/show framework. */ 7075796c8dcSSimon Schubert 7085796c8dcSSimon Schubert static struct cmd_list_element *serial_set_cmdlist; 7095796c8dcSSimon Schubert static struct cmd_list_element *serial_show_cmdlist; 7105796c8dcSSimon Schubert 7115796c8dcSSimon Schubert static void 7125796c8dcSSimon Schubert serial_set_cmd (char *args, int from_tty) 7135796c8dcSSimon Schubert { 7145796c8dcSSimon Schubert printf_unfiltered ("\"set serial\" must be followed by the name of a command.\n"); 7155796c8dcSSimon Schubert help_list (serial_set_cmdlist, "set serial ", -1, gdb_stdout); 7165796c8dcSSimon Schubert } 7175796c8dcSSimon Schubert 7185796c8dcSSimon Schubert static void 7195796c8dcSSimon Schubert serial_show_cmd (char *args, int from_tty) 7205796c8dcSSimon Schubert { 7215796c8dcSSimon Schubert cmd_show_list (serial_show_cmdlist, from_tty, ""); 7225796c8dcSSimon Schubert } 7235796c8dcSSimon Schubert 7245796c8dcSSimon Schubert 7255796c8dcSSimon Schubert void 7265796c8dcSSimon Schubert _initialize_serial (void) 7275796c8dcSSimon Schubert { 7285796c8dcSSimon Schubert #if 0 7295796c8dcSSimon Schubert add_com ("connect", class_obscure, connect_command, _("\ 7305796c8dcSSimon Schubert Connect the terminal directly up to the command monitor.\n\ 7315796c8dcSSimon Schubert Use <CR>~. or <CR>~^D to break out.")); 7325796c8dcSSimon Schubert #endif /* 0 */ 7335796c8dcSSimon Schubert 7345796c8dcSSimon Schubert add_prefix_cmd ("serial", class_maintenance, serial_set_cmd, _("\ 7355796c8dcSSimon Schubert Set default serial/parallel port configuration."), 7365796c8dcSSimon Schubert &serial_set_cmdlist, "set serial ", 7375796c8dcSSimon Schubert 0/*allow-unknown*/, 7385796c8dcSSimon Schubert &setlist); 7395796c8dcSSimon Schubert 7405796c8dcSSimon Schubert add_prefix_cmd ("serial", class_maintenance, serial_show_cmd, _("\ 7415796c8dcSSimon Schubert Show default serial/parallel port configuration."), 7425796c8dcSSimon Schubert &serial_show_cmdlist, "show serial ", 7435796c8dcSSimon Schubert 0/*allow-unknown*/, 7445796c8dcSSimon Schubert &showlist); 7455796c8dcSSimon Schubert 7465796c8dcSSimon Schubert add_setshow_filename_cmd ("remotelogfile", no_class, &serial_logfile, _("\ 7475796c8dcSSimon Schubert Set filename for remote session recording."), _("\ 7485796c8dcSSimon Schubert Show filename for remote session recording."), _("\ 7495796c8dcSSimon Schubert This file is used to record the remote session for future playback\n\ 7505796c8dcSSimon Schubert by gdbserver."), 7515796c8dcSSimon Schubert NULL, 7525796c8dcSSimon Schubert NULL, /* FIXME: i18n: */ 7535796c8dcSSimon Schubert &setlist, &showlist); 7545796c8dcSSimon Schubert 7555796c8dcSSimon Schubert add_setshow_enum_cmd ("remotelogbase", no_class, logbase_enums, 7565796c8dcSSimon Schubert &serial_logbase, _("\ 7575796c8dcSSimon Schubert Set numerical base for remote session logging"), _("\ 7585796c8dcSSimon Schubert Show numerical base for remote session logging"), NULL, 7595796c8dcSSimon Schubert NULL, 7605796c8dcSSimon Schubert NULL, /* FIXME: i18n: */ 7615796c8dcSSimon Schubert &setlist, &showlist); 7625796c8dcSSimon Schubert 7635796c8dcSSimon Schubert add_setshow_zinteger_cmd ("serial", class_maintenance, 7645796c8dcSSimon Schubert &global_serial_debug_p, _("\ 7655796c8dcSSimon Schubert Set serial debugging."), _("\ 7665796c8dcSSimon Schubert Show serial debugging."), _("\ 7675796c8dcSSimon Schubert When non-zero, serial port debugging is enabled."), 7685796c8dcSSimon Schubert NULL, 7695796c8dcSSimon Schubert NULL, /* FIXME: i18n: */ 7705796c8dcSSimon Schubert &setdebuglist, &showdebuglist); 7715796c8dcSSimon Schubert } 772