summaryrefslogtreecommitdiffabout
path: root/gammu/emb/common/device/serial/ser_unx.c
Unidiff
Diffstat (limited to 'gammu/emb/common/device/serial/ser_unx.c') (more/less context) (ignore whitespace changes)
-rw-r--r--gammu/emb/common/device/serial/ser_unx.c291
1 files changed, 291 insertions, 0 deletions
diff --git a/gammu/emb/common/device/serial/ser_unx.c b/gammu/emb/common/device/serial/ser_unx.c
new file mode 100644
index 0000000..2a87b11
--- a/dev/null
+++ b/gammu/emb/common/device/serial/ser_unx.c
@@ -0,0 +1,291 @@
1/* (c) 2002-2004 by Marcin Wiacek */
2/* locking device and settings all speeds by Michal Cihar */
3
4#include "../../gsmstate.h"
5
6#ifdef GSM_ENABLE_SERIALDEVICE
7#ifndef WIN32
8#ifndef DJGPP
9
10#include <sys/file.h>
11#include <sys/time.h>
12#include <string.h>
13#include <termios.h>
14#include <errno.h>
15
16#include "../../gsmcomon.h"
17#include "ser_unx.h"
18
19static GSM_Error serial_close(GSM_StateMachine *s)
20{
21 GSM_Device_SerialData *d = &s->Device.Data.Serial;
22
23 /* Restores old settings */
24 tcsetattr(d->hPhone, TCSANOW, &d->old_settings);
25
26 /* Closes device */
27 close(d->hPhone);
28
29 return ERR_NONE;
30}
31
32#ifndef O_NONBLOCK
33# define O_NONBLOCK 0
34#endif
35
36static GSM_Error serial_open (GSM_StateMachine *s)
37{
38 GSM_Device_SerialData *d = &s->Device.Data.Serial;
39 struct termios t;
40 int i;
41
42 /* O_NONBLOCK MUST is required to avoid waiting for DCD */
43 d->hPhone = open(s->CurrentConfig->Device, O_RDWR | O_NOCTTY | O_NONBLOCK);
44 if (d->hPhone < 0) {
45 i = errno;
46 GSM_OSErrorInfo(s,"open in serial_open");
47 if (i == 2) return ERR_DEVICENOTEXIST; //no such file or directory
48 if (i == 13) return ERR_DEVICENOPERMISSION;//permission denied
49 return ERR_DEVICEOPENERROR;
50 }
51
52#ifdef TIOCEXCL
53 /* open() calls from other applications shall fail now */
54 ioctl(d->hPhone, TIOCEXCL, (char *) 0);
55#endif
56
57 if (tcgetattr(d->hPhone, &d->old_settings) == -1) {
58 close(d->hPhone);
59 GSM_OSErrorInfo(s,"tcgetattr in serial_open");
60 return ERR_DEVICEREADERROR;
61 }
62
63 if (tcflush(d->hPhone, TCIOFLUSH) == -1) {
64 serial_close(s);
65 GSM_OSErrorInfo(s,"tcflush in serial_open");
66 return ERR_DEVICEOPENERROR;
67 }
68
69 memcpy(&t, &d->old_settings, sizeof(struct termios));
70
71 /* Opening without parity */
72 t.c_iflag = IGNPAR;
73 t.c_oflag = 0;
74 /* disconnect line, 8 bits, enable receiver,
75 * ignore modem lines,lower modem line after disconnect
76 */
77 t.c_cflag = B0 | CS8 | CREAD | CLOCAL | HUPCL;
78 /* enable hardware (RTS/CTS) flow control (NON POSIX) */
79 /* t.c_cflag |= CRTSCTS; */
80 t.c_lflag = 0;
81 t.c_cc[VMIN] = 1;
82 t.c_cc[VTIME] = 0;
83
84 if (tcsetattr(d->hPhone, TCSANOW, &t) == -1) {
85 serial_close(s);
86 GSM_OSErrorInfo(s,"tcsetattr in serial_open");
87 return ERR_DEVICEOPENERROR;
88 }
89
90 /* Making file descriptor asynchronous. */
91 if (fcntl(d->hPhone, F_SETFL, FASYNC | FNONBLOCK) == -1) {
92 serial_close(s);
93 GSM_OSErrorInfo(s,"fcntl in serial_open");
94 return ERR_DEVICEOPENERROR;
95 }
96
97 return ERR_NONE;
98}
99
100static GSM_Error serial_setparity(GSM_StateMachine *s, bool parity)
101{
102 GSM_Device_SerialData *d = &s->Device.Data.Serial;
103 struct termios t;
104
105 if (tcgetattr(d->hPhone, &t)) {
106 GSM_OSErrorInfo(s,"tcgetattr in serial_setparity");
107 return ERR_DEVICEREADERROR;
108 }
109
110 if (parity) {
111 t.c_cflag |= (PARENB | PARODD);
112 t.c_iflag = 0;
113 } else {
114 t.c_iflag = IGNPAR;
115 }
116
117 if (tcsetattr(d->hPhone, TCSANOW, &t) == -1){
118 serial_close(s);
119 GSM_OSErrorInfo(s,"tcsetattr in serial_setparity");
120 return ERR_DEVICEPARITYERROR;
121 }
122
123 return ERR_NONE;
124}
125
126static GSM_Error serial_setdtrrts(GSM_StateMachine *s, bool dtr, bool rts)
127{
128 GSM_Device_SerialData *d = &s->Device.Data.Serial;
129 struct termios t;
130 unsigned int flags;
131
132 if (tcgetattr(d->hPhone, &t)) {
133 GSM_OSErrorInfo(s,"tcgetattr in serial_setdtrrts");
134 return ERR_DEVICEREADERROR;
135 }
136
137#ifdef CRTSCTS
138 /* Disabling hardware flow control */
139 t.c_cflag &= ~CRTSCTS;
140#endif
141
142 if (tcsetattr(d->hPhone, TCSANOW, &t) == -1) {
143 serial_close(s);
144 GSM_OSErrorInfo(s,"tcsetattr in serial_setdtrrts");
145 return ERR_DEVICEDTRRTSERROR;
146 }
147
148 flags = TIOCM_DTR;
149 if (dtr) {
150 ioctl(d->hPhone, TIOCMBIS, &flags);
151 } else {
152 ioctl(d->hPhone, TIOCMBIC, &flags);
153 }
154
155 flags = TIOCM_RTS;
156 if (rts) {
157 ioctl(d->hPhone, TIOCMBIS, &flags);
158 } else {
159 ioctl(d->hPhone, TIOCMBIC, &flags);
160 }
161
162 flags = 0;
163 ioctl(d->hPhone, TIOCMGET, &flags);
164
165 dbgprintf("Serial device:");
166 dbgprintf(" DTR is %s", flags&TIOCM_DTR?"up":"down");
167 dbgprintf(", RTS is %s", flags&TIOCM_RTS?"up":"down");
168 dbgprintf(", CAR is %s", flags&TIOCM_CAR?"up":"down");
169 dbgprintf(", CTS is %s\n", flags&TIOCM_CTS?"up":"down");
170 if (((flags&TIOCM_DTR)==TIOCM_DTR) != dtr) return ERR_DEVICEDTRRTSERROR;
171 if (((flags&TIOCM_RTS)==TIOCM_RTS) != rts) return ERR_DEVICEDTRRTSERROR;
172
173 return ERR_NONE;
174}
175
176static GSM_Error serial_setspeed(GSM_StateMachine *s, int speed)
177{
178 GSM_Device_SerialData *d = &s->Device.Data.Serial;
179 struct termios t;
180 int speed2 = B19200;
181
182 if (tcgetattr(d->hPhone, &t)) {
183 GSM_OSErrorInfo(s,"tcgetattr in serial_setspeed");
184 return ERR_DEVICEREADERROR;
185 }
186
187 smprintf(s, "Setting speed to %d\n", speed);
188
189 switch (speed) {
190 case 50: speed2 = B50; break;
191 case 75: speed2 = B75; break;
192 case 110: speed2 = B110; break;
193 case 134: speed2 = B134; break;
194 case 150: speed2 = B150; break;
195 case 200: speed2 = B200; break;
196 case 300: speed2 = B300; break;
197 case 600: speed2 = B600; break;
198 case 1200: speed2 = B1200; break;
199 case 1800: speed2 = B1800; break;
200 case 2400: speed2 = B2400; break;
201 case 4800: speed2 = B4800; break;
202 case 9600: speed2 = B9600; break;
203 case 19200: speed2 = B19200;break;
204 case 38400: speed2 = B38400;break;
205 case 57600: speed2 = B57600;break;
206 case 115200: speed2 = B115200;break;
207 case 230400: speed2 = B230400;break;
208 case 460800: speed2 = B460800;break;
209 case 500000: speed2 = B500000;break;
210 case 576000: speed2 = B576000;break;
211 case 921600: speed2 = B921600;break;
212 case 1000000: speed2 = B1000000;break;
213 case 1152000: speed2 = B1152000;break;
214 case 1500000: speed2 = B1500000;break;
215 case 2000000: speed2 = B2000000;break;
216 case 2500000: speed2 = B2500000;break;
217 case 3000000: speed2 = B3000000;break;
218 case 3500000: speed2 = B3500000;break;
219 case 4000000: speed2 = B4000000; break;
220 }
221
222 /* This should work on all systems because it is done according to POSIX */
223 cfsetispeed(&t, speed2);
224 cfsetospeed(&t, speed2);
225
226 if (tcsetattr(d->hPhone, TCSADRAIN, &t) == -1) {
227 serial_close(s);
228 GSM_OSErrorInfo(s,"tcsetattr in serial_setspeed");
229 return ERR_DEVICECHANGESPEEDERROR;
230 }
231
232 return ERR_NONE;
233}
234
235static int serial_read(GSM_StateMachine *s, void *buf, size_t nbytes)
236{
237 GSM_Device_SerialData *d = &s->Device.Data.Serial;
238 struct timeval timeout2;
239 fd_set readfds;
240 int actual = 0;
241
242 FD_ZERO(&readfds);
243 FD_SET(d->hPhone, &readfds);
244
245 timeout2.tv_sec = 0;
246 timeout2.tv_usec = 1;
247
248 if (select(d->hPhone+1, &readfds, NULL, NULL, &timeout2)) {
249 actual = read(d->hPhone, buf, nbytes);
250 if (actual == -1) GSM_OSErrorInfo(s,"serial_read");
251 }
252 return actual;
253}
254
255static int serial_write(GSM_StateMachine *s, void *buf, size_t nbytes)
256{
257 GSM_Device_SerialData *d = &s->Device.Data.Serial;
258 int ret;
259 size_t actual = 0;
260
261 do {
262 ret = write(d->hPhone, (unsigned char *)buf, nbytes - actual);
263 if (ret < 0 && errno == EAGAIN) continue;
264 if (ret < 0) {
265 if (actual != nbytes) GSM_OSErrorInfo(s,"serial_write");
266 return actual;
267 }
268 actual += ret;
269 buf += ret;
270 if (s->ConnectionType == GCT_FBUS2PL2303) my_sleep(1);
271 } while (actual < nbytes);
272 return actual;
273}
274
275GSM_Device_Functions SerialDevice = {
276 serial_open,
277 serial_close,
278 serial_setparity,
279 serial_setdtrrts,
280 serial_setspeed,
281 serial_read,
282 serial_write
283};
284
285#endif
286#endif
287#endif
288
289/* How should editor hadle tabs in this file? Add editor commands here.
290 * vim: noexpandtab sw=8 ts=8 sts=8:
291 */