Setting parity for remote serial

Message ID CAAyhtXSsfZss0UqLTjG0sWN-T0k-XLkKLtvz-ea-QaAbrZFCEw@mail.gmail.com
State New, archived
Headers

Commit Message

Yurij Grechishhev March 15, 2015, 9:49 p.m. UTC
  Hello Joel,
I kindly ask you to review this patch. Please, let me know in the case
I have missed something.
I see, you've reworked the command for baudrate setting.
Parity is set the same way now: set/show serial parity.

Thank you.


--
WBR,
Yury

2015-02-27 11:16 GMT+03:00 Joel Brobecker <brobecker@adacore.com>:
>> Glad to hear that this patch is still needed.
>> I believe, all questions with FSF copyright assignments had been resolved?
>> Please, let me know what I should do to complete this contribution.
>
> Indeed! Thanks very much for doing that.
>
> If you could rebase the patch against master, and resubmit,
> I promise to review it promptly (I will taking a week off
> Mar 07-15, though). If you'd rather I took it over, I will
> try to do so after I come back.
>
> Thanks again!
> --
> Joel
  

Comments

Eli Zaretskii March 16, 2015, 3:32 a.m. UTC | #1
> Date: Mon, 16 Mar 2015 00:49:33 +0300
> From: Yurij Grechishhev <yurij.grechishhev@gmail.com>
> Cc: gdb-patches@sourceware.org
> 
> I kindly ask you to review this patch. Please, let me know in the case
> I have missed something.
> I see, you've reworked the command for baudrate setting.
> Parity is set the same way now: set/show serial parity.

Thanks, the documentation parts are OK.
  
Joel Brobecker March 17, 2015, 2:56 p.m. UTC | #2
Yurij,

Below are my commends regarding your patch.

You'll see that I have a lot of comments, but they are very minor and
the patch essentially looks fine to me. Please forgive me if it feels
like I am nitpicking - GDB has a fairly complex coding style, which
is mostly dictated by the fact that it is part of the GNU project and
therefore following the GNU Coding Style (and then some).

Also, it would be useful for you to confirm that this patch is on top
of master, and on which platform you tested this patch (I assume that
you tested it by running the testsuite before and after your change).

Thank you!

> +2013-07-16  Yurij Grechishhev  <yurij.grechishhev@gmail.com>
> +
> +    * NEWS: Mention set/show serial parity command.
> +    * monitor.c (monitor_open): Add serial_setparity.

"Add" was a little confusing to me. How about "Call serial_setparity"?

> +    * remote.c (remote_open_1): Likewise.
> +    * ser-base.c (ser_base_serparity): New function.
> +    * ser-base.h: Add ser_base_setparity declaration.

        * ser-base.h (ser_base_setparity): Add declaration.

> +    * serail.c: Add serial_parity declaration and definitions of
> +    parity_enums and parity.
> +    (serial_parity): Definition
> +    (set_parity): New function.
> +    (serial_setparity): New function.
> +    (_initialize_serial): Add set/show serial parity command description

typo: "serail.c" -> "serial.c"

Same remark as above in terms of how the entry should be formatted.
It also seems like the contents is a bit out of order with respect
to the diff, making it hard to double-check it. I suggest:

        * serial.c (serial_parity): New function.
        (serial_parity): New global.
        (parity_none, parity_odd, parity_even, parity_enums, parity):
        New static globals.
        (set_parity): New function.
        (_initialize_serial): Add set/show serial parity commands.

Also, the last comment on the ChangeLog entry is that sentences should
start with a capital letter, and end with a period.

Can you adjust the rest of the ChangeLog entry using the above
guidelines, please?

> +    * serial.h: Add GDBPARITY_NONE, GDBPARITY_ODD, GDBPARITY_EVEN
> +    definitions. Add serial_setparity declaration.
> +    (serial_ops): Add setparity entry.
> +    * ser-mingw.c (ser_windows_raw): Remove state.fParity and
> +    state.Parity definitions.
> +    (ser_windows_setparity): New function.
> +    (hardwire_ops): add ser_windows_setparity.
> +    (tty_ops): add NULL for setparity field
> +    (pipe_ops): add ser_base_setparity.
> +    (tcp_ops): add ser_base_setparity.
> +    * ser-pipe.c (pipe_ops): Likewise.
> +    * ser-tcp.c (tcp_ops): Likewise.
> +    * ser-unix.c: Add hardwire_setparity declaration.
> +    (hardwire_setparity): New function.
> +    (hardwire_ops): add hardwire_setparity.
> +    * ser-go32.c (dos_ops): add dos_noop
> +    * target.h: serial_parity declaration.

> diff --git a/gdb/monitor.c b/gdb/monitor.c
> index b040ec4..548dae3 100644
> --- a/gdb/monitor.c
> +++ b/gdb/monitor.c
> @@ -767,6 +767,7 @@ monitor_open (const char *args, struct monitor_ops
> *mon_ops, int from_tty)
>      }
>      }
> 
> +  serial_setparity (monitor_desc, serial_parity);
>    serial_raw (monitor_desc);
> 
>    serial_flush_input (monitor_desc);
> diff --git a/gdb/remote.c b/gdb/remote.c
> index 9aaee13..1554259 100644
> --- a/gdb/remote.c
> +++ b/gdb/remote.c
> @@ -4310,6 +4310,7 @@ remote_open_1 (const char *name, int from_tty,
>      }
>      }
> 
> +  serial_setparity(rs->remote_desc, serial_parity);

Missing space before the '('.

>    serial_raw (rs->remote_desc);
> 
>    /* If there is something sitting in the buffer we might take it as a
> diff --git a/gdb/ser-base.c b/gdb/ser-base.c
> index 87817c4..93aad40 100644
> --- a/gdb/ser-base.c
> +++ b/gdb/ser-base.c
> @@ -541,6 +541,12 @@ ser_base_setstopbits (struct serial *scb, int num)
>    return 0;            /* Never fails!  */
>  }
> 
> +int
> +ser_base_setparity (struct serial *scb, int parity)

We have a policy, now, that all new functions should be documented.
For functions like these, that simply implement a callback, a one-line
introductory comment is sufficient. For instance:

/* Implement the "setparity" serial_ops callback.  */

That's sufficient to show that the function's documentation is the same
as the callback's documentation.

>  extern int ser_base_setbaudrate (struct serial *scb, int rate);
> -extern int ser_base_setstopbits (struct serial *scb, int rate);
> +extern int ser_base_setstopbits (struct serial *scb, int num);

This change is unrelated, and obvious, so I pushed it on its own:
https://www.sourceware.org/ml/gdb-patches/2015-03/msg00488.html

> diff --git a/gdb/ser-mingw.c b/gdb/ser-mingw.c
> index 7f335e9..be0f990 100644
> --- a/gdb/ser-mingw.c
> +++ b/gdb/ser-mingw.c
> @@ -153,7 +153,6 @@ ser_windows_raw (struct serial *scb)
>    if (GetCommState (h, &state) == 0)
>      return;
> 
> -  state.fParity = FALSE;
>    state.fOutxCtsFlow = FALSE;
>    state.fOutxDsrFlow = FALSE;
>    state.fDtrControl = DTR_CONTROL_ENABLE;
> @@ -163,7 +162,6 @@ ser_windows_raw (struct serial *scb)
>    state.fNull = FALSE;
>    state.fAbortOnError = FALSE;
>    state.ByteSize = 8;
> -  state.Parity = NOPARITY;
> 
>    scb->current_timeout = 0;
> 
> @@ -199,6 +197,36 @@ ser_windows_setstopbits (struct serial *scb, int num)
>  }
> 
>  static int
> +ser_windows_setparity (struct serial *scb, int parity)

Same as above - missing function introductory comment.

> +{
> +  HANDLE h = (HANDLE) _get_osfhandle (scb->fd);
> +  DCB state;
> +
> +  if (GetCommState (h, &state) == 0)
> +    return -1;
> +
> +  switch (parity)
> +    {
> +    case GDBPARITY_NONE:
> +      state.Parity = NOPARITY;
> +      state.fParity = FALSE;
> +      break;
> +    case GDBPARITY_ODD:
> +      state.Parity = ODDPARITY;
> +      state.fParity = TRUE;
> +      break;
> +    case GDBPARITY_EVEN:
> +      state.Parity = EVENPARITY;
> +      state.fParity = TRUE;
> +      break;
> +    default:
> +      return 1;

Let's emit an internal_warning if parity has an unknown value.
PARITY should always be one of those 3, and getting anything else
is an internal_error. But the reason why I suggested the use of
an internal_warning instead of internal_error is that internal_error
is pretty-much a fatal error, but maybe we don't absolutely need it
to be fatal. Communication is probably going to be screwed up, but
anything else should still be working. We just want to warn the user
of the issue he's likely going to face.

> +    }
> +static int
> +hardwire_setparity (struct serial *scb, int parity)
> +{

Missing function documentation.

> +  struct hardwire_ttystate state;
> +  int newparity = 0;
> +
> +  if (get_tty_state (scb, &state))
> +    return -1;
> +
> +  switch (parity)
> +    {
> +    case GDBPARITY_NONE:
> +      newparity = 0;
> +      break;
> +    case GDBPARITY_ODD:
> +      newparity = PARENB | PARODD;
> +      break;
> +    case GDBPARITY_EVEN:
> +      newparity = PARENB;
> +      break;
> +    default:
> +      return 1;

Same here - internal_warning to warn the user of likely communication
issues.

> --- a/gdb/serial.c
> +++ b/gdb/serial.c
> @@ -525,6 +525,12 @@ serial_setstopbits (struct serial *scb, int num)
>  }
> 
>  int
> +serial_setparity (struct serial*scb, int parity)
> +{
> +    return scb->ops->setparity (scb, parity);
> +}

Missing function documentation.

> +/* Parity for serial port */
> +int serial_parity = GDBPARITY_NONE;
> +
> +static const char parity_none[] = "none";
> +static const char parity_odd[] = "odd";
> +static const char parity_even[] = "even";
> +static const char *const parity_enums[] =
> +{parity_none, parity_odd, parity_even,  NULL};

Two spaces before '{' (indentation).

> +static const char *parity = parity_none;

> +static void
> +set_parity (char *ignore_args, int from_tty, struct cmd_list_element *c)

When the function's documentation is in the .h file, can you add a
comment that says, Eg:

/* See serial.h.  */

?

> +/* Set parity for serial port. Return 0 for success, -1 for failure */
> +
> +#define GDBPARITY_NONE     0
> +#define GDBPARITY_ODD      1
> +#define GDBPARITY_EVEN     2
> +
> +extern int serial_setparity (struct serial *scb, int parity);

Can you move the function's documentation after the #define's?

>  /* Can the serial device support asynchronous mode?  */
> @@ -271,6 +279,7 @@ struct serial_ops
>                    serial_ttystate);
>      int (*setbaudrate) (struct serial *, int rate);
>      int (*setstopbits) (struct serial *, int num);
> +    int (*setparity) (struct serial *, int parity);

Please document here what this hook should be doing. Please name
all the arguments as well, so you can use those names in the hook's
description. Below is an example from target.h which shows how
these kinds of "methods" are now documented in GDB:

    /* Return the thread-local address at OFFSET in the
       thread-local storage for the thread PTID and the shared library
       or executable file given by OBJFILE.  If that block of
       thread-local storage hasn't been allocated yet, this function
       may return an error.  LOAD_MODULE_ADDR may be zero for statically
       linked multithreaded inferiors.  */
    CORE_ADDR (*to_get_thread_local_address) (struct target_ops *ops,
                                              ptid_t ptid,
                                              CORE_ADDR load_module_addr,
                                              CORE_ADDR offset)


> index c95e1a4..685a37f 100644
> --- a/gdb/target.h
> +++ b/gdb/target.h
> @@ -2236,6 +2236,10 @@ extern int remote_debug;
> 
>  /* Speed in bits per second, or -1 which means don't mess with the speed.  */
>  extern int baud_rate;
> +
> +/* Parity for serial port */
> +extern int serial_parity;

For the global's documentation, can you add a period followed by
two spaces? Thus:

/* Parity for serial port. */
  

Patch

diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index 65a0051..7b88708 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,3 +1,34 @@ 
+2013-07-16  Yurij Grechishhev  <yurij.grechishhev@gmail.com>
+
+	* NEWS: Mention set/show serial parity command.
+	* monitor.c (monitor_open): Add serial_setparity.
+	* remote.c (remote_open_1): Likewise.
+	* ser-base.c (ser_base_serparity): New function.
+	* ser-base.h: Add ser_base_setparity declaration.
+	* serail.c: Add serial_parity declaration and definitions of
+	parity_enums and parity.
+	(serial_parity): Definition
+	(set_parity): New function.
+	(serial_setparity): New function.
+	(_initialize_serial): Add set/show serial parity command description
+	* serial.h: Add GDBPARITY_NONE, GDBPARITY_ODD, GDBPARITY_EVEN
+	definitions. Add serial_setparity declaration.
+	(serial_ops): Add setparity entry.
+	* ser-mingw.c (ser_windows_raw): Remove state.fParity and
+	state.Parity definitions.
+	(ser_windows_setparity): New function.
+	(hardwire_ops): add ser_windows_setparity.
+	(tty_ops): add NULL for setparity field
+	(pipe_ops): add ser_base_setparity.
+	(tcp_ops): add ser_base_setparity.
+	* ser-pipe.c (pipe_ops): Likewise.
+	* ser-tcp.c (tcp_ops): Likewise.
+	* ser-unix.c: Add hardwire_setparity declaration.
+	(hardwire_setparity): New function.
+	(hardwire_ops): add hardwire_setparity.
+	* ser-go32.c (dos_ops): add dos_noop
+	* target.h: serial_parity declaration.
+
 2014-10-16  Jan Kratochvil  <jan.kratochvil@redhat.com>
 
 	Remove HPUX.
diff --git a/gdb/NEWS b/gdb/NEWS
index f08f972..cd2e82b3 100644
--- a/gdb/NEWS
+++ b/gdb/NEWS
@@ -3,6 +3,10 @@ 
 
 *** Changes since GDB 7.9
 
+* GDB has two new commands: "set serial parity odd|even|none" and
+  "show serial parity".  These allows to set or show parity for the
+  remote serial I/O.
+
 * The "info source" command now displays the producer string if it was
   present in the debug info.  This typically includes the compiler version
   and may include things like its command line arguments.
diff --git a/gdb/doc/ChangeLog b/gdb/doc/ChangeLog
index 5efb060..dd601fe 100644
--- a/gdb/doc/ChangeLog
+++ b/gdb/doc/ChangeLog
@@ -1,3 +1,8 @@ 
+2015-03-16  Yurij Grechishhev  <yurij.grechishhev@gmail.com>
+
+	* gdb.texinfo (Remote configuration): Document "set/show
+	serial parity command".
+
 2015-03-11  Gary Benson <gbenson@redhat.com>
 
 	* gdb.texinfo (Remote Configuration): Document the
diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
index 9e71642..a818d58 100644
--- a/gdb/doc/gdb.texinfo
+++ b/gdb/doc/gdb.texinfo
@@ -19443,6 +19443,13 @@  remote targets.
 @item show serial baud
 Show the current speed of the remote connection.
 
+@item set serial parity @var{parity}
+Set the parity for the remote serial I/O.  Supported values of @var{parity} are:
+@code{even}, @code{none}, and @code{odd}.  The default is @code{none}.
+
+@item show serial parity
+Show the current parity of the serial port.
+
 @item set remotebreak
 @cindex interrupt remote programs
 @cindex BREAK signal instead of Ctrl-C
diff --git a/gdb/monitor.c b/gdb/monitor.c
index b040ec4..548dae3 100644
--- a/gdb/monitor.c
+++ b/gdb/monitor.c
@@ -767,6 +767,7 @@  monitor_open (const char *args, struct monitor_ops *mon_ops, int from_tty)
 	}
     }
 
+  serial_setparity (monitor_desc, serial_parity);
   serial_raw (monitor_desc);
 
   serial_flush_input (monitor_desc);
diff --git a/gdb/remote.c b/gdb/remote.c
index 9aaee13..1554259 100644
--- a/gdb/remote.c
+++ b/gdb/remote.c
@@ -4310,6 +4310,7 @@  remote_open_1 (const char *name, int from_tty,
 	}
     }
 
+  serial_setparity(rs->remote_desc, serial_parity);
   serial_raw (rs->remote_desc);
 
   /* If there is something sitting in the buffer we might take it as a
diff --git a/gdb/ser-base.c b/gdb/ser-base.c
index 87817c4..93aad40 100644
--- a/gdb/ser-base.c
+++ b/gdb/ser-base.c
@@ -541,6 +541,12 @@  ser_base_setstopbits (struct serial *scb, int num)
   return 0;			/* Never fails!  */
 }
 
+int
+ser_base_setparity (struct serial *scb, int parity)
+{
+  return 0;			/* Never fails!  */
+}
+
 /* Put the SERIAL device into/out-of ASYNC mode.  */
 
 void
diff --git a/gdb/ser-base.h b/gdb/ser-base.h
index 2aba66d..bb1c51d 100644
--- a/gdb/ser-base.h
+++ b/gdb/ser-base.h
@@ -42,7 +42,8 @@  extern int ser_base_noflush_set_tty_state (struct serial *scb,
 					   serial_ttystate new_ttystate,
 					   serial_ttystate old_ttystate);
 extern int ser_base_setbaudrate (struct serial *scb, int rate);
-extern int ser_base_setstopbits (struct serial *scb, int rate);
+extern int ser_base_setstopbits (struct serial *scb, int num);
+extern int ser_base_setparity (struct serial *scb, int parity);
 extern int ser_base_drain_output (struct serial *scb);
 
 extern int ser_base_write (struct serial *scb, const void *buf, size_t count);
diff --git a/gdb/ser-go32.c b/gdb/ser-go32.c
index 6bf1b4e..bbcf6af 100644
--- a/gdb/ser-go32.c
+++ b/gdb/ser-go32.c
@@ -864,6 +864,7 @@  static const struct serial_ops dos_ops =
   dos_noflush_set_tty_state,
   dos_setbaudrate,
   dos_setstopbits,
+  dos_noop,
   dos_noop,			/* Wait for output to drain.  */
   (void (*)(struct serial *, int))NULL	/* Change into async mode.  */
 };
diff --git a/gdb/ser-mingw.c b/gdb/ser-mingw.c
index 7f335e9..be0f990 100644
--- a/gdb/ser-mingw.c
+++ b/gdb/ser-mingw.c
@@ -153,7 +153,6 @@  ser_windows_raw (struct serial *scb)
   if (GetCommState (h, &state) == 0)
     return;
 
-  state.fParity = FALSE;
   state.fOutxCtsFlow = FALSE;
   state.fOutxDsrFlow = FALSE;
   state.fDtrControl = DTR_CONTROL_ENABLE;
@@ -163,7 +162,6 @@  ser_windows_raw (struct serial *scb)
   state.fNull = FALSE;
   state.fAbortOnError = FALSE;
   state.ByteSize = 8;
-  state.Parity = NOPARITY;
 
   scb->current_timeout = 0;
 
@@ -199,6 +197,36 @@  ser_windows_setstopbits (struct serial *scb, int num)
 }
 
 static int
+ser_windows_setparity (struct serial *scb, int parity)
+{
+  HANDLE h = (HANDLE) _get_osfhandle (scb->fd);
+  DCB state;
+
+  if (GetCommState (h, &state) == 0)
+    return -1;
+
+  switch (parity)
+    {
+    case GDBPARITY_NONE:
+      state.Parity = NOPARITY;
+      state.fParity = FALSE;
+      break;
+    case GDBPARITY_ODD:
+      state.Parity = ODDPARITY;
+      state.fParity = TRUE;
+      break;
+    case GDBPARITY_EVEN:
+      state.Parity = EVENPARITY;
+      state.fParity = TRUE;
+      break;
+    default:
+      return 1;
+    }
+
+  return (SetCommState (h, &state) != 0) ? 0 : -1;
+}
+
+static int
 ser_windows_setbaudrate (struct serial *scb, int rate)
 {
   HANDLE h = (HANDLE) _get_osfhandle (scb->fd);
@@ -1227,6 +1255,7 @@  static const struct serial_ops hardwire_ops =
   ser_base_noflush_set_tty_state,
   ser_windows_setbaudrate,
   ser_windows_setstopbits,
+  ser_windows_setparity,
   ser_windows_drain_output,
   ser_base_async,
   ser_windows_read_prim,
@@ -1257,6 +1286,7 @@  static const struct serial_ops tty_ops =
   ser_base_noflush_set_tty_state,
   NULL,
   NULL,
+  NULL,
   ser_base_drain_output,
   NULL,
   NULL,
@@ -1287,6 +1317,7 @@  static const struct serial_ops pipe_ops =
   ser_base_noflush_set_tty_state,
   ser_base_setbaudrate,
   ser_base_setstopbits,
+  ser_base_setparity,
   ser_base_drain_output,
   ser_base_async,
   pipe_windows_read,
@@ -1317,6 +1348,7 @@  static const struct serial_ops tcp_ops =
   ser_base_noflush_set_tty_state,
   ser_base_setbaudrate,
   ser_base_setstopbits,
+  ser_base_setparity,
   ser_base_drain_output,
   ser_base_async,
   net_read_prim,
diff --git a/gdb/ser-pipe.c b/gdb/ser-pipe.c
index bf5e4d4..0700132 100644
--- a/gdb/ser-pipe.c
+++ b/gdb/ser-pipe.c
@@ -224,6 +224,7 @@  static const struct serial_ops pipe_ops =
   ser_base_noflush_set_tty_state,
   ser_base_setbaudrate,
   ser_base_setstopbits,
+  ser_base_setparity,
   ser_base_drain_output,
   ser_base_async,
   ser_unix_read_prim,
diff --git a/gdb/ser-tcp.c b/gdb/ser-tcp.c
index 9c3dcf4..35512e6 100644
--- a/gdb/ser-tcp.c
+++ b/gdb/ser-tcp.c
@@ -394,6 +394,7 @@  static const struct serial_ops tcp_ops =
   ser_base_noflush_set_tty_state,
   ser_base_setbaudrate,
   ser_base_setstopbits,
+  ser_base_setparity,
   ser_base_drain_output,
   ser_base_async,
   net_read_prim,
diff --git a/gdb/ser-unix.c b/gdb/ser-unix.c
index 4125797..88c16ba 100644
--- a/gdb/ser-unix.c
+++ b/gdb/ser-unix.c
@@ -83,6 +83,7 @@  static int hardwire_readchar (struct serial *scb, int timeout);
 static int do_hardwire_readchar (struct serial *scb, int timeout);
 static int rate_to_code (int rate);
 static int hardwire_setbaudrate (struct serial *scb, int rate);
+static int hardwire_setparity (struct serial *scb, int parity);
 static void hardwire_close (struct serial *scb);
 static int get_tty_state (struct serial *scb,
 			  struct hardwire_ttystate * state);
@@ -893,6 +894,46 @@  hardwire_setstopbits (struct serial *scb, int num)
   return set_tty_state (scb, &state);
 }
 
+static int
+hardwire_setparity (struct serial *scb, int parity)
+{
+  struct hardwire_ttystate state;
+  int newparity = 0;
+
+  if (get_tty_state (scb, &state))
+    return -1;
+
+  switch (parity)
+    {
+    case GDBPARITY_NONE:
+      newparity = 0;
+      break;
+    case GDBPARITY_ODD:
+      newparity = PARENB | PARODD;
+      break;
+    case GDBPARITY_EVEN:
+      newparity = PARENB;
+      break;
+    default:
+      return 1;
+    }
+
+#ifdef HAVE_TERMIOS
+  state.termios.c_cflag |= newparity;
+#endif
+
+#ifdef HAVE_TERMIO
+  state.termio.c_cflag |= newparity;
+#endif
+
+#ifdef HAVE_SGTTY
+  return 0;            /* sgtty doesn't support this */
+#endif
+
+  return set_tty_state (scb, &state);
+}
+
+
 static void
 hardwire_close (struct serial *scb)
 {
@@ -929,6 +970,7 @@  static const struct serial_ops hardwire_ops =
   hardwire_noflush_set_tty_state,
   hardwire_setbaudrate,
   hardwire_setstopbits,
+  hardwire_setparity,
   hardwire_drain_output,
   ser_base_async,
   ser_unix_read_prim,
diff --git a/gdb/serial.c b/gdb/serial.c
index b7e620d..09c8b8d 100644
--- a/gdb/serial.c
+++ b/gdb/serial.c
@@ -525,6 +525,12 @@  serial_setstopbits (struct serial *scb, int num)
 }
 
 int
+serial_setparity (struct serial*scb, int parity)
+{
+    return scb->ops->setparity (scb, parity);
+}
+
+int
 serial_can_async_p (struct serial *scb)
 {
   return (scb->ops->async != NULL);
@@ -638,6 +644,27 @@  serial_baud_show_cmd (struct ui_file *file, int from_tty,
 		    value);
 }
 
+/* Parity for serial port */
+int serial_parity = GDBPARITY_NONE;
+
+static const char parity_none[] = "none";
+static const char parity_odd[] = "odd";
+static const char parity_even[] = "even";
+static const char *const parity_enums[] =
+{parity_none, parity_odd, parity_even,  NULL};
+static const char *parity = parity_none;
+
+static void
+set_parity (char *ignore_args, int from_tty, struct cmd_list_element *c)
+{
+  if (parity == parity_odd)
+    serial_parity = GDBPARITY_ODD;
+  else if (parity == parity_even)
+    serial_parity = GDBPARITY_EVEN;
+  else
+    serial_parity = GDBPARITY_NONE;
+}
+
 void
 _initialize_serial (void)
 {
@@ -670,6 +697,14 @@  using remote targets."),
 			    serial_baud_show_cmd,
 			    &serial_set_cmdlist, &serial_show_cmdlist);
 
+  add_setshow_enum_cmd ("parity", no_class, parity_enums,
+                        &parity, _("\
+Set parity for remote serial I/O"), _("\
+Show parity for remote serial I/O"), NULL,
+                        set_parity,
+                        NULL, /* FIXME: i18n: */
+                        &serial_set_cmdlist, &serial_show_cmdlist);
+
   add_setshow_filename_cmd ("remotelogfile", no_class, &serial_logfile, _("\
 Set filename for remote session recording."), _("\
 Show filename for remote session recording."), _("\
diff --git a/gdb/serial.h b/gdb/serial.h
index 9eb1c39..0481ea1 100644
--- a/gdb/serial.h
+++ b/gdb/serial.h
@@ -186,6 +186,14 @@  extern int serial_setbaudrate (struct serial *scb, int rate);
 
 extern int serial_setstopbits (struct serial *scb, int num);
 
+/* Set parity for serial port. Return 0 for success, -1 for failure */
+
+#define GDBPARITY_NONE     0
+#define GDBPARITY_ODD      1
+#define GDBPARITY_EVEN     2
+
+extern int serial_setparity (struct serial *scb, int parity);
+
 /* Asynchronous serial interface: */
 
 /* Can the serial device support asynchronous mode?  */
@@ -271,6 +279,7 @@  struct serial_ops
 				  serial_ttystate);
     int (*setbaudrate) (struct serial *, int rate);
     int (*setstopbits) (struct serial *, int num);
+    int (*setparity) (struct serial *, int parity);
     /* Wait for output to drain.  */
     int (*drain_output) (struct serial *);
     /* Change the serial device into/out of asynchronous mode, call
diff --git a/gdb/target.h b/gdb/target.h
index c95e1a4..685a37f 100644
--- a/gdb/target.h
+++ b/gdb/target.h
@@ -2236,6 +2236,10 @@  extern int remote_debug;
 
 /* Speed in bits per second, or -1 which means don't mess with the speed.  */
 extern int baud_rate;
+
+/* Parity for serial port */
+extern int serial_parity;
+
 /* Timeout limit for response from target.  */
 extern int remote_timeout;