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