This commit was manufactured by cvs2svn to create tag 'bp_uc_works1'.
[gnokii.git] / common / devices / device.c
1 /*
2
3   G N O K I I
4
5   A Linux/Unix toolset and driver for Nokia mobile phones.
6
7   Released under the terms of the GNU GPL, see file COPYING for more details.
8
9 */
10
11 #ifndef WIN32
12   #include "devices/unixserial.h"
13   #include "devices/unixirda.h"
14   #include "devices/tekram.h"
15   #include <sys/ioctl.h>
16   #include <pthread.h>
17   #include <termios.h>
18   #include <signal.h>
19   #include <errno.h>
20 #else
21   #include <windows.h>
22   #include "devices/winserial.h"
23 #endif
24
25 #include "gsm-api.h"
26 #include "devices/device.h"
27
28 #include <string.h>
29
30 #ifdef VC6
31   /* for VC6 make scripts save VERSION constant in mversion.h file */
32   #include "mversion.h"
33 #endif
34
35 char PortDevice[GSM_MAX_DEVICE_NAME_LENGTH]={0x00};
36
37 bool duringwrite;
38
39 #ifndef WIN32
40
41 //pthread_t Thread;
42 #if defined(__svr4__) || defined(__FreeBSD__)
43   pthread_t selThread;
44 #endif
45
46 int device_portfd = -1;
47
48 /*
49  * Structure to store the filedescriptor we use.
50  *
51  */
52 int device_getfd(void)
53 {
54   return device_portfd;
55 }
56
57 int device_open(__const char *__file, int __with_odd_parity) {
58
59   switch (CurrentConnectionType) {
60     case GCT_Tekram:
61       device_portfd = tekram_open(__file);
62       break;
63     case GCT_Irda:
64       device_portfd = irda_open();
65       break;
66     default:
67       device_portfd = serial_opendevice(__file, __with_odd_parity, true, false);
68       break;
69   }
70   
71   return (device_portfd >= 0);
72 }
73
74 void device_close(void)
75 {
76   AppendLogText("CLOSE\n",false);
77
78   /* Now wait for thread to terminate. */
79   //pthread_join(Thread, NULL);
80
81   switch (CurrentConnectionType) {
82     case GCT_Tekram: tekram_close(device_portfd); break;
83     case GCT_Irda  :   irda_close(device_portfd); break;
84     default        : serial_close(device_portfd); break;
85   }
86
87   PortDevice[0]=0x00;
88 }
89
90 void device_reset(void) {
91 }
92
93 void device_setdtrrts(int __dtr, int __rts)
94 {
95   switch (CurrentConnectionType) {
96     case GCT_Tekram:
97     case GCT_Irda:
98       break;
99     default:
100       serial_setdtrrts(device_portfd, __dtr, __rts);
101 #ifdef DEBUG
102       device_dumpserial();
103 #endif
104       break;
105   }
106 }
107
108 void device_changespeed(int __speed)
109 {
110   switch (CurrentConnectionType) {
111     case GCT_Irda:
112       break;
113     case GCT_Tekram:
114       tekram_changespeed(device_portfd, __speed);
115       break;
116     default:
117       serial_changespeed(device_portfd, __speed);
118 #ifdef DEBUG
119       fprintf(stdout,_("Serial device: changing speed to %i\n"),__speed);
120 #endif
121       break;
122   }
123 }
124
125 size_t device_read(__ptr_t __buf, size_t __nbytes)
126 {
127   switch (CurrentConnectionType) {
128     case GCT_Tekram: return (tekram_read(device_portfd, __buf, __nbytes)); break;
129     case GCT_Irda  : return (  irda_read(device_portfd, __buf, __nbytes)); break;
130     default        : return (serial_read(device_portfd, __buf, __nbytes)); break;
131   }
132 }
133
134 size_t device_write(__const __ptr_t __buf, size_t __n) {
135   u8 buffer[300];
136   size_t mysize;
137   
138   while (duringwrite) {}
139
140   memcpy(buffer,__buf,__n);
141   AppendLog(buffer,__n,true);
142
143   duringwrite=true;
144   switch (CurrentConnectionType) {
145     case GCT_Irda  : mysize =   irda_write(device_portfd, __buf, __n); break;
146     case GCT_Tekram: mysize = tekram_write(device_portfd, __buf, __n); break;      
147     default        : mysize = serial_write(device_portfd, __buf, __n); break;
148   }
149   duringwrite=false;
150   return mysize;
151 }
152
153 #ifdef DEBUG
154 void device_dumpserial(void)
155 {
156   int PortFD;
157   unsigned int Flags=0;
158
159   PortFD = device_getfd();
160
161   ioctl(PortFD, TIOCMGET, &Flags);
162
163   fprintf(stdout, _("Serial device:"));
164   fprintf(stdout,  _(" DTR is %s"), Flags&TIOCM_DTR?_("up"):_("down"));
165   fprintf(stdout, _(", RTS is %s"), Flags&TIOCM_RTS?_("up"):_("down"));
166   fprintf(stdout, _(", CAR is %s"), Flags&TIOCM_CAR?_("up"):_("down"));
167   fprintf(stdout, _(", CTS is %s\n"), Flags&TIOCM_CTS?_("up"):_("down"));
168 }
169 #endif /* DEBUG */
170
171 void SigHandler(int status)
172 {
173
174   unsigned char buffer[2048];
175
176   int count, res;
177
178   res = device_read(buffer, 255);
179
180   for (count = 0; count < res ; count ++) {
181     Protocol->StateMachine(buffer[count]);
182   }
183 }
184
185
186 #if defined(__svr4__) || defined(__FreeBSD__)
187 /* thread for handling incoming data */
188 void SelectLoop() {
189   int err;
190   fd_set readfds;
191   struct timeval timeout;
192
193   FD_ZERO(&readfds);
194   FD_SET(device_portfd,&readfds);
195   /* set timeout to 15 seconds */
196   timeout.tv_sec=15;
197   timeout.tv_usec=0;
198   while (!CurrentRequestTerminate) {
199     err=select(device_portfd+1,&readfds,NULL,NULL,&timeout);
200     if ( err > 0 ) {
201       /* call singal handler to process incoming data */
202       SigHandler(0);
203       /* refresh timeout, just for linux :-( */
204       /* required for irda */
205       timeout.tv_sec=15;
206     } else {
207       if (err == -1)
208       perror("Error in SelectLoop");
209     }
210   }
211 }
212 #endif
213
214 bool StartConnection (char *port_device, bool with_odd_parity, GSM_ConnectionType con)
215 {
216   int result;
217
218   char text[100];
219
220 #if defined(__svr4__) || defined(__FreeBSD__)
221   int rtn;
222 #else
223   struct sigaction sig_io;
224 #endif
225
226 #ifdef DEBUG
227       if ((strstr(GSM_Info->IrdaModels,"decode")!=NULL) &&  (CurrentConnectionType == GCT_Irda))
228        {
229          printf("DEBUG and Irda decode Model -> not realy open ;-)\n");
230          return true;
231        }
232 #endif 
233
234   if (PortDevice[0]!=0x00) return true;
235
236   duringwrite=false;
237   
238   strncpy(PortDevice, port_device, GSM_MAX_DEVICE_NAME_LENGTH);
239
240 #ifdef DEBUG
241   fprintf(stdout,_("Opening \"%s\" device...\n"),PortDevice);
242 #endif
243
244   strcpy(text,"\n\n\nMygnokii ");
245   sprintf(text+strlen(text), "%s",VERSION);
246   strcpy(text+strlen(text),"\n");
247   AppendLogText(text,false);
248
249   strcpy(text,"Port ");
250   strcpy(text+strlen(text),PortDevice);
251   strcpy(text+strlen(text),"\n");
252   AppendLogText(text,false);
253
254   strcpy(text,"Connection ");
255   switch (con) {
256     case GCT_FBUS    :strcpy(text+strlen(text),"FBUS");break;
257     case GCT_Infrared:strcpy(text+strlen(text),"infrared");break;
258     case GCT_Irda    :strcpy(text+strlen(text),"irda sockets");break;
259     case GCT_MBUS    :strcpy(text+strlen(text),"MBUS");break;
260     case GCT_DLR3    :strcpy(text+strlen(text),"DLR3");break;
261     case GCT_Tekram  :strcpy(text+strlen(text),"Tekram");break;
262     case GCT_AT      :strcpy(text+strlen(text),"AT");break;
263     default          :strcpy(text+strlen(text),"unknown");break;
264   }
265   strcpy(text+strlen(text),"\n");
266   AppendLogText(text,false);
267
268   /* Ralf Thelen: In this moment there is NO method of communication,
269    which require keepalive packets and GSM->KeepAlive is
270    always NULL_KeepAlive, I comment this thread, */
271
272   /* Create and start main thread. */
273 //  rtn = pthread_create(&Thread, NULL,(void*)GSM->KeepAlive, (void *)NULL);
274 //
275 //  if (rtn != 0) {
276 //    fprintf(stdout,_("Error\n"));  
277 //    return false;
278 //  }
279
280 #if defined(__svr4__) || defined(__FreeBSD__)
281 #else
282         /* Set up and install handler before enabling async IO on port. */
283         sig_io.sa_handler = SigHandler;
284         sig_io.sa_flags = 0;
285         sigaction (SIGIO, &sig_io, NULL);
286 #endif
287
288     /* Open device. */
289     result = device_open(PortDevice, with_odd_parity);
290     
291     if (!result) {
292       fprintf(stdout,_("Error\n"));  
293       return false;
294     }
295
296 #if defined(__svr4__) || defined(__FreeBSD__)
297     /* create a thread to handle incoming data from mobile phone */
298     rtn=pthread_create(&selThread,NULL,(void*)SelectLoop,(void*)NULL);
299     if (rtn != 0) {
300       fprintf(stdout,_("Error\n"));  
301       return false;
302     }
303 #endif
304
305   return true;
306 }
307
308 /* ---------------- RTH:   #ifdef WIN32 ------------------ */  
309
310 #else
311
312   extern HANDLE hPhone;
313
314 void device_close(void)
315 {
316   AppendLogText("CLOSE\n",false);
317
318   CloseConnection();
319
320   PortDevice[0]=0x00;
321 }
322
323 #ifdef DEBUG
324 void device_dumpserial(void)
325 {
326   DCB dcb;
327   
328   dcb.DCBlength = sizeof(DCB);
329   GetCommState(hPhone, &dcb);
330
331   fprintf(stdout, _("Serial device:"));
332   fprintf(stdout,  _(" DTR is "));
333   switch (dcb.fDtrControl) {
334     case DTR_CONTROL_ENABLE   : fprintf(stdout,  _("up"));       break;
335     case DTR_CONTROL_DISABLE  : fprintf(stdout,  _("down"));     break;
336     case DTR_CONTROL_HANDSHAKE: fprintf(stdout,  _("handshake"));break;
337   }
338   fprintf(stdout, _(", RTS is "));
339   switch (dcb.fRtsControl) {
340     case RTS_CONTROL_ENABLE   : fprintf(stdout,  _("up\n"));       break;
341     case RTS_CONTROL_DISABLE  : fprintf(stdout,  _("down\n"));     break;
342     case RTS_CONTROL_HANDSHAKE: fprintf(stdout,  _("handshake\n"));break;
343     case RTS_CONTROL_TOGGLE   : fprintf(stdout,  _("toggle\n"));   break;
344   }
345 }
346 #endif /* DEBUG */
347
348 void device_setdtrrts(int __dtr, int __rts)
349 {
350   DCB dcb;
351   
352   dcb.DCBlength = sizeof(DCB);
353   GetCommState(hPhone, &dcb);
354
355   if (__dtr==1) dcb.fDtrControl = DTR_CONTROL_ENABLE;
356            else dcb.fDtrControl = DTR_CONTROL_DISABLE;
357
358    if (__rts==1) dcb.fRtsControl = RTS_CONTROL_ENABLE;
359             else dcb.fRtsControl = RTS_CONTROL_DISABLE;
360
361    SetCommState(hPhone, &dcb);
362
363 #ifdef DEBUG
364   device_dumpserial();
365 #endif
366 }
367
368 void device_changespeed(int __speed)
369 {
370
371   DCB dcb;
372
373   dcb.DCBlength = sizeof(DCB);
374   GetCommState(hPhone, &dcb);
375
376   switch (__speed) {
377     case 115200: dcb.BaudRate=CBR_115200; break;
378     case 19200 : dcb.BaudRate=CBR_19200;  break;
379     case 9600  : dcb.BaudRate=CBR_9600;   break;
380    }
381    
382    SetCommState(hPhone, &dcb);
383
384 #ifdef DEBUG
385    fprintf(stdout,_("Serial device: changing speed to %i\n"),__speed);
386 #endif
387 }
388
389 bool StartConnection (char *port_device, bool with_odd_parity, GSM_ConnectionType con)
390 {
391   DCB dcb;
392   char text[100];
393
394   int rtn;
395
396   if (PortDevice[0]!=0x00) return true;  
397
398   duringwrite=false;
399   strncpy(PortDevice, port_device, GSM_MAX_DEVICE_NAME_LENGTH);
400
401 #ifdef DEBUG
402   fprintf(stdout,_("Opening \"%s\" device...\n"),PortDevice);
403 #endif
404
405   strcpy(text,"\n\n\nMygnokii ");
406   sprintf(text+strlen(text), "%s",VERSION);
407   strcpy(text+strlen(text),"\n");
408   AppendLogText(text,false);
409
410   strcpy(text,"Port ");
411   strcpy(text+strlen(text),PortDevice);
412   strcpy(text+strlen(text),"\n");
413   AppendLogText(text,false);
414
415   strcpy(text,"Connection ");
416   switch (con) {
417     case GCT_FBUS    :strcpy(text+strlen(text),"FBUS");break;
418     case GCT_Infrared:strcpy(text+strlen(text),"infrared");break;
419     case GCT_Irda    :strcpy(text+strlen(text),"irda sockets");break;
420     case GCT_MBUS    :strcpy(text+strlen(text),"MBUS");break;
421     case GCT_DLR3    :strcpy(text+strlen(text),"DLR3");break;
422     case GCT_Tekram  :strcpy(text+strlen(text),"Tekram");break;
423     case GCT_AT      :strcpy(text+strlen(text),"AT");break;
424     default          :strcpy(text+strlen(text),"unknown");break;
425   }
426   strcpy(text+strlen(text),"\n");
427   AppendLogText(text,false);
428
429   CurrentDisableKeepAlive = true;
430
431   /* Create and start main thread. */
432   rtn = ! OpenConnection(PortDevice, Protocol->StateMachine, GSM->KeepAlive);
433
434   if (rtn != 0) {
435
436     fprintf(stdout,_("Error\n"));  
437     return false;
438   } else {
439     CurrentDisableKeepAlive = false;
440   }
441
442   if (with_odd_parity) {
443     dcb.DCBlength = sizeof(DCB);
444     GetCommState(hPhone, &dcb);
445
446     dcb.Parity=ODDPARITY;
447
448     SetCommState(hPhone, &dcb);
449   }
450   
451   return true;
452 }
453
454 size_t device_write(const __ptr_t __buf, size_t __n) {
455   int i;
456   while (duringwrite) {}
457   duringwrite=true;
458   AppendLog(__buf,__n,true);
459   i=WriteCommBlock(__buf,__n);
460   duringwrite=false;
461   if (i) return __n; else return 0;
462 }
463
464 #endif /*WIN32*/