119370Spst/* Generic serial interface routines 219370Spst 3130803Smarcel Copyright 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 4130803Smarcel 2001, 2002 Free Software Foundation, Inc. 519370Spst 698944Sobrien This file is part of GDB. 719370Spst 898944Sobrien This program is free software; you can redistribute it and/or modify 998944Sobrien it under the terms of the GNU General Public License as published by 1098944Sobrien the Free Software Foundation; either version 2 of the License, or 1198944Sobrien (at your option) any later version. 1219370Spst 1398944Sobrien This program is distributed in the hope that it will be useful, 1498944Sobrien but WITHOUT ANY WARRANTY; without even the implied warranty of 1598944Sobrien MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 1698944Sobrien GNU General Public License for more details. 1719370Spst 1898944Sobrien You should have received a copy of the GNU General Public License 1998944Sobrien along with this program; if not, write to the Free Software 2098944Sobrien Foundation, Inc., 59 Temple Place - Suite 330, 2198944Sobrien Boston, MA 02111-1307, USA. */ 2298944Sobrien 2319370Spst#include "defs.h" 2419370Spst#include <ctype.h> 2519370Spst#include "serial.h" 2619370Spst#include "gdb_string.h" 2719370Spst#include "gdbcmd.h" 2819370Spst 2998944Sobrienextern void _initialize_serial (void); 3098944Sobrien 3198944Sobrien/* Is serial being debugged? */ 3298944Sobrien 3398944Sobrienstatic int global_serial_debug_p; 3498944Sobrien 3519370Spst/* Linked list of serial I/O handlers */ 3619370Spst 3719370Spststatic struct serial_ops *serial_ops_list = NULL; 3819370Spst 3919370Spst/* This is the last serial stream opened. Used by connect command. */ 4019370Spst 4198944Sobrienstatic struct serial *last_serial_opened = NULL; 4219370Spst 4319370Spst/* Pointer to list of scb's. */ 4419370Spst 4598944Sobrienstatic struct serial *scb_base; 4619370Spst 4719370Spst/* Non-NULL gives filename which contains a recording of the remote session, 4819370Spst suitable for playback by gdbserver. */ 4919370Spst 5046283Sdfrstatic char *serial_logfile = NULL; 5198944Sobrienstatic struct ui_file *serial_logfp = NULL; 5219370Spst 5398944Sobrienstatic struct serial_ops *serial_interface_lookup (char *); 5498944Sobrienstatic void serial_logchar (struct ui_file *stream, int ch_type, int ch, int timeout); 5598944Sobrienstatic const char logbase_hex[] = "hex"; 5698944Sobrienstatic const char logbase_octal[] = "octal"; 5798944Sobrienstatic const char logbase_ascii[] = "ascii"; 5898944Sobrienstatic const char *logbase_enums[] = 5998944Sobrien{logbase_hex, logbase_octal, logbase_ascii, NULL}; 6098944Sobrienstatic const char *serial_logbase = logbase_ascii; 6119370Spst 6298944Sobrien 6346283Sdfrstatic int serial_current_type = 0; 6419370Spst 6546283Sdfr/* Log char CH of type CHTYPE, with TIMEOUT */ 6646283Sdfr 6746283Sdfr/* Define bogus char to represent a BREAK. Should be careful to choose a value 6846283Sdfr that can't be confused with a normal char, or an error code. */ 6946283Sdfr#define SERIAL_BREAK 1235 7046283Sdfr 7146283Sdfrstatic void 7298944Sobrienserial_logchar (struct ui_file *stream, int ch_type, int ch, int timeout) 7319370Spst{ 7446283Sdfr if (ch_type != serial_current_type) 7519370Spst { 7698944Sobrien fprintf_unfiltered (stream, "\n%c ", ch_type); 7746283Sdfr serial_current_type = ch_type; 7819370Spst } 7919370Spst 8046283Sdfr if (serial_logbase != logbase_ascii) 8198944Sobrien fputc_unfiltered (' ', stream); 8246283Sdfr 8319370Spst switch (ch) 8419370Spst { 8546283Sdfr case SERIAL_TIMEOUT: 8698944Sobrien fprintf_unfiltered (stream, "<Timeout: %d seconds>", timeout); 8746283Sdfr return; 8846283Sdfr case SERIAL_ERROR: 8998944Sobrien fprintf_unfiltered (stream, "<Error: %s>", safe_strerror (errno)); 9046283Sdfr return; 9146283Sdfr case SERIAL_EOF: 9298944Sobrien fputs_unfiltered ("<Eof>", stream); 9346283Sdfr return; 9446283Sdfr case SERIAL_BREAK: 9598944Sobrien fputs_unfiltered ("<Break>", stream); 9646283Sdfr return; 9746283Sdfr default: 9846283Sdfr if (serial_logbase == logbase_hex) 9998944Sobrien fprintf_unfiltered (stream, "%02x", ch & 0xff); 10046283Sdfr else if (serial_logbase == logbase_octal) 10198944Sobrien fprintf_unfiltered (stream, "%03o", ch & 0xff); 10246283Sdfr else 10346283Sdfr switch (ch) 10446283Sdfr { 10598944Sobrien case '\\': 10698944Sobrien fputs_unfiltered ("\\\\", stream); 10798944Sobrien break; 10898944Sobrien case '\b': 10998944Sobrien fputs_unfiltered ("\\b", stream); 11098944Sobrien break; 11198944Sobrien case '\f': 11298944Sobrien fputs_unfiltered ("\\f", stream); 11398944Sobrien break; 11498944Sobrien case '\n': 11598944Sobrien fputs_unfiltered ("\\n", stream); 11698944Sobrien break; 11798944Sobrien case '\r': 11898944Sobrien fputs_unfiltered ("\\r", stream); 11998944Sobrien break; 12098944Sobrien case '\t': 12198944Sobrien fputs_unfiltered ("\\t", stream); 12298944Sobrien break; 12398944Sobrien case '\v': 12498944Sobrien fputs_unfiltered ("\\v", stream); 12598944Sobrien break; 12698944Sobrien default: 12798944Sobrien fprintf_unfiltered (stream, isprint (ch) ? "%c" : "\\x%02x", ch & 0xFF); 12898944Sobrien break; 12946283Sdfr } 13019370Spst } 13119370Spst} 13219370Spst 13346283Sdfrvoid 13498944Sobrienserial_log_command (const char *cmd) 13546283Sdfr{ 13646283Sdfr if (!serial_logfp) 13746283Sdfr return; 13846283Sdfr 13946283Sdfr serial_current_type = 'c'; 14046283Sdfr 14146283Sdfr fputs_unfiltered ("\nc ", serial_logfp); 14246283Sdfr fputs_unfiltered (cmd, serial_logfp); 14346283Sdfr 14446283Sdfr /* Make sure that the log file is as up-to-date as possible, 14546283Sdfr in case we are getting ready to dump core or something. */ 14646283Sdfr gdb_flush (serial_logfp); 14746283Sdfr} 14846283Sdfr 14998944Sobrien 15019370Spststatic struct serial_ops * 15198944Sobrienserial_interface_lookup (char *name) 15219370Spst{ 15319370Spst struct serial_ops *ops; 15419370Spst 15519370Spst for (ops = serial_ops_list; ops; ops = ops->next) 15619370Spst if (strcmp (name, ops->name) == 0) 15719370Spst return ops; 15819370Spst 15919370Spst return NULL; 16019370Spst} 16119370Spst 16219370Spstvoid 16398944Sobrienserial_add_interface (struct serial_ops *optable) 16419370Spst{ 16519370Spst optable->next = serial_ops_list; 16619370Spst serial_ops_list = optable; 16719370Spst} 16819370Spst 16919370Spst/* Open up a device or a network socket, depending upon the syntax of NAME. */ 17019370Spst 17198944Sobrienstruct serial * 17298944Sobrienserial_open (const char *name) 17319370Spst{ 17498944Sobrien struct serial *scb; 17519370Spst struct serial_ops *ops; 17698944Sobrien const char *open_name = name; 17719370Spst 17819370Spst for (scb = scb_base; scb; scb = scb->next) 17919370Spst if (scb->name && strcmp (scb->name, name) == 0) 18019370Spst { 18119370Spst scb->refcnt++; 18219370Spst return scb; 18319370Spst } 18419370Spst 18598944Sobrien if (strcmp (name, "pc") == 0) 18619370Spst ops = serial_interface_lookup ("pc"); 18719370Spst else if (strchr (name, ':')) 18819370Spst ops = serial_interface_lookup ("tcp"); 18919370Spst else if (strncmp (name, "lpt", 3) == 0) 19019370Spst ops = serial_interface_lookup ("parallel"); 19198944Sobrien else if (strncmp (name, "|", 1) == 0) 19298944Sobrien { 19398944Sobrien ops = serial_interface_lookup ("pipe"); 19498944Sobrien open_name = name + 1; /* discard ``|'' */ 19598944Sobrien } 19619370Spst else 19719370Spst ops = serial_interface_lookup ("hardwire"); 19819370Spst 19919370Spst if (!ops) 20019370Spst return NULL; 20119370Spst 20298944Sobrien scb = XMALLOC (struct serial); 20319370Spst 20419370Spst scb->ops = ops; 20519370Spst 20619370Spst scb->bufcnt = 0; 20719370Spst scb->bufp = scb->buf; 20819370Spst 20998944Sobrien if (scb->ops->open (scb, open_name)) 21019370Spst { 21198944Sobrien xfree (scb); 21219370Spst return NULL; 21319370Spst } 21419370Spst 21598944Sobrien scb->name = xstrdup (name); 21619370Spst scb->next = scb_base; 21719370Spst scb->refcnt = 1; 21898944Sobrien scb->debug_p = 0; 21998944Sobrien scb->async_state = 0; 22098944Sobrien scb->async_handler = NULL; 22198944Sobrien scb->async_context = NULL; 22219370Spst scb_base = scb; 22319370Spst 22419370Spst last_serial_opened = scb; 22519370Spst 22619370Spst if (serial_logfile != NULL) 22719370Spst { 22846283Sdfr serial_logfp = gdb_fopen (serial_logfile, "w"); 22919370Spst if (serial_logfp == NULL) 23046283Sdfr perror_with_name (serial_logfile); 23119370Spst } 23219370Spst 23319370Spst return scb; 23419370Spst} 23519370Spst 23698944Sobrienstruct serial * 23798944Sobrienserial_fdopen (const int fd) 23819370Spst{ 23998944Sobrien struct serial *scb; 24019370Spst struct serial_ops *ops; 24119370Spst 24219370Spst for (scb = scb_base; scb; scb = scb->next) 24319370Spst if (scb->fd == fd) 24419370Spst { 24519370Spst scb->refcnt++; 24619370Spst return scb; 24719370Spst } 24819370Spst 24919370Spst ops = serial_interface_lookup ("hardwire"); 25019370Spst 25119370Spst if (!ops) 25219370Spst return NULL; 25319370Spst 25498944Sobrien scb = XMALLOC (struct serial); 25519370Spst 25619370Spst scb->ops = ops; 25719370Spst 25819370Spst scb->bufcnt = 0; 25919370Spst scb->bufp = scb->buf; 26019370Spst 26119370Spst scb->fd = fd; 26219370Spst 26319370Spst scb->name = NULL; 26419370Spst scb->next = scb_base; 26519370Spst scb->refcnt = 1; 26698944Sobrien scb->debug_p = 0; 26798944Sobrien scb->async_state = 0; 26898944Sobrien scb->async_handler = NULL; 26998944Sobrien scb->async_context = NULL; 27019370Spst scb_base = scb; 27119370Spst 27219370Spst last_serial_opened = scb; 27319370Spst 27419370Spst return scb; 27519370Spst} 27619370Spst 27798944Sobrienstatic void 27898944Sobriendo_serial_close (struct serial *scb, int really_close) 27919370Spst{ 28098944Sobrien struct serial *tmp_scb; 28119370Spst 28219370Spst last_serial_opened = NULL; 28319370Spst 28419370Spst if (serial_logfp) 28519370Spst { 28646283Sdfr fputs_unfiltered ("\nEnd of log\n", serial_logfp); 28746283Sdfr serial_current_type = 0; 28846283Sdfr 28946283Sdfr /* XXX - What if serial_logfp == gdb_stdout or gdb_stderr? */ 29098944Sobrien ui_file_delete (serial_logfp); 29119370Spst serial_logfp = NULL; 29219370Spst } 29319370Spst 29419370Spst/* This is bogus. It's not our fault if you pass us a bad scb...! Rob, you 29519370Spst should fix your code instead. */ 29619370Spst 29719370Spst if (!scb) 29819370Spst return; 29919370Spst 30019370Spst scb->refcnt--; 30119370Spst if (scb->refcnt > 0) 30219370Spst return; 30319370Spst 30498944Sobrien /* ensure that the FD has been taken out of async mode */ 30598944Sobrien if (scb->async_handler != NULL) 30698944Sobrien serial_async (scb, NULL, NULL); 30798944Sobrien 30819370Spst if (really_close) 30919370Spst scb->ops->close (scb); 31019370Spst 31119370Spst if (scb->name) 31298944Sobrien xfree (scb->name); 31319370Spst 31419370Spst if (scb_base == scb) 31519370Spst scb_base = scb_base->next; 31619370Spst else 31719370Spst for (tmp_scb = scb_base; tmp_scb; tmp_scb = tmp_scb->next) 31819370Spst { 31919370Spst if (tmp_scb->next != scb) 32019370Spst continue; 32119370Spst 32219370Spst tmp_scb->next = tmp_scb->next->next; 32319370Spst break; 32419370Spst } 32519370Spst 32698944Sobrien xfree (scb); 32719370Spst} 32819370Spst 32998944Sobrienvoid 33098944Sobrienserial_close (struct serial *scb) 33198944Sobrien{ 33298944Sobrien do_serial_close (scb, 1); 33398944Sobrien} 33498944Sobrien 33598944Sobrienvoid 33698944Sobrienserial_un_fdopen (struct serial *scb) 33798944Sobrien{ 33898944Sobrien do_serial_close (scb, 0); 33998944Sobrien} 34098944Sobrien 34198944Sobrienint 34298944Sobrienserial_readchar (struct serial *scb, int timeout) 34398944Sobrien{ 34498944Sobrien int ch; 34598944Sobrien 34698944Sobrien /* FIXME: cagney/1999-10-11: Don't enable this check until the ASYNC 34798944Sobrien code is finished. */ 34898944Sobrien if (0 && serial_is_async_p (scb) && timeout < 0) 34998944Sobrien internal_error (__FILE__, __LINE__, 35098944Sobrien "serial_readchar: blocking read in async mode"); 35198944Sobrien 35298944Sobrien ch = scb->ops->readchar (scb, timeout); 35398944Sobrien if (serial_logfp != NULL) 35498944Sobrien { 35598944Sobrien serial_logchar (serial_logfp, 'r', ch, timeout); 35698944Sobrien 35798944Sobrien /* Make sure that the log file is as up-to-date as possible, 35898944Sobrien in case we are getting ready to dump core or something. */ 35998944Sobrien gdb_flush (serial_logfp); 36098944Sobrien } 36198944Sobrien if (serial_debug_p (scb)) 36298944Sobrien { 36398944Sobrien fprintf_unfiltered (gdb_stdlog, "["); 36498944Sobrien serial_logchar (gdb_stdlog, 'r', ch, timeout); 36598944Sobrien fprintf_unfiltered (gdb_stdlog, "]"); 36698944Sobrien gdb_flush (gdb_stdlog); 36798944Sobrien } 36898944Sobrien 36998944Sobrien return (ch); 37098944Sobrien} 37198944Sobrien 37298944Sobrienint 37398944Sobrienserial_write (struct serial *scb, const char *str, int len) 37498944Sobrien{ 37598944Sobrien if (serial_logfp != NULL) 37698944Sobrien { 37798944Sobrien int count; 37898944Sobrien 37998944Sobrien for (count = 0; count < len; count++) 38098944Sobrien serial_logchar (serial_logfp, 'w', str[count] & 0xff, 0); 38198944Sobrien 38298944Sobrien /* Make sure that the log file is as up-to-date as possible, 38398944Sobrien in case we are getting ready to dump core or something. */ 38498944Sobrien gdb_flush (serial_logfp); 38598944Sobrien } 38698944Sobrien 38798944Sobrien return (scb->ops->write (scb, str, len)); 38898944Sobrien} 38998944Sobrien 39098944Sobrienvoid 39198944Sobrienserial_printf (struct serial *desc, const char *format,...) 39298944Sobrien{ 39398944Sobrien va_list args; 39498944Sobrien char *buf; 39598944Sobrien va_start (args, format); 39698944Sobrien 39798944Sobrien xvasprintf (&buf, format, args); 39898944Sobrien serial_write (desc, buf, strlen (buf)); 39998944Sobrien 40098944Sobrien xfree (buf); 40198944Sobrien va_end (args); 40298944Sobrien} 40398944Sobrien 40498944Sobrienint 40598944Sobrienserial_drain_output (struct serial *scb) 40698944Sobrien{ 40798944Sobrien return scb->ops->drain_output (scb); 40898944Sobrien} 40998944Sobrien 41098944Sobrienint 41198944Sobrienserial_flush_output (struct serial *scb) 41298944Sobrien{ 41398944Sobrien return scb->ops->flush_output (scb); 41498944Sobrien} 41598944Sobrien 41698944Sobrienint 41798944Sobrienserial_flush_input (struct serial *scb) 41898944Sobrien{ 41998944Sobrien return scb->ops->flush_input (scb); 42098944Sobrien} 42198944Sobrien 42298944Sobrienint 42398944Sobrienserial_send_break (struct serial *scb) 42498944Sobrien{ 42598944Sobrien if (serial_logfp != NULL) 42698944Sobrien serial_logchar (serial_logfp, 'w', SERIAL_BREAK, 0); 42798944Sobrien 42898944Sobrien return (scb->ops->send_break (scb)); 42998944Sobrien} 43098944Sobrien 43198944Sobrienvoid 43298944Sobrienserial_raw (struct serial *scb) 43398944Sobrien{ 43498944Sobrien scb->ops->go_raw (scb); 43598944Sobrien} 43698944Sobrien 43798944Sobrienserial_ttystate 43898944Sobrienserial_get_tty_state (struct serial *scb) 43998944Sobrien{ 44098944Sobrien return scb->ops->get_tty_state (scb); 44198944Sobrien} 44298944Sobrien 44398944Sobrienint 44498944Sobrienserial_set_tty_state (struct serial *scb, serial_ttystate ttystate) 44598944Sobrien{ 44698944Sobrien return scb->ops->set_tty_state (scb, ttystate); 44798944Sobrien} 44898944Sobrien 44998944Sobrienvoid 45098944Sobrienserial_print_tty_state (struct serial *scb, 45198944Sobrien serial_ttystate ttystate, 45298944Sobrien struct ui_file *stream) 45398944Sobrien{ 45498944Sobrien scb->ops->print_tty_state (scb, ttystate, stream); 45598944Sobrien} 45698944Sobrien 45798944Sobrienint 45898944Sobrienserial_noflush_set_tty_state (struct serial *scb, 45998944Sobrien serial_ttystate new_ttystate, 46098944Sobrien serial_ttystate old_ttystate) 46198944Sobrien{ 46298944Sobrien return scb->ops->noflush_set_tty_state (scb, new_ttystate, old_ttystate); 46398944Sobrien} 46498944Sobrien 46598944Sobrienint 46698944Sobrienserial_setbaudrate (struct serial *scb, int rate) 46798944Sobrien{ 46898944Sobrien return scb->ops->setbaudrate (scb, rate); 46998944Sobrien} 47098944Sobrien 47198944Sobrienint 47298944Sobrienserial_setstopbits (struct serial *scb, int num) 47398944Sobrien{ 47498944Sobrien return scb->ops->setstopbits (scb, num); 47598944Sobrien} 47698944Sobrien 47798944Sobrienint 47898944Sobrienserial_can_async_p (struct serial *scb) 47998944Sobrien{ 48098944Sobrien return (scb->ops->async != NULL); 48198944Sobrien} 48298944Sobrien 48398944Sobrienint 48498944Sobrienserial_is_async_p (struct serial *scb) 48598944Sobrien{ 48698944Sobrien return (scb->ops->async != NULL) && (scb->async_handler != NULL); 48798944Sobrien} 48898944Sobrien 48998944Sobrienvoid 49098944Sobrienserial_async (struct serial *scb, 49198944Sobrien serial_event_ftype *handler, 49298944Sobrien void *context) 49398944Sobrien{ 49498944Sobrien /* Only change mode if there is a need. */ 49598944Sobrien if ((scb->async_handler == NULL) 49698944Sobrien != (handler == NULL)) 49798944Sobrien scb->ops->async (scb, handler != NULL); 49898944Sobrien scb->async_handler = handler; 49998944Sobrien scb->async_context = context; 50098944Sobrien} 50198944Sobrien 50298944Sobrienint 50398944Sobriendeprecated_serial_fd (struct serial *scb) 50498944Sobrien{ 50598944Sobrien /* FIXME: should this output a warning that deprecated code is being 50698944Sobrien called? */ 50798944Sobrien if (scb->fd < 0) 50898944Sobrien { 50998944Sobrien internal_error (__FILE__, __LINE__, 51098944Sobrien "serial: FD not valid"); 51198944Sobrien } 51298944Sobrien return scb->fd; /* sigh */ 51398944Sobrien} 51498944Sobrien 51598944Sobrienvoid 51698944Sobrienserial_debug (struct serial *scb, int debug_p) 51798944Sobrien{ 51898944Sobrien scb->debug_p = debug_p; 51998944Sobrien} 52098944Sobrien 52198944Sobrienint 52298944Sobrienserial_debug_p (struct serial *scb) 52398944Sobrien{ 52498944Sobrien return scb->debug_p || global_serial_debug_p; 52598944Sobrien} 52698944Sobrien 52798944Sobrien 52819370Spst#if 0 52998944Sobrien/* The connect command is #if 0 because I hadn't thought of an elegant 53098944Sobrien way to wait for I/O on two `struct serial *'s simultaneously. Two 53198944Sobrien solutions came to mind: 53219370Spst 53398944Sobrien 1) Fork, and have have one fork handle the to user direction, 53498944Sobrien and have the other hand the to target direction. This 53598944Sobrien obviously won't cut it for MSDOS. 53619370Spst 53798944Sobrien 2) Use something like select. This assumes that stdin and 53898944Sobrien the target side can both be waited on via the same 53998944Sobrien mechanism. This may not be true for DOS, if GDB is 54098944Sobrien talking to the target via a TCP socket. 54198944Sobrien -grossman, 8 Jun 93 */ 54219370Spst 54319370Spst/* Connect the user directly to the remote system. This command acts just like 54419370Spst the 'cu' or 'tip' command. Use <CR>~. or <CR>~^D to break out. */ 54519370Spst 54698944Sobrienstatic struct serial *tty_desc; /* Controlling terminal */ 54719370Spst 54819370Spststatic void 54998944Sobriencleanup_tty (serial_ttystate ttystate) 55019370Spst{ 55119370Spst printf_unfiltered ("\r\n[Exiting connect mode]\r\n"); 55298944Sobrien serial_set_tty_state (tty_desc, ttystate); 55398944Sobrien xfree (ttystate); 55498944Sobrien serial_close (tty_desc); 55519370Spst} 55619370Spst 55719370Spststatic void 55898944Sobrienconnect_command (char *args, int fromtty) 55919370Spst{ 56019370Spst int c; 56119370Spst char cur_esc = 0; 56219370Spst serial_ttystate ttystate; 56398944Sobrien struct serial *port_desc; /* TTY port */ 56419370Spst 56598944Sobrien dont_repeat (); 56619370Spst 56719370Spst if (args) 56898944Sobrien fprintf_unfiltered (gdb_stderr, "This command takes no args. They have been ignored.\n"); 56919370Spst 57098944Sobrien printf_unfiltered ("[Entering connect mode. Use ~. or ~^D to escape]\n"); 57198944Sobrien 57298944Sobrien tty_desc = serial_fdopen (0); 57319370Spst port_desc = last_serial_opened; 57419370Spst 57598944Sobrien ttystate = serial_get_tty_state (tty_desc); 57619370Spst 57798944Sobrien serial_raw (tty_desc); 57898944Sobrien serial_raw (port_desc); 57919370Spst 58019370Spst make_cleanup (cleanup_tty, ttystate); 58119370Spst 58219370Spst while (1) 58319370Spst { 58419370Spst int mask; 58519370Spst 58698944Sobrien mask = serial_wait_2 (tty_desc, port_desc, -1); 58719370Spst 58819370Spst if (mask & 2) 58919370Spst { /* tty input */ 59019370Spst char cx; 59119370Spst 59219370Spst while (1) 59319370Spst { 59498944Sobrien c = serial_readchar (tty_desc, 0); 59519370Spst 59619370Spst if (c == SERIAL_TIMEOUT) 59798944Sobrien break; 59819370Spst 59919370Spst if (c < 0) 60098944Sobrien perror_with_name ("connect"); 60119370Spst 60219370Spst cx = c; 60398944Sobrien serial_write (port_desc, &cx, 1); 60419370Spst 60519370Spst switch (cur_esc) 60619370Spst { 60719370Spst case 0: 60819370Spst if (c == '\r') 60919370Spst cur_esc = c; 61019370Spst break; 61119370Spst case '\r': 61219370Spst if (c == '~') 61319370Spst cur_esc = c; 61419370Spst else 61519370Spst cur_esc = 0; 61619370Spst break; 61719370Spst case '~': 61819370Spst if (c == '.' || c == '\004') 61919370Spst return; 62019370Spst else 62119370Spst cur_esc = 0; 62219370Spst } 62319370Spst } 62419370Spst } 62519370Spst 62619370Spst if (mask & 1) 62719370Spst { /* Port input */ 62819370Spst char cx; 62919370Spst 63019370Spst while (1) 63119370Spst { 63298944Sobrien c = serial_readchar (port_desc, 0); 63319370Spst 63419370Spst if (c == SERIAL_TIMEOUT) 63598944Sobrien break; 63619370Spst 63719370Spst if (c < 0) 63898944Sobrien perror_with_name ("connect"); 63919370Spst 64019370Spst cx = c; 64119370Spst 64298944Sobrien serial_write (tty_desc, &cx, 1); 64319370Spst } 64419370Spst } 64519370Spst } 64619370Spst} 64719370Spst#endif /* 0 */ 64819370Spst 64998944Sobrien/* Serial set/show framework. */ 65019370Spst 65198944Sobrienstatic struct cmd_list_element *serial_set_cmdlist; 65298944Sobrienstatic struct cmd_list_element *serial_show_cmdlist; 65319370Spst 65498944Sobrienstatic void 65598944Sobrienserial_set_cmd (char *args, int from_tty) 65698944Sobrien{ 65798944Sobrien printf_unfiltered ("\"set serial\" must be followed by the name of a command.\n"); 65898944Sobrien help_list (serial_set_cmdlist, "set serial ", -1, gdb_stdout); 65998944Sobrien} 66019370Spst 66198944Sobrienstatic void 66298944Sobrienserial_show_cmd (char *args, int from_tty) 66398944Sobrien{ 66498944Sobrien cmd_show_list (serial_show_cmdlist, from_tty, ""); 66519370Spst} 66619370Spst 66798944Sobrien 66819370Spstvoid 66998944Sobrien_initialize_serial (void) 67019370Spst{ 67119370Spst#if 0 67219370Spst add_com ("connect", class_obscure, connect_command, 67319370Spst "Connect the terminal directly up to the command monitor.\n\ 67419370SpstUse <CR>~. or <CR>~^D to break out."); 67519370Spst#endif /* 0 */ 67619370Spst 67798944Sobrien add_prefix_cmd ("serial", class_maintenance, serial_set_cmd, "\ 67898944SobrienSet default serial/parallel port configuration.", 67998944Sobrien &serial_set_cmdlist, "set serial ", 68098944Sobrien 0/*allow-unknown*/, 68198944Sobrien &setlist); 68298944Sobrien 68398944Sobrien add_prefix_cmd ("serial", class_maintenance, serial_show_cmd, "\ 68498944SobrienShow default serial/parallel port configuration.", 68598944Sobrien &serial_show_cmdlist, "show serial ", 68698944Sobrien 0/*allow-unknown*/, 68798944Sobrien &showlist); 68898944Sobrien 68998944Sobrien add_show_from_set 69046283Sdfr (add_set_cmd ("remotelogfile", no_class, 69146283Sdfr var_filename, (char *) &serial_logfile, 69246283Sdfr "Set filename for remote session recording.\n\ 69319370SpstThis file is used to record the remote session for future playback\n\ 69498944Sobrienby gdbserver.", 69546283Sdfr &setlist), 69646283Sdfr &showlist); 69719370Spst 69898944Sobrien add_show_from_set 69946283Sdfr (add_set_enum_cmd ("remotelogbase", no_class, 70098944Sobrien logbase_enums, &serial_logbase, 70146283Sdfr "Set numerical base for remote session logging", 70246283Sdfr &setlist), 70346283Sdfr &showlist); 70498944Sobrien 70598944Sobrien add_show_from_set (add_set_cmd ("serial", 70698944Sobrien class_maintenance, 70798944Sobrien var_zinteger, 70898944Sobrien (char *)&global_serial_debug_p, 70998944Sobrien "Set serial debugging.\n\ 71098944SobrienWhen non-zero, serial port debugging is enabled.", &setdebuglist), 71198944Sobrien &showdebuglist); 71219370Spst} 713