* a68v-xdep.c (store_inferior_registers): declare as void.

* infptrace.c:  HP/Apollos have ptrace.h in the wrong place.
* remote-st2000.c:  Massive changes to use new serial package.
Also added 'connect' command to transparantly connect to serial
port.
* ser-termios.c:  Big cleanup, use nicer coding conventions.
* ser-bsd.c:  New module, serial stuff for BSD systems.
* serial.h:  Define struct ttystate properly using HAVE_TERMIO.
* xm-apollo68b.h:  #define PTRACE_IN_WRONG_PLACE...
This commit is contained in:
Stu Grossman 1992-09-08 22:46:08 +00:00
parent 1e4f3c200a
commit a0f9783ea7
7 changed files with 648 additions and 395 deletions

View File

@ -141,6 +141,7 @@ fetch_inferior_registers ()
} }
/* ARGSUSED */ /* ARGSUSED */
void
store_inferior_registers (regno) store_inferior_registers (regno)
int regno; int regno;
{ {

View File

@ -31,8 +31,12 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
#include <signal.h> #include <signal.h>
#include <sys/ioctl.h> #include <sys/ioctl.h>
#ifndef USG #ifndef USG
#ifdef PTRACE_IN_WRONG_PLACE
#include <ptrace.h>
#else
#include <sys/ptrace.h> #include <sys/ptrace.h>
#endif #endif
#endif
#if !defined (PT_KILL) #if !defined (PT_KILL)
#define PT_KILL 8 #define PT_KILL 8
@ -395,8 +399,7 @@ child_xfer_memory (memaddr, myaddr, len, write, target)
/* Copy data to be written over corresponding part of buffer */ /* Copy data to be written over corresponding part of buffer */
(void) memcpy ((char *) buffer + (memaddr & (sizeof (int) - 1)), myaddr, memcpy ((char *) buffer + (memaddr & (sizeof (int) - 1)), myaddr, len);
len);
/* Write the entire buffer. */ /* Write the entire buffer. */
@ -431,8 +434,7 @@ child_xfer_memory (memaddr, myaddr, len, write, target)
} }
/* Copy appropriate bytes out of the buffer. */ /* Copy appropriate bytes out of the buffer. */
(void) memcpy (myaddr, (char *) buffer + (memaddr & (sizeof (int) - 1)), memcpy (myaddr, (char *) buffer + (memaddr & (sizeof (int) - 1)), len);
len);
} }
return len; return len;
} }

View File

@ -36,12 +36,13 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
#include "defs.h" #include "defs.h"
#include "gdbcore.h" #include "gdbcore.h"
#include "terminal.h"
#include "target.h" #include "target.h"
#include "wait.h" #include "wait.h"
#include <varargs.h> #include <varargs.h>
#include <signal.h> #include <signal.h>
#include <string.h> #include <string.h>
#include <sys/types.h>
#include "serial.h"
extern struct target_ops st2000_ops; /* Forward declaration */ extern struct target_ops st2000_ops; /* Forward declaration */
@ -61,10 +62,6 @@ static int timeout = 24;
starts. */ starts. */
int st2000_desc = -1; int st2000_desc = -1;
/* stream which is fdopen'd from st2000_desc. Only valid when
st2000_desc != -1. */
FILE *st2000_stream;
/* Send data to stdebug. Works just like printf. */ /* Send data to stdebug. Works just like printf. */
static void static void
@ -73,60 +70,62 @@ printf_stdebug(va_alist)
{ {
va_list args; va_list args;
char *pattern; char *pattern;
char buf[200];
va_start(args); va_start(args);
pattern = va_arg(args, char *); pattern = va_arg(args, char *);
vfprintf(st2000_stream, pattern, args); vsprintf(buf, pattern, args);
fflush(st2000_stream); if (!serial_write(buf, strlen(buf)))
fprintf(stderr, "serial_write failed: %s\n", safe_strerror(errno));
} }
/* Read a character from the remote system, doing all the fancy /* Read a character from the remote system, doing all the fancy
timeout stuff. */ timeout stuff. */
static int static int
readchar () readchar(timeout)
int timeout;
{ {
char buf; int c;
buf = '\0'; c = serial_readchar(timeout);
#ifdef HAVE_TERMIO
/* termio does the timeout for us. */ #ifdef LOG_FILE
read (st2000_desc, &buf, 1); putc(c & 0x7f, log_file);
#else
alarm (timeout);
if (read (st2000_desc, &buf, 1) < 0)
{
if (errno == EINTR)
error ("Timeout reading from remote system.");
else
perror_with_name ("remote");
}
alarm (0);
#endif #endif
if (buf == '\0') if (c >= 0)
return c & 0x7f;
if (c == -2)
{
if (timeout == 0)
return c; /* Polls shouldn't generate timeout errors */
error("Timeout reading from remote system."); error("Timeout reading from remote system.");
#if defined (LOG_FILE)
putc (buf & 0x7f, log_file);
#endif
return buf & 0x7f;
} }
/* Keep discarding input from the remote system, until STRING is found. perror_with_name("remote-st2000");
}
/* Scan input from the remote system, until STRING is found. If DISCARD is
non-zero, then discard non-matching input, else print it out.
Let the user break out immediately. */ Let the user break out immediately. */
static void static void
expect (string) expect(string, discard)
char *string; char *string;
int discard;
{ {
char *p = string; char *p = string;
int c;
immediate_quit = 1; immediate_quit = 1;
while (1) while (1)
{ {
if (readchar() == *p) c = readchar(timeout);
if (c == *p++)
{ {
p++;
if (*p == '\0') if (*p == '\0')
{ {
immediate_quit = 0; immediate_quit = 0;
@ -134,9 +133,17 @@ expect (string)
} }
} }
else else
{
if (!discard)
{
fwrite(string, 1, (p - 1) - string, stdout);
putchar((char)c);
fflush(stdout);
}
p = string; p = string;
} }
} }
}
/* Keep discarding input until we see the STDEBUG prompt. /* Keep discarding input until we see the STDEBUG prompt.
@ -153,14 +160,15 @@ expect (string)
necessary to prevent getting into states from which we can't necessary to prevent getting into states from which we can't
recover. */ recover. */
static void static void
expect_prompt () expect_prompt(discard)
int discard;
{ {
#if defined (LOG_FILE) #if defined (LOG_FILE)
/* This is a convenient place to do this. The idea is to do it often /* This is a convenient place to do this. The idea is to do it often
enough that we never lose much data if we terminate abnormally. */ enough that we never lose much data if we terminate abnormally. */
fflush(log_file); fflush(log_file);
#endif #endif
expect ("dbug> "); expect ("dbug> ", discard);
} }
/* Get a hex digit from the remote system & return its value. /* Get a hex digit from the remote system & return its value.
@ -172,7 +180,7 @@ get_hex_digit (ignore_space)
int ch; int ch;
while (1) while (1)
{ {
ch = readchar (); ch = readchar(timeout);
if (ch >= '0' && ch <= '9') if (ch >= '0' && ch <= '9')
return ch - '0'; return ch - '0';
else if (ch >= 'A' && ch <= 'F') else if (ch >= 'A' && ch <= 'F')
@ -183,13 +191,13 @@ get_hex_digit (ignore_space)
; ;
else else
{ {
expect_prompt (); expect_prompt(1);
error("Invalid hex digit from remote system."); error("Invalid hex digit from remote system.");
} }
} }
} }
/* Get a byte from st2000_desc and put it in *BYT. Accept any number /* Get a byte from stdebug and put it in *BYT. Accept any number
leading spaces. */ leading spaces. */
static void static void
get_hex_byte (byt) get_hex_byte (byt)
@ -223,21 +231,6 @@ get_hex_regs (n, regno)
} }
} }
/* Called when SIGALRM signal sent due to alarm() timeout. */
#ifndef HAVE_TERMIO
#ifndef __STDC__
#define volatile /**/
#endif
volatile int n_alarms;
static void
st2000_timer ()
{
n_alarms++;
}
#endif
/* This is called not only when we first attach, but also when the /* This is called not only when we first attach, but also when the
user types "run" after having attached. */ user types "run" after having attached. */
static void static void
@ -279,129 +272,36 @@ st2000_create_inferior (execfile, args, env)
proceed ((CORE_ADDR)entry_pt, -1, 0); /* Let 'er rip... */ proceed ((CORE_ADDR)entry_pt, -1, 0); /* Let 'er rip... */
} }
/* Translate baud rates from integers to damn B_codes. Unix should
have outgrown this crap years ago, but even POSIX wouldn't buck it. */
#ifndef B19200
#define B19200 EXTA
#endif
#ifndef B38400
#define B38400 EXTB
#endif
static struct {int rate, damn_b;} baudtab[] = {
{0, B0},
{50, B50},
{75, B75},
{110, B110},
{134, B134},
{150, B150},
{200, B200},
{300, B300},
{600, B600},
{1200, B1200},
{1800, B1800},
{2400, B2400},
{4800, B4800},
{9600, B9600},
{19200, B19200},
{38400, B38400},
{-1, -1},
};
static int
damn_b (rate)
int rate;
{
int i;
for (i = 0; baudtab[i].rate != -1; i++)
if (rate == baudtab[i].rate) return baudtab[i].damn_b;
return B38400; /* Random */
}
/* Open a connection to a remote debugger. /* Open a connection to a remote debugger.
NAME is the filename used for communication. */ NAME is the filename used for communication. */
static int baudrate = 9600; static int baudrate = 9600;
static char *dev_name; static char dev_name[100];
static TERMINAL old_sg;
static void static void
st2000_open (name, from_tty) st2000_open(args, from_tty)
char *name; char *args;
int from_tty; int from_tty;
{ {
TERMINAL sg; int n;
char junk[100];
char *p;
target_preopen(from_tty); target_preopen(from_tty);
if (!name) n = sscanf(args, " %s %d %s", dev_name, &baudrate, junk);
goto erroid;
/* Find the first whitespace character, it separates dev_name from if (n != 2)
the baud rate. */ error("Bad arguments. Usage: target st2000 <device> <speed>\n\
or target st2000 <host> <port>\n");
for (p = name; *p && !isspace (*p); p++)
;
if (*p == '\0')
erroid:
error ("\
Please include the name of the device for the serial port, and the baud rate.");
dev_name = alloca (p - name + 1);
strncpy (dev_name, name, p - name);
dev_name[p - name] = '\0';
/* Skip over the whitespace after dev_name */
for (; isspace (*p); p++)
/*EMPTY*/;
if (1 != sscanf (p, "%d ", &baudrate))
goto erroid;
st2000_close(0); st2000_close(0);
st2000_desc = open (dev_name, O_RDWR); st2000_desc = serial_open(dev_name);
if (st2000_desc < 0)
perror_with_name (dev_name);
ioctl (st2000_desc, TIOCGETP, &sg);
old_sg = sg;
#ifdef HAVE_TERMIO serial_setbaudrate(baudrate);
sg.c_cc[VMIN] = 0; /* read with timeout. */
sg.c_cc[VTIME] = timeout * 10;
sg.c_lflag &= ~(ICANON | ECHO);
sg.c_cflag = (sg.c_cflag & ~CBAUD) | damn_b (baudrate);
#else
sg.sg_ispeed = damn_b (baudrate);
sg.sg_ospeed = damn_b (baudrate);
sg.sg_flags |= RAW | ANYP;
sg.sg_flags &= ~ECHO;
#endif
ioctl (st2000_desc, TIOCSETP, &sg);
st2000_stream = fdopen (st2000_desc, "r+");
push_target(&st2000_ops); push_target(&st2000_ops);
#ifndef HAVE_TERMIO
#ifndef NO_SIGINTERRUPT
/* Cause SIGALRM's to make reads fail with EINTR instead of resuming
the read. */
if (siginterrupt (SIGALRM, 1) != 0)
perror ("st2000_open: error in siginterrupt");
#endif
/* Set up read timeout timer. */
if ((void (*)) signal (SIGALRM, st2000_timer) == (void (*)) -1)
perror ("st2000_open: error in signal");
#endif
#if defined (LOG_FILE) #if defined (LOG_FILE)
log_file = fopen (LOG_FILE, "w"); log_file = fopen (LOG_FILE, "w");
if (log_file == NULL) if (log_file == NULL)
@ -409,9 +309,9 @@ Please include the name of the device for the serial port, and the baud rate.");
#endif #endif
/* Hello? Are you there? */ /* Hello? Are you there? */
printf_stdebug ("\r"); printf_stdebug("\003"); /* ^C wakes up dbug */
expect_prompt (); expect_prompt(1);
if (from_tty) if (from_tty)
printf("Remote %s connected to %s\n", target_shortname, printf("Remote %s connected to %s\n", target_shortname,
@ -424,27 +324,14 @@ static void
st2000_close (quitting) st2000_close (quitting)
int quitting; int quitting;
{ {
serial_close();
/* Reset the terminal to its original settings. */
ioctl (st2000_desc, TIOCSETP, &old_sg);
/* Due to a bug in Unix, fclose closes not only the stdio stream,
but also the file descriptor. So we don't actually close
st2000_desc. */
if (st2000_stream)
fclose (st2000_stream); /* This also closes st2000_desc */
/* Do not try to close st2000_desc again, later in the program. */
st2000_stream = NULL;
st2000_desc = -1;
#if defined (LOG_FILE) #if defined (LOG_FILE)
if (log_file) { if (log_file) {
if (ferror(log_file)) if (ferror(log_file))
printf ("Error writing log file.\n"); fprintf(stderr, "Error writing log file.\n");
if (fclose(log_file) != 0) if (fclose(log_file) != 0)
printf ("Error closing log file.\n"); fprintf(stderr, "Error closing log file.\n");
} }
#endif #endif
} }
@ -471,13 +358,13 @@ st2000_resume (step, sig)
{ {
printf_stdebug ("ST\r"); printf_stdebug ("ST\r");
/* Wait for the echo. */ /* Wait for the echo. */
expect ("ST\r"); expect ("ST\r", 1);
} }
else else
{ {
printf_stdebug ("GO\r"); printf_stdebug ("GO\r");
/* Swallow the echo. */ /* Swallow the echo. */
expect ("GO\r"); expect ("GO\r", 1);
} }
} }
@ -488,56 +375,16 @@ static int
st2000_wait (status) st2000_wait (status)
WAITTYPE *status; WAITTYPE *status;
{ {
/* FIXME --- USE A REAL STRING MATCHING ALGORITHM HERE!!! */
static char bpt[] = "dbug> ";
char *bp = bpt;
/* Large enough for either sizeof (bpt) or sizeof (exitmsg) chars. */
char swallowed[50];
/* Current position in swallowed. */
char *swallowed_p = swallowed;
int ch;
int ch_handled;
int old_timeout = timeout; int old_timeout = timeout;
WSETEXIT ((*status), 0); WSETEXIT ((*status), 0);
timeout = 0; /* Don't time out -- user program is running. */ timeout = 0; /* Don't time out -- user program is running. */
while (1)
{
ch_handled = 0;
ch = readchar ();
if (ch == *bp)
{
bp++;
if (*bp == '\0')
break;
ch_handled = 1;
*swallowed_p++ = ch; expect_prompt(0); /* Wait for prompt, outputting extraneous text */
}
else
bp = bpt;
if (!ch_handled)
{
char *p;
/* Print out any characters which have been swallowed. */
for (p = swallowed; p < swallowed_p; ++p)
putc (*p, stdout);
swallowed_p = swallowed;
putc (ch, stdout);
}
}
if (*bp == '\000')
WSETSTOP ((*status), SIGTRAP); WSETSTOP ((*status), SIGTRAP);
else
WSETEXIT ((*status), 0);
timeout = old_timeout; timeout = old_timeout;
return 0; return 0;
@ -589,10 +436,10 @@ st2000_fetch_register (regno)
{ {
char *name = get_reg_name (regno); char *name = get_reg_name (regno);
printf_stdebug ("DR %s\r", name); printf_stdebug ("DR %s\r", name);
expect (name); expect (name, 1);
expect (" : "); expect (" : ", 1);
get_hex_regs (1, regno); get_hex_regs (1, regno);
expect_prompt (); expect_prompt (1);
} }
return; return;
} }
@ -623,7 +470,7 @@ st2000_store_register (regno)
printf_stdebug ("PR %s %x\r", get_reg_name (regno), printf_stdebug ("PR %s %x\r", get_reg_name (regno),
read_register (regno)); read_register (regno));
expect_prompt (); expect_prompt (1);
} }
} }
@ -659,7 +506,7 @@ st2000_write_inferior_memory (memaddr, myaddr, len)
for (i = 0; i < len; i++) for (i = 0; i < len; i++)
{ {
printf_stdebug ("PM.B %x %x\r", memaddr + i, myaddr[i]); printf_stdebug ("PM.B %x %x\r", memaddr + i, myaddr[i]);
expect_prompt (); expect_prompt (1);
} }
return len; return len;
} }
@ -708,12 +555,12 @@ st2000_read_inferior_memory(memaddr, myaddr, len)
len_this_pass = (len - count); len_this_pass = (len - count);
printf_stdebug ("DI.L %x %x\r", startaddr, len_this_pass); printf_stdebug ("DI.L %x %x\r", startaddr, len_this_pass);
expect (": "); expect (": ", 1);
for (i = 0; i < len_this_pass; i++) for (i = 0; i < len_this_pass; i++)
get_hex_byte (&myaddr[count++]); get_hex_byte (&myaddr[count++]);
expect_prompt (); expect_prompt (1);
startaddr += len_this_pass; startaddr += len_this_pass;
} }
@ -775,7 +622,7 @@ st2000_insert_breakpoint (addr, shadow)
st2000_read_inferior_memory(addr, shadow, memory_breakpoint_size); st2000_read_inferior_memory(addr, shadow, memory_breakpoint_size);
printf_stdebug("BR %x H\r", addr); printf_stdebug("BR %x H\r", addr);
expect_prompt(); expect_prompt(1);
return 0; return 0;
} }
@ -796,7 +643,7 @@ st2000_remove_breakpoint (addr, shadow)
breakaddr[i] = 0; breakaddr[i] = 0;
printf_stdebug("CB %d\r", i); printf_stdebug("CB %d\r", i);
expect_prompt(); expect_prompt(1);
return 0; return 0;
} }
@ -804,29 +651,160 @@ st2000_remove_breakpoint (addr, shadow)
return 1; return 1;
} }
/* Put a command string, in args, out to STDBUG. Output from STDBUG is placed
on the users terminal until the prompt is seen. */
static void
st2000_command (args, fromtty)
char *args;
int fromtty;
{
if (st2000_desc < 0)
error("st2000 target not open.");
if (!args)
error("Missing command.");
printf_stdebug("%s\r", args);
expect_prompt(0);
}
/* Connect the user directly to STDBUG. This command acts just like the
'cu' or 'tip' command. Use <CR>~. or <CR>~^D to break out. */
static struct ttystate ttystate;
static void
cleanup_tty()
{
printf("\r\n[Exiting connect mode]\r\n");
serial_restore(0, &ttystate);
}
static void
connect_command (args, fromtty)
char *args;
int fromtty;
{
fd_set readfds;
int numfds;
int c;
char cur_esc = 0;
dont_repeat();
if (st2000_desc < 0)
error("st2000 target not open.");
if (args)
fprintf("This command takes no args. They have been ignored.\n");
printf("[Entering connect mode. Use ~. or ~^D to escape]\n");
serial_raw(0, &ttystate);
make_cleanup(cleanup_tty, 0);
FD_ZERO(&readfds);
while (1)
{
do
{
FD_SET(0, &readfds);
FD_SET(st2000_desc, &readfds);
numfds = select(sizeof(readfds)*8, &readfds, 0, 0, 0);
}
while (numfds == 0);
if (numfds < 0)
perror_with_name("select");
if (FD_ISSET(0, &readfds))
{ /* tty input, send to stdebug */
c = getchar();
if (c < 0)
perror_with_name("connect");
printf_stdebug("%c", c);
switch (cur_esc)
{
case 0:
if (c == '\r')
cur_esc = c;
break;
case '\r':
if (c == '~')
cur_esc = c;
else
cur_esc = 0;
break;
case '~':
if (c == '.' || c == '\004')
return;
else
cur_esc = 0;
}
}
if (FD_ISSET(st2000_desc, &readfds))
{
while (1)
{
c = readchar(0);
if (c < 0)
break;
putchar(c);
}
fflush(stdout);
}
}
}
/* Define the target subroutine names */ /* Define the target subroutine names */
static struct target_ops st2000_ops = { struct target_ops st2000_ops = {
"st2000", "Remote serial Tandem ST2000 target", "st2000",
"Remote serial Tandem ST2000 target",
"Use a remote computer running STDEBUG connected by a serial line,\n\ "Use a remote computer running STDEBUG connected by a serial line,\n\
or a network connection.\n\ or a network connection.\n\
Arguments are the name of the device for the serial line,\n\ Arguments are the name of the device for the serial line,\n\
the speed to connect at in bits per second.", the speed to connect at in bits per second.",
st2000_open, st2000_close, st2000_open,
0, st2000_detach, st2000_resume, st2000_wait, st2000_close,
st2000_fetch_register, st2000_store_register, 0,
st2000_prepare_to_store, 0, 0, /* conv_to, conv_from */ st2000_detach,
st2000_xfer_inferior_memory, st2000_files_info, st2000_resume,
st2000_insert_breakpoint, st2000_remove_breakpoint, /* Breakpoints */ st2000_wait,
0, 0, 0, 0, 0, /* Terminal handling */ st2000_fetch_register,
st2000_store_register,
st2000_prepare_to_store,
0,
0, /* conv_to, conv_from */
st2000_xfer_inferior_memory,
st2000_files_info,
st2000_insert_breakpoint,
st2000_remove_breakpoint, /* Breakpoints */
0,
0,
0,
0,
0, /* Terminal handling */
st2000_kill, st2000_kill,
0, /* load */ 0, /* load */
0, /* lookup_symbol */ 0, /* lookup_symbol */
st2000_create_inferior, st2000_create_inferior,
st2000_mourn_inferior, st2000_mourn_inferior,
process_stratum, 0, /* next */ process_stratum,
1, 1, 1, 1, 1, /* all mem, mem, stack, regs, exec */ 0, /* next */
0, 0, /* Section pointers */ 1,
1,
1,
1,
1, /* all mem, mem, stack, regs, exec */
0,
0, /* Section pointers */
OPS_MAGIC, /* Always the last thing */ OPS_MAGIC, /* Always the last thing */
}; };
@ -834,4 +812,9 @@ void
_initialize_remote_st2000 () _initialize_remote_st2000 ()
{ {
add_target (&st2000_ops); add_target (&st2000_ops);
add_com ("st2000 <command>", class_obscure, st2000_command,
"Send a command to the STDBUG monitor.");
add_com ("connect", class_obscure, connect_command,
"Connect the terminal directly up to the STDBUG command monitor.\n\
Use <CR>~. or <CR>~^D to break out.");
} }

228
gdb/ser-bsd.c Normal file
View File

@ -0,0 +1,228 @@
/* Remote serial interface for OS's with sgttyb
Copyright 1992 Free Software Foundation, Inc.
This file is part of GDB.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
#include "defs.h"
#include <sys/types.h>
#include <sys/time.h>
#include <fcntl.h>
#include "serial.h"
static int desc = -1;
void
serial_raw(fd, oldstate)
int fd;
struct ttystate *oldstate;
{
struct sgttyb sgttyb;
oldstate->flags = fcntl(fd, F_GETFL, 0);
fcntl(fd, F_SETFL, oldstate->flags|FNDELAY);
if (ioctl(fd, TIOCGETP, &sgttyb))
{
fprintf(stderr, "TIOCGETP failed: %s\n", safe_strerror(errno));
}
oldstate->sgttyb = sgttyb;
sgttyb.sg_flags = RAW;
if (ioctl(fd, TIOCSETP, &sgttyb))
{
fprintf(stderr, "TIOCSETP failed: %s\n", safe_strerror(errno));
}
}
void
serial_restore(fd, oldstate)
int fd;
struct ttystate *oldstate;
{
fcntl(fd, F_SETFL, oldstate->flags);
ioctl(fd, TIOCSETP, &oldstate->sgttyb);
}
static struct ttystate oldstate;
static fd_set readfds;
int
serial_open(name)
char *name;
{
struct sgttyb sgttyb;
desc = open (name, O_RDWR);
if (desc < 0)
error("Open of %s failed: %s", name, safe_strerror(errno));
serial_raw(desc, &oldstate);
/* Setup constant stuff for select */
FD_ZERO(&readfds);
return desc;
}
/* Read a character with user-specified timeout. TIMEOUT is number of seconds
to wait, or -1 to wait forever. Use timeout of 0 to effect a poll. Returns
char if successful. Returns -2 if timeout expired, EOF if line dropped
dead, or -3 for any other error (see errno in that case). */
int
serial_readchar(timeout)
int timeout;
{
static unsigned char buf[BUFSIZ];
static unsigned char *bufp;
static int bufcnt = 0;
int numfds;
struct timeval tv;
if (bufcnt-- > 0)
return *bufp++;
tv.tv_sec = timeout;
tv.tv_usec = 0;
FD_SET(desc, &readfds);
if (timeout >= 0)
numfds = select(desc+1, &readfds, 0, 0, &tv);
else
numfds = select(desc+1, &readfds, 0, 0, 0);
if (numfds <= 0)
if (numfds == 0)
return -2; /* Timeout */
else
return -3; /* Got an error from select */
bufcnt = read(desc, buf, BUFSIZ);
if (bufcnt <= 0)
if (bufcnt == 0)
return EOF; /* 0 chars means end of file */
else
return -3; /* Got an error from read */
bufcnt--;
bufp = buf;
return *bufp++;
}
#ifndef B19200
#define B19200 EXTA
#endif
#ifndef B38400
#define B38400 EXTB
#endif
/* Translate baud rates from integers to damn B_codes. Unix should
have outgrown this crap years ago, but even POSIX wouldn't buck it. */
static struct
{
int rate;
int code;
} baudtab[] = {
{50, B50},
{75, B75},
{110, B110},
{134, B134},
{150, B150},
{200, B200},
{300, B300},
{600, B600},
{1200, B1200},
{1800, B1800},
{2400, B2400},
{4800, B4800},
{9600, B9600},
{19200, B19200},
{38400, B38400},
{-1, -1},
};
static int
rate_to_code(rate)
int rate;
{
int i;
for (i = 0; baudtab[i].rate != -1; i++)
if (rate == baudtab[i].rate)
return baudtab[i].code;
return -1;
}
int
serial_setbaudrate(rate)
int rate;
{
struct sgttyb sgttyb;
if (ioctl(desc, TIOCGETP, &sgttyb))
error("TIOCGETP failed: %s\n", safe_strerror(errno));
sgttyb.sg_ospeed = rate_to_code(rate);
sgttyb.sg_ispeed = rate_to_code(rate);
if (ioctl(desc, TIOCSETP, &sgttyb))
error("TIOCSETP failed: %s\n", safe_strerror(errno));
return 1;
}
int
serial_write(str, len)
char *str;
int len;
{
int cc;
while (len > 0)
{
cc = write(desc, str, len);
if (cc < 0)
return 0;
len -= cc;
str += cc;
}
return 1;
}
void
serial_close()
{
if (desc < 0)
return;
serial_restore(desc, oldstate);
close(desc);
desc = -1;
}

View File

@ -18,60 +18,29 @@ along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
#include "defs.h" #include "defs.h"
#include "serial.h"
#include <fcntl.h> #include <fcntl.h>
#include <termios.h>
#include <sys/time.h> #include <sys/time.h>
#include "serial.h"
/* File descriptor used in termios routines to access serial line. */ static int desc = -1;
static int desc;
/* Saved state about the terminal. */
static struct termios otermios;
static int oflags;
const char *
serial_default_name ()
{
return "/dev/ttya";
}
void void
serial_raw () serial_raw(fd, oldstate)
{ int fd;
/* Now happens inside of serial_open */ struct ttystate *oldstate;
}
void
serial_normal ()
{
fcntl(desc, oflags, 0);
if (tcsetattr(desc, TCSANOW, &otermios))
{
printf("tcgetattr failed: errno=%d\n", errno);
}
}
int
serial_open (name)
const char *name;
{ {
struct termios termios; struct termios termios;
desc = open (name, O_RDWR); oldstate->flags = fcntl(fd, F_GETFL, 0);
if (desc < 0)
perror("Open failed: ");
oflags = fcntl(desc, F_GETFL, 0); fcntl(fd, F_SETFL, oldstate->flags|FNDELAY);
fcntl(desc, F_SETFL, oflags|FNDELAY); if (tcgetattr(fd, &termios))
{
if (tcgetattr(desc, &termios)) { fprintf(stderr, "tcgetattr failed: %s\n", safe_strerror(errno));
printf("tcgetattr failed: errno=%d\n", errno);
} }
otermios = termios; oldstate->termios = termios;
termios.c_iflag = 0; termios.c_iflag = 0;
termios.c_oflag = 0; termios.c_oflag = 0;
@ -79,83 +48,128 @@ serial_open (name)
termios.c_cc[VMIN] = 0; termios.c_cc[VMIN] = 0;
termios.c_cc[VTIME] = 0; termios.c_cc[VTIME] = 0;
if (tcsetattr(desc, TCSANOW, &termios)) { if (tcsetattr(fd, TCSANOW, &termios))
printf("tcgetattr failed: errno=%d\n", errno); {
fprintf(stderr, "tcsetattr failed: %s\n", safe_strerror(errno));
}
} }
return 1; void
serial_restore(fd, oldstate)
int fd;
struct ttystate *oldstate;
{
fcntl(fd, F_SETFL, oldstate->flags);
tcsetattr(fd, TCSANOW, &oldstate->termios);
} }
static struct ttystate oldstate;
static fd_set readfds;
int int
serial_timedreadchar (timeout, ok) serial_open(name)
int timeout; char *name;
int *ok;
{ {
unsigned char buf; struct termios termios;
fd_set readfds;
int val; desc = open (name, O_RDWR);
struct timeval tv; if (desc < 0)
error("Open of %s failed: %s", name, safe_strerror(errno));
serial_raw(desc, &oldstate);
/* Setup constant stuff for select */
FD_ZERO(&readfds); FD_ZERO(&readfds);
FD_SET(desc, &readfds);
return desc;
}
/* Read a character with user-specified timeout. TIMEOUT is number of seconds
to wait, or -1 to wait forever. Use timeout of 0 to effect a poll. Returns
char if successful. Returns -2 if timeout expired, EOF if line dropped
dead, or -3 for any other error (see errno in that case). */
int
serial_readchar(timeout)
int timeout;
{
static unsigned char buf[BUFSIZ];
static unsigned char *bufp;
static int bufcnt = 0;
int numfds;
struct timeval tv;
if (bufcnt-- > 0)
return *bufp++;
tv.tv_sec = timeout; tv.tv_sec = timeout;
tv.tv_usec = 0; tv.tv_usec = 0;
val = select(desc+1, &readfds, 0, 0, &tv); FD_SET(desc, &readfds);
if (val > 0 && FD_ISSET(desc, &readfds)) if (timeout >= 0)
{ numfds = select(desc+1, &readfds, 0, 0, &tv);
val = read (desc, &buf, 1); else
numfds = select(desc+1, &readfds, 0, 0, 0);
if (val == 1) if (numfds <= 0)
{ if (numfds == 0)
*ok = 1; return -2; /* Timeout */
return buf; else
} return -3; /* Got an error from select */
}
*ok = 0; bufcnt = read(desc, buf, BUFSIZ);
return 0; if (bufcnt <= 0)
if (bufcnt == 0)
return EOF; /* 0 chars means end of file */
else
return -3; /* Got an error from read */
bufcnt--;
bufp = buf;
return *bufp++;
} }
/* Translate baud rates from integers to damn B_codes. Unix should /* Translate baud rates from integers to damn B_codes. Unix should
have outgrown this crap years ago, but even POSIX wouldn't buck it. */ have outgrown this crap years ago, but even POSIX wouldn't buck it. */
#ifndef B19200 static struct
#define B19200 EXTA {
#endif int rate;
#ifndef B38400 int code;
#define B38400 EXTB } baudtab[] = {
#endif {50, B50},
{75, B75},
static struct {int rate, damn_b;} baudtab[] = { {110, B110},
{9600, B9600}, {134, B134},
{150, B150},
{19200, B19200}, {200, B200},
{38400, B38400},
#if 0
{300, B300}, {300, B300},
{600, B600},
{1200, B1200}, {1200, B1200},
{1800, B1800},
{2400, B2400}, {2400, B2400},
{4800, B4800}, {4800, B4800},
#endif {9600, B9600},
{19200, B19200},
{38400, B38400},
{-1, -1}, {-1, -1},
}; };
static int static int
damn_b (rate) rate_to_code(rate)
int rate; int rate;
{ {
int i; int i;
for (i = 0; baudtab[i].rate != -1; i++) for (i = 0; baudtab[i].rate != -1; i++)
{
if (rate == baudtab[i].rate) if (rate == baudtab[i].rate)
{ return baudtab[i].code;
return i;
}
}
return -1; return -1;
} }
@ -165,45 +179,45 @@ serial_setbaudrate (rate)
{ {
struct termios termios; struct termios termios;
if (tcgetattr(desc, &termios)) { if (tcgetattr(desc, &termios))
printf("tcgetattr failed: errno=%d\n", errno); error("tcgetattr failed: %s\n", safe_strerror(errno));
}
cfsetospeed(&termios, baudtab[damn_b(rate)].damn_b); cfsetospeed(&termios, rate_to_code(rate));
cfsetispeed(&termios, baudtab[damn_b(rate)].damn_b); cfsetispeed(&termios, rate_to_code(rate));
if (tcsetattr(desc, TCSANOW, &termios)) { if (tcsetattr(desc, TCSANOW, &termios))
printf("tcgetattr failed: errno=%d\n", errno); error("tcsetattr failed: %s\n", safe_strerror(errno));
}
return 1; return 1;
} }
int
serial_nextbaudrate (rate)
int rate;
{
int lookup;
lookup = damn_b(rate);
if (lookup == -1)
return baudtab[0].rate;
lookup++;
if (baudtab[lookup].rate == -1)
return baudtab[0].rate;
return baudtab[lookup].rate;
}
int int
serial_write(str, len) serial_write(str, len)
const char *str; char *str;
int len; int len;
{ {
return (write (desc, str, len)); int cc;
while (len > 0)
{
cc = write(desc, str, len);
if (cc < 0)
return 0;
len -= cc;
str += cc;
}
return 1;
} }
void
int
serial_close() serial_close()
{ {
return (close(desc)); if (desc < 0)
return;
serial_restore(desc, oldstate);
close(desc);
desc = -1;
} }

View File

@ -42,16 +42,37 @@ int serial_timedreadchar PARAMS ((int to, int *ok));
/* Set the baudrate to the decimal value supplied, and return 1, or fail and /* Set the baudrate to the decimal value supplied, and return 1, or fail and
return 0. */ return 0. */
int serial_setbaudrate PARAMS ((int to)); int serial_setbaudrate PARAMS ((int rate));
/* Return the next rate in the sequence, or return 0 for failure. */ /* Return the next rate in the sequence, or return 0 for failure. */
int serial_nextbaudrate PARAMS ((int rate)); /* Write some chars to the device, returns 0 for failure. See errno for
details. */
/* Write some chars to the device, return 1 if ok, 0 if not. */
int serial_write PARAMS ((const char *str , int len)); int serial_write PARAMS ((const char *str , int len));
/* Close the serial port. */ /* Close the serial port */
int serial_close PARAMS ((void)); void serial_close PARAMS ((void));
#ifdef HAVE_TERMIO
#include <termios.h>
#include <unistd.h>
struct ttystate
{
int flags; /* Flags from fcntl F_GETFL */
struct termios termios; /* old tty driver settings */
};
#else /* not HAVE_TERMIO */
#include <sgtty.h>
struct ttystate {
int flags; /* Flags from fcntl F_GETFL */
struct sgttyb sgttyb; /* old tty driver settings */
};
#endif /* not HAVE_TERMIO */

View File

@ -22,3 +22,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
#define ALIGN_STACK_ON_STARTUP #define ALIGN_STACK_ON_STARTUP
#define FETCH_INFERIOR_REGISTERS #define FETCH_INFERIOR_REGISTERS
#define PTRACE_IN_WRONG_PLACE
extern char *strdup();