/* Some source from Gnokii (www.gnokii.org) * (C) 1999-2000 Hugh Blemings & Pavel Janik ml. (C) 2001-2004 Pawel Kot * GNU GPL version 2 or later */ /* Some source from Minicom (http://alioth.debian.org/projects/minicom) * (C) 1991,1992,1993,1994,1995,1996 by Miquel van Smoorenburg * GNU GPL version 2 */ /* Due to a problem in the source code management, the names of some of * the authors have unfortunately been lost. We do not mean to belittle * their efforts and hope they will contact us to see their names * properly added to the Copyright notice above. * Having published their contributions under the terms of the GNU * General Public License (GPL) [version 2], the Copyright of these * authors will remain respected by adhering to the license they chose * to publish their code under. */ #include #include #ifdef WIN32 # include # include #else # include # include # include # include #endif #include "devfunc.h" #include "../gsmstate.h" #ifdef GSM_ENABLE_BLUETOOTHDEVICE #ifdef BLUETOOTH_RF_SEARCHING int bluetooth_checkservicename(GSM_StateMachine *s, const char *name) { /* Phonet */ if (s->ConnectionType == GCT_BLUEPHONET) { if (strstr(name, "Nokia PC Suite") != NULL) return 1; /* OBEX */ } else if (s->ConnectionType == GCT_BLUEOBEX) { /* Prefer this on Nokia as this gives better access to filesystem */ if (strstr(name, "Nokia OBEX PC Suite Services") != NULL) { if (strcmp(s->CurrentConfig->Model, "obex") == 0) { return 5; } return 3; } /* For filesystem, we prefer file transfer */ if (strstr(name, "OBEX File Transfer") != NULL || strstr(name, "OBEX file transfer") != NULL) { if (strcmp(s->CurrentConfig->Model, "obex") == 0) { return 4; } return 3; } /* Ususally this name also contains OBEX, preffered for irmc */ if (strstr(name, "IrMC Sync") != NULL || strstr(name, "OBEX Synchronisation")) { if (strcmp(s->CurrentConfig->Model, "obexirmc") == 0 || strcmp(s->CurrentConfig->Model, "seobex") == 0) { return 4; } return 3; } /* Simple send of files should work here */ if (strstr(name, "OBEX Object Push") != NULL) { if (strcmp(s->CurrentConfig->Model, "obexnone") == 0) { return 3; } return 2; } /* Anything matching OBEX has lowest priority */ if (strstr(name, "OBEX") != NULL) return 1; /* AT */ } else if (s->ConnectionType == GCT_BLUEAT) { /* Sony-Ericsson */ if (strstr(name, "Serial Port 1") != NULL) return 3; if (strstr(name, "Serial Port") != NULL) return 2; /* Motorola */ if (strstr(name, "Dial-up networking Gateway") != NULL) return 3; if (strstr(name, "Serial port") != NULL) return 2; /* Siemens, Thomas Eitzenberger */ if (strstr(name, "SerialPort1") != NULL) return 3; if (strstr(name, "SerialPort") != NULL) return 2; if (strstr(name, "COM1") != NULL) return 3; if (strstr(name, "COM") != NULL) return 1; } return 0; } #endif #endif #if defined (GSM_ENABLE_BLUETOOTHDEVICE) || defined (GSM_ENABLE_IRDADEVICE) int socket_read(GSM_StateMachine *s UNUSED, void *buf, size_t nbytes, socket_type hPhone) { fd_set readfds; int result = 0; #ifdef WIN32 struct timeval timer; #else int flags; #endif FD_ZERO(&readfds); FD_SET(hPhone, &readfds); #ifndef WIN32 if (select(hPhone+1, &readfds, NULL, NULL, 0) > 0) { flags = fcntl(hPhone, F_GETFL); fcntl(hPhone, F_SETFL, flags | O_NONBLOCK); result = read(hPhone, buf, nbytes); if (result < 0 && errno != EINTR) { return 0; } fcntl(hPhone, F_SETFL, flags); } #else memset(&timer,0,sizeof(timer)); if (select(0, &readfds, NULL, NULL, &timer) > 0) { result = recv(hPhone, buf, nbytes, 0); } #endif return result; } int socket_write(GSM_StateMachine *s, unsigned const char *buf, size_t nbytes, socket_type hPhone) { int ret; size_t actual = 0; do { ret = send(hPhone, buf, nbytes - actual, 0); if (ret < 0) { if (actual != nbytes) { GSM_OSErrorInfo(s,"socket_write"); #ifndef WIN32 if (errno != EINTR) { return 0; } #endif } return actual; } actual += ret; buf += ret; } while (actual < nbytes); return actual; } GSM_Error socket_close(GSM_StateMachine *s UNUSED, socket_type hPhone) { shutdown(hPhone, 0); #ifdef WIN32 closesocket(hPhone); /*FIXME: error checking */ #else close(hPhone); /*FIXME: error checking */ #endif return ERR_NONE; } #endif #define max_buf_len 128 #define lock_path "/var/lock/LCK.." /* Lock the device. Allocated string with a lock name is returned * in lock_device */ #if !defined(WIN32) && !defined(DJGPP) GSM_Error lock_device(const char* port, char **lock_name) { char *lock_file = NULL; char buffer[max_buf_len]; const char *aux; int fd, len; GSM_Error error = ERR_NONE; size_t wrotebytes; dbgprintf("Locking device\n"); aux = strrchr(port, '/'); /* Remove leading '/' */ if (aux) { aux++; } else { /* No / in port */ aux = port; } len = strlen(aux) + strlen(lock_path); memset(buffer, 0, sizeof(buffer)); lock_file = calloc(len + 1, 1); if (!lock_file) { dbgprintf("Out of memory error while locking device\n"); return ERR_MOREMEMORY; } /* 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) { dbgprintf("Lockfile %s is stale. Overriding it..\n", lock_file); sleep(1); if (unlink(lock_file) == -1) { dbgprintf("Overriding failed, please check the permissions\n"); dbgprintf("Cannot lock device\n"); error = ERR_PERMISSION; goto failed; } } else { dbgprintf("Device already locked by PID %d.\n", pid); error = ERR_DEVICELOCKED; 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 */ if (n == 0) { dbgprintf("Unable to read lockfile %s.\n", lock_file); dbgprintf("Please check for reason and remove the lockfile by hand.\n"); dbgprintf("Cannot lock device\n"); error = ERR_UNKNOWN; 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) { dbgprintf("Device seems to be locked by unknown process\n"); error = ERR_DEVICEOPENERROR; } else if (errno == EACCES) { dbgprintf("Please check permission on lock directory\n"); error = ERR_PERMISSION; } else if (errno == ENOENT) { dbgprintf("Cannot create lockfile %s. Please check for existence of path\n", lock_file); error = ERR_UNKNOWN; } else { dbgprintf("Unknown error with creating lockfile %s\n", lock_file); error = ERR_UNKNOWN; } goto failed; } sprintf(buffer, "%10ld gammu\n", (long)getpid()); wrotebytes = write(fd, buffer, strlen(buffer)); if (wrotebytes != strlen(buffer)) { return ERR_WRITING_FILE; } close(fd); *lock_name = lock_file; return ERR_NONE; failed: free(lock_file); *lock_name = NULL; return error; } #else GSM_Error lock_device(const char* port UNUSED, char **lock_name) { *lock_name = NULL; return ERR_NONE; } #endif /* Removes lock and frees memory */ #if !defined(WIN32) && !defined(DJGPP) bool unlock_device(char **lock_file) { int err; if (!lock_file) { dbgprintf("Cannot unlock device\n"); return false; } err = unlink(*lock_file); free(*lock_file); *lock_file = NULL; return (err + 1); } #else bool unlock_device(char **lock_file UNUSED) { return true; } #endif int FindSerialSpeed(const char *buffer) { switch (atoi(buffer)) { case 50 : return 50; case 75 : return 75; case 110 : return 110; case 134 : return 134; case 150 : return 150; case 200 : return 200; case 300 : return 300; case 600 : return 600; case 1200 : return 1200; case 1800 : return 1800; case 2400 : return 2400; case 4800 : return 4800; case 9600 : return 9600; case 19200 : return 19200; case 38400 : return 38400; case 57600 : return 57600; case 115200 : return 115200; case 230400 : return 230400; default : return 0; } } /* How should editor hadle tabs in this file? Add editor commands here. * vim: noexpandtab sw=8 ts=8 sts=8: */