summaryrefslogtreecommitdiffabout
path: root/gammu/emb/common/device/serial/ser_w32.c
Unidiff
Diffstat (limited to 'gammu/emb/common/device/serial/ser_w32.c') (more/less context) (ignore whitespace changes)
-rw-r--r--gammu/emb/common/device/serial/ser_w32.c340
1 files changed, 340 insertions, 0 deletions
diff --git a/gammu/emb/common/device/serial/ser_w32.c b/gammu/emb/common/device/serial/ser_w32.c
new file mode 100644
index 0000000..9fa0135
--- a/dev/null
+++ b/gammu/emb/common/device/serial/ser_w32.c
@@ -0,0 +1,340 @@
1/* (c) 2002-2004 by Marcin Wiacek */
2/* based on some work from Gnokii, MSDN and others */
3
4#include "../../gsmstate.h"
5
6#ifdef GSM_ENABLE_SERIALDEVICE
7#ifdef WIN32
8
9#include <windows.h>
10#include <string.h>
11#include <stdio.h>
12#include <io.h>
13#include <memory.h>
14
15#include "../../gsmcomon.h"
16#include "ser_w32.h"
17
18static GSM_Error serial_close(GSM_StateMachine *s)
19{
20 GSM_Device_SerialData *d = &s->Device.Data.Serial;
21
22 /* Disables all monitored events for device */
23 SetCommMask(d->hPhone, 0);
24
25 /* Discards all characters from input/output buffer and terminates
26 * pending read/write operations
27 */
28 PurgeComm(d->hPhone, PURGE_TXABORT | PURGE_RXABORT |
29 PURGE_TXCLEAR | PURGE_RXCLEAR);
30
31 /* Clears the DTR (data-terminal-ready) signal */
32 EscapeCommFunction(d->hPhone, CLRDTR);
33
34 /* Restores old settings */
35 if (SetCommState(d->hPhone, &d->old_settings)==0) {
36 GSM_OSErrorInfo(s, "SetCommState in serial_close");
37 }
38
39 /* Closes device */
40 if (CloseHandle(d->hPhone)==0) {
41 GSM_OSErrorInfo(s, "CloseHandle in serial_close");
42 }
43
44 return ERR_NONE;
45}
46
47static GSM_Error serial_open (GSM_StateMachine *s)
48{
49 GSM_Device_SerialData *d = &s->Device.Data.Serial;
50 DCB dcb;
51 unsigned char DeviceName[80],DeviceName2[80];
52 int i;
53#ifdef GSM_ENABLE_FBUS2DKU5
54 HKEY hKey;
55 DWORD DeviceNameLen, KeyNameLen;
56 unsigned char KeyName[100];
57#endif
58
59 strcpy(DeviceName2,s->CurrentConfig->Device);
60
61#ifdef GSM_ENABLE_FBUS2DKU5
62 if (s->ConnectionType == GCT_FBUS2DKU5) {
63 smprintf(s,"Reading DKU5 device\n");
64 DeviceName2[0] = 0;
65 if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, "HARDWARE\\DEVICEMAP\\SERIALCOMM", 0, KEY_QUERY_VALUE, &hKey) != ERROR_SUCCESS) {
66 smprintf(s,"Error opening key\n");
67 return ERR_DEVICENOTWORK;
68 }
69 i = 0;
70 while(1) {
71 DeviceNameLen = 80;
72 KeyNameLen = 100;
73 if (RegEnumValue(hKey,i,KeyName,&KeyNameLen,NULL,NULL,DeviceName2,&DeviceNameLen) != ERROR_SUCCESS) {
74 smprintf(s,"Error reading key value\n");
75 return ERR_DEVICENOTWORK;
76 }
77 // smprintf(s,"Key name is %s, value is %s\n",KeyName,DeviceName2);
78 if (!strncmp(KeyName,"\\Device\\AtmelVirtualPort",24)) break;
79 i++;
80 }
81 RegCloseKey(hKey);
82 if (strlen(DeviceName2) == 0) return ERR_DEVICENOTWORK;
83 smprintf(s,"DKU5 device is \"%s\"\n",DeviceName2);
84 //nodriver
85 }
86#endif
87
88 if ((s->ConnectionType == GCT_FBUS2DKU5) ||
89 (!strncmp(DeviceName2,"com",3) && strlen(DeviceName2)>3)) {
90 sprintf(DeviceName,"\\\\.\\COM%i",atoi(DeviceName2+3));
91 } else {
92 strcpy(DeviceName,DeviceName2);
93 }
94
95 smprintf(s,"Device is %s\n",DeviceName);
96
97 /* Allows for reading/writing, no device sharing */
98 d->hPhone = CreateFile(DeviceName,
99 GENERIC_READ | GENERIC_WRITE,
100 0,
101 0,
102 OPEN_EXISTING,
103 FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED,
104 NULL);
105
106 if (d->hPhone == INVALID_HANDLE_VALUE) {
107 i = GetLastError();
108 GSM_OSErrorInfo(s, "CreateFile in serial_open");
109 if (i == 2) return ERR_DEVICENOTWORK; //can't find specified file
110 if (i == 5) return ERR_DEVICEBUSY; //access denied
111 if (i == 31) return ERR_DEVICENOTWORK; //attached device not working
112 if (i == 123) return ERR_DEVICENOTEXIST;
113 return ERR_DEVICEOPENERROR;
114 }
115
116 d->old_settings.DCBlength = sizeof(DCB);
117 if (GetCommState(d->hPhone, &d->old_settings)==0) {
118 GSM_OSErrorInfo(s, "ReadDevice in serial_open");
119 return ERR_DEVICEREADERROR;
120 }
121
122 /* When char will be received, we will receive notifications */
123 SetCommMask(d->hPhone, EV_RXCHAR);
124
125 /* Sets size for input/output buffer */
126 SetupComm(d->hPhone, 4096, 4096);
127
128 /* Discards all characters from input/output buffer and terminates
129 * pending read/write operations
130 */
131 PurgeComm(d->hPhone, PURGE_TXABORT | PURGE_RXABORT |
132 PURGE_TXCLEAR | PURGE_RXCLEAR);
133
134 memcpy(&dcb, &d->old_settings, sizeof(DCB));
135
136 dcb.ByteSize = 8;
137 dcb.Parity = NOPARITY;
138 dcb.StopBits = ONESTOPBIT;
139
140 /* No Xon/Xof flow control */
141 // dcb.fOutX = false;
142 // dcb.fInX = false;
143
144 /* Hardware flow control */
145 //dcb.fOutxDsrFlow = true;
146 //dcb.fOutxCtsFlow = true;
147 //dcb.fDtrControl = DTR_CONTROL_HANDSHAKE;
148 //dcb.fRtsControl = RTS_CONTROL_HANDSHAKE;
149
150 /* Initialise the port settings */
151 if (SetCommState(d->hPhone, &dcb)==0) {
152 GSM_OSErrorInfo(s, "WriteDevice in serial_open");
153 return ERR_DEVICEOPENERROR;
154 }
155
156 return ERR_NONE;
157}
158
159static GSM_Error serial_setparity (GSM_StateMachine *s, bool parity)
160{
161 DCB dcb;
162 GSM_Device_SerialData *d = &s->Device.Data.Serial;
163
164 dcb.DCBlength = sizeof(DCB);
165 if (GetCommState(d->hPhone, &dcb)==0) {
166 GSM_OSErrorInfo(s, "ReadDevice in serial_setparity");
167 return ERR_DEVICEREADERROR;
168 }
169
170 if (parity) {
171 dcb.Parity = ODDPARITY;
172 } else {
173 dcb.Parity = NOPARITY;
174 }
175
176 if (SetCommState(d->hPhone, &dcb)==0) {
177 GSM_OSErrorInfo(s, "WriteDevice in serial_setparity");
178 return ERR_DEVICEPARITYERROR;
179 }
180
181 return ERR_NONE;
182}
183
184static GSM_Error serial_setdtrrts(GSM_StateMachine *s, bool dtr, bool rts)
185{
186 DCB dcb;
187 GSM_Device_SerialData *d = &s->Device.Data.Serial;
188
189 dcb.DCBlength = sizeof(DCB);
190 if (GetCommState(d->hPhone, &dcb)==0) {
191 GSM_OSErrorInfo(s, "ReadDevice in serial_setdtrrts");
192 return ERR_DEVICEREADERROR;
193 }
194
195 dcb.fOutxDsrFlow = 0;
196 dcb.fDtrControl = DTR_CONTROL_DISABLE;
197 if (dtr) dcb.fDtrControl = DTR_CONTROL_ENABLE;
198
199 dcb.fOutxCtsFlow = 0;
200 dcb.fRtsControl = RTS_CONTROL_DISABLE;
201 if (rts) dcb.fRtsControl = RTS_CONTROL_ENABLE;
202
203 /* no software (Xon/Xof) flow control */
204 dcb.fInX = dcb.fOutX = 0;
205
206 if (SetCommState(d->hPhone, &dcb)==0) {
207 GSM_OSErrorInfo(s, "WriteDevice in serial_setdtrrts");
208 return ERR_DEVICEDTRRTSERROR;
209 }
210
211 /* the rest of function checks, if setting was really done */
212
213 dcb.DCBlength = sizeof(DCB);
214 GetCommState(d->hPhone, &dcb);
215
216 dbgprintf("Serial device:");
217 dbgprintf(" DTR is ");
218 switch (dcb.fDtrControl) {
219 case DTR_CONTROL_ENABLE : dbgprintf("up"); break;
220 case DTR_CONTROL_DISABLE : dbgprintf("down"); break;
221 case DTR_CONTROL_HANDSHAKE : dbgprintf("handshake"); break;
222 }
223 dbgprintf(", RTS is ");
224 switch (dcb.fRtsControl) {
225 case RTS_CONTROL_ENABLE : dbgprintf("up"); break;
226 case RTS_CONTROL_DISABLE : dbgprintf("down"); break;
227 case RTS_CONTROL_HANDSHAKE : dbgprintf("handshake"); break;
228 case RTS_CONTROL_TOGGLE : dbgprintf("toggle"); break;
229 }
230 dbgprintf("\n");
231 if ( dtr && dcb.fDtrControl != DTR_CONTROL_ENABLE ) return ERR_DEVICEDTRRTSERROR;
232 if (!dtr && dcb.fDtrControl != DTR_CONTROL_DISABLE) return ERR_DEVICEDTRRTSERROR;
233 if ( rts && dcb.fRtsControl != RTS_CONTROL_ENABLE ) return ERR_DEVICEDTRRTSERROR;
234 if (!rts && dcb.fRtsControl != RTS_CONTROL_DISABLE) return ERR_DEVICEDTRRTSERROR;
235
236 return ERR_NONE;
237}
238
239static GSM_Error serial_setspeed(GSM_StateMachine *s, int speed)
240{
241 DCB dcb;
242 GSM_Device_SerialData *d = &s->Device.Data.Serial;
243
244 dcb.DCBlength = sizeof(DCB);
245 if (GetCommState(d->hPhone, &dcb)==0) {
246 GSM_OSErrorInfo(s, "ReadDevice in serial_setspeed");
247 return ERR_DEVICEREADERROR;
248 }
249
250 dcb.BaudRate = speed;
251
252 if (SetCommState(d->hPhone, &dcb)==0) {
253 GSM_OSErrorInfo(s, "WriteDevice in serial_setspeed");
254 return ERR_DEVICECHANGESPEEDERROR;
255 }
256
257 return ERR_NONE;
258}
259
260static int serial_read(GSM_StateMachine *s, void *buf, size_t nbytes)
261{
262 COMSTAT ComStat;
263 DWORD ErrorFlags, Length;
264 GSM_Device_SerialData *d = &s->Device.Data.Serial;
265
266 /* Gets information about a communications error and
267 * current status of device
268 */
269 ClearCommError(d->hPhone, &ErrorFlags, &ComStat);
270 Length = ComStat.cbInQue;
271
272 /* Nothing to read */
273 if (Length <= 0) return Length;
274
275 /* Read without problems */
276 if (ReadFile(d->hPhone, buf, Length, &Length, &d->osRead)) return Length;
277
278 if (GetLastError() != ERROR_IO_PENDING) {
279 GSM_OSErrorInfo(s, "serial_read1");
280 Length = 0;
281 ClearCommError(d->hPhone, &ErrorFlags, &ComStat);
282 return Length;
283 }
284
285 while(1) {
286 if (GetOverlappedResult(d->hPhone,&d->osRead, &Length, TRUE)) break;
287 if (GetLastError() != ERROR_IO_INCOMPLETE) {
288 GSM_OSErrorInfo(s, "serial_read2");
289 /* an error occurred, try to recover */
290 ClearCommError(d->hPhone, &ErrorFlags, &ComStat);
291 break;
292 }
293 }
294 return Length;
295}
296
297static int serial_write(GSM_StateMachine *s, void *buf, size_t nbytes)
298{
299 DWORD BytesWritten,ErrorFlags,BytesSent=0;
300 COMSTAT ComStat;
301 GSM_Device_SerialData *d = &s->Device.Data.Serial;
302
303 if (WriteFile(d->hPhone, buf, nbytes, &BytesSent, &d->osWrite)) return BytesSent;
304
305 if (GetLastError() != ERROR_IO_PENDING) {
306 GSM_OSErrorInfo(s, "serial_write1");
307 ClearCommError(d->hPhone, &ErrorFlags, &ComStat);
308 return BytesSent;
309 }
310
311 while (1) {
312 if (GetOverlappedResult(d->hPhone, &d->osWrite, &BytesWritten, TRUE)) break;
313 if (GetLastError() != ERROR_IO_INCOMPLETE) {
314 GSM_OSErrorInfo(s, "serial_write2");
315 ClearCommError(d->hPhone, &ErrorFlags, &ComStat);
316 break;
317 }
318 BytesSent += BytesWritten;
319 }
320 BytesSent += BytesWritten;
321
322 return BytesSent;
323}
324
325GSM_Device_Functions SerialDevice = {
326 serial_open,
327 serial_close,
328 serial_setparity,
329 serial_setdtrrts,
330 serial_setspeed,
331 serial_read,
332 serial_write
333};
334
335#endif
336#endif
337
338/* How should editor hadle tabs in this file? Add editor commands here.
339 * vim: noexpandtab sw=8 ts=8 sts=8:
340 */