Gammu internals  1.38.0
s60phone.c
Go to the documentation of this file.
1 /* This program is free software; you can redistribute it and/or modify
2  * it under the terms of the GNU General Public License as published by
3  * the Free Software Foundation; either version 2 of the License, or
4  * (at your option) any later version.
5  *
6  * This program is distributed in the hope that it will be useful,
7  * but WITHOUT ANY WARRANTY; without even the implied warranty of
8  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
9  * GNU General Public License for more details.
10  *
11  * You should have received a copy of the GNU General Public License along
12  * with this program; if not, write to the Free Software Foundation, Inc.,
13  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
14  *
15  * Copyright (c) 2011 - 2012 Michal Cihar <[email protected]>
16  */
17 
18 
19 #define _GNU_SOURCE
20 #include "../../gsmstate.h"
21 #include "../../protocol/s60/s60-ids.h"
22 #include "../../gsmcomon.h"
23 #include "../../misc/coding/coding.h"
24 #include "../../gsmphones.h"
25 #include "../../gsmstate.h"
26 #include "../../service/gsmmisc.h"
27 #include "../../misc/locales.h"
28 #include "../pfunc.h"
29 #include <string.h>
30 
31 #include "../../../helper/string.h"
32 
33 #if defined(GSM_ENABLE_S60)
34 
35 GSM_Error S60_Install(GSM_StateMachine *s, const char *ExtraPath, gboolean Minimal)
36 {
37  GSM_StateMachine *gsm;
38  GSM_Debug_Info *debug_info;
39  GSM_Config *cfg;
40  GSM_Error error;
41  GSM_File PythonFile, PIPSFile, AppletFile;
42  gboolean install_python, install_pips;
43 
44  PythonFile.Buffer = NULL;
45  PythonFile.Used = 0;
46  PIPSFile.Buffer = NULL;
47  PIPSFile.Used = 0;
48  AppletFile.Buffer = NULL;
49  AppletFile.Used = 0;
50 
51  error = PHONE_FindDataFile(s, &AppletFile, ExtraPath, "gammu-s60-remote.sis");
52  if (error != ERR_NONE) {
53  smprintf(s, "Failed to find applet, trying another filename!\n");
54  error = PHONE_FindDataFile(s, &AppletFile, ExtraPath, "gammu-s60-remote-sign.sis");
55  if (error != ERR_NONE) {
56  smprintf(s, "Failed to load applet data!\n");
57  return ERR_INSTALL_NOT_FOUND;
58  }
59  }
60 
61  if (Minimal) {
62 
63  install_python = FALSE;
64  install_pips = FALSE;
65 
66  } else {
67 
68  error = PHONE_FindDataFile(s, &PythonFile, ExtraPath, "Python_2.0.0.sis");
69  if (error == ERR_NONE) {
70  install_python = TRUE;
71  } else {
72  smprintf(s, "Could not find Python for S60 to install, skipping!\n");
73  install_python = FALSE;
74  install_pips = FALSE;
75  }
76 
77  if (install_python) {
78  error = PHONE_FindDataFile(s, &PIPSFile, ExtraPath, "pips.sis");
79  if (error == ERR_NONE) {
80  install_pips = TRUE;
81  } else {
82  smprintf(s, "Could not find PIPS to install, skipping!\n");
83  install_pips = FALSE;
84  }
85  }
86  }
87 
88  gsm = GSM_AllocStateMachine();
89  if (gsm == NULL) {
90  return ERR_MOREMEMORY;
91  }
92 
93  /* Copy debug configuration */
94  debug_info = GSM_GetDebug(gsm);
95  *debug_info = *GSM_GetDebug(s);
96  debug_info->closable = FALSE;
97  GSM_SetDebugFileDescriptor(GSM_GetDebug(s)->df, FALSE, debug_info);
99 
100  /* Generate configuration */
101  cfg = GSM_GetConfig(gsm, 0);
102  cfg->Device = strdup(s->CurrentConfig->Device);
103  cfg->Connection = strdup("blueobex");
104  strcpy(cfg->Model, "obexnone");
105  strcpy(cfg->DebugLevel, s->CurrentConfig->DebugLevel);
107 
108  /* We have one configuration */
109  GSM_SetConfigNum(gsm, 1);
110 
111  error = GSM_InitConnection(gsm, 1);
112  if (error != ERR_NONE) {
113  return error;
114  }
115 
116  if (install_pips) {
117  error = PHONE_UploadFile(gsm, &PIPSFile);
118  free(PIPSFile.Buffer);
119  if (error != ERR_NONE) {
120  return error;
121  }
122  }
123 
124  if (install_python) {
125  error = PHONE_UploadFile(gsm, &PythonFile);
126  free(PythonFile.Buffer);
127  if (error != ERR_NONE) {
128  return error;
129  }
130  }
131 
132  error = PHONE_UploadFile(gsm, &AppletFile);
133  free(AppletFile.Buffer);
134  if (error != ERR_NONE) {
135  return error;
136  }
137 
138  error = GSM_TerminateConnection(gsm);
139  if (error != ERR_NONE) {
140  return error;
141  }
142 
143  /* Free up used memory */
145 
146  return ERR_NONE;
147 }
148 
149 GSM_Error S60_Initialise(GSM_StateMachine *s)
150 {
151  GSM_Phone_S60Data *Priv = &s->Phone.Data.Priv.S60;
152  GSM_Error error;
153  size_t i;
154 
155  Priv->SMSLocations = NULL;
156  Priv->SMSLocationsSize = 0;
157  Priv->SMSLocationsPos = 0;
158 
159  Priv->ContactLocations = NULL;
160  Priv->ContactLocationsSize = 0;
161  Priv->ContactLocationsPos = 0;
162 
163  Priv->CalendarLocations = NULL;
164  Priv->CalendarLocationsSize = 0;
165  Priv->CalendarLocationsPos = 0;
166 
167  Priv->ToDoLocations = NULL;
168  Priv->ToDoLocationsSize = 0;
169  Priv->ToDoLocationsPos = 0;
170 
171  s->Phone.Data.NetworkInfo = NULL;
172  s->Phone.Data.SignalQuality = NULL;
173  s->Phone.Data.BatteryCharge = NULL;
174  s->Phone.Data.Memory = NULL;
175  s->Phone.Data.MemoryStatus = NULL;
176  s->Phone.Data.CalStatus = NULL;
177  s->Phone.Data.ToDoStatus = NULL;
178 
179  for (i = 0; i < sizeof(Priv->MessageParts) / sizeof(Priv->MessageParts[0]); i++) {
180  Priv->MessageParts[i] = NULL;
181  }
182 
183  error = GSM_WaitFor (s, NULL, 0, 0, S60_TIMEOUT, ID_Initialise);
184  if (error != ERR_NONE) {
185  return error;
186  }
187 
188  if (Priv->MajorVersion != 1 || Priv->MinorVersion != 6) {
189  smprintf(s, "Unsupported protocol version\n");
190  return ERR_NOTSUPPORTED;
191  }
192 
194  if (error != ERR_NONE) {
195  return error;
196  }
197 
198  return error;
199 
200 // return ERR_NONE;
201 }
202 
206 GSM_Error S60_SplitValues(GSM_Protocol_Message *msg, GSM_StateMachine *s)
207 {
208  unsigned char * pos = msg->Buffer - 1;
209  size_t i;
210  GSM_Phone_S60Data *Priv = &s->Phone.Data.Priv.S60;
211 
212  for (i = 0; i < sizeof(Priv->MessageParts) / sizeof(Priv->MessageParts[0]); i++) {
213  Priv->MessageParts[i] = NULL;
214  }
215 
216  i = 0;
217 
218  if (msg->Length == 0) {
219  return ERR_NONE;
220  }
221 
222  while ((pos - msg->Buffer) < (ssize_t)msg->Length) {
223  if (i >= sizeof(Priv->MessageParts) / sizeof(Priv->MessageParts[0])) {
224  smprintf(s, "Too many reply parts!\n");
225  return ERR_MOREMEMORY;
226  }
227  Priv->MessageParts[i++] = pos + 1;
228 
229  /* Find end of next field */
230  pos = strchr(pos + 1, NUM_SEPERATOR);
231  if (pos == NULL) {
232  break;
233  }
234 
235  /* Zero terminate string */
236  *pos = 0;
237  }
238  return ERR_NONE;
239 }
240 
241 GSM_Error S60_Terminate(GSM_StateMachine *s)
242 {
243  GSM_Phone_S60Data *Priv = &s->Phone.Data.Priv.S60;
244 
245  free(Priv->SMSLocations);
246  Priv->SMSLocations = NULL;
247  Priv->SMSLocationsSize = 0;
248  Priv->SMSLocationsPos = 0;
249 
250  free(Priv->ContactLocations);
251  Priv->ContactLocations = NULL;
252  Priv->ContactLocationsSize = 0;
253  Priv->ContactLocationsPos = 0;
254 
255  free(Priv->CalendarLocations);
256  Priv->CalendarLocations = NULL;
257  Priv->CalendarLocationsSize = 0;
258  Priv->CalendarLocationsPos = 0;
259 
260  free(Priv->ToDoLocations);
261  Priv->ToDoLocations = NULL;
262  Priv->ToDoLocationsSize = 0;
263  Priv->ToDoLocationsPos = 0;
264 
265  return GSM_WaitFor(s, NULL, 0, NUM_QUIT, S60_TIMEOUT, ID_Terminate);
266 }
267 
268 static GSM_Error S60_Reply_Generic(GSM_Protocol_Message *msg, GSM_StateMachine *s)
269 {
270  switch (msg->Type) {
275  return ERR_NEEDANOTHERANSWER;
277  return ERR_NOTSUPPORTED;
280  return ERR_EMPTY;
281  default:
282  return ERR_NONE;
283  }
284 }
285 
286 static GSM_Error S60_Reply_SendSMS(GSM_Protocol_Message *msg, GSM_StateMachine *s)
287 {
288  switch (msg->Type) {
290  if (s->User.SendSMSStatus != NULL) {
291  s->User.SendSMSStatus(s, 1, -1, s->User.SendSMSStatusUserData);
292  }
293  return ERR_BUSY;
295  return ERR_NONE;
297  if (s->User.SendSMSStatus != NULL) {
298  s->User.SendSMSStatus(s, 0, -1, s->User.SendSMSStatusUserData);
299  }
300  return ERR_NONE;
302  if (s->User.SendSMSStatus != NULL) {
303  s->User.SendSMSStatus(s, 1, -1, s->User.SendSMSStatusUserData);
304  }
305  return ERR_UNKNOWN;
306  default:
307  return ERR_UNKNOWN;
308  }
309 }
310 
311 static GSM_Error S60_Reply_Connect(GSM_Protocol_Message *msg, GSM_StateMachine *s)
312 {
313  GSM_Phone_S60Data *Priv = &s->Phone.Data.Priv.S60;
314  char *pos;
315 
316  Priv->MajorVersion = atoi(msg->Buffer);
317  pos = strchr(msg->Buffer, '.');
318  if (pos == NULL) {
319  return ERR_UNKNOWN;
320  }
321  Priv->MinorVersion = atoi(pos + 1);
322  smprintf(s, "Connected to Gammu S60 Remote version %d.%d\n", Priv->MajorVersion, Priv->MinorVersion);
323 
324  return ERR_NONE;
325 }
326 
327 static GSM_Error S60_GetInfo(GSM_StateMachine *s)
328 {
330 }
331 
332 static GSM_Error S60_GetSignalQuality(GSM_StateMachine *s, GSM_SignalQuality *sig)
333 {
334  GSM_Error error;
335 
336  sig->BitErrorRate = -1;
337  sig->SignalStrength = -1;
338  sig->SignalPercent = -1;
339 
340  s->Phone.Data.SignalQuality = sig;
341  error = S60_GetInfo(s);
342  s->Phone.Data.SignalQuality = NULL;
343  return error;
344 }
345 
346 static GSM_Error S60_GetNetworkInfo(GSM_StateMachine *s, GSM_NetworkInfo *netinfo)
347 {
348  GSM_Error error;
349 
350  s->Phone.Data.NetworkInfo = netinfo;
352  s->Phone.Data.NetworkInfo = NULL;
353  return error;
354 }
355 
356 static GSM_Error S60_Reply_GetNetworkInfo(GSM_Protocol_Message *msg, GSM_StateMachine *s)
357 {
358  GSM_Phone_S60Data *Priv = &s->Phone.Data.Priv.S60;
359  GSM_Error error;
360  char *mcc, *mnc, *lac, *cellid;
361 
362  if (s->Phone.Data.NetworkInfo == NULL) {
363  return ERR_NONE;
364  }
365 
366  error = S60_SplitValues(msg, s);
367  if (error != ERR_NONE) {
368  return error;
369  }
370 
371  /* Grab values */
372  mcc = Priv->MessageParts[0];
373  mnc = Priv->MessageParts[1];
374  lac = Priv->MessageParts[2];
375  cellid =Priv->MessageParts[3];
376 
377  /* We need all of them */
378  if (mcc == NULL || mnc == NULL || lac == NULL || cellid == NULL) {
379  return ERR_UNKNOWN;
380  }
381 
382  strcpy(s->Phone.Data.NetworkInfo->CID, cellid);
383  strcpy(s->Phone.Data.NetworkInfo->NetworkCode, mcc);
384  strcat(s->Phone.Data.NetworkInfo->NetworkCode, " ");
385  strcat(s->Phone.Data.NetworkInfo->NetworkCode, mnc);
387  strcpy(s->Phone.Data.NetworkInfo->LAC, lac);
388  s->Phone.Data.NetworkInfo->NetworkName[0] = 0;
389  s->Phone.Data.NetworkInfo->NetworkName[1] = 0;
390  s->Phone.Data.NetworkInfo->GPRS = 0;
391  s->Phone.Data.NetworkInfo->PacketCID[0] = 0;
393  s->Phone.Data.NetworkInfo->PacketLAC[0] = 0;
394 
395  return ERR_NONE;
396 }
397 
398 static GSM_Error S60_GetBatteryCharge(GSM_StateMachine *s, GSM_BatteryCharge *bat)
399 {
400  GSM_Error error;
401 
403  s->Phone.Data.BatteryCharge = bat;
404  error = S60_GetInfo(s);
405  s->Phone.Data.BatteryCharge = NULL;
406  return error;
407 }
408 
409 
410 static GSM_Error S60_Reply_GetInfo(GSM_Protocol_Message *msg, GSM_StateMachine *s)
411 {
412  GSM_Phone_S60Data *Priv = &s->Phone.Data.Priv.S60;
413  GSM_Error error;
414  char *pos;
415  int signal_value;
417  GSM_BatteryCharge *BatteryCharge = s->Phone.Data.BatteryCharge;
418 
419  error = S60_SplitValues(msg, s);
420  if (error != ERR_NONE) {
421  return error;
422  }
423  if (Priv->MessageParts[0] == NULL || Priv->MessageParts[1] == NULL) {
424  return ERR_UNKNOWN;
425  }
426  smprintf(s, "Received %s=%s\n", Priv->MessageParts[0], Priv->MessageParts[1]);
427  if (strcmp(Priv->MessageParts[0], "imei") == 0) {
428  strcpy(s->Phone.Data.IMEI, Priv->MessageParts[1]);
429  } else if (strcmp(Priv->MessageParts[0], "model") == 0) {
430  /* Parse manufacturer */
431  pos = strcasestr(Priv->MessageParts[1], "(C)");
432  if (pos != NULL) {
433  strcpy(s->Phone.Data.Manufacturer, pos + 3);
434  }
435  /* Try to find model */
436  pos = strchr(Priv->MessageParts[1], ' ');
437  if (pos != NULL) {
438  pos = strchr(pos + 1, ' ');
439  if (pos != NULL) {
440  strcpy(s->Phone.Data.Model, pos + 1);
441  pos = strchr(s->Phone.Data.Model, ' ');
442  if (pos != NULL) {
443  *pos = 0;
444  }
445  } else {
446  strcpy(s->Phone.Data.Model, Priv->MessageParts[1]);
447  }
448  } else {
449  strcpy(s->Phone.Data.Model, Priv->MessageParts[1]);
450  }
451  s->Phone.Data.ModelInfo = GetModelData(s, NULL, s->Phone.Data.Model, NULL);
452 
453  if (s->Phone.Data.ModelInfo->number[0] == 0)
454  s->Phone.Data.ModelInfo = GetModelData(s, NULL, NULL, s->Phone.Data.Model);
455 
456  if (s->Phone.Data.ModelInfo->number[0] == 0)
457  s->Phone.Data.ModelInfo = GetModelData(s, s->Phone.Data.Model, NULL, NULL);
458 
459  if (s->Phone.Data.ModelInfo->number[0] == 0) {
460  smprintf(s, "Unknown model, but it should still work\n");
461  }
462  smprintf(s, "[Model name: `%s']\n", s->Phone.Data.Model);
463  smprintf(s, "[Model data: `%s']\n", s->Phone.Data.ModelInfo->number);
464  smprintf(s, "[Model data: `%s']\n", s->Phone.Data.ModelInfo->model);
465  } else if (strcmp(Priv->MessageParts[0], "s60_version") == 0) {
466  strcpy(s->Phone.Data.Version, Priv->MessageParts[1]);
467  strcat(s->Phone.Data.Version, ".");
468  strcat(s->Phone.Data.Version, Priv->MessageParts[2]);
470  } else if (Signal != NULL && strcmp(Priv->MessageParts[0], "signal_dbm") == 0) {
471  Signal->SignalStrength = atoi(Priv->MessageParts[1]);
472  } else if (Signal != NULL && strcmp(Priv->MessageParts[0], "signal_bars") == 0) {
473  signal_value = atoi(Priv->MessageParts[1]);
474  if (signal_value != 0) {
475  Signal->SignalPercent = 100 * 7 / signal_value;
476  } else {
477  Signal->SignalPercent = 0;
478  }
479  } else if (BatteryCharge != NULL && strcmp(Priv->MessageParts[0], "battery") == 0) {
480  BatteryCharge->BatteryPercent = atoi(Priv->MessageParts[1]);
481  }
482  return ERR_NEEDANOTHERANSWER;
483 }
484 
485 static GSM_Error S60_GetMemoryStatus(GSM_StateMachine *s, GSM_MemoryStatus *Status)
486 {
487  GSM_Error error;
488 
489  if (Status->MemoryType != MEM_ME) {
490  return ERR_NOTSUPPORTED;
491  }
492 
493  s->Phone.Data.MemoryStatus = Status;
494  Status->MemoryUsed = 0;
495  Status->MemoryFree = 1000;
497  s->Phone.Data.MemoryStatus = NULL;
498  return error;
499 }
500 
501 static GSM_Error S60_GetMemoryLocations(GSM_StateMachine *s)
502 {
503  GSM_Phone_S60Data *Priv = &s->Phone.Data.Priv.S60;
504  Priv->ContactLocationsPos = 0;
506 }
507 
508 static GSM_Error S60_StoreLocation(GSM_StateMachine *s, int **locations, size_t *size, size_t *pos, int location)
509 {
510  if ((*pos) + 3 >= (*size)) {
511  *locations = (int *)realloc(*locations, ((*size) + 20) * sizeof(int));
512  if (*locations == NULL) {
513  return ERR_MOREMEMORY;
514  }
515  *size += 20;
516  }
517  (*locations)[(*pos)] = location;
518  (*locations)[(*pos) + 1] = 0;
519  (*pos) += 1;
520  return ERR_NONE;
521 }
522 
523 
524 static GSM_Error S60_Reply_GetMemoryStatus(GSM_Protocol_Message *msg, GSM_StateMachine *s)
525 {
526  s->Phone.Data.MemoryStatus->MemoryUsed = atoi(msg->Buffer);
527 
528  return ERR_NONE;
529 }
530 
531 static GSM_Error S60_Reply_ContactHash(GSM_Protocol_Message *msg, GSM_StateMachine *s)
532 {
533  GSM_Phone_S60Data *Priv = &s->Phone.Data.Priv.S60;
534  GSM_Error error;
535 
536  error = S60_SplitValues(msg, s);
537  if (error != ERR_NONE) {
538  return error;
539 
540  }
541 
542  if (Priv->MessageParts[0] == NULL) {
543  return ERR_UNKNOWN;
544  }
545 
546  error = S60_StoreLocation(s, &Priv->ContactLocations, &Priv->ContactLocationsSize, &Priv->ContactLocationsPos, atoi(Priv->MessageParts[0]));
547  if (error != ERR_NONE) {
548  return error;
549 
550  }
551 
552  return ERR_NEEDANOTHERANSWER;
553 }
554 
555 static GSM_Error S60_Reply_GetCalendarStatus(GSM_Protocol_Message *msg, GSM_StateMachine *s)
556 {
557  GSM_Phone_S60Data *Priv = &s->Phone.Data.Priv.S60;
558  GSM_Error error;
559 
560  error = S60_SplitValues(msg, s);
561  if (error != ERR_NONE) {
562  return error;
563  }
564 
565  if (Priv->MessageParts[0] == NULL || Priv->MessageParts[1] == NULL || Priv->MessageParts[2] == NULL) {
566  return ERR_UNKNOWN;
567  }
568 
569  if (s->Phone.Data.CalStatus != NULL) {
570  s->Phone.Data.CalStatus->Used = atoi(Priv->MessageParts[1]);
571  }
572  if (s->Phone.Data.ToDoStatus != NULL) {
573  s->Phone.Data.ToDoStatus->Used = atoi(Priv->MessageParts[2]);
574  }
575 
576  return ERR_NONE;
577 }
578 
579 static GSM_Error S60_GetCalendarStatus(GSM_StateMachine *s, GSM_CalendarStatus *Status)
580 {
581  GSM_Error error;
582 
583  s->Phone.Data.CalStatus = Status;
584  Status->Used = 0;
585  Status->Free = 1000;
587  s->Phone.Data.CalStatus = NULL;
588  return error;
589 }
590 
591 static GSM_Error S60_GetCalendarLocations(GSM_StateMachine *s)
592 {
593  GSM_Phone_S60Data *Priv = &s->Phone.Data.Priv.S60;
594 
595  Priv->CalendarLocationsPos = 0;
597 }
598 
599 static GSM_Error S60_Reply_CalendarCount(GSM_Protocol_Message *msg, GSM_StateMachine *s)
600 {
601  GSM_Phone_S60Data *Priv = &s->Phone.Data.Priv.S60;
602  GSM_Error error;
603 
604  error = S60_SplitValues(msg, s);
605  if (error != ERR_NONE) {
606  return error;
607 
608  }
609 
610  if (Priv->MessageParts[0] == NULL || Priv->MessageParts[1] == NULL) {
611  return ERR_UNKNOWN;
612  }
613 
614  if (strcmp(Priv->MessageParts[1], "appointment") != 0 &&
615  strcmp(Priv->MessageParts[1], "event") != 0 &&
616  strcmp(Priv->MessageParts[1], "reminder") != 0 &&
617  strcmp(Priv->MessageParts[1], "anniversary") != 0) {
618  return ERR_NEEDANOTHERANSWER;
619  }
620 
621  error = S60_StoreLocation(s, &Priv->CalendarLocations, &Priv->CalendarLocationsSize, &Priv->CalendarLocationsPos, atoi(Priv->MessageParts[0]));
622  if (error != ERR_NONE) {
623  return error;
624 
625  }
626 
627  if (s->Phone.Data.CalStatus != NULL) {
628  s->Phone.Data.CalStatus->Used++;
629  }
630  return ERR_NEEDANOTHERANSWER;
631 }
632 
633 static GSM_Error S60_GetToDoStatus(GSM_StateMachine *s, GSM_ToDoStatus *Status)
634 {
635  GSM_Error error;
636 
637  s->Phone.Data.ToDoStatus = Status;
638  Status->Used = 0;
639  Status->Free = 1000;
641  s->Phone.Data.ToDoStatus = NULL;
642  return error;
643 }
644 
645 static GSM_Error S60_GetToDoLocations(GSM_StateMachine *s)
646 {
647  GSM_Phone_S60Data *Priv = &s->Phone.Data.Priv.S60;
648 
649  Priv->ToDoLocationsPos = 0;
651 }
652 
653 static GSM_Error S60_Reply_ToDoCount(GSM_Protocol_Message *msg, GSM_StateMachine *s)
654 {
655  GSM_Phone_S60Data *Priv = &s->Phone.Data.Priv.S60;
656  GSM_Error error;
657 
658  error = S60_SplitValues(msg, s);
659  if (error != ERR_NONE) {
660  return error;
661 
662  }
663 
664  if (Priv->MessageParts[0] == NULL || Priv->MessageParts[1] == NULL) {
665  return ERR_UNKNOWN;
666  }
667 
668  if (strcmp(Priv->MessageParts[1], "todo") != 0) {
669  return ERR_NEEDANOTHERANSWER;
670  }
671 
672  error = S60_StoreLocation(s, &Priv->ToDoLocations, &Priv->ToDoLocationsSize, &Priv->ToDoLocationsPos, atoi(Priv->MessageParts[0]));
673  if (error != ERR_NONE) {
674  return error;
675 
676  }
677 
678  if (s->Phone.Data.ToDoStatus != NULL) {
679  s->Phone.Data.ToDoStatus->Used++;
680  }
681  return ERR_NEEDANOTHERANSWER;
682 }
683 
684 GSM_Error S60_GetMemory(GSM_StateMachine *s, GSM_MemoryEntry *Entry)
685 {
686  char buffer[100];
687  GSM_Error error;
688 
689  if (Entry->MemoryType != MEM_ME) {
690  return ERR_NOTSUPPORTED;
691  }
692  Entry->EntriesNum = 0;
693 
694  sprintf(buffer, "%d", Entry->Location);
695 
696  s->Phone.Data.Memory = Entry;
697  error = GSM_WaitFor(s, buffer, strlen(buffer), NUM_CONTACTS_REQUEST_CONTACT, S60_TIMEOUT, ID_GetMemory);
698  s->Phone.Data.Memory = NULL;
699 
700  return error;
701 }
702 
703 GSM_Error S60_GetNextMemory(GSM_StateMachine *s, GSM_MemoryEntry *Entry, gboolean Start)
704 {
705  GSM_Error error;
706  GSM_Phone_S60Data *Priv = &s->Phone.Data.Priv.S60;
707 
708  if (Entry->MemoryType != MEM_ME) {
709  return ERR_NOTSUPPORTED;
710  }
711 
712  if (Start) {
713  error = S60_GetMemoryLocations(s);
714  if (error != ERR_NONE) {
715  return error;
716  }
717  Priv->ContactLocationsPos = 0;
718  }
719 
720  if (Priv->ContactLocations[Priv->ContactLocationsPos] == 0) {
721  return ERR_EMPTY;
722  }
723 
724  Entry->Location = Priv->ContactLocations[Priv->ContactLocationsPos++];
725 
726  return S60_GetMemory(s, Entry);
727 }
728 
729 static GSM_Error S60_Reply_GetMemory(GSM_Protocol_Message *msg, GSM_StateMachine *s)
730 {
731  GSM_Phone_S60Data *Priv = &s->Phone.Data.Priv.S60;
732  GSM_Error error;
733  char *pos, *type, *location, *value;
734  GSM_MemoryEntry *Entry;
735  gboolean text = FALSE;
736 
737  error = S60_SplitValues(msg, s);
738  if (error != ERR_NONE) {
739  return error;
740  }
741 
742  Entry = s->Phone.Data.Memory;
743 
744  /* Grab values */
745  pos = Priv->MessageParts[0];
746  type = Priv->MessageParts[1];
747  location = Priv->MessageParts[2];
748  value =Priv->MessageParts[3];
749 
750  /* We need all of them */
751  if (pos == NULL || type == NULL || location == NULL || value == NULL) {
752  return ERR_UNKNOWN;
753  }
754 
755  /* Handle location */
756  if ((strcmp(location, "work") == 0)) {
757  Entry->Entries[Entry->EntriesNum].Location = PBK_Location_Work;
758  } else if ((strcmp(location, "home") == 0)) {
759  Entry->Entries[Entry->EntriesNum].Location = PBK_Location_Home;
760  } else {
762  }
763 
764  /* Store in contacts */
765  if(strcmp(type, "city") == 0) {
766  text = TRUE;
767  Entry->Entries[Entry->EntriesNum].EntryType = PBK_Text_City;
768  } else if(strcmp(type, "company_name") == 0) {
769  text = TRUE;
770  Entry->Entries[Entry->EntriesNum].EntryType = PBK_Text_Company;
771  } else if(strcmp(type, "country") == 0) {
772  text = TRUE;
773  Entry->Entries[Entry->EntriesNum].EntryType = PBK_Text_Country;
774  } else if(strcmp(type, "date") == 0) {
775  Entry->Entries[Entry->EntriesNum].EntryType = PBK_Date;
776  if (!ReadVCALDateTime(value, &(Entry->Entries[Entry->EntriesNum].Date))) {
777  return ERR_UNKNOWN;
778  }
779  } else if(strcmp(type, "dtmf_string") == 0) {
780  text = TRUE;
781  Entry->Entries[Entry->EntriesNum].EntryType = PBK_Text_DTMF;
782  } else if(strcmp(type, "email_address") == 0) {
783  text = TRUE;
784  Entry->Entries[Entry->EntriesNum].EntryType = PBK_Text_Email;
785  } else if(strcmp(type, "po_box") == 0) {
786  text = TRUE;
787  } else if(strcmp(type, "extended_address") == 0) {
788  text = TRUE;
789  } else if(strcmp(type, "fax_number") == 0) {
790  text = TRUE;
791  Entry->Entries[Entry->EntriesNum].EntryType = PBK_Number_Fax;
792  } else if(strcmp(type, "first_name") == 0) {
793  text = TRUE;
795  } else if(strcmp(type, "second_name") == 0) {
796  text = TRUE;
798  } else if(strcmp(type, "job_title") == 0) {
799  text = TRUE;
801  } else if(strcmp(type, "last_name") == 0) {
802  text = TRUE;
804  } else if(strcmp(type, "voip") == 0) {
805  text = TRUE;
806  Entry->Entries[Entry->EntriesNum].EntryType = PBK_Text_VOIP;
807  } else if(strcmp(type, "sip_id") == 0) {
808  text = TRUE;
809  Entry->Entries[Entry->EntriesNum].EntryType = PBK_Text_SIP;
810  } else if(strcmp(type, "push_to_talk") == 0) {
811  text = TRUE;
812  Entry->Entries[Entry->EntriesNum].EntryType = PBK_PushToTalkID;
813  } else if(strcmp(type, "mobile_number") == 0) {
814  text = TRUE;
816  } else if(strcmp(type, "note") == 0) {
817  text = TRUE;
818  Entry->Entries[Entry->EntriesNum].EntryType = PBK_Text_Note;
819  } else if(strcmp(type, "pager_number") == 0) {
820  text = TRUE;
821  Entry->Entries[Entry->EntriesNum].EntryType = PBK_Number_Pager;
822  } else if(strcmp(type, "phone_number") == 0) {
823  text = TRUE;
825  } else if(strcmp(type, "postal_address") == 0) {
826  text = TRUE;
827  Entry->Entries[Entry->EntriesNum].EntryType = PBK_Text_Postal;
828  } else if(strcmp(type, "postal_code") == 0) {
829  text = TRUE;
830  Entry->Entries[Entry->EntriesNum].EntryType = PBK_Text_Zip;
831  } else if(strcmp(type, "state") == 0) {
832  text = TRUE;
833  Entry->Entries[Entry->EntriesNum].EntryType = PBK_Text_State;
834  } else if(strcmp(type, "street_address") == 0) {
835  text = TRUE;
837  } else if(strcmp(type, "url") == 0) {
838  text = TRUE;
839  Entry->Entries[Entry->EntriesNum].EntryType = PBK_Text_URL;
840  } else if(strcmp(type, "video_number") == 0) {
841  text = TRUE;
842  Entry->Entries[Entry->EntriesNum].EntryType = PBK_Number_Video;
843  } else if(strcmp(type, "wvid") == 0) {
844  text = TRUE;
845  Entry->Entries[Entry->EntriesNum].EntryType = PBK_Text_WVID;
846  } else if(strcmp(type, "thumbnail_image") == 0) {
847  /* TODO */
848  } else if(strcmp(type, "suffix") == 0) {
849  text = TRUE;
851  } else if(strcmp(type, "prefix") == 0) {
852  text = TRUE;
854  } else if(strcmp(type, "share_view") == 0) {
855  text = TRUE;
856  Entry->Entries[Entry->EntriesNum].EntryType = PBK_Text_SWIS;
857  } else {
858  smprintf(s, "WARNING: Ignoring unknown field type: %s\n", type);
859  return ERR_NEEDANOTHERANSWER;
860  }
861 
862  if (text) {
863  if (strlen(value) == 0) {
864  /* Ignore empty responses */
865  return ERR_NEEDANOTHERANSWER;
866  }
867  DecodeUTF8(Entry->Entries[Entry->EntriesNum].Text, value, strlen(value));
868  }
869 
870  Entry->EntriesNum++;
871  if (Entry->EntriesNum >= GSM_PHONEBOOK_ENTRIES) {
872  smprintf(s, "ERROR: reached limit of phonebook entries\n");
873  return ERR_MOREMEMORY;
874  }
875 
876  return ERR_NEEDANOTHERANSWER;
877 }
878 
879 GSM_Error S60_DeleteMemory(GSM_StateMachine *s, GSM_MemoryEntry *Entry)
880 {
881  char buffer[100];
882  GSM_Error error;
883 
884  if (Entry->MemoryType != MEM_ME) {
885  return ERR_NOTSUPPORTED;
886  }
887 
888  sprintf(buffer, "%d", Entry->Location);
889 
890  error = GSM_WaitFor(s, buffer, strlen(buffer), NUM_CONTACTS_DELETE, S60_TIMEOUT, ID_None);
891 
892  return error;
893 }
894 
895 GSM_Error S60_SetMemoryEntry(GSM_StateMachine *s, GSM_SubMemoryEntry *Entry, int pos, int reqtype)
896 {
897  const char *type, *location = "none";
898  char value[(GSM_PHONEBOOK_TEXT_LENGTH + 1) * 2];
899  char buffer [100 + (GSM_PHONEBOOK_TEXT_LENGTH + 1) * 2];
900  gboolean text = FALSE;
901 
902  switch (Entry->Location) {
904  location = "none";
905  break;
906  case PBK_Location_Home:
907  location = "home";
908  break;
909  case PBK_Location_Work:
910  location = "work";
911  break;
912  }
913 
914  switch (Entry->EntryType) {
915  case PBK_Text_City:
916  type = "city";
917  text = TRUE;
918  break;
919  case PBK_Text_Company:
920  type = "company_name";
921  text = TRUE;
922  break;
923  case PBK_Text_Country:
924  type = "country";
925  text = TRUE;
926  break;
927  case PBK_Date:
928  type = "date";
929  snprintf(value, sizeof(value), "%04d%02d%02d", Entry->Date.Year, Entry->Date.Month, Entry->Date.Day);
930  break;
931  case PBK_Text_DTMF:
932  type = "dtmf_string";
933  text = TRUE;
934  break;
935  case PBK_Text_Email:
936  type = "email_address";
937  text = TRUE;
938  break;
939  case PBK_Number_Fax:
940  type = "fax_number";
941  text = TRUE;
942  break;
943  case PBK_Text_FirstName:
944  type = "first_name";
945  text = TRUE;
946  break;
947  case PBK_Text_SecondName:
948  type = "second_name";
949  text = TRUE;
950  break;
951  case PBK_Text_JobTitle:
952  type = "job_title";
953  text = TRUE;
954  break;
955  case PBK_Text_LastName:
956  type = "last_name";
957  text = TRUE;
958  break;
959  case PBK_Text_VOIP:
960  type = "voip";
961  text = TRUE;
962  break;
963  case PBK_Text_SIP:
964  type = "sip_id";
965  text = TRUE;
966  break;
967  case PBK_PushToTalkID:
968  type = "push_to_talk";
969  text = TRUE;
970  break;
971  case PBK_Number_Mobile:
972  type = "mobile_number";
973  text = TRUE;
974  break;
975  case PBK_Text_Note:
976  type = "note";
977  text = TRUE;
978  break;
979  case PBK_Number_Pager:
980  type = "pager";
981  text = TRUE;
982  break;
983  case PBK_Number_General:
984  type = "phone_number";
985  text = TRUE;
986  break;
987  case PBK_Text_Postal:
988  type = "postal_address";
989  text = TRUE;
990  break;
991  case PBK_Text_Zip:
992  type = "postal_code";
993  text = TRUE;
994  break;
995  case PBK_Text_State:
996  type = "state";
997  text = TRUE;
998  break;
1000  type = "street_address";
1001  text = TRUE;
1002  break;
1003  case PBK_Text_URL:
1004  type = "url";
1005  text = TRUE;
1006  break;
1007  case PBK_Number_Video:
1008  type = "video_number";
1009  text = TRUE;
1010  break;
1011  case PBK_Text_WVID:
1012  type = "wvid";
1013  text = TRUE;
1014  break;
1015  case PBK_Text_NameSuffix:
1016  type = "suffix";
1017  text = TRUE;
1018  break;
1019  case PBK_Text_NamePrefix:
1020  type = "prefix";
1021  text = TRUE;
1022  break;
1023  case PBK_Text_SWIS:
1024  type = "share_view";
1025  text = TRUE;
1026  break;
1027  default:
1028  Entry->AddError = ERR_NOTIMPLEMENTED;
1029  return ERR_NONE;
1030  }
1031 
1032  if (text) {
1033  EncodeUTF8(value, Entry->Text);
1034  }
1035 
1036  snprintf(buffer, sizeof(buffer), "%d%c%s%c%s%c%s%c",
1037  pos, NUM_SEPERATOR,
1038  type , NUM_SEPERATOR,
1039  location, NUM_SEPERATOR,
1040  value, NUM_SEPERATOR);
1041 
1042  return GSM_WaitFor(s, buffer, strlen(buffer), reqtype, S60_TIMEOUT, ID_None);
1043 }
1044 
1045 GSM_Error S60_SetMemory(GSM_StateMachine *s, GSM_MemoryEntry *Entry)
1046 {
1047  GSM_MemoryEntry oldentry;
1048  GSM_Error error;
1049  int i;
1050 
1051  if (Entry->MemoryType != MEM_ME) {
1052  return ERR_NOTSUPPORTED;
1053  }
1054  oldentry.MemoryType = Entry->MemoryType;
1055  oldentry.Location = Entry->Location;
1056 
1057  /* Read existing entry */
1058  error = S60_GetMemory(s, &oldentry);
1059  if (error != ERR_NONE) {
1060  return error;
1061  }
1062 
1063  /* TODO: Here should be some clever method for doing only needed changes */
1064 
1065  /* Delete all existing fields */
1066  for (i = 0; i < oldentry.EntriesNum; i++) {
1067  error = S60_SetMemoryEntry(s, &(oldentry.Entries[i]), Entry->Location, NUM_CONTACTS_CHANGE_REMOVEFIELD);
1068  if (error != ERR_NONE) {
1069  return error;
1070  }
1071  }
1072 
1073  /* Set all new fields */
1074  for (i = 0; i < Entry->EntriesNum; i++) {
1075  error = S60_SetMemoryEntry(s, &(Entry->Entries[i]), Entry->Location, NUM_CONTACTS_CHANGE_ADDFIELD);
1076  if (error != ERR_NONE) {
1077  return error;
1078  }
1079  }
1080 
1081  return ERR_NONE;
1082 }
1083 
1084 GSM_Error S60_AddMemory(GSM_StateMachine *s, GSM_MemoryEntry *Entry)
1085 {
1086  GSM_Error error;
1087 
1088  if (Entry->MemoryType != MEM_ME) {
1089  return ERR_NOTSUPPORTED;
1090  }
1091 
1092  s->Phone.Data.Memory = Entry;
1093  error = GSM_WaitFor(s, NULL, 0, NUM_CONTACTS_ADD, S60_TIMEOUT, ID_SetMemory);
1094  s->Phone.Data.Memory = NULL;
1095 
1096  if (error != ERR_NONE) {
1097  return error;
1098  }
1099 
1100  return S60_SetMemory(s, Entry);
1101 }
1102 
1103 static GSM_Error S60_Reply_AddMemory(GSM_Protocol_Message *msg, GSM_StateMachine *s)
1104 {
1105  s->Phone.Data.Memory->Location = atoi(msg->Buffer);
1106  smprintf(s, "Added contact ID %d\n", s->Phone.Data.Memory->Location);
1107  return ERR_NONE;
1108 }
1109 
1110 static GSM_Error S60_Reply_GetCalendar(GSM_Protocol_Message *msg, GSM_StateMachine *s)
1111 {
1112  GSM_Phone_S60Data *Priv = &s->Phone.Data.Priv.S60;
1113  GSM_Error error;
1114  char *type, *content, *location, *start, *end, *modified, *replication, *alarm_time, *repeat, *repeat_rule, *repeat_start, *repeat_end, *interval;
1115  GSM_CalendarEntry *Entry;
1116  int i;
1117 
1118  error = S60_SplitValues(msg, s);
1119  if (error != ERR_NONE) {
1120  return error;
1121  }
1122 
1123  /* Check for required fields */
1124  for (i = 0; i < 16; i++) {
1125  if (Priv->MessageParts[i] == NULL) {
1126  smprintf(s, "Not enough parts in reply!\n");
1127  return ERR_UNKNOWN;
1128  }
1129  }
1130 
1131  Entry = s->Phone.Data.Cal;
1132 
1133  /* Grab values */
1134  /* No need to parse position */
1135  type = Priv->MessageParts[1];
1136  content = Priv->MessageParts[2];
1137  location = Priv->MessageParts[3];
1138  start = Priv->MessageParts[4];
1139  end = Priv->MessageParts[5];
1140  modified = Priv->MessageParts[6];
1141  replication = Priv->MessageParts[7];
1142  alarm_time = Priv->MessageParts[8];
1143  /* Priority not used for calendar */
1144  repeat = Priv->MessageParts[10];
1145  repeat_rule = Priv->MessageParts[11];
1146  /* We do not handle repeat_exceptions for now */
1147  repeat_start = Priv->MessageParts[13];
1148  repeat_end = Priv->MessageParts[14];
1149  interval = Priv->MessageParts[15];
1150 
1151  /* Check for correct type */
1152  if (strcmp(type, "appointment") == 0) {
1153  Entry->Type = GSM_CAL_MEETING;
1154  } else if (strcmp(type, "event") == 0) {
1155  Entry->Type = GSM_CAL_MEMO;
1156  } else if (strcmp(type, "anniversary") == 0) {
1157  Entry->Type = GSM_CAL_BIRTHDAY;
1158  } else if (strcmp(type, "reminder") == 0) {
1159  Entry->Type = GSM_CAL_REMINDER;
1160  } else {
1161  return ERR_EMPTY;
1162  }
1163 
1164  if (strlen(content) > 0) {
1165  Entry->Entries[Entry->EntriesNum].EntryType = CAL_TEXT;
1166  DecodeUTF8(Entry->Entries[Entry->EntriesNum].Text, content, strlen(content));
1167  Entry->EntriesNum++;
1168  }
1169 
1170  if (strlen(location) > 0) {
1171  Entry->Entries[Entry->EntriesNum].EntryType = CAL_LOCATION;
1172  DecodeUTF8(Entry->Entries[Entry->EntriesNum].Text, location, strlen(location));
1173  Entry->EntriesNum++;
1174  }
1175 
1176  if (strlen(start) > 0) {
1178  GSM_DateTimeFromTimestamp(&(Entry->Entries[Entry->EntriesNum].Date), start);
1179  Entry->EntriesNum++;
1180  }
1181 
1182  if (strlen(end) > 0) {
1183  Entry->Entries[Entry->EntriesNum].EntryType = CAL_END_DATETIME;
1184  GSM_DateTimeFromTimestamp(&(Entry->Entries[Entry->EntriesNum].Date), end);
1185  Entry->EntriesNum++;
1186  }
1187 
1188  if (strlen(modified) > 0) {
1189  Entry->Entries[Entry->EntriesNum].EntryType = CAL_LAST_MODIFIED;
1190  GSM_DateTimeFromTimestamp(&(Entry->Entries[Entry->EntriesNum].Date), modified);
1191  Entry->EntriesNum++;
1192  }
1193 
1194  if (strlen(replication) > 0) {
1195  Entry->Entries[Entry->EntriesNum].EntryType = CAL_PRIVATE;
1196  if (strcmp(replication, "open") == 0) {
1197  Entry->Entries[Entry->EntriesNum].Number = 0;
1198  } else {
1199  Entry->Entries[Entry->EntriesNum].Number = 1;
1200  }
1201  Entry->EntriesNum++;
1202  }
1203 
1204  if (strlen(alarm_time) > 0) {
1206  GSM_DateTimeFromTimestamp(&(Entry->Entries[Entry->EntriesNum].Date), alarm_time);
1207  Entry->EntriesNum++;
1208  }
1209 
1210  if ((strlen(repeat) > 0) && (strlen(repeat_rule) > 0)) {
1211  if (strcmp(repeat, "daily") == 0 ) {
1212  } else if (strcmp(repeat, "weekly") == 0 ) {
1214  Entry->Entries[Entry->EntriesNum].Number = atoi(repeat_rule);
1215  Entry->EntriesNum++;
1216  } else if (strcmp(repeat, "monthly_by_dates") == 0 ) {
1217  Entry->Entries[Entry->EntriesNum].EntryType = CAL_REPEAT_DAY;
1218  Entry->Entries[Entry->EntriesNum].Number = atoi(repeat_rule);
1219  Entry->EntriesNum++;
1220  } else if (strcmp(repeat, "monthly_by_days") == 0 ) {
1221  } else if (strcmp(repeat, "yearly_by_date") == 0 ) {
1222  } else if (strcmp(repeat, "yearly_by_day") == 0 ) {
1224  Entry->Entries[Entry->EntriesNum].Number = atoi(repeat_rule);
1225  Entry->EntriesNum++;
1226  } else {
1227  smprintf(s, "Unknown value for repeating: %s\n", repeat);
1228  return ERR_UNKNOWN;
1229  }
1230  }
1231 
1232  if (strlen(repeat_start) > 0) {
1234  GSM_DateTimeFromTimestamp(&(Entry->Entries[Entry->EntriesNum].Date), repeat_start);
1235  Entry->EntriesNum++;
1236  }
1237 
1238  if (strlen(repeat_end) > 0) {
1240  GSM_DateTimeFromTimestamp(&(Entry->Entries[Entry->EntriesNum].Date), repeat_end);
1241  Entry->EntriesNum++;
1242  }
1243 
1244  if (strlen(interval) > 0) {
1246  Entry->Entries[Entry->EntriesNum].Number = atoi(interval);
1247  Entry->EntriesNum++;
1248  }
1249 
1250 
1251  /* TODO: implement rest of repeating */
1252 
1253  return ERR_NONE;
1254 }
1255 
1256 GSM_Error S60_GetCalendar(GSM_StateMachine *s, GSM_CalendarEntry *Entry)
1257 {
1258  char buffer[100];
1259  GSM_Error error;
1260 
1261  Entry->EntriesNum = 0;
1262 
1263  sprintf(buffer, "%d", Entry->Location);
1264 
1265  s->Phone.Data.Cal = Entry;
1266  error = GSM_WaitFor(s, buffer, strlen(buffer), NUM_CALENDAR_REQUEST_ENTRY, S60_TIMEOUT, ID_GetCalendarNote);
1267  s->Phone.Data.Cal = NULL;
1268 
1269  return error;
1270 }
1271 
1272 static GSM_Error S60_Reply_AddCalendar(GSM_Protocol_Message *msg, GSM_StateMachine *s)
1273 {
1274  s->Phone.Data.Cal->Location = atoi(msg->Buffer);
1275  smprintf(s, "Added calendar ID %d\n", s->Phone.Data.Cal->Location);
1276  return ERR_NONE;
1277 }
1278 
1279 int S60_FindCalendarField(GSM_StateMachine *s, GSM_CalendarEntry *Entry, GSM_CalendarType Type)
1280 {
1281  int i;
1282 
1283  for (i = 0; i < Entry->EntriesNum; i++) {
1284  if (Entry->Entries[i].EntryType == Type && Entry->Entries[i].AddError == ERR_NOTSUPPORTED) {
1285  Entry->Entries[i].AddError = ERR_NONE;
1286  return i;
1287  }
1288  }
1289  return -1;
1290 }
1291 
1292 void S60_SetCalendarError(GSM_StateMachine *s, GSM_CalendarEntry *Entry)
1293 {
1294  int i;
1295 
1296  for (i = 0; i < Entry->EntriesNum; i++) {
1297  Entry->Entries[i].AddError = ERR_NOTSUPPORTED;
1298  }
1299 }
1300 
1301 GSM_Error S60_SetAddCalendar(GSM_StateMachine *s, GSM_CalendarEntry *Entry, int request, int ID_request)
1302 {
1303  int i;
1304  char buffer[1024];
1305  const char *type;
1306 
1307  if (ID_request == ID_SetCalendarNote) {
1308  sprintf(buffer, "%d%s", Entry->Location, NUM_SEPERATOR_STR);
1309  } else {
1310  switch (Entry->Type) {
1311  case GSM_CAL_MEETING:
1312  type = "appointment";
1313  break;
1314  case GSM_CAL_MEMO:
1315  type = "event";
1316  break;
1317  case GSM_CAL_BIRTHDAY:
1318  type = "anniversary";
1319  break;
1320  case GSM_CAL_REMINDER:
1321  type = "reminder";
1322  break;
1323  default:
1324  type = "appointment";
1325  break;
1326  }
1327  sprintf(buffer, "%s%s", type, NUM_SEPERATOR_STR);
1328  }
1329 
1330 
1331  S60_SetCalendarError(s, Entry);
1332 
1333  i = S60_FindCalendarField(s, Entry, CAL_TEXT);
1334  if (i == -1) {
1335  i = S60_FindCalendarField(s, Entry, CAL_DESCRIPTION);
1336  }
1337  if (i != -1) {
1338  EncodeUTF8(buffer + strlen(buffer), Entry->Entries[i].Text);
1339  }
1340  strcat(buffer, NUM_SEPERATOR_STR);
1341 
1342  i = S60_FindCalendarField(s, Entry, CAL_LOCATION);
1343  if (i != -1) {
1344  EncodeUTF8(buffer + strlen(buffer), Entry->Entries[i].Text);
1345  }
1346  strcat(buffer, NUM_SEPERATOR_STR);
1347 
1348  i = S60_FindCalendarField(s, Entry, CAL_START_DATETIME);
1349  if (i != -1) {
1350  GSM_DateTimeToTimestamp(&(Entry->Entries[i].Date), buffer + strlen(buffer));
1351  }
1352  strcat(buffer, NUM_SEPERATOR_STR);
1353 
1354  i = S60_FindCalendarField(s, Entry, CAL_END_DATETIME);
1355  if (i != -1) {
1356  GSM_DateTimeToTimestamp(&(Entry->Entries[i].Date), buffer + strlen(buffer));
1357  }
1358  strcat(buffer, NUM_SEPERATOR_STR);
1359 
1360  i = S60_FindCalendarField(s, Entry, CAL_PRIVATE);
1361  if (i != -1) {
1362  if (Entry->Entries[i].Number) {
1363  strcat(buffer, "private");
1364  } else {
1365  strcat(buffer, "open");
1366  }
1367  }
1368  strcat(buffer, NUM_SEPERATOR_STR);
1369 
1370  i = S60_FindCalendarField(s, Entry, CAL_TONE_ALARM_DATETIME);
1371  if (i == -1) {
1372  i = S60_FindCalendarField(s, Entry, CAL_SILENT_ALARM_DATETIME);
1373  }
1374  if (i != -1) {
1375  GSM_DateTimeToTimestamp(&(Entry->Entries[i].Date), buffer + strlen(buffer));
1376  }
1377  strcat(buffer, NUM_SEPERATOR_STR);
1378 
1379  /* Priority */
1380  strcat(buffer, "2");
1381  strcat(buffer, NUM_SEPERATOR_STR);
1382 
1383  /* TODO: implement repeating */
1384  strcat(buffer, NUM_SEPERATOR_STR); /* Type */
1385  strcat(buffer, NUM_SEPERATOR_STR); /* Days */
1386  strcat(buffer, NUM_SEPERATOR_STR); /* Exceptions */
1387 
1388  i = S60_FindCalendarField(s, Entry, CAL_REPEAT_STARTDATE);
1389  if (i != -1) {
1390  GSM_DateTimeToTimestamp(&(Entry->Entries[i].Date), buffer + strlen(buffer));
1391  }
1392  strcat(buffer, NUM_SEPERATOR_STR);
1393 
1394  i = S60_FindCalendarField(s, Entry, CAL_REPEAT_STOPDATE);
1395  if (i != -1) {
1396  GSM_DateTimeToTimestamp(&(Entry->Entries[i].Date), buffer + strlen(buffer));
1397  }
1398  strcat(buffer, NUM_SEPERATOR_STR);
1399 
1400  i = S60_FindCalendarField(s, Entry, CAL_REPEAT_FREQUENCY);
1401  if (i != -1) {
1402  sprintf(buffer + strlen(buffer), "%d", Entry->Entries[i].Number);
1403  }
1404  strcat(buffer, NUM_SEPERATOR_STR);
1405 
1406  return GSM_WaitFor(s, buffer, strlen(buffer), request, S60_TIMEOUT, ID_request);
1407 }
1408 
1409 GSM_Error S60_SetCalendar(GSM_StateMachine *s, GSM_CalendarEntry *Entry)
1410 {
1411  return S60_SetAddCalendar(s, Entry, NUM_CALENDAR_ENTRY_CHANGE, ID_SetCalendarNote);
1412 }
1413 
1414 GSM_Error S60_AddCalendar(GSM_StateMachine *s, GSM_CalendarEntry *Entry)
1415 {
1416  s->Phone.Data.Cal = Entry;
1417  return S60_SetAddCalendar(s, Entry, NUM_CALENDAR_ENTRY_ADD, ID_AddCalendarNote);
1418 }
1419 
1420 GSM_Error S60_GetNextCalendar(GSM_StateMachine *s, GSM_CalendarEntry *Entry, gboolean Start)
1421 {
1422  GSM_Error error;
1423  GSM_Phone_S60Data *Priv = &s->Phone.Data.Priv.S60;
1424 
1425  if (Start) {
1426  error = S60_GetCalendarLocations(s);
1427  if (error != ERR_NONE) {
1428  return error;
1429  }
1430  Priv->CalendarLocationsPos = 0;
1431  }
1432 
1433  if (Priv->CalendarLocations[Priv->CalendarLocationsPos] == 0) {
1434  return ERR_EMPTY;
1435  }
1436 
1437  Entry->Location = Priv->CalendarLocations[Priv->CalendarLocationsPos++];
1438 
1439  return S60_GetCalendar(s, Entry);
1440 }
1441 
1442 GSM_Error S60_DeleteCalendar(GSM_StateMachine *s, GSM_CalendarEntry *Entry)
1443 {
1444  char buffer[100];
1445  GSM_Error error;
1446 
1447  sprintf(buffer, "%d", Entry->Location);
1448 
1449  error = GSM_WaitFor(s, buffer, strlen(buffer), NUM_CALENDAR_ENTRY_DELETE, S60_TIMEOUT, ID_None);
1450 
1451  return error;
1452 }
1453 
1454 static GSM_Error S60_Reply_GetToDo(GSM_Protocol_Message *msg, GSM_StateMachine *s)
1455 {
1456  GSM_Phone_S60Data *Priv = &s->Phone.Data.Priv.S60;
1457  GSM_Error error;
1458  char *type, *content, *location, *start, *end, *modified, *replication, *alarm_time, *priority, *crossedout, *crossedout_time;
1459  GSM_ToDoEntry *Entry;
1460  int i;
1461 
1462  error = S60_SplitValues(msg, s);
1463  if (error != ERR_NONE) {
1464  return error;
1465  }
1466 
1467  /* Check for required fields */
1468  for (i = 0; i < 18; i++) {
1469  if (Priv->MessageParts[i] == NULL) {
1470  smprintf(s, "Not enough parts in reply!\n");
1471  return ERR_UNKNOWN;
1472  }
1473  }
1474 
1475  Entry = s->Phone.Data.ToDo;
1476 
1477  /* Grab values */
1478  /* No need to parse position */
1479  type = Priv->MessageParts[1];
1480  content = Priv->MessageParts[2];
1481  location = Priv->MessageParts[3];
1482  start = Priv->MessageParts[4];
1483  end = Priv->MessageParts[5];
1484  modified = Priv->MessageParts[6];
1485  replication = Priv->MessageParts[7];
1486  alarm_time = Priv->MessageParts[8];
1487  priority = Priv->MessageParts[9];
1488  /* Repeating does not make sense for todo */
1489  crossedout = Priv->MessageParts[16];
1490  crossedout_time = Priv->MessageParts[17];
1491 
1492  /* Check for correct type */
1493  if (strcmp(type, "todo") == 0) {
1494  Entry->Type = GSM_CAL_MEMO;
1495  } else {
1496  return ERR_EMPTY;
1497  }
1498 
1499  if (strlen(content) > 0) {
1500  Entry->Entries[Entry->EntriesNum].EntryType = TODO_TEXT;
1501  DecodeUTF8(Entry->Entries[Entry->EntriesNum].Text, content, strlen(content));
1502  Entry->EntriesNum++;
1503  }
1504 
1505  if (strlen(location) > 0) {
1506  Entry->Entries[Entry->EntriesNum].EntryType = TODO_LOCATION;
1507  DecodeUTF8(Entry->Entries[Entry->EntriesNum].Text, location, strlen(location));
1508  Entry->EntriesNum++;
1509  }
1510 
1511  if (strlen(start) > 0) {
1513  GSM_DateTimeFromTimestamp(&(Entry->Entries[Entry->EntriesNum].Date), start);
1514  Entry->EntriesNum++;
1515  }
1516 
1517  if (strlen(end) > 0) {
1518  Entry->Entries[Entry->EntriesNum].EntryType = TODO_END_DATETIME;
1519  GSM_DateTimeFromTimestamp(&(Entry->Entries[Entry->EntriesNum].Date), end);
1520  Entry->EntriesNum++;
1521  }
1522 
1523  if (strlen(modified) > 0) {
1525  GSM_DateTimeFromTimestamp(&(Entry->Entries[Entry->EntriesNum].Date), modified);
1526  Entry->EntriesNum++;
1527  }
1528 
1529  if (strlen(replication) > 0) {
1530  Entry->Entries[Entry->EntriesNum].EntryType = TODO_PRIVATE;
1531  if (strcmp(replication, "open") == 0) {
1532  Entry->Entries[Entry->EntriesNum].Number = 0;
1533  } else {
1534  Entry->Entries[Entry->EntriesNum].Number = 1;
1535  }
1536  Entry->EntriesNum++;
1537  }
1538 
1539  if (strlen(alarm_time) > 0) {
1541  GSM_DateTimeFromTimestamp(&(Entry->Entries[Entry->EntriesNum].Date), alarm_time);
1542  Entry->EntriesNum++;
1543  }
1544 
1545  if (strlen(priority) > 0) {
1546  Entry->Priority = atoi(priority);
1547  }
1548 
1549  if (strlen(crossedout) > 0) {
1550  Entry->Entries[Entry->EntriesNum].EntryType = TODO_COMPLETED;
1551  Entry->Entries[Entry->EntriesNum].Number = atoi(crossedout);
1552  Entry->EntriesNum++;
1553  }
1554 
1555  if (strlen(crossedout_time) > 0) {
1557  GSM_DateTimeFromTimestamp(&(Entry->Entries[Entry->EntriesNum].Date), crossedout_time);
1558  Entry->EntriesNum++;
1559  }
1560 
1561  return ERR_NONE;
1562 }
1563 
1564 GSM_Error S60_GetToDo(GSM_StateMachine *s, GSM_ToDoEntry *Entry)
1565 {
1566  char buffer[100];
1567  GSM_Error error;
1568 
1569  Entry->EntriesNum = 0;
1570 
1571  sprintf(buffer, "%d", Entry->Location);
1572 
1573  s->Phone.Data.ToDo = Entry;
1574  error = GSM_WaitFor(s, buffer, strlen(buffer), NUM_CALENDAR_REQUEST_ENTRY, S60_TIMEOUT, ID_GetToDo);
1575  s->Phone.Data.ToDo = NULL;
1576 
1577  return error;
1578 }
1579 
1580 GSM_Error S60_GetNextToDo(GSM_StateMachine *s, GSM_ToDoEntry *Entry, gboolean Start)
1581 {
1582  GSM_Error error;
1583  GSM_Phone_S60Data *Priv = &s->Phone.Data.Priv.S60;
1584 
1585  if (Start) {
1586  error = S60_GetToDoLocations(s);
1587  if (error != ERR_NONE) {
1588  return error;
1589  }
1590  Priv->ToDoLocationsPos = 0;
1591  }
1592 
1593  if (Priv->ToDoLocations[Priv->ToDoLocationsPos] == 0) {
1594  return ERR_EMPTY;
1595  }
1596 
1597  Entry->Location = Priv->ToDoLocations[Priv->ToDoLocationsPos++];
1598 
1599  return S60_GetToDo(s, Entry);
1600 }
1601 
1602 GSM_Error S60_DeleteToDo(GSM_StateMachine *s, GSM_ToDoEntry *Entry)
1603 {
1604  char buffer[100];
1605  GSM_Error error;
1606 
1607  sprintf(buffer, "%d", Entry->Location);
1608 
1609  error = GSM_WaitFor(s, buffer, strlen(buffer), NUM_CALENDAR_ENTRY_DELETE, S60_TIMEOUT, ID_None);
1610 
1611  return error;
1612 }
1613 
1614 static GSM_Error S60_Reply_AddToDo(GSM_Protocol_Message *msg, GSM_StateMachine *s)
1615 {
1616  s->Phone.Data.ToDo->Location = atoi(msg->Buffer);
1617  smprintf(s, "Added todo ID %d\n", s->Phone.Data.ToDo->Location);
1618  return ERR_NONE;
1619 }
1620 
1621 int S60_FindToDoField(GSM_StateMachine *s, GSM_ToDoEntry *Entry, GSM_ToDoType Type)
1622 {
1623  int i;
1624 
1625  for (i = 0; i < Entry->EntriesNum; i++) {
1626  if (Entry->Entries[i].EntryType == Type) {
1627  return i;
1628  }
1629  }
1630  return -1;
1631 }
1632 
1633 GSM_Error S60_SetAddToDo(GSM_StateMachine *s, GSM_ToDoEntry *Entry, int request, int ID_request)
1634 {
1635  int i;
1636  char buffer[1024];
1637 
1638  if (ID_request == ID_SetToDo) {
1639  sprintf(buffer, "%d%s", Entry->Location, NUM_SEPERATOR_STR);
1640  } else {
1641  sprintf(buffer, "%s%s", "todo", NUM_SEPERATOR_STR);
1642  }
1643 
1644  i = S60_FindToDoField(s, Entry, TODO_TEXT);
1645  if (i == -1) {
1646  i = S60_FindToDoField(s, Entry, TODO_DESCRIPTION);
1647  }
1648  if (i != -1) {
1649  EncodeUTF8(buffer + strlen(buffer), Entry->Entries[i].Text);
1650  }
1651  strcat(buffer, NUM_SEPERATOR_STR);
1652 
1653  i = S60_FindToDoField(s, Entry, TODO_LOCATION);
1654  if (i != -1) {
1655  EncodeUTF8(buffer + strlen(buffer), Entry->Entries[i].Text);
1656  }
1657  strcat(buffer, NUM_SEPERATOR_STR);
1658 
1659  i = S60_FindToDoField(s, Entry, TODO_START_DATETIME);
1660  if (i != -1) {
1661  GSM_DateTimeToTimestamp(&(Entry->Entries[i].Date), buffer + strlen(buffer));
1662  }
1663  strcat(buffer, NUM_SEPERATOR_STR);
1664 
1665  i = S60_FindToDoField(s, Entry, TODO_END_DATETIME);
1666  if (i != -1) {
1667  GSM_DateTimeToTimestamp(&(Entry->Entries[i].Date), buffer + strlen(buffer));
1668  }
1669  strcat(buffer, NUM_SEPERATOR_STR);
1670 
1671  i = S60_FindToDoField(s, Entry, TODO_PRIVATE);
1672  if (i != -1) {
1673  if (Entry->Entries[i].Number) {
1674  strcat(buffer, "private");
1675  } else {
1676  strcat(buffer, "open");
1677  }
1678  }
1679  strcat(buffer, NUM_SEPERATOR_STR);
1680 
1681  i = S60_FindToDoField(s, Entry, TODO_ALARM_DATETIME);
1682  if (i == -1) {
1683  i = S60_FindToDoField(s, Entry, TODO_SILENT_ALARM_DATETIME);
1684  }
1685  if (i != -1) {
1686  GSM_DateTimeToTimestamp(&(Entry->Entries[i].Date), buffer + strlen(buffer));
1687  }
1688  strcat(buffer, NUM_SEPERATOR_STR);
1689 
1690  /* Priority */
1691  sprintf(buffer + strlen(buffer), "%d", Entry->Priority);
1692  strcat(buffer, NUM_SEPERATOR_STR);
1693 
1694  strcat(buffer, NUM_SEPERATOR_STR); /* Type */
1695  strcat(buffer, NUM_SEPERATOR_STR); /* Days */
1696  strcat(buffer, NUM_SEPERATOR_STR); /* Exceptions */
1697  strcat(buffer, NUM_SEPERATOR_STR); /* Start */
1698  strcat(buffer, NUM_SEPERATOR_STR); /* End */
1699  strcat(buffer, NUM_SEPERATOR_STR); /* Frequency */
1700 
1701  return GSM_WaitFor(s, buffer, strlen(buffer), request, S60_TIMEOUT, ID_request);
1702 }
1703 
1704 GSM_Error S60_SetToDo(GSM_StateMachine *s, GSM_ToDoEntry *Entry)
1705 {
1706  return S60_SetAddToDo(s, Entry, NUM_CALENDAR_ENTRY_CHANGE, ID_SetToDo);
1707 }
1708 
1709 GSM_Error S60_AddToDo(GSM_StateMachine *s, GSM_ToDoEntry *Entry)
1710 {
1711  s->Phone.Data.ToDo = Entry;
1712  return S60_SetAddToDo(s, Entry, NUM_CALENDAR_ENTRY_ADD, ID_AddToDo);
1713 }
1714 
1715 GSM_Error S60_GetScreenshot(GSM_StateMachine *s, GSM_BinaryPicture *picture)
1716 {
1717  GSM_Error error;
1718 
1719  s->Phone.Data.Picture = picture;
1720  error = GSM_WaitFor(s, NULL, 0, NUM_SCREENSHOT, S60_TIMEOUT, ID_Screenshot);
1721  s->Phone.Data.Picture = NULL;
1722 
1723  return error;
1724 }
1725 
1726 GSM_Error S60_Reply_Screenshot(GSM_Protocol_Message *msg, GSM_StateMachine *s)
1727 {
1729  s->Phone.Data.Picture->Buffer = (unsigned char *)malloc(msg->Length);
1730  if (s->Phone.Data.Picture->Buffer == NULL) {
1731  return ERR_MOREMEMORY;
1732  }
1734  return ERR_NONE;
1735 }
1736 
1737 GSM_Error S60_GetSMSStatus(GSM_StateMachine *s, GSM_SMSMemoryStatus *status)
1738 {
1739  GSM_Error error;
1740 
1741  status->SIMUnRead = 0;
1742  status->SIMUsed = 0;
1743  status->SIMSize = 0;
1744  status->TemplatesUsed = 0;
1745  status->PhoneUnRead = 0;
1746  status->PhoneUsed = 0;
1747  status->PhoneSize = 0;
1748 
1749  s->Phone.Data.SMSStatus = status;
1751  s->Phone.Data.SMSStatus = NULL;
1752 
1753  return error;
1754 }
1755 
1756 GSM_Error S60_Reply_GetSMSStatus(GSM_Protocol_Message *msg, GSM_StateMachine *s)
1757 {
1758  GSM_Error error;
1759  GSM_Phone_S60Data *Priv = &s->Phone.Data.Priv.S60;
1760 
1761  error = S60_SplitValues(msg, s);
1762  if (error != ERR_NONE) {
1763  return error;
1764  }
1765 
1766  if (Priv->MessageParts[0] == NULL || Priv->MessageParts[1] == NULL) {
1767  return ERR_UNKNOWN;
1768  }
1769  s->Phone.Data.SMSStatus->PhoneUsed = atoi(Priv->MessageParts[0]);
1770  s->Phone.Data.SMSStatus->PhoneUnRead = atoi(Priv->MessageParts[1]);
1772 
1773  return ERR_NONE;
1774 }
1775 
1776 GSM_Error S60_GetSMSFolders(GSM_StateMachine *s UNUSED, GSM_SMSFolders *folders)
1777 {
1778  folders->Number=2;
1779  EncodeUnicode(folders->Folder[0].Name,_("Inbox"),strlen(_("Inbox")));
1780  EncodeUnicode(folders->Folder[1].Name,_("Outbox"),strlen(_("Outbox")));
1781  folders->Folder[0].InboxFolder = TRUE;
1782  folders->Folder[1].InboxFolder = FALSE;
1783  folders->Folder[0].OutboxFolder = FALSE;
1784  folders->Folder[1].OutboxFolder = TRUE;
1785  folders->Folder[0].Memory = MEM_ME;
1786  folders->Folder[1].Memory = MEM_ME;
1787  return ERR_NONE;
1788 }
1789 
1790 GSM_Error S60_GetSMS(GSM_StateMachine *s, GSM_MultiSMSMessage *sms)
1791 {
1792 
1793  char buffer[100];
1794 
1795  sprintf(buffer, "%d", sms->SMS[0].Location);
1796 
1797  sms->Number = 1;
1798  GSM_SetDefaultReceivedSMSData(&(sms->SMS[0]));
1799  s->Phone.Data.SaveSMSMessage = &(sms->SMS[0]);
1800 
1801 
1802  return GSM_WaitFor(s, buffer, strlen(buffer), NUM_MESSAGE_REQUEST_ONE, S60_TIMEOUT, ID_GetSMSMessage);
1803 }
1804 
1805 GSM_Error S60_DeleteSMS(GSM_StateMachine *s, GSM_SMSMessage *sms)
1806 {
1807 
1808  char buffer[100];
1809 
1810  sprintf(buffer, "%d", sms->Location);
1811 
1812  return GSM_WaitFor(s, buffer, strlen(buffer), NUM_MESSAGE_DELETE, S60_TIMEOUT, ID_None);
1813 }
1814 
1815 GSM_Error S60_Reply_GetSMS(GSM_Protocol_Message *msg, GSM_StateMachine *s)
1816 {
1817  GSM_Error error;
1818  GSM_Phone_S60Data *Priv = &s->Phone.Data.Priv.S60;
1819  int i;
1820 
1821  error = S60_SplitValues(msg, s);
1822  if (error != ERR_NONE) {
1823  return error;
1824  }
1825 
1826  if (Priv->MessageParts[0] == NULL || Priv->MessageParts[0][0] == 0) {
1827  return ERR_EMPTY;
1828  }
1829 
1830  /* Check for required fields */
1831  for (i = 0; i < 6; i++) {
1832  if (Priv->MessageParts[i] == NULL) {
1833  smprintf(s, "Not enough parts in reply!\n");
1834  return ERR_UNKNOWN;
1835  }
1836  }
1837 
1838  /* Folder */
1839  if (strcmp(Priv->MessageParts[0], "inbox") == 0) {
1840  s->Phone.Data.SaveSMSMessage->Folder = 1;
1843  } else {
1844  s->Phone.Data.SaveSMSMessage->Folder = 2;
1847  }
1848 
1849  /* ID */
1850 
1851  /* Time */
1853 
1854  /* Address */
1855  DecodeUTF8(s->Phone.Data.SaveSMSMessage->Number, Priv->MessageParts[3], strlen(Priv->MessageParts[3]));
1856 
1857  /* Content */
1858  DecodeUTF8(s->Phone.Data.SaveSMSMessage->Text, Priv->MessageParts[4], strlen(Priv->MessageParts[4]));
1861 
1862  /* Unread */
1863  if (strcmp(Priv->MessageParts[5], "1") == 0) {
1865  } else if (s->Phone.Data.SaveSMSMessage->InboxFolder) {
1867  } else {
1869  }
1870  return ERR_NONE;
1871 }
1872 
1873 GSM_Error S60_Reply_SMSLocation(GSM_Protocol_Message *msg, GSM_StateMachine *s)
1874 {
1875  GSM_Phone_S60Data *Priv = &s->Phone.Data.Priv.S60;
1876  GSM_Error error;
1877 
1878  error = S60_SplitValues(msg, s);
1879  if (error != ERR_NONE) {
1880  return error;
1881 
1882  }
1883 
1884  if (Priv->MessageParts[0] == NULL) {
1885  return ERR_UNKNOWN;
1886  }
1887 
1888  error = S60_StoreLocation(s, &Priv->SMSLocations, &Priv->SMSLocationsSize, &Priv->SMSLocationsPos, atoi(Priv->MessageParts[0]));
1889  if (error != ERR_NONE) {
1890  return error;
1891 
1892  }
1893 
1894  return ERR_NEEDANOTHERANSWER;
1895 }
1896 
1897 
1898 static GSM_Error S60_GetSMSLocations(GSM_StateMachine *s)
1899 {
1900  GSM_Phone_S60Data *Priv = &s->Phone.Data.Priv.S60;
1901  Priv->SMSLocationsPos = 0;
1903 }
1904 
1905 GSM_Error S60_GetNextSMS(GSM_StateMachine *s, GSM_MultiSMSMessage *sms, gboolean Start)
1906 {
1907  GSM_Error error;
1908  GSM_Phone_S60Data *Priv = &s->Phone.Data.Priv.S60;
1909 
1910  if (Start) {
1911  error = S60_GetSMSLocations(s);
1912  if (error != ERR_NONE) {
1913  return error;
1914  }
1915  Priv->SMSLocationsPos = 0;
1916  }
1917 
1918  if (Priv->SMSLocations[Priv->SMSLocationsPos] == 0) {
1919  return ERR_EMPTY;
1920  }
1921 
1922  sms->SMS[0].Location = Priv->SMSLocations[Priv->SMSLocationsPos++];
1923 
1924  return S60_GetSMS(s, sms);
1925 }
1926 
1927 GSM_Error S60_SendSMS(GSM_StateMachine *s, GSM_SMSMessage *sms)
1928 {
1929  char buffer[((GSM_MAX_SMS_LENGTH + 1) * 2) + ((GSM_MAX_SMS_NAME_LENGTH + 1) * 2) + ((GSM_MAX_NUMBER_LENGTH + 1) * 2)];
1930  char textbuffer[((GSM_MAX_SMS_LENGTH + 1) * 2)];
1931 
1932  if (sms->UDH.Type != UDH_NoUDH) {
1933  return ERR_NOTSUPPORTED;
1934  }
1935 
1936  EncodeUTF8(buffer, sms->Name);
1937  strcat(buffer, NUM_SEPERATOR_STR);
1938  EncodeUTF8(buffer + strlen(buffer), sms->Number);
1939  strcat(buffer, NUM_SEPERATOR_STR);
1940  switch (sms->Coding) {
1943  strcat(buffer, "UCS2");
1944  break;
1947  strcat(buffer, "7bit");
1948  break;
1949  case SMS_Coding_8bit:
1950  strcat(buffer, "8bit");
1951  break;
1952  }
1953  strcat(buffer, NUM_SEPERATOR_STR);
1954  EncodeUTF8(textbuffer, sms->Text);
1955  EncodeSpecialChars(buffer + strlen(buffer), textbuffer);
1956  strcat(buffer, NUM_SEPERATOR_STR);
1957 
1958  return GSM_WaitFor(s, buffer, strlen(buffer), NUM_MESSAGE_SEND_REQUEST, S60_TIMEOUT, ID_None);
1959 }
1960 
1961 GSM_Error S60_GetSMSC(GSM_StateMachine *s, GSM_SMSC *smsc)
1962 {
1963  if (smsc->Location != 1) {
1964  return ERR_EMPTY;
1965  }
1966  smsc->Name[0] = 0;
1967  smsc->Name[1] = 0;
1968  smsc->Number[0] = 0;
1969  smsc->Number[1] = 0;
1972  smsc->DefaultNumber[0] = 0;
1973  smsc->DefaultNumber[1] = 0;
1974  smsc->Format = SMS_FORMAT_Text;
1975  return ERR_NONE;
1976 }
1977 
1978 GSM_Error S60_DialVoice(GSM_StateMachine *s, char *Number, GSM_CallShowNumber ShowNumber)
1979 {
1980  return GSM_WaitFor(s, Number, strlen(Number), NUM_DIAL, S60_TIMEOUT, ID_None);
1981 }
1982 
1983 GSM_Error S60_CancelCall(GSM_StateMachine *s, int ID, gboolean all)
1984 {
1985  return GSM_WaitFor(s, "", 0, NUM_HANGUP, S60_TIMEOUT, ID_None);
1986 }
1987 
1988 GSM_Reply_Function S60ReplyFunctions[] = {
1989 
1990  {S60_Reply_Connect, "", 0x00, NUM_CONNECTED, ID_Initialise },
1991  {S60_Reply_Generic, "", 0x00, NUM_HELLO_REPLY, ID_EnableEcho },
1992 
1993  {S60_Reply_Generic, "", 0x00, NUM_SYSINFO_REPLY_START, ID_GetModel },
1994  {S60_Reply_GetInfo, "", 0x00, NUM_SYSINFO_REPLY_LINE, ID_GetModel },
1995  {S60_Reply_Generic, "", 0x00, NUM_SYSINFO_REPLY_END, ID_GetModel },
1996 
1997  {S60_Reply_Generic, "", 0x00, NUM_CONTACTS_REPLY_HASH_SINGLE_START, ID_GetMemoryStatus },
1998  {S60_Reply_ContactHash, "", 0x00, NUM_CONTACTS_REPLY_HASH_SINGLE_LINE, ID_GetMemoryStatus },
1999  {S60_Reply_Generic, "", 0x00, NUM_CONTACTS_REPLY_HASH_SINGLE_END, ID_GetMemoryStatus },
2000 
2001  {S60_Reply_SMSLocation, "", 0x00, NUM_MESSAGE_REPLY_LIST, ID_GetSMSStatus },
2002  {S60_Reply_Generic, "", 0x00, NUM_MESSAGE_REPLY_END, ID_GetSMSStatus },
2003 
2004  {S60_Reply_GetMemoryStatus, "", 0x00, NUM_CONTACTS_REPLY_COUNT, ID_GetMemoryStatus },
2005 
2006  {S60_Reply_Generic, "", 0x00, NUM_CALENDAR_REPLY_ENTRIES_START, ID_GetCalendarNotesInfo },
2007  {S60_Reply_CalendarCount, "", 0x00, NUM_CALENDAR_REPLY_ENTRY, ID_GetCalendarNotesInfo },
2008  {S60_Reply_Generic, "", 0x00, NUM_CALENDAR_REPLY_ENTRIES_END, ID_GetCalendarNotesInfo },
2009 
2010  {S60_Reply_Generic, "", 0x00, NUM_CALENDAR_REPLY_ENTRIES_START, ID_GetToDoInfo },
2011  {S60_Reply_ToDoCount, "", 0x00, NUM_CALENDAR_REPLY_ENTRY, ID_GetToDoInfo },
2012  {S60_Reply_Generic, "", 0x00, NUM_CALENDAR_REPLY_ENTRIES_END, ID_GetToDoInfo },
2013 
2014  {S60_Reply_Generic, "", 0x00, NUM_CONTACTS_REPLY_CONTACT_START, ID_GetMemory },
2015  {S60_Reply_GetMemory, "", 0x00, NUM_CONTACTS_REPLY_CONTACT_LINE, ID_GetMemory },
2016  {S60_Reply_Generic, "", 0x00, NUM_CONTACTS_REPLY_CONTACT_END, ID_GetMemory },
2017  {S60_Reply_Generic, "", 0x00, NUM_CONTACTS_REPLY_CONTACT_NOT_FOUND, ID_GetMemory },
2018 
2019  {S60_Reply_GetCalendar, "", 0x00, NUM_CALENDAR_REPLY_ENTRY, ID_GetCalendarNote },
2020  {S60_Reply_Generic, "", 0x00, NUM_CALENDAR_REPLY_ENTRY_NOT_FOUND, ID_GetCalendarNote },
2021 
2022  {S60_Reply_GetToDo, "", 0x00, NUM_CALENDAR_REPLY_ENTRY, ID_GetToDo },
2023  {S60_Reply_Generic, "", 0x00, NUM_CALENDAR_REPLY_ENTRY_NOT_FOUND, ID_GetToDo },
2024 
2025  {S60_Reply_AddMemory, "", 0x00, NUM_CONTACTS_ADD_REPLY_ID, ID_SetMemory },
2026 
2027  {S60_Reply_GetNetworkInfo, "", 0x00, NUM_LOCATION_REPLY, ID_GetNetworkInfo },
2028  {S60_Reply_Generic, "", 0x00, NUM_LOCATION_REPLY_NA, ID_GetNetworkInfo },
2029 
2030  {S60_Reply_Generic, "", 0x00, NUM_QUIT, ID_Terminate },
2031 
2032  {S60_Reply_Screenshot, "", 0x00, NUM_SCREENSHOT_REPLY, ID_Screenshot },
2033 
2034  {S60_Reply_GetSMSStatus, "", 0x00,NUM_MESSAGE_REPLY_COUNT, ID_GetSMSStatus },
2035  {S60_Reply_GetSMS, "", 0x00, NUM_MESSAGE_REPLY_ONE, ID_GetSMSMessage },
2036 
2037  {S60_Reply_GetCalendarStatus, "", 0x00, NUM_CALENDAR_REPLY_COUNT, ID_GetCalendarNotesInfo },
2038 
2039  {S60_Reply_SendSMS, "", 0x00, NUM_MESSAGE_SEND_REPLY_RETRY, ID_IncomingFrame },
2040  {S60_Reply_SendSMS, "", 0x00, NUM_MESSAGE_SEND_REPLY_STATUS, ID_IncomingFrame },
2041  {S60_Reply_SendSMS, "", 0x00, NUM_MESSAGE_SEND_REPLY_OK, ID_IncomingFrame },
2042  {S60_Reply_SendSMS, "", 0x00, NUM_MESSAGE_SEND_REPLY_FAILURE, ID_IncomingFrame },
2043 
2044  {S60_Reply_Generic, "", 0x00, NUM_CALENDAR_ENTRY_CHANGE_REPLY_TIME, ID_SetCalendarNote },
2045  {S60_Reply_AddCalendar, "", 0x00, NUM_CALENDAR_ENTRY_ADD_REPLY, ID_AddCalendarNote },
2046 
2047  {S60_Reply_Generic, "", 0x00, NUM_CALENDAR_ENTRY_CHANGE_REPLY_TIME, ID_SetToDo },
2048  {S60_Reply_AddToDo, "", 0x00, NUM_CALENDAR_ENTRY_ADD_REPLY, ID_AddToDo },
2049 
2050  {NULL, "", 0x00, 0x00, ID_None }
2051 };
2052 
2053 GSM_Phone_Functions S60Phone = {
2054  "s60",
2055  S60ReplyFunctions,
2056  S60_Install,
2057  S60_Initialise,
2058  S60_Terminate,
2060  NOTIMPLEMENTED, /* ShowStartInfo */
2061  S60_GetInfo, /* GetManufacturer */
2062  S60_GetInfo, /* GetModel */
2063  S60_GetInfo, /* GetFirmware */
2064  S60_GetInfo, /* GetIMEI */
2065  NOTIMPLEMENTED, /* GetOriginalIMEI */
2066  NOTIMPLEMENTED, /* GetManufactureMonth */
2067  NOTIMPLEMENTED, /* GetProductCode */
2068  NOTIMPLEMENTED, /* GetHardware */
2069  NOTIMPLEMENTED, /* GetPPM */
2070  NOTIMPLEMENTED, /* GetSIMIMSI */
2071  NOTIMPLEMENTED, /* GetDateTime */
2072  NOTIMPLEMENTED, /* SetDateTime */
2073  NOTIMPLEMENTED, /* GetAlarm */
2074  NOTIMPLEMENTED, /* SetAlarm */
2075  NOTSUPPORTED, /* GetLocale */
2076  NOTSUPPORTED, /* SetLocale */
2077  NOTIMPLEMENTED, /* PressKey */
2078  NOTIMPLEMENTED, /* Reset */
2079  NOTIMPLEMENTED, /* ResetPhoneSettings */
2080  NOTIMPLEMENTED, /* EnterSecurityCode */
2081  NOTIMPLEMENTED, /* GetSecurityStatus */
2082  NOTIMPLEMENTED, /* GetDisplayStatus */
2083  NOTIMPLEMENTED, /* SetAutoNetworkLogin */
2084  S60_GetBatteryCharge,
2085  S60_GetSignalQuality,
2086  S60_GetNetworkInfo,
2087  NOTIMPLEMENTED, /* GetCategory */
2088  NOTSUPPORTED, /* AddCategory */
2089  NOTIMPLEMENTED, /* GetCategoryStatus */
2090  S60_GetMemoryStatus,
2091  S60_GetMemory,
2092  S60_GetNextMemory,
2093  S60_SetMemory,
2094  S60_AddMemory,
2095  S60_DeleteMemory,
2096  NOTIMPLEMENTED, /* DeleteAllMemory */
2097  NOTIMPLEMENTED, /* GetSpeedDial */
2098  NOTIMPLEMENTED, /* SetSpeedDial */
2099  S60_GetSMSC,
2100  NOTIMPLEMENTED, /* SetSMSC */
2101  S60_GetSMSStatus,
2102  S60_GetSMS,
2103  S60_GetNextSMS,
2104  NOTIMPLEMENTED, /* SetSMS */
2105  NOTIMPLEMENTED, /* AddSMS */
2106  S60_DeleteSMS,
2107  S60_SendSMS,
2108  NOTSUPPORTED, /* SendSavedSMS */
2109  NOTSUPPORTED, /* SetFastSMSSending */
2110  NOTIMPLEMENTED, /* SetIncomingSMS */
2111  NOTIMPLEMENTED, /* SetIncomingCB */
2112  S60_GetSMSFolders,
2113  NOTIMPLEMENTED, /* AddSMSFolder */
2114  NOTIMPLEMENTED, /* DeleteSMSFolder */
2115  S60_DialVoice,
2116  NOTIMPLEMENTED, /* DialService */
2117  NOTIMPLEMENTED, /* AnswerCall */
2118  S60_CancelCall,
2119  NOTIMPLEMENTED, /* HoldCall */
2120  NOTIMPLEMENTED, /* UnholdCall */
2121  NOTIMPLEMENTED, /* ConferenceCall */
2122  NOTIMPLEMENTED, /* SplitCall */
2123  NOTIMPLEMENTED, /* TransferCall */
2124  NOTIMPLEMENTED, /* SwitchCall */
2125  NOTIMPLEMENTED, /* GetCallDivert */
2126  NOTIMPLEMENTED, /* SetCallDivert */
2127  NOTIMPLEMENTED, /* CancelAllDiverts */
2128  NOTIMPLEMENTED, /* SetIncomingCall */
2129  NOTIMPLEMENTED, /* SetIncomingUSSD */
2130  NOTIMPLEMENTED, /* SendDTMF */
2131  NOTIMPLEMENTED, /* GetRingtone */
2132  NOTIMPLEMENTED, /* SetRingtone */
2133  NOTIMPLEMENTED, /* GetRingtonesInfo */
2134  NOTIMPLEMENTED, /* DeleteUserRingtones */
2135  NOTIMPLEMENTED, /* PlayTone */
2136  NOTIMPLEMENTED, /* GetWAPBookmark */
2137  NOTIMPLEMENTED, /* SetWAPBookmark */
2138  NOTIMPLEMENTED, /* DeleteWAPBookmark */
2139  NOTIMPLEMENTED, /* GetWAPSettings */
2140  NOTIMPLEMENTED, /* SetWAPSettings */
2141  NOTSUPPORTED, /* GetSyncMLSettings */
2142  NOTSUPPORTED, /* SetSyncMLSettings */
2143  NOTSUPPORTED, /* GetChatSettings */
2144  NOTSUPPORTED, /* SetChatSettings */
2145  NOTSUPPORTED, /* GetMMSSettings */
2146  NOTSUPPORTED, /* SetMMSSettings */
2147  NOTSUPPORTED, /* GetMMSFolders */
2148  NOTSUPPORTED, /* GetNextMMSFileInfo */
2149  NOTIMPLEMENTED, /* GetBitmap */
2150  NOTIMPLEMENTED, /* SetBitmap */
2151  S60_GetToDoStatus,
2152  S60_GetToDo,
2153  S60_GetNextToDo,
2154  S60_SetToDo,
2155  S60_AddToDo,
2156  NOTIMPLEMENTED, /* DeleteTodo */
2157  NOTIMPLEMENTED, /* DeleteAllTodo */
2158  S60_GetCalendarStatus,
2159  S60_GetCalendar,
2160  S60_GetNextCalendar,
2161  S60_SetCalendar,
2162  S60_AddCalendar,
2163  NOTIMPLEMENTED, /* DeleteCalendar */
2164  NOTIMPLEMENTED, /* DeleteAllCalendar */
2165  NOTSUPPORTED, /* GetCalendarSettings */
2166  NOTSUPPORTED, /* SetCalendarSettings */
2167  NOTIMPLEMENTED, /* GetNoteStatus */
2168  NOTIMPLEMENTED, /* GetNote */
2169  NOTIMPLEMENTED, /* GetNextNote */
2170  NOTIMPLEMENTED, /* SetNote */
2171  NOTIMPLEMENTED, /* AddNote */
2172  NOTIMPLEMENTED, /* DeleteNote */
2173  NOTIMPLEMENTED, /* DeleteAllNotes */
2174  NOTIMPLEMENTED, /* GetProfile */
2175  NOTIMPLEMENTED, /* SetProfile */
2176  NOTIMPLEMENTED, /* GetFMStation */
2177  NOTIMPLEMENTED, /* SetFMStation */
2178  NOTIMPLEMENTED, /* ClearFMStations */
2179  NOTIMPLEMENTED, /* GetNextFileFolder */
2180  NOTIMPLEMENTED, /* GetFolderListing */
2181  NOTSUPPORTED, /* GetNextRootFolder */
2182  NOTSUPPORTED, /* SetFileAttributes */
2183  NOTIMPLEMENTED, /* GetFilePart */
2184  NOTIMPLEMENTED, /* AddFilePart */
2185  NOTIMPLEMENTED, /* SendFilePart */
2186  NOTIMPLEMENTED, /* GetFileSystemStatus */
2187  NOTIMPLEMENTED, /* DeleteFile */
2188  NOTIMPLEMENTED, /* AddFolder */
2189  NOTIMPLEMENTED, /* DeleteFile */ /* DeleteFolder */
2190  NOTSUPPORTED, /* GetGPRSAccessPoint */
2191  NOTSUPPORTED, /* SetGPRSAccessPoint */
2192  S60_GetScreenshot,
2193  NOTSUPPORTED, /* SetPower */
2194  NOTSUPPORTED, /* PostConnect */
2195  NONEFUNCTION /* PreAPICall */
2196 };
2197 #endif
2198 
2199 
2200 /* How should editor hadle tabs in this file? Add editor commands here.
2201  * vim: noexpandtab sw=8 ts=8 sts=8:
2202  */
GSM_SMSMessageType PDU
char * MessageParts[50]
Definition: s60phone.h:41
#define NUM_CALENDAR_ENTRY_ADD
Definition: s60-ids.h:85
#define NUM_SEPERATOR_STR
Definition: s60-ids.h:100
GSM_DateTime DateTime
GSM_Config * CurrentConfig
Definition: gsmstate.h:1415
#define NUM_CALENDAR_REPLY_ENTRIES_END
Definition: s60-ids.h:83
#define NUM_CALENDAR_REPLY_ENTRIES_START
Definition: s60-ids.h:81
void GSM_SetDefaultReceivedSMSData(GSM_SMSMessage *SMS)
Definition: gsmsms.c:1092
gboolean UseGlobalDebugFile
size_t ContactLocationsSize
Definition: s60phone.h:46
unsigned char Text[(GSM_MAX_SMS_LENGTH+1) *2]
#define NUM_MESSAGE_SEND_REPLY_STATUS
Definition: s60-ids.h:47
int * ToDoLocations
Definition: s60phone.h:51
#define NUM_SCREENSHOT_REPLY
Definition: s60-ids.h:94
#define NUM_CONTACTS_CHANGE_REMOVEFIELD
Definition: s60-ids.h:31
GSM_Error GSM_InitConnection(GSM_StateMachine *s, int ReplyNum)
Definition: gsmstate.c:914
unsigned char Number[(GSM_MAX_NUMBER_LENGTH+1) *2]
#define NUM_CALENDAR_ENTRY_CHANGE
Definition: s60-ids.h:88
#define NUM_MESSAGE_SEND_REPLY_OK
Definition: s60-ids.h:46
GSM_BinaryPicture * Picture
Definition: gsmstate.h:593
#define NUM_CONTACTS_ADD
Definition: s60-ids.h:27
GSM_StateMachine * GSM_AllocStateMachine(void)
Definition: gsmstate.c:1677
#define NUM_MESSAGE_REPLY_END
Definition: s60-ids.h:56
#define NUM_CALENDAR_REPLY_COUNT
Definition: s60-ids.h:71
#define NUM_CALENDAR_ENTRY_ADD_REPLY
Definition: s60-ids.h:86
GSM_ToDo_Priority Priority
#define NUM_MESSAGE_REPLY_ONE
Definition: s60-ids.h:68
void GSM_SetConfigNum(GSM_StateMachine *s, int sections)
Definition: gsmstate.c:1317
GSM_SMS_State State
GSM_MemoryType MemoryType
Definition: gammu-memory.h:415
#define GSM_PHONEBOOK_TEXT_LENGTH
Definition: gammu-limits.h:91
unsigned int Number
#define NUM_CONTACTS_CHANGE_ADDFIELD
Definition: s60-ids.h:30
#define NUM_MESSAGE_REQUEST_LIST
Definition: s60-ids.h:61
size_t ToDoLocationsPos
Definition: s60phone.h:53
#define NUM_CALENDAR_REQUEST_ENTRIES_ALL
Definition: s60-ids.h:76
GSM_CalendarNoteType Type
size_t CalendarLocationsPos
Definition: s60phone.h:50
#define NOTSUPPORTED
Definition: gsmcomon.h:14
size_t ToDoLocationsSize
Definition: s60phone.h:52
GSM_MemoryEntry * Memory
Definition: gsmstate.h:497
unsigned char NetworkName[15 *2]
Definition: gammu-info.h:135
#define NUM_MESSAGE_REQUEST_COUNT
Definition: s60-ids.h:64
#define GSM_PHONEBOOK_ENTRIES
Definition: gammu-limits.h:98
#define NUM_HELLO_REPLY
Definition: s60-ids.h:8
GSM_SMSMemoryStatus * SMSStatus
Definition: gsmstate.h:517
#define GSM_MAX_NUMBER_LENGTH
Definition: gammu-limits.h:77
GSM_ToDoEntry * ToDo
Definition: gsmstate.h:585
SendSMSStatusCallback SendSMSStatus
Definition: gsmstate.h:1385
GSM_Error GSM_DispatchMessage(GSM_StateMachine *s)
Definition: gsmstate.c:1131
#define NONEFUNCTION
Definition: gsmcomon.h:12
#define NUM_CALENDAR_REPLY_ENTRY
Definition: s60-ids.h:82
GSM_Error
Definition: gammu-error.h:23
#define NUM_MESSAGE_REQUEST_ONE
Definition: s60-ids.h:67
GSM_BinaryPicture_Types Type
Definition: gammu-bitmap.h:44
#define NUM_CONTACTS_REPLY_HASH_SINGLE_END
Definition: s60-ids.h:20
const char * model
Definition: gammu-info.h:764
GSM_CallShowNumber
Definition: gammu-call.h:192
GSM_NetworkInfo * NetworkInfo
Definition: gsmstate.h:541
unsigned char * Buffer
Definition: gammu-bitmap.h:45
#define NUM_CONTACTS_REPLY_HASH_SINGLE_START
Definition: s60-ids.h:18
GSM_OneSMSFolder Folder[GSM_MAX_SMS_FOLDERS]
char LAC[10]
Definition: gammu-info.h:131
void * SendSMSStatusUserData
Definition: gsmstate.h:1390
size_t UnicodeLength(const unsigned char *str)
Definition: coding.c:186
#define NUM_CONTACTS_REPLY_CONTACT_LINE
Definition: s60-ids.h:23
GSM_UDHHeader UDH
char PacketCID[10]
Definition: gammu-info.h:143
GSM_ToDoStatus * ToDoStatus
Definition: gsmstate.h:557
GSM_ToDoType
#define NUM_CALENDAR_ENTRY_DELETE
Definition: s60-ids.h:87
GSM_Error GSM_SetDebugFileDescriptor(FILE *fd, gboolean closable, GSM_Debug_Info *privdi)
Definition: debug.c:127
GSM_CalendarStatus * CalStatus
Definition: gsmstate.h:553
char IMEI[GSM_MAX_IMEI_LENGTH+1]
Definition: gsmstate.h:437
unsigned char * Buffer
Definition: gammu-file.h:94
char Version[GSM_MAX_VERSION_LENGTH+1]
Definition: gsmstate.h:454
GSM_Coding_Type Coding
char Manufacturer[GSM_MAX_MANUFACTURER_LENGTH+1]
Definition: gsmstate.h:441
GSM_SMSFormat Format
GSM_PhoneModel * ModelInfo
Definition: gsmstate.h:449
char NetworkCode[10]
Definition: gammu-info.h:122
#define NUM_CONTACTS_REPLY_CONTACT_END
Definition: s60-ids.h:24
char CID[10]
Definition: gammu-info.h:118
#define GSM_MAX_SMS_LENGTH
Definition: gammu-limits.h:176
#define NUM_CALENDAR_REQUEST_ENTRY
Definition: s60-ids.h:75
GSM_EntryType EntryType
Definition: gammu-memory.h:372
GSM_SignalQuality * SignalQuality
Definition: gsmstate.h:533
char DebugLevel[50]
size_t Used
Definition: gammu-file.h:70
GSM_ToDoType EntryType
#define NUM_SYSINFO_REPLY_LINE
Definition: s60-ids.h:35
gboolean ReadVCALDateTime(const char *Buffer, GSM_DateTime *dt)
Definition: gsmmisc.c:254
#define GSM_MAX_SMS_NAME_LENGTH
Definition: gammu-limits.h:138
void GSM_ClearBatteryCharge(GSM_BatteryCharge *bat)
Definition: gsmmisc.c:784
#define NUM_SEPERATOR
Definition: s60-ids.h:99
unsigned char DefaultNumber[(GSM_MAX_NUMBER_LENGTH+1) *2]
unsigned char Text[(GSM_PHONEBOOK_TEXT_LENGTH+1) *2]
Definition: gammu-memory.h:399
#define NUM_SYSINFO_REPLY_START
Definition: s60-ids.h:34
int gboolean
Definition: gammu-types.h:23
GSM_ValidityPeriodFormat Format
#define NUM_CONTACTS_REPLY_COUNT
Definition: s60-ids.h:21
GSM_CalendarNoteType Type
GSM_PhoneModel * GetModelData(GSM_StateMachine *s, const char *model, const char *number, const char *irdamodel)
Definition: gsmphones.c:1002
void EncodeUnicode(unsigned char *dest, const char *src, size_t len)
Definition: coding.c:301
unsigned char Name[(GSM_MAX_SMS_NAME_LENGTH+1) *2]
gboolean InboxFolder
GSM_Phone Phone
Definition: gsmstate.h:1431
#define FALSE
Definition: gammu-types.h:25
GSM_SMSValidity Validity
struct GSM_Phone_Data::@2 Priv
#define NUM_MESSAGE_DELETE
Definition: s60-ids.h:51
GSM_SubToDoEntry Entries[GSM_TODO_ENTRIES]
size_t ContactLocationsPos
Definition: s60phone.h:47
#define NUM_CONTACTS_REQUEST_COUNT
Definition: s60-ids.h:14
int * SMSLocations
Definition: s60phone.h:42
char * EncodeSpecialChars(char *dest, const char *buffer)
Definition: coding.c:94
GSM_Error GSM_WaitFor(GSM_StateMachine *s, unsigned const char *buffer, size_t length, int type, int timeout, GSM_Phone_RequestID request)
Definition: gsmstate.c:1029
#define NUM_SCREENSHOT
Definition: s60-ids.h:93
#define NUM_CALENDAR_REQUEST_COUNT
Definition: s60-ids.h:70
#define NUM_CONTACTS_REPLY_CONTACT_START
Definition: s60-ids.h:22
int * CalendarLocations
Definition: s60phone.h:48
#define NUM_QUIT
Definition: s60-ids.h:9
#define NUM_MESSAGE_SEND_REPLY_FAILURE
Definition: s60-ids.h:48
GSM_GPRS_State GPRS
Definition: gammu-info.h:139
#define NUM_CONTACTS_REQUEST_CONTACT
Definition: s60-ids.h:15
#define NUM_SYSINFO_REPLY_END
Definition: s60-ids.h:36
#define NUM_MESSAGE_REPLY_LIST
Definition: s60-ids.h:62
#define NUM_LOCATION_REPLY
Definition: s60-ids.h:39
GSM_Error PHONE_FindDataFile(GSM_StateMachine *s, GSM_File *File, const char *ExtraPath, const char *filename)
Definition: pfunc.c:141
void DecodeUTF8(unsigned char *dest, const char *src, size_t len)
Definition: coding.c:1947
int * ContactLocations
Definition: s60phone.h:45
unsigned char Name[(GSM_MAX_SMS_FOLDER_NAME_LEN+1) *2]
#define NUM_HANGUP
Definition: s60-ids.h:43
#define NUM_LOCATION_REQUEST
Definition: s60-ids.h:38
GSM_MemoryType Memory
gboolean OutboxFolder
#define NUM_CALENDAR_ENTRY_CHANGE_REPLY_TIME
Definition: s60-ids.h:89
#define NUM_CONTACTS_REQUEST_HASH_SINGLE
Definition: s60-ids.h:13
GSM_SMSMessage SMS[GSM_MAX_MULTI_SMS]
GSM_CalendarType EntryType
GSM_Error GSM_TerminateConnection(GSM_StateMachine *s)
Definition: gsmstate.c:949
#define NOTIMPLEMENTED
Definition: gsmcomon.h:13
gboolean InboxFolder
GSM_BatteryCharge * BatteryCharge
Definition: gsmstate.h:537
#define NUM_SYSINFO_REQUEST
Definition: s60-ids.h:33
GSM_Config * GSM_GetConfig(GSM_StateMachine *s, int num)
Definition: gsmstate.c:1301
GSM_NetworkInfo_State State
Definition: gammu-info.h:127
GSM_DateTime Date
Definition: gammu-memory.h:380
unsigned char Number[(GSM_MAX_NUMBER_LENGTH+1) *2]
#define NUM_HELLO_REQUEST
Definition: s60-ids.h:7
#define S60_TIMEOUT
Definition: s60phone.h:36
gboolean closable
Definition: debug.h:40
GSM_Phone_Data Data
Definition: gsmstate.h:1369
GSM_SubCalendarEntry Entries[GSM_CALENDAR_ENTRIES]
GSM_MemoryType MemoryType
Definition: gammu-memory.h:131
#define NUM_CONTACTS_REPLY_HASH_SINGLE_LINE
Definition: s60-ids.h:19
gboolean GSM_SetDebugLevel(const char *info, GSM_Debug_Info *privdi)
Definition: debug.c:186
#define NUM_CONTACTS_REPLY_CONTACT_NOT_FOUND
Definition: s60-ids.h:26
#define NUM_CONTACTS_DELETE
Definition: s60-ids.h:29
GSM_EntryLocation Location
Definition: gammu-memory.h:376
void GSM_CreateFirmwareNumber(GSM_StateMachine *s)
Definition: pfunc.c:52
const char * number
Definition: gammu-info.h:768
#define _(x)
Definition: locales.h:21
#define NUM_MESSAGE_REPLY_COUNT
Definition: s60-ids.h:65
size_t SMSLocationsPos
Definition: s60phone.h:44
GSM_NetworkInfo_State PacketState
Definition: gammu-info.h:148
char PacketLAC[10]
Definition: gammu-info.h:152
#define NUM_CALENDAR_REPLY_ENTRY_NOT_FOUND
Definition: s60-ids.h:84
GSM_CalendarType
gboolean EncodeUTF8(char *dest, const unsigned char *src)
Definition: coding.c:1835
GSM_Error PHONE_UploadFile(GSM_StateMachine *s, GSM_File *File)
Definition: pfunc.c:173
#define NUM_CONNECTED
Definition: s60-ids.h:6
void GSM_DateTimeToTimestamp(GSM_DateTime *Date, char *str)
Definition: misc.c:155
#define TRUE
Definition: gammu-types.h:28
GSM_MemoryStatus * MemoryStatus
Definition: gsmstate.h:501
GSM_SMSMessage * SaveSMSMessage
Definition: gsmstate.h:513
#define NUM_DIAL
Definition: s60-ids.h:42
#define NUM_LOCATION_REPLY_NA
Definition: s60-ids.h:40
unsigned char * Buffer
Definition: protocol.h:22
void GSM_DateTimeFromTimestamp(GSM_DateTime *Date, const char *str)
Definition: misc.c:162
unsigned char Text[(GSM_MAX_TODO_TEXT_LENGTH+1) *2]
#define UNUSED
Definition: gammu-misc.h:105
#define NUM_MESSAGE_SEND_REQUEST
Definition: s60-ids.h:45
size_t SMSLocationsSize
Definition: s60phone.h:43
void GSM_FreeStateMachine(GSM_StateMachine *s)
Definition: gsmstate.c:1689
GSM_ValidityPeriod Relative
char Model[GSM_MAX_MODEL_LENGTH+1]
Definition: gsmstate.h:445
size_t CalendarLocationsSize
Definition: s60phone.h:49
GSM_DateTime Date
#define NUM_CONTACTS_ADD_REPLY_ID
Definition: s60-ids.h:28
unsigned char Text[(GSM_MAX_CALENDAR_TEXT_LENGTH+1) *2]
#define NUM_MESSAGE_SEND_REPLY_RETRY
Definition: s60-ids.h:49
int smprintf(GSM_StateMachine *s, const char *format,...)
Definition: debug.c:261
int DecodeBASE64(const char *Input, unsigned char *Output, const size_t Length)
Definition: coding.c:2149
GSM_Debug_Info * GSM_GetDebug(GSM_StateMachine *s)
Definition: gsmstate.c:1719
GSM_CalendarEntry * Cal
Definition: gsmstate.h:549
unsigned char Name[(GSM_MAX_SMSC_NAME_LENGTH+1) *2]
GSM_SubMemoryEntry Entries[GSM_PHONEBOOK_ENTRIES]
Definition: gammu-memory.h:427