X-Git-Url: http://git.jankratochvil.net/?p=gnokii.git;a=blobdiff_plain;f=common%2Fdevices%2Fdevice.c;h=abf18628275cc3d059e44b840b96c0e46902f5fc;hp=be2f079f46811131ea06eb439b509dfd7cb23be7;hb=0484268a27be1ab830d087847d830bc0ec734016;hpb=975a83d253eea8aa37bf3dfd7e026df3027db4ff diff --git a/common/devices/device.c b/common/devices/device.c index be2f079..abf1862 100644 --- a/common/devices/device.c +++ b/common/devices/device.c @@ -8,11 +8,12 @@ */ -#include "config.h" - #ifndef WIN32 #include "devices/unixserial.h" + #include "devices/unixirda.h" + #include "devices/tekram.h" #include + #include #include #include #include @@ -23,6 +24,7 @@ #include "gsm-api.h" #include "devices/device.h" +#include "files/cfgreader.h" #include @@ -31,12 +33,14 @@ #include "mversion.h" #endif -static char PortDevice[GSM_MAX_DEVICE_NAME_LENGTH]={0x00}; +char PortDevice[GSM_MAX_DEVICE_NAME_LENGTH]={0x00}; -static bool duringwrite; +bool duringwrite; #ifndef WIN32 +char *lockfile; + //pthread_t Thread; #if defined(__svr4__) || defined(__FreeBSD__) pthread_t selThread; @@ -44,20 +48,141 @@ static bool duringwrite; int device_portfd = -1; +#define max_buf_len 128 +#define lock_path "/var/lock/LCK.." + +/* Lock the device. Return allocated string with a lock name */ +char *lock_device(const char* port) +{ + char *lock_file = NULL; + char buffer[max_buf_len]; + const char *aux = rindex(port, '/'); + int fd, len = strlen(aux) + strlen(lock_path); + + /* Remove leading '/' */ + if (aux) aux++; + else aux = port; + + memset(buffer, 0, sizeof(buffer)); + lock_file = calloc(len + 1, 1); + if (!lock_file) { + fprintf(stderr, _("Out of memory error while locking device\n")); + return NULL; + } + /* I think we don't need to use strncpy, as we should have enough + * buffer due to strlen results + */ + strcpy(lock_file, lock_path); + strcat(lock_file, aux); + + /* Check for the stale lockfile. + * The code taken from minicom by Miquel van Smoorenburg */ + if ((fd = open(lock_file, O_RDONLY)) >= 0) { + char buf[max_buf_len]; + int pid, n = 0; + + n = read(fd, buf, sizeof(buf) - 1); + close(fd); + if (n > 0) { + pid = -1; + if (n == 4) + /* Kermit-style lockfile. */ + pid = *(int *)buf; + else { + /* Ascii lockfile. */ + buf[n] = 0; + sscanf(buf, "%d", &pid); + } + if (pid > 0 && kill((pid_t)pid, 0) < 0 && errno == ESRCH) { + fprintf(stderr, _("Lockfile %s is stale. Overriding it..\n"), lock_file); + sleep(1); + if (unlink(lock_file) == -1) { + fprintf(stderr, _("Overriding failed, please check the permissions\n")); + fprintf(stderr, _("Cannot lock device\n")); + goto failed; + } + } else { + fprintf(stderr, _("Device already locked.\n")); + goto failed; + } + } + /* this must not happen. because we could open the file */ + /* no wrong permissions are set. only reason could be */ + /* flock/lockf or a empty lockfile due to a broken binary */ + /* which is more likely (like gnokii 0.4.0pre11 ;-) */ + if (n == 0) { + fprintf(stderr, _("Unable to read lockfile %s.\n"), lock_file); + fprintf(stderr, _("Please check for reason and remove the lockfile by hand.\n")); + fprintf(stderr, _("Cannot lock device\n")); + goto failed; + } + } + + /* Try to create a new file, with 0644 mode */ + fd = open(lock_file, O_CREAT | O_EXCL | O_WRONLY, 0644); + if (fd == -1) { + if (errno == EEXIST) + fprintf(stderr, _("Device seems to be locked by unknown process\n")); + else if (errno == EACCES) + fprintf(stderr, _("Please check permission on lock directory\n")); + else if (errno == ENOENT) + fprintf(stderr, _("Cannot create lockfile %s. Please check for existence of path"), lock_file); + goto failed; + } + sprintf(buffer, "%10ld gnokii\n", (long)getpid()); + write(fd, buffer, strlen(buffer)); + close(fd); + return lock_file; +failed: + free(lock_file); + return NULL; +} + +/* Removes lock and frees memory */ +bool unlock_device(char *lock_file) +{ + int err; + + if (!lock_file) { +// fprintf(stderr, _("Cannot unlock device\n")); + return false; + } + err = unlink(lock_file); + free(lock_file); + return (err + 1); +} + /* * Structure to store the filedescriptor we use. * */ -#ifdef DEBUG -static int device_getfd(void) +int device_getfd(void) { return device_portfd; } -#endif /* DEBUG */ - -static int device_open(__const char *__file, int __with_odd_parity) { +int device_open(__const char *__file, int __with_odd_parity) { + struct CFG_Header *cfg_info; + char *aux; + + cfg_info=CFG_FindGnokiirc(); + if (cfg_info!=NULL) { + aux = CFG_Get(cfg_info, "global", "use_locking"); + if (aux) { + if (!strcmp(aux, "yes")) { + lockfile = lock_device(__file); + if (!lockfile) return false; + } + } + } + switch (CurrentConnectionType) { + case GCT_Tekram: + device_portfd = tekram_open(__file); + break; + case GCT_Irda: + device_portfd = irda_open(); + break; default: device_portfd = serial_opendevice(__file, __with_odd_parity, true, false); break; @@ -73,27 +198,26 @@ void device_close(void) /* Now wait for thread to terminate. */ //pthread_join(Thread, NULL); + unlock_device(lockfile); + switch (CurrentConnectionType) { + case GCT_Tekram: tekram_close(device_portfd); break; + case GCT_Irda : irda_close(device_portfd); break; default : serial_close(device_portfd); break; } PortDevice[0]=0x00; } -#ifndef UCLINUX - void device_reset(void) { } -#endif /* UCLINUX */ - -#ifdef DEBUG -static void device_dumpserial(void); -#endif /* DEBUG */ - void device_setdtrrts(int __dtr, int __rts) { switch (CurrentConnectionType) { + case GCT_Tekram: + case GCT_Irda: + break; default: serial_setdtrrts(device_portfd, __dtr, __rts); #ifdef DEBUG @@ -106,6 +230,11 @@ void device_setdtrrts(int __dtr, int __rts) void device_changespeed(int __speed) { switch (CurrentConnectionType) { + case GCT_Irda: + break; + case GCT_Tekram: + tekram_changespeed(device_portfd, __speed); + break; default: serial_changespeed(device_portfd, __speed); #ifdef DEBUG @@ -115,9 +244,11 @@ void device_changespeed(int __speed) } } -static size_t device_read(__ptr_t __buf, size_t __nbytes) +size_t device_read(__ptr_t __buf, size_t __nbytes) { switch (CurrentConnectionType) { + case GCT_Tekram: return (tekram_read(device_portfd, __buf, __nbytes)); break; + case GCT_Irda : return ( irda_read(device_portfd, __buf, __nbytes)); break; default : return (serial_read(device_portfd, __buf, __nbytes)); break; } } @@ -126,26 +257,23 @@ size_t device_write(__const __ptr_t __buf, size_t __n) { u8 buffer[300]; size_t mysize; - while (duringwrite) { - fprintf(stderr,"device_write: reentrance violation!\n"); - _exit(1); - } + while (duringwrite) {} memcpy(buffer,__buf,__n); AppendLog(buffer,__n,true); duringwrite=true; switch (CurrentConnectionType) { + case GCT_Irda : mysize = irda_write(device_portfd, __buf, __n); break; + case GCT_Tekram: mysize = tekram_write(device_portfd, __buf, __n); break; default : mysize = serial_write(device_portfd, __buf, __n); break; } duringwrite=false; - if (mysize!=__n) - fprintf(stderr,"WARNING: device_write(__n=%ld)=%ld\n",(long)__n,(long)mysize); return mysize; } #ifdef DEBUG -static void device_dumpserial(void) +void device_dumpserial(void) { int PortFD; unsigned int Flags=0; @@ -162,71 +290,20 @@ static void device_dumpserial(void) } #endif /* DEBUG */ -static char SigHandler_buffer[255]; - void SigHandler(int status) { - int count, res; - LIVE_DISABLE; - LIVE; + unsigned char buffer[2048]; + + int count, res; - res = device_read(SigHandler_buffer, sizeof(SigHandler_buffer)); + res = device_read(buffer, 255); for (count = 0; count < res ; count ++) { - Protocol->StateMachine(SigHandler_buffer[count]); + Protocol->StateMachine(buffer[count]); } - LIVE_ENABLE; } -#ifdef UCLINUX -void usleep_watchdevice(unsigned long usecs) -{ -int err; -fd_set readfds; -struct timeval target,timeout; -long timeout_sec,timeout_usec; /* signed! */ - - if (gettimeofday(&target/*tv*/,NULL/*tz*/)) - perror("usleep_watchdevice()/gettimeofday(2) init"); - target.tv_usec+=usecs%1000000; - target.tv_sec +=usecs/1000000 + (target.tv_usec/1000000); - target.tv_usec%=1000000; - - for (;;) { - if (gettimeofday(&timeout/*tv*/,NULL/*tz*/)) - perror("usleep_watchdevice()/gettimeofday(2) loop"); - - timeout_sec =target.tv_sec -(long)timeout.tv_sec ; - timeout_usec=target.tv_usec-(long)timeout.tv_usec; - - if (timeout_usec<0) { - timeout_sec--; - timeout_usec+=1000000; - } - if (timeout_sec<0) - return; - - timeout.tv_sec =timeout_sec ; - timeout.tv_usec=timeout_usec; - - FD_ZERO(&readfds); - if (device_portfd>=0) - FD_SET(device_portfd,&readfds); - - err=select((device_portfd<0 ? 0 : device_portfd+1),&readfds,NULL,NULL,&timeout); - if ( err > 0 ) { - if (device_portfd>=0 && FD_ISSET(device_portfd,&readfds)) { - /* call singal handler to process incoming data */ - SigHandler(0); - } - } else { - if (err == -1) - perror("Error in SelectLoop"); - } - } -} -#endif #if defined(__svr4__) || defined(__FreeBSD__) /* thread for handling incoming data */ @@ -245,9 +322,9 @@ void SelectLoop() { if ( err > 0 ) { /* call singal handler to process incoming data */ SigHandler(0); - /* refresh timeout, just for linux :-( */ + /* refresh timeout, just for linux :-( */ /* required for irda */ - timeout.tv_sec=15; + timeout.tv_sec=15; } else { if (err == -1) perror("Error in SelectLoop"); @@ -262,15 +339,12 @@ bool StartConnection (char *port_device, bool with_odd_parity, GSM_ConnectionTyp char text[100]; -#ifndef UCLINUX #if defined(__svr4__) || defined(__FreeBSD__) int rtn; #else struct sigaction sig_io; #endif -#endif /* UCLINUX */ -#ifndef UCLINUX #ifdef DEBUG if ((strstr(GSM_Info->IrdaModels,"decode")!=NULL) && (CurrentConnectionType == GCT_Irda)) { @@ -278,7 +352,6 @@ bool StartConnection (char *port_device, bool with_odd_parity, GSM_ConnectionTyp return true; } #endif -#endif /* UCLINUX */ if (PortDevice[0]!=0x00) return true; @@ -303,12 +376,13 @@ bool StartConnection (char *port_device, bool with_odd_parity, GSM_ConnectionTyp strcpy(text,"Connection "); switch (con) { case GCT_FBUS :strcpy(text+strlen(text),"FBUS");break; -#ifndef UCLINUX + case GCT_Infrared:strcpy(text+strlen(text),"infrared");break; + case GCT_Irda :strcpy(text+strlen(text),"irda sockets");break; case GCT_MBUS :strcpy(text+strlen(text),"MBUS");break; case GCT_DLR3 :strcpy(text+strlen(text),"DLR3");break; + case GCT_Tekram :strcpy(text+strlen(text),"Tekram");break; case GCT_AT :strcpy(text+strlen(text),"AT");break; default :strcpy(text+strlen(text),"unknown");break; -#endif /* UCLINUX */ } strcpy(text+strlen(text),"\n"); AppendLogText(text,false); @@ -325,7 +399,6 @@ bool StartConnection (char *port_device, bool with_odd_parity, GSM_ConnectionTyp // return false; // } -#ifndef UCLINUX #if defined(__svr4__) || defined(__FreeBSD__) #else /* Set up and install handler before enabling async IO on port. */ @@ -333,7 +406,6 @@ bool StartConnection (char *port_device, bool with_odd_parity, GSM_ConnectionTyp sig_io.sa_flags = 0; sigaction (SIGIO, &sig_io, NULL); #endif -#endif /* UCLINUX */ /* Open device. */ result = device_open(PortDevice, with_odd_parity); @@ -343,7 +415,6 @@ bool StartConnection (char *port_device, bool with_odd_parity, GSM_ConnectionTyp return false; } -#ifndef UCLINUX #if defined(__svr4__) || defined(__FreeBSD__) /* create a thread to handle incoming data from mobile phone */ rtn=pthread_create(&selThread,NULL,(void*)SelectLoop,(void*)NULL); @@ -352,7 +423,6 @@ bool StartConnection (char *port_device, bool with_odd_parity, GSM_ConnectionTyp return false; } #endif -#endif /* UCLINUX */ return true; } @@ -467,8 +537,11 @@ bool StartConnection (char *port_device, bool with_odd_parity, GSM_ConnectionTyp strcpy(text,"Connection "); switch (con) { case GCT_FBUS :strcpy(text+strlen(text),"FBUS");break; + case GCT_Infrared:strcpy(text+strlen(text),"infrared");break; + case GCT_Irda :strcpy(text+strlen(text),"irda sockets");break; case GCT_MBUS :strcpy(text+strlen(text),"MBUS");break; case GCT_DLR3 :strcpy(text+strlen(text),"DLR3");break; + case GCT_Tekram :strcpy(text+strlen(text),"Tekram");break; case GCT_AT :strcpy(text+strlen(text),"AT");break; default :strcpy(text+strlen(text),"unknown");break; }