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.c | 27 |
1 files changed, 18 insertions, 9 deletions
diff --git a/gammu/emb/common/device/serial/ser_unx.c b/gammu/emb/common/device/serial/ser_unx.c index 69c7515..18b5f6f 100644 --- a/gammu/emb/common/device/serial/ser_unx.c +++ b/gammu/emb/common/device/serial/ser_unx.c | |||
@@ -1,22 +1,31 @@ | |||
1 | /* (c) 2002-2004 by Marcin Wiacek */ | 1 | /* (c) 2002-2004 by Marcin Wiacek */ |
2 | /* locking device and settings all speeds by Michal Cihar */ | 2 | /* locking device and settings all speeds by Michal Cihar */ |
3 | /* based on some work from Gnokii (www.gnokii.org) | 3 | /* based on some work from Gnokii (www.gnokii.org) |
4 | * (C) 1999-2000 Hugh Blemings & Pavel Janik ml. (C) 2001-2004 Pawel Kot | 4 | * (C) 1999-2000 Hugh Blemings & Pavel Janik ml. (C) 2001-2004 Pawel Kot |
5 | * GNU GPL version 2 or later | 5 | * GNU GPL version 2 or later |
6 | */ | 6 | */ |
7 | /* Due to a problem in the source code management, the names of some of | ||
8 | * the authors have unfortunately been lost. We do not mean to belittle | ||
9 | * their efforts and hope they will contact us to see their names | ||
10 | * properly added to the Copyright notice above. | ||
11 | * Having published their contributions under the terms of the GNU | ||
12 | * General Public License (GPL) [version 2], the Copyright of these | ||
13 | * authors will remain respected by adhering to the license they chose | ||
14 | * to publish their code under. | ||
15 | */ | ||
7 | 16 | ||
8 | #include "../../gsmstate.h" | 17 | #include "../../gsmstate.h" |
9 | 18 | ||
10 | #ifdef GSM_ENABLE_SERIALDEVICE | 19 | #ifdef GSM_ENABLE_SERIALDEVICE |
11 | #ifndef WIN32 | 20 | #ifndef WIN32 |
12 | #ifndef DJGPP | 21 | #ifndef DJGPP |
13 | 22 | ||
14 | #include <sys/file.h> | 23 | #include <sys/file.h> |
15 | #include <sys/time.h> | 24 | #include <sys/time.h> |
16 | #include <string.h> | 25 | #include <string.h> |
17 | #include <termios.h> | 26 | #include <termios.h> |
18 | #include <errno.h> | 27 | #include <errno.h> |
19 | 28 | ||
20 | #include "../../gsmcomon.h" | 29 | #include "../../gsmcomon.h" |
21 | #include "ser_unx.h" | 30 | #include "ser_unx.h" |
22 | 31 | ||
@@ -47,34 +56,34 @@ | |||
47 | static GSM_Error serial_close(GSM_StateMachine *s) | 56 | static GSM_Error serial_close(GSM_StateMachine *s) |
48 | { | 57 | { |
49 | GSM_Device_SerialData *d = &s->Device.Data.Serial; | 58 | GSM_Device_SerialData *d = &s->Device.Data.Serial; |
50 | 59 | ||
51 | /* Restores old settings */ | 60 | /* Restores old settings */ |
52 | tcsetattr(d->hPhone, TCSANOW, &d->old_settings); | 61 | tcsetattr(d->hPhone, TCSANOW, &d->old_settings); |
53 | 62 | ||
54 | /* Closes device */ | 63 | /* Closes device */ |
55 | close(d->hPhone); | 64 | close(d->hPhone); |
56 | 65 | ||
57 | return ERR_NONE; | 66 | return ERR_NONE; |
58 | } | 67 | } |
59 | 68 | ||
60 | static GSM_Error serial_open (GSM_StateMachine *s) | 69 | static GSM_Error serial_open (GSM_StateMachine *s) |
61 | { | 70 | { |
62 | GSM_Device_SerialData *d = &s->Device.Data.Serial; | 71 | GSM_Device_SerialData *d = &s->Device.Data.Serial; |
63 | struct termios t; | 72 | struct termios t; |
64 | int i; | 73 | int i; |
65 | 74 | ||
66 | /* O_NONBLOCK MUST is required to avoid waiting for DCD */ | 75 | /* O_NONBLOCK MUST is required to avoid waiting for DCD */ |
67 | d->hPhone = open(s->CurrentConfig->Device, O_RDWR | O_NOCTTY | O_NONBLOCK); | 76 | d->hPhone = open(s->CurrentConfig->Device, O_RDWR | O_NOCTTY | O_NONBLOCK); |
68 | if (d->hPhone < 0) { | 77 | if (d->hPhone < 0) { |
69 | i = errno; | 78 | i = errno; |
70 | GSM_OSErrorInfo(s,"open in serial_open"); | 79 | GSM_OSErrorInfo(s,"open in serial_open"); |
71 | if (i == 2) return ERR_DEVICENOTEXIST; //no such file or directory | 80 | if (i == 2) return ERR_DEVICENOTEXIST; //no such file or directory |
72 | if (i == 13) return ERR_DEVICENOPERMISSION;//permission denied | 81 | if (i == 13) return ERR_DEVICENOPERMISSION;//permission denied |
73 | return ERR_DEVICEOPENERROR; | 82 | return ERR_DEVICEOPENERROR; |
74 | } | 83 | } |
75 | 84 | ||
76 | #ifdef TIOCEXCL | 85 | #ifdef TIOCEXCL |
77 | /* open() calls from other applications shall fail now */ | 86 | /* open() calls from other applications shall fail now */ |
78 | ioctl(d->hPhone, TIOCEXCL, (char *) 0); | 87 | ioctl(d->hPhone, TIOCEXCL, (char *) 0); |
79 | #endif | 88 | #endif |
80 | 89 | ||
@@ -111,60 +120,60 @@ static GSM_Error serial_open (GSM_StateMachine *s) | |||
111 | return ERR_DEVICEOPENERROR; | 120 | return ERR_DEVICEOPENERROR; |
112 | } | 121 | } |
113 | 122 | ||
114 | /* Making file descriptor asynchronous. */ | 123 | /* Making file descriptor asynchronous. */ |
115 | if (fcntl(d->hPhone, F_SETFL, FASYNC | FNONBLOCK) == -1) { | 124 | if (fcntl(d->hPhone, F_SETFL, FASYNC | FNONBLOCK) == -1) { |
116 | serial_close(s); | 125 | serial_close(s); |
117 | GSM_OSErrorInfo(s,"fcntl in serial_open"); | 126 | GSM_OSErrorInfo(s,"fcntl in serial_open"); |
118 | return ERR_DEVICEOPENERROR; | 127 | return ERR_DEVICEOPENERROR; |
119 | } | 128 | } |
120 | 129 | ||
121 | return ERR_NONE; | 130 | return ERR_NONE; |
122 | } | 131 | } |
123 | 132 | ||
124 | static GSM_Error serial_setparity(GSM_StateMachine *s, bool parity) | 133 | static GSM_Error serial_setparity(GSM_StateMachine *s, bool parity) |
125 | { | 134 | { |
126 | GSM_Device_SerialData *d = &s->Device.Data.Serial; | 135 | GSM_Device_SerialData *d = &s->Device.Data.Serial; |
127 | struct termios t; | 136 | struct termios t; |
128 | 137 | ||
129 | if (tcgetattr(d->hPhone, &t)) { | 138 | if (tcgetattr(d->hPhone, &t)) { |
130 | GSM_OSErrorInfo(s,"tcgetattr in serial_setparity"); | 139 | GSM_OSErrorInfo(s,"tcgetattr in serial_setparity"); |
131 | return ERR_DEVICEREADERROR; | 140 | return ERR_DEVICEREADERROR; |
132 | } | 141 | } |
133 | 142 | ||
134 | if (parity) { | 143 | if (parity) { |
135 | t.c_cflag |= (PARENB | PARODD); | 144 | t.c_cflag |= (PARENB | PARODD); |
136 | t.c_iflag = 0; | 145 | t.c_iflag = 0; |
137 | } else { | 146 | } else { |
138 | t.c_iflag = IGNPAR; | 147 | t.c_iflag = IGNPAR; |
139 | } | 148 | } |
140 | 149 | ||
141 | if (tcsetattr(d->hPhone, TCSANOW, &t) == -1){ | 150 | if (tcsetattr(d->hPhone, TCSANOW, &t) == -1){ |
142 | serial_close(s); | 151 | serial_close(s); |
143 | GSM_OSErrorInfo(s,"tcsetattr in serial_setparity"); | 152 | GSM_OSErrorInfo(s,"tcsetattr in serial_setparity"); |
144 | return ERR_DEVICEPARITYERROR; | 153 | return ERR_DEVICEPARITYERROR; |
145 | } | 154 | } |
146 | 155 | ||
147 | return ERR_NONE; | 156 | return ERR_NONE; |
148 | } | 157 | } |
149 | 158 | ||
150 | static GSM_Error serial_setdtrrts(GSM_StateMachine *s, bool dtr, bool rts) | 159 | static GSM_Error serial_setdtrrts(GSM_StateMachine *s, bool dtr, bool rts) |
151 | { | 160 | { |
152 | GSM_Device_SerialData *d = &s->Device.Data.Serial; | 161 | GSM_Device_SerialData *d = &s->Device.Data.Serial; |
153 | struct termios t; | 162 | struct termios t; |
154 | unsigned int flags; | 163 | unsigned int flags; |
155 | 164 | ||
156 | if (tcgetattr(d->hPhone, &t)) { | 165 | if (tcgetattr(d->hPhone, &t)) { |
157 | GSM_OSErrorInfo(s,"tcgetattr in serial_setdtrrts"); | 166 | GSM_OSErrorInfo(s,"tcgetattr in serial_setdtrrts"); |
158 | return ERR_DEVICEREADERROR; | 167 | return ERR_DEVICEREADERROR; |
159 | } | 168 | } |
160 | 169 | ||
161 | #ifdef CRTSCTS | 170 | #ifdef CRTSCTS |
162 | /* Disabling hardware flow control */ | 171 | /* Disabling hardware flow control */ |
163 | t.c_cflag &= ~CRTSCTS; | 172 | t.c_cflag &= ~CRTSCTS; |
164 | #endif | 173 | #endif |
165 | 174 | ||
166 | if (tcsetattr(d->hPhone, TCSANOW, &t) == -1) { | 175 | if (tcsetattr(d->hPhone, TCSANOW, &t) == -1) { |
167 | serial_close(s); | 176 | serial_close(s); |
168 | GSM_OSErrorInfo(s,"tcsetattr in serial_setdtrrts"); | 177 | GSM_OSErrorInfo(s,"tcsetattr in serial_setdtrrts"); |
169 | return ERR_DEVICEDTRRTSERROR; | 178 | return ERR_DEVICEDTRRTSERROR; |
170 | } | 179 | } |
@@ -251,53 +260,53 @@ static GSM_Error serial_setspeed(GSM_StateMachine *s, int speed) | |||
251 | cfsetispeed(&t, speed2); | 260 | cfsetispeed(&t, speed2); |
252 | cfsetospeed(&t, speed2); | 261 | cfsetospeed(&t, speed2); |
253 | 262 | ||
254 | if (tcsetattr(d->hPhone, TCSADRAIN, &t) == -1) { | 263 | if (tcsetattr(d->hPhone, TCSADRAIN, &t) == -1) { |
255 | serial_close(s); | 264 | serial_close(s); |
256 | GSM_OSErrorInfo(s,"tcsetattr in serial_setspeed"); | 265 | GSM_OSErrorInfo(s,"tcsetattr in serial_setspeed"); |
257 | return ERR_DEVICECHANGESPEEDERROR; | 266 | return ERR_DEVICECHANGESPEEDERROR; |
258 | } | 267 | } |
259 | 268 | ||
260 | return ERR_NONE; | 269 | return ERR_NONE; |
261 | } | 270 | } |
262 | 271 | ||
263 | static int serial_read(GSM_StateMachine *s, void *buf, size_t nbytes) | 272 | static int serial_read(GSM_StateMachine *s, void *buf, size_t nbytes) |
264 | { | 273 | { |
265 | GSM_Device_SerialData *d = &s->Device.Data.Serial; | 274 | GSM_Device_SerialData *d = &s->Device.Data.Serial; |
266 | struct timeval timeout2; | 275 | struct timeval timeout2; |
267 | fd_set readfds; | 276 | fd_set readfds; |
268 | int actual = 0; | 277 | int actual = 0; |
269 | 278 | ||
270 | FD_ZERO(&readfds); | 279 | FD_ZERO(&readfds); |
271 | FD_SET(d->hPhone, &readfds); | 280 | FD_SET(d->hPhone, &readfds); |
272 | 281 | ||
273 | timeout2.tv_sec = 0; | 282 | timeout2.tv_sec = 0; |
274 | timeout2.tv_usec = 1; | 283 | timeout2.tv_usec = 1; |
275 | 284 | ||
276 | if (select(d->hPhone+1, &readfds, NULL, NULL, &timeout2)) { | 285 | if (select(d->hPhone+1, &readfds, NULL, NULL, &timeout2)) { |
277 | actual = read(d->hPhone, buf, nbytes); | 286 | actual = read(d->hPhone, buf, nbytes); |
278 | if (actual == -1) GSM_OSErrorInfo(s,"serial_read"); | 287 | if (actual == -1) GSM_OSErrorInfo(s,"serial_read"); |
279 | } | 288 | } |
280 | return actual; | 289 | return actual; |
281 | } | 290 | } |
282 | 291 | ||
283 | static int serial_write(GSM_StateMachine *s, void *buf, size_t nbytes) | 292 | static int serial_write(GSM_StateMachine *s, void *buf, size_t nbytes) |
284 | { | 293 | { |
285 | GSM_Device_SerialData *d = &s->Device.Data.Serial; | 294 | GSM_Device_SerialData *d = &s->Device.Data.Serial; |
286 | int ret; | 295 | int ret; |
287 | size_t actual = 0; | 296 | size_t actual = 0; |
288 | 297 | ||
289 | do { | 298 | do { |
290 | ret = write(d->hPhone, (unsigned char *)buf, nbytes - actual); | 299 | ret = write(d->hPhone, (unsigned char *)buf, nbytes - actual); |
291 | if (ret < 0 && errno == EAGAIN) continue; | 300 | if (ret < 0 && errno == EAGAIN) continue; |
292 | if (ret < 0) { | 301 | if (ret < 0) { |
293 | if (actual != nbytes) GSM_OSErrorInfo(s,"serial_write"); | 302 | if (actual != nbytes) GSM_OSErrorInfo(s,"serial_write"); |
294 | return actual; | 303 | return actual; |
295 | } | 304 | } |
296 | actual += ret; | 305 | actual += ret; |
297 | buf += ret; | 306 | buf += ret; |
298 | if (s->ConnectionType == GCT_FBUS2PL2303) my_sleep(1); | 307 | if (s->ConnectionType == GCT_FBUS2PL2303) my_sleep(1); |
299 | } while (actual < nbytes); | 308 | } while (actual < nbytes); |
300 | return actual; | 309 | return actual; |
301 | } | 310 | } |
302 | 311 | ||
303 | GSM_Device_Functions SerialDevice = { | 312 | GSM_Device_Functions SerialDevice = { |