:pserver:cvs@pserver.samba.org:/cvsroot - gnokii - Sun Nov 25 22:56 CET 2001
[gnokii.git] / common / devices / unixserial.c
1 /*
2   
3   $Id$
4
5   G N O K I I
6
7   A Linux/Unix toolset and driver for Nokia mobile phones.
8
9   Copyright (C) 1999, 2000 Hugh Blemings & Pavel Janík ml.
10
11   Released under the terms of the GNU GPL, see file COPYING for more details.
12
13   $Log$
14   Revision 1.1.1.1  2001/11/25 21:59:09  short
15   :pserver:cvs@pserver.samba.org:/cvsroot - gnokii - Sun Nov 25 22:56 CET 2001
16
17   Revision 1.10  2001/11/14 10:46:12  pkot
18   Small cleanup with __unices__
19
20   Revision 1.9  2001/09/14 12:15:28  pkot
21   Cleanups from 0.3.3 (part1)
22
23   Revision 1.8  2001/08/20 23:27:37  pkot
24   Add hardware shakehand to the link layer (Manfred Jonsson)
25
26   Revision 1.7  2001/07/03 00:03:36  pkot
27   Small fixes to let gnokii compile and work under solaris (thanks to Artur Kubiak)
28
29   Revision 1.6  2001/03/21 23:36:04  chris
30   Added the statemachine
31   This will break gnokii --identify and --monitor except for 6210/7110
32
33   Revision 1.5  2001/03/19 23:43:46  pkot
34   Solaris/ *BSD '#if defined' cleanup
35
36   Revision 1.4  2001/03/13 01:21:38  pkot
37   *BSD updates (Bert Driehuis)
38
39   Revision 1.3  2001/03/06 22:27:46  pkot
40   Misc docs and Makefiles updates and cleanups
41
42   Revision 1.2  2001/02/21 19:57:05  chris
43   More fiddling with the directory layout
44
45 */
46
47 #include "misc.h"
48
49 /* Do not compile this file under Win32 systems. */
50
51 #ifndef WIN32
52
53 #include <stdio.h>
54 #include <fcntl.h>
55 #include <sys/ioctl.h>
56 #include <string.h>
57
58 #include <termios.h>
59 #include "devices/unixserial.h"
60
61 #ifdef HAVE_SYS_IOCTL_COMPAT_H
62   #include <sys/ioctl_compat.h>
63 #endif
64
65 #ifdef HAVE_SYS_SELECT_H
66 #include <sys/select.h>
67 #endif
68
69 /* If the target operating system does not have cfsetspeed, we can emulate
70    it. */
71
72 #ifndef HAVE_CFSETSPEED
73   #if defined(HAVE_CFSETISPEED) && defined(HAVE_CFSETOSPEED)
74      #define cfsetspeed(t, speed) \
75      (cfsetispeed(t, speed) || cfsetospeed(t, speed))
76   #else
77     static int cfsetspeed(struct termios *t, int speed) {
78     #ifdef HAVE_TERMIOS_CSPEED
79       t->c_ispeed = speed;
80       t->c_ospeed = speed;
81     #else
82       t->c_cflag |= speed;
83     #endif
84       return 0;
85     }
86   #endif
87 #endif
88
89 #ifndef O_NONBLOCK
90   #define O_NONBLOCK  0
91 #endif
92
93 /* Structure to backup the setting of the terminal. */
94
95 struct termios serial_termios;
96
97 /* Open the serial port and store the settings. */
98
99 int serial_open(__const char *__file, int __oflag) {
100
101   int __fd;
102   int retcode;
103
104   __fd = open(__file, __oflag);
105   if (__fd == -1) {
106     perror("Gnokii serial_open: open");
107     return (-1);
108   }
109
110   retcode=tcgetattr(__fd, &serial_termios);
111   if(retcode==-1) {
112     perror("Gnokii serial_open:tcgetattr");
113     /* Don't call serial_close since serial_termios is not valid */
114     close(__fd);
115     return(-1);
116   }
117   
118   return __fd;
119 }
120
121 /* Close the serial port and restore old settings. */
122
123 int serial_close(int __fd) {
124
125   if (__fd >= 0)
126     tcsetattr(__fd, TCSANOW, &serial_termios);
127
128   return (close(__fd));
129 }
130
131 /* Open a device with standard options. */
132
133 int serial_opendevice(__const char *__file, int __with_odd_parity, int __with_async, int __with_hw_handshake) {
134
135   int fd;
136   int retcode;
137   struct termios tp;
138
139   /* Open device */
140
141   fd = serial_open(__file, O_RDWR | O_NOCTTY | O_NONBLOCK);
142
143   if (fd < 0) 
144     return fd;
145
146   /* Allow process/thread to receive SIGIO */
147
148 #if !(__unices__)
149   retcode = fcntl(fd, F_SETOWN, getpid());
150   if (retcode == -1){
151     perror("Gnokii serial_opendevice: fnctl(F_SETOWN)");
152     serial_close(fd);
153     return(-1);
154   }
155 #endif
156
157   /* Make filedescriptor asynchronous. */
158
159   if (__with_async) {
160     retcode=fcntl(fd, F_SETFL, FASYNC);
161     if (retcode == -1){
162       perror("Gnokii serial_opendevice: fnctl(F_SETFL)");
163       serial_close(fd);
164       return(-1);
165     }
166   }
167   
168   /* Initialise the port settings */
169
170   memcpy(&tp, &serial_termios, sizeof(struct termios));
171
172   /* Set port settings for canonical input processing */
173
174   tp.c_cflag = B0 | CS8 | CLOCAL | CREAD;
175   if (__with_odd_parity) {
176     tp.c_cflag |= (PARENB | PARODD);
177     tp.c_iflag = 0;
178   }
179   else
180     tp.c_iflag = IGNPAR;
181   if (__with_hw_handshake)
182     tp.c_cflag |= CRTSCTS;
183   else
184     tp.c_cflag &= ~CRTSCTS;
185
186   tp.c_oflag = 0;
187   tp.c_lflag = 0;
188   tp.c_cc[VMIN] = 1;
189   tp.c_cc[VTIME] = 0;
190
191   retcode=tcflush(fd, TCIFLUSH);
192   if (retcode == -1) {
193     perror("Gnokii serial_opendevice: tcflush");
194     serial_close(fd);
195     return(-1);
196   }
197
198   retcode=tcsetattr(fd, TCSANOW, &tp);
199   if (retcode == -1){
200     perror("Gnokii serial_opendevice: tcsetattr");
201     serial_close(fd);
202     return(-1);
203   }
204
205   return fd;
206 }
207
208 /* Set the DTR and RTS bit of the serial device. */
209
210 void serial_setdtrrts(int __fd, int __dtr, int __rts) {
211
212   unsigned int flags;
213
214   flags = TIOCM_DTR;
215
216   if (__dtr)
217     ioctl(__fd, TIOCMBIS, &flags);
218   else
219     ioctl(__fd, TIOCMBIC, &flags);
220
221   flags = TIOCM_RTS;
222
223   if (__rts)
224     ioctl(__fd, TIOCMBIS, &flags);
225   else
226     ioctl(__fd, TIOCMBIC, &flags);
227 }
228
229
230 int serial_select(int fd, struct timeval *timeout) {
231
232   fd_set readfds;
233
234   FD_ZERO(&readfds);
235   FD_SET(fd, &readfds);
236
237   return (select(fd + 1, &readfds, NULL, NULL, timeout));
238
239 }
240
241
242 /* Change the speed of the serial device. */
243
244 void serial_changespeed(int __fd, int __speed) {
245
246 #ifndef SGTTY
247   struct termios t;
248 #else
249   struct sgttyb t;
250 #endif
251
252   int speed=B9600;
253
254   switch (__speed) {
255     case 9600:   speed = B9600;   break;
256     case 19200:  speed = B19200;  break;
257     case 38400:  speed = B38400;  break;
258     case 57600:  speed = B57600;  break;
259     case 115200: speed = B115200; break;
260   }
261
262 #ifndef SGTTY
263   tcgetattr(__fd, &t);
264
265   // This is not needed! We set up the speed via cfsetspeed
266   //  t.c_cflag &= ~CBAUD;
267   //  t.c_cflag |= speed;
268   if (cfsetspeed(&t, speed) == -1)
269         dprintf(_("Serial port speed setting failed\n"));
270
271   tcsetattr(__fd, TCSADRAIN, &t);
272 #else
273   ioctl(__fd, TIOCGETP, &t);
274
275   t.sg_ispeed = speed;
276   t.sg_ospeed = speed;
277
278   ioctl(__fd, TIOCSETN, &t);
279 #endif
280 }
281
282 /* Read from serial device. */
283
284 size_t serial_read(int __fd, __ptr_t __buf, size_t __nbytes) {
285
286   return (read(__fd, __buf, __nbytes));
287 }
288
289 /* Write to serial device. */
290
291 size_t serial_write(int __fd, __const __ptr_t __buf, size_t __n) {
292         
293         return (write(__fd, __buf, __n));
294 }
295
296 #endif  /* WIN32 */