Fr�d�ric Besson wrote in message <36BC2987.322E2423@hei.fr>... >I 'd like to use my serial port to exchange datas with >an external card. >But how can I exchange datas with the serial port with Ada? >My configuration is: PC under Linux. > You didn't give full details, but the solution I provide here works for me with gnat-3.11 (set for native-threads RTS), and RedHat 5.2 (2.0.36). I had this task on my plate anyway, so when I saw your post, I decided to do it now, rather than later. This is far from being a finished work, but does demonstrate how it's done in Ada. First, you need to get the florist library which is an Ada95 binding to POSIX, in accordance with the IEEE spec. The library is available at http://www.cs.fsu.edu/~baker/ftp/pub/PART/FLORIST/ in the file "florist981211.tar.gz" I had to apply the following patch to get the library to build: ---- begin patch ---- diff -Naur orig/florist-3.12w/posix-implementation.gpb new/florist-3.12w/posix-implementation.gpb --- orig/florist-3.12w/posix-implementation.gpb Sat Sep 19 07:51:22 1998 +++ new/florist-3.12w/posix-implementation.gpb Mon Feb 8 13:24:56 1999 @@ -436,7 +436,9 @@ end To_Struct_Timeval; #if HAVE_Leroy_Threads then + function getpid return pid_t; + pragma Import (C, getpid, getpid_LINKNAME); begin - This_Process := Process_ID (getpid); + This_Process := getpid; #end if; end POSIX.Implementation; diff -Naur orig/florist-3.12w/posix-unsafe_process_primitives.gpb new/florist-3.12w/posix-unsafe_process_primitives.gpb --- orig/florist-3.12w/posix-unsafe_process_primitives.gpb Sat Sep 19 07:51:33 1998 +++ new/florist-3.12w/posix-unsafe_process_primitives.gpb Mon Feb 8 13:24:56 1999 @@ -105,9 +105,9 @@ Result := fork; if Result = -1 then Raise_POSIX_Error; end if; if Result = 0 then -# if HAVE_Leroy_Threads then - This_Process := getpid; -# end if; +-- # if HAVE_Leroy_Threads then +-- This_Process := getpid; +-- # end if; -- reset soft links to non-tasking versions of operations # if HAVE_Soft_Abort_Defer TSL.Abort_Defer := TSL.Abort_Defer_NT'Access; --- end patch --- Then I wrote a small test program which just sends "ATZ" to a modem, and waits for a response, and displays it, then sends "ATI7", waits for the response, and displays it. Here is the Ada95 source code for that test program: ---- begin Ada source code ---- with Ada.Calendar; with Ada.Characters.Latin_1; with Ada.Command_Line; with Ada.Exceptions; with Ada.Strings.Unbounded; with Ada.Text_IO; with Interfaces.C; with POSIX.C; with POSIX.IO; with POSIX.Terminal_Functions; with System; procedure Serial is -- NOTE: This is far from complete. Most of this should be in a separate -- package, done to a higher level of abstraction, and implementation details -- should be hidden. -- This is just "quick and dirty" for proof of concept. subtype File_Descriptor is POSIX.IO.File_Descriptor; use type File_Descriptor; subtype Bit_Rate is POSIX.Terminal_Functions.Baud_Rate; Serial_File_Descriptor : File_Descriptor; Characteristics : POSIX.Terminal_functions.Terminal_Characteristics; Invalid_Command_Line : exception; Unable_To_Open_Serial_Port : exception; Invalid_Bit_Rate : exception; use type POSIX.POSIX_String; CR : constant POSIX.POSIX_Character := POSIX.POSIX_Character'Val (13); LF : constant POSIX.POSIX_Character := POSIX.POSIX_Character'Val (10); Modem_Reset : constant POSIX.POSIX_String := "ATZ" & CR; Modem_Query : constant POSIX.POSIX_String := "ATI7" & CR; Modem_Response : POSIX.POSIX_String (1 .. 20480); Modem_Read_Length : POSIX.IO_Count; Modem_Write_Length : POSIX.IO_Count; Rate : Bit_Rate; Modes : POSIX.Terminal_Functions.Terminal_Modes_Set; use type POSIX.IO.Open_Option_Set; function Image (Modes : POSIX.Terminal_Functions.Terminal_Modes_Set) return POSIX.POSIX_String is Result : Ada.Strings.Unbounded.Unbounded_String := Ada.Strings.Unbounded.Null_Unbounded_String; begin for M in Modes'Range loop declare Modes_Image : constant String := POSIX.Terminal_Functions.Terminal_Modes'Image (M); Spacer : constant String ( 1 .. (POSIX.Terminal_Functions.Terminal_Modes'Width - Modes_Image'Length) + 1) := (others => ' '); begin Ada.Strings.Unbounded.Append (Source => Result, New_Item => Modes_Image & Spacer & Boolean'Image (Modes (M)) & Ada.Characters.Latin_1.LF); end; end loop; return POSIX.To_POSIX_String (Ada.Strings.Unbounded.To_String (Result)); end Image; procedure Read (FD : File_Descriptor; Item : out POSIX.POSIX_String; Timeout : Duration; Last : out POSIX.IO_Count) is use type POSIX.IO_Count; begin Last := POSIX.IO_Count (Item'First - 1); -- Since the POSIX.IO.Read command will return whenever it reads a -- CR character in the stream, we keep reading until there is a -- period of Timeout seconds with no more input, then aborts the -- blocking POSIX.IO>Read, and returns with the data. -- This procedure is not robust in such areas as buffer overflow. loop select delay Timeout; exit; then abort POSIX.IO.Read (File => FD, Buffer => Item (Natural (Last) + 1 .. Item'Last), Last => Last); end select; end loop; end Read; begin if Ada.Command_Line.Argument_Count /= 3 then Ada.Exceptions.Raise_Exception (E => Invalid_Command_Line'Identity, Message => "USAGE: " & Ada.Command_Line.Command_Name & " (sec.) (bps)"); end if; declare Device_Name : constant POSIX.Pathname := POSIX.To_POSIX_String (Ada.Command_Line.Argument (1)); Time_To_Wait : constant Duration := Duration'Value (Ada.Command_Line.Argument (2)); begin begin Rate := Bit_Rate'Value ("B" & Ada.Command_Line.Argument (3)); exception when Constraint_Error => Ada.Exceptions.Raise_Exception (E => Invalid_Bit_Rate'Identity, Message => "Attempted setting => """ & Ada.Command_Line.Argument (3) & """"); end; select -- We add one second here, so as to give time for the open operation. delay Time_To_Wait + 1.0; Ada.Exceptions.Raise_Exception (E => Unable_To_Open_Serial_Port'Identity, Message => "Operation timed out"); then abort Ada.Text_IO.Put_Line (POSIX.To_String ("Attempting to open """ & Device_Name & """ for input and output...")); Serial_File_Descriptor := POSIX.IO.Open (Name => Device_Name, Mode => POSIX.IO.Read_Write, Options => POSIX.IO.Not_Controlling_Terminal - POSIX.IO.Non_Blocking); end select; exception when E: others => Ada.Exceptions.Raise_Exception (E => Ada.Exceptions.Exception_Identity (E), Message => Ada.Exceptions.Exception_Information (E) & POSIX.To_String ("while attempting to open file """ & Device_Name & """ for input")); end; -- If we get here, the file is open. Characteristics := POSIX.Terminal_Functions.Get_Terminal_Characteristics (File => Serial_File_Descriptor); Modes := POSIX.Terminal_Functions.Terminal_Modes_Of (Characteristics => Characteristics); Ada.Text_IO.Put_Line ("Initial modes:" & Ada.Characters.Latin_1.Lf & POSIX.To_String (Image (Modes))); POSIX.Terminal_Functions.Define_Output_Baud_Rate (Characteristics => Characteristics, Output_Baud_Rate => Rate); POSIX.Terminal_Functions.Define_Input_Baud_Rate (Characteristics => Characteristics, Input_Baud_Rate => Rate); Modes (POSIX.Terminal_Functions.Canonical_Input) := False; Modes (POSIX.Terminal_Functions.Map_Cr_To_Lf) := False; Modes (POSIX.Terminal_Functions.Echo) := False; POSIX.Terminal_Functions.Define_Terminal_Modes (Characteristics => Characteristics, Modes => Modes); POSIX.Terminal_Functions.Define_Input_Time (Characteristics => Characteristics, Input_Time => 1.0); POSIX.Terminal_Functions.Define_Minimum_Input_Count (Characteristics => Characteristics, Minimum_Input_Count => 0); POSIX.Terminal_Functions.Set_Terminal_Characteristics (File => Serial_File_Descriptor, Characteristics => Characteristics, Masked_Signals => POSIX.All_Signals); Modes := POSIX.Terminal_Functions.Terminal_Modes_Of (Characteristics => Characteristics); Ada.Text_IO.Put_Line ("Operating modes:" & Ada.Characters.Latin_1.Lf & POSIX.To_String (Image (Modes))); delay 0.1; POSIX.IO.Write (File => Serial_File_Descriptor, Buffer => Modem_Reset, Last => Modem_Write_Length); Ada.Text_IO.Put_Line ("Sent:"); Ada.Text_IO.Put_Line (POSIX.To_String (Modem_Reset (Modem_Reset'First .. Modem_Reset'First + Natural (Modem_Write_Length) - 1))); Read (FD => Serial_File_Descriptor, Item => Modem_Response, Last => Modem_Read_Length, -- Alloww 0.1 sec. + 100 bit times Timeout => 0.1 + 100.0 / Natural'Value (Ada.Command_Line.Argument (3))); Ada.Text_IO.Put_Line (POSIX.To_string ("Received: """ & Modem_Response (Modem_Response'First .. Modem_Response'First + Natural (Modem_Read_Length) - 1) & """")); POSIX.IO.Write (File => Serial_File_Descriptor, Buffer => Modem_Query, Last => Modem_Write_Length); Ada.Text_IO.Put_Line ("Sent:"); Ada.Text_IO.Put_Line (POSIX.To_String (Modem_Query (Modem_Query'First .. Modem_Query'First + Natural (Modem_Write_Length) - 1))); Read (FD => Serial_File_Descriptor, item => Modem_Response, Last => Modem_Read_Length, -- Alloww 0.1 sec. + 100 bit times Timeout => 0.1 + 100.0 / Natural'Value (Ada.Command_Line.Argument (3))); Ada.Text_IO.Put_Line (POSIX.To_string ("Received: """ & Modem_Response (Modem_Response'First .. Modem_Response'First + Natural (Modem_Read_Length) - 1) & """")); exception when E: others => Ada.Text_IO.Put_Line (Ada.Exceptions.Exception_Information (E)); Ada.Command_Line.Set_Exit_Status (Ada.Command_Line.Failure); end Serial; --- end Ada source code --- The device name to use is the appropriate ones of /dev/ttyS0 (for COM1:) through /dev/ttySn (for COMn+1:) Hope this helps. David C. Hoos, Sr.