5 A Linux/Unix toolset and driver for Nokia mobile phones.
7 Released under the terms of the GNU GPL, see file COPYING for more details.
12 #include "devices/unixserial.h"
13 #include "devices/unixirda.h"
14 #include "devices/tekram.h"
15 #include <sys/ioctl.h>
22 #include "devices/winserial.h"
26 #include "devices/device.h"
27 #include "files/cfgreader.h"
32 /* for VC6 make scripts save VERSION constant in mversion.h file */
36 char PortDevice[GSM_MAX_DEVICE_NAME_LENGTH]={0x00};
45 #if defined(__svr4__) || defined(__FreeBSD__)
49 int device_portfd = -1;
51 #define max_buf_len 128
52 #define lock_path "/var/lock/LCK.."
54 /* Lock the device. Return allocated string with a lock name */
55 char *lock_device(const char* port)
57 char *lock_file = NULL;
58 char buffer[max_buf_len];
59 const char *aux = rindex(port, '/');
60 int fd, len = strlen(aux) + strlen(lock_path);
62 /* Remove leading '/' */
66 memset(buffer, 0, sizeof(buffer));
67 lock_file = calloc(len + 1, 1);
69 fprintf(stderr, _("Out of memory error while locking device\n"));
72 /* I think we don't need to use strncpy, as we should have enough
73 * buffer due to strlen results
75 strcpy(lock_file, lock_path);
76 strcat(lock_file, aux);
78 /* Check for the stale lockfile.
79 * The code taken from minicom by Miquel van Smoorenburg */
80 if ((fd = open(lock_file, O_RDONLY)) >= 0) {
81 char buf[max_buf_len];
84 n = read(fd, buf, sizeof(buf) - 1);
89 /* Kermit-style lockfile. */
94 sscanf(buf, "%d", &pid);
96 if (pid > 0 && kill((pid_t)pid, 0) < 0 && errno == ESRCH) {
97 fprintf(stderr, _("Lockfile %s is stale. Overriding it..\n"), lock_file);
99 if (unlink(lock_file) == -1) {
100 fprintf(stderr, _("Overriding failed, please check the permissions\n"));
101 fprintf(stderr, _("Cannot lock device\n"));
105 fprintf(stderr, _("Device already locked.\n"));
109 /* this must not happen. because we could open the file */
110 /* no wrong permissions are set. only reason could be */
111 /* flock/lockf or a empty lockfile due to a broken binary */
112 /* which is more likely (like gnokii 0.4.0pre11 ;-) */
114 fprintf(stderr, _("Unable to read lockfile %s.\n"), lock_file);
115 fprintf(stderr, _("Please check for reason and remove the lockfile by hand.\n"));
116 fprintf(stderr, _("Cannot lock device\n"));
121 /* Try to create a new file, with 0644 mode */
122 fd = open(lock_file, O_CREAT | O_EXCL | O_WRONLY, 0644);
125 fprintf(stderr, _("Device seems to be locked by unknown process\n"));
126 else if (errno == EACCES)
127 fprintf(stderr, _("Please check permission on lock directory\n"));
128 else if (errno == ENOENT)
129 fprintf(stderr, _("Cannot create lockfile %s. Please check for existence of path"), lock_file);
132 sprintf(buffer, "%10ld gnokii\n", (long)getpid());
133 write(fd, buffer, strlen(buffer));
141 /* Removes lock and frees memory */
142 bool unlock_device(char *lock_file)
147 // fprintf(stderr, _("Cannot unlock device\n"));
150 err = unlink(lock_file);
156 * Structure to store the filedescriptor we use.
159 int device_getfd(void)
161 return device_portfd;
164 int device_open(__const char *__file, int __with_odd_parity) {
165 struct CFG_Header *cfg_info;
168 cfg_info=CFG_FindGnokiirc();
169 if (cfg_info!=NULL) {
170 aux = CFG_Get(cfg_info, "global", "use_locking");
172 if (!strcmp(aux, "yes")) {
173 lockfile = lock_device(__file);
174 if (!lockfile) return false;
179 switch (CurrentConnectionType) {
181 device_portfd = tekram_open(__file);
184 device_portfd = irda_open();
187 device_portfd = serial_opendevice(__file, __with_odd_parity, true, false);
191 return (device_portfd >= 0);
194 void device_close(void)
196 AppendLogText("CLOSE\n",false);
198 /* Now wait for thread to terminate. */
199 //pthread_join(Thread, NULL);
201 unlock_device(lockfile);
203 switch (CurrentConnectionType) {
204 case GCT_Tekram: tekram_close(device_portfd); break;
205 case GCT_Irda : irda_close(device_portfd); break;
206 default : serial_close(device_portfd); break;
212 void device_reset(void) {
215 void device_setdtrrts(int __dtr, int __rts)
217 switch (CurrentConnectionType) {
222 serial_setdtrrts(device_portfd, __dtr, __rts);
230 void device_changespeed(int __speed)
232 switch (CurrentConnectionType) {
236 tekram_changespeed(device_portfd, __speed);
239 serial_changespeed(device_portfd, __speed);
241 fprintf(stdout,_("Serial device: changing speed to %i\n"),__speed);
247 size_t device_read(__ptr_t __buf, size_t __nbytes)
249 switch (CurrentConnectionType) {
250 case GCT_Tekram: return (tekram_read(device_portfd, __buf, __nbytes)); break;
251 case GCT_Irda : return ( irda_read(device_portfd, __buf, __nbytes)); break;
252 default : return (serial_read(device_portfd, __buf, __nbytes)); break;
256 size_t device_write(__const __ptr_t __buf, size_t __n) {
260 while (duringwrite) {}
262 memcpy(buffer,__buf,__n);
263 AppendLog(buffer,__n,true);
266 switch (CurrentConnectionType) {
267 case GCT_Irda : mysize = irda_write(device_portfd, __buf, __n); break;
268 case GCT_Tekram: mysize = tekram_write(device_portfd, __buf, __n); break;
269 default : mysize = serial_write(device_portfd, __buf, __n); break;
276 void device_dumpserial(void)
279 unsigned int Flags=0;
281 PortFD = device_getfd();
283 ioctl(PortFD, TIOCMGET, &Flags);
285 fprintf(stdout, _("Serial device:"));
286 fprintf(stdout, _(" DTR is %s"), Flags&TIOCM_DTR?_("up"):_("down"));
287 fprintf(stdout, _(", RTS is %s"), Flags&TIOCM_RTS?_("up"):_("down"));
288 fprintf(stdout, _(", CAR is %s"), Flags&TIOCM_CAR?_("up"):_("down"));
289 fprintf(stdout, _(", CTS is %s\n"), Flags&TIOCM_CTS?_("up"):_("down"));
293 void SigHandler(int status)
296 unsigned char buffer[2048];
300 res = device_read(buffer, 255);
302 for (count = 0; count < res ; count ++) {
303 Protocol->StateMachine(buffer[count]);
308 #if defined(__svr4__) || defined(__FreeBSD__)
309 /* thread for handling incoming data */
313 struct timeval timeout;
316 FD_SET(device_portfd,&readfds);
317 /* set timeout to 15 seconds */
320 while (!CurrentRequestTerminate) {
321 err=select(device_portfd+1,&readfds,NULL,NULL,&timeout);
323 /* call singal handler to process incoming data */
325 /* refresh timeout, just for linux :-( */
326 /* required for irda */
330 perror("Error in SelectLoop");
336 bool StartConnection (char *port_device, bool with_odd_parity, GSM_ConnectionType con)
342 #if defined(__svr4__) || defined(__FreeBSD__)
345 struct sigaction sig_io;
349 if ((strstr(GSM_Info->IrdaModels,"decode")!=NULL) && (CurrentConnectionType == GCT_Irda))
351 printf("DEBUG and Irda decode Model -> not realy open ;-)\n");
356 if (PortDevice[0]!=0x00) return true;
360 strncpy(PortDevice, port_device, GSM_MAX_DEVICE_NAME_LENGTH);
363 fprintf(stdout,_("Opening \"%s\" device...\n"),PortDevice);
366 strcpy(text,"\n\n\nMygnokii ");
367 sprintf(text+strlen(text), "%s",VERSION);
368 strcpy(text+strlen(text),"\n");
369 AppendLogText(text,false);
371 strcpy(text,"Port ");
372 strcpy(text+strlen(text),PortDevice);
373 strcpy(text+strlen(text),"\n");
374 AppendLogText(text,false);
376 strcpy(text,"Connection ");
378 case GCT_FBUS :strcpy(text+strlen(text),"FBUS");break;
379 case GCT_Infrared:strcpy(text+strlen(text),"infrared");break;
380 case GCT_Irda :strcpy(text+strlen(text),"irda sockets");break;
381 case GCT_MBUS :strcpy(text+strlen(text),"MBUS");break;
382 case GCT_DLR3 :strcpy(text+strlen(text),"DLR3");break;
383 case GCT_Tekram :strcpy(text+strlen(text),"Tekram");break;
384 case GCT_AT :strcpy(text+strlen(text),"AT");break;
385 default :strcpy(text+strlen(text),"unknown");break;
387 strcpy(text+strlen(text),"\n");
388 AppendLogText(text,false);
390 /* Ralf Thelen: In this moment there is NO method of communication,
391 which require keepalive packets and GSM->KeepAlive is
392 always NULL_KeepAlive, I comment this thread, */
394 /* Create and start main thread. */
395 // rtn = pthread_create(&Thread, NULL,(void*)GSM->KeepAlive, (void *)NULL);
398 // fprintf(stdout,_("Error\n"));
402 #if defined(__svr4__) || defined(__FreeBSD__)
404 /* Set up and install handler before enabling async IO on port. */
405 sig_io.sa_handler = SigHandler;
407 sigaction (SIGIO, &sig_io, NULL);
411 result = device_open(PortDevice, with_odd_parity);
414 fprintf(stdout,_("Error\n"));
418 #if defined(__svr4__) || defined(__FreeBSD__)
419 /* create a thread to handle incoming data from mobile phone */
420 rtn=pthread_create(&selThread,NULL,(void*)SelectLoop,(void*)NULL);
422 fprintf(stdout,_("Error\n"));
430 /* ---------------- RTH: #ifdef WIN32 ------------------ */
434 extern HANDLE hPhone;
436 void device_close(void)
438 AppendLogText("CLOSE\n",false);
446 void device_dumpserial(void)
450 dcb.DCBlength = sizeof(DCB);
451 GetCommState(hPhone, &dcb);
453 fprintf(stdout, _("Serial device:"));
454 fprintf(stdout, _(" DTR is "));
455 switch (dcb.fDtrControl) {
456 case DTR_CONTROL_ENABLE : fprintf(stdout, _("up")); break;
457 case DTR_CONTROL_DISABLE : fprintf(stdout, _("down")); break;
458 case DTR_CONTROL_HANDSHAKE: fprintf(stdout, _("handshake"));break;
460 fprintf(stdout, _(", RTS is "));
461 switch (dcb.fRtsControl) {
462 case RTS_CONTROL_ENABLE : fprintf(stdout, _("up\n")); break;
463 case RTS_CONTROL_DISABLE : fprintf(stdout, _("down\n")); break;
464 case RTS_CONTROL_HANDSHAKE: fprintf(stdout, _("handshake\n"));break;
465 case RTS_CONTROL_TOGGLE : fprintf(stdout, _("toggle\n")); break;
470 void device_setdtrrts(int __dtr, int __rts)
474 dcb.DCBlength = sizeof(DCB);
475 GetCommState(hPhone, &dcb);
477 if (__dtr==1) dcb.fDtrControl = DTR_CONTROL_ENABLE;
478 else dcb.fDtrControl = DTR_CONTROL_DISABLE;
480 if (__rts==1) dcb.fRtsControl = RTS_CONTROL_ENABLE;
481 else dcb.fRtsControl = RTS_CONTROL_DISABLE;
483 SetCommState(hPhone, &dcb);
490 void device_changespeed(int __speed)
495 dcb.DCBlength = sizeof(DCB);
496 GetCommState(hPhone, &dcb);
499 case 115200: dcb.BaudRate=CBR_115200; break;
500 case 19200 : dcb.BaudRate=CBR_19200; break;
501 case 9600 : dcb.BaudRate=CBR_9600; break;
504 SetCommState(hPhone, &dcb);
507 fprintf(stdout,_("Serial device: changing speed to %i\n"),__speed);
511 bool StartConnection (char *port_device, bool with_odd_parity, GSM_ConnectionType con)
518 if (PortDevice[0]!=0x00) return true;
521 strncpy(PortDevice, port_device, GSM_MAX_DEVICE_NAME_LENGTH);
524 fprintf(stdout,_("Opening \"%s\" device...\n"),PortDevice);
527 strcpy(text,"\n\n\nMygnokii ");
528 sprintf(text+strlen(text), "%s",VERSION);
529 strcpy(text+strlen(text),"\n");
530 AppendLogText(text,false);
532 strcpy(text,"Port ");
533 strcpy(text+strlen(text),PortDevice);
534 strcpy(text+strlen(text),"\n");
535 AppendLogText(text,false);
537 strcpy(text,"Connection ");
539 case GCT_FBUS :strcpy(text+strlen(text),"FBUS");break;
540 case GCT_Infrared:strcpy(text+strlen(text),"infrared");break;
541 case GCT_Irda :strcpy(text+strlen(text),"irda sockets");break;
542 case GCT_MBUS :strcpy(text+strlen(text),"MBUS");break;
543 case GCT_DLR3 :strcpy(text+strlen(text),"DLR3");break;
544 case GCT_Tekram :strcpy(text+strlen(text),"Tekram");break;
545 case GCT_AT :strcpy(text+strlen(text),"AT");break;
546 default :strcpy(text+strlen(text),"unknown");break;
548 strcpy(text+strlen(text),"\n");
549 AppendLogText(text,false);
551 CurrentDisableKeepAlive = true;
553 /* Create and start main thread. */
554 rtn = ! OpenConnection(PortDevice, Protocol->StateMachine, GSM->KeepAlive);
558 fprintf(stdout,_("Error\n"));
561 CurrentDisableKeepAlive = false;
564 if (with_odd_parity) {
565 dcb.DCBlength = sizeof(DCB);
566 GetCommState(hPhone, &dcb);
568 dcb.Parity=ODDPARITY;
570 SetCommState(hPhone, &dcb);
576 size_t device_write(const __ptr_t __buf, size_t __n) {
578 while (duringwrite) {}
580 AppendLog(__buf,__n,true);
581 i=WriteCommBlock(__buf,__n);
583 if (i) return __n; else return 0;