]> git.ipfire.org Git - thirdparty/gcc.git/blob - gcc/ada/libgnat/g-sercom__mingw.adb
[Ada] Bump copyright year
[thirdparty/gcc.git] / gcc / ada / libgnat / g-sercom__mingw.adb
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-2020, 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 3, 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. --
17 -- --
18 -- As a special exception under Section 7 of GPL version 3, you are granted --
19 -- additional permissions described in the GCC Runtime Library Exception, --
20 -- version 3.1, as published by the Free Software Foundation. --
21 -- --
22 -- You should have received a copy of the GNU General Public License and --
23 -- a copy of the GCC Runtime Library Exception along with this program; --
24 -- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see --
25 -- <http://www.gnu.org/licenses/>. --
26 -- --
27 -- GNAT was originally developed by the GNAT team at New York University. --
28 -- Extensive contributions were provided by Ada Core Technologies Inc. --
29 -- --
30 ------------------------------------------------------------------------------
31
32 -- This is the Windows implementation of this package
33
34 with Ada.Streams; use Ada.Streams, Ada;
35
36 with System; use System;
37 with System.Communication; use System.Communication;
38 with System.CRTL; use System.CRTL;
39 with System.Win32; use System.Win32;
40 with System.Win32.Ext; use System.Win32.Ext;
41
42 with GNAT.OS_Lib;
43
44 package body GNAT.Serial_Communications is
45
46 package OSC renames System.OS_Constants;
47
48 -- Common types
49
50 C_Bits : constant array (Data_Bits) of Interfaces.C.unsigned := (8, 7);
51 C_Parity : constant array (Parity_Check) of Interfaces.C.unsigned :=
52 (None => NOPARITY, Odd => ODDPARITY, Even => EVENPARITY);
53 C_Stop_Bits : constant array (Stop_Bits_Number) of Interfaces.C.unsigned :=
54 (One => ONESTOPBIT, Two => TWOSTOPBITS);
55
56 -----------
57 -- Files --
58 -----------
59
60 procedure Raise_Error (Message : String; Error : DWORD := GetLastError);
61 pragma No_Return (Raise_Error);
62
63 -----------
64 -- Close --
65 -----------
66
67 procedure Close (Port : in out Serial_Port) is
68 Success : BOOL;
69
70 begin
71 if Port.H /= -1 then
72 Success := CloseHandle (HANDLE (Port.H));
73
74 if Success = Win32.FALSE then
75 Raise_Error ("error closing the port");
76 end if;
77 end if;
78 end Close;
79
80 ----------
81 -- Name --
82 ----------
83
84 function Name (Number : Positive) return Port_Name is
85 N_Img : constant String := Positive'Image (Number);
86 begin
87 if Number > 9 then
88 return
89 Port_Name ("\\.\COM" & N_Img (N_Img'First + 1 .. N_Img'Last));
90 else
91 return
92 Port_Name ("COM" & N_Img (N_Img'First + 1 .. N_Img'Last) & ':');
93 end if;
94 end Name;
95
96 ----------
97 -- Open --
98 ----------
99
100 procedure Open
101 (Port : out Serial_Port;
102 Name : Port_Name)
103 is
104 C_Name : constant String := String (Name) & ASCII.NUL;
105 Success : BOOL;
106 pragma Unreferenced (Success);
107
108 begin
109 if Port.H /= -1 then
110 Success := CloseHandle (HANDLE (Port.H));
111 end if;
112
113 Port.H := CreateFileA
114 (lpFileName => C_Name (C_Name'First)'Address,
115 dwDesiredAccess => GENERIC_READ or GENERIC_WRITE,
116 dwShareMode => 0,
117 lpSecurityAttributes => null,
118 dwCreationDisposition => OPEN_EXISTING,
119 dwFlagsAndAttributes => 0,
120 hTemplateFile => 0);
121
122 pragma Assert (INVALID_HANDLE_VALUE = -1);
123
124 if Port.H = Serial_Port_Descriptor (INVALID_HANDLE_VALUE) then
125 Raise_Error ("cannot open com port");
126 end if;
127 end Open;
128
129 -----------------
130 -- Raise_Error --
131 -----------------
132
133 procedure Raise_Error (Message : String; Error : DWORD := GetLastError) is
134 begin
135 raise Serial_Error with Message
136 & (if Error /= 0
137 then " (" & GNAT.OS_Lib.Errno_Message (Err => Integer (Error)) & ')'
138 else "");
139 end Raise_Error;
140
141 ----------
142 -- Read --
143 ----------
144
145 overriding procedure Read
146 (Port : in out Serial_Port;
147 Buffer : out Stream_Element_Array;
148 Last : out Stream_Element_Offset)
149 is
150 Success : BOOL;
151 Read_Last : aliased DWORD;
152
153 begin
154 if Port.H = -1 then
155 Raise_Error ("read: port not opened", 0);
156 end if;
157
158 Success :=
159 ReadFile
160 (hFile => HANDLE (Port.H),
161 lpBuffer => Buffer (Buffer'First)'Address,
162 nNumberOfBytesToRead => DWORD (Buffer'Length),
163 lpNumberOfBytesRead => Read_Last'Access,
164 lpOverlapped => null);
165
166 if Success = Win32.FALSE then
167 Raise_Error ("read error");
168 end if;
169
170 Last := Last_Index (Buffer'First, CRTL.size_t (Read_Last));
171 end Read;
172
173 ---------
174 -- Set --
175 ---------
176
177 procedure Set
178 (Port : Serial_Port;
179 Rate : Data_Rate := B9600;
180 Bits : Data_Bits := CS8;
181 Stop_Bits : Stop_Bits_Number := One;
182 Parity : Parity_Check := None;
183 Block : Boolean := True;
184 Local : Boolean := True;
185 Flow : Flow_Control := None;
186 Timeout : Duration := 10.0)
187 is
188 pragma Unreferenced (Local);
189
190 Success : BOOL;
191 Com_Time_Out : aliased COMMTIMEOUTS;
192 Com_Settings : aliased DCB;
193
194 begin
195 if Port.H = -1 then
196 Raise_Error ("set: port not opened", 0);
197 end if;
198
199 Success := GetCommState (HANDLE (Port.H), Com_Settings'Access);
200
201 if Success = Win32.FALSE then
202 Success := CloseHandle (HANDLE (Port.H));
203 Raise_Error ("set: cannot get comm state");
204 end if;
205
206 Com_Settings.BaudRate := DWORD (Data_Rate_Value (Rate));
207 Com_Settings.fParity := 1;
208 Com_Settings.fBinary := Bits1 (System.Win32.TRUE);
209 Com_Settings.fOutxDsrFlow := 0;
210 Com_Settings.fDsrSensitivity := 0;
211 Com_Settings.fDtrControl := OSC.DTR_CONTROL_ENABLE;
212 Com_Settings.fInX := 0;
213 Com_Settings.fRtsControl := OSC.RTS_CONTROL_ENABLE;
214
215 case Flow is
216 when None =>
217 Com_Settings.fOutX := 0;
218 Com_Settings.fOutxCtsFlow := 0;
219
220 when RTS_CTS =>
221 Com_Settings.fOutX := 0;
222 Com_Settings.fOutxCtsFlow := 1;
223
224 when Xon_Xoff =>
225 Com_Settings.fOutX := 1;
226 Com_Settings.fOutxCtsFlow := 0;
227 end case;
228
229 Com_Settings.fAbortOnError := 0;
230 Com_Settings.ByteSize := BYTE (C_Bits (Bits));
231 Com_Settings.Parity := BYTE (C_Parity (Parity));
232 Com_Settings.StopBits := BYTE (C_Stop_Bits (Stop_Bits));
233
234 Success := SetCommState (HANDLE (Port.H), Com_Settings'Access);
235
236 if Success = Win32.FALSE then
237 Success := CloseHandle (HANDLE (Port.H));
238 Raise_Error ("cannot set comm state");
239 end if;
240
241 -- Set the timeout status, to honor our spec with respect to read
242 -- timeouts. Always disconnect write timeouts.
243
244 -- Blocking reads - no timeout at all
245
246 if Block then
247 Com_Time_Out := (others => 0);
248
249 -- Non-blocking reads and null timeout - immediate return with what we
250 -- have - set ReadIntervalTimeout to MAXDWORD.
251
252 elsif Timeout = 0.0 then
253 Com_Time_Out :=
254 (ReadIntervalTimeout => DWORD'Last,
255 others => 0);
256
257 -- Non-blocking reads with timeout - set total read timeout accordingly
258
259 else
260 Com_Time_Out :=
261 (ReadTotalTimeoutConstant => DWORD (1000 * Timeout),
262 others => 0);
263 end if;
264
265 Success :=
266 SetCommTimeouts
267 (hFile => HANDLE (Port.H),
268 lpCommTimeouts => Com_Time_Out'Access);
269
270 if Success = Win32.FALSE then
271 Raise_Error ("cannot set the timeout");
272 end if;
273 end Set;
274
275 ------------
276 -- To_Ada --
277 ------------
278
279 procedure To_Ada (Port : out Serial_Port; Fd : Serial_Port_Descriptor) is
280 begin
281 Port.H := Fd;
282 end To_Ada;
283
284 -----------
285 -- Write --
286 -----------
287
288 overriding procedure Write
289 (Port : in out Serial_Port;
290 Buffer : Stream_Element_Array)
291 is
292 Success : BOOL;
293 Temp_Last : aliased DWORD;
294
295 begin
296 if Port.H = -1 then
297 Raise_Error ("write: port not opened", 0);
298 end if;
299
300 Success :=
301 WriteFile
302 (hFile => HANDLE (Port.H),
303 lpBuffer => Buffer'Address,
304 nNumberOfBytesToWrite => DWORD (Buffer'Length),
305 lpNumberOfBytesWritten => Temp_Last'Access,
306 lpOverlapped => null);
307
308 if Success = Win32.FALSE
309 or else Stream_Element_Offset (Temp_Last) /= Buffer'Length
310 then
311 Raise_Error ("failed to write data");
312 end if;
313 end Write;
314
315 end GNAT.Serial_Communications;