1 /* © 2007 - 2009 Michal Čihař */
2 
3 /**
4  * @file motorola.c
5  * @author Michal Čihař
6  */
7 /**
8  * @ingroup Phone
9  * @{
10  */
11 /**
12  * @addtogroup ATPhone
13  * @{
14  */
15 
16 #include <gammu-config.h>
17 
18 #ifdef GSM_ENABLE_ATGEN
19 
20 #include "../../gsmcomon.h"
21 #include "../../gsmstate.h"
22 #include "../../service/gsmpbk.h"
23 #include "atgen.h"
24 #include <string.h>
25 #include "../../../libgammu/misc/string.h"
26 
27 typedef struct {
28 	char Command[20];
29 	int Mode;
30 } MOTOROLA_CommandInfo;
31 
32 /**
33  * AT Commands which can be issued only in one mode.
34  *
35  * List is based on c18 AT Commands document revision C.
36  */
37 MOTOROLA_CommandInfo Commands[] = {
38 	{"+CGMI", 2},
39 	{"+CGMM", 2},
40 	{"+CGMR", 2},
41 	{"+CGSN", 2},
42 	{"+CSCS", 2},
43 	{"+CIMI", 2},
44 	{"+CNUM", 2},
45 	{"+CVHU", 2},
46 	{"+CHUP", 2},
47 	{"+CIND", 2},
48 	{"+CLCK", 2},
49 	{"D", 2},  /* We want voice call */
50 	{"H", 2},  /* We want voice call */
51 	{"A", 2},  /* We want voice call */
52 	{"+CRING", 2},
53 	{"+CLIP", 2},
54 	{"+CLIR", 2},
55 	{"+CCFC", 2},
56 	{"+CHLD", 2},
57 	{"+COLP", 2},
58 	{"+CCWA", 2},
59 	{"+CLCC", 2},
60 	{"+CPBS", 2},
61 	{"+CPBR", 2},
62 	{"+CPBF", 2},
63 	{"+CPBW", 2},
64 	{"+CCLK", 2},
65 	{"+CNMI", 2},
66 	{"+CMGD", 2},
67 	{"+CMSS", 2},
68 	{"+CSMS", 2},
69 	{"+CPMS", 2},
70 	{"+CMGF", 2},
71 	{"+CSDH", 2},
72 	{"+CMTI", 2},
73 	{"+CMGL", 2},
74 	{"+CMGR", 2},
75 	{"+CMGW", 2},
76 	{"+CSCA", 2},
77 	{"+COPS", 2},
78 	{"+CBC", 2},
79 	{"+CRTT", 2},
80 	{"+CMEE", 2},
81 	{"+CKPD", 2},
82 
83 	{"+CHV", 0},
84 	{"+CDV", 0},
85 	{"+CPAS", 0},
86 	{"+CREG", 0},
87 	{"+CSQ", 0},
88 	{"+GCAP", 0},
89 	{"+CMUT", 0},
90 	{"+CIMSI", 0},
91 
92 	{"", 0},
93 };
94 
MOTOROLA_SetModeReply(GSM_Protocol_Message * msg UNUSED,GSM_StateMachine * s)95 GSM_Error MOTOROLA_SetModeReply(GSM_Protocol_Message *msg UNUSED, GSM_StateMachine *s)
96 {
97 	GSM_Phone_ATGENData *Priv = &s->Phone.Data.Priv.ATGEN;
98 
99 	switch (s->Phone.Data.Priv.ATGEN.ReplyState) {
100 		case AT_Reply_OK:
101 		case AT_Reply_Connect:
102 			/*
103 			 * The typo in next line (Unkown) is intentional,
104 			 * phone returns it this way.
105 			 */
106 			if (strstr(GetLineString(msg->Buffer, &Priv->Lines, 2), "Unkown mode value") != NULL) {
107 				return ERR_NOTSUPPORTED;
108 			}
109 			return ERR_NONE;
110 		case AT_Reply_Error:
111 			return ERR_UNKNOWN;
112 		case AT_Reply_CMSError:
113 			return ATGEN_HandleCMSError(s);
114 		case AT_Reply_CMEError:
115 			return ATGEN_HandleCMEError(s);
116 		default:
117 			break;
118 	}
119 	return ERR_UNKNOWNRESPONSE;
120 }
121 
MOTOROLA_SetMode(GSM_StateMachine * s,const char * command)122 GSM_Error MOTOROLA_SetMode(GSM_StateMachine *s, const char *command)
123 {
124 	GSM_Phone_ATGENData *Priv = &s->Phone.Data.Priv.ATGEN;
125 	MOTOROLA_CommandInfo *cmd;
126 	const char *realcmd;
127 	char buffer[30]={0};
128 	GSM_Error error = ERR_NONE;
129 	size_t len;
130 
131 	/* Do we need any mode switching? */
132 	if (!Priv->Mode) {
133 		return ERR_NONE;
134 	}
135 
136 	/* We don't care about non AT commands */
137 	if (strncasecmp(command, "AT", 2) != 0) {
138 		return ERR_NONE;
139 	}
140 
141 	/* Skip AT prefix */
142 	realcmd = command + 2;
143 
144 	/* Do we have it in our list? */
145 	for (cmd = Commands; cmd->Command[0] != 0; cmd++) {
146 		if (strncasecmp(realcmd, cmd->Command, strlen(cmd->Command)) == 0) {
147 			break;
148 		}
149 	}
150 
151 	/* Not found? */
152 	if (cmd->Command[0] == 0) {
153 		smprintf(s, "Nothing known about %s command, using current mode\n", command);
154 		return ERR_NONE;
155 	}
156 
157 	/* Compare current mode */
158 	if (cmd->Mode == Priv->CurrentMode) {
159 		smprintf(s, "Already in mode %d\n", cmd->Mode);
160 		return ERR_NONE;
161 	}
162 
163 	/* Switch mode */
164 	smprintf(s, "Switching to mode %d\n", cmd->Mode);
165 	len = sprintf(buffer, "AT+MODE=%d\r", cmd->Mode);
166 	error = GSM_WaitFor(s, buffer, len, 0x00, 100, ID_ModeSwitch);
167 
168 	/* On succes we remember it */
169 	if (error == ERR_NONE) {
170 
171 		/* We might need to restore charset as phone resets it */
172 		if (cmd->Mode == 2) {
173 			smprintf(s, "Waiting for banner...\n");
174 
175 			/* Wait for banner */
176 			error = GSM_WaitForOnce(s, NULL, 0x00, 0x00, 40);
177 
178 			if (error != ERR_NONE) {
179 				return error;
180 			}
181 
182 			/* Check for banner result */
183 			if (Priv->CurrentMode != 2) {
184 				smprintf(s, "Failed to set mode 2!\n");
185 				return ERR_BUG;
186 			}
187 
188 			/* Now we can work with phone */
189 			error = ATGEN_SetCharset(s, AT_PREF_CHARSET_RESET);
190 		} else {
191 			Priv->CurrentMode = cmd->Mode;
192 		}
193 	}
194 	return error;
195 }
196 
197 /**
198  * Catches +MBAN: reply.
199  */
MOTOROLA_Banner(GSM_Protocol_Message * msg UNUSED,GSM_StateMachine * s)200 GSM_Error MOTOROLA_Banner(GSM_Protocol_Message *msg UNUSED, GSM_StateMachine *s)
201 {
202 	s->Phone.Data.Priv.ATGEN.CurrentMode = 2;
203 	return ERR_NONE;
204 }
205 
206 
MOTOROLA_ReplyGetMemoryInfo(GSM_Protocol_Message * msg,GSM_StateMachine * s)207 GSM_Error MOTOROLA_ReplyGetMemoryInfo(GSM_Protocol_Message *msg, GSM_StateMachine *s)
208 {
209  	GSM_Phone_ATGENData 	*Priv = &s->Phone.Data.Priv.ATGEN;
210 	GSM_Error error;
211 
212 	Priv->PBK_MPBR = AT_NOTAVAILABLE;
213 
214  	switch (Priv->ReplyState) {
215  	case AT_Reply_OK:
216 		/* Reply string:
217 		 * +MPBR: 10-18259,40,24,14,0-1,64,(255),(0),(0-1),(1-11),(255),25,(0-1,255),264,(0),62,62,32,32,32,32,50,264
218 		 */
219 		Priv->PBK_MPBR = AT_AVAILABLE;
220 		error = ATGEN_ParseReply(s, GetLineString(msg->Buffer, &Priv->Lines, 2),
221 					"+MPBR: @i-@i, @0",
222 					&Priv->MotorolaFirstMemoryEntry,
223 					&Priv->MotorolaMemorySize);
224 		if (error != ERR_NONE) {
225 			return error;
226 		}
227 
228 		Priv->MotorolaMemorySize -= Priv->MotorolaFirstMemoryEntry;
229 
230 		return ERR_NONE;
231 	case AT_Reply_Error:
232 		/* The phone returns simply ERROR on empty entry */
233 		return ERR_EMPTY;
234 	case AT_Reply_CMSError:
235 	        return ATGEN_HandleCMSError(s);
236 	case AT_Reply_CMEError:
237 	        return ATGEN_HandleCMEError(s);
238  	default:
239 		return ERR_UNKNOWNRESPONSE;
240 	}
241 }
242 
MOTOROLA_ReplyGetMemory(GSM_Protocol_Message * msg,GSM_StateMachine * s)243 GSM_Error MOTOROLA_ReplyGetMemory(GSM_Protocol_Message *msg, GSM_StateMachine *s)
244 {
245  	GSM_Phone_ATGENData 	*Priv = &s->Phone.Data.Priv.ATGEN;
246  	GSM_MemoryEntry		*Memory = s->Phone.Data.Memory;
247 	GSM_Error error;
248 	const char *str;
249 	int number_type, entry_type;
250 
251 	switch (Priv->ReplyState) {
252 	case AT_Reply_OK:
253  		smprintf(s, "Phonebook entry received\n");
254 		Memory->EntriesNum = 2;
255 		Memory->Entries[0].AddError = ERR_NONE;
256 		Memory->Entries[0].VoiceTag = 0;
257 		Memory->Entries[0].SMSList[0] = 0;
258 		Memory->Entries[0].Location = PBK_Location_Unknown;
259 		Memory->Entries[1].EntryType = PBK_Text_Name;
260 		Memory->Entries[1].Location = PBK_Location_Unknown;
261 		Memory->Entries[1].AddError = ERR_NONE;
262 		Memory->Entries[1].VoiceTag = 0;
263 		Memory->Entries[1].SMSList[0] = 0;
264 
265 		/* Get line from reply */
266 		str = GetLineString(msg->Buffer, &Priv->Lines, 2);
267 
268 		/* Detect empty entry */
269 		if (strcmp(str, "OK") == 0) return ERR_EMPTY;
270 
271 		/*
272 		 * Parse reply string
273 		 *
274 		 * +MPBR: 18,"user@domain.net",128,"Contact Name",6,0,255,0,0,1,255,255,0,"",0,0,"","","","","","","",""
275 		 */
276 		error = ATGEN_ParseReply(s, str,
277 					"+MPBR: @i, @p, @i, @s, @i, @0",
278 					&Memory->Location,
279 					Memory->Entries[0].Text, sizeof(Memory->Entries[0].Text),
280 					&number_type,
281 					Memory->Entries[1].Text, sizeof(Memory->Entries[1].Text),
282 					&entry_type);
283 		Memory->Location = Memory->Location + 1 - Priv->MotorolaFirstMemoryEntry;
284 		switch (entry_type) {
285 			case 0:
286 				Memory->Entries[0].EntryType = PBK_Number_General;
287 				Memory->Entries[0].Location = PBK_Location_Work;
288 				GSM_TweakInternationalNumber(Memory->Entries[0].Text, number_type);
289 				break;
290 			case 1:
291 				Memory->Entries[0].EntryType = PBK_Number_General;
292 				Memory->Entries[0].Location = PBK_Location_Home;
293 				GSM_TweakInternationalNumber(Memory->Entries[0].Text, number_type);
294 				break;
295 			case 2:
296 			case 10:
297 			case 11:
298 				Memory->Entries[0].EntryType = PBK_Number_General;
299 				Memory->Entries[0].Location = PBK_Location_Unknown;
300 				GSM_TweakInternationalNumber(Memory->Entries[0].Text, number_type);
301 				break;
302 			case 3:
303 				Memory->Entries[0].EntryType = PBK_Number_Mobile;
304 				Memory->Entries[0].Location = PBK_Location_Unknown;
305 				GSM_TweakInternationalNumber(Memory->Entries[0].Text, number_type);
306 				break;
307 			case 4:
308 				Memory->Entries[0].EntryType = PBK_Number_Fax;
309 				Memory->Entries[0].Location = PBK_Location_Unknown;
310 				GSM_TweakInternationalNumber(Memory->Entries[0].Text, number_type);
311 				break;
312 			case 5:
313 				Memory->Entries[0].EntryType = PBK_Number_Pager;
314 				Memory->Entries[0].Location = PBK_Location_Unknown;
315 				GSM_TweakInternationalNumber(Memory->Entries[0].Text, number_type);
316 				break;
317 			case 6:
318 				Memory->Entries[0].EntryType = PBK_Text_Email;
319 				Memory->Entries[0].Location = PBK_Location_Unknown;
320 				break;
321 			case 7:
322 				Memory->Entries[0].EntryType = PBK_Text_Email; /* Mailing list */
323 				Memory->Entries[0].Location = PBK_Location_Unknown;
324 				break;
325 			default:
326 				Memory->Entries[0].EntryType = PBK_Text_Note;
327 				Memory->Entries[0].Location = PBK_Location_Unknown;
328 		}
329 
330 		if (error != ERR_NONE) {
331 			return error;
332 		}
333 		return ERR_NONE;
334 	case AT_Reply_Error:
335                 return ERR_UNKNOWN;
336 	case AT_Reply_CMSError:
337  	        return ATGEN_HandleCMSError(s);
338 	case AT_Reply_CMEError:
339 	        return ATGEN_HandleCMEError(s);
340 	default:
341 		break;
342 	}
343 	return ERR_UNKNOWNRESPONSE;
344 }
345 
MOTOROLA_LockCalendar(GSM_StateMachine * s)346 GSM_Error MOTOROLA_LockCalendar(GSM_StateMachine *s)
347 {
348 	GSM_Error error;
349 
350 	error = ATGEN_WaitForAutoLen(s, "AT+MDBL=1\r", 0x00, 10, ID_SetCalendarNote);
351 
352 	return error;
353 }
354 
MOTOROLA_UnlockCalendar(GSM_StateMachine * s)355 GSM_Error MOTOROLA_UnlockCalendar(GSM_StateMachine *s)
356 {
357 	GSM_Error error;
358 
359 	error = ATGEN_WaitForAutoLen(s, "AT+MDBL=0\r", 0x00, 10, ID_SetCalendarNote);
360 
361 	return error;
362 }
363 
MOTOROLA_ReplyGetCalendarStatus(GSM_Protocol_Message * msg,GSM_StateMachine * s)364 GSM_Error MOTOROLA_ReplyGetCalendarStatus(GSM_Protocol_Message *msg, GSM_StateMachine *s)
365 {
366 	GSM_Phone_ATGENData	*Priv = &s->Phone.Data.Priv.ATGEN;
367 	GSM_Error error;
368 	int ignore;
369 
370 	if (Priv->ReplyState != AT_Reply_OK) {
371 		switch (s->Phone.Data.Priv.ATGEN.ReplyState) {
372 		case AT_Reply_Error:
373 			return ERR_NOTSUPPORTED;
374 		case AT_Reply_CMSError:
375 			return ATGEN_HandleCMSError(s);
376 		case AT_Reply_CMEError:
377 			return ATGEN_HandleCMEError(s);
378 		default:
379 			return ERR_UNKNOWNRESPONSE;
380 		}
381 	}
382 
383 	/*
384 	 * Reply looks like:
385 	 * +MDBR: 500,1,64,8,2
386 	 * (max events that can be stored, number of stored events, ?, ?, ?)
387 	 */
388 
389 	error = ATGEN_ParseReply(s,
390 		GetLineString(msg->Buffer, &Priv->Lines, 2),
391 		"+MDBR: @i, @i, @i, @i, @i",
392 		&s->Phone.Data.CalStatus->Free,
393 		&s->Phone.Data.CalStatus->Used,
394 		&ignore,
395 		&ignore,
396 		&ignore);
397 	if (error != ERR_NONE) return error;
398 	s->Phone.Data.CalStatus->Free += s->Phone.Data.CalStatus->Used;
399 	return ERR_NONE;
400 }
401 
MOTOROLA_GetCalendarStatus(GSM_StateMachine * s,GSM_CalendarStatus * Status)402 GSM_Error MOTOROLA_GetCalendarStatus(GSM_StateMachine *s, GSM_CalendarStatus *Status)
403 {
404 	GSM_Error error;
405 
406 	s->Phone.Data.CalStatus = Status;
407 
408 	error = ATGEN_WaitForAutoLen(s, "AT+MDBR=?\r", 0x00, 10, ID_GetCalendarNotesInfo);
409 
410 	return error;
411 }
412 
MOTOROLA_ParseCalendarSimple(GSM_StateMachine * s,const char * line)413 GSM_Error MOTOROLA_ParseCalendarSimple(GSM_StateMachine *s, const char *line)
414 {
415 	GSM_Error error;
416 	int ignore;
417 	GSM_CalendarEntry *Note = s->Phone.Data.Cal;
418 	int duration, repeat, has_time, has_alarm;
419 	/*
420 	 * Parse following format:
421 	 *
422 	 * +MDBR: 0,"Meeting",1,0,"17:00","02-24-2006",60,"00:00","00-00-2000",0
423 	 * +MDBR: 1,"Breakfast",1,1,"10:00","02-25-2006",60,"09:30","02-25-2006",2
424 	 * event num, description, time flag (if 0, start time is meaningless), alarm enabl
425 	 * ed flag (if 0, alarm time is meaningless), time, date, duration (mins), alarm ti
426 	 * me, alarm date, repeat type
427 	 *
428 	 * repeat type:
429 	 * 1 = daily
430 	 * 2 = weekly
431 	 * 3 = monthly on date
432 	 * 4 = monthly on day
433 	 * 5 = yearly
434 	 */
435 	Note->Type = GSM_CAL_MEMO;
436 	Note->Entries[0].EntryType = CAL_TEXT;
437 	Note->Entries[1].EntryType = CAL_START_DATETIME;
438 	Note->Entries[1].Date.Timezone = 0;
439 	Note->Entries[1].Date.Second = 0;
440 	Note->Entries[2].EntryType = CAL_TONE_ALARM_DATETIME;
441 	Note->Entries[2].Date.Timezone = 0;
442 	Note->Entries[2].Date.Second = 0;
443 	Note->EntriesNum = 3;
444 	error = ATGEN_ParseReply(s,
445 		line,
446 		"+MDBR: @i, @s, @i, @i, @d, @i, @d, @i",
447 		&ignore,
448 		Note->Entries[0].Text, sizeof(Note->Entries[0].Text),
449 		&has_time,
450 		&has_alarm,
451 		&(Note->Entries[1].Date),
452 		&duration,
453 		&(Note->Entries[2].Date),
454 		&repeat);
455 
456 	if (!has_time && !has_alarm) {
457 		Note->EntriesNum = 1;
458 	} else if (!has_alarm) {
459 		Note->EntriesNum = 2;
460 	} else if (!has_time) {
461 		Note->EntriesNum = 2;
462 		Note->Entries[1].EntryType = Note->Entries[2].EntryType;
463 		Note->Entries[1].Date = Note->Entries[2].Date;
464 	}
465 	switch (repeat) {
466 		case 1:
467 			Note->Entries[Note->EntriesNum].EntryType = CAL_REPEAT_FREQUENCY;
468 			Note->Entries[Note->EntriesNum].Number = 1;
469 			Note->EntriesNum++;
470 			break;
471 		case 2:
472 			Note->Entries[Note->EntriesNum].EntryType = CAL_REPEAT_FREQUENCY;
473 			Note->Entries[Note->EntriesNum].Number = 7;
474 			Note->EntriesNum++;
475 			break;
476 		case 3:
477 			Note->Entries[Note->EntriesNum].EntryType = CAL_REPEAT_FREQUENCY;
478 			Note->Entries[Note->EntriesNum].Number = 1;
479 			Note->EntriesNum++;
480 			Note->Entries[Note->EntriesNum].EntryType = CAL_REPEAT_DAY;
481 			Note->Entries[Note->EntriesNum].Number = Note->Entries[1].Date.Day;
482 			Note->EntriesNum++;
483 			break;
484 		case 4:
485 			Note->Entries[Note->EntriesNum].EntryType = CAL_REPEAT_FREQUENCY;
486 			Note->Entries[Note->EntriesNum].Number = 1;
487 			Note->EntriesNum++;
488 			Note->Entries[Note->EntriesNum].EntryType = CAL_REPEAT_DAY;
489 			Note->Entries[Note->EntriesNum].Number = Note->Entries[1].Date.Day;
490 			Note->EntriesNum++;
491 			break;
492 		case 5:
493 			Note->Entries[Note->EntriesNum].EntryType = CAL_REPEAT_FREQUENCY;
494 			Note->Entries[Note->EntriesNum].Number = 365;
495 			Note->EntriesNum++;
496 			break;
497 	}
498 	return error;
499 }
500 
MOTOROLA_ReplyGetCalendar(GSM_Protocol_Message * msg,GSM_StateMachine * s)501 GSM_Error MOTOROLA_ReplyGetCalendar(GSM_Protocol_Message *msg, GSM_StateMachine *s)
502 {
503 	GSM_Phone_ATGENData	*Priv = &s->Phone.Data.Priv.ATGEN;
504 	GSM_Error error;
505 	const char *line;
506 
507 	if (Priv->ReplyState != AT_Reply_OK) {
508 		switch (s->Phone.Data.Priv.ATGEN.ReplyState) {
509 		case AT_Reply_Error:
510 			return ERR_NOTSUPPORTED;
511 		case AT_Reply_CMSError:
512 			return ATGEN_HandleCMSError(s);
513 		case AT_Reply_CMEError:
514 			return ATGEN_HandleCMEError(s);
515 		default:
516 			return ERR_UNKNOWNRESPONSE;
517 		}
518 	}
519 
520 	line = GetLineString(msg->Buffer, &Priv->Lines, 2);
521 
522 	if (strcmp("OK", line) == 0) {
523 		return ERR_EMPTY;
524 	}
525 
526 	error = MOTOROLA_ParseCalendarSimple(s, line);
527 	if (error != ERR_NONE) {
528 		/* Fallback to parse complex later */
529 	}
530 	return error;
531 }
532 
MOTOROLA_GetNextCalendar(GSM_StateMachine * s,GSM_CalendarEntry * Note,gboolean start)533 GSM_Error MOTOROLA_GetNextCalendar(GSM_StateMachine *s, GSM_CalendarEntry *Note, gboolean start)
534 {
535 	GSM_Error error;
536 	GSM_Phone_ATGENData	*Priv = &s->Phone.Data.Priv.ATGEN;
537 	if (start) {
538 		/* One below actual first position */
539 		Note->Location = 0;
540 		error = MOTOROLA_GetCalendarStatus(s, &Priv->CalendarStatus);
541 		if (error != ERR_NONE) {
542 			return error;
543 		}
544 		Priv->CalendarRead = 0;
545 	}
546 	s->Phone.Data.Cal 	= Note;
547 	Note->EntriesNum 	= 0;
548 	smprintf(s, "Getting calendar entry\n");
549 	error = ERR_EMPTY;
550 	while (error == ERR_EMPTY) {
551 		Note->Location++;
552 		if (Note->Location >= Priv->CalendarStatus.Used + Priv->CalendarStatus.Free) {
553 			/* We're at the end */
554 			return ERR_EMPTY;
555 		}
556 		if (Priv->CalendarRead >= Priv->CalendarStatus.Used) {
557 			/* We've read all entries */
558 			return ERR_EMPTY;
559 		}
560 		error = MOTOROLA_GetCalendar(s, Note);
561 		if (error == ERR_NONE) {
562 			Priv->CalendarRead++;
563 		}
564 	}
565 	return error;
566 }
567 
MOTOROLA_GetCalendar(GSM_StateMachine * s,GSM_CalendarEntry * Note)568 GSM_Error MOTOROLA_GetCalendar(GSM_StateMachine *s, GSM_CalendarEntry *Note)
569 {
570 	char req[50];
571 	GSM_Error error;
572 	size_t len;
573 
574 	error = MOTOROLA_LockCalendar(s);
575 	if (error != ERR_NONE) return ERR_NONE;
576 
577 	s->Phone.Data.Cal = Note;
578 
579 	len = sprintf(req, "AT+MDBR=%d\r", Note->Location - 1);
580 
581 	error = ATGEN_WaitFor(s, req, len, 0x00, 10, ID_GetCalendarNote);
582 	MOTOROLA_UnlockCalendar(s);
583 	return error;
584 }
585 
MOTOROLA_ReplySetCalendar(GSM_Protocol_Message * msg,GSM_StateMachine * s)586 GSM_Error MOTOROLA_ReplySetCalendar(GSM_Protocol_Message *msg, GSM_StateMachine *s)
587 {
588 	return ERR_NOTIMPLEMENTED;
589 }
590 
MOTOROLA_DelCalendar(GSM_StateMachine * s,GSM_CalendarEntry * Note)591 GSM_Error MOTOROLA_DelCalendar(GSM_StateMachine *s, GSM_CalendarEntry *Note)
592 {
593 	char req[50];
594 	GSM_Error error;
595 	size_t len;
596 
597 	error = MOTOROLA_LockCalendar(s);
598 	if (error != ERR_NONE) return ERR_NONE;
599 
600 	len = sprintf(req, "AT+MDBWE=%d,0,0\r", Note->Location);
601 
602 	error = ATGEN_WaitFor(s, req, len, 0x00, 10, ID_DeleteCalendarNote);
603 	MOTOROLA_UnlockCalendar(s);
604 	return error;
605 }
606 
MOTOROLA_SetCalendar(GSM_StateMachine * s,GSM_CalendarEntry * Note)607 GSM_Error MOTOROLA_SetCalendar(GSM_StateMachine *s, GSM_CalendarEntry *Note)
608 {
609 	GSM_Error error;
610 
611 	error = MOTOROLA_LockCalendar(s);
612 	if (error != ERR_NONE) return ERR_NONE;
613 
614 	MOTOROLA_UnlockCalendar(s);
615 	return ERR_NOTIMPLEMENTED;
616 }
617 
MOTOROLA_AddCalendar(GSM_StateMachine * s,GSM_CalendarEntry * Note)618 GSM_Error MOTOROLA_AddCalendar(GSM_StateMachine *s, GSM_CalendarEntry *Note)
619 {
620 	GSM_Error error;
621 
622 	error = MOTOROLA_LockCalendar(s);
623 	if (error != ERR_NONE) return ERR_NONE;
624 
625 	MOTOROLA_UnlockCalendar(s);
626 	return ERR_NOTIMPLEMENTED;
627 }
628 
MOTOROLA_ReplyGetMPBRMemoryStatus(GSM_Protocol_Message * msg,GSM_StateMachine * s)629 GSM_Error MOTOROLA_ReplyGetMPBRMemoryStatus(GSM_Protocol_Message *msg, GSM_StateMachine *s)
630 {
631  	GSM_Phone_ATGENData *Priv = &s->Phone.Data.Priv.ATGEN;
632 
633  	switch (Priv->ReplyState) {
634  	case AT_Reply_OK:
635 		smprintf(s, "Memory status received\n");
636 		return ERR_NONE;
637 	case AT_Reply_Error:
638 		return ERR_UNKNOWN;
639 	case AT_Reply_CMSError:
640 	        return ATGEN_HandleCMSError(s);
641 	case AT_Reply_CMEError:
642 		return ATGEN_HandleCMEError(s);
643  	default:
644 		return ERR_UNKNOWNRESPONSE;
645 	}
646 }
647 
648 #endif
649 
650 /*@}*/
651 /*@}*/
652 
653 /* How should editor hadle tabs in this file? Add editor commands here.
654  * vim: noexpandtab sw=8 ts=8 sts=8:
655  */
656