Patchwork [Ada] Serial port flow control support

login
register
mail settings
Submitter Arnaud Charlet
Date Aug. 6, 2012, 8:36 a.m.
Message ID <20120806083603.GA28629@adacore.com>
Download mbox | patch
Permalink /patch/175299/
State New
Headers show

Comments

Arnaud Charlet - Aug. 6, 2012, 8:36 a.m.
This change adds two new optional parameters to GNAT.Serial_Comminications.Set
to allow the user to specify a local port (no modem control lines), and to
choose a flow control method (none, hardware, software). Note that the
default behaviour is now consistently no flow control on all platforms.
Previously it was the case on Windows only; on Linux, RTS/CTS flow control
was always enabled.

Tested on x86_64-pc-linux-gnu, committed on trunk

2012-08-06  Thomas Quinot  <quinot@adacore.com>

	* g-sercom.adb, g-sercom.ads, g-sercom-mingw.adb, g-sercom-linux.adb
	(Set): Add Local and Flow_Control settings.

Patch

Index: g-sercom.adb
===================================================================
--- g-sercom.adb	(revision 190155)
+++ g-sercom.adb	(working copy)
@@ -6,7 +6,7 @@ 
 --                                                                          --
 --                                 B o d y                                  --
 --                                                                          --
---                     Copyright (C) 2007-2010, AdaCore                     --
+--                     Copyright (C) 2007-2012, AdaCore                     --
 --                                                                          --
 -- GNAT is free software;  you can  redistribute it  and/or modify it under --
 -- terms of the  GNU General Public License as published  by the Free Soft- --
@@ -82,6 +82,8 @@ 
       Stop_Bits : Stop_Bits_Number := One;
       Parity    : Parity_Check     := None;
       Block     : Boolean          := True;
+      Local     : Boolean          := True;
+      Flow      : Flow_Control     := None;
       Timeout   : Duration         := 10.0)
    is
    begin
Index: g-sercom.ads
===================================================================
--- g-sercom.ads	(revision 190155)
+++ g-sercom.ads	(working copy)
@@ -6,7 +6,7 @@ 
 --                                                                          --
 --                                 S p e c                                  --
 --                                                                          --
---                    Copyright (C) 2007-2010, AdaCore                      --
+--                    Copyright (C) 2007-2012, AdaCore                      --
 --                                                                          --
 -- GNAT is free software;  you can  redistribute it  and/or modify it under --
 -- terms of the  GNU General Public License as published  by the Free Soft- --
@@ -62,6 +62,9 @@ 
    type Parity_Check is (None, Even, Odd);
    --  Either no parity check or an even or odd parity
 
+   type Flow_Control is (None, RTS_CTS, Xon_Xoff);
+   --  No flow control, hardware flow control, software flow control
+
    type Serial_Port is new Ada.Streams.Root_Stream_Type with private;
 
    procedure Open
@@ -77,13 +80,18 @@ 
       Stop_Bits : Stop_Bits_Number := One;
       Parity    : Parity_Check     := None;
       Block     : Boolean          := True;
+      Local     : Boolean          := True;
+      Flow      : Flow_Control     := None;
       Timeout   : Duration         := 10.0);
    --  The communication port settings. If Block is set then a read call
    --  will wait for the whole buffer to be filed. If Block is not set then
-   --  the given Timeout (in seconds) is used. Note that the timeout precision
-   --  may be limited on some implementation (e.g. on GNU/Linux the maximum
-   --  precision is a tenth of seconds).
+   --  the given Timeout (in seconds) is used. If Local is set then modem
+   --  control lines (in particular DCD) are ignored (not supported on
+   --  Windows).
 
+   --  Note that the timeout precision may be limited on some implementation
+   --  (e.g. on GNU/Linux the maximum precision is a tenth of seconds).
+
    overriding procedure Read
      (Port   : in out Serial_Port;
       Buffer : out Ada.Streams.Stream_Element_Array;
Index: g-sercom-mingw.adb
===================================================================
--- g-sercom-mingw.adb	(revision 190155)
+++ g-sercom-mingw.adb	(working copy)
@@ -6,7 +6,7 @@ 
 --                                                                          --
 --                                 B o d y                                  --
 --                                                                          --
---                    Copyright (C) 2007-2010, AdaCore                      --
+--                    Copyright (C) 2007-2012, AdaCore                      --
 --                                                                          --
 -- GNAT is free software;  you can  redistribute it  and/or modify it under --
 -- terms of the  GNU General Public License as published  by the Free Soft- --
@@ -175,8 +175,12 @@ 
       Stop_Bits : Stop_Bits_Number := One;
       Parity    : Parity_Check     := None;
       Block     : Boolean          := True;
+      Local     : Boolean          := True;
+      Flow      : Flow_Control     := None;
       Timeout   : Duration         := 10.0)
    is
+      pragma Unreferenced (Local);
+
       Success      : BOOL;
       Com_Time_Out : aliased COMMTIMEOUTS;
       Com_Settings : aliased DCB;
@@ -197,13 +201,26 @@ 
       Com_Settings.BaudRate        := DWORD (Data_Rate_Value (Rate));
       Com_Settings.fParity         := 1;
       Com_Settings.fBinary         := Bits1 (System.Win32.TRUE);
-      Com_Settings.fOutxCtsFlow    := 0;
       Com_Settings.fOutxDsrFlow    := 0;
       Com_Settings.fDsrSensitivity := 0;
-      Com_Settings.fDtrControl     := DTR_CONTROL_DISABLE;
-      Com_Settings.fOutX           := 0;
+      Com_Settings.fDtrControl     := DTR_CONTROL_ENABLE;
       Com_Settings.fInX            := 0;
-      Com_Settings.fRtsControl     := RTS_CONTROL_DISABLE;
+      Com_Settings.fRtsControl     := RTS_CONTROL_ENABLE;
+
+      case Flow is
+         when None =>
+            Com_Settings.fOutX        := 0;
+            Com_Settings.fOutxCtsFlow := 0;
+
+         when RTS_CTS =>
+            Com_Settings.fOutX        := 0;
+            Com_Settings.fOutxCtsFlow := 1;
+
+         when Xon_Xoff =>
+            Com_Settings.fOutX        := 1;
+            Com_Settings.fOutxCtsFlow := 0;
+      end case;
+
       Com_Settings.fAbortOnError   := 0;
       Com_Settings.ByteSize        := BYTE (C_Bits (Bits));
       Com_Settings.Parity          := BYTE (C_Parity (Parity));
Index: g-sercom-linux.adb
===================================================================
--- g-sercom-linux.adb	(revision 190155)
+++ g-sercom-linux.adb	(working copy)
@@ -6,7 +6,7 @@ 
 --                                                                          --
 --                                 B o d y                                  --
 --                                                                          --
---                    Copyright (C) 2007-2010, AdaCore                      --
+--                    Copyright (C) 2007-2012, AdaCore                      --
 --                                                                          --
 -- GNAT is free software;  you can  redistribute it  and/or modify it under --
 -- terms of the  GNU General Public License as published  by the Free Soft- --
@@ -38,11 +38,14 @@ 
 with System;               use System;
 with System.Communication; use System.Communication;
 with System.CRTL;          use System.CRTL;
+with System.OS_Constants;
 
 with GNAT.OS_Lib; use GNAT.OS_Lib;
 
 package body GNAT.Serial_Communications is
 
+   package OSC renames System.OS_Constants;
+
    use type Interfaces.C.unsigned;
 
    type Port_Data is new int;
@@ -54,43 +57,26 @@ 
    function fcntl (fd : int; cmd : int; value : int) return int;
    pragma Import (C, fcntl, "fcntl");
 
-   O_RDWR   : constant := 8#02#;
-   O_NOCTTY : constant := 8#0400#;
-   O_NDELAY : constant := 8#04000#;
-   FNDELAY  : constant := O_NDELAY;
-   F_SETFL  : constant := 4;
-   TCSANOW  : constant := 0;
-   TCIFLUSH : constant := 0;
-   CLOCAL   : constant := 8#04000#;
-   CREAD    : constant := 8#0200#;
-   CSTOPB   : constant := 8#0100#;
-   CRTSCTS  : constant := 8#020000000000#;
-   PARENB   : constant := 8#00400#;
-   PARODD   : constant := 8#01000#;
-
-   --  c_cc indexes
-
-   VTIME : constant := 5;
-   VMIN  : constant := 6;
-
    C_Data_Rate : constant array (Data_Rate) of unsigned :=
-                   (B1200   => 8#000011#,
-                    B2400   => 8#000013#,
-                    B4800   => 8#000014#,
-                    B9600   => 8#000015#,
-                    B19200  => 8#000016#,
-                    B38400  => 8#000017#,
-                    B57600  => 8#010001#,
-                    B115200 => 8#010002#);
+                   (B1200   => OSC.B1200,
+                    B2400   => OSC.B2400,
+                    B4800   => OSC.B4800,
+                    B9600   => OSC.B9600,
+                    B19200  => OSC.B19200,
+                    B38400  => OSC.B38400,
+                    B57600  => OSC.B57600,
+                    B115200 => OSC.B115200);
 
    C_Bits      : constant array (Data_Bits) of unsigned :=
-                   (CS7 => 8#040#, CS8 => 8#060#);
+                   (CS7 => OSC.CS7, CS8 => OSC.CS8);
 
    C_Stop_Bits : constant array (Stop_Bits_Number) of unsigned :=
-                   (One => 0, Two => CSTOPB);
+                   (One => 0, Two => OSC.CSTOPB);
 
    C_Parity    : constant array (Parity_Check) of unsigned :=
-                   (None => 0, Odd => PARENB or PARODD, Even => PARENB);
+                   (None => 0,
+                    Odd  => OSC.PARENB or OSC.PARODD,
+                    Even => OSC.PARENB);
 
    procedure Raise_Error (Message : String; Error : Integer := Errno);
    pragma No_Return (Raise_Error);
@@ -114,6 +100,8 @@ 
      (Port : out Serial_Port;
       Name : Port_Name)
    is
+      use OSC;
+
       C_Name : constant String := String (Name) & ASCII.NUL;
       Res    : int;
 
@@ -184,8 +172,12 @@ 
       Stop_Bits : Stop_Bits_Number := One;
       Parity    : Parity_Check     := None;
       Block     : Boolean          := True;
+      Local     : Boolean          := True;
+      Flow      : Flow_Control     := None;
       Timeout   : Duration         := 10.0)
    is
+      use OSC;
+
       type termios is record
          c_iflag  : unsigned;
          c_oflag  : unsigned;
@@ -229,12 +221,24 @@ 
                                 or C_Bits (Bits)
                                 or C_Stop_Bits (Stop_Bits)
                                 or C_Parity (Parity)
-                                or CLOCAL
-                                or CREAD
-                                or CRTSCTS;
+                                or CREAD;
+      Current.c_iflag      := 0;
       Current.c_lflag      := 0;
-      Current.c_iflag      := 0;
       Current.c_oflag      := 0;
+
+      if Local then
+         Current.c_cflag := Current.c_cflag or CLOCAL;
+      end if;
+
+      case Flow is
+         when None =>
+            null;
+         when RTS_CTS =>
+            Current.c_cflag := Current.c_cflag or CRTSCTS;
+         when Xon_Xoff =>
+            Current.c_iflag := Current.c_iflag or IXON;
+      end case;
+
       Current.c_ispeed     := Data_Rate_Value (Rate);
       Current.c_ospeed     := Data_Rate_Value (Rate);
       Current.c_cc (VMIN)  := char'Val (0);