PR testsuite/44195
[official-gcc.git] / gcc / ada / g-sercom-mingw.adb
blobcc6123bbc7c0306d65d2ad7791771ed759003ec9
1 ------------------------------------------------------------------------------
2 -- --
3 -- GNAT COMPILER COMPONENTS --
4 -- --
5 -- G N A T . S E R I A L _ C O M M U N I C A T I O N S --
6 -- --
7 -- B o d y --
8 -- --
9 -- Copyright (C) 2007-2009, AdaCore --
10 -- --
11 -- GNAT is free software; you can redistribute it and/or modify it under --
12 -- terms of the GNU General Public License as published by the Free Soft- --
13 -- ware Foundation; either version 2, or (at your option) any later ver- --
14 -- sion. GNAT is distributed in the hope that it will be useful, but WITH- --
15 -- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY --
16 -- or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License --
17 -- for more details. You should have received a copy of the GNU General --
18 -- Public License distributed with GNAT; see file COPYING. If not, write --
19 -- to the Free Software Foundation, 51 Franklin Street, Fifth Floor, --
20 -- Boston, MA 02110-1301, USA. --
21 -- --
22 -- As a special exception, if other files instantiate generics from this --
23 -- unit, or you link this unit with other files to produce an executable, --
24 -- this unit does not by itself cause the resulting executable to be --
25 -- covered by the GNU General Public License. This exception does not --
26 -- however invalidate any other reasons why the executable file might be --
27 -- covered by the GNU Public License. --
28 -- --
29 -- GNAT was originally developed by the GNAT team at New York University. --
30 -- Extensive contributions were provided by Ada Core Technologies Inc. --
31 -- --
32 ------------------------------------------------------------------------------
34 -- This is the Windows implementation of this package
36 with Ada.Unchecked_Deallocation; use Ada;
37 with Ada.Streams; use Ada.Streams;
39 with System; use System;
40 with System.Communication; use System.Communication;
41 with System.CRTL; use System.CRTL;
42 with System.Win32; use System.Win32;
43 with System.Win32.Ext; use System.Win32.Ext;
45 package body GNAT.Serial_Communications is
47 -- Common types
49 type Port_Data is new HANDLE;
51 C_Bits : constant array (Data_Bits) of Interfaces.C.unsigned := (8, 7);
52 C_Parity : constant array (Parity_Check) of Interfaces.C.unsigned :=
53 (None => NOPARITY, Odd => ODDPARITY, Even => EVENPARITY);
54 C_Stop_Bits : constant array (Stop_Bits_Number) of Interfaces.C.unsigned :=
55 (One => ONESTOPBIT, Two => TWOSTOPBITS);
57 -----------
58 -- Files --
59 -----------
61 procedure Raise_Error (Message : String; Error : DWORD := GetLastError);
62 pragma No_Return (Raise_Error);
64 -----------
65 -- Close --
66 -----------
68 procedure Close (Port : in out Serial_Port) is
69 procedure Unchecked_Free is
70 new Unchecked_Deallocation (Port_Data, Port_Data_Access);
72 Success : BOOL;
74 begin
75 if Port.H /= null then
76 Success := CloseHandle (HANDLE (Port.H.all));
77 Unchecked_Free (Port.H);
79 if Success = Win32.FALSE then
80 Raise_Error ("error closing the port");
81 end if;
82 end if;
83 end Close;
85 ----------
86 -- Name --
87 ----------
89 function Name (Number : Positive) return Port_Name is
90 N_Img : constant String := Positive'Image (Number);
91 begin
92 return Port_Name ("COM" & N_Img (N_Img'First + 1 .. N_Img'Last) & ':');
93 end Name;
95 ----------
96 -- Open --
97 ----------
99 procedure Open
100 (Port : out Serial_Port;
101 Name : Port_Name)
103 C_Name : constant String := String (Name) & ASCII.NUL;
104 Success : BOOL;
105 pragma Unreferenced (Success);
107 begin
108 if Port.H = null then
109 Port.H := new Port_Data;
110 else
111 Success := CloseHandle (HANDLE (Port.H.all));
112 end if;
114 Port.H.all := CreateFileA
115 (lpFileName => C_Name (C_Name'First)'Address,
116 dwDesiredAccess => GENERIC_READ or GENERIC_WRITE,
117 dwShareMode => 0,
118 lpSecurityAttributes => null,
119 dwCreationDisposition => OPEN_EXISTING,
120 dwFlagsAndAttributes => 0,
121 hTemplateFile => 0);
123 if Port.H.all = 0 then
124 Raise_Error ("cannot open com port");
125 end if;
126 end Open;
128 -----------------
129 -- Raise_Error --
130 -----------------
132 procedure Raise_Error (Message : String; Error : DWORD := GetLastError) is
133 begin
134 raise Serial_Error with Message & " (" & DWORD'Image (Error) & ')';
135 end Raise_Error;
137 ----------
138 -- Read --
139 ----------
141 overriding procedure Read
142 (Port : in out Serial_Port;
143 Buffer : out Stream_Element_Array;
144 Last : out Stream_Element_Offset)
146 Success : BOOL;
147 Read_Last : aliased DWORD;
149 begin
150 if Port.H = null then
151 Raise_Error ("read: port not opened", 0);
152 end if;
154 Success :=
155 ReadFile
156 (hFile => HANDLE (Port.H.all),
157 lpBuffer => Buffer (Buffer'First)'Address,
158 nNumberOfBytesToRead => DWORD (Buffer'Length),
159 lpNumberOfBytesRead => Read_Last'Access,
160 lpOverlapped => null);
162 if Success = Win32.FALSE then
163 Raise_Error ("read error");
164 end if;
166 Last := Last_Index (Buffer'First, size_t (Read_Last));
167 end Read;
169 ---------
170 -- Set --
171 ---------
173 procedure Set
174 (Port : Serial_Port;
175 Rate : Data_Rate := B9600;
176 Bits : Data_Bits := CS8;
177 Stop_Bits : Stop_Bits_Number := One;
178 Parity : Parity_Check := None;
179 Block : Boolean := True;
180 Timeout : Duration := 10.0)
182 Success : BOOL;
183 Com_Time_Out : aliased COMMTIMEOUTS;
184 Com_Settings : aliased DCB;
186 begin
187 if Port.H = null then
188 Raise_Error ("set: port not opened", 0);
189 end if;
191 Success := GetCommState (HANDLE (Port.H.all), Com_Settings'Access);
193 if Success = Win32.FALSE then
194 Success := CloseHandle (HANDLE (Port.H.all));
195 Port.H.all := 0;
196 Raise_Error ("set: cannot get comm state");
197 end if;
199 Com_Settings.BaudRate := DWORD (Data_Rate_Value (Rate));
200 Com_Settings.fParity := 1;
201 Com_Settings.fBinary := Bits1 (System.Win32.TRUE);
202 Com_Settings.fOutxCtsFlow := 0;
203 Com_Settings.fOutxDsrFlow := 0;
204 Com_Settings.fDsrSensitivity := 0;
205 Com_Settings.fDtrControl := DTR_CONTROL_DISABLE;
206 Com_Settings.fOutX := 0;
207 Com_Settings.fInX := 0;
208 Com_Settings.fRtsControl := RTS_CONTROL_DISABLE;
209 Com_Settings.fAbortOnError := 0;
210 Com_Settings.ByteSize := BYTE (C_Bits (Bits));
211 Com_Settings.Parity := BYTE (C_Parity (Parity));
212 Com_Settings.StopBits := BYTE (C_Stop_Bits (Stop_Bits));
214 Success := SetCommState (HANDLE (Port.H.all), Com_Settings'Access);
216 if Success = Win32.FALSE then
217 Success := CloseHandle (HANDLE (Port.H.all));
218 Port.H.all := 0;
219 Raise_Error ("cannot set comm state");
220 end if;
222 -- Set the timeout status
224 if Block then
225 Com_Time_Out := (others => 0);
226 else
227 Com_Time_Out :=
228 (ReadTotalTimeoutConstant => DWORD (1000 * Timeout),
229 others => 0);
230 end if;
232 Success :=
233 SetCommTimeouts
234 (hFile => HANDLE (Port.H.all),
235 lpCommTimeouts => Com_Time_Out'Access);
237 if Success = Win32.FALSE then
238 Raise_Error ("cannot set the timeout");
239 end if;
240 end Set;
242 -----------
243 -- Write --
244 -----------
246 overriding procedure Write
247 (Port : in out Serial_Port;
248 Buffer : Stream_Element_Array)
250 Success : BOOL;
251 Temp_Last : aliased DWORD;
253 begin
254 if Port.H = null then
255 Raise_Error ("write: port not opened", 0);
256 end if;
258 Success :=
259 WriteFile
260 (hFile => HANDLE (Port.H.all),
261 lpBuffer => Buffer'Address,
262 nNumberOfBytesToWrite => DWORD (Buffer'Length),
263 lpNumberOfBytesWritten => Temp_Last'Access,
264 lpOverlapped => null);
266 if Success = Win32.FALSE
267 or else Stream_Element_Offset (Temp_Last) /= Buffer'Length
268 then
269 Raise_Error ("failed to write data");
270 end if;
271 end Write;
273 end GNAT.Serial_Communications;