1 /* (c) 2002-2003 by Walek, 2005 by Michal Cihar */
2
3 #include "../../gsmstate.h"
4
5 #ifdef GSM_ENABLE_ATGEN
6
7 #include <string.h>
8 #include <time.h>
9 #include <ctype.h>
10
11 #include "../../misc/coding/coding.h"
12 #include "../../gsmcomon.h"
13 #include "../pfunc.h"
14
15 #include "atgen.h"
16 #include "siemens.h"
17
18 #include "../../service/gsmlogo.h"
19
20
GetSiemensFrame(GSM_Protocol_Message * msg,GSM_StateMachine * s,const char * templ,unsigned char * buffer,size_t * len)21 static GSM_Error GetSiemensFrame(GSM_Protocol_Message *msg, GSM_StateMachine *s, const char *templ,
22 unsigned char *buffer, size_t *len)
23 {
24 GSM_Phone_ATGENData *Priv = &s->Phone.Data.Priv.ATGEN;
25 int i=2, pos=0, length=0;
26 unsigned char buf[512];
27
28 if (strstr(GetLineString(msg->Buffer,&Priv->Lines,2), "OK")) {
29 return ERR_EMPTY;
30 }
31 if (!strstr(GetLineString(msg->Buffer,&Priv->Lines,2), templ)) {
32 return ERR_UNKNOWN;
33 }
34
35 while (1) {
36 if (Priv->Lines.numbers[i*2+1]==0) break;
37 if ((!strstr(GetLineString(msg->Buffer, &Priv->Lines, i + 1), templ)) &&
38 (strstr(GetLineString(msg->Buffer, &Priv->Lines, i), templ))){
39 length = strlen(GetLineString(msg->Buffer, &Priv->Lines, i + 1));
40 DecodeHexBin(buf, GetLineString(msg->Buffer, &Priv->Lines, i + 1),length);
41 length = length / 2;
42 memcpy (buffer+pos,buf,length);
43 pos+=length;
44 }
45 i++;
46 }
47 *len = pos;
48 return ERR_NONE;
49 }
50
SetSiemensFrame(GSM_StateMachine * s,unsigned char * buff,const char * templ,int Location,GSM_Phone_RequestID RequestID,size_t len)51 static GSM_Error SetSiemensFrame (GSM_StateMachine *s, unsigned char *buff, const char *templ,
52 int Location, GSM_Phone_RequestID RequestID, size_t len)
53 {
54 GSM_Phone_Data *Phone = &s->Phone.Data;
55 GSM_Error error;
56 unsigned char req[60],req1[512],hexreq[10000];
57 int MaxFrame,CurrentFrame,size,sz,pos=0;
58 size_t reqlen;
59
60 if ((len * 2) > (sizeof(hexreq) - 1)) {
61 smprintf(s, "Too long request!\n");
62 return ERR_MOREMEMORY;
63 }
64
65 /* Encode request data */
66 EncodeHexBin(hexreq, buff, len);
67
68 /* Calculate number of frames */
69 size = len * 2;
70 MaxFrame = size / 352;
71 if (size % 352) {
72 MaxFrame++;
73 }
74
75 for (CurrentFrame = 0; CurrentFrame < MaxFrame; CurrentFrame++) {
76 pos = CurrentFrame * 352;
77 if (pos + 352 < size) {
78 sz = 352;
79 } else {
80 sz = size - pos;
81 }
82
83 /* Write AT command */
84 reqlen = sprintf(req, "AT^SBNW=\"%s\",%i,%i,%i\r",templ,Location,CurrentFrame+1,MaxFrame);
85 s->Protocol.Data.AT.EditMode = TRUE;
86 error = GSM_WaitFor(s, req, reqlen, 0x00, 3, RequestID);
87 s->Phone.Data.DispatchError = ERR_TIMEOUT;
88 s->Phone.Data.RequestID = RequestID;
89 if (error != ERR_NONE) {
90 return error;
91 }
92
93 /* Write data */
94 memcpy(req1, hexreq + pos, sz);
95 error = s->Protocol.Functions->WriteMessage(s, req1, sz, 0x00);
96 if (error!=ERR_NONE) {
97 return error;
98 }
99
100 /* Write termination mark */
101 error = s->Protocol.Functions->WriteMessage(s,"\x1A", 1, 0x00);
102 if (error != ERR_NONE) {
103 return error;
104 }
105
106 /* Wait for transaction completion */
107 error = GSM_WaitForOnce(s, NULL, 0x00, 0x00, 4);
108 if (error == ERR_TIMEOUT) {
109 return error;
110 }
111 }
112 /* Give phone some time to process the request */
113 /* @todo: This is probably way too big */
114 usleep(500000);
115 return Phone->DispatchError;
116 }
117
SIEMENS_ReplyGetBitmap(GSM_Protocol_Message * msg,GSM_StateMachine * s)118 GSM_Error SIEMENS_ReplyGetBitmap(GSM_Protocol_Message *msg, GSM_StateMachine *s)
119 {
120 unsigned char buffer[4096];
121 size_t length;
122 GSM_Error error;
123
124 error = GetSiemensFrame(msg,s,"bmp",buffer,&length);
125 if (error!=ERR_NONE) return error;
126 smprintf(s, "Operator logo received lenght=%ld\n", (long)length);
127 error = BMP2Bitmap (buffer,NULL,s->Phone.Data.Bitmap);
128 if (error==ERR_NONE) return error;
129 else return ERR_UNKNOWN;
130 }
131
SIEMENS_ReplySetFunction(GSM_Protocol_Message * msg UNUSED,GSM_StateMachine * s,const char * function)132 GSM_Error SIEMENS_ReplySetFunction (GSM_Protocol_Message *msg UNUSED, GSM_StateMachine *s, const char *function)
133 {
134 if (s->Protocol.Data.AT.EditMode) {
135 s->Protocol.Data.AT.EditMode = FALSE;
136 return ERR_NONE;
137 }
138 smprintf(s, "Written %s",function);
139 if (s->Phone.Data.Priv.ATGEN.ReplyState == AT_Reply_OK){
140 smprintf(s, " - OK\n");
141 return ERR_NONE;
142 } else {
143 smprintf(s, " - error\n");
144 return ERR_UNKNOWN;
145 }
146 }
147
SIEMENS_ReplySetBitmap(GSM_Protocol_Message * msg,GSM_StateMachine * s)148 GSM_Error SIEMENS_ReplySetBitmap(GSM_Protocol_Message *msg, GSM_StateMachine *s)
149 {
150 return SIEMENS_ReplySetFunction (msg, s, "Operator Logo");
151 }
152
SIEMENS_GetBitmap(GSM_StateMachine * s,GSM_Bitmap * Bitmap)153 GSM_Error SIEMENS_GetBitmap(GSM_StateMachine *s, GSM_Bitmap *Bitmap)
154 {
155 unsigned char req[32];
156 size_t len;
157
158 if (Bitmap->Type!=GSM_OperatorLogo) return ERR_NOTSUPPORTED;
159 if (Bitmap->Location-1 < 0) Bitmap->Location++;
160 s->Phone.Data.Bitmap=Bitmap;
161 len = sprintf(req, "AT^SBNR=\"bmp\",%i\r", Bitmap->Location-1);
162 smprintf(s, "Getting Bitmap\n");
163 return GSM_WaitFor (s, req, len, 0x00, 4, ID_GetBitmap);
164 }
165
SIEMENS_SetBitmap(GSM_StateMachine * s,GSM_Bitmap * Bitmap)166 GSM_Error SIEMENS_SetBitmap(GSM_StateMachine *s, GSM_Bitmap *Bitmap)
167 {
168 unsigned char buffer[4096];
169 int length;
170 GSM_Error error;
171
172 if (Bitmap->Type!=GSM_OperatorLogo) return ERR_NOTSUPPORTED;
173
174 error = Bitmap2BMP (buffer,NULL,Bitmap);
175 if (error!=ERR_NONE) return error;
176 length = 0x100 * buffer[3] + buffer[2];
177 buffer[58]=0xff; buffer[59]=0xff; buffer[60]=0xff;
178 if (Bitmap->Location-1 < 0) Bitmap->Location++;
179 s->Phone.Data.Bitmap=Bitmap;
180 return SetSiemensFrame(s, buffer,"bmp",Bitmap->Location-1,
181 ID_SetBitmap,length);
182 }
183
SIEMENS_ReplyGetRingtone(GSM_Protocol_Message * msg,GSM_StateMachine * s)184 GSM_Error SIEMENS_ReplyGetRingtone(GSM_Protocol_Message *msg, GSM_StateMachine *s)
185 {
186 char buffer[] = "Individual";
187 size_t length;
188 GSM_Error error;
189
190 error = GetSiemensFrame(msg,s,"mid",s->Phone.Data.Ringtone->NokiaBinary.Frame,&length);
191 if (error!=ERR_NONE) return error;
192 smprintf(s, "Midi ringtone received\n");
193
194 s->Phone.Data.Ringtone->Format = RING_MIDI;
195 s->Phone.Data.Ringtone->NokiaBinary.Length = length;
196 EncodeUnicode (s->Phone.Data.Ringtone->Name,buffer,strlen(buffer));
197 return ERR_NONE;
198 }
199
SIEMENS_GetRingtone(GSM_StateMachine * s,GSM_Ringtone * Ringtone,gboolean PhoneRingtone UNUSED)200 GSM_Error SIEMENS_GetRingtone(GSM_StateMachine *s, GSM_Ringtone *Ringtone, gboolean PhoneRingtone UNUSED)
201 {
202 unsigned char req[32];
203 size_t len;
204
205 s->Phone.Data.Ringtone=Ringtone;
206 len = sprintf(req, "AT^SBNR=\"mid\",%i\r", Ringtone->Location-1);
207 smprintf(s, "Getting RingTone\n");
208 return GSM_WaitFor (s, req, len, 0x00, 4, ID_GetRingtone);
209 }
210
SIEMENS_ReplySetRingtone(GSM_Protocol_Message * msg,GSM_StateMachine * s)211 GSM_Error SIEMENS_ReplySetRingtone(GSM_Protocol_Message *msg, GSM_StateMachine *s)
212 {
213 return SIEMENS_ReplySetFunction (msg, s, "Ringtone");
214 }
215
SIEMENS_SetRingtone(GSM_StateMachine * s,GSM_Ringtone * Ringtone,int * maxlength UNUSED)216 GSM_Error SIEMENS_SetRingtone(GSM_StateMachine *s, GSM_Ringtone *Ringtone, int *maxlength UNUSED)
217 {
218 GSM_Phone_Data *Phone = &s->Phone.Data;
219
220 if (Ringtone->Location==255) Ringtone->Location=1;
221 if (Ringtone->Location-1 > 1) return ERR_INVALIDLOCATION;
222
223 s->Phone.Data.Ringtone = Ringtone;
224 Phone->Ringtone = Ringtone;
225 return SetSiemensFrame(s, Ringtone->NokiaBinary.Frame,"mid",Ringtone->Location-1,
226 ID_SetRingtone,Ringtone->NokiaBinary.Length);
227 }
228
SIEMENS_ReplyGetNextCalendar(GSM_Protocol_Message * msg,GSM_StateMachine * s)229 GSM_Error SIEMENS_ReplyGetNextCalendar(GSM_Protocol_Message *msg, GSM_StateMachine *s)
230 {
231 GSM_Phone_ATGENData *Priv = &s->Phone.Data.Priv.ATGEN;
232 GSM_Phone_Data *Data = &s->Phone.Data;
233 GSM_CalendarEntry *Calendar = Data->Cal;
234 GSM_ToDoEntry ToDo;
235 GSM_Error error;
236 unsigned char buffer[354];
237 size_t pos=0;
238 size_t len;
239
240 switch (Priv->ReplyState) {
241 case AT_Reply_OK:
242 smprintf(s, "Calendar entry received\n");
243 error = GetSiemensFrame(msg, s, "vcs", buffer, &len);
244 if (error != ERR_NONE) return error;
245 return GSM_DecodeVCALENDAR_VTODO(&(s->di), buffer,&pos,Calendar,&ToDo,Siemens_VCalendar,0);
246 case AT_Reply_Error:
247 smprintf(s, "Error - too high location ?\n");
248 return ERR_INVALIDLOCATION;
249 case AT_Reply_CMSError:
250 return ATGEN_HandleCMSError(s);
251 case AT_Reply_CMEError:
252 /* S55 say this way, that this is empty */
253 if (Priv->ErrorCode == 100) {
254 return ERR_EMPTY;
255 }
256 return ATGEN_HandleCMEError(s);
257 default:
258 break;
259 }
260 return ERR_UNKNOWNRESPONSE;
261 }
262
SIEMENS_GetNextCalendar(GSM_StateMachine * s,GSM_CalendarEntry * Note,gboolean start)263 GSM_Error SIEMENS_GetNextCalendar(GSM_StateMachine *s, GSM_CalendarEntry *Note, gboolean start)
264 {
265 GSM_Phone_ATGENData *Priv = &s->Phone.Data.Priv.ATGEN;
266 GSM_Error error;
267 unsigned char req[32];
268 int Location;
269 size_t len;
270
271 if (Priv->Manufacturer!=AT_Siemens) return ERR_NOTSUPPORTED;
272
273 if (start) Note->Location = Priv->FirstCalendarPos;
274 s->Phone.Data.Cal = Note;
275 Note->EntriesNum = 0;
276 smprintf(s, "Getting VCALENDAR\n");
277 Location = Note->Location;
278 while (1){
279 Location++;
280 len = sprintf(req, "AT^SBNR=\"vcs\",%i\r",Location);
281 error = GSM_WaitFor (s, req, len, 0x00, 4, ID_GetCalendarNote);
282 if ((error!=ERR_NONE) && (error!=ERR_EMPTY)) {
283 error = ERR_INVALIDLOCATION;
284 break;
285 }
286 Note->Location = Location;
287 if (Location > MAX_VCALENDAR_LOCATION) {
288 error = ERR_EMPTY;
289 break;
290 }
291 if (error==ERR_NONE)
292 break;
293 }
294 return error;
295 }
296
SIEMENS_GetCalendar(GSM_StateMachine * s,GSM_CalendarEntry * Note)297 GSM_Error SIEMENS_GetCalendar(GSM_StateMachine *s, GSM_CalendarEntry *Note)
298 {
299 GSM_Phone_ATGENData *Priv = &s->Phone.Data.Priv.ATGEN;
300 unsigned char req[32];
301 size_t len;
302
303 if (Priv->Manufacturer!=AT_Siemens) return ERR_NOTSUPPORTED;
304
305 s->Phone.Data.Cal = Note;
306 len = sprintf(req, "AT^SBNR=\"vcs\",%i\r",Note->Location);
307 smprintf(s, "Getting calendar note\n");
308
309 return GSM_WaitFor (s, req, len, 0x00, 4, ID_GetCalendarNote);
310 }
311
SIEMENS_ReplyAddCalendarNote(GSM_Protocol_Message * msg,GSM_StateMachine * s)312 GSM_Error SIEMENS_ReplyAddCalendarNote(GSM_Protocol_Message *msg, GSM_StateMachine *s)
313 {
314 return SIEMENS_ReplySetFunction (msg, s, "Calendar Note");
315 }
316
SIEMENS_ReplySetMemory(GSM_Protocol_Message * msg,GSM_StateMachine * s)317 GSM_Error SIEMENS_ReplySetMemory(GSM_Protocol_Message *msg, GSM_StateMachine *s)
318 {
319 return SIEMENS_ReplySetFunction (msg, s, "Memory entry");
320 }
321
SIEMENS_ReplyDelCalendarNote(GSM_Protocol_Message * msg UNUSED,GSM_StateMachine * s)322 GSM_Error SIEMENS_ReplyDelCalendarNote(GSM_Protocol_Message *msg UNUSED, GSM_StateMachine *s)
323 {
324 GSM_Phone_Data *Data = &s->Phone.Data;
325
326 if (Data->Cal->Location > MAX_VCALENDAR_LOCATION) return ERR_UNKNOWN;
327
328 if (Data->Priv.ATGEN.ReplyState== AT_Reply_OK) {
329 smprintf(s, "Calendar note deleted\n");
330 return ERR_NONE;
331 } else {
332 smprintf(s, "Can't delete calendar note\n");
333 return ERR_UNKNOWN;
334 }
335 }
336
SIEMENS_DelCalendarNote(GSM_StateMachine * s,GSM_CalendarEntry * Note)337 GSM_Error SIEMENS_DelCalendarNote(GSM_StateMachine *s, GSM_CalendarEntry *Note)
338 {
339 GSM_Phone_ATGENData *Priv = &s->Phone.Data.Priv.ATGEN;
340 unsigned char req[32];
341 size_t len;
342
343 if (s->Phone.Data.Priv.ATGEN.Manufacturer!=AT_Siemens) return ERR_NOTSUPPORTED;
344 s->Phone.Data.Cal = Note;
345 len = sprintf(req, "AT^SBNW=\"vcs\",%i,0\r",Note->Location);
346 smprintf(s, "Deleting calendar note\n");
347 Priv->FirstFreeCalendarPos = 0;
348 return GSM_WaitFor(s, req, len, 0x00, 4, ID_DeleteCalendarNote);
349 }
350
SIEMENS_SetCalendarNote(GSM_StateMachine * s,GSM_CalendarEntry * Note)351 GSM_Error SIEMENS_SetCalendarNote(GSM_StateMachine *s, GSM_CalendarEntry *Note)
352 {
353 GSM_Phone_ATGENData *Priv = &s->Phone.Data.Priv.ATGEN;
354 GSM_Error error;
355 unsigned char req[500];
356 size_t size=0;
357
358 if (Priv->Manufacturer!=AT_Siemens) return ERR_NOTSUPPORTED;
359
360 s->Phone.Data.Cal = Note;
361 error=GSM_EncodeVCALENDAR(req, sizeof(req) ,&size,Note,TRUE,Siemens_VCalendar);
362 if (error != ERR_NONE) return error;
363
364 return SetSiemensFrame (s,req,"vcs",Note->Location,ID_SetCalendarNote,size);
365 }
366
SIEMENS_AddCalendarNote(GSM_StateMachine * s,GSM_CalendarEntry * Note)367 GSM_Error SIEMENS_AddCalendarNote(GSM_StateMachine *s, GSM_CalendarEntry *Note)
368 {
369 GSM_Phone_ATGENData *Priv = &s->Phone.Data.Priv.ATGEN;
370 GSM_Error error;
371 unsigned char req[500], req1[32];
372 size_t size=0;
373 int Location;
374 size_t len;
375
376 if (Priv->Manufacturer!=AT_Siemens) return ERR_NOTSUPPORTED;
377
378 error=GSM_EncodeVCALENDAR(req, sizeof(req),&size,Note,TRUE,Siemens_VCalendar);
379 if (error != ERR_NONE) {
380 return error;
381 }
382
383 Note->Location = Priv->FirstFreeCalendarPos;
384 s->Phone.Data.Cal = Note;
385 Note->EntriesNum = 0;
386 smprintf(s, "Getting VCALENDAR\n");
387 Location = Note->Location;
388 while (1){
389 Location++;
390 len = sprintf(req1, "AT^SBNR=\"vcs\",%i\r",Location);
391 error = GSM_WaitFor (s, req1, len, 0x00, 4, ID_GetCalendarNote);
392 Note->Location = Location;
393 Priv->FirstFreeCalendarPos = Location;
394 if (error==ERR_EMPTY) break;
395 if (Location > MAX_VCALENDAR_LOCATION) {
396 Priv->FirstFreeCalendarPos = 0;
397 return ERR_FULL;
398 }
399 if (error!=ERR_NONE) return error;
400 }
401 return SetSiemensFrame (s,req,"vcs",Note->Location,ID_SetCalendarNote,size);
402 }
403
SIEMENS_ReplyGetMemory(GSM_Protocol_Message * msg,GSM_StateMachine * s)404 GSM_Error SIEMENS_ReplyGetMemory(GSM_Protocol_Message *msg, GSM_StateMachine *s)
405 {
406 GSM_Phone_ATGENData *Priv = &s->Phone.Data.Priv.ATGEN;
407 GSM_MemoryEntry *Memory = s->Phone.Data.Memory;
408 char buffer[4096];
409 size_t length = 0;
410 GSM_Error error;
411
412 switch (Priv->ReplyState) {
413 case AT_Reply_OK:
414 smprintf(s, "Phonebook entry received\n");
415 error = GetSiemensFrame(msg,s,"vcf", buffer, &length);
416 if (error != ERR_NONE) return error;
417 Memory->EntriesNum = 0;
418 length = 0;
419 return GSM_DecodeVCARD(&(s->di), buffer, &length, Memory, SonyEricsson_VCard21_Phone);
420 case AT_Reply_Error:
421 smprintf(s, "Error - too high location ?\n");
422 return ERR_INVALIDLOCATION;
423 case AT_Reply_CMSError:
424 return ATGEN_HandleCMSError(s);
425 case AT_Reply_CMEError:
426 /* S55 say this way, that this is empty */
427 if (Priv->ErrorCode == 100) {
428 return ERR_EMPTY;
429 }
430 return ATGEN_HandleCMEError(s);
431 default:
432 break;
433 }
434 return ERR_UNKNOWNRESPONSE;
435 }
436
SIEMENS_ReplyGetMemoryInfo(GSM_Protocol_Message * msg,GSM_StateMachine * s)437 GSM_Error SIEMENS_ReplyGetMemoryInfo(GSM_Protocol_Message *msg, GSM_StateMachine *s)
438 {
439 GSM_Phone_ATGENData *Priv = &s->Phone.Data.Priv.ATGEN;
440 char *pos;
441 /* Text to parse: ^SBNR: ("vcs",(1-50)) */
442
443 Priv->PBKSBNR = AT_NOTAVAILABLE;
444
445 switch (Priv->ReplyState) {
446 case AT_Reply_OK:
447 smprintf(s, "Memory info received\n");
448
449 /* Parse first location */
450 pos = strstr(msg->Buffer, "\"vcf\"");
451 if (!pos) return ERR_NOTSUPPORTED;
452 pos = strchr(pos + 1, '(');
453 if (!pos) return ERR_UNKNOWNRESPONSE;
454 pos++;
455 if (!isdigit((int)*pos)) return ERR_UNKNOWNRESPONSE;
456 Priv->FirstMemoryEntry = atoi(pos);
457
458 /* Parse last location*/
459 pos = strchr(pos, '-');
460 if (!pos) return ERR_UNKNOWNRESPONSE;
461 pos++;
462 if (!isdigit((int)*pos)) return ERR_UNKNOWNRESPONSE;
463 Priv->MemorySize = atoi(pos) + 1 - Priv->FirstMemoryEntry;
464
465 Priv->PBKSBNR = AT_AVAILABLE;
466
467 return ERR_NONE;
468 case AT_Reply_Error:
469 return ERR_NONE;
470 case AT_Reply_CMSError:
471 return ATGEN_HandleCMSError(s);
472 case AT_Reply_CMEError:
473 return ATGEN_HandleCMEError(s);
474 default:
475 return ERR_UNKNOWNRESPONSE;
476 }
477 }
478
SIEMENS_SetMemory(GSM_StateMachine * s,GSM_MemoryEntry * entry)479 GSM_Error SIEMENS_SetMemory(GSM_StateMachine *s, GSM_MemoryEntry *entry)
480 {
481 GSM_Phone_ATGENData *Priv = &s->Phone.Data.Priv.ATGEN;
482 GSM_Error error;
483 unsigned char req[5000];
484 size_t size=0;
485
486 if (Priv->Manufacturer != AT_Siemens) {
487 return ERR_NOTSUPPORTED;
488 }
489 if (entry->MemoryType != MEM_ME) {
490 return ERR_NOTSUPPORTED;
491 }
492
493 /*
494 * Phone does not seem to be able to handle full vCard 2.1,
495 * it might be necessary to add some another vCard type specially
496 * tailored for Siemens.
497 */
498 error = GSM_EncodeVCARD(&(s->di), req, sizeof(req) ,&size, entry, TRUE, SonyEricsson_VCard10);
499 if (error != ERR_NONE) return error;
500
501 return SetSiemensFrame(s, req, "vcf", entry->Location, ID_SetMemory, size);
502 }
503
504 #endif
505
506 /* How should editor hadle tabs in this file? Add editor commands here.
507 * vim: noexpandtab sw=8 ts=8 sts=8:
508 */
509