diff mbox

Setting parity for remote serial

Message ID CAAyhtXQUqokKS8CvqwK063DmzG1=OY2KJxg25fZWUDH4_3tK3Q@mail.gmail.com
State New
Headers show

Commit Message

Yurij Grechishhev March 22, 2015, 10:52 p.m. UTC
Hi Joel,
It's really useful experience to follow so strict coding style. Are
there any plans to use any system for code review (like Gerrit)?
This patch is created on the top of the latest code (after the git
cloning gdb repo).
I have tested these changes with my Linux machine (Ubuntu 12.04.4
x86_64) and external USB-UART cable: I was checking tty parameters by
using stty:
Initial setup:
$ sudo stty -F /dev/ttyUSB0 --all
speed 0 baud; rows 0; columns 0; line = 0;
intr = ^C; quit = ^\; erase = ^?; kill = ^U; eof = ^D; eol = <undef>;
eol2 = <undef>; swtch = <undef>; start = ^Q; stop = ^S; susp = ^Z;
rprnt = ^R; werase = ^W; lnext = ^V;
flush = ^O; min = 0; time = 10;
-parenb -parodd cs8 -hupcl -cstopb -cread clocal -crtscts
-ignbrk -brkint -ignpar -parmrk -inpck -istrip -inlcr -igncr -icrnl
-ixon -ixoff -iuclc -ixany -imaxbel -iutf8
-opost -olcuc -ocrnl -onlcr -onocr -onlret -ofill -ofdel nl0 cr0 tab0
bs0 vt0 ff0
-isig -icanon -iexten -echo -echoe -echok -echonl -noflsh -xcase
-tostop -echoprt -echoctl -echoke

gdb-7.9, without changes:
(gdb) set serial baud 38400
(gdb) target remote /dev/ttyUSB0
$ sudo stty -F /dev/ttyUSB0 --all
speed 38400 baud; rows 0; columns 0; line = 0;
intr = ^C; quit = ^\; erase = ^?; kill = ^U; eof = ^D; eol = <undef>;
eol2 = <undef>; swtch = <undef>; start = ^Q; stop = ^S; susp = ^Z;
rprnt = ^R; werase = ^W; lnext = ^V;
flush = ^O; min = 0; time = 10;
-parenb -parodd cs8 -hupcl -cstopb -cread clocal -crtscts
-ignbrk -brkint -ignpar -parmrk -inpck -istrip -inlcr -igncr -icrnl
-ixon -ixoff -iuclc -ixany -imaxbel -iutf8
-opost -olcuc -ocrnl -onlcr -onocr -onlret -ofill -ofdel nl0 cr0 tab0
bs0 vt0 ff0
-isig -icanon -iexten -echo -echoe -echok -echonl -noflsh -xcase
-tostop -echoprt -echoctl -echoke

GDB, compiled with patch:
(gdb) set serial baud 19200
(gdb) show serial parity
Parity for remote serial I/O is "none".
(gdb) target remote /dev/ttyUSB0
$ sudo stty -F /dev/ttyUSB0 --all
speed 19200 baud; rows 0; columns 0; line = 0;
intr = ^C; quit = ^\; erase = ^?; kill = ^U; eof = ^D; eol = <undef>;
eol2 = <undef>; swtch = <undef>; start = ^Q; stop = ^S; susp = ^Z;
rprnt = ^R; werase = ^W; lnext = ^V;
flush = ^O; min = 0; time = 10;
-parenb -parodd cs8 -hupcl -cstopb -cread clocal -crtscts
-ignbrk -brkint -ignpar -parmrk -inpck -istrip -inlcr -igncr -icrnl
-ixon -ixoff -iuclc -ixany -imaxbel -iutf8
-opost -olcuc -ocrnl -onlcr -onocr -onlret -ofill -ofdel nl0 cr0 tab0
bs0 vt0 ff0
-isig -icanon -iexten -echo -echoe -echok -echonl -noflsh -xcase
-tostop -echoprt -echoctl -echoke

(gdb) set serial parity even
(gdb) show serial parity
Parity for remote serial I/O is "even"
(gdb) target remote /dev/ttyUSB0
speed 19200 baud; rows 0; columns 0; line = 0;
intr = ^C; quit = ^\; erase = ^?; kill = ^U; eof = ^D; eol = <undef>;
eol2 = <undef>; swtch = <undef>; start = ^Q; stop = ^S; susp = ^Z;
rprnt = ^R; werase = ^W; lnext = ^V;
flush = ^O; min = 0; time = 10;
parenb -parodd cs8 -hupcl -cstopb -cread clocal -crtscts
-ignbrk -brkint -ignpar -parmrk -inpck -istrip -inlcr -igncr -icrnl
-ixon -ixoff -iuclc -ixany -imaxbel -iutf8
-opost -olcuc -ocrnl -onlcr -onocr -onlret -ofill -ofdel nl0 cr0 tab0
bs0 vt0 ff0
-isig -icanon -iexten -echo -echoe -echok -echonl -noflsh -xcase
-tostop -echoprt -echoctl -echoke

(gdb) set serial parity odd
(gdb) show serial parity
Parity for remote serial I/O is "odd
(gdb) target remote /dev/ttyUSB0
speed 19200 baud; rows 0; columns 0; line = 0;
intr = ^C; quit = ^\; erase = ^?; kill = ^U; eof = ^D; eol = <undef>;
eol2 = <undef>; swtch = <undef>; start = ^Q; stop = ^S; susp = ^Z;
rprnt = ^R; werase = ^W; lnext = ^V;
flush = ^O; min = 0; time = 10;
parenb parodd cs8 -hupcl -cstopb -cread clocal -crtscts
-ignbrk -brkint -ignpar -parmrk -inpck -istrip -inlcr -igncr -icrnl
-ixon -ixoff -iuclc -ixany -imaxbel -iutf8
-opost -olcuc -ocrnl -onlcr -onocr -onlret -ofill -ofdel nl0 cr0 tab0
bs0 vt0 ff0
-isig -icanon -iexten -echo -echoe -echok -echonl -noflsh -xcase
-tostop -echoprt -echoctl -echoke

(gdb) set serial parity none
(gdb) show serial parity
Parity for remote serial I/O is "none".
(gdb) target remote /dev/ttyUSB0
speed 19200 baud; rows 0; columns 0; line = 0;
intr = ^C; quit = ^\; erase = ^?; kill = ^U; eof = ^D; eol = <undef>;
eol2 = <undef>; swtch = <undef>; start = ^Q; stop = ^S; susp = ^Z;
rprnt = ^R; werase = ^W; lnext = ^V;
flush = ^O; min = 0; time = 10;
-parenb -parodd cs8 -hupcl -cstopb -cread clocal -crtscts
-ignbrk -brkint -ignpar -parmrk -inpck -istrip -inlcr -igncr -icrnl
-ixon -ixoff -iuclc -ixany -imaxbel -iutf8
-opost -olcuc -ocrnl -onlcr -onocr -onlret -ofill -ofdel nl0 cr0 tab0
bs0 vt0 ff0
-isig -icanon -iexten -echo -echoe -echok -echonl -noflsh -xcase
-tostop -echoprt -echoctl -echoke

(gdb) set serial parity wrong
Undefined item: "wrong".
(gdb) show serial parity
Parity for remote serial I/O is "none".

Unfortunately, now I don't have the ability to fully-test it with
windows (but I was checking initial version one year ago, with real
hardware). Now it has been compiled by using mingw with
--host=i586-mingw32msvc.

Updated patch is below. Also I've fixed one issue with zeroing PARENB flag.


--
Thanks,
Yury

Comments

Joel Brobecker March 23, 2015, 1:11 p.m. UTC | #1
> Unfortunately, now I don't have the ability to fully-test it with
> windows (but I was checking initial version one year ago, with real
> hardware). Now it has been compiled by using mingw with
> --host=i586-mingw32msvc.

No problem - the code looked about right to me, and we will let those
who do work on Windows take care of fixing any bugs if they use this
feature and encounter a bug.

> diff --git a/gdb/ChangeLog b/gdb/ChangeLog
> index ca8bbaf..02f9ddc 100644
> --- a/gdb/ChangeLog
> +++ b/gdb/ChangeLog
> @@ -1,3 +1,37 @@
> +2015-03-21  Yurij Grechishhev  <yurij.grechishhev@gmail.com>
> +
> +    * NEWS: Mention set/show serial parity command.
> +    * monitor.c (monitor_open): Call serial_setparity.
> +    * remote.c (remote_open_1): Likewise.
> +    * ser-base.c (ser_base_serparity): New function.
> +    * ser-base.h (ser_base_setparity): Add  declaration.
> +    * ser-go32.c (dos_ops): Add dos_noop field.

The name of the struct field is actually "setparity" (instead of
"dos_noop").

> +    * ser-mingw.c (ser_windows_raw): Remove state.fParity and
> +    state.Parity definitions.

"Do not set state.fParity and state.Parity". You remmoved assignments,
rather than 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): Likewise.
> +    * ser-pipe.c (pipe_ops): Likewise.
> +    * ser-tcp.c (tcp_ops): Likewise.
> +    * ser-unix.c (hardwire_setparity): Add declaration.
> +    (hardwire_raw): Don't reset PARENB flag.
> +    (hardwire_setparity): New function.
> +    (hardwire_ops): Add hardwire_setparity.
> +    * serial.c (serial_setparity): New function.
> +    (serial_parity): New global.
> +    (parity_none, parity_odd, parity_even, parity_enums, parity):
> +        New static globals.

Wrong indentation of "New static globals". I suspect that this is
because you used 8 spaces instead of a tab to indent that line?

> +    (set_parity): New function.
> +    (_initialize_serial): Add set/show serial parity commands.
> +    * serial.h (GDBPARITY_NONE): Define.
> +    (GDBPARITY_ODD): Define.
> +    (GDBPARITY_EVEN): Define.
> +    (serial_setparity) Add declaration.
> +    (serial_ops): Add setparity entry.

Let's say...

        (struct serial_ops): Add setparity field

... instead.

> +    * target.h (serial_parity): Add declaration.

The rest are minor comments:

> +      internal_warning (__FILE__, __LINE__, "Incorrect parity value:
> %d", parity);

This line is too long. It shouldn't exceed 79 characters.

      internal_warning (__FILE__, __LINE__, "Incorrect parity value: %d", parity);

Use instead:

      internal_warning (__FILE__, __LINE__,
			"Incorrect parity value: %d", parity);

Also, watch out for the fact that your mailer appears to have wrapped
the line. I suggest you switch to sending the patch either using
"git send-email" (the recommended method), or else sending the patch
as an attachment ("git format-patch" + attach to email).

> @@ -409,7 +410,7 @@ hardwire_raw (struct serial *scb)
>    state.termios.c_iflag = 0;
>    state.termios.c_oflag = 0;
>    state.termios.c_lflag = 0;
> -  state.termios.c_cflag &= ~(CSIZE | PARENB);
> +  state.termios.c_cflag &= ~(CSIZE);

You don't really need the parentheses anymore -> ~CSIZE

>    state.termios.c_cflag |= CLOCAL | CS8;
>  #ifdef CRTSCTS
>    /* h/w flow control.  */
> @@ -432,7 +433,7 @@ hardwire_raw (struct serial *scb)
>    state.termio.c_iflag = 0;
>    state.termio.c_oflag = 0;
>    state.termio.c_lflag = 0;
> -  state.termio.c_cflag &= ~(CSIZE | PARENB);
> +  state.termio.c_cflag &= ~(CSIZE);

Likewise.

> @@ -893,6 +894,50 @@ hardwire_setstopbits (struct serial *scb, int num)
>    return set_tty_state (scb, &state);
>  }
> 
> +/* Implement the "setparity" serial_ops callback.  */
> +
> +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:
> +      internal_warning (__FILE__, __LINE__, "Incorrect parity value:
> %d", parity);

Same as above - line is too long.

> +/* See serial.h.  */
> +
> +int
> +serial_setparity (struct serial *scb, int parity)
> +{
> +    return scb->ops->setparity (scb, parity);

The indentation is wrong (we use a 2-space indentation). Hence:

    int
    serial_setparity (struct serial *scb, int parity)
    {
      return scb->ops->setparity (scb, parity);
    }
Eli Zaretskii March 23, 2015, 3:36 p.m. UTC | #2
> Date: Mon, 23 Mar 2015 01:52:26 +0300
> From: Yurij Grechishhev <yurij.grechishhev@gmail.com>
> Cc: gdb-patches@sourceware.org
> 
> Updated patch is below. Also I've fixed one issue with zeroing PARENB flag.

OK for the documentation parts.

Thanks.
diff mbox

Patch

diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index ca8bbaf..02f9ddc 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,3 +1,37 @@ 
+2015-03-21  Yurij Grechishhev  <yurij.grechishhev@gmail.com>
+
+    * NEWS: Mention set/show serial parity command.
+    * monitor.c (monitor_open): Call serial_setparity.
+    * remote.c (remote_open_1): Likewise.
+    * ser-base.c (ser_base_serparity): New function.
+    * ser-base.h (ser_base_setparity): Add  declaration.
+    * ser-go32.c (dos_ops): Add dos_noop field.
+    * 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): Likewise.
+    * ser-pipe.c (pipe_ops): Likewise.
+    * ser-tcp.c (tcp_ops): Likewise.
+    * ser-unix.c (hardwire_setparity): Add declaration.
+    (hardwire_raw): Don't reset PARENB flag.
+    (hardwire_setparity): New function.
+    (hardwire_ops): Add hardwire_setparity.
+    * serial.c (serial_setparity): 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.
+    * serial.h (GDBPARITY_NONE): Define.
+    (GDBPARITY_ODD): Define.
+    (GDBPARITY_EVEN): Define.
+    (serial_setparity) Add declaration.
+    (serial_ops): Add setparity entry.
+    * target.h (serial_parity): Add declaration.
+
 2015-03-17  Yurij Grechishhev  <yurij.grechishhev@gmail.com>

     * ser-base.h (ser_base_setstopbits): Change second argument name
diff --git a/gdb/NEWS b/gdb/NEWS
index bda4a35..3fa33c9 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..f7d6485 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..ed3ab57 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..09aacec 100644
--- a/gdb/ser-base.c
+++ b/gdb/ser-base.c
@@ -541,6 +541,14 @@  ser_base_setstopbits (struct serial *scb, int num)
   return 0;            /* Never fails!  */
 }

+/* Implement the "setparity" serial_ops callback.  */
+
+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 6aac925..bb1c51d 100644
--- a/gdb/ser-base.h
+++ b/gdb/ser-base.h
@@ -43,6 +43,7 @@  extern int ser_base_noflush_set_tty_state (struct serial *scb,
                        serial_ttystate old_ttystate);
 extern int ser_base_setbaudrate (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..cedbcd6 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;

@@ -198,6 +196,39 @@  ser_windows_setstopbits (struct serial *scb, int num)
   return (SetCommState (h, &state) != 0) ? 0 : -1;
 }

+/* Implement the "setparity" serial_ops callback.  */
+
+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:
+      internal_warning (__FILE__, __LINE__, "Incorrect parity value:
%d", parity);
+      return -1;
+    }
+
+  return (SetCommState (h, &state) != 0) ? 0 : -1;
+}
+
 static int
 ser_windows_setbaudrate (struct serial *scb, int rate)
 {
@@ -1227,6 +1258,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 +1289,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 +1320,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 +1351,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..fa547b3 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);
@@ -409,7 +410,7 @@  hardwire_raw (struct serial *scb)
   state.termios.c_iflag = 0;
   state.termios.c_oflag = 0;
   state.termios.c_lflag = 0;
-  state.termios.c_cflag &= ~(CSIZE | PARENB);
+  state.termios.c_cflag &= ~(CSIZE);
   state.termios.c_cflag |= CLOCAL | CS8;
 #ifdef CRTSCTS
   /* h/w flow control.  */
@@ -432,7 +433,7 @@  hardwire_raw (struct serial *scb)
   state.termio.c_iflag = 0;
   state.termio.c_oflag = 0;
   state.termio.c_lflag = 0;
-  state.termio.c_cflag &= ~(CSIZE | PARENB);
+  state.termio.c_cflag &= ~(CSIZE);
   state.termio.c_cflag |= CLOCAL | CS8;
   state.termio.c_cc[VMIN] = 0;
   state.termio.c_cc[VTIME] = 0;
@@ -893,6 +894,50 @@  hardwire_setstopbits (struct serial *scb, int num)
   return set_tty_state (scb, &state);
 }

+/* Implement the "setparity" serial_ops callback.  */
+
+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:
+      internal_warning (__FILE__, __LINE__, "Incorrect parity value:
%d", parity);
+      return -1;
+    }
+
+#ifdef HAVE_TERMIOS
+  state.termios.c_cflag &= ~(PARENB | PARODD);
+  state.termios.c_cflag |= newparity;
+#endif
+
+#ifdef HAVE_TERMIO
+  state.termio.c_cflag &= ~(PARENB | PARODD);
+  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 +974,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..5f1b5cf 100644
--- a/gdb/serial.c
+++ b/gdb/serial.c
@@ -524,6 +524,14 @@  serial_setstopbits (struct serial *scb, int num)
   return scb->ops->setstopbits (scb, num);
 }

+/* See serial.h.  */
+
+int
+serial_setparity (struct serial *scb, int parity)
+{
+    return scb->ops->setparity (scb, parity);
+}
+
 int
 serial_can_async_p (struct serial *scb)
 {
@@ -638,6 +646,30 @@  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;
+
+/* Set serial_parity value.  */
+
+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 +702,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..add0f15 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);

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

 /* Can the serial device support asynchronous mode?  */
@@ -271,6 +279,9 @@  struct serial_ops
                   serial_ttystate);
     int (*setbaudrate) (struct serial *, int rate);
     int (*setstopbits) (struct serial *, int num);
+    /* Set the value PARITY as parity setting for serial object.
+       Return 0 in the case of success.  */
+    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..05dcd9f 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;