Gammu internals  1.38.0
backlmb.c
Go to the documentation of this file.
1 /* (c) 2001-2004 by Marcin Wiacek */
2 
3 #include <string.h>
4 #include <ctype.h>
5 
6 #include <gammu-config.h>
7 
8 #include "../../phone/nokia/nfunc.h"
9 #include "../../misc/coding/coding.h"
10 #include "../gsmlogo.h"
11 #include "../gsmmisc.h"
12 #include "../../debug.h"
13 #include "backlmb.h"
14 #include "../../gsmphones.h"
15 
16 #ifdef GSM_ENABLE_BACKUP
17 
21 #define chk_fwrite(data, size, count, file) \
22  if (fwrite(data, size, count, file) != count) goto fail;
23 
24 static GSM_Error SaveLMBStartupEntry(FILE *file, GSM_Bitmap *bitmap)
25 {
26  size_t count = 13;
28  /* Welcome note and logo header block */
29  char req[1000] = {
30  'W','E','L',' ', /*block identifier*/
31  00,00, /*block data size*/
32  0x02,00,00,00,00,00,
33  0x00}; /*number of blocks (like in 6110 frame)*/
34 
35  if (bitmap->Type == GSM_StartupLogo) {
36  req[count++] = 0x01;
37  req[count++] = bitmap->BitmapHeight;
38  req[count++] = bitmap->BitmapWidth;
39  Type = GSM_NokiaStartupLogo;
40  switch (bitmap->BitmapHeight) {
41  case 65: Type = GSM_Nokia7110StartupLogo; break;
42  case 60: Type = GSM_Nokia6210StartupLogo; break;
43  }
44  PHONE_EncodeBitmap(Type, req+count, bitmap);
45  count = count + PHONE_GetBitmapSize(Type, 0, 0);
46 
47  req[12]++;
48  }
49  if (bitmap->Type == GSM_WelcomeNote_Text) {
50  req[count++]=0x02;
51  req[count++]=UnicodeLength(bitmap->Text);
52  memcpy(req+count,DecodeUnicodeString(bitmap->Text),UnicodeLength(bitmap->Text));
53  count=count+UnicodeLength(bitmap->Text);
54 
55  req[12]++;
56  }
57 
58  req[4]=(count-12)%256;
59  req[5]=(count-12)/256;
60 
61  chk_fwrite(req, 1, count, file);
62  return ERR_NONE;
63 fail:
64  return ERR_WRITING_FILE;
65 }
66 
67 static GSM_Error SaveLMBCallerEntry(FILE *file, GSM_Bitmap *bitmap)
68 {
69  size_t count = 12, textlen;
70  char req[500] = {
71  'C','G','R',' ', /*block identifier*/
72  00,00, /*block data size*/
73  02,00,
74  00, /*group number=0,1,etc.*/
75  00,00,00};
76 
77  req[count++] = bitmap->Location - 1;
78  if (bitmap->DefaultName) {
79  req[count++] = 0;
80  } else {
81  textlen = UnicodeLength(bitmap->Text);
82  req[count++] = textlen;
83  memcpy(req+count,DecodeUnicodeString(bitmap->Text),textlen);
84  count += textlen;
85  }
86  if (bitmap->DefaultRingtone) {
87  req[count++] = 0x16;
88  } else {
89  req[count++] = bitmap->RingtoneID;
90  }
91  if (bitmap->BitmapEnabled) req[count++] = 0x01; else req[count++] = 0x00;
92  req[count++] = (PHONE_GetBitmapSize(GSM_NokiaCallerLogo,0,0) + 4) >> 8;
93  req[count++] = (PHONE_GetBitmapSize(GSM_NokiaCallerLogo,0,0) + 4) % 0xff;
94  if (bitmap->DefaultBitmap) {
95  bitmap->BitmapWidth = 72;
96  bitmap->BitmapHeight = 14;
97  GSM_ClearBitmap(bitmap);
98  }
99  NOKIA_CopyBitmap(GSM_NokiaCallerLogo, bitmap, req, &count);
100  req[count++]=0;
101 
102  req[4]=(count-12)%256;
103  req[5]=(count-12)/256;
104  req[8]=bitmap->Location;
105 
106  chk_fwrite(req, 1, count, file);
107  return ERR_NONE;
108 fail:
109  return ERR_WRITING_FILE;
110 }
111 
112 GSM_Error SaveLMBPBKEntry(FILE *file, GSM_MemoryEntry *entry)
113 {
114  GSM_StateMachine *fake_sm;
115  size_t count = 16, blocks;
116  char req[500] = {
117  'P','B','E','2', /*block identifier*/
118  00,00, /*block data size*/
119  00,00,
120  00,00, /*position of phonebook entry*/
121  03, /*memory type. ME=02;SM=03*/
122  00,
123  00,00, /*position of phonebook entry*/
124  03, /*memory type. ME=02;SM=03*/
125  00};
126 
127  fake_sm = GSM_AllocStateMachine();
128  fake_sm->di.use_global = TRUE;
129  fake_sm->Phone.Data.ModelInfo = GetModelData(NULL, "unknown", NULL, NULL);
130 
131  count=count+N71_65_EncodePhonebookFrame(fake_sm, req+16, entry, &blocks, TRUE, TRUE);
132 
133  req[4]=(count-12)%256;
134  req[5]=(count-12)/256;
135  req[8]=req[12] = entry->Location & 0xff;
136  req[9]=req[13] = (entry->Location >> 8);
137  if (entry->MemoryType==MEM_ME) req[10]=req[14]=2;
138 
139  chk_fwrite(req, 1, count, file);
140  GSM_FreeStateMachine(fake_sm);
141  return ERR_NONE;
142 fail:
143  GSM_FreeStateMachine(fake_sm);
144  return ERR_WRITING_FILE;
145 }
146 
147 GSM_Error SaveLMB(const char *FileName, GSM_Backup *backup)
148 {
149  FILE *file;
150  int i;
151  char LMBHeader[] = {'L','M','B',' '}; /*file identifier*/
152  char PBKHeader[] = { /*Phonebook header block */
153  'P','B','K',' ', /*block identifier*/
154  0x08,00, /*block data size*/
155  0x02,00,
156  03, /*memory type. ME=02;SM=03*/
157  00,00,00,
158  00,00, /*size of phonebook*/
159  14, /*max length of each position*/
160  00,00,00,00,00};
161  GSM_Error error;
162 
163 
164  file = fopen(FileName, "wb");
165  if (file == NULL) return ERR_CANTOPENFILE;
166 
167  /* Write the header of the file. */
168  chk_fwrite(LMBHeader, 1, sizeof(LMBHeader), file);
169 
170  if (backup->PhonePhonebook[0]!=NULL) {
171  PBKHeader[8] = 2; /* memory type=MEM_ME */
172  PBKHeader[12] = (unsigned char)(500 % 256);
173  PBKHeader[13] = 500 / 256;
174  chk_fwrite(PBKHeader, 1, sizeof(PBKHeader), file);
175  i=0;
176  while (backup->PhonePhonebook[i]!=NULL) {
177  error = SaveLMBPBKEntry(file, backup->PhonePhonebook[i]);
178  if (error != ERR_NONE) {
179  fclose(file);
180  return error;
181  }
182  i++;
183  }
184  }
185  if (backup->SIMPhonebook[0]!=NULL) {
186  PBKHeader[8] = 3; /* memory type=MEM_SM */
187  PBKHeader[12] = (unsigned char)(250 % 256);
188  PBKHeader[13] = 250 / 256;
189  PBKHeader[14] = 0x16; /* max size of one entry */
190  chk_fwrite(PBKHeader, 1, sizeof(PBKHeader), file);
191  i=0;
192  while (backup->SIMPhonebook[i]!=NULL) {
193  error = SaveLMBPBKEntry(file, backup->SIMPhonebook[i]);
194  if (error != ERR_NONE) {
195  fclose(file);
196  return error;
197  }
198  i++;
199  }
200  }
201  i=0;
202  while (backup->CallerLogos[i]!=NULL) {
203  error = SaveLMBCallerEntry(file, backup->CallerLogos[i]);
204  if (error != ERR_NONE) {
205  fclose(file);
206  return error;
207  }
208  i++;
209  }
210  if (backup->StartupLogo!=NULL) {
211  error = SaveLMBStartupEntry(file, backup->StartupLogo);
212  if (error != ERR_NONE) {
213  fclose(file);
214  return error;
215  }
216  }
217 
218  fclose(file);
219  return ERR_NONE;
220 fail:
221  fclose(file);
222  return ERR_WRITING_FILE;
223 }
224 
225 static GSM_Error LoadLMBCallerEntry(unsigned char *buffer UNUSED, unsigned char *buffer2, GSM_Backup *backup)
226 {
227  GSM_Bitmap bitmap;
228  int num;
229 
230 #ifdef DEBUG
231  dbgprintf(NULL, "Number %i, name \"", buffer2[0]+1);
232  for (num=0;num<buffer2[1];num++) dbgprintf(NULL, "%c", buffer2[num+2]);
233  dbgprintf(NULL, "\"\n");
234  dbgprintf(NULL, "Ringtone ID=%i\n", buffer2[num+2]);
235  if (buffer2[num+3]==1) {
236  dbgprintf(NULL, "Logo enabled\n");
237  } else {
238  dbgprintf(NULL, "Logo disabled\n");
239  }
240 #endif
241 
242  bitmap.Location = buffer2[0] + 1;
243  bitmap.Type = GSM_CallerGroupLogo;
244  bitmap.DefaultRingtone = FALSE;
245  bitmap.RingtoneID = buffer2[buffer2[1]+2];
246  bitmap.FileSystemRingtone = FALSE;
247  bitmap.PictureID = 0;
248 
249  EncodeUnicode(bitmap.Text,buffer2+2,buffer2[1]);
250  if (bitmap.Text[0] == 0x00 && bitmap.Text[1] == 0x00) {
251  bitmap.DefaultName = TRUE;
252  } else {
253  bitmap.DefaultName = FALSE;
254  }
255 
256  bitmap.BitmapEnabled = FALSE;
257  if (buffer2[buffer2[1]+3]==1) bitmap.BitmapEnabled=TRUE;
258 
259  bitmap.DefaultBitmap = FALSE;
260  PHONE_DecodeBitmap(GSM_NokiaCallerLogo, buffer2+(buffer2[1]+10), &bitmap);
261 
262 #ifdef DEBUG
263  dbgprintf(NULL, "Caller logo\n");
266 #endif
267 
268  num = 0;
269  while (backup->CallerLogos[num] != NULL) num++;
270  if (num < GSM_BACKUP_MAX_CALLER) {
271  backup->CallerLogos[num] = (GSM_Bitmap *)malloc(sizeof(GSM_Bitmap));
272  if (backup->CallerLogos[num] == NULL) return ERR_MOREMEMORY;
273  backup->CallerLogos[num + 1] = NULL;
274  } else {
275  dbgprintf(NULL, "Increase GSM_BACKUP_MAX_CALLER\n");
276  return ERR_MOREMEMORY;
277  }
278  *backup->CallerLogos[num] = bitmap;
279 
280  return ERR_NONE;
281 }
282 
283 static GSM_Error LoadLMBStartupEntry(unsigned char *buffer UNUSED, unsigned char *buffer2, GSM_Backup *backup)
284 {
285  int i,j;
286 #ifdef DEBUG
287  int z;
288 #endif
290 
291  j=1;
292  for (i=0;i<buffer2[0];i++) {
293  switch (buffer2[j++]) {
294  case 1:
295  dbgprintf(NULL, "Block 1 - startup logo\n");
296  backup->StartupLogo = (GSM_Bitmap *)malloc(sizeof(GSM_Bitmap));
297  if (backup->StartupLogo == NULL) return ERR_MOREMEMORY;
298  backup->StartupLogo->Location = 1;
299  backup->StartupLogo->BitmapHeight = buffer2[j++];
300  backup->StartupLogo->BitmapWidth = buffer2[j++];
301  Type = GSM_NokiaStartupLogo;
302  switch (backup->StartupLogo->BitmapHeight) {
303  case 65: Type = GSM_Nokia7110StartupLogo; break;
304  case 60: Type = GSM_Nokia6210StartupLogo; break;
305  }
306  PHONE_DecodeBitmap(Type, buffer2+j, backup->StartupLogo);
307 #ifdef DEBUG
309  GSM_PrintBitmap(GSM_global_debug.df,backup->StartupLogo);
310 #endif
311  j = j + PHONE_GetBitmapSize(Type,0,0);
312  break;
313  case 2:
314 #ifdef DEBUG
315  dbgprintf(NULL, "Block 2 - welcome note \"");
316  for (z=0;z<buffer2[j];z++) dbgprintf(NULL, "%c",buffer2[j+z+1]);
317  dbgprintf(NULL, "\"\n");
318 #endif
319  if (backup->StartupLogo == NULL) {
320  backup->StartupLogo = (GSM_Bitmap *)malloc(sizeof(GSM_Bitmap));
321  if (backup->StartupLogo == NULL) return ERR_MOREMEMORY;
322  backup->StartupLogo->Type = GSM_WelcomeNote_Text;
323  EncodeUnicode(backup->StartupLogo->Text,buffer2+j,buffer2[j]);
324  }
325  j = j + buffer2[j];
326  break;
327  default:
328  dbgprintf(NULL, "Unknown block %02x\n",buffer2[j]);
329  break;
330  }
331  }
332  return ERR_NONE;
333 }
334 
335 static GSM_Error LoadLMBPbkEntry(unsigned char *buffer, unsigned char *buffer2, GSM_Backup *backup)
336 {
337  GSM_MemoryEntry pbk;
338  int num;
339  GSM_StateMachine *fake_sm;
340 
341  fake_sm = GSM_AllocStateMachine();
342  fake_sm->di.use_global = TRUE;
343  fake_sm->Phone.Data.ModelInfo = GetModelData(NULL, "unknown", NULL, NULL);
344 
345  dbgprintf(NULL, "Memory : ");
346  switch(buffer[10]) {
347  case 2 :
348  dbgprintf(NULL, "(internal)\n");
349  pbk.MemoryType = MEM_ME;
350  break;
351  case 3 :
352  dbgprintf(NULL, "(sim)\n");
353  pbk.MemoryType = MEM_SM;
354  break;
355  default:
356  dbgprintf(NULL, "(unknown)\n");
357  pbk.MemoryType = 0;
358  break;
359  }
360  pbk.Location = buffer2[0] + buffer2[1] * 256;
361  dbgprintf(NULL, "Location : %i\n", pbk.Location);
362 
363  N71_65_DecodePhonebook(fake_sm, &pbk, NULL,NULL,buffer2+4,(buffer[4]+buffer[5]*256)-4,FALSE);
364 
365  pbk.MemoryType=MEM_SM;
366  if (buffer[10]==2) pbk.MemoryType=MEM_ME;
367 
368  pbk.Location=buffer2[0]+256*buffer2[1];
369 
370  num = 0;
371  if (buffer[10]==2) {
372  while (backup->PhonePhonebook[num] != NULL) num++;
373  if (num < GSM_BACKUP_MAX_PHONEPHONEBOOK) {
374  backup->PhonePhonebook[num] = (GSM_MemoryEntry *)malloc(sizeof(GSM_MemoryEntry));
375  if (backup->PhonePhonebook[num] == NULL) {
376  GSM_FreeStateMachine(fake_sm);
377  return ERR_MOREMEMORY;
378  }
379  backup->PhonePhonebook[num + 1] = NULL;
380  } else {
381  GSM_FreeStateMachine(fake_sm);
382  dbgprintf(NULL, "Increase GSM_BACKUP_MAX_PHONEPHONEBOOK\n");
383  return ERR_MOREMEMORY;
384  }
385  *backup->PhonePhonebook[num] = pbk;
386  } else {
387  while (backup->SIMPhonebook[num] != NULL) num++;
388  if (num < GSM_BACKUP_MAX_SIMPHONEBOOK) {
389  backup->SIMPhonebook[num] = (GSM_MemoryEntry *)malloc(sizeof(GSM_MemoryEntry));
390  if (backup->SIMPhonebook[num] == NULL) {
391  GSM_FreeStateMachine(fake_sm);
392  return ERR_MOREMEMORY;
393  }
394  backup->SIMPhonebook[num + 1] = NULL;
395  } else {
396  dbgprintf(NULL, "Increase GSM_BACKUP_MAX_SIMPHONEBOOK\n");
397  GSM_FreeStateMachine(fake_sm);
398  return ERR_MOREMEMORY;
399  }
400  *backup->SIMPhonebook[num] = pbk;
401  }
402  GSM_FreeStateMachine(fake_sm);
403  return ERR_NONE;
404 }
405 
406 GSM_Error LoadLMB(const char *FileName, GSM_Backup *backup)
407 {
408 #ifdef DEBUG
409  int i;
410 #endif
411  unsigned char buffer[12], buffer2[1000];
412  FILE *file;
413  GSM_Error error;
414  size_t blocksize;
415 
416  file = fopen(FileName, "rb");
417  if (file == NULL) return(ERR_CANTOPENFILE);
418 
419  /* Read the header of the file. */
420  if (fread(buffer, 1, 4, file) != 4) {
421  fclose(file);
422  return ERR_FILENOTSUPPORTED;
423  }
424 
425  /* while we have something to read */
426  while (fread(buffer, 1, 12, file) == 12) {
427 #ifdef DEBUG
428  /* Info about block in the file */
429  dbgprintf(NULL, "Block \"");
430  for (i=0;i<4;i++) {dbgprintf(NULL, "%c",buffer[i]);}
431  dbgprintf(NULL, "\" (");
432  if (memcmp(buffer, "PBK ",4)==0) { dbgprintf(NULL, "Phonebook");
433  } else if (memcmp(buffer, "PBE2",4)==0) { dbgprintf(NULL, "Phonebook entry");
434  } else if (memcmp(buffer, "CGR ",4)==0) { dbgprintf(NULL, "Caller group");
435  } else if (memcmp(buffer, "SPD ",4)==0) { dbgprintf(NULL, "Speed dial");
436  } else if (memcmp(buffer, "OLG ",4)==0) { dbgprintf(NULL, "Operator logo");
437  } else if (memcmp(buffer, "WEL ",4)==0) { dbgprintf(NULL, "Startup logo and welcome text");
438  } else { dbgprintf(NULL, "unknown - ignored");
439  }
440  dbgprintf(NULL, ") - length %i\n", buffer[4]+buffer[5]*256);
441 #endif
442  /* reading block data */
443  blocksize = buffer[4] + buffer[5] * 256;
444  if (blocksize > sizeof(buffer2)) {
445  dbgprintf(NULL, "Too big block size!\n");
446  fclose(file);
447  return ERR_MOREMEMORY;
448  }
449  if (fread(buffer2, 1, blocksize, file) != blocksize) {
450  fclose(file);
451  return ERR_FILENOTSUPPORTED;
452  }
453 
454 #ifdef DEBUG
455  if (memcmp(buffer, "PBK ",4)==0) {
456  dbgprintf(NULL, "Size of phonebook %i, type %i ",(buffer2[0]+buffer2[1]*256),buffer[8]);
457  switch(buffer[8]) {
458  case 2 : dbgprintf(NULL, "(internal)");break;
459  case 3 : dbgprintf(NULL, "(sim)") ;break;
460  default: dbgprintf(NULL, "(unknown)") ;break;
461  }
462  dbgprintf(NULL, ", length of each position - %i\n",buffer2[2]);
463  }
464 #endif
465  if (memcmp(buffer, "PBE2",4)==0) {
466  error = LoadLMBPbkEntry(buffer,buffer2,backup);
467  if (error != ERR_NONE) {
468  fclose(file);
469  return error;
470  }
471  }
472  if (memcmp(buffer, "CGR ",4)==0) {
473  error = LoadLMBCallerEntry(buffer, buffer2, backup);
474  if (error != ERR_NONE) {
475  fclose(file);
476  return error;
477  }
478  }
479  if (memcmp(buffer, "WEL ",4)==0) {
480  error = LoadLMBStartupEntry(buffer, buffer2, backup);
481  if (error != ERR_NONE) {
482  fclose(file);
483  return error;
484  }
485  }
486  }
487 
488  fclose(file);
489 
490  return ERR_NONE;
491 }
492 
493 #endif
494 
495 /* How should editor hadle tabs in this file? Add editor commands here.
496  * vim: noexpandtab sw=8 ts=8 sts=8:
497  */
gboolean DefaultRingtone
Definition: gammu-bitmap.h:134
char * DecodeUnicodeString(const unsigned char *src)
Definition: coding.c:245
size_t PHONE_GetBitmapSize(GSM_Phone_Bitmap_Types Type, size_t Width, size_t Height)
Definition: gsmlogo.c:44
GSM_StateMachine * GSM_AllocStateMachine(void)
Definition: gsmstate.c:1677
GSM_MemoryType MemoryType
Definition: gammu-memory.h:415
gboolean FileSystemRingtone
Definition: gammu-bitmap.h:139
GSM_Bitmap_Types Type
Definition: gammu-bitmap.h:107
GSM_Error
Definition: gammu-error.h:23
void PHONE_EncodeBitmap(GSM_Phone_Bitmap_Types Type, char *buffer, GSM_Bitmap *Bitmap)
Definition: gsmlogo.c:197
FILE * df
Definition: debug.h:36
GSM_Debug_Info di
Definition: gsmstate.h:1412
size_t UnicodeLength(const unsigned char *str)
Definition: coding.c:186
void PHONE_DecodeBitmap(GSM_Phone_Bitmap_Types Type, char *buffer, GSM_Bitmap *Bitmap)
Definition: gsmlogo.c:141
unsigned char Location
Definition: gammu-bitmap.h:112
GSM_Phone_Bitmap_Types
Definition: gsmlogo.h:9
#define chk_fwrite(data, size, count, file)
Definition: gsmlogo.c:20
GSM_PhoneModel * ModelInfo
Definition: gsmstate.h:449
void NOKIA_CopyBitmap(GSM_Phone_Bitmap_Types Type, GSM_Bitmap *Bitmap, char *Buffer, size_t *Length)
Definition: gsmlogo.c:1132
unsigned char RingtoneID
Definition: gammu-bitmap.h:138
void GSM_PrintBitmap(FILE *file, GSM_Bitmap *bitmap)
Definition: gsmlogo.c:257
GSM_Debug_Info GSM_global_debug
Definition: debug.c:33
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
GSM_Phone Phone
Definition: gsmstate.h:1431
#define FALSE
Definition: gammu-types.h:25
GSM_Error N71_65_DecodePhonebook(GSM_StateMachine *s, GSM_MemoryEntry *entry, GSM_Bitmap *bitmap, GSM_SpeedDial *speed, unsigned char *MessageBuffer, int MessageLength, gboolean DayMonthReverse)
Definition: nfunc.c:364
gboolean BitmapEnabled
Definition: gammu-bitmap.h:122
gboolean DefaultBitmap
Definition: gammu-bitmap.h:130
gboolean use_global
Definition: debug.h:37
GSM_Phone_Data Data
Definition: gsmstate.h:1369
#define dbgprintf
Definition: debug.h:72
void GSM_ClearBitmap(GSM_Bitmap *bmp)
Definition: gsmlogo.c:247
size_t N71_65_EncodePhonebookFrame(GSM_StateMachine *s, unsigned char *req, GSM_MemoryEntry *entry, size_t *block2, gboolean DCT4, gboolean VoiceTag)
Definition: nfunc.c:54
gboolean DefaultName
Definition: gammu-bitmap.h:126
size_t BitmapHeight
Definition: gammu-bitmap.h:152
size_t BitmapWidth
Definition: gammu-bitmap.h:156
unsigned char Text[2 *(GSM_BITMAP_TEXT_LENGTH+1)]
Definition: gammu-bitmap.h:118
#define TRUE
Definition: gammu-types.h:28
#define UNUSED
Definition: gammu-misc.h:105
void GSM_FreeStateMachine(GSM_StateMachine *s)
Definition: gsmstate.c:1689
Debug_Level dl
Definition: debug.h:35