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.
14 #include "devices/unixserial.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 static char PortDevice[GSM_MAX_DEVICE_NAME_LENGTH]={0x00};
38 static bool duringwrite;
47 #if defined(__svr4__) || defined(__FreeBSD__)
51 int device_portfd = -1;
53 #define max_buf_len 128
54 #define lock_path "/var/lock/LCK.."
58 /* Lock the device. Return allocated string with a lock name */
59 char *lock_device(const char* port)
61 char *lock_file = NULL;
62 char buffer[max_buf_len];
63 const char *aux = rindex(port, '/');
64 int fd, len = strlen(aux) + strlen(lock_path);
66 /* Remove leading '/' */
70 memset(buffer, 0, sizeof(buffer));
71 lock_file = calloc(len + 1, 1);
73 fprintf(stderr, _("Out of memory error while locking device\n"));
76 /* I think we don't need to use strncpy, as we should have enough
77 * buffer due to strlen results
79 strcpy(lock_file, lock_path);
80 strcat(lock_file, aux);
82 /* Check for the stale lockfile.
83 * The code taken from minicom by Miquel van Smoorenburg */
84 if ((fd = open(lock_file, O_RDONLY)) >= 0) {
85 char buf[max_buf_len];
88 n = read(fd, buf, sizeof(buf) - 1);
93 /* Kermit-style lockfile. */
100 if (pid > 0 && kill((pid_t)pid, 0) < 0 && errno == ESRCH) {
101 fprintf(stderr, _("Lockfile %s is stale. Overriding it..\n"), lock_file);
103 if (unlink(lock_file) == -1) {
104 fprintf(stderr, _("Overriding failed, please check the permissions\n"));
105 fprintf(stderr, _("Cannot lock device\n"));
109 fprintf(stderr, _("Device already locked.\n"));
113 /* this must not happen. because we could open the file */
114 /* no wrong permissions are set. only reason could be */
115 /* flock/lockf or a empty lockfile due to a broken binary */
116 /* which is more likely (like gnokii 0.4.0pre11 ;-) */
118 fprintf(stderr, _("Unable to read lockfile %s.\n"), lock_file);
119 fprintf(stderr, _("Please check for reason and remove the lockfile by hand.\n"));
120 fprintf(stderr, _("Cannot lock device\n"));
125 /* Try to create a new file, with 0644 mode */
126 fd = open(lock_file, O_CREAT | O_EXCL | O_WRONLY, 0644);
129 fprintf(stderr, _("Device seems to be locked by unknown process\n"));
130 else if (errno == EACCES)
131 fprintf(stderr, _("Please check permission on lock directory\n"));
132 else if (errno == ENOENT)
133 fprintf(stderr, _("Cannot create lockfile %s. Please check for existence of path"), lock_file);
136 sprintf(buffer, "%10ld gnokii\n", (long)getpid());
137 write(fd, buffer, strlen(buffer));
145 /* Removes lock and frees memory */
146 bool unlock_device(char *lock_file)
151 // fprintf(stderr, _("Cannot unlock device\n"));
154 err = unlink(lock_file);
162 * Structure to store the filedescriptor we use.
166 static int device_getfd(void)
168 return device_portfd;
172 static int device_open(__const char *__file, int __with_odd_parity) {
174 struct CFG_Header *cfg_info;
177 cfg_info=CFG_FindGnokiirc();
178 if (cfg_info!=NULL) {
179 aux = CFG_Get(cfg_info, "global", "use_locking");
181 if (!strcmp(aux, "yes")) {
182 lockfile = lock_device(__file);
183 if (!lockfile) return false;
189 switch (CurrentConnectionType) {
191 device_portfd = serial_opendevice(__file, __with_odd_parity, true, false);
195 return (device_portfd >= 0);
198 void device_close(void)
200 AppendLogText("CLOSE\n",false);
202 /* Now wait for thread to terminate. */
203 //pthread_join(Thread, NULL);
206 unlock_device(lockfile);
209 switch (CurrentConnectionType) {
210 default : serial_close(device_portfd); break;
218 void device_reset(void) {
224 static void device_dumpserial(void);
227 void device_setdtrrts(int __dtr, int __rts)
229 switch (CurrentConnectionType) {
231 serial_setdtrrts(device_portfd, __dtr, __rts);
239 void device_changespeed(int __speed)
241 switch (CurrentConnectionType) {
243 serial_changespeed(device_portfd, __speed);
245 fprintf(stdout,_("Serial device: changing speed to %i\n"),__speed);
251 static size_t device_read(__ptr_t __buf, size_t __nbytes)
253 switch (CurrentConnectionType) {
254 default : return (serial_read(device_portfd, __buf, __nbytes)); break;
258 size_t device_write(__const __ptr_t __buf, size_t __n) {
262 while (duringwrite) {
263 fprintf(stderr,"device_write: reentrance violation!\n");
267 memcpy(buffer,__buf,__n);
268 AppendLog(buffer,__n,true);
271 switch (CurrentConnectionType) {
272 default : mysize = serial_write(device_portfd, __buf, __n); break;
276 fprintf(stderr,"WARNING: device_write(__n=%ld)=%ld\n",(long)__n,(long)mysize);
281 static void device_dumpserial(void)
284 unsigned int Flags=0;
286 PortFD = device_getfd();
288 ioctl(PortFD, TIOCMGET, &Flags);
290 fprintf(stdout, _("Serial device:"));
291 fprintf(stdout, _(" DTR is %s"), Flags&TIOCM_DTR?_("up"):_("down"));
292 fprintf(stdout, _(", RTS is %s"), Flags&TIOCM_RTS?_("up"):_("down"));
293 fprintf(stdout, _(", CAR is %s"), Flags&TIOCM_CAR?_("up"):_("down"));
294 fprintf(stdout, _(", CTS is %s\n"), Flags&TIOCM_CTS?_("up"):_("down"));
298 static char SigHandler_buffer[255];
300 void SigHandler(int status)
307 res = device_read(SigHandler_buffer, sizeof(SigHandler_buffer));
309 for (count = 0; count < res ; count ++) {
310 Protocol->StateMachine(SigHandler_buffer[count]);
316 void usleep_watchdevice(unsigned long usecs)
320 struct timeval target,timeout;
321 long timeout_sec,timeout_usec; /* signed! */
323 if (gettimeofday(&target/*tv*/,NULL/*tz*/))
324 perror("usleep_watchdevice()/gettimeofday(2) init");
325 target.tv_usec+=usecs%1000000;
326 target.tv_sec +=usecs/1000000 + (target.tv_usec/1000000);
327 target.tv_usec%=1000000;
330 if (gettimeofday(&timeout/*tv*/,NULL/*tz*/))
331 perror("usleep_watchdevice()/gettimeofday(2) loop");
333 timeout_sec =target.tv_sec -(long)timeout.tv_sec ;
334 timeout_usec=target.tv_usec-(long)timeout.tv_usec;
336 if (timeout_usec<0) {
338 timeout_usec+=1000000;
343 timeout.tv_sec =timeout_sec ;
344 timeout.tv_usec=timeout_usec;
347 if (device_portfd>=0)
348 FD_SET(device_portfd,&readfds);
350 err=select((device_portfd<0 ? 0 : device_portfd+1),&readfds,NULL,NULL,&timeout);
352 if (device_portfd>=0 && FD_ISSET(device_portfd,&readfds)) {
353 /* call singal handler to process incoming data */
358 perror("Error in SelectLoop");
364 #if defined(__svr4__) || defined(__FreeBSD__)
365 /* thread for handling incoming data */
369 struct timeval timeout;
372 FD_SET(device_portfd,&readfds);
373 /* set timeout to 15 seconds */
376 while (!CurrentRequestTerminate) {
377 err=select(device_portfd+1,&readfds,NULL,NULL,&timeout);
379 /* call singal handler to process incoming data */
381 /* refresh timeout, just for linux :-( */
382 /* required for irda */
386 perror("Error in SelectLoop");
392 bool StartConnection (char *port_device, bool with_odd_parity, GSM_ConnectionType con)
399 #if defined(__svr4__) || defined(__FreeBSD__)
402 struct sigaction sig_io;
408 if ((strstr(GSM_Info->IrdaModels,"decode")!=NULL) && (CurrentConnectionType == GCT_Irda))
410 printf("DEBUG and Irda decode Model -> not realy open ;-)\n");
416 if (PortDevice[0]!=0x00) return true;
420 strncpy(PortDevice, port_device, GSM_MAX_DEVICE_NAME_LENGTH);
423 fprintf(stdout,_("Opening \"%s\" device...\n"),PortDevice);
426 strcpy(text,"\n\n\nMygnokii ");
427 sprintf(text+strlen(text), "%s",VERSION);
428 strcpy(text+strlen(text),"\n");
429 AppendLogText(text,false);
431 strcpy(text,"Port ");
432 strcpy(text+strlen(text),PortDevice);
433 strcpy(text+strlen(text),"\n");
434 AppendLogText(text,false);
436 strcpy(text,"Connection ");
438 case GCT_FBUS :strcpy(text+strlen(text),"FBUS");break;
440 case GCT_MBUS :strcpy(text+strlen(text),"MBUS");break;
441 case GCT_DLR3 :strcpy(text+strlen(text),"DLR3");break;
442 case GCT_AT :strcpy(text+strlen(text),"AT");break;
443 default :strcpy(text+strlen(text),"unknown");break;
446 strcpy(text+strlen(text),"\n");
447 AppendLogText(text,false);
449 /* Ralf Thelen: In this moment there is NO method of communication,
450 which require keepalive packets and GSM->KeepAlive is
451 always NULL_KeepAlive, I comment this thread, */
453 /* Create and start main thread. */
454 // rtn = pthread_create(&Thread, NULL,(void*)GSM->KeepAlive, (void *)NULL);
457 // fprintf(stdout,_("Error\n"));
462 #if defined(__svr4__) || defined(__FreeBSD__)
464 /* Set up and install handler before enabling async IO on port. */
465 sig_io.sa_handler = SigHandler;
467 sigaction (SIGIO, &sig_io, NULL);
472 result = device_open(PortDevice, with_odd_parity);
475 fprintf(stdout,_("Error\n"));
480 #if defined(__svr4__) || defined(__FreeBSD__)
481 /* create a thread to handle incoming data from mobile phone */
482 rtn=pthread_create(&selThread,NULL,(void*)SelectLoop,(void*)NULL);
484 fprintf(stdout,_("Error\n"));
493 /* ---------------- RTH: #ifdef WIN32 ------------------ */
497 extern HANDLE hPhone;
499 void device_close(void)
501 AppendLogText("CLOSE\n",false);
509 void device_dumpserial(void)
513 dcb.DCBlength = sizeof(DCB);
514 GetCommState(hPhone, &dcb);
516 fprintf(stdout, _("Serial device:"));
517 fprintf(stdout, _(" DTR is "));
518 switch (dcb.fDtrControl) {
519 case DTR_CONTROL_ENABLE : fprintf(stdout, _("up")); break;
520 case DTR_CONTROL_DISABLE : fprintf(stdout, _("down")); break;
521 case DTR_CONTROL_HANDSHAKE: fprintf(stdout, _("handshake"));break;
523 fprintf(stdout, _(", RTS is "));
524 switch (dcb.fRtsControl) {
525 case RTS_CONTROL_ENABLE : fprintf(stdout, _("up\n")); break;
526 case RTS_CONTROL_DISABLE : fprintf(stdout, _("down\n")); break;
527 case RTS_CONTROL_HANDSHAKE: fprintf(stdout, _("handshake\n"));break;
528 case RTS_CONTROL_TOGGLE : fprintf(stdout, _("toggle\n")); break;
533 void device_setdtrrts(int __dtr, int __rts)
537 dcb.DCBlength = sizeof(DCB);
538 GetCommState(hPhone, &dcb);
540 if (__dtr==1) dcb.fDtrControl = DTR_CONTROL_ENABLE;
541 else dcb.fDtrControl = DTR_CONTROL_DISABLE;
543 if (__rts==1) dcb.fRtsControl = RTS_CONTROL_ENABLE;
544 else dcb.fRtsControl = RTS_CONTROL_DISABLE;
546 SetCommState(hPhone, &dcb);
553 void device_changespeed(int __speed)
558 dcb.DCBlength = sizeof(DCB);
559 GetCommState(hPhone, &dcb);
562 case 115200: dcb.BaudRate=CBR_115200; break;
563 case 19200 : dcb.BaudRate=CBR_19200; break;
564 case 9600 : dcb.BaudRate=CBR_9600; break;
567 SetCommState(hPhone, &dcb);
570 fprintf(stdout,_("Serial device: changing speed to %i\n"),__speed);
574 bool StartConnection (char *port_device, bool with_odd_parity, GSM_ConnectionType con)
581 if (PortDevice[0]!=0x00) return true;
584 strncpy(PortDevice, port_device, GSM_MAX_DEVICE_NAME_LENGTH);
587 fprintf(stdout,_("Opening \"%s\" device...\n"),PortDevice);
590 strcpy(text,"\n\n\nMygnokii ");
591 sprintf(text+strlen(text), "%s",VERSION);
592 strcpy(text+strlen(text),"\n");
593 AppendLogText(text,false);
595 strcpy(text,"Port ");
596 strcpy(text+strlen(text),PortDevice);
597 strcpy(text+strlen(text),"\n");
598 AppendLogText(text,false);
600 strcpy(text,"Connection ");
602 case GCT_FBUS :strcpy(text+strlen(text),"FBUS");break;
603 case GCT_MBUS :strcpy(text+strlen(text),"MBUS");break;
604 case GCT_DLR3 :strcpy(text+strlen(text),"DLR3");break;
605 case GCT_AT :strcpy(text+strlen(text),"AT");break;
606 default :strcpy(text+strlen(text),"unknown");break;
608 strcpy(text+strlen(text),"\n");
609 AppendLogText(text,false);
611 CurrentDisableKeepAlive = true;
613 /* Create and start main thread. */
614 rtn = ! OpenConnection(PortDevice, Protocol->StateMachine, GSM->KeepAlive);
618 fprintf(stdout,_("Error\n"));
621 CurrentDisableKeepAlive = false;
624 if (with_odd_parity) {
625 dcb.DCBlength = sizeof(DCB);
626 GetCommState(hPhone, &dcb);
628 dcb.Parity=ODDPARITY;
630 SetCommState(hPhone, &dcb);
636 size_t device_write(const __ptr_t __buf, size_t __n) {
638 while (duringwrite) {}
640 AppendLog(__buf,__n,true);
641 i=WriteCommBlock(__buf,__n);
643 if (i) return __n; else return 0;