"Fossies" - the Fresh Open Source Software Archive

Member "gammu-1.42.0/libgammu/gsmstate.c" (3 Oct 2020, 51314 Bytes) of package /linux/privat/gammu-1.42.0.tar.bz2:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "gsmstate.c" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 1.41.0_vs_1.42.0.

    1   /* (c) 2002-2005 by Marcin Wiacek and Michal Cihar */
    2 /* Phones ID (c) partially by Walek */
    3 
    4 #include <stdarg.h>
    5 #define _GNU_SOURCE /* For strcasestr */
    6 #include <string.h>
    7 #include <errno.h>
    8 #include <limits.h>
    9 #include <assert.h>
   10 
   11 #include <gammu-call.h>
   12 #include <gammu-settings.h>
   13 #include <gammu-unicode.h>
   14 #include <gammu-config.h>
   15 #include <gammu-misc.h>
   16 
   17 #include "debug.h"
   18 #include "gsmcomon.h"
   19 #include "gsmphones.h"
   20 #include "gsmstate.h"
   21 #include "misc/coding/coding.h"
   22 #include "misc/misc.h"
   23 #include "device/devfunc.h"
   24 
   25 #include "../libgammu/misc/string.h"
   26 
   27 #if defined(HAVE_GETPWUID) && defined(HAVE_GETUID)
   28 #include <sys/types.h>
   29 #include <pwd.h>
   30 #include <unistd.h>
   31 #include <ctype.h>
   32 
   33 #endif
   34 
   35 #if defined(WIN32) || defined(DJGPP)
   36 /* Needed for SHGFP_TYPE_CURRENT */
   37 #ifndef _WIN32_IE
   38 #define _WIN32_IE 0x0501
   39 #endif
   40 #include <shlobj.h>
   41 
   42 #define FALLBACK_GAMMURC "gammurc"
   43 #define GAMMURC_NAME "\\gammurc"
   44 #else
   45 #define FALLBACK_GAMMURC "/etc/gammurc"
   46 #define GAMMURC_NAME "/.gammurc"
   47 #endif
   48 #define XDG_GAMMURC_NAME "/gammu/config"
   49 
   50 /* Win32 compatibility */
   51 #ifndef PATH_MAX
   52 #define PATH_MAX (MAX_PATH)
   53 #endif
   54 
   55 /* Default settings */
   56 #if defined(WIN32) || defined(DJGPP)
   57 #  define DEFAULT_DEVICE "com2:"
   58 #else
   59 #  define DEFAULT_DEVICE "/dev/ttyUSB0"
   60 #endif
   61 #define DEFAULT_MODEL ""
   62 #define DEFAULT_CONNECTION "at"
   63 #define DEFAULT_SYNCHRONIZE_TIME FALSE
   64 #define DEFAULT_DEBUG_FILE ""
   65 #define DEFAULT_DEBUG_LEVEL ""
   66 #define DEFAULT_LOCK_DEVICE FALSE
   67 #define DEFAULT_START_INFO FALSE
   68 
   69 /**
   70  * Returns current debuging descriptor. It honors use_global
   71  * flag.
   72  */
   73 GSM_Debug_Info *GSM_GetDI(GSM_StateMachine *s)
   74 {
   75     GSM_Debug_Info *curdi;
   76 
   77     curdi = &GSM_global_debug;
   78     if (s != NULL && s->di.use_global == FALSE) {
   79         curdi = &(s->di);
   80     }
   81     return curdi;
   82 }
   83 
   84 static void GSM_RegisterConnection(GSM_StateMachine *s, unsigned int connection,
   85         GSM_Device_Functions *device, GSM_Protocol_Functions *protocol)
   86 {
   87     if ((unsigned int)s->ConnectionType == connection) {
   88         s->Device.Functions = device;
   89         s->Protocol.Functions   = protocol;
   90     }
   91 }
   92 
   93 /**
   94  * Information about connection names and parameters.
   95  */
   96 typedef struct {
   97     /**
   98      * Name of the connection used in config file.
   99      */
  100     const char *Name;
  101     /**
  102      * Connection type.
  103      */
  104     const GSM_ConnectionType Connection;
  105     /**
  106      * Whether to disable DTR/RTS handling on this connection.
  107      */
  108     gboolean SkipDtrRts;
  109 } GSM_ConnectionInfo;
  110 
  111 /**
  112  * Mapping of connection names to internal identifications.
  113  */
  114 static const GSM_ConnectionInfo GSM_Connections[] = {
  115     {"at", GCT_AT, FALSE},
  116 
  117     /* cables */
  118     {"mbus", GCT_MBUS2, FALSE},
  119 
  120     {"fbus", GCT_FBUS2, FALSE},
  121 
  122     {"fbususb", GCT_FBUS2USB, FALSE},
  123 
  124     {"fbuspl2303", GCT_FBUS2PL2303, FALSE},
  125 
  126     {"dlr3", GCT_FBUS2DLR3, FALSE},
  127     {"fbusdlr3", GCT_FBUS2DLR3, FALSE},
  128 
  129     {"dku5", GCT_DKU5FBUS2, FALSE},
  130     {"fbusdku5", GCT_DKU5FBUS2, FALSE},
  131     {"dku5fbus", GCT_DKU5FBUS2, FALSE},
  132 
  133     {"ark3116fbus", GCT_DKU5FBUS2, TRUE},
  134 #ifdef WIN32
  135     {"dku2", GCT_DKU2PHONET, FALSE},
  136     {"dku2phonet", GCT_DKU2PHONET, FALSE},
  137 #else
  138     {"dku2", GCT_FBUS2USB, FALSE},
  139     {"dku2phonet", GCT_FBUS2USB, FALSE},
  140 #endif
  141     {"dku2at", GCT_DKU2AT, FALSE},
  142 
  143         /* for serial ports assigned by bt stack */
  144     {"fbusblue", GCT_FBUS2BLUE, FALSE},
  145     {"phonetblue", GCT_PHONETBLUE, FALSE},
  146 
  147     /* bt */
  148     {"blueobex", GCT_BLUEOBEX, FALSE},
  149     {"bluephonet", GCT_BLUEPHONET, FALSE},
  150     {"blueat", GCT_BLUEAT, FALSE},
  151     {"bluerfobex", GCT_BLUEOBEX, FALSE},
  152     {"bluefbus", GCT_BLUEFBUS2, FALSE},
  153     {"bluerffbus", GCT_BLUEFBUS2, FALSE},
  154     {"bluerfphonet", GCT_BLUEPHONET, FALSE},
  155     {"bluerfat", GCT_BLUEAT, FALSE},
  156     {"bluerfgnapbus", GCT_BLUEGNAPBUS, FALSE},
  157     {"blues60", GCT_BLUES60, FALSE},
  158     {"bluerfs60", GCT_BLUES60, FALSE},
  159 
  160     /* proxy */
  161     {"proxyobex", GCT_PROXYOBEX, FALSE},
  162     {"proxyphonet", GCT_PROXYPHONET, FALSE},
  163     {"proxyat", GCT_PROXYAT, FALSE},
  164     {"proxygnapbus", GCT_PROXYGNAPBUS, FALSE},
  165     {"proxyfbus", GCT_PROXYFBUS2, FALSE},
  166     {"proxys60", GCT_PROXYS60, FALSE},
  167 
  168     /* old "serial" irda */
  169     {"infrared", GCT_FBUS2IRDA, FALSE},
  170     {"fbusirda", GCT_FBUS2IRDA, FALSE},
  171 
  172     /* socket irda */
  173     {"irda", GCT_IRDAPHONET, FALSE},
  174     {"irdaphonet", GCT_IRDAPHONET, FALSE},
  175     {"irdaat", GCT_IRDAAT, FALSE},
  176     {"irdaobex", GCT_IRDAOBEX, FALSE},
  177     {"irdagnapbus", GCT_IRDAGNAPBUS, FALSE},
  178 
  179     /* testing purposes */
  180     {"none", GCT_NONE, FALSE},
  181 };
  182 
  183 GSM_Device_Functions NoneDevice = {
  184     NONEFUNCTION,
  185     NONEFUNCTION,
  186     NONEFUNCTION,
  187     NONEFUNCTION,
  188     NONEFUNCTION,
  189     NONEFUNCTION,
  190     NONEFUNCTION
  191 };
  192 
  193 GSM_Protocol_Functions NoProtocol = {
  194     NONEFUNCTION,
  195     NONEFUNCTION,
  196     NONEFUNCTION,
  197     NONEFUNCTION
  198 };
  199 
  200 static GSM_Error GSM_RegisterAllConnections(GSM_StateMachine *s, const char *connection)
  201 {
  202     size_t i;
  203     char *buff, *nodtr_pos, *nopower_pos;
  204 
  205     /* Copy connection name, so that we can play with it */
  206     buff = strdup(connection);
  207     if (buff == NULL) {
  208         return ERR_MOREMEMORY;
  209     }
  210 
  211     /* We check here is used connection string type is correct for ANY
  212      * OS. If not, we return with error, that string is incorrect at all
  213      */
  214     s->ConnectionType = 0;
  215     s->SkipDtrRts = FALSE;
  216     s->NoPowerCable = FALSE;
  217 
  218     /* Are we asked for connection using stupid cable? */
  219     nodtr_pos = strcasestr(buff, "-nodtr");
  220     if (nodtr_pos != NULL) {
  221         *nodtr_pos = 0;
  222     }
  223 
  224     /* Are we asked for connection using cable which does not
  225      * use DTR/RTS as power supply? */
  226     nopower_pos = strcasestr(buff, "-nopower");
  227     if (nopower_pos != NULL) {
  228         *nopower_pos = 0;
  229         s->NoPowerCable = TRUE;
  230     }
  231 
  232     /* Compare known connections to what we got */
  233     for (i = 0; i < sizeof(GSM_Connections) / sizeof(GSM_Connections[0]); i++) {
  234         /* Check connection name */
  235         if (strcasecmp(GSM_Connections[i].Name, buff) == 0) {
  236             s->ConnectionType = GSM_Connections[i].Connection;
  237             s->SkipDtrRts = GSM_Connections[i].SkipDtrRts;
  238             break;
  239         }
  240     }
  241 
  242     /* If we were forced, set this flag */
  243     if (nodtr_pos != NULL) {
  244         s->SkipDtrRts = TRUE;
  245     }
  246 
  247     /* Special case - at can contains speed */
  248     if (s->ConnectionType == 0 && strncasecmp("at", buff, 2) == 0) {
  249         s->Speed = FindSerialSpeed(buff + 2);
  250         if (s->Speed != 0) {
  251             s->ConnectionType = GCT_AT;
  252         }
  253     }
  254 
  255     /* Free allocated memory */
  256     free(buff);
  257     buff = NULL;
  258 
  259     if (s->ConnectionType == 0) {
  260         return ERR_UNKNOWNCONNECTIONTYPESTRING;
  261     }
  262 
  263     /* We check now if user gave connection type compiled & available
  264      * for used OS (if not, we return, that source not available)
  265      */
  266     s->Device.Functions = NULL;
  267     s->Protocol.Functions   = NULL;
  268     GSM_RegisterConnection(s, GCT_NONE,       &NoneDevice,    &NoProtocol);
  269 #ifdef GSM_ENABLE_MBUS2
  270     GSM_RegisterConnection(s, GCT_MBUS2,      &SerialDevice,  &MBUS2Protocol);
  271 #endif
  272 #ifdef GSM_ENABLE_FBUS2
  273     GSM_RegisterConnection(s, GCT_FBUS2,      &SerialDevice,  &FBUS2Protocol);
  274 #endif
  275 #ifdef GSM_ENABLE_FBUS2DLR3
  276     GSM_RegisterConnection(s, GCT_FBUS2DLR3,  &SerialDevice,  &FBUS2Protocol);
  277 #endif
  278 #ifdef GSM_ENABLE_DKU5FBUS2
  279     GSM_RegisterConnection(s, GCT_DKU5FBUS2,  &SerialDevice,  &FBUS2Protocol);
  280 #endif
  281 #ifdef GSM_ENABLE_FBUS2PL2303
  282     GSM_RegisterConnection(s, GCT_FBUS2PL2303,&SerialDevice,  &FBUS2Protocol);
  283 #endif
  284 #ifdef GSM_ENABLE_FBUS2BLUE
  285     GSM_RegisterConnection(s, GCT_FBUS2BLUE,  &SerialDevice,  &FBUS2Protocol);
  286 #endif
  287 #ifdef GSM_ENABLE_FBUS2IRDA
  288     GSM_RegisterConnection(s, GCT_FBUS2IRDA,  &SerialDevice,  &FBUS2Protocol);
  289 #endif
  290 #if defined(GSM_ENABLE_DKU2PHONET) && defined(GSM_ENABLE_USBDEVICE)
  291     GSM_RegisterConnection(s, GCT_FBUS2USB,   &FBUSUSBDevice,  &PHONETProtocol);
  292 #endif
  293 #ifdef GSM_ENABLE_DKU2PHONET
  294     GSM_RegisterConnection(s, GCT_DKU2PHONET, &SerialDevice,  &PHONETProtocol);
  295 #endif
  296 #ifdef GSM_ENABLE_DKU2AT
  297     GSM_RegisterConnection(s, GCT_DKU2AT,     &SerialDevice,  &ATProtocol);
  298 #endif
  299 #ifdef GSM_ENABLE_AT
  300     GSM_RegisterConnection(s, GCT_AT,     &SerialDevice,  &ATProtocol);
  301 #endif
  302 #ifdef GSM_ENABLE_PHONETBLUE
  303     GSM_RegisterConnection(s, GCT_PHONETBLUE, &SerialDevice,  &PHONETProtocol);
  304 #endif
  305 #ifdef GSM_ENABLE_IRDAGNAPBUS
  306     GSM_RegisterConnection(s, GCT_IRDAGNAPBUS,&IrdaDevice,    &GNAPBUSProtocol);
  307 #endif
  308 #ifdef GSM_ENABLE_IRDAPHONET
  309     GSM_RegisterConnection(s, GCT_IRDAPHONET, &IrdaDevice,    &PHONETProtocol);
  310 #endif
  311 #ifdef GSM_ENABLE_IRDAAT
  312     GSM_RegisterConnection(s, GCT_IRDAAT,     &IrdaDevice,    &ATProtocol);
  313 #endif
  314 #ifdef GSM_ENABLE_IRDAOBEX
  315     GSM_RegisterConnection(s, GCT_IRDAOBEX,   &IrdaDevice,    &OBEXProtocol);
  316 #endif
  317 #ifdef GSM_ENABLE_BLUEGNAPBUS
  318     GSM_RegisterConnection(s, GCT_BLUES60,    &BlueToothDevice,&S60Protocol);
  319 #endif
  320 #ifdef GSM_ENABLE_BLUEGNAPBUS
  321     GSM_RegisterConnection(s, GCT_BLUEGNAPBUS,&BlueToothDevice,&GNAPBUSProtocol);
  322 #endif
  323 #ifdef GSM_ENABLE_BLUEFBUS2
  324     GSM_RegisterConnection(s, GCT_BLUEFBUS2,  &BlueToothDevice,&FBUS2Protocol);
  325 #endif
  326 #ifdef GSM_ENABLE_BLUEPHONET
  327     GSM_RegisterConnection(s, GCT_BLUEPHONET, &BlueToothDevice,&PHONETProtocol);
  328 #endif
  329 #ifdef GSM_ENABLE_BLUEAT
  330     GSM_RegisterConnection(s, GCT_BLUEAT,     &BlueToothDevice,&ATProtocol);
  331 #endif
  332 #ifdef GSM_ENABLE_BLUEOBEX
  333     GSM_RegisterConnection(s, GCT_BLUEOBEX,   &BlueToothDevice,&OBEXProtocol);
  334 #endif
  335 #ifdef GSM_ENABLE_PROXY
  336 #ifdef GSM_ENABLE_S60
  337     GSM_RegisterConnection(s, GCT_PROXYS60,   &ProxyDevice,&S60Protocol);
  338 #endif
  339 #ifdef GSM_ENABLE_BLUEGNAPBUS
  340     GSM_RegisterConnection(s, GCT_PROXYGNAPBUS,&ProxyDevice,&GNAPBUSProtocol);
  341 #endif
  342 #ifdef GSM_ENABLE_FBUS2
  343     GSM_RegisterConnection(s, GCT_PROXYFBUS2,  &ProxyDevice,&FBUS2Protocol);
  344 #endif
  345 #ifdef GSM_ENABLE_DKU2PHONET
  346     GSM_RegisterConnection(s, GCT_PROXYPHONET, &ProxyDevice,&PHONETProtocol);
  347 #endif
  348 #ifdef GSM_ENABLE_ATGEN
  349     GSM_RegisterConnection(s, GCT_PROXYAT,    &ProxyDevice,&ATProtocol);
  350 #endif
  351 #ifdef GSM_ENABLE_OBEXGEN
  352     GSM_RegisterConnection(s, GCT_PROXYOBEX,   &ProxyDevice,&OBEXProtocol);
  353 #endif
  354 #endif
  355     if (s->Device.Functions == NULL || s->Protocol.Functions == NULL) {
  356         smprintf(s, "Connection %s is know but was disabled on compile time\n", connection);
  357         return ERR_DISABLED;
  358     }
  359 
  360     return ERR_NONE;
  361 }
  362 
  363 static void GSM_RegisterModule(GSM_StateMachine *s,GSM_Phone_Functions *phone)
  364 {
  365     /* Auto model */
  366     if (s->CurrentConfig->Model[0] == 0) {
  367         if (strstr(phone->models,GetModelData(s, NULL, s->Phone.Data.Model, NULL)->model) != NULL) {
  368             smprintf(s,"[Module           - \"%s\"]\n",phone->models);
  369             s->Phone.Functions = phone;
  370         }
  371     } else {
  372         if (strstr(phone->models,s->CurrentConfig->Model) != NULL) {
  373             smprintf(s,"[Module           - \"%s\"]\n",phone->models);
  374             s->Phone.Functions = phone;
  375         }
  376     }
  377 }
  378 
  379 /**
  380  * Tries to register all modules to find one matching current configuration.
  381  *
  382  * \param s State machine pointer.
  383  *
  384  * \return Error code, ERR_NONE on success.
  385  */
  386 GSM_Error GSM_RegisterAllPhoneModules(GSM_StateMachine *s)
  387 {
  388     GSM_PhoneModel *model;
  389 
  390     /* Auto model */
  391     if (s->CurrentConfig->Model[0] == 0) {
  392         model = GetModelData(s, NULL, s->Phone.Data.Model, NULL);
  393 #ifdef GSM_ENABLE_ATGEN
  394         /* With ATgen and auto model we can work with unknown models too */
  395         if (s->ConnectionType==GCT_AT || s->ConnectionType==GCT_PROXYAT || s->ConnectionType==GCT_IRDAAT || s->ConnectionType==GCT_DKU2AT) {
  396 #ifdef GSM_ENABLE_ALCATEL
  397             /* If phone provides Alcatel specific functions, enable them */
  398             if (model->model[0] != 0 && GSM_IsPhoneFeatureAvailable(model, F_ALCATEL)) {
  399                 smprintf(s,"[Module           - \"%s\"]\n",ALCATELPhone.models);
  400                 s->Phone.Functions = &ALCATELPhone;
  401                 return ERR_NONE;
  402             }
  403 #endif
  404 #ifdef GSM_ENABLE_ATOBEX
  405             /* If phone provides Sony-Ericsson specific functions, enable them */
  406             if (model->model[0] != 0 && GSM_IsPhoneFeatureAvailable(model, F_OBEX)) {
  407                 smprintf(s,"[Module           - \"%s\"]\n",ATOBEXPhone.models);
  408                 s->Phone.Functions = &ATOBEXPhone;
  409                 return ERR_NONE;
  410             }
  411 #endif
  412             smprintf(s,"[Module           - \"%s\"]\n",ATGENPhone.models);
  413             s->Phone.Functions = &ATGENPhone;
  414             return ERR_NONE;
  415         }
  416 #endif
  417         /* With OBEXgen and auto model we can work with unknown models too */
  418 #ifdef GSM_ENABLE_OBEXGEN
  419         if (s->ConnectionType==GCT_BLUEOBEX || s->ConnectionType==GCT_PROXYOBEX || s->ConnectionType==GCT_IRDAOBEX) {
  420             smprintf(s,"[Module           - \"%s\"]\n",OBEXGENPhone.models);
  421             s->Phone.Functions = &OBEXGENPhone;
  422             return ERR_NONE;
  423         }
  424 #endif
  425 
  426 #ifdef GSM_ENABLE_BACKUP
  427         if (s->ConnectionType == GCT_NONE) {
  428             smprintf(s,"[Module           - \"%s\"]\n",DUMMYPhone.models);
  429             s->Phone.Functions = &DUMMYPhone;
  430             return ERR_NONE;
  431         }
  432 #endif
  433 
  434         /* With GNAPgen and auto model we can work with unknown models too */
  435 #ifdef GSM_ENABLE_GNAPGEN
  436         if (s->ConnectionType == GCT_BLUEGNAPBUS || s->ConnectionType == GCT_PROXYGNAPBUS || s->ConnectionType == GCT_IRDAGNAPBUS) {
  437             smprintf(s,"[Module           - \"%s\"]\n",GNAPGENPhone.models);
  438             s->Phone.Functions = &GNAPGENPhone;
  439             return ERR_NONE;
  440         }
  441 #endif
  442 #ifdef GSM_ENABLE_S60
  443         if (s->ConnectionType == GCT_BLUES60 || s->ConnectionType == GCT_PROXYS60) {
  444             smprintf(s,"[Module           - \"%s\"]\n",S60Phone.models);
  445             s->Phone.Functions = &S60Phone;
  446             return ERR_NONE;
  447         }
  448 #endif
  449 
  450 #ifdef GSM_ENABLE_NOKIA6510
  451         if ( s->ConnectionType ==  GCT_MBUS2 ||
  452                 s->ConnectionType ==  GCT_FBUS2 ||
  453                 s->ConnectionType ==  GCT_FBUS2USB ||
  454                 s->ConnectionType ==  GCT_FBUS2DLR3 ||
  455                 s->ConnectionType ==  GCT_FBUS2PL2303 ||
  456                 s->ConnectionType ==  GCT_FBUS2BLUE ||
  457                 s->ConnectionType ==  GCT_FBUS2IRDA ||
  458                 s->ConnectionType ==  GCT_DKU5FBUS2 ||
  459                 s->ConnectionType ==  GCT_DKU2PHONET ||
  460                 s->ConnectionType ==  GCT_PHONETBLUE ||
  461                 s->ConnectionType ==  GCT_IRDAPHONET ||
  462                 s->ConnectionType ==  GCT_BLUEFBUS2 ||
  463                 s->ConnectionType ==  GCT_PROXYFBUS2 ||
  464                 s->ConnectionType ==  GCT_PROXYPHONET ||
  465                 s->ConnectionType ==  GCT_BLUEPHONET) {
  466             /* Try to detect phone type */
  467             if (strcmp(model->model, "unknown") == 0 && model->features[0] == 0) {
  468                 smprintf(s, "WARNING: phone not known, please report it to authors (see <https://wammu.eu/support/bugs/>). Thank you.\n");
  469                 if (strncmp(s->Phone.Data.Model, "RM-", 3) == 0) {
  470                     /* 167 is really a wild guess */
  471                     if (atoi(s->Phone.Data.Model + 3) > 167) {
  472                         smprintf(s, "WARNING: Guessed phone as S40/30 compatible (RM series)!\n");
  473                         GSM_AddPhoneFeature(model, F_SERIES40_30);
  474                         GSM_AddPhoneFeature(model, F_FILES2);
  475                         GSM_AddPhoneFeature(model, F_TODO66);
  476                         GSM_AddPhoneFeature(model, F_RADIO);
  477                         GSM_AddPhoneFeature(model, F_NOTES);
  478                         GSM_AddPhoneFeature(model, F_SMS_FILES);
  479                         GSM_AddPhoneFeature(model, F_6230iCALLER);
  480                     }
  481                 }
  482                 if (strncmp(s->Phone.Data.Model, "RH-", 3) == 0) {
  483                     /* 63 is really a wild guess */
  484                     if (atoi(s->Phone.Data.Model + 3) > 63) {
  485                         smprintf(s, "WARNING: Guessed phone as S40/30 compatible (RH series)!\n");
  486                         GSM_AddPhoneFeature(model, F_SERIES40_30);
  487                         GSM_AddPhoneFeature(model, F_FILES2);
  488                         GSM_AddPhoneFeature(model, F_TODO66);
  489                         GSM_AddPhoneFeature(model, F_RADIO);
  490                         GSM_AddPhoneFeature(model, F_NOTES);
  491                         GSM_AddPhoneFeature(model, F_SMS_FILES);
  492                     }
  493                 }
  494             }
  495 
  496             /* If phone is S40, use 6510 */
  497             if (GSM_IsPhoneFeatureAvailable(model, F_SERIES40_30)) {
  498                 smprintf(s,"[Module           - \"%s\"]\n", N6510Phone.models);
  499                 s->Phone.Functions = &N6510Phone;
  500                 return ERR_NONE;
  501             }
  502         }
  503 #endif
  504         if (model->model[0] == 0) return ERR_UNKNOWNMODELSTRING;
  505     }
  506     s->Phone.Functions = NULL;
  507 #ifdef GSM_ENABLE_ATGEN
  508     /* AT module can have the same models ID to "normal" Nokia modules */
  509     if (s->ConnectionType==GCT_AT || s->ConnectionType==GCT_PROXYAT || s->ConnectionType==GCT_BLUEAT || s->ConnectionType==GCT_IRDAAT || s->ConnectionType==GCT_DKU2AT) {
  510         GSM_RegisterModule(s,&ATGENPhone);
  511         if (s->Phone.Functions != NULL) return ERR_NONE;
  512     }
  513 #endif
  514 #ifdef GSM_ENABLE_BACKUP
  515     GSM_RegisterModule(s, &DUMMYPhone);
  516 #endif
  517 #ifdef GSM_ENABLE_OBEXGEN
  518     GSM_RegisterModule(s,&OBEXGENPhone);
  519 #endif
  520 #ifdef GSM_ENABLE_GNAPGEN
  521     GSM_RegisterModule(s,&GNAPGENPhone);
  522 #endif
  523 #ifdef GSM_ENABLE_S60
  524     GSM_RegisterModule(s,&S60Phone);
  525 #endif
  526 #ifdef GSM_ENABLE_NOKIA3320
  527     GSM_RegisterModule(s,&N3320Phone);
  528 #endif
  529 #ifdef GSM_ENABLE_NOKIA3650
  530     GSM_RegisterModule(s,&N3650Phone);
  531 #endif
  532 #ifdef GSM_ENABLE_NOKIA650
  533     GSM_RegisterModule(s,&N650Phone);
  534 #endif
  535 #ifdef GSM_ENABLE_NOKIA6110
  536     GSM_RegisterModule(s,&N6110Phone);
  537 #endif
  538 #ifdef GSM_ENABLE_NOKIA6510
  539     GSM_RegisterModule(s,&N6510Phone);
  540 #endif
  541 #ifdef GSM_ENABLE_NOKIA7110
  542     GSM_RegisterModule(s,&N7110Phone);
  543 #endif
  544 #ifdef GSM_ENABLE_NOKIA9210
  545     GSM_RegisterModule(s,&N9210Phone);
  546 #endif
  547 #ifdef GSM_ENABLE_ALCATEL
  548     GSM_RegisterModule(s,&ALCATELPhone);
  549 #endif
  550 #ifdef GSM_ENABLE_ATOBEX
  551     GSM_RegisterModule(s,&ATOBEXPhone);
  552 #endif
  553     if (s->Phone.Functions == NULL) {
  554         return ERR_UNKNOWNMODELSTRING;
  555     }
  556     return ERR_NONE;
  557 }
  558 
  559 
  560 /**
  561  * Opens connection to device and initiates protocol layer.
  562  */
  563 GSM_Error GSM_OpenConnection(GSM_StateMachine *s)
  564 {
  565     GSM_Error error;
  566 
  567     if (s->CurrentConfig->LockDevice) {
  568         error = lock_device(s, s->CurrentConfig->Device, &(s->LockFile));
  569         if (error != ERR_NONE) return error;
  570     }
  571 
  572     /* Irda devices can set now model to some specific and
  573      * we don't have to make auto detection later */
  574     error=s->Device.Functions->OpenDevice(s);
  575     if (error!=ERR_NONE) {
  576         if (s->LockFile != NULL)
  577             unlock_device(s, &(s->LockFile));
  578         return error;
  579     }
  580 
  581     s->opened = TRUE;
  582 
  583     error=s->Protocol.Functions->Initialise(s);
  584     if (error!=ERR_NONE) return error;
  585 
  586     return ERR_NONE;
  587 }
  588 
  589 /**
  590  * Internal function which just closes connection and cleans up structures.
  591  */
  592 GSM_Error GSM_CloseConnection(GSM_StateMachine *s)
  593 {
  594     GSM_Error error;
  595 
  596     smprintf(s, "[Closing]\n");
  597 
  598     /* Terminate protocol */
  599     error = s->Protocol.Functions->Terminate(s);
  600     if (error != ERR_NONE) return error;
  601 
  602     /* Close the device */
  603     error = s->Device.Functions->CloseDevice(s);
  604     if (error != ERR_NONE) return error;
  605 
  606     /* Release lock if there was any */
  607     if (s->LockFile != NULL) {
  608         unlock_device(s, &(s->LockFile));
  609     }
  610 
  611     /* Null all structures in case we will be asked for new initialisation */
  612     s->Phone.Data.ModelInfo       = NULL;
  613     s->Phone.Data.Manufacturer[0]     = 0;
  614     s->Phone.Data.Model[0]        = 0;
  615     s->Phone.Data.Version[0]      = 0;
  616     s->Phone.Data.VerDate[0]      = 0;
  617     s->Phone.Data.VerNum          = 0;
  618 
  619     return ERR_NONE;
  620 }
  621 
  622 
  623 /**
  624  * Tries to read model using configured phone connection.
  625  */
  626 GSM_Error GSM_TryGetModel(GSM_StateMachine *s)
  627 {
  628     GSM_Error error;
  629 
  630     error = GSM_OpenConnection(s);
  631     if (error != ERR_NONE) return error;
  632 
  633     /* If still auto model, try to get model by asking phone for it */
  634     if (s->Phone.Data.Model[0]==0) {
  635         smprintf(s,"[Module           - \"auto\"]\n");
  636         switch (s->ConnectionType) {
  637 #ifdef GSM_ENABLE_BACKUP
  638             case GCT_NONE:
  639                 s->Phone.Functions = &DUMMYPhone;
  640                 break;
  641 #endif
  642 #ifdef GSM_ENABLE_ATGEN
  643             case GCT_AT:
  644             case GCT_BLUEAT:
  645             case GCT_PROXYAT:
  646             case GCT_IRDAAT:
  647             case GCT_DKU2AT:
  648                 s->Phone.Functions = &ATGENPhone;
  649                 break;
  650 #endif
  651 #ifdef GSM_ENABLE_OBEXGEN
  652             case GCT_IRDAOBEX:
  653             case GCT_PROXYOBEX:
  654             case GCT_BLUEOBEX:
  655                 s->Phone.Functions = &OBEXGENPhone;
  656                 break;
  657 #endif
  658 #ifdef GSM_ENABLE_GNAPGEN
  659             case GCT_BLUEGNAPBUS:
  660             case GCT_PROXYGNAPBUS:
  661             case GCT_IRDAGNAPBUS:
  662                 s->Phone.Functions = &GNAPGENPhone;
  663                 break;
  664 #endif
  665 #ifdef GSM_ENABLE_S60
  666             case GCT_BLUES60:
  667             case GCT_PROXYS60:
  668                 s->Phone.Functions = &S60Phone;
  669                 break;
  670 #endif
  671 #if defined(GSM_ENABLE_NOKIA_DCT3) || defined(GSM_ENABLE_NOKIA_DCT4)
  672             case GCT_MBUS2:
  673             case GCT_FBUS2:
  674             case GCT_FBUS2USB:
  675             case GCT_FBUS2DLR3:
  676             case GCT_FBUS2PL2303:
  677             case GCT_FBUS2BLUE:
  678             case GCT_FBUS2IRDA:
  679             case GCT_DKU5FBUS2:
  680             case GCT_DKU2PHONET:
  681             case GCT_PHONETBLUE:
  682             case GCT_IRDAPHONET:
  683             case GCT_BLUEFBUS2:
  684             case GCT_PROXYFBUS2:
  685             case GCT_BLUEPHONET:
  686             case GCT_PROXYPHONET:
  687                 s->Phone.Functions = &NAUTOPhone;
  688                 break;
  689 #endif
  690             default:
  691                 s->Phone.Functions = NULL;
  692         }
  693         /* Did we find matching phone driver? */
  694         if (s->Phone.Functions == NULL) {
  695             smprintf(s, "ERROR: Could not find proper module for autodetection!\n");
  696             return ERR_UNKNOWN;
  697         }
  698 
  699         /* Initialize the phone driver */
  700         error = s->Phone.Functions->Initialise(s);
  701         if (error != ERR_NONE) return error;
  702 
  703         /* Get model name from phone */
  704         error = s->Phone.Functions->GetModel(s);
  705         if (error != ERR_NONE) return error;
  706 
  707         /* And terminate it again */
  708         error = s->Phone.Functions->Terminate(s);
  709         if (error != ERR_NONE) return error;
  710     }
  711     return ERR_NONE;
  712 }
  713 
  714 GSM_Error GSM_InitConnection_Log(GSM_StateMachine *s, int ReplyNum, GSM_Log_Function log_function, void *user_data)
  715 {
  716     GSM_Error   error;
  717     GSM_DateTime    current_time;
  718     int     i;
  719 
  720     for (i=0;i<s->ConfigNum;i++) {
  721         s->CurrentConfig          = &s->Config[i];
  722 
  723         /* Skip non configured sections */
  724         if (s->CurrentConfig->Connection == NULL) {
  725             smprintf_level(s, D_ERROR, "[Empty section    - %d]\n", i);
  726             continue;
  727         }
  728 
  729         s->Speed              = 0;
  730         s->ReplyNum           = ReplyNum;
  731         s->Phone.Data.ModelInfo       = GetModelData(s, "unknown", NULL, NULL);
  732         s->Phone.Data.Manufacturer[0]     = 0;
  733         s->Phone.Data.Model[0]        = 0;
  734         s->Phone.Data.Version[0]      = 0;
  735         s->Phone.Data.VerDate[0]      = 0;
  736         s->Phone.Data.VerNum          = 0;
  737         s->Phone.Data.StartInfoCounter    = 0;
  738         s->Phone.Data.SentMsg         = NULL;
  739 
  740         s->Phone.Data.HardwareCache[0]    = 0;
  741         s->Phone.Data.ProductCodeCache[0] = 0;
  742         s->Phone.Data.EnableIncomingCall  = FALSE;
  743         s->Phone.Data.EnableIncomingSMS   = FALSE;
  744         s->Phone.Data.EnableIncomingCB    = FALSE;
  745         s->Phone.Data.EnableIncomingUSSD  = FALSE;
  746         s->User.UserReplyFunctions    = NULL;
  747         s->User.IncomingCall          = NULL;
  748         s->User.IncomingSMS       = NULL;
  749         s->User.IncomingCB        = NULL;
  750         s->User.IncomingUSSD          = NULL;
  751         s->User.SendSMSStatus         = NULL;
  752         s->LockFile           = NULL;
  753         s->opened             = FALSE;
  754         s->Phone.Functions        = NULL;
  755 
  756         s->di                 = GSM_none_debug;
  757         s->di.use_global          = s->CurrentConfig->UseGlobalDebugFile;
  758         if (!s->di.use_global) {
  759             GSM_SetDebugFunction(log_function, user_data, &s->di);
  760             GSM_SetDebugLevel(s->CurrentConfig->DebugLevel, &s->di);
  761             error = GSM_SetDebugFile(s->CurrentConfig->DebugFile, &s->di);
  762             if (error != ERR_NONE) {
  763                 GSM_LogError(s, "Init:GSM_SetDebugFile" , error);
  764                 return error;
  765             }
  766         }
  767 
  768         smprintf_level(s, D_ERROR, "[Gammu            - %s]\n", GAMMU_VERSION);
  769         StripSpaces(s->CurrentConfig->Connection);
  770         StripSpaces(s->CurrentConfig->Model);
  771         StripSpaces(s->CurrentConfig->Device);
  772         smprintf_level(s, D_ERROR, "[Connection       - \"%s\"]\n",
  773                 s->CurrentConfig->Connection);
  774         smprintf_level(s, D_ERROR, "[Connection index - %d]\n", i);
  775         smprintf_level(s, D_ERROR, "[Model type       - \"%s\"]\n",
  776                 s->CurrentConfig->Model);
  777         smprintf_level(s, D_ERROR, "[Device           - \"%s\"]\n",
  778                 s->CurrentConfig->Device);
  779         if (strlen(GetOS()) != 0) {
  780             smprintf_level(s, D_ERROR, "[Running on       - %s]\n",
  781                     GetOS());
  782         }
  783 
  784         if (GSM_GetDI(s)->dl == DL_BINARY) {
  785             smprintf(s,"%c",((unsigned char)strlen(GAMMU_VERSION)));
  786             smprintf(s,"%s",GAMMU_VERSION);
  787         }
  788 
  789         error = GSM_RegisterAllConnections(s, s->CurrentConfig->Connection);
  790         if (error != ERR_NONE) {
  791             GSM_LogError(s, "Init:GSM_RegisterAllConnections" , error);
  792             return error;
  793         }
  794 
  795 autodetect:
  796         /* Model auto */
  797         /* Try to guess correct driver based on model */
  798         if (s->CurrentConfig->Model[0] == 0 &&
  799                 s->ConnectionType != GCT_NONE &&
  800                 s->ConnectionType != GCT_IRDAOBEX &&
  801                 s->ConnectionType != GCT_BLUEOBEX &&
  802                 s->ConnectionType != GCT_PROXYOBEX &&
  803                 s->ConnectionType != GCT_BLUEGNAPBUS &&
  804                 s->ConnectionType != GCT_PROXYGNAPBUS &&
  805                 s->ConnectionType != GCT_IRDAGNAPBUS &&
  806                 s->ConnectionType != GCT_PROXYS60 &&
  807                 s->ConnectionType != GCT_BLUES60) {
  808             error = GSM_TryGetModel(s);
  809             /* Fall back to other configuraitons if the device is not existing (or similar error) */
  810             if ((i != s->ConfigNum - 1) && (
  811                 (error == ERR_DEVICEOPENERROR) ||
  812                 (error == ERR_DEVICELOCKED) ||
  813                 (error == ERR_DEVICENOTEXIST) ||
  814                 (error == ERR_DEVICEBUSY) ||
  815                 (error == ERR_DEVICENOPERMISSION) ||
  816                 (error == ERR_DEVICENODRIVER) ||
  817                 (error == ERR_DEVICENOTWORK))) {
  818                 GSM_CloseConnection(s);
  819                 continue;
  820             }
  821             if (error != ERR_NONE) {
  822                 GSM_LogError(s, "Init:GSM_TryGetModel" , error);
  823                 return error;
  824             }
  825         }
  826 
  827         /* Switching to "correct" module */
  828         error = GSM_RegisterAllPhoneModules(s);
  829         /* If user selected soemthing which is not supported, try autodetection */
  830         if (s->CurrentConfig->Model[0] != 0 && error == ERR_UNKNOWNMODELSTRING) {
  831             smprintf(s, "Configured model %s is not known, retrying with autodetection!\n",
  832                     s->CurrentConfig->Model);
  833             s->CurrentConfig->Model[0] = 0;
  834             goto autodetect;
  835         }
  836         if (error != ERR_NONE) {
  837             GSM_LogError(s, "Init:GSM_RegisterAllPhoneModules" , error);
  838             return error;
  839         }
  840 
  841         /* We didn't open device earlier ? Make it now */
  842         if (!s->opened) {
  843             error = GSM_OpenConnection(s);
  844             if ((i != s->ConfigNum - 1) && (
  845                 (error == ERR_DEVICEOPENERROR) ||
  846                 (error == ERR_DEVICELOCKED) ||
  847                 (error == ERR_DEVICENOTEXIST) ||
  848                 (error == ERR_DEVICEBUSY) ||
  849                 (error == ERR_DEVICENOPERMISSION) ||
  850                 (error == ERR_DEVICENODRIVER) ||
  851                 (error == ERR_DEVICENOTWORK))) {
  852                 GSM_CloseConnection(s);
  853                 continue;
  854             }
  855             if (error != ERR_NONE) {
  856                 GSM_LogError(s, "Init:GSM_OpenConnection" , error);
  857                 return error;
  858             }
  859         }
  860 
  861         /* Initialize phone layer */
  862         error=s->Phone.Functions->Initialise(s);
  863         if (error == ERR_TIMEOUT && i != s->ConfigNum - 1) {
  864             GSM_CloseConnection(s);
  865             continue;
  866         }
  867         if (error != ERR_NONE) {
  868             GSM_LogError(s, "Init:Phone->Initialise" , error);
  869             return error;
  870         }
  871 
  872         if (s->CurrentConfig->StartInfo) {
  873             s->Phone.Functions->ShowStartInfo(s,TRUE);
  874             s->Phone.Data.StartInfoCounter = 30;
  875         }
  876 
  877         if (s->CurrentConfig->SyncTime) {
  878             GSM_GetCurrentDateTime (&current_time);
  879             s->Phone.Functions->SetDateTime(s,&current_time);
  880         }
  881 
  882         /* For debug it's good to have firmware and real model version and manufacturer */
  883         error=s->Phone.Functions->GetManufacturer(s);
  884         if (error == ERR_TIMEOUT && i != s->ConfigNum - 1) {
  885             GSM_CloseConnection(s);
  886             continue;
  887         }
  888         if (error != ERR_NONE && error != ERR_NOTSUPPORTED) {
  889             GSM_LogError(s, "Init:Phone->GetManufacturer" , error);
  890             return error;
  891         }
  892 
  893         error=s->Phone.Functions->GetModel(s);
  894         if (error != ERR_NONE && error != ERR_NOTSUPPORTED) {
  895             GSM_LogError(s, "Init:Phone->GetModel" , error);
  896             return error;
  897         }
  898 
  899         error=s->Phone.Functions->GetFirmware(s);
  900         if (error != ERR_NONE && error != ERR_NOTSUPPORTED) {
  901             GSM_LogError(s, "Init:Phone->GetFirmware" , error);
  902             return error;
  903         }
  904 
  905         error=s->Phone.Functions->SetPower(s, 1);
  906         if (error != ERR_NONE && error != ERR_NOTSUPPORTED) {
  907             GSM_LogError(s, "Init:Phone->SetPower" , error);
  908             return error;
  909         }
  910 
  911         error=s->Phone.Functions->PostConnect(s);
  912         if (error != ERR_NONE && error != ERR_NOTSUPPORTED) {
  913             GSM_LogError(s, "Init:Phone->PostConnect" , error);
  914             return error;
  915         }
  916 
  917         smprintf(s,"[Connected]\n");
  918         return ERR_NONE;
  919     }
  920     return ERR_UNCONFIGURED;
  921 }
  922 
  923 GSM_Error GSM_InitConnection(GSM_StateMachine *s, int ReplyNum)
  924 {
  925     return GSM_InitConnection_Log(s, ReplyNum, GSM_none_debug.log_function, GSM_none_debug.user_data);
  926 }
  927 
  928 int GSM_ReadDevice (GSM_StateMachine *s, gboolean waitforreply)
  929 {
  930     GSM_DateTime    Date;
  931     unsigned char   buff[65536]={'\0'};
  932     int     res=0,count=0,i=0;
  933 
  934     if (!GSM_IsConnected(s)) {
  935         return -1;
  936     }
  937 
  938     GSM_GetCurrentDateTime (&Date);
  939     i = Date.Second;
  940     while (i == Date.Second && !s->Abort) {
  941         res = s->Device.Functions->ReadDevice(s, buff, sizeof(buff));
  942 
  943         if (!waitforreply) {
  944             break;
  945         }
  946         if (res > 0) {
  947             break;
  948         }
  949         usleep(5000);
  950         GSM_GetCurrentDateTime(&Date);
  951     }
  952     for (count = 0; count < res; count++) {
  953         s->Protocol.Functions->StateMachine(s, buff[count]);
  954     }
  955     return res;
  956 }
  957 
  958 GSM_Error GSM_TerminateConnection(GSM_StateMachine *s)
  959 {
  960     GSM_Error error;
  961 
  962     if (!s->opened) return ERR_NONE;
  963 
  964     smprintf(s,"[Terminating]\n");
  965 
  966     if (s->CurrentConfig->StartInfo) {
  967         if (s->Phone.Data.StartInfoCounter > 0) s->Phone.Functions->ShowStartInfo(s,FALSE);
  968     }
  969 
  970     if (s->Phone.Functions != NULL) {
  971         error=s->Phone.Functions->Terminate(s);
  972         if (error!=ERR_NONE) return error;
  973     }
  974 
  975     error = GSM_CloseConnection(s);
  976     if (error != ERR_NONE) return error;
  977 
  978     GSM_SetDebugFileDescriptor(NULL, FALSE, &(s->di));
  979 
  980     s->opened = FALSE;
  981 
  982     return ERR_NONE;
  983 }
  984 
  985 gboolean GSM_IsConnected(GSM_StateMachine *s) {
  986     return (s != NULL) && s->Phone.Functions != NULL && s->opened;
  987 }
  988 
  989 GSM_Error GSM_AbortOperation(GSM_StateMachine * s)
  990 {
  991     s->Abort = TRUE;
  992     return ERR_NONE;
  993 }
  994 
  995 GSM_Error GSM_WaitForOnce(GSM_StateMachine *s, unsigned const char *buffer,
  996               size_t length, int type, int timeout)
  997 {
  998     GSM_Phone_Data *Phone = &s->Phone.Data;
  999     GSM_Protocol_Message sentmsg;
 1000     int i = 0;
 1001 
 1002     do {
 1003         if (length != 0) {
 1004             sentmsg.Length  = length;
 1005             sentmsg.Type    = type;
 1006             sentmsg.Buffer  = (unsigned char *)malloc(length);
 1007             memcpy(sentmsg.Buffer, buffer, length);
 1008             Phone->SentMsg  = &sentmsg;
 1009         }
 1010 
 1011         /* Some data received. Reset timer */
 1012         if (GSM_ReadDevice(s, TRUE) > 0) {
 1013             i = 0;
 1014         } else {
 1015             usleep(10000);
 1016         }
 1017 
 1018         if (length != 0) {
 1019             free(sentmsg.Buffer);
 1020             sentmsg.Buffer = NULL;
 1021             Phone->SentMsg = NULL;
 1022         }
 1023 
 1024         if (s->Abort) {
 1025             return ERR_ABORTED;
 1026         }
 1027 
 1028         /* Request completed */
 1029         if (Phone->RequestID == ID_None) {
 1030             return Phone->DispatchError;
 1031         }
 1032         i++;
 1033     } while (i < timeout);
 1034 
 1035     return ERR_TIMEOUT;
 1036 }
 1037 
 1038 GSM_Error GSM_WaitFor (GSM_StateMachine *s, unsigned const char *buffer,
 1039                size_t length, int type, int timeout,
 1040                GSM_Phone_RequestID request)
 1041 {
 1042     GSM_Phone_Data      *Phone = &s->Phone.Data;
 1043     GSM_Error       error;
 1044     int         reply;
 1045 
 1046     if (s->CurrentConfig->StartInfo) {
 1047         if (Phone->StartInfoCounter > 0) {
 1048             Phone->StartInfoCounter--;
 1049             if (Phone->StartInfoCounter == 0) {
 1050                 s->Phone.Functions->ShowStartInfo(s,FALSE);
 1051             }
 1052         }
 1053     }
 1054 
 1055     Phone->RequestID    = request;
 1056     Phone->DispatchError    = ERR_TIMEOUT;
 1057 
 1058     for (reply = 0; reply < s->ReplyNum; reply++) {
 1059         if (reply != 0) {
 1060             smprintf_level(s, D_ERROR, "[Retrying %i type 0x%02X]\n", reply, type);
 1061         }
 1062         error = s->Protocol.Functions->WriteMessage(s, buffer, length, type);
 1063         if (error != ERR_NONE) {
 1064             return error;
 1065         }
 1066 
 1067         /* Special case when no reply is expected */
 1068         if (request == ID_None) {
 1069             return ERR_NONE;
 1070         }
 1071 
 1072         error = GSM_WaitForOnce(s, buffer, length, type, timeout);
 1073         if (error != ERR_TIMEOUT) {
 1074             return error;
 1075         }
 1076   }
 1077 
 1078     if (request != ID_Reset && GSM_IsPhoneFeatureAvailable(s->Phone.Data.ModelInfo, F_RESET_AFTER_TIMEOUT)) {
 1079         smprintf_level(s, D_ERROR, "Performing device reset after timeout!\n");
 1080         GSM_Reset(s, FALSE);
 1081     }
 1082 
 1083     return ERR_TIMEOUT;
 1084 }
 1085 
 1086 static GSM_Error CheckReplyFunctions(GSM_StateMachine *s, GSM_Reply_Function *Reply, int *reply)
 1087 {
 1088     GSM_Phone_Data          *Data     = &s->Phone.Data;
 1089     GSM_Protocol_Message        *msg      = s->Phone.Data.RequestMsg;
 1090     gboolean                execute;
 1091     gboolean                available = FALSE;
 1092     int             i     = 0;
 1093 
 1094     while (Reply[i].requestID != ID_None) {
 1095         execute = FALSE;
 1096         /* Long ID frames like S60 */
 1097         if (Reply[i].msgtype[0] == 0 && Reply[i].subtypechar == 0) {
 1098             if (Reply[i].subtype == msg->Type) {
 1099                 execute = TRUE;
 1100             }
 1101         /* Binary frames like in Nokia */
 1102         } else if (strlen(Reply[i].msgtype) < 2) {
 1103             if (Reply[i].msgtype[0]==msg->Type) {
 1104                 if (Reply[i].subtypechar!=0) {
 1105                     if (Reply[i].subtypechar<=msg->Length) {
 1106                         if (msg->Buffer[Reply[i].subtypechar]==Reply[i].subtype)
 1107                             execute=TRUE;
 1108                     }
 1109                 } else {
 1110                     execute=TRUE;
 1111                 }
 1112             }
 1113         } else {
 1114             if (strlen(Reply[i].msgtype) < msg->Length) {
 1115                 if (strncmp(Reply[i].msgtype,msg->Buffer,strlen(Reply[i].msgtype))==0) {
 1116                     execute=TRUE;
 1117                 }
 1118             }
 1119         }
 1120 
 1121         if (execute) {
 1122             *reply = i;
 1123             if (Reply[i].requestID == ID_IncomingFrame ||
 1124                 Reply[i].requestID == Data->RequestID ||
 1125                 Data->RequestID    == ID_EachFrame) {
 1126                 return ERR_NONE;
 1127             }
 1128             available = TRUE;
 1129         }
 1130         i++;
 1131     }
 1132 
 1133     if (available) {
 1134         return ERR_FRAMENOTREQUESTED;
 1135     } else {
 1136         return ERR_UNKNOWNFRAME;
 1137     }
 1138 }
 1139 
 1140 GSM_Error EventQueue_Push(GSM_StateMachine *s, const EventBinding *binding)
 1141 {
 1142   DeferredEventQueue *Queue = &s->Phone.Data.DeferredEvents;
 1143 
 1144   assert(binding != NULL);
 1145   assert(Queue->head < MAX_DEFERRED_EVENTS);
 1146 
 1147   if(Queue->entries == MAX_DEFERRED_EVENTS)
 1148     return ERR_FULL;
 1149 
 1150   Queue->event_bindings[Queue->head] = *binding;
 1151   Queue->head = (Queue->head + 1) % MAX_DEFERRED_EVENTS;
 1152   ++Queue->entries;
 1153 
 1154   assert(Queue->entries <= MAX_DEFERRED_EVENTS);
 1155 
 1156   return ERR_NONE;
 1157 }
 1158 
 1159 GSM_Error EventQueue_Pop(GSM_StateMachine *s, EventBinding *binding)
 1160 {
 1161   DeferredEventQueue *Queue = &s->Phone.Data.DeferredEvents;
 1162 
 1163   assert(binding != NULL);
 1164 
 1165   if(Queue->entries == 0)
 1166     return ERR_EMPTY;
 1167 
 1168   *binding = Queue->event_bindings[Queue->tail];
 1169   Queue->tail = (Queue->tail + 1) % MAX_DEFERRED_EVENTS;
 1170   --Queue->entries;
 1171 
 1172   assert(Queue->entries >= 0);
 1173 
 1174   return ERR_NONE;
 1175 }
 1176 
 1177 void GSM_CancelEventsOfType(GSM_StateMachine *s, unsigned event_types)
 1178 {
 1179   DeferredEventQueue *q = &s->Phone.Data.DeferredEvents;
 1180   int i = q->tail;
 1181 
 1182   while(i != q->head) {
 1183     if(q->event_bindings[i].type & event_types)
 1184       q->event_bindings[i].event_cancelled = TRUE;
 1185 
 1186     i = (i + 1) % MAX_DEFERRED_EVENTS;
 1187   }
 1188 }
 1189 
 1190 GSM_Error GSM_DeferIncomingCallEvent(GSM_StateMachine *s, GSM_Call *call, BeforeDeferredEvent before_event)
 1191 {
 1192   GSM_Error error;
 1193   EventBinding binding;
 1194 
 1195   if(s->Phone.Data.RequestID == ID_None) {
 1196     s->User.IncomingCall(s, call, s->User.IncomingCallUserData);
 1197     return ERR_NONE;
 1198   }
 1199 
 1200   binding.type = GSM_EV_CALL;
 1201   binding.handler = (EventHandler)s->User.IncomingCall;
 1202   binding.before_event = before_event;
 1203   binding.after_event = NULL;
 1204   binding.event_cancelled = FALSE;
 1205   binding.event_data.call = *call;
 1206   binding.user_data = s->User.IncomingCallUserData;
 1207 
 1208   error = EventQueue_Push(s, &binding);
 1209 
 1210   if(error != ERR_NONE)
 1211     smprintf_level(s, D_ERROR,
 1212       "the incoming call handler could not be deferred.\n");
 1213 
 1214   return error;
 1215 }
 1216 
 1217 GSM_Error ProcessDeferredEvent(GSM_StateMachine *s)
 1218 {
 1219   EventBinding binding;
 1220   GSM_Error error = EventQueue_Pop(s, &binding);
 1221 
 1222   if(error != ERR_NONE)
 1223     return error;
 1224 
 1225   assert(s->Phone.Data.RequestID == ID_None);
 1226   assert(binding.handler != NULL);
 1227   assert(binding.type != GSM_EV_UNSET);
 1228 
 1229   if(binding.event_cancelled == FALSE) {
 1230     if (binding.before_event)
 1231       error = binding.before_event(s);
 1232 
 1233     if(error == ERR_NONE)
 1234       binding.handler(s, &binding.event_data, binding.user_data);
 1235   }
 1236 
 1237   if(binding.after_event)
 1238     binding.after_event(s, &binding);
 1239 
 1240   return error;
 1241 }
 1242 
 1243 GSM_Error GSM_DispatchMessage(GSM_StateMachine *s)
 1244 {
 1245     GSM_Error       error   = ERR_UNKNOWNFRAME;
 1246     GSM_Protocol_Message    *msg    = s->Phone.Data.RequestMsg;
 1247     GSM_Phone_Data      *Phone  = &s->Phone.Data;
 1248     gboolean            disp    = FALSE;
 1249     GSM_Reply_Function  *Reply;
 1250     int         reply;
 1251 
 1252     s->MessagesCount++;
 1253 
 1254     GSM_DumpMessageTextRecv(s, msg->Buffer, msg->Length, msg->Type);
 1255     GSM_DumpMessageBinaryRecv(s, msg->Buffer, msg->Length, msg->Type);
 1256 
 1257     Reply = s->User.UserReplyFunctions;
 1258     if (Reply != NULL) {
 1259         error = CheckReplyFunctions(s, Reply, &reply);
 1260     }
 1261 
 1262     if (error == ERR_UNKNOWNFRAME) {
 1263         Reply = s->Phone.Functions->ReplyFunctions;
 1264         error = CheckReplyFunctions(s, Reply, &reply);
 1265     }
 1266 
 1267     if (error == ERR_NONE) {
 1268         error = Reply[reply].Function(msg, s);
 1269         if (Reply[reply].requestID == Phone->RequestID) {
 1270             if (error == ERR_NEEDANOTHERANSWER) {
 1271                 error = ERR_NONE;
 1272             } else {
 1273                 Phone->RequestID = ID_None;
 1274         while(ProcessDeferredEvent(s) == ERR_NONE);
 1275             }
 1276         }
 1277     }
 1278 
 1279     if (strcmp(s->Phone.Functions->models,"NAUTO")) {
 1280         disp = TRUE;
 1281         switch (error) {
 1282         case ERR_UNKNOWNRESPONSE:
 1283             smprintf_level(s, D_ERROR, "\nUNKNOWN response");
 1284             break;
 1285         case ERR_UNKNOWNFRAME:
 1286             smprintf_level(s, D_ERROR, "\nUNKNOWN frame");
 1287             break;
 1288         case ERR_FRAMENOTREQUESTED:
 1289             smprintf_level(s, D_ERROR, "\nFrame not request now");
 1290             break;
 1291         default:
 1292             disp = FALSE;
 1293         }
 1294 
 1295         if (error == ERR_UNKNOWNFRAME || error == ERR_FRAMENOTREQUESTED) {
 1296             error = ERR_TIMEOUT;
 1297         }
 1298     }
 1299 
 1300     if (disp) {
 1301         smprintf(s,". Please report the error, see <https://wammu.eu/support/bugs/>. Thank you\n");
 1302         if (Phone->SentMsg != NULL) {
 1303             smprintf(s,"LAST SENT frame ");
 1304             smprintf(s, "type 0x%02X/length %ld", Phone->SentMsg->Type, (long)Phone->SentMsg->Length);
 1305             DumpMessage(GSM_GetDI(s), Phone->SentMsg->Buffer, Phone->SentMsg->Length);
 1306         }
 1307         smprintf(s, "RECEIVED frame ");
 1308         smprintf(s, "type 0x%02X/length 0x%lx/%ld", msg->Type, (long)msg->Length, (long)msg->Length);
 1309         DumpMessage(GSM_GetDI(s), msg->Buffer, msg->Length);
 1310         smprintf(s, "\n");
 1311     }
 1312 
 1313     return error;
 1314 }
 1315 
 1316 GSM_Error GSM_TryReadGammuRC (const char *path, INI_Section **result)
 1317 {
 1318     dbgprintf(NULL, "Open config: \"%s\"\n", path);
 1319     return  INI_ReadFile(path, FALSE, result);
 1320 }
 1321 
 1322 GSM_Error GSM_FindGammuRC (INI_Section **result, const char *force_config)
 1323 {
 1324     char configfile[PATH_MAX + 1];
 1325     char *envpath;
 1326     GSM_Error error;
 1327 #if defined(HAVE_GETPWUID) && defined(HAVE_GETUID)
 1328     struct passwd *pwent;
 1329 #endif
 1330 
 1331     *result = NULL;
 1332 
 1333     if (force_config != NULL) {
 1334         return GSM_TryReadGammuRC(force_config, result);
 1335     }
 1336 
 1337 #ifdef WIN32
 1338     /* Get Windows application data path */
 1339     if (SUCCEEDED(SHGetFolderPath(NULL, CSIDL_APPDATA, NULL, SHGFP_TYPE_CURRENT, configfile))) {
 1340         strcat(configfile, GAMMURC_NAME);
 1341 
 1342         error = GSM_TryReadGammuRC(configfile, result);
 1343         if (error == ERR_NONE) return ERR_NONE;
 1344     }
 1345 #endif
 1346 
 1347     /* XDG paths */
 1348     envpath = getenv("XDG_CONFIG_HOME");
 1349     if (envpath) {
 1350         strcpy(configfile, envpath);
 1351         strcat(configfile, XDG_GAMMURC_NAME);
 1352 
 1353         error = GSM_TryReadGammuRC(configfile, result);
 1354         if (error == ERR_NONE) return ERR_NONE;
 1355     } else {
 1356         envpath  = getenv("HOME");
 1357         if (envpath) {
 1358             strcpy(configfile, envpath);
 1359             strcat(configfile, "/.config");
 1360             strcat(configfile, XDG_GAMMURC_NAME);
 1361 
 1362             error = GSM_TryReadGammuRC(configfile, result);
 1363             if (error == ERR_NONE) return ERR_NONE;
 1364         }
 1365     }
 1366 
 1367     /* Try home from environment */
 1368     envpath  = getenv("HOME");
 1369     if (envpath) {
 1370         strcpy(configfile, envpath);
 1371         strcat(configfile, GAMMURC_NAME);
 1372 
 1373         error = GSM_TryReadGammuRC(configfile, result);
 1374         if (error == ERR_NONE) return ERR_NONE;
 1375     }
 1376 
 1377 #if defined(HAVE_GETPWUID) && defined(HAVE_GETUID)
 1378     /* Tru home from passwd */
 1379     pwent = getpwuid(getuid());
 1380     if (pwent != NULL) {
 1381         strcpy(configfile, pwent->pw_dir);
 1382         strcat(configfile, GAMMURC_NAME);
 1383 
 1384         error = GSM_TryReadGammuRC(configfile, result);
 1385         if (error == ERR_NONE) return ERR_NONE;
 1386     }
 1387 
 1388 #endif
 1389 
 1390 #if defined(WIN32)
 1391     /* Reset as we're using strcat */
 1392     configfile[0] = 0;
 1393 
 1394     /* This makes sense only on Windows */
 1395     envpath = getenv("HOMEDRIVE");
 1396     if (envpath) {
 1397         strcat(configfile, envpath);
 1398     }
 1399 
 1400     envpath = getenv("HOMEPATH");
 1401     if (envpath) {
 1402         strcat(configfile, envpath);
 1403         strcat(configfile, GAMMURC_NAME);
 1404 
 1405         error = GSM_TryReadGammuRC(configfile, result);
 1406         if (error == ERR_NONE) return ERR_NONE;
 1407     }
 1408 #endif
 1409 
 1410     /* Try fallback config as last */
 1411     return GSM_TryReadGammuRC(FALLBACK_GAMMURC, result);
 1412 }
 1413 
 1414 GSM_Config *GSM_GetConfig(GSM_StateMachine *s, int num)
 1415 {
 1416     if (num == -1) {
 1417         return s->CurrentConfig;
 1418     } else {
 1419         if (num > MAX_CONFIG_NUM) return NULL;
 1420         return &(s->Config[num]);
 1421     }
 1422 }
 1423 
 1424 
 1425 int GSM_GetConfigNum(const GSM_StateMachine *s)
 1426 {
 1427     return s->ConfigNum;
 1428 }
 1429 
 1430 void GSM_SetConfigNum(GSM_StateMachine *s, int sections)
 1431 {
 1432     if (sections > MAX_CONFIG_NUM) return;
 1433     s->ConfigNum = sections;
 1434 }
 1435 
 1436 /**
 1437  * Expand path to user home.
 1438  */
 1439 void GSM_ExpandUserPath(char **string)
 1440 {
 1441     char *tmp = NULL, *home = NULL;
 1442 
 1443     /* Is there something to expand */
 1444     if (*string[0] != '~') return;
 1445 
 1446     /* Grab home */
 1447     home = getenv("HOME");
 1448     if (home == NULL) return;
 1449 
 1450     /* Allocate memory */
 1451     tmp = (char *)malloc(strlen(home) + strlen(*string) + 2);
 1452     if (tmp == NULL) return;
 1453 
 1454     /* Create final path */
 1455     strcpy(tmp, home);
 1456     strcat(tmp, *string + 1);
 1457 
 1458     /* Free old storage and replace it */
 1459     free(*string);
 1460     *string = tmp;
 1461 }
 1462 
 1463 /**
 1464  * Parses an ASCII string of comma delimited single digits into a set of integer
 1465  * parameters, any whitespace is ignored.
 1466  *
 1467  * @param out_params array to receive the parsed parameters
 1468  * @param num_params number of parameters out_params can hold
 1469  * @param args string containing list of parameters to parse
 1470  * @return ERR_NONE on success, otherwise ERR_INVALIDDATA
 1471  */
 1472 GSM_Error GSM_ReadParams(int *out_params, const int num_params, const char *args)
 1473 {
 1474   int *params_ptr = out_params;
 1475   const int *params_end = out_params + num_params * sizeof(int);
 1476   const char *args_ptr = args;
 1477   int whitespace_count = 0;
 1478   gboolean expect_comma = 0;
 1479 
 1480   if (!args)
 1481     return ERR_NONE;
 1482 
 1483   while (params_ptr < params_end) {
 1484     while (isspace((unsigned char)*args_ptr)) {
 1485       ++whitespace_count;
 1486       ++args_ptr;
 1487     }
 1488 
 1489     if(!*args_ptr)
 1490       return ERR_NONE;
 1491 
 1492     switch (*args_ptr) {
 1493       case '0': case '1': case '2': case '3': case '4':
 1494       case '5': case '6': case '7': case '8': case '9':
 1495         if (expect_comma) {
 1496           printf("expected comma but got %c for parameter %d\n", *args_ptr, (int)(++params_ptr - out_params));
 1497           return ERR_INVALIDDATA;
 1498         }
 1499         *params_ptr = *args_ptr - '0';
 1500         expect_comma = TRUE;
 1501         break;
 1502 
 1503       case ',':
 1504         ++params_ptr;
 1505         expect_comma = FALSE;
 1506         break;
 1507 
 1508       default: {
 1509         printf("error parsing parameters, unrecognized token '%c' in position %d\n",
 1510                *args_ptr, (int)(++params_ptr - --out_params + ++whitespace_count));
 1511         return ERR_INVALIDDATA; }
 1512     }
 1513 
 1514     ++args_ptr;
 1515   }
 1516 
 1517   return ERR_NONE;
 1518 }
 1519 
 1520 GSM_Error GSM_ReadCNMIParams(int out_params[5], const char *args)
 1521 {
 1522   return GSM_ReadParams(out_params, 5, args);
 1523 }
 1524 
 1525 GSM_Error GSM_ReadConfig(INI_Section *cfg_info, GSM_Config *cfg, int num)
 1526 {
 1527     INI_Section     *h;
 1528     unsigned char   section[50]={0};
 1529     gboolean    found = FALSE;
 1530     char        *Temp = NULL;
 1531     const int cnmi_default[5] = {-1,-1,-1,-1,-1};
 1532 
 1533     GSM_Error error = ERR_UNKNOWN;
 1534     cfg->UseGlobalDebugFile  = TRUE;
 1535     memcpy(cfg->CNMIParams, &cnmi_default, sizeof(cfg->CNMIParams));
 1536 
 1537     /* If we don't have valid config, bail out */
 1538     if (cfg_info == NULL) {
 1539         error = ERR_UNCONFIGURED;
 1540         goto fail;
 1541     }
 1542 
 1543     /* Which section should we read? */
 1544     if (num == 0) {
 1545         snprintf(section, sizeof(section) - 1, "gammu");
 1546     } else {
 1547         snprintf(section, sizeof(section) - 1, "gammu%i", num);
 1548     }
 1549 
 1550     /* Scan for section */
 1551         for (h = cfg_info; h != NULL; h = h->Next) {
 1552                 if (strcasecmp(section, h->SectionName) == 0) {
 1553             found = TRUE;
 1554             break;
 1555         }
 1556         }
 1557     if (!found) {
 1558         error = ERR_NONE_SECTION;
 1559         goto fail;
 1560     }
 1561 
 1562     /* Set device name */
 1563     free(cfg->Device);
 1564     cfg->Device      = INI_GetValue(cfg_info, section, "device",        FALSE);
 1565     if (!cfg->Device) {
 1566         cfg->Device      = INI_GetValue(cfg_info, section, "port",      FALSE);
 1567         if (!cfg->Device) {
 1568             cfg->Device          = strdup(DEFAULT_DEVICE);
 1569         } else {
 1570             cfg->Device          = strdup(cfg->Device);
 1571         }
 1572     } else {
 1573         cfg->Device          = strdup(cfg->Device);
 1574     }
 1575 
 1576     /* Set connection type */
 1577     free(cfg->Connection);
 1578     cfg->Connection  = INI_GetValue(cfg_info, section, "connection",    FALSE);
 1579     if (cfg->Connection == NULL) {
 1580         cfg->Connection          = strdup(DEFAULT_CONNECTION);
 1581     } else {
 1582         cfg->Connection          = strdup(cfg->Connection);
 1583     }
 1584 
 1585     /* Set time sync */
 1586     cfg->SyncTime = INI_GetBool(cfg_info, section, "synchronizetime", DEFAULT_SYNCHRONIZE_TIME);
 1587 
 1588     /* Set debug file */
 1589     free(cfg->DebugFile);
 1590     cfg->DebugFile   = INI_GetValue(cfg_info, section, "logfile",       FALSE);
 1591     if (cfg->DebugFile == NULL) {
 1592         cfg->DebugFile           = strdup(DEFAULT_DEBUG_FILE);
 1593     } else {
 1594         cfg->DebugFile           = strdup(cfg->DebugFile);
 1595         GSM_ExpandUserPath(&cfg->DebugFile);
 1596     }
 1597 
 1598     /* Set file locking */
 1599     cfg->LockDevice  = INI_GetBool(cfg_info, section, "use_locking", DEFAULT_LOCK_DEVICE);
 1600 
 1601     /* Set model */
 1602     Temp         = INI_GetValue(cfg_info, section, "model",         FALSE);
 1603     if (Temp == NULL || strcmp(Temp, "auto") == 0) {
 1604         strcpy(cfg->Model,DEFAULT_MODEL);
 1605     } else {
 1606         if (strlen(Temp) >= sizeof(cfg->Model))
 1607             Temp[sizeof(cfg->Model) - 1] = '\0';
 1608         strcpy(cfg->Model,Temp);
 1609     }
 1610 
 1611     /* Set Log format */
 1612     Temp         = INI_GetValue(cfg_info, section, "logformat",     FALSE);
 1613 
 1614     if (Temp == NULL) {
 1615         strcpy(cfg->DebugLevel,DEFAULT_DEBUG_LEVEL);
 1616     } else {
 1617         if (strlen(Temp) >= sizeof(cfg->DebugLevel))
 1618             Temp[sizeof(cfg->DebugLevel) - 1] = '\0';
 1619         strcpy(cfg->DebugLevel,Temp);
 1620     }
 1621 
 1622     /* Set startup info */
 1623     cfg->StartInfo = INI_GetBool(cfg_info, section, "startinfo", DEFAULT_START_INFO);
 1624 
 1625     /* Read localised strings for some phones */
 1626 
 1627     Temp         = INI_GetValue(cfg_info, section, "reminder",      FALSE);
 1628 
 1629     if (Temp == NULL) {
 1630         strcpy(cfg->TextReminder,"Reminder");
 1631     } else {
 1632         if (strlen(Temp) >= sizeof(cfg->TextReminder))
 1633             Temp[sizeof(cfg->TextReminder) - 1] = '\0';
 1634         strcpy(cfg->TextReminder,Temp);
 1635     }
 1636 
 1637     Temp         = INI_GetValue(cfg_info, section, "meeting",       FALSE);
 1638 
 1639     if (Temp == NULL) {
 1640         strcpy(cfg->TextMeeting,"Meeting");
 1641     } else {
 1642         if (strlen(Temp) >= sizeof(cfg->TextMeeting))
 1643             Temp[sizeof(cfg->TextMeeting) - 1] = '\0';
 1644         strcpy(cfg->TextMeeting,Temp);
 1645     }
 1646 
 1647     Temp         = INI_GetValue(cfg_info, section, "call",      FALSE);
 1648 
 1649     if (Temp == NULL) {
 1650         strcpy(cfg->TextCall,"Call");
 1651     } else {
 1652         if (strlen(Temp) >= sizeof(cfg->TextCall))
 1653             Temp[sizeof(cfg->TextCall) - 1] = '\0';
 1654         strcpy(cfg->TextCall,Temp);
 1655     }
 1656 
 1657     Temp         = INI_GetValue(cfg_info, section, "birthday",      FALSE);
 1658 
 1659     if (Temp == NULL) {
 1660         strcpy(cfg->TextBirthday,"Birthday");
 1661     } else {
 1662         if (strlen(Temp) >= sizeof(cfg->TextBirthday))
 1663             Temp[sizeof(cfg->TextBirthday) - 1] = '\0';
 1664         strcpy(cfg->TextBirthday,Temp);
 1665     }
 1666 
 1667     Temp         = INI_GetValue(cfg_info, section, "memo",      FALSE);
 1668 
 1669     if (Temp == NULL) {
 1670         strcpy(cfg->TextMemo,"Memo");
 1671     } else {
 1672         if (strlen(Temp) >= sizeof(cfg->TextMemo))
 1673             Temp[sizeof(cfg->TextMemo) - 1] = '\0';
 1674         strcpy(cfg->TextMemo,Temp);
 1675     }
 1676 
 1677     /* Phone features */
 1678     Temp         = INI_GetValue(cfg_info, section, "features",      FALSE);
 1679 
 1680     if (Temp == NULL) {
 1681         cfg->PhoneFeatures[0] = 0;
 1682     } else {
 1683         error = GSM_SetFeatureString(cfg->PhoneFeatures, Temp);
 1684 
 1685         if (error != ERR_NONE) {
 1686             goto fail;
 1687         }
 1688     }
 1689 
 1690     Temp = INI_GetValue(cfg_info, section, "atgen_setcnmi", FALSE);
 1691     if (Temp) {
 1692     error = GSM_ReadCNMIParams(cfg->CNMIParams, Temp);
 1693     if (error != ERR_NONE)
 1694       goto fail;
 1695   }
 1696 
 1697   return ERR_NONE;
 1698 
 1699 fail:
 1700     /* Special case, this config needs to be somehow valid */
 1701     if (num == 0) {
 1702         cfg->Device          = strdup(DEFAULT_DEVICE);
 1703         cfg->Connection          = strdup(DEFAULT_CONNECTION);
 1704         cfg->SyncTime            = DEFAULT_SYNCHRONIZE_TIME;
 1705         cfg->DebugFile           = strdup(DEFAULT_DEBUG_FILE);
 1706         cfg->LockDevice          = DEFAULT_LOCK_DEVICE;
 1707         strcpy(cfg->Model,DEFAULT_MODEL);
 1708         strcpy(cfg->DebugLevel,DEFAULT_DEBUG_LEVEL);
 1709         cfg->StartInfo           = DEFAULT_START_INFO;
 1710         strcpy(cfg->TextReminder,"Reminder");
 1711         strcpy(cfg->TextMeeting,"Meeting");
 1712         strcpy(cfg->TextCall,"Call");
 1713         strcpy(cfg->TextBirthday,"Birthday");
 1714         strcpy(cfg->TextMemo,"Memo");
 1715         cfg->PhoneFeatures[0] = 0;
 1716         /* Indicate that we used defaults */
 1717         return ERR_USING_DEFAULTS;
 1718     }
 1719     return error;
 1720 }
 1721 
 1722 void GSM_DumpMessageText_Custom(GSM_StateMachine *s, unsigned const char *message, size_t messagesize, int type, const char *text)
 1723 {
 1724     GSM_Debug_Info *curdi;
 1725 
 1726     curdi = GSM_GetDI(s);
 1727 
 1728     if (curdi->dl == DL_TEXT ||
 1729             curdi->dl == DL_TEXTALL ||
 1730             curdi->dl == DL_TEXTDATE ||
 1731             curdi->dl == DL_TEXTALLDATE) {
 1732         smprintf(s, "%s ", text);
 1733         smprintf(s, "type 0x%02X/length 0x%02lX/%ld",
 1734                 type, (long)messagesize, (long)messagesize);
 1735         DumpMessage(curdi, message, messagesize);
 1736     }
 1737 }
 1738 
 1739 void GSM_DumpMessageText(GSM_StateMachine *s, unsigned const char *message, size_t messagesize, int type)
 1740 {
 1741     GSM_DumpMessageText_Custom(s, message, messagesize, type, "SENDING frame");
 1742 }
 1743 
 1744 void GSM_DumpMessageTextRecv(GSM_StateMachine *s, unsigned const char *message, size_t messagesize, int type)
 1745 {
 1746     GSM_DumpMessageText_Custom(s, message, messagesize, type, "RECEIVED frame");
 1747 }
 1748 
 1749 void GSM_DumpMessageBinary_Custom(GSM_StateMachine *s, unsigned const char *message, size_t messagesize, int type, int direction)
 1750 {
 1751     size_t i=0;
 1752     GSM_Debug_Info *curdi;
 1753 
 1754     curdi = GSM_GetDI(s);
 1755 
 1756     if (curdi->dl == DL_BINARY) {
 1757         smprintf(s,"%c", direction);
 1758         smprintf(s,"%c",type);
 1759         smprintf(s,"%c",(int)(messagesize/256));
 1760         smprintf(s,"%c",(int)(messagesize%256));
 1761 
 1762         for (i=0;i<messagesize;i++) {
 1763             smprintf(s,"%c",message[i]);
 1764         }
 1765     }
 1766 }
 1767 void GSM_DumpMessageBinary(GSM_StateMachine *s, unsigned const char *message, size_t messagesize, int type)
 1768 {
 1769     GSM_DumpMessageBinary_Custom(s, message, messagesize, type, 0x01);
 1770 }
 1771 
 1772 void GSM_DumpMessageBinaryRecv(GSM_StateMachine *s, unsigned const char *message, size_t messagesize, int type)
 1773 {
 1774     GSM_DumpMessageBinary_Custom(s, message, messagesize, type, 0x02);
 1775 }
 1776 
 1777 void GSM_OSErrorInfo(GSM_StateMachine *s, const char *description)
 1778 {
 1779 #ifdef WIN32
 1780     int         i=0;
 1781     unsigned char   *lpMsgBuf = NULL;
 1782 #endif
 1783     GSM_Debug_Info *curdi;
 1784 
 1785     curdi = GSM_GetDI(s);
 1786 
 1787 #ifdef WIN32
 1788     /* We don't use errno in win32 - GetLastError gives better info */
 1789     if (GetLastError() != 0) {
 1790         if (curdi->dl == DL_TEXTERROR ||
 1791                 curdi->dl == DL_TEXT ||
 1792                 curdi->dl == DL_TEXTALL ||
 1793                 curdi->dl == DL_TEXTERRORDATE ||
 1794                 curdi->dl == DL_TEXTDATE ||
 1795                 curdi->dl == DL_TEXTALLDATE) {
 1796             FormatMessage(
 1797                 FORMAT_MESSAGE_ALLOCATE_BUFFER |
 1798                 FORMAT_MESSAGE_FROM_SYSTEM |
 1799                 FORMAT_MESSAGE_IGNORE_INSERTS,
 1800                 NULL,
 1801                 GetLastError(),
 1802                 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), /* Default language */
 1803                 (LPTSTR) &lpMsgBuf,
 1804                 0,
 1805                 NULL
 1806             );
 1807             for (i=0;i<(int)strlen(lpMsgBuf);i++) {
 1808                 if (lpMsgBuf[i] == 13 || lpMsgBuf[i] == 10) {
 1809                     lpMsgBuf[i] = ' ';
 1810                 }
 1811             }
 1812             smprintf(s,"[System error     - %s, %i, \"%s\"]\n", description, (int)GetLastError(), (LPCTSTR)lpMsgBuf);
 1813             LocalFree(lpMsgBuf);
 1814         }
 1815     }
 1816 #else
 1817 
 1818     if (errno!=-1) {
 1819         if (curdi->dl == DL_TEXTERROR ||
 1820                 curdi->dl == DL_TEXT ||
 1821                 curdi->dl == DL_TEXTALL ||
 1822                 curdi->dl == DL_TEXTERRORDATE ||
 1823                 curdi->dl == DL_TEXTDATE ||
 1824                 curdi->dl == DL_TEXTALLDATE) {
 1825             smprintf(s,"[System error     - %s, %i, \"%s\"]\n",description,errno,strerror(errno));
 1826         }
 1827     }
 1828 #endif
 1829 }
 1830 
 1831 void GSM_SetIncomingCallCallback(GSM_StateMachine *s, IncomingCallCallback callback, void *user_data)
 1832 {
 1833     s->User.IncomingCall = callback;
 1834     s->User.IncomingCallUserData = user_data;
 1835 }
 1836 
 1837 void GSM_SetIncomingSMSCallback(GSM_StateMachine *s, IncomingSMSCallback callback, void *user_data)
 1838 {
 1839     s->User.IncomingSMS = callback;
 1840     s->User.IncomingSMSUserData = user_data;
 1841 }
 1842 
 1843 void GSM_SetIncomingCBCallback(GSM_StateMachine *s, IncomingCBCallback callback, void *user_data)
 1844 {
 1845     s->User.IncomingCB = callback;
 1846     s->User.IncomingCBUserData = user_data;
 1847 }
 1848 
 1849 void GSM_SetIncomingUSSDCallback(GSM_StateMachine *s, IncomingUSSDCallback callback, void *user_data)
 1850 {
 1851     s->User.IncomingUSSD = callback;
 1852     s->User.IncomingUSSDUserData = user_data;
 1853 }
 1854 
 1855 void GSM_SetSendSMSStatusCallback(GSM_StateMachine *s, SendSMSStatusCallback callback, void *user_data)
 1856 {
 1857     s->User.SendSMSStatus = callback;
 1858     s->User.SendSMSStatusUserData = user_data;
 1859 }
 1860 
 1861 GSM_StateMachine *GSM_AllocStateMachine(void)
 1862 {
 1863     GSM_StateMachine *ret;
 1864     ret = (GSM_StateMachine *)calloc(1, sizeof(GSM_StateMachine));
 1865     if (ret == NULL) {
 1866         return ret;
 1867     }
 1868     ret->CurrentConfig = &(ret->Config[0]);
 1869     ret->Abort = FALSE;
 1870     return ret;
 1871 }
 1872 
 1873 void GSM_FreeStateMachine(GSM_StateMachine *s)
 1874 {
 1875     int i=0;
 1876 
 1877     if (s == NULL) return;
 1878 
 1879     /* Free allocated memory */
 1880     for (i = 0; i <= MAX_CONFIG_NUM; i++) {
 1881         free(s->Config[i].Device);
 1882         s->Config[i].Device = NULL;
 1883         free(s->Config[i].Connection);
 1884         s->Config[i].Connection = NULL;
 1885         free(s->Config[i].DebugFile);
 1886         s->Config[i].DebugFile = NULL;
 1887     }
 1888     free(s);
 1889     s = NULL;
 1890 }
 1891 
 1892 
 1893 GSM_ConnectionType GSM_GetUsedConnection(GSM_StateMachine *s)
 1894 {
 1895     return s->ConnectionType;
 1896 }
 1897 
 1898 GSM_PhoneModel *GSM_GetModelInfo(GSM_StateMachine *s)
 1899 {
 1900     return s->Phone.Data.ModelInfo;
 1901 }
 1902 
 1903 GSM_Debug_Info *GSM_GetDebug(GSM_StateMachine *s)
 1904 {
 1905     return s == NULL ? NULL : &(s->di);
 1906 }
 1907 
 1908 
 1909 /* How should editor hadle tabs in this file? Add editor commands here.
 1910  * vim: noexpandtab sw=8 ts=8 sts=8:
 1911  */