1 ------------------------------------------------------------------------------
3 -- GNAT COMPILER COMPONENTS --
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 --
9 -- Copyright (C) 2007-2012, AdaCore --
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. --
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. --
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/>. --
27 -- GNAT was originally developed by the GNAT team at New York University. --
28 -- Extensive contributions were provided by Ada Core Technologies Inc. --
30 ------------------------------------------------------------------------------
32 -- This is the GNU/Linux implementation of this package
34 with Ada
.Streams
; use Ada
.Streams
;
36 with Ada
.Unchecked_Deallocation
;
38 with System
; use System
;
39 with System
.Communication
; use System
.Communication
;
40 with System
.CRTL
; use System
.CRTL
;
41 with System
.OS_Constants
;
43 with GNAT
.OS_Lib
; use GNAT
.OS_Lib
;
45 package body GNAT
.Serial_Communications
is
47 package OSC
renames System
.OS_Constants
;
49 use type Interfaces
.C
.unsigned
;
51 type Port_Data
is new int
;
53 subtype unsigned
is Interfaces
.C
.unsigned
;
54 subtype char
is Interfaces
.C
.char
;
55 subtype unsigned_char
is Interfaces
.C
.unsigned_char
;
57 function fcntl
(fd
: int
; cmd
: int
; value
: int
) return int
;
58 pragma Import
(C
, fcntl
, "fcntl");
60 C_Data_Rate
: constant array (Data_Rate
) of unsigned
:=
68 B115200
=> OSC
.B115200
);
70 C_Bits
: constant array (Data_Bits
) of unsigned
:=
71 (CS7
=> OSC
.CS7
, CS8
=> OSC
.CS8
);
73 C_Stop_Bits
: constant array (Stop_Bits_Number
) of unsigned
:=
74 (One
=> 0, Two
=> OSC
.CSTOPB
);
76 C_Parity
: constant array (Parity_Check
) of unsigned
:=
78 Odd
=> OSC
.PARENB
or OSC
.PARODD
,
81 procedure Raise_Error
(Message
: String; Error
: Integer := Errno
);
82 pragma No_Return
(Raise_Error
);
88 function Name
(Number
: Positive) return Port_Name
is
89 N
: constant Natural := Number
- 1;
90 N_Img
: constant String := Natural'Image (N
);
92 return Port_Name
("/dev/ttyS" & N_Img
(N_Img
'First + 1 .. N_Img
'Last));
100 (Port
: out Serial_Port
;
105 C_Name
: constant String := String (Name
) & ASCII
.NUL
;
109 if Port
.H
= null then
110 Port
.H
:= new Port_Data
;
113 Port
.H
.all := Port_Data
(open
114 (C_Name
(C_Name
'First)'Address, int
(O_RDWR
+ O_NOCTTY
+ O_NDELAY
)));
116 if Port
.H
.all = -1 then
117 Raise_Error
("open: open failed");
120 -- By default we are in blocking mode
122 Res
:= fcntl
(int
(Port
.H
.all), F_SETFL
, 0);
125 Raise_Error
("open: fcntl failed");
133 procedure Raise_Error
(Message
: String; Error
: Integer := Errno
) is
135 raise Serial_Error
with Message
& " (" & Integer'Image (Error
) & ')';
142 overriding
procedure Read
143 (Port
: in out Serial_Port
;
144 Buffer
: out Stream_Element_Array
;
145 Last
: out Stream_Element_Offset
)
147 Len
: constant size_t
:= Buffer
'Length;
151 if Port
.H
= null then
152 Raise_Error
("read: port not opened", 0);
155 Res
:= read
(Integer (Port
.H
.all), Buffer
'Address, Len
);
158 Raise_Error
("read failed");
161 Last
:= Last_Index
(Buffer
'First, size_t
(Res
));
170 Rate
: Data_Rate
:= B9600
;
171 Bits
: Data_Bits
:= CS8
;
172 Stop_Bits
: Stop_Bits_Number
:= One
;
173 Parity
: Parity_Check
:= None
;
174 Block
: Boolean := True;
175 Local
: Boolean := True;
176 Flow
: Flow_Control
:= None
;
177 Timeout
: Duration := 10.0)
181 type termios
is record
186 c_line
: unsigned_char
;
187 c_cc
: Interfaces
.C
.char_array
(0 .. 31);
191 pragma Convention
(C
, termios
);
193 function tcgetattr
(fd
: int
; termios_p
: Address
) return int
;
194 pragma Import
(C
, tcgetattr
, "tcgetattr");
197 (fd
: int
; action
: int
; termios_p
: Address
) return int
;
198 pragma Import
(C
, tcsetattr
, "tcsetattr");
200 function tcflush
(fd
: int
; queue_selector
: int
) return int
;
201 pragma Import
(C
, tcflush
, "tcflush");
206 pragma Warnings
(Off
, Res
);
207 -- Warnings off, since we don't always test the result
210 if Port
.H
= null then
211 Raise_Error
("set: port not opened", 0);
214 -- Get current port settings
216 Res
:= tcgetattr
(int
(Port
.H
.all), Current
'Address);
218 -- Change settings now
220 Current
.c_cflag
:= C_Data_Rate
(Rate
)
222 or C_Stop_Bits
(Stop_Bits
)
225 Current
.c_iflag
:= 0;
226 Current
.c_lflag
:= 0;
227 Current
.c_oflag
:= 0;
230 Current
.c_cflag
:= Current
.c_cflag
or CLOCAL
;
237 Current
.c_cflag
:= Current
.c_cflag
or CRTSCTS
;
239 Current
.c_iflag
:= Current
.c_iflag
or IXON
;
242 Current
.c_ispeed
:= Data_Rate_Value
(Rate
);
243 Current
.c_ospeed
:= Data_Rate_Value
(Rate
);
244 Current
.c_cc
(VMIN
) := char
'Val (0);
245 Current
.c_cc
(VTIME
) := char
'Val (Natural (Timeout
* 10));
249 Res
:= tcflush
(int
(Port
.H
.all), TCIFLUSH
);
250 Res
:= tcsetattr
(int
(Port
.H
.all), TCSANOW
, Current
'Address);
254 Res
:= fcntl
(int
(Port
.H
.all), F_SETFL
, (if Block
then 0 else FNDELAY
));
257 Raise_Error
("set: fcntl failed");
265 overriding
procedure Write
266 (Port
: in out Serial_Port
;
267 Buffer
: Stream_Element_Array
)
269 Len
: constant size_t
:= Buffer
'Length;
273 if Port
.H
= null then
274 Raise_Error
("write: port not opened", 0);
277 Res
:= write
(int
(Port
.H
.all), Buffer
'Address, Len
);
280 Raise_Error
("write failed");
283 pragma Assert
(size_t
(Res
) = Len
);
290 procedure Close
(Port
: in out Serial_Port
) is
291 procedure Unchecked_Free
is
292 new Unchecked_Deallocation
(Port_Data
, Port_Data_Access
);
295 pragma Unreferenced
(Res
);
298 if Port
.H
/= null then
299 Res
:= close
(int
(Port
.H
.all));
300 Unchecked_Free
(Port
.H
);
304 end GNAT
.Serial_Communications
;