/* (c) 2002-2005 by Marcin Wiacek and Michal Cihar */ /* Phones ID (c) partially by Walek */ #include #define _GNU_SOURCE /* For strcasestr */ #include #include #include #include #include #include #include #include #include "debug.h" #include "gsmcomon.h" #include "gsmphones.h" #include "gsmstate.h" #include "misc/coding/coding.h" #include "misc/misc.h" #include "device/devfunc.h" #include "../helper/string.h" #if defined(HAVE_GETPWUID) && defined(HAVE_GETUID) #include #include #include #endif #if defined(WIN32) || defined(DJGPP) /* Needed for SHGFP_TYPE_CURRENT */ #ifndef _WIN32_IE #define _WIN32_IE 0x0501 #endif #include #define FALLBACK_GAMMURC "gammurc" #define GAMMURC_NAME "\\gammurc" #else #define FALLBACK_GAMMURC "/etc/gammurc" #define GAMMURC_NAME "/.gammurc" #endif #define XDG_GAMMURC_NAME "/gammu/config" /* Win32 compatibility */ #ifndef PATH_MAX #define PATH_MAX (MAX_PATH) #endif /* Default settings */ #if defined(WIN32) || defined(DJGPP) # define DEFAULT_DEVICE "com2:" #else # define DEFAULT_DEVICE "/dev/ttyUSB0" #endif #define DEFAULT_MODEL "" #define DEFAULT_CONNECTION "at" #define DEFAULT_SYNCHRONIZE_TIME FALSE #define DEFAULT_DEBUG_FILE "" #define DEFAULT_DEBUG_LEVEL "" #define DEFAULT_LOCK_DEVICE FALSE #define DEFAULT_START_INFO FALSE /** * Returns current debuging descriptor. It honors use_global * flag. */ GSM_Debug_Info *GSM_GetDI(GSM_StateMachine *s) { GSM_Debug_Info *curdi; curdi = &GSM_global_debug; if (s != NULL && s->di.use_global == FALSE) { curdi = &(s->di); } return curdi; } static void GSM_RegisterConnection(GSM_StateMachine *s, unsigned int connection, GSM_Device_Functions *device, GSM_Protocol_Functions *protocol) { if ((unsigned int)s->ConnectionType == connection) { s->Device.Functions = device; s->Protocol.Functions = protocol; } } /** * Information about connection names and parameters. */ typedef struct { /** * Name of the connection used in config file. */ const char *Name; /** * Connection type. */ const GSM_ConnectionType Connection; /** * Whether to disable DTR/RTS handling on this connection. */ gboolean SkipDtrRts; } GSM_ConnectionInfo; /** * Mapping of connection names to internal identifications. */ static const GSM_ConnectionInfo GSM_Connections[] = { {"at", GCT_AT, FALSE}, /* cables */ {"mbus", GCT_MBUS2, FALSE}, {"fbus", GCT_FBUS2, FALSE}, {"fbususb", GCT_FBUS2USB, FALSE}, {"fbuspl2303", GCT_FBUS2PL2303, FALSE}, {"dlr3", GCT_FBUS2DLR3, FALSE}, {"fbusdlr3", GCT_FBUS2DLR3, FALSE}, {"dku5", GCT_DKU5FBUS2, FALSE}, {"fbusdku5", GCT_DKU5FBUS2, FALSE}, {"dku5fbus", GCT_DKU5FBUS2, FALSE}, {"ark3116fbus", GCT_DKU5FBUS2, TRUE}, #ifdef WIN32 {"dku2", GCT_DKU2PHONET, FALSE}, {"dku2phonet", GCT_DKU2PHONET, FALSE}, #else {"dku2", GCT_FBUS2USB, FALSE}, {"dku2phonet", GCT_FBUS2USB, FALSE}, #endif {"dku2at", GCT_DKU2AT, FALSE}, /* for serial ports assigned by bt stack */ {"fbusblue", GCT_FBUS2BLUE, FALSE}, {"phonetblue", GCT_PHONETBLUE, FALSE}, /* bt */ {"blueobex", GCT_BLUEOBEX, FALSE}, {"bluephonet", GCT_BLUEPHONET, FALSE}, {"blueat", GCT_BLUEAT, FALSE}, {"bluerfobex", GCT_BLUEOBEX, FALSE}, {"bluefbus", GCT_BLUEFBUS2, FALSE}, {"bluerffbus", GCT_BLUEFBUS2, FALSE}, {"bluerfphonet", GCT_BLUEPHONET, FALSE}, {"bluerfat", GCT_BLUEAT, FALSE}, {"bluerfgnapbus", GCT_BLUEGNAPBUS, FALSE}, {"blues60", GCT_BLUES60, FALSE}, {"bluerfs60", GCT_BLUES60, FALSE}, /* proxy */ {"proxyobex", GCT_PROXYOBEX, FALSE}, {"proxyphonet", GCT_PROXYPHONET, FALSE}, {"proxyat", GCT_PROXYAT, FALSE}, {"proxygnapbus", GCT_PROXYGNAPBUS, FALSE}, {"proxyfbus", GCT_PROXYFBUS2, FALSE}, {"proxys60", GCT_PROXYS60, FALSE}, /* old "serial" irda */ {"infrared", GCT_FBUS2IRDA, FALSE}, {"fbusirda", GCT_FBUS2IRDA, FALSE}, /* socket irda */ {"irda", GCT_IRDAPHONET, FALSE}, {"irdaphonet", GCT_IRDAPHONET, FALSE}, {"irdaat", GCT_IRDAAT, FALSE}, {"irdaobex", GCT_IRDAOBEX, FALSE}, {"irdagnapbus", GCT_IRDAGNAPBUS, FALSE}, /* testing purposes */ {"none", GCT_NONE, FALSE}, }; GSM_Device_Functions NoneDevice = { NONEFUNCTION, NONEFUNCTION, NONEFUNCTION, NONEFUNCTION, NONEFUNCTION, NONEFUNCTION, NONEFUNCTION }; GSM_Protocol_Functions NoProtocol = { NONEFUNCTION, NONEFUNCTION, NONEFUNCTION, NONEFUNCTION }; static GSM_Error GSM_RegisterAllConnections(GSM_StateMachine *s, const char *connection) { size_t i; char *buff, *nodtr_pos, *nopower_pos; /* Copy connection name, so that we can play with it */ buff = strdup(connection); if (buff == NULL) { return ERR_MOREMEMORY; } /* We check here is used connection string type is correct for ANY * OS. If not, we return with error, that string is incorrect at all */ s->ConnectionType = 0; s->SkipDtrRts = FALSE; s->NoPowerCable = FALSE; /* Are we asked for connection using stupid cable? */ nodtr_pos = strcasestr(buff, "-nodtr"); if (nodtr_pos != NULL) { *nodtr_pos = 0; } /* Are we asked for connection using cable which does not * use DTR/RTS as power supply? */ nopower_pos = strcasestr(buff, "-nopower"); if (nopower_pos != NULL) { *nopower_pos = 0; s->NoPowerCable = TRUE; } /* Compare known connections to what we got */ for (i = 0; i < sizeof(GSM_Connections) / sizeof(GSM_Connections[0]); i++) { /* Check connection name */ if (strcasecmp(GSM_Connections[i].Name, buff) == 0) { s->ConnectionType = GSM_Connections[i].Connection; s->SkipDtrRts = GSM_Connections[i].SkipDtrRts; break; } } /* If we were forced, set this flag */ if (nodtr_pos != NULL) { s->SkipDtrRts = TRUE; } /* Special case - at can contains speed */ if (s->ConnectionType == 0 && strncasecmp("at", buff, 2) == 0) { s->Speed = FindSerialSpeed(buff + 2); if (s->Speed != 0) { s->ConnectionType = GCT_AT; } } /* Free allocated memory */ free(buff); buff = NULL; if (s->ConnectionType == 0) { return ERR_UNKNOWNCONNECTIONTYPESTRING; } /* We check now if user gave connection type compiled & available * for used OS (if not, we return, that source not available) */ s->Device.Functions = NULL; s->Protocol.Functions = NULL; GSM_RegisterConnection(s, GCT_NONE, &NoneDevice, &NoProtocol); #ifdef GSM_ENABLE_MBUS2 GSM_RegisterConnection(s, GCT_MBUS2, &SerialDevice, &MBUS2Protocol); #endif #ifdef GSM_ENABLE_FBUS2 GSM_RegisterConnection(s, GCT_FBUS2, &SerialDevice, &FBUS2Protocol); #endif #ifdef GSM_ENABLE_FBUS2DLR3 GSM_RegisterConnection(s, GCT_FBUS2DLR3, &SerialDevice, &FBUS2Protocol); #endif #ifdef GSM_ENABLE_DKU5FBUS2 GSM_RegisterConnection(s, GCT_DKU5FBUS2, &SerialDevice, &FBUS2Protocol); #endif #ifdef GSM_ENABLE_FBUS2PL2303 GSM_RegisterConnection(s, GCT_FBUS2PL2303,&SerialDevice, &FBUS2Protocol); #endif #ifdef GSM_ENABLE_FBUS2BLUE GSM_RegisterConnection(s, GCT_FBUS2BLUE, &SerialDevice, &FBUS2Protocol); #endif #ifdef GSM_ENABLE_FBUS2IRDA GSM_RegisterConnection(s, GCT_FBUS2IRDA, &SerialDevice, &FBUS2Protocol); #endif #if defined(GSM_ENABLE_DKU2PHONET) && defined(GSM_ENABLE_USBDEVICE) GSM_RegisterConnection(s, GCT_FBUS2USB, &FBUSUSBDevice, &PHONETProtocol); #endif #ifdef GSM_ENABLE_DKU2PHONET GSM_RegisterConnection(s, GCT_DKU2PHONET, &SerialDevice, &PHONETProtocol); #endif #ifdef GSM_ENABLE_DKU2AT GSM_RegisterConnection(s, GCT_DKU2AT, &SerialDevice, &ATProtocol); #endif #ifdef GSM_ENABLE_AT GSM_RegisterConnection(s, GCT_AT, &SerialDevice, &ATProtocol); #endif #ifdef GSM_ENABLE_PHONETBLUE GSM_RegisterConnection(s, GCT_PHONETBLUE, &SerialDevice, &PHONETProtocol); #endif #ifdef GSM_ENABLE_IRDAGNAPBUS GSM_RegisterConnection(s, GCT_IRDAGNAPBUS,&IrdaDevice, &GNAPBUSProtocol); #endif #ifdef GSM_ENABLE_IRDAPHONET GSM_RegisterConnection(s, GCT_IRDAPHONET, &IrdaDevice, &PHONETProtocol); #endif #ifdef GSM_ENABLE_IRDAAT GSM_RegisterConnection(s, GCT_IRDAAT, &IrdaDevice, &ATProtocol); #endif #ifdef GSM_ENABLE_IRDAOBEX GSM_RegisterConnection(s, GCT_IRDAOBEX, &IrdaDevice, &OBEXProtocol); #endif #ifdef GSM_ENABLE_BLUEGNAPBUS GSM_RegisterConnection(s, GCT_BLUES60, &BlueToothDevice,&S60Protocol); #endif #ifdef GSM_ENABLE_BLUEGNAPBUS GSM_RegisterConnection(s, GCT_BLUEGNAPBUS,&BlueToothDevice,&GNAPBUSProtocol); #endif #ifdef GSM_ENABLE_BLUEFBUS2 GSM_RegisterConnection(s, GCT_BLUEFBUS2, &BlueToothDevice,&FBUS2Protocol); #endif #ifdef GSM_ENABLE_BLUEPHONET GSM_RegisterConnection(s, GCT_BLUEPHONET, &BlueToothDevice,&PHONETProtocol); #endif #ifdef GSM_ENABLE_BLUEAT GSM_RegisterConnection(s, GCT_BLUEAT, &BlueToothDevice,&ATProtocol); #endif #ifdef GSM_ENABLE_BLUEOBEX GSM_RegisterConnection(s, GCT_BLUEOBEX, &BlueToothDevice,&OBEXProtocol); #endif #if !defined(WIN32) && defined(HAVE_PTHREAD) #ifdef GSM_ENABLE_S60 GSM_RegisterConnection(s, GCT_PROXYS60, &ProxyDevice,&S60Protocol); #endif #ifdef GSM_ENABLE_BLUEGNAPBUS GSM_RegisterConnection(s, GCT_PROXYGNAPBUS,&ProxyDevice,&GNAPBUSProtocol); #endif #ifdef GSM_ENABLE_FBUS2 GSM_RegisterConnection(s, GCT_PROXYFBUS2, &ProxyDevice,&FBUS2Protocol); #endif #ifdef GSM_ENABLE_DKU2PHONET GSM_RegisterConnection(s, GCT_PROXYPHONET, &ProxyDevice,&PHONETProtocol); #endif #ifdef GSM_ENABLE_ATGEN GSM_RegisterConnection(s, GCT_PROXYAT, &ProxyDevice,&ATProtocol); #endif #ifdef GSM_ENABLE_OBEXGEN GSM_RegisterConnection(s, GCT_PROXYOBEX, &ProxyDevice,&OBEXProtocol); #endif #endif if (s->Device.Functions == NULL || s->Protocol.Functions == NULL) { smprintf(s, "Connection %s is know but was disabled on compile time\n", connection); return ERR_DISABLED; } return ERR_NONE; } static void GSM_RegisterModule(GSM_StateMachine *s,GSM_Phone_Functions *phone) { /* Auto model */ if (s->CurrentConfig->Model[0] == 0) { if (strstr(phone->models,GetModelData(s, NULL, s->Phone.Data.Model, NULL)->model) != NULL) { smprintf(s,"[Module - \"%s\"]\n",phone->models); s->Phone.Functions = phone; } } else { if (strstr(phone->models,s->CurrentConfig->Model) != NULL) { smprintf(s,"[Module - \"%s\"]\n",phone->models); s->Phone.Functions = phone; } } } /** * Tries to register all modules to find one matching current configuration. * * \param s State machine pointer. * * \return Error code, ERR_NONE on success. */ GSM_Error GSM_RegisterAllPhoneModules(GSM_StateMachine *s) { GSM_PhoneModel *model; /* Auto model */ if (s->CurrentConfig->Model[0] == 0) { model = GetModelData(s, NULL, s->Phone.Data.Model, NULL); #ifdef GSM_ENABLE_ATGEN /* With ATgen and auto model we can work with unknown models too */ if (s->ConnectionType==GCT_AT || s->ConnectionType==GCT_PROXYAT || s->ConnectionType==GCT_IRDAAT || s->ConnectionType==GCT_DKU2AT) { #ifdef GSM_ENABLE_ALCATEL /* If phone provides Alcatel specific functions, enable them */ if (model->model[0] != 0 && GSM_IsPhoneFeatureAvailable(model, F_ALCATEL)) { smprintf(s,"[Module - \"%s\"]\n",ALCATELPhone.models); s->Phone.Functions = &ALCATELPhone; return ERR_NONE; } #endif #ifdef GSM_ENABLE_ATOBEX /* If phone provides Sony-Ericsson specific functions, enable them */ if (model->model[0] != 0 && GSM_IsPhoneFeatureAvailable(model, F_OBEX)) { smprintf(s,"[Module - \"%s\"]\n",ATOBEXPhone.models); s->Phone.Functions = &ATOBEXPhone; return ERR_NONE; } #endif smprintf(s,"[Module - \"%s\"]\n",ATGENPhone.models); s->Phone.Functions = &ATGENPhone; return ERR_NONE; } #endif /* With OBEXgen and auto model we can work with unknown models too */ #ifdef GSM_ENABLE_OBEXGEN if (s->ConnectionType==GCT_BLUEOBEX || s->ConnectionType==GCT_PROXYOBEX || s->ConnectionType==GCT_IRDAOBEX) { smprintf(s,"[Module - \"%s\"]\n",OBEXGENPhone.models); s->Phone.Functions = &OBEXGENPhone; return ERR_NONE; } #endif #ifdef GSM_ENABLE_BACKUP if (s->ConnectionType == GCT_NONE) { smprintf(s,"[Module - \"%s\"]\n",DUMMYPhone.models); s->Phone.Functions = &DUMMYPhone; return ERR_NONE; } #endif /* With GNAPgen and auto model we can work with unknown models too */ #ifdef GSM_ENABLE_GNAPGEN if (s->ConnectionType == GCT_BLUEGNAPBUS || s->ConnectionType == GCT_PROXYGNAPBUS || s->ConnectionType == GCT_IRDAGNAPBUS) { smprintf(s,"[Module - \"%s\"]\n",GNAPGENPhone.models); s->Phone.Functions = &GNAPGENPhone; return ERR_NONE; } #endif #ifdef GSM_ENABLE_S60 if (s->ConnectionType == GCT_BLUES60 || s->ConnectionType == GCT_PROXYS60) { smprintf(s,"[Module - \"%s\"]\n",S60Phone.models); s->Phone.Functions = &S60Phone; return ERR_NONE; } #endif #ifdef GSM_ENABLE_NOKIA6510 if ( s->ConnectionType == GCT_MBUS2 || s->ConnectionType == GCT_FBUS2 || s->ConnectionType == GCT_FBUS2USB || s->ConnectionType == GCT_FBUS2DLR3 || s->ConnectionType == GCT_FBUS2PL2303 || s->ConnectionType == GCT_FBUS2BLUE || s->ConnectionType == GCT_FBUS2IRDA || s->ConnectionType == GCT_DKU5FBUS2 || s->ConnectionType == GCT_DKU2PHONET || s->ConnectionType == GCT_PHONETBLUE || s->ConnectionType == GCT_IRDAPHONET || s->ConnectionType == GCT_BLUEFBUS2 || s->ConnectionType == GCT_PROXYFBUS2 || s->ConnectionType == GCT_PROXYPHONET || s->ConnectionType == GCT_BLUEPHONET) { /* Try to detect phone type */ if (strcmp(model->model, "unknown") == 0 && model->features[0] == 0) { smprintf(s, "WARNING: phone not known, please report it to authors (see ). Thank you.\n"); if (strncmp(s->Phone.Data.Model, "RM-", 3) == 0) { /* 167 is really a wild guess */ if (atoi(s->Phone.Data.Model + 3) > 167) { smprintf(s, "WARNING: Guessed phone as S40/30 compatible (RM series)!\n"); GSM_AddPhoneFeature(model, F_SERIES40_30); GSM_AddPhoneFeature(model, F_FILES2); GSM_AddPhoneFeature(model, F_TODO66); GSM_AddPhoneFeature(model, F_RADIO); GSM_AddPhoneFeature(model, F_NOTES); GSM_AddPhoneFeature(model, F_SMS_FILES); GSM_AddPhoneFeature(model, F_6230iCALLER); } } if (strncmp(s->Phone.Data.Model, "RH-", 3) == 0) { /* 63 is really a wild guess */ if (atoi(s->Phone.Data.Model + 3) > 63) { smprintf(s, "WARNING: Guessed phone as S40/30 compatible (RH series)!\n"); GSM_AddPhoneFeature(model, F_SERIES40_30); GSM_AddPhoneFeature(model, F_FILES2); GSM_AddPhoneFeature(model, F_TODO66); GSM_AddPhoneFeature(model, F_RADIO); GSM_AddPhoneFeature(model, F_NOTES); GSM_AddPhoneFeature(model, F_SMS_FILES); } } } /* If phone is S40, use 6510 */ if (GSM_IsPhoneFeatureAvailable(model, F_SERIES40_30)) { smprintf(s,"[Module - \"%s\"]\n", N6510Phone.models); s->Phone.Functions = &N6510Phone; return ERR_NONE; } } #endif if (model->model[0] == 0) return ERR_UNKNOWNMODELSTRING; } s->Phone.Functions = NULL; #ifdef GSM_ENABLE_ATGEN /* AT module can have the same models ID to "normal" Nokia modules */ if (s->ConnectionType==GCT_AT || s->ConnectionType==GCT_PROXYAT || s->ConnectionType==GCT_BLUEAT || s->ConnectionType==GCT_IRDAAT || s->ConnectionType==GCT_DKU2AT) { GSM_RegisterModule(s,&ATGENPhone); if (s->Phone.Functions != NULL) return ERR_NONE; } #endif #ifdef GSM_ENABLE_BACKUP GSM_RegisterModule(s, &DUMMYPhone); #endif #ifdef GSM_ENABLE_OBEXGEN GSM_RegisterModule(s,&OBEXGENPhone); #endif #ifdef GSM_ENABLE_GNAPGEN GSM_RegisterModule(s,&GNAPGENPhone); #endif #ifdef GSM_ENABLE_S60 GSM_RegisterModule(s,&S60Phone); #endif #ifdef GSM_ENABLE_NOKIA3320 GSM_RegisterModule(s,&N3320Phone); #endif #ifdef GSM_ENABLE_NOKIA3650 GSM_RegisterModule(s,&N3650Phone); #endif #ifdef GSM_ENABLE_NOKIA650 GSM_RegisterModule(s,&N650Phone); #endif #ifdef GSM_ENABLE_NOKIA6110 GSM_RegisterModule(s,&N6110Phone); #endif #ifdef GSM_ENABLE_NOKIA6510 GSM_RegisterModule(s,&N6510Phone); #endif #ifdef GSM_ENABLE_NOKIA7110 GSM_RegisterModule(s,&N7110Phone); #endif #ifdef GSM_ENABLE_NOKIA9210 GSM_RegisterModule(s,&N9210Phone); #endif #ifdef GSM_ENABLE_ALCATEL GSM_RegisterModule(s,&ALCATELPhone); #endif #ifdef GSM_ENABLE_ATOBEX GSM_RegisterModule(s,&ATOBEXPhone); #endif if (s->Phone.Functions == NULL) { return ERR_UNKNOWNMODELSTRING; } return ERR_NONE; } /** * Opens connection to device and initiates protocol layer. */ GSM_Error GSM_OpenConnection(GSM_StateMachine *s) { GSM_Error error; if (s->CurrentConfig->LockDevice) { error = lock_device(s, s->CurrentConfig->Device, &(s->LockFile)); if (error != ERR_NONE) return error; } /* Irda devices can set now model to some specific and * we don't have to make auto detection later */ error=s->Device.Functions->OpenDevice(s); if (error!=ERR_NONE) { if (s->LockFile != NULL) unlock_device(s, &(s->LockFile)); return error; } s->opened = TRUE; error=s->Protocol.Functions->Initialise(s); if (error!=ERR_NONE) return error; return ERR_NONE; } /** * Internal function which just closes connection and cleans up structures. */ GSM_Error GSM_CloseConnection(GSM_StateMachine *s) { GSM_Error error; smprintf(s, "[Closing]\n"); /* Terminate protocol */ error = s->Protocol.Functions->Terminate(s); if (error != ERR_NONE) return error; /* Close the device */ error = s->Device.Functions->CloseDevice(s); if (error != ERR_NONE) return error; /* Release lock if there was any */ if (s->LockFile != NULL) { unlock_device(s, &(s->LockFile)); } /* Null all structures in case we will be asked for new initialisation */ s->Phone.Data.ModelInfo = NULL; s->Phone.Data.Manufacturer[0] = 0; s->Phone.Data.Model[0] = 0; s->Phone.Data.Version[0] = 0; s->Phone.Data.VerDate[0] = 0; s->Phone.Data.VerNum = 0; return ERR_NONE; } /** * Tries to read model using configured phone connection. */ GSM_Error GSM_TryGetModel(GSM_StateMachine *s) { GSM_Error error; error = GSM_OpenConnection(s); if (error != ERR_NONE) return error; /* If still auto model, try to get model by asking phone for it */ if (s->Phone.Data.Model[0]==0) { smprintf(s,"[Module - \"auto\"]\n"); switch (s->ConnectionType) { #ifdef GSM_ENABLE_BACKUP case GCT_NONE: s->Phone.Functions = &DUMMYPhone; break; #endif #ifdef GSM_ENABLE_ATGEN case GCT_AT: case GCT_BLUEAT: case GCT_PROXYAT: case GCT_IRDAAT: case GCT_DKU2AT: s->Phone.Functions = &ATGENPhone; break; #endif #ifdef GSM_ENABLE_OBEXGEN case GCT_IRDAOBEX: case GCT_PROXYOBEX: case GCT_BLUEOBEX: s->Phone.Functions = &OBEXGENPhone; break; #endif #ifdef GSM_ENABLE_GNAPGEN case GCT_BLUEGNAPBUS: case GCT_PROXYGNAPBUS: case GCT_IRDAGNAPBUS: s->Phone.Functions = &GNAPGENPhone; break; #endif #ifdef GSM_ENABLE_S60 case GCT_BLUES60: case GCT_PROXYS60: s->Phone.Functions = &S60Phone; break; #endif #if defined(GSM_ENABLE_NOKIA_DCT3) || defined(GSM_ENABLE_NOKIA_DCT4) case GCT_MBUS2: case GCT_FBUS2: case GCT_FBUS2USB: case GCT_FBUS2DLR3: case GCT_FBUS2PL2303: case GCT_FBUS2BLUE: case GCT_FBUS2IRDA: case GCT_DKU5FBUS2: case GCT_DKU2PHONET: case GCT_PHONETBLUE: case GCT_IRDAPHONET: case GCT_BLUEFBUS2: case GCT_PROXYFBUS2: case GCT_BLUEPHONET: case GCT_PROXYPHONET: s->Phone.Functions = &NAUTOPhone; break; #endif default: s->Phone.Functions = NULL; } /* Did we find matching phone driver? */ if (s->Phone.Functions == NULL) { smprintf(s, "ERROR: Could not find proper module for autodetection!\n"); return ERR_UNKNOWN; } /* Initialize the phone driver */ error = s->Phone.Functions->Initialise(s); if (error != ERR_NONE) return error; /* Get model name from phone */ error = s->Phone.Functions->GetModel(s); if (error != ERR_NONE) return error; /* And terminate it again */ error = s->Phone.Functions->Terminate(s); if (error != ERR_NONE) return error; } return ERR_NONE; } GSM_Error GSM_InitConnection_Log(GSM_StateMachine *s, int ReplyNum, GSM_Log_Function log_function, void *user_data) { GSM_Error error; GSM_DateTime current_time; int i; for (i=0;iConfigNum;i++) { s->CurrentConfig = &s->Config[i]; /* Skip non configured sections */ if (s->CurrentConfig->Connection == NULL) { smprintf_level(s, D_ERROR, "[Empty section - %d]\n", i); continue; } s->Speed = 0; s->ReplyNum = ReplyNum; s->Phone.Data.ModelInfo = GetModelData(s, "unknown", NULL, NULL); s->Phone.Data.Manufacturer[0] = 0; s->Phone.Data.Model[0] = 0; s->Phone.Data.Version[0] = 0; s->Phone.Data.VerDate[0] = 0; s->Phone.Data.VerNum = 0; s->Phone.Data.StartInfoCounter = 0; s->Phone.Data.SentMsg = NULL; s->Phone.Data.HardwareCache[0] = 0; s->Phone.Data.ProductCodeCache[0] = 0; s->Phone.Data.EnableIncomingCall = FALSE; s->Phone.Data.EnableIncomingSMS = FALSE; s->Phone.Data.EnableIncomingCB = FALSE; s->Phone.Data.EnableIncomingUSSD = FALSE; s->User.UserReplyFunctions = NULL; s->User.IncomingCall = NULL; s->User.IncomingSMS = NULL; s->User.IncomingCB = NULL; s->User.IncomingUSSD = NULL; s->User.SendSMSStatus = NULL; s->LockFile = NULL; s->opened = FALSE; s->Phone.Functions = NULL; s->di = GSM_none_debug; s->di.use_global = s->CurrentConfig->UseGlobalDebugFile; if (!s->di.use_global) { GSM_SetDebugFunction(log_function, user_data, &s->di); GSM_SetDebugLevel(s->CurrentConfig->DebugLevel, &s->di); error = GSM_SetDebugFile(s->CurrentConfig->DebugFile, &s->di); if (error != ERR_NONE) { GSM_LogError(s, "Init:GSM_SetDebugFile" , error); return error; } } smprintf_level(s, D_ERROR, "[Gammu - %s]\n", GAMMU_VERSION); StripSpaces(s->CurrentConfig->Connection); StripSpaces(s->CurrentConfig->Model); StripSpaces(s->CurrentConfig->Device); smprintf_level(s, D_ERROR, "[Connection - \"%s\"]\n", s->CurrentConfig->Connection); smprintf_level(s, D_ERROR, "[Connection index - %d]\n", i); smprintf_level(s, D_ERROR, "[Model type - \"%s\"]\n", s->CurrentConfig->Model); smprintf_level(s, D_ERROR, "[Device - \"%s\"]\n", s->CurrentConfig->Device); if (strlen(GetOS()) != 0) { smprintf_level(s, D_ERROR, "[Running on - %s]\n", GetOS()); } if (GSM_GetDI(s)->dl == DL_BINARY) { smprintf(s,"%c",((unsigned char)strlen(GAMMU_VERSION))); smprintf(s,"%s",GAMMU_VERSION); } error = GSM_RegisterAllConnections(s, s->CurrentConfig->Connection); if (error != ERR_NONE) { GSM_LogError(s, "Init:GSM_RegisterAllConnections" , error); return error; } autodetect: /* Model auto */ /* Try to guess correct driver based on model */ if (s->CurrentConfig->Model[0] == 0 && s->ConnectionType != GCT_NONE && s->ConnectionType != GCT_IRDAOBEX && s->ConnectionType != GCT_BLUEOBEX && s->ConnectionType != GCT_PROXYOBEX && s->ConnectionType != GCT_BLUEGNAPBUS && s->ConnectionType != GCT_PROXYGNAPBUS && s->ConnectionType != GCT_IRDAGNAPBUS && s->ConnectionType != GCT_PROXYS60 && s->ConnectionType != GCT_BLUES60) { error = GSM_TryGetModel(s); /* Fall back to other configuraitons if the device is not existing (or similar error) */ if ((i != s->ConfigNum - 1) && ( (error == ERR_DEVICEOPENERROR) || (error == ERR_DEVICELOCKED) || (error == ERR_DEVICENOTEXIST) || (error == ERR_DEVICEBUSY) || (error == ERR_DEVICENOPERMISSION) || (error == ERR_DEVICENODRIVER) || (error == ERR_DEVICENOTWORK))) { GSM_CloseConnection(s); continue; } if (error != ERR_NONE) { GSM_LogError(s, "Init:GSM_TryGetModel" , error); return error; } } /* Switching to "correct" module */ error = GSM_RegisterAllPhoneModules(s); /* If user selected soemthing which is not supported, try autodetection */ if (s->CurrentConfig->Model[0] != 0 && error == ERR_UNKNOWNMODELSTRING) { smprintf(s, "Configured model %s is not known, retrying with autodetection!\n", s->CurrentConfig->Model); s->CurrentConfig->Model[0] = 0; goto autodetect; } if (error != ERR_NONE) { GSM_LogError(s, "Init:GSM_RegisterAllPhoneModules" , error); return error; } /* We didn't open device earlier ? Make it now */ if (!s->opened) { error = GSM_OpenConnection(s); if ((i != s->ConfigNum - 1) && ( (error == ERR_DEVICEOPENERROR) || (error == ERR_DEVICELOCKED) || (error == ERR_DEVICENOTEXIST) || (error == ERR_DEVICEBUSY) || (error == ERR_DEVICENOPERMISSION) || (error == ERR_DEVICENODRIVER) || (error == ERR_DEVICENOTWORK))) { GSM_CloseConnection(s); continue; } if (error != ERR_NONE) { GSM_LogError(s, "Init:GSM_OpenConnection" , error); return error; } } /* Initialize phone layer */ error=s->Phone.Functions->Initialise(s); if (error == ERR_TIMEOUT && i != s->ConfigNum - 1) { GSM_CloseConnection(s); continue; } if (error != ERR_NONE) { GSM_LogError(s, "Init:Phone->Initialise" , error); return error; } if (s->CurrentConfig->StartInfo) { s->Phone.Functions->ShowStartInfo(s,TRUE); s->Phone.Data.StartInfoCounter = 30; } if (s->CurrentConfig->SyncTime) { GSM_GetCurrentDateTime (¤t_time); s->Phone.Functions->SetDateTime(s,¤t_time); } /* For debug it's good to have firmware and real model version and manufacturer */ error=s->Phone.Functions->GetManufacturer(s); if (error == ERR_TIMEOUT && i != s->ConfigNum - 1) { GSM_CloseConnection(s); continue; } if (error != ERR_NONE && error != ERR_NOTSUPPORTED) { GSM_LogError(s, "Init:Phone->GetManufacturer" , error); return error; } error=s->Phone.Functions->GetModel(s); if (error != ERR_NONE && error != ERR_NOTSUPPORTED) { GSM_LogError(s, "Init:Phone->GetModel" , error); return error; } error=s->Phone.Functions->GetFirmware(s); if (error != ERR_NONE && error != ERR_NOTSUPPORTED) { GSM_LogError(s, "Init:Phone->GetFirmware" , error); return error; } error=s->Phone.Functions->PostConnect(s); if (error != ERR_NONE && error != ERR_NOTSUPPORTED) { GSM_LogError(s, "Init:Phone->PostConnect" , error); return error; } smprintf(s,"[Connected]\n"); return ERR_NONE; } return ERR_UNCONFIGURED; } GSM_Error GSM_InitConnection(GSM_StateMachine *s, int ReplyNum) { return GSM_InitConnection_Log(s, ReplyNum, GSM_none_debug.log_function, GSM_none_debug.user_data); } int GSM_ReadDevice (GSM_StateMachine *s, gboolean waitforreply) { GSM_DateTime Date; unsigned char buff[65536]={'\0'}; int res=0,count=0,i=0; if (!GSM_IsConnected(s)) { return -1; } GSM_GetCurrentDateTime (&Date); i = Date.Second; while (i == Date.Second && !s->Abort) { res = s->Device.Functions->ReadDevice(s, buff, sizeof(buff)); if (!waitforreply) { break; } if (res > 0) { break; } usleep(5000); GSM_GetCurrentDateTime(&Date); } for (count = 0; count < res; count++) { s->Protocol.Functions->StateMachine(s, buff[count]); } return res; } GSM_Error GSM_TerminateConnection(GSM_StateMachine *s) { GSM_Error error; if (!s->opened) return ERR_NONE; smprintf(s,"[Terminating]\n"); if (s->CurrentConfig->StartInfo) { if (s->Phone.Data.StartInfoCounter > 0) s->Phone.Functions->ShowStartInfo(s,FALSE); } if (s->Phone.Functions != NULL) { error=s->Phone.Functions->Terminate(s); if (error!=ERR_NONE) return error; } error = GSM_CloseConnection(s); if (error != ERR_NONE) return error; GSM_SetDebugFileDescriptor(NULL, FALSE, &(s->di)); s->opened = FALSE; return ERR_NONE; } gboolean GSM_IsConnected(GSM_StateMachine *s) { return (s != NULL) && s->Phone.Functions != NULL && s->opened; } GSM_Error GSM_AbortOperation(GSM_StateMachine * s) { s->Abort = TRUE; return ERR_NONE; } GSM_Error GSM_WaitForOnce(GSM_StateMachine *s, unsigned const char *buffer, int length, int type, int timeout) { GSM_Phone_Data *Phone = &s->Phone.Data; GSM_Protocol_Message sentmsg; int i = 0; do { if (length != 0) { sentmsg.Length = length; sentmsg.Type = type; sentmsg.Buffer = (unsigned char *)malloc(length); memcpy(sentmsg.Buffer, buffer, length); Phone->SentMsg = &sentmsg; } /* Some data received. Reset timer */ if (GSM_ReadDevice(s, TRUE) > 0) { i = 0; } else { usleep(10000); } if (length != 0) { free(sentmsg.Buffer); sentmsg.Buffer = NULL; Phone->SentMsg = NULL; } if (s->Abort) { return ERR_ABORTED; } /* Request completed */ if (Phone->RequestID == ID_None) { return Phone->DispatchError; } i++; } while (i < timeout); return ERR_TIMEOUT; } GSM_Error GSM_WaitFor (GSM_StateMachine *s, unsigned const char *buffer, int length, int type, int timeout, GSM_Phone_RequestID request) { GSM_Phone_Data *Phone = &s->Phone.Data; GSM_Error error; int reply; if (s->CurrentConfig->StartInfo) { if (Phone->StartInfoCounter > 0) { Phone->StartInfoCounter--; if (Phone->StartInfoCounter == 0) { s->Phone.Functions->ShowStartInfo(s,FALSE); } } } Phone->RequestID = request; Phone->DispatchError = ERR_TIMEOUT; for (reply = 0; reply < s->ReplyNum; reply++) { if (reply != 0) { smprintf_level(s, D_ERROR, "[Retrying %i type 0x%02X]\n", reply, type); } error = s->Protocol.Functions->WriteMessage(s, buffer, length, type); if (error != ERR_NONE) { return error; } /* Special case when no reply is expected */ if (request == ID_None) { return ERR_NONE; } error = GSM_WaitForOnce(s, buffer, length, type, timeout); if (error != ERR_TIMEOUT) { return error; } } if (request != ID_Reset && GSM_IsPhoneFeatureAvailable(s->Phone.Data.ModelInfo, F_RESET_AFTER_TIMEOUT)) { smprintf_level(s, D_ERROR, "Performing device reset after timeout!\n"); GSM_Reset(s, FALSE); } return ERR_TIMEOUT; } static GSM_Error CheckReplyFunctions(GSM_StateMachine *s, GSM_Reply_Function *Reply, int *reply) { GSM_Phone_Data *Data = &s->Phone.Data; GSM_Protocol_Message *msg = s->Phone.Data.RequestMsg; gboolean execute; gboolean available = FALSE; int i = 0; while (Reply[i].requestID != ID_None) { execute = FALSE; /* Long ID frames like S60 */ if (Reply[i].msgtype[0] == 0 && Reply[i].subtypechar == 0) { if (Reply[i].subtype == msg->Type) { execute = TRUE; } /* Binary frames like in Nokia */ } else if (strlen(Reply[i].msgtype) < 2) { if (Reply[i].msgtype[0]==msg->Type) { if (Reply[i].subtypechar!=0) { if (Reply[i].subtypechar<=msg->Length) { if (msg->Buffer[Reply[i].subtypechar]==Reply[i].subtype) execute=TRUE; } } else { execute=TRUE; } } } else { if (strlen(Reply[i].msgtype) < msg->Length) { if (strncmp(Reply[i].msgtype,msg->Buffer,strlen(Reply[i].msgtype))==0) { execute=TRUE; } } } if (execute) { *reply = i; if (Reply[i].requestID == ID_IncomingFrame || Reply[i].requestID == Data->RequestID || Data->RequestID == ID_EachFrame) { return ERR_NONE; } available = TRUE; } i++; } if (available) { return ERR_FRAMENOTREQUESTED; } else { return ERR_UNKNOWNFRAME; } } GSM_Error GSM_DispatchMessage(GSM_StateMachine *s) { GSM_Error error = ERR_UNKNOWNFRAME; GSM_Protocol_Message *msg = s->Phone.Data.RequestMsg; GSM_Phone_Data *Phone = &s->Phone.Data; gboolean disp = FALSE; GSM_Reply_Function *Reply; int reply; GSM_DumpMessageTextRecv(s, msg->Buffer, msg->Length, msg->Type); GSM_DumpMessageBinaryRecv(s, msg->Buffer, msg->Length, msg->Type); Reply = s->User.UserReplyFunctions; if (Reply != NULL) { error = CheckReplyFunctions(s, Reply, &reply); } if (error == ERR_UNKNOWNFRAME) { Reply = s->Phone.Functions->ReplyFunctions; error = CheckReplyFunctions(s, Reply, &reply); } if (error == ERR_NONE) { error = Reply[reply].Function(msg, s); if (Reply[reply].requestID == Phone->RequestID) { if (error == ERR_NEEDANOTHERANSWER) { error = ERR_NONE; } else { Phone->RequestID = ID_None; } } } if (strcmp(s->Phone.Functions->models,"NAUTO")) { disp = TRUE; switch (error) { case ERR_UNKNOWNRESPONSE: smprintf_level(s, D_ERROR, "\nUNKNOWN response"); break; case ERR_UNKNOWNFRAME: smprintf_level(s, D_ERROR, "\nUNKNOWN frame"); break; case ERR_FRAMENOTREQUESTED: smprintf_level(s, D_ERROR, "\nFrame not request now"); break; default: disp = FALSE; } if (error == ERR_UNKNOWNFRAME || error == ERR_FRAMENOTREQUESTED) { error = ERR_TIMEOUT; } } if (disp) { smprintf(s,". Please report the error, see . Thank you\n"); if (Phone->SentMsg != NULL) { smprintf(s,"LAST SENT frame "); smprintf(s, "type 0x%02X/length %ld", Phone->SentMsg->Type, (long)Phone->SentMsg->Length); DumpMessage(GSM_GetDI(s), Phone->SentMsg->Buffer, Phone->SentMsg->Length); } smprintf(s, "RECEIVED frame "); smprintf(s, "type 0x%02X/length 0x%lx/%ld", msg->Type, (long)msg->Length, (long)msg->Length); DumpMessage(GSM_GetDI(s), msg->Buffer, msg->Length); smprintf(s, "\n"); } return error; } GSM_Error GSM_TryReadGammuRC (const char *path, INI_Section **result) { dbgprintf(NULL, "Open config: \"%s\"\n", path); return INI_ReadFile(path, FALSE, result); } GSM_Error GSM_FindGammuRC (INI_Section **result, const char *force_config) { char configfile[PATH_MAX + 1]; char *envpath; GSM_Error error; #if defined(HAVE_GETPWUID) && defined(HAVE_GETUID) struct passwd *pwent; #endif *result = NULL; if (force_config != NULL) { return GSM_TryReadGammuRC(force_config, result); } #ifdef WIN32 /* Get Windows application data path */ if (SUCCEEDED(SHGetFolderPath(NULL, CSIDL_APPDATA, NULL, SHGFP_TYPE_CURRENT, configfile))) { strcat(configfile, GAMMURC_NAME); error = GSM_TryReadGammuRC(configfile, result); if (error == ERR_NONE) return ERR_NONE; } #endif /* XDG paths */ envpath = getenv("XDG_CONFIG_HOME"); if (envpath) { strcpy(configfile, envpath); strcat(configfile, XDG_GAMMURC_NAME); error = GSM_TryReadGammuRC(configfile, result); if (error == ERR_NONE) return ERR_NONE; } else { envpath = getenv("HOME"); if (envpath) { strcpy(configfile, envpath); strcat(configfile, "/.config"); strcat(configfile, XDG_GAMMURC_NAME); error = GSM_TryReadGammuRC(configfile, result); if (error == ERR_NONE) return ERR_NONE; } } /* Try home from environment */ envpath = getenv("HOME"); if (envpath) { strcpy(configfile, envpath); strcat(configfile, GAMMURC_NAME); error = GSM_TryReadGammuRC(configfile, result); if (error == ERR_NONE) return ERR_NONE; } #if defined(HAVE_GETPWUID) && defined(HAVE_GETUID) /* Tru home from passwd */ pwent = getpwuid(getuid()); if (pwent != NULL) { strcpy(configfile, pwent->pw_dir); strcat(configfile, GAMMURC_NAME); error = GSM_TryReadGammuRC(configfile, result); if (error == ERR_NONE) return ERR_NONE; } #endif #if defined(WIN32) /* Reset as we're using strcat */ configfile[0] = 0; /* This makes sense only on Windows */ envpath = getenv("HOMEDRIVE"); if (envpath) { strcat(configfile, envpath); } envpath = getenv("HOMEPATH"); if (envpath) { strcat(configfile, envpath); strcat(configfile, GAMMURC_NAME); error = GSM_TryReadGammuRC(configfile, result); if (error == ERR_NONE) return ERR_NONE; } #endif /* Try fallback config as last */ return GSM_TryReadGammuRC(FALLBACK_GAMMURC, result); } GSM_Config *GSM_GetConfig(GSM_StateMachine *s, int num) { if (num == -1) { return s->CurrentConfig; } else { if (num > MAX_CONFIG_NUM) return NULL; return &(s->Config[num]); } } int GSM_GetConfigNum(const GSM_StateMachine *s) { return s->ConfigNum; } void GSM_SetConfigNum(GSM_StateMachine *s, int sections) { if (sections > MAX_CONFIG_NUM) return; s->ConfigNum = sections; } /** * Expand path to user home. */ void GSM_ExpandUserPath(char **string) { char *tmp = NULL, *home = NULL; /* Is there something to expand */ if (*string[0] != '~') return; /* Grab home */ home = getenv("HOME"); if (home == NULL) return; /* Allocate memory */ tmp = (char *)malloc(strlen(home) + strlen(*string) + 2); if (tmp == NULL) return; /* Create final path */ strcpy(tmp, home); strcat(tmp, *string + 1); /* Free old storage and replace it */ free(*string); *string = tmp; } GSM_Error GSM_ReadConfig(INI_Section *cfg_info, GSM_Config *cfg, int num) { INI_Section *h; unsigned char section[50]={0}; gboolean found = FALSE; char *Temp = NULL; GSM_Error error = ERR_UNKNOWN; cfg->UseGlobalDebugFile = TRUE; /* If we don't have valid config, bail out */ if (cfg_info == NULL) { error = ERR_UNCONFIGURED; goto fail; } /* Which section should we read? */ if (num == 0) { snprintf(section, sizeof(section) - 1, "gammu"); } else { snprintf(section, sizeof(section) - 1, "gammu%i", num); } /* Scan for section */ for (h = cfg_info; h != NULL; h = h->Next) { if (strcasecmp(section, h->SectionName) == 0) { found = TRUE; break; } } if (!found) { error = ERR_NONE_SECTION; goto fail; } /* Set device name */ free(cfg->Device); cfg->Device = INI_GetValue(cfg_info, section, "device", FALSE); if (!cfg->Device) { cfg->Device = INI_GetValue(cfg_info, section, "port", FALSE); if (!cfg->Device) { cfg->Device = strdup(DEFAULT_DEVICE); } else { cfg->Device = strdup(cfg->Device); } } else { cfg->Device = strdup(cfg->Device); } /* Set connection type */ free(cfg->Connection); cfg->Connection = INI_GetValue(cfg_info, section, "connection", FALSE); if (cfg->Connection == NULL) { cfg->Connection = strdup(DEFAULT_CONNECTION); } else { cfg->Connection = strdup(cfg->Connection); } /* Set time sync */ cfg->SyncTime = INI_GetBool(cfg_info, section, "synchronizetime", DEFAULT_SYNCHRONIZE_TIME); /* Set debug file */ free(cfg->DebugFile); cfg->DebugFile = INI_GetValue(cfg_info, section, "logfile", FALSE); if (cfg->DebugFile == NULL) { cfg->DebugFile = strdup(DEFAULT_DEBUG_FILE); } else { cfg->DebugFile = strdup(cfg->DebugFile); GSM_ExpandUserPath(&cfg->DebugFile); } /* Set file locking */ cfg->LockDevice = INI_GetBool(cfg_info, section, "use_locking", DEFAULT_LOCK_DEVICE); /* Set model */ Temp = INI_GetValue(cfg_info, section, "model", FALSE); if (Temp == NULL || strcmp(Temp, "auto") == 0) { strcpy(cfg->Model,DEFAULT_MODEL); } else { if (strlen(Temp) >= sizeof(cfg->Model)) Temp[sizeof(cfg->Model) - 1] = '\0'; strcpy(cfg->Model,Temp); } /* Set Log format */ Temp = INI_GetValue(cfg_info, section, "logformat", FALSE); if (Temp == NULL) { strcpy(cfg->DebugLevel,DEFAULT_DEBUG_LEVEL); } else { if (strlen(Temp) >= sizeof(cfg->DebugLevel)) Temp[sizeof(cfg->DebugLevel) - 1] = '\0'; strcpy(cfg->DebugLevel,Temp); } /* Set startup info */ cfg->StartInfo = INI_GetBool(cfg_info, section, "startinfo", DEFAULT_START_INFO); /* Read localised strings for some phones */ Temp = INI_GetValue(cfg_info, section, "reminder", FALSE); if (Temp == NULL) { strcpy(cfg->TextReminder,"Reminder"); } else { if (strlen(Temp) >= sizeof(cfg->TextReminder)) Temp[sizeof(cfg->TextReminder) - 1] = '\0'; strcpy(cfg->TextReminder,Temp); } Temp = INI_GetValue(cfg_info, section, "meeting", FALSE); if (Temp == NULL) { strcpy(cfg->TextMeeting,"Meeting"); } else { if (strlen(Temp) >= sizeof(cfg->TextMeeting)) Temp[sizeof(cfg->TextMeeting) - 1] = '\0'; strcpy(cfg->TextMeeting,Temp); } Temp = INI_GetValue(cfg_info, section, "call", FALSE); if (Temp == NULL) { strcpy(cfg->TextCall,"Call"); } else { if (strlen(Temp) >= sizeof(cfg->TextCall)) Temp[sizeof(cfg->TextCall) - 1] = '\0'; strcpy(cfg->TextCall,Temp); } Temp = INI_GetValue(cfg_info, section, "birthday", FALSE); if (Temp == NULL) { strcpy(cfg->TextBirthday,"Birthday"); } else { if (strlen(Temp) >= sizeof(cfg->TextBirthday)) Temp[sizeof(cfg->TextBirthday) - 1] = '\0'; strcpy(cfg->TextBirthday,Temp); } Temp = INI_GetValue(cfg_info, section, "memo", FALSE); if (Temp == NULL) { strcpy(cfg->TextMemo,"Memo"); } else { if (strlen(Temp) >= sizeof(cfg->TextMemo)) Temp[sizeof(cfg->TextMemo) - 1] = '\0'; strcpy(cfg->TextMemo,Temp); } /* Phone features */ Temp = INI_GetValue(cfg_info, section, "features", FALSE); if (Temp == NULL) { cfg->PhoneFeatures[0] = 0; } else { error = GSM_SetFeatureString(cfg->PhoneFeatures, Temp); if (error != ERR_NONE) { goto fail; } } return ERR_NONE; fail: /* Special case, this config needs to be somehow valid */ if (num == 0) { cfg->Device = strdup(DEFAULT_DEVICE); cfg->Connection = strdup(DEFAULT_CONNECTION); cfg->SyncTime = DEFAULT_SYNCHRONIZE_TIME; cfg->DebugFile = strdup(DEFAULT_DEBUG_FILE); cfg->LockDevice = DEFAULT_LOCK_DEVICE; strcpy(cfg->Model,DEFAULT_MODEL); strcpy(cfg->DebugLevel,DEFAULT_DEBUG_LEVEL); cfg->StartInfo = DEFAULT_START_INFO; strcpy(cfg->TextReminder,"Reminder"); strcpy(cfg->TextMeeting,"Meeting"); strcpy(cfg->TextCall,"Call"); strcpy(cfg->TextBirthday,"Birthday"); strcpy(cfg->TextMemo,"Memo"); cfg->PhoneFeatures[0] = 0; /* Indicate that we used defaults */ return ERR_USING_DEFAULTS; } return error; } void GSM_DumpMessageText_Custom(GSM_StateMachine *s, unsigned const char *message, int messagesize, int type, const char *text) { GSM_Debug_Info *curdi; curdi = GSM_GetDI(s); if (curdi->dl == DL_TEXT || curdi->dl == DL_TEXTALL || curdi->dl == DL_TEXTDATE || curdi->dl == DL_TEXTALLDATE) { smprintf(s, "%s ", text); smprintf(s, "type 0x%02X/length 0x%02X/%i", type, messagesize, messagesize); DumpMessage(curdi, message, messagesize); } } void GSM_DumpMessageText(GSM_StateMachine *s, unsigned const char *message, int messagesize, int type) { GSM_DumpMessageText_Custom(s, message, messagesize, type, "SENDING frame"); } void GSM_DumpMessageTextRecv(GSM_StateMachine *s, unsigned const char *message, int messagesize, int type) { GSM_DumpMessageText_Custom(s, message, messagesize, type, "RECEIVED frame"); } void GSM_DumpMessageBinary_Custom(GSM_StateMachine *s, unsigned const char *message, int messagesize, int type, int direction) { int i=0; GSM_Debug_Info *curdi; curdi = GSM_GetDI(s); if (curdi->dl == DL_BINARY) { smprintf(s,"%c", direction); smprintf(s,"%c",type); smprintf(s,"%c",messagesize/256); smprintf(s,"%c",messagesize%256); for (i=0;idl == DL_TEXTERROR || curdi->dl == DL_TEXT || curdi->dl == DL_TEXTALL || curdi->dl == DL_TEXTERRORDATE || curdi->dl == DL_TEXTDATE || curdi->dl == DL_TEXTALLDATE) { FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, GetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), /* Default language */ (LPTSTR) &lpMsgBuf, 0, NULL ); for (i=0;i<(int)strlen(lpMsgBuf);i++) { if (lpMsgBuf[i] == 13 || lpMsgBuf[i] == 10) { lpMsgBuf[i] = ' '; } } smprintf(s,"[System error - %s, %i, \"%s\"]\n", description, (int)GetLastError(), (LPCTSTR)lpMsgBuf); LocalFree(lpMsgBuf); } } #else if (errno!=-1) { if (curdi->dl == DL_TEXTERROR || curdi->dl == DL_TEXT || curdi->dl == DL_TEXTALL || curdi->dl == DL_TEXTERRORDATE || curdi->dl == DL_TEXTDATE || curdi->dl == DL_TEXTALLDATE) { smprintf(s,"[System error - %s, %i, \"%s\"]\n",description,errno,strerror(errno)); } } #endif } void GSM_SetIncomingCallCallback(GSM_StateMachine *s, IncomingCallCallback callback, void *user_data) { s->User.IncomingCall = callback; s->User.IncomingCallUserData = user_data; } void GSM_SetIncomingSMSCallback(GSM_StateMachine *s, IncomingSMSCallback callback, void *user_data) { s->User.IncomingSMS = callback; s->User.IncomingSMSUserData = user_data; } void GSM_SetIncomingCBCallback(GSM_StateMachine *s, IncomingCBCallback callback, void *user_data) { s->User.IncomingCB = callback; s->User.IncomingCBUserData = user_data; } void GSM_SetIncomingUSSDCallback(GSM_StateMachine *s, IncomingUSSDCallback callback, void *user_data) { s->User.IncomingUSSD = callback; s->User.IncomingUSSDUserData = user_data; } void GSM_SetSendSMSStatusCallback(GSM_StateMachine *s, SendSMSStatusCallback callback, void *user_data) { s->User.SendSMSStatus = callback; s->User.SendSMSStatusUserData = user_data; } GSM_StateMachine *GSM_AllocStateMachine(void) { GSM_StateMachine *ret; ret = (GSM_StateMachine *)calloc(1, sizeof(GSM_StateMachine)); if (ret == NULL) { return ret; } ret->CurrentConfig = &(ret->Config[0]); ret->Abort = FALSE; return ret; } void GSM_FreeStateMachine(GSM_StateMachine *s) { int i=0; if (s == NULL) return; /* Free allocated memory */ for (i = 0; i <= MAX_CONFIG_NUM; i++) { free(s->Config[i].Device); s->Config[i].Device = NULL; free(s->Config[i].Connection); s->Config[i].Connection = NULL; free(s->Config[i].DebugFile); s->Config[i].DebugFile = NULL; } free(s); s = NULL; } GSM_ConnectionType GSM_GetUsedConnection(GSM_StateMachine *s) { return s->ConnectionType; } GSM_PhoneModel *GSM_GetModelInfo(GSM_StateMachine *s) { return s->Phone.Data.ModelInfo; } GSM_Debug_Info *GSM_GetDebug(GSM_StateMachine *s) { return s == NULL ? NULL : &(s->di); } /* How should editor hadle tabs in this file? Add editor commands here. * vim: noexpandtab sw=8 ts=8 sts=8: */