Gammu internals  1.38.0
6510file.c
Go to the documentation of this file.
1 /* (c) 2003-2006 by Marcin Wiacek */
2 /* function for making CRC for filesystem (c) 2003 by Michael Schroeder */
3 
4 #include <gammu-config.h>
5 
6 #ifdef GSM_ENABLE_NOKIA6510
7 
8 #include <string.h>
9 #include <time.h>
10 
11 #include "../../../../misc/coding/coding.h"
12 #include "../../../../gsmcomon.h"
13 #include "../../../../service/gsmlogo.h"
14 #include "../../nfunc.h"
15 #include "../../nfuncold.h"
16 #include "../../../pfunc.h"
17 #include "../dct4func.h"
18 #include "n6510.h"
19 #include "../../../../../helper/string.h"
20 
21 /* shared */
22 
30 static GSM_Error N6510_ShiftFileCache(GSM_StateMachine *s, int move)
31 {
32  GSM_Phone_N6510Data *Priv = &s->Phone.Data.Priv.N6510;
33  int i;
34 
35  if (move < 0) {
36  for (i = 0; i < Priv->FilesLocationsUsed + move; i++) {
37  memcpy(&Priv->FilesCache[i], &Priv->FilesCache[i - move], sizeof(GSM_File));
38  smprintf(s, "Copying %i to %i\n", i - move, i);
39  }
40  } else {
41  for (i = Priv->FilesLocationsUsed - 1; i >= 0; i--) {
42  memcpy(&Priv->FilesCache[i + move], &Priv->FilesCache[i], sizeof(GSM_File));
43  smprintf(s, "Copying %i to %i\n", i, i + move);
44  }
45  }
46 
47  Priv->FilesLocationsUsed += move;
48 
49  return ERR_NONE;
50 }
56 static GSM_Error N6510_AllocFileCache(GSM_StateMachine *s, int requested)
57 {
58  GSM_Phone_N6510Data *Priv = &s->Phone.Data.Priv.N6510;
59  int newsize;
60 
61  /* Maybe there is already enough allocated */
62  if (Priv->FilesLocationsAvail >= requested) return ERR_NONE;
63 
64  /* Do not allocate one by one */
65  newsize = requested + 10;
66 
67  /* Reallocate memory */
68  Priv->FilesCache = (GSM_File *)realloc(Priv->FilesCache, newsize * sizeof(GSM_File));
69  if (Priv->FilesCache == NULL) return ERR_MOREMEMORY;
70 
71  /* Store new cache size */
72  Priv->FilesLocationsAvail = newsize;
73 
74  return ERR_NONE;
75 }
76 
77 static int N6510_FindFileCheckSum12(GSM_StateMachine *s, unsigned char *ptr, int len)
78 {
79  int acc, i, accx;
80 
81  accx = 0;
82  acc = 0xffff;
83  while (len--) {
84  accx = (accx & 0xffff00ff) | (acc & 0xff00);
85  acc = (acc & 0xffff00ff) | (*ptr++ << 8);
86  for (i = 0; i < 8; i++) {
87  acc <<= 1;
88  if (acc & 0x10000) acc ^= 0x1021;
89  if (accx & 0x80000000) acc ^= 0x1021;
90  accx <<= 1;
91  }
92  }
93  smprintf(s, "Checksum from Gammu is %04X\n",(acc & 0xffff));
94  return (acc & 0xffff);
95 }
96 
98 {
99  int old;
100 
101  smprintf(s,"File part received\n");
102  old = s->Phone.Data.File->Used;
103  s->Phone.Data.File->Used += msg->Buffer[6]*256*256*256+
104  msg->Buffer[7]*256*256+
105  msg->Buffer[8]*256+
106  msg->Buffer[9];
107  smprintf(s,"Length of file part: %i\n",
108  msg->Buffer[6]*256*256*256+
109  msg->Buffer[7]*256*256+
110  msg->Buffer[8]*256+
111  msg->Buffer[9]);
112  s->Phone.Data.File->Buffer = (unsigned char *)realloc(s->Phone.Data.File->Buffer,s->Phone.Data.File->Used);
113  memcpy(s->Phone.Data.File->Buffer+old,msg->Buffer+10,s->Phone.Data.File->Used-old);
114  return ERR_NONE;
115 }
116 
118 {
119  GSM_Phone_N6510Data *Priv = &s->Phone.Data.Priv.N6510;
120 
121  Priv->FileCheckSum = msg->Buffer[6] * 256 + msg->Buffer[7];
122  smprintf(s,"File checksum from phone is %04X\n",Priv->FileCheckSum);
123  return ERR_NONE;
124 }
125 
126 /* filesystem 1 */
127 
128 static GSM_Error N6510_GetFileCRC1(GSM_StateMachine *s, unsigned char *id)
129 {
130  unsigned char GetCRC[] = {
131  N7110_FRAME_HEADER, 0x42, 0x00, 0x00, 0x00, 0x01,
132  0x00, 0x1E}; /* file ID */
133 
134  GetCRC[8] = atoi(DecodeUnicodeString(id)) / 256;
135  GetCRC[9] = atoi(DecodeUnicodeString(id)) % 256;
136  smprintf(s,"Getting CRC for file in filesystem\n");
137  return GSM_WaitFor (s, GetCRC, 10, 0x6D, 4, ID_GetCRC);
138 }
139 
141 {
142  GSM_File *File = s->Phone.Data.FileInfo;
143  GSM_Phone_N6510Data *Priv = &s->Phone.Data.Priv.N6510;
144  int i, newsize;
145  unsigned char buffer[500];
146  GSM_Error error;
147 
148  switch (msg->Buffer[3]) {
149  case 0x15:
150  smprintf(s,"File or folder details received\n");
151  CopyUnicodeString(File->Name,msg->Buffer+10);
152  if (msg->Length == 14) {
153  smprintf(s,"File not exist\n");
154  return ERR_FILENOTEXIST;
155  }
156  if (!strncmp(DecodeUnicodeString(File->Name),"GMSTemp",7)) return ERR_EMPTY;
157  if (File->Name[0] == 0x00 && File->Name[1] == 0x00) return ERR_UNKNOWN;
158 
159 /* EncodeHexUnicode (buffer, File->Name, UnicodeLength(File->Name)); */
160 /* smprintf(s,"Name encoded: %s\n",buffer); */
161 
162  i = msg->Buffer[8]*256+msg->Buffer[9];
163  smprintf(s, "%02x %02x %02x %02x %02x %02x %02x %02x %02x\n",
164  msg->Buffer[i-5],msg->Buffer[i-4],msg->Buffer[i-3],
165  msg->Buffer[i-2],msg->Buffer[i-1],msg->Buffer[i],
166  msg->Buffer[i+1],msg->Buffer[i+2],msg->Buffer[i+3]);
167 
168  File->Folder = FALSE;
169  if (msg->Buffer[i-5] == 0x00 && msg->Buffer[i-3]==0x02) File->Folder = TRUE;
170 
171  File->ReadOnly = FALSE;
172  File->Protected = FALSE;
173  File->System = FALSE;
174  File->Hidden = FALSE;
175  if (msg->Buffer[i+2] == 0x01) File->Protected = TRUE;
176  if (msg->Buffer[i+4] == 0x01) File->ReadOnly = TRUE;
177  if (msg->Buffer[i+5] == 0x01) File->Hidden = TRUE;
178  if (msg->Buffer[i+6] == 0x01) File->System = TRUE;/* fixme */
179 
180  File->ModifiedEmpty = FALSE;
181  NOKIA_DecodeDateTime(s, msg->Buffer+i-22, &File->Modified, TRUE, FALSE);
182  if (File->Modified.Year == 0x00) File->ModifiedEmpty = TRUE;
183  if (File->Modified.Year == 0xffff) File->ModifiedEmpty = TRUE;
184  smprintf(s, "%02x %02x %02x %02x\n",msg->Buffer[i-22],msg->Buffer[i-21],msg->Buffer[i-20],msg->Buffer[i-19]);
185 
186  Priv->FileToken = msg->Buffer[i-10]*256+msg->Buffer[i-9];
187  Priv->ParentID = msg->Buffer[i]*256+msg->Buffer[i+1];
188  smprintf(s,"ParentID is %i\n",Priv->ParentID);
189 
190  File->Type = GSM_File_Other;
191  if (msg->Length > 240){
192  i = 227;
193  if (msg->Buffer[i]==0x02 && msg->Buffer[i+2]==0x01)
194  File->Type = GSM_File_Image_JPG;
195  else if (msg->Buffer[i]==0x02 && msg->Buffer[i+2]==0x02)
196  File->Type = GSM_File_Image_BMP;
197  else if (msg->Buffer[i]==0x02 && msg->Buffer[i+2]==0x07)
198  File->Type = GSM_File_Image_BMP;
199  else if (msg->Buffer[i]==0x02 && msg->Buffer[i+2]==0x03)
200  File->Type = GSM_File_Image_PNG;
201  else if (msg->Buffer[i]==0x02 && msg->Buffer[i+2]==0x05)
202  File->Type = GSM_File_Image_GIF;
203  else if (msg->Buffer[i]==0x02 && msg->Buffer[i+2]==0x09)
204  File->Type = GSM_File_Image_WBMP;
205  else if (msg->Buffer[i]==0x04 && msg->Buffer[i+2]==0x01)
206  File->Type = GSM_File_Sound_AMR;
207  else if (msg->Buffer[i]==0x04 && msg->Buffer[i+2]==0x02)
208  File->Type = GSM_File_Sound_MIDI;
209  else if (msg->Buffer[i]==0x08 && msg->Buffer[i+2]==0x05)
210  File->Type = GSM_File_Video_3GP;
211  else if (msg->Buffer[i]==0x10 && msg->Buffer[i+2]==0x01)
212  File->Type = GSM_File_Java_JAR;
213  else if (msg->Buffer[i]==0x00 && msg->Buffer[i+2]==0x01)
214  File->Type = GSM_File_MMS;
215  }
216  return ERR_NONE;
217  case 0x2F:
218  smprintf(s,"File or folder used bytes received\n");
219  File->Used = msg->Buffer[6]*256*256*256+
220  msg->Buffer[7]*256*256+
221  msg->Buffer[8]*256+
222  msg->Buffer[9];
223  return ERR_NONE;
224  case 0x33:
225  if (s->Phone.Data.RequestID == ID_GetFileInfo) {
226 
227  newsize = msg->Buffer[8] * 256 + msg->Buffer[9];
228 
229  error = N6510_AllocFileCache(s, Priv->FilesLocationsUsed + newsize);
230  if (error != ERR_NONE) return error;
231 
232  error = N6510_ShiftFileCache(s, newsize);
233  if (error != ERR_NONE) return error;
234 
235  for (i = 0; i < newsize; i++) {
236  sprintf(buffer,"%i",msg->Buffer[13+i*4-1]*256 + msg->Buffer[13+i*4]);
237  EncodeUnicode(Priv->FilesCache[i].ID_FullName,buffer,strlen(buffer));
238  Priv->FilesCache[i].Level = File->Level+1;
240  }
241  smprintf(s, "\n");
242  }
243  if ((msg->Buffer[8]*256+msg->Buffer[9]) != 0x00) File->Folder = TRUE;
244  return ERR_NONE;
245  case 0xf0:
246  smprintf(s, "File system is not supported\n");
247  return ERR_NOTSUPPORTED;
248  }
249  return ERR_UNKNOWNRESPONSE;
250 }
251 
252 static GSM_Error N6510_GetFileFolderInfo1(GSM_StateMachine *s, GSM_File *File, gboolean full)
253 {
254  GSM_Error error;
255  unsigned char req[10] = {
257  0x14, /* 0x14 - info, 0x22 - free/total, 0x2E - used, 0x32 - sublocations */
258  0x01, /* 0x00 for sublocations reverse sorting, 0x01 for free */
259  0x00, 0x00, 0x01,
260  0x00, 0x01}; /* Folder or file number */
261 
262  s->Phone.Data.FileInfo = File;
263  req[8] = atoi(DecodeUnicodeString(File->ID_FullName)) / 256;
264  req[9] = atoi(DecodeUnicodeString(File->ID_FullName)) % 256;
265 
266  req[3] = 0x14;
267  req[4] = 0x01;
268  smprintf(s,"Getting info for file in filesystem\n");
269  error=GSM_WaitFor (s, req, 10, 0x6D, 4, ID_GetFileInfo);
270  if (error != ERR_NONE) return error;
271 
272  if (full) {
273  req[3] = 0x32;
274  req[4] = 0x00;
275  smprintf(s,"Getting subfolders for filesystem\n");
276  error=GSM_WaitFor (s, req, 10, 0x6D, 4, ID_GetFileInfo);
277  if (error != ERR_NONE) return error;
278  }
279 
280  if (!File->Folder) {
281  req[3] = 0x2E;
282  req[4] = 0x01;
283  smprintf(s,"Getting used memory for file in filesystem\n");
284  return GSM_WaitFor (s, req, 10, 0x6D, 4, ID_GetFileInfo);
285  }
286 
287  return error;
288 }
289 
290 static GSM_Error N6510_GetNextFileFolder1(GSM_StateMachine *s, GSM_File *File, gboolean start)
291 {
292  GSM_Phone_N6510Data *Priv = &s->Phone.Data.Priv.N6510;
293  GSM_Error error;
294  unsigned char buffer[5];
295 
296  if (start) {
297  error = N6510_AllocFileCache(s, 1);
298  if (error != ERR_NONE) return error;
299 
300  Priv->FilesLocationsUsed = 1;
301 
302  sprintf(buffer,"%i",0x01);
303  EncodeUnicode(Priv->FilesCache[0].ID_FullName,buffer,strlen(buffer));
304  Priv->FilesCache[0].Level = 1;
305  }
306 
307  while (1) {
308  if (Priv->FilesLocationsUsed == 0) return ERR_EMPTY;
309 
311  File->Level = Priv->FilesCache[0].Level;
312 
313  error = N6510_ShiftFileCache(s, -1);
314  if (error != ERR_NONE) return error;
315 
316  error = N6510_GetFileFolderInfo1(s, File, TRUE);
317  if (error == ERR_EMPTY) continue;
318  return error;
319  }
320 }
321 
323 {
324  switch (msg->Buffer[3]) {
325  case 0x23:
326  if (!strcmp(s->Phone.Data.ModelInfo->model,"6310i")) {
327  smprintf(s,"File or folder total bytes received\n");
329  3*256*256 + msg->Buffer[8]*256 + msg->Buffer[9] -
331  } else {
332  smprintf(s,"File or folder free bytes received\n");
334  msg->Buffer[6]*256*256*256+
335  msg->Buffer[7]*256*256+
336  msg->Buffer[8]*256+
337  msg->Buffer[9];
338  }
339  return ERR_NONE;
340  case 0x2F:
341  smprintf(s,"File or folder used bytes received\n");
343  msg->Buffer[6]*256*256*256+
344  msg->Buffer[7]*256*256+
345  msg->Buffer[8]*256+
346  msg->Buffer[9];
347  return ERR_NONE;
348  }
349  return ERR_UNKNOWNRESPONSE;
350 }
351 
352 static GSM_Error N6510_GetFileSystemStatus1(GSM_StateMachine *s, GSM_FileSystemStatus *status)
353 {
354  GSM_Error error;
355  unsigned char req[10] = {
357  0x22, /* 0x14 - info, 0x22 - free/total, 0x2E - used, 0x32 - sublocations */
358  0x01, /* 0x00 for sublocations reverse sorting, 0x01 for free */
359  0x00, 0x00, 0x01,
360  0x00, 0x01}; /* Folder or file number */
361 
362  /* Used memory by types */
363  status->UsedImages = 0;
364  status->UsedSounds = 0;
365  status->UsedThemes = 0;
366  s->Phone.Data.FileSystemStatus = status;
367 
368  status->Free = 0;
369 
370  req[3] = 0x2E;
371  req[4] = 0x01;
372  smprintf(s, "Getting used/total memory in filesystem\n");
373  error = GSM_WaitFor (s, req, 10, 0x6D, 4, ID_FileSystemStatus);
374  if (error != ERR_NONE) return error;
375 
376  req[3] = 0x22;
377  req[4] = 0x01;
378  smprintf(s, "Getting free memory in filesystem\n");
379  return GSM_WaitFor (s, req, 10, 0x6D, 4, ID_FileSystemStatus);
380 }
381 
382 static GSM_Error N6510_GetFilePart1(GSM_StateMachine *s, GSM_File *File, int *Handle UNUSED, size_t *Size)
383 {
384  GSM_Phone_N6510Data *Priv = &s->Phone.Data.Priv.N6510;
385  int old;
386  GSM_Error error;
387  unsigned char req[] = {
388  N7110_FRAME_HEADER, 0x0E, 0x00, 0x00, 0x00, 0x01,
389  0x00, 0x01, /* Folder or file number */
390  0x00, 0x00, 0x00, 0x00, /* Start from xxx byte */
391  0x00, 0x00,
392  0x03, 0xE8}; /* Read xxx bytes */
393 
394  if (File->Used == 0x00) {
395  error = N6510_GetFileFolderInfo1(s, File, FALSE);
396  if (error != ERR_NONE) return error;
397 
398  if (File->Folder) return ERR_SHOULDBEFILE;
399 
400  (*Size) = File->Used;
401  File->Used = 0;
402  }
403 
404  old = File->Used;
405  req[8] = atoi(DecodeUnicodeString(File->ID_FullName)) / 256;
406  req[9] = atoi(DecodeUnicodeString(File->ID_FullName)) % 256;
407  req[10] = old / (256*256*256);
408  req[11] = old / (256*256);
409  req[12] = old / 256;
410  req[13] = old % 256;
411 
412  s->Phone.Data.File = File;
413  smprintf(s, "Getting file part from filesystem\n");
414  error=GSM_WaitFor (s, req, 18, 0x6D, 4, ID_GetFile);
415  if (error != ERR_NONE) return error;
416  if (File->Used - old != (0x03 * 256 + 0xE8)) {
417  error = N6510_GetFileCRC1(s, File->ID_FullName);
418  if (error != ERR_NONE) return error;
419 
420  if (N6510_FindFileCheckSum12(s, File->Buffer, File->Used) != Priv->FileCheckSum) {
421  smprintf(s,"File2 checksum is %i, File checksum is %i\n",N6510_FindFileCheckSum12(s, File->Buffer, File->Used),Priv->FileCheckSum);
422  return ERR_WRONGCRC;
423  }
424  return ERR_EMPTY;
425  }
426  return ERR_NONE;
427 }
428 
429 static GSM_Error N6510_SetReadOnly1(GSM_StateMachine *s, unsigned char *ID, gboolean enable)
430 {
431  unsigned char SetAttr[] = {
432  N7110_FRAME_HEADER, 0x18,
433  0x00, /* state */
434  0x00, 0x00, 0x01,
435  0x00, 0x20}; /* File ID */
436 
437  if (!enable) SetAttr[4] = 0x06;
438 
439  SetAttr[8] = atoi(DecodeUnicodeString(ID)) / 256;
440  SetAttr[9] = atoi(DecodeUnicodeString(ID)) % 256;
441  smprintf(s, "Setting readonly attribute\n");
442  return GSM_WaitFor (s, SetAttr, 10, 0x6D, 4, ID_SetAttrib);
443 }
444 
445 static GSM_Error N6510_SetFileAttributes1(GSM_StateMachine *s, GSM_File *File)
446 {
447  GSM_Error error;
448  GSM_File file2;
449 
450  memset(&file2, 0, sizeof(file2));
451 
453  error = N6510_GetFileFolderInfo1(s, &file2, FALSE);
454  if (error != ERR_NONE) return error;
455 
456  /* setting folder attrib works, but we block it */
457  if (file2.Folder) return ERR_SHOULDBEFILE;
458 
459  /* todo */
460  if (file2.System != File->System ||
461  file2.Hidden != File->Hidden ||
462  file2.Protected != File->Protected) {
463  return ERR_NOTSUPPORTED;
464  }
465 
466  return N6510_SetReadOnly1(s, File->ID_FullName, File->ReadOnly);
467 }
468 
469 /* function checks if there is file/folder with searched name in folder with specified ID */
470 static GSM_Error N6510_SearchForFileName1(GSM_StateMachine *s, GSM_File *File)
471 {
472  GSM_Error error;
473  GSM_File *BackupCache, *NewFiles;
474  int FilesLocationsUsed,FilesLocationsUsed2,i;
475  GSM_Phone_N6510Data *Priv = &s->Phone.Data.Priv.N6510;
476 
477  File->Folder = FALSE;
478 
479  /* making backup */
480  BackupCache = (GSM_File *)malloc(sizeof(GSM_File) * Priv->FilesLocationsUsed);
481  if (BackupCache == NULL) return ERR_MOREMEMORY;
482  memcpy(BackupCache, Priv->FilesCache, sizeof(GSM_File) * Priv->FilesLocationsUsed);
483  FilesLocationsUsed = Priv->FilesLocationsUsed;
484 
485  /* Allocate new cache */
486  error = N6510_AllocFileCache(s, 1);
487  if (error != ERR_NONE) {
488  free(BackupCache);
489  return error;
490  }
491 
492  /* putting own data */
493  Priv->FilesCache[0].Level = 1;
494  Priv->FilesLocationsUsed = 1;
496 
497  /* checking */
498  error = N6510_GetFileFolderInfo1(s, &Priv->FilesCache[0], TRUE);
499 
500  /* backuping new data */
501  NewFiles = (GSM_File *)malloc(sizeof(GSM_File) * Priv->FilesLocationsUsed);
502  if (NewFiles == NULL) {
503  free(BackupCache);
504  BackupCache=NULL;
505  return ERR_MOREMEMORY;
506  }
507  memcpy(NewFiles, Priv->FilesCache, sizeof(GSM_File) * Priv->FilesLocationsUsed);
508  FilesLocationsUsed2 = Priv->FilesLocationsUsed;
509 
510  /* restoring */
511  memcpy(Priv->FilesCache, BackupCache, sizeof(GSM_File) * FilesLocationsUsed);
512  free(BackupCache);
513  BackupCache=NULL;
514  Priv->FilesLocationsUsed = FilesLocationsUsed;
515 
516  if (error != ERR_NONE) {
517  free(NewFiles);
518  NewFiles=NULL;
519  return error;
520  }
521 
522  for (i = 0; i < FilesLocationsUsed2; i++) {
523  smprintf(s, "ID is %s\n",DecodeUnicodeString(NewFiles[i].ID_FullName));
524  error = N6510_GetFileFolderInfo1(s, &NewFiles[i], FALSE);
525  if (error == ERR_EMPTY) continue;
526  if (error != ERR_NONE) {
527  free(NewFiles);
528  NewFiles=NULL;
529  return error;
530  }
531  smprintf(s, "%s",DecodeUnicodeString(File->Name));
532  smprintf(s, "%s \n",DecodeUnicodeString(NewFiles[i].Name));
533  if (mywstrncasecmp(NewFiles[i].Name,File->Name,0)) {
534  smprintf(s, "the same\n");
535  File->Folder = NewFiles[i].Folder;
536  free(NewFiles);
537  NewFiles=NULL;
538  return ERR_NONE;
539  }
540  }
541  free(NewFiles);
542  NewFiles=NULL;
543  return ERR_EMPTY;
544 }
545 
547 {
548  unsigned char buffer[5];
549 
550  switch (msg->Buffer[3]) {
551  case 0x03:
552  smprintf(s,"File header added\n");
553  sprintf(buffer,"%i",msg->Buffer[8]*256+msg->Buffer[9]);
554  EncodeUnicode(s->Phone.Data.File->ID_FullName,buffer,strlen(buffer));
555  return ERR_NONE;
556  case 0x13:
557  return ERR_NONE;
558  }
559  return ERR_UNKNOWNRESPONSE;
560 }
561 
563 {
564  return ERR_NONE;
565 }
566 
567 static GSM_Error N6510_AddFilePart1(GSM_StateMachine *s, GSM_File *File, size_t *Pos, int *Handle UNUSED)
568 {
569  GSM_Phone_N6510Data *Priv = &s->Phone.Data.Priv.N6510;
570  GSM_File File2;
571  GSM_Error error;
572  int j;
573  unsigned char Header[20 + (2 * (GSM_MAX_FILENAME_ID_LENGTH + 1))] = {
574  N7110_FRAME_HEADER, 0x02, 0x00, 0x00, 0x00, 0x01,
575  0x00, 0x0C, /* parent folder ID */
576  0x00, 0x00, 0x00, 0xE8};
577  unsigned char Add[15000] = {
578  N7110_FRAME_HEADER, 0x40, 0x00, 0x00, 0x00, 0x01,
579  0x00, 0x04, /* file ID */
580  0x00, 0x00,
581  0x01, 0x28}; /* length */
582  unsigned char end[30] = {
583  N7110_FRAME_HEADER, 0x40, 0x00, 0x00, 0x00, 0x01,
584  0x00, 0x04, /* file ID */
585  0x00, 0x00, 0x00, 0x00};
586 
587  memset(&File2, 0, sizeof(File2));
588 
589  s->Phone.Data.File = File;
590 
591  if (*Pos == 0) {
592  error = N6510_SearchForFileName1(s,File);
593  if (error == ERR_NONE) return ERR_FILEALREADYEXIST;
594  if (error != ERR_EMPTY) return error;
595 
596  Header[8] = atoi(DecodeUnicodeString(File->ID_FullName)) / 256;
597  Header[9] = atoi(DecodeUnicodeString(File->ID_FullName)) % 256;
598  memset(Header+14, 0x00, 300);
599  CopyUnicodeString(Header+14,File->Name);
600  Header[222] = File->Used / (256*256*256);
601  Header[223] = File->Used / (256*256);
602  Header[224] = File->Used / 256;
603  Header[225] = File->Used % 256;
604  switch(File->Type) {
605  case GSM_File_Image_JPG : Header[231]=0x02; Header[233]=0x01; break;
606  case GSM_File_Image_BMP : Header[231]=0x02; Header[233]=0x02; break;
607  case GSM_File_Image_PNG : Header[231]=0x02; Header[233]=0x03; break;
608  case GSM_File_Image_GIF : Header[231]=0x02; Header[233]=0x05; break;
609  case GSM_File_Image_WBMP : Header[231]=0x02; Header[233]=0x09; break;
610  case GSM_File_Sound_AMR : Header[231]=0x04; Header[233]=0x01; break;
611  case GSM_File_Sound_MIDI : Header[231]=0x04; Header[233]=0x05; break; /* Header[238]=0x01; */
612  case GSM_File_Sound_NRT : Header[231]=0x04; Header[233]=0x06; break;
613  case GSM_File_Video_3GP : Header[231]=0x08; Header[233]=0x05; break;
614  case GSM_File_Java_JAR : Header[231]=0x10; Header[233]=0x01; break;
615  case GSM_File_MMS:
616  Header[214]=0x07;
617  Header[215]=0xd3;
618  Header[216]=0x06;
619  Header[217]=0x01;
620  Header[218]=0x12;
621  Header[219]=0x13;
622  Header[220]=0x29;
623  Header[233]=0x01;
624  break;
625  default : Header[231]=0x01; Header[233]=0x05;
626  }
627  Header[235] = 0x01;
628  Header[236] = atoi(DecodeUnicodeString(File->ID_FullName)) / 256;
629  Header[237] = atoi(DecodeUnicodeString(File->ID_FullName)) % 256;
630  if (File->Protected) Header[238] = 0x01; /* Nokia forward lock */
631  if (File->Hidden) Header[241] = 0x01;
632  if (File->System) Header[242] = 0x01; /* fixme */
633  smprintf(s, "Adding file header\n");
634  error=GSM_WaitFor (s, Header, 246, 0x6D, 4, ID_AddFile);
635  if (error != ERR_NONE) return error;
636  }
637 
638  j = 1000;
639  if (File->Used - *Pos < 1000) j = File->Used - *Pos;
640  Add[ 8] = atoi(DecodeUnicodeString(File->ID_FullName)) / 256;
641  Add[ 9] = atoi(DecodeUnicodeString(File->ID_FullName)) % 256;
642  Add[12] = j / 256;
643  Add[13] = j % 256;
644  memcpy(Add+14,File->Buffer+(*Pos),j);
645  smprintf(s, "Adding file part %ld %i\n", (long)*Pos,j);
646  error=GSM_WaitFor (s, Add, 14+j, 0x6D, 4, ID_AddFile);
647  if (error != ERR_NONE) return error;
648  *Pos = *Pos + j;
649 
650  if (j < 1000) {
651  /* FIXME: This looks strange */
652  end[8] = atoi(DecodeUnicodeString(File->ID_FullName)) / 256;
653  end[9] = atoi(DecodeUnicodeString(File->ID_FullName)) % 256;
654  smprintf(s, "Frame for ending adding file\n");
655  error = GSM_WaitFor (s, end, 14, 0x6D, 4, ID_AddFile);
656  if (error != ERR_NONE) return error;
657 
658  CopyUnicodeString(File2.ID_FullName,File->ID_FullName);
659  error = N6510_GetFileFolderInfo1(s, &File2, FALSE);
660  if (error != ERR_NONE) return error;
661 
662  if (!File->ModifiedEmpty) {
663  Header[3] = 0x12;
664  Header[4] = 0x01;
665  Header[12] = 0x00;
666  Header[13] = 0xE8;
667  Header[8] = atoi(DecodeUnicodeString(File->ID_FullName)) / 256;
668  Header[9] = atoi(DecodeUnicodeString(File->ID_FullName)) % 256;
669  memset(Header+14, 0x00, 300);
670  CopyUnicodeString(Header+14,File->Name);
671  NOKIA_EncodeDateTime(s,Header+214,&File->Modified);
672  /* When you save too big file for phone and it changes
673  * size (some part is cut by firmware), you HAVE to write
674  * here correct file size. In other case filesystem
675  * will be damaged
676  */
677  Header[224] = File2.Used / 256;
678  Header[225] = File2.Used % 256;
679  Header[226] = Priv->FileToken / 256;
680  Header[227] = Priv->FileToken % 256;
681  switch(File->Type) {
682  case GSM_File_Image_JPG : Header[231]=0x02; Header[233]=0x01; break;
683  case GSM_File_Image_BMP : Header[231]=0x02; Header[233]=0x02; break;
684  case GSM_File_Image_PNG : Header[231]=0x02; Header[233]=0x03; break;
685  case GSM_File_Image_GIF : Header[231]=0x02; Header[233]=0x05; break;
686  case GSM_File_Image_WBMP : Header[231]=0x02; Header[233]=0x09; break;
687  case GSM_File_Sound_AMR : Header[231]=0x04; Header[233]=0x01; break;
688  case GSM_File_Sound_MIDI : Header[231]=0x04; Header[233]=0x05; break; /* Header[238]=0x01; */
689  case GSM_File_Sound_NRT : Header[231]=0x04; Header[233]=0x06; break;
690  case GSM_File_Video_3GP : Header[231]=0x08; Header[233]=0x05; break;
691  case GSM_File_Java_JAR : Header[231]=0x10; Header[233]=0x01; break;
692  case GSM_File_MMS:
693  Header[214]=0x07;
694  Header[215]=0xd3;
695  Header[216]=0x06;
696  Header[217]=0x01;
697  Header[218]=0x12;
698  Header[219]=0x13;
699  Header[220]=0x29;
700  Header[233]=0x01;
701  break;
702  default : Header[231]=0x01; Header[233]=0x05;
703  }
704  Header[235] = 0x01;
705  Header[236] = Priv->ParentID / 256;
706  Header[237] = Priv->ParentID % 256;
707  smprintf(s, "Adding file header\n");
708  error=GSM_WaitFor (s, Header, 246, 0x6D, 4, ID_AddFile);
709  if (error != ERR_NONE) return error;
710  }
711 
712  /* Can't delete from phone menu */
713  if (File->ReadOnly) {
714  error = N6510_SetReadOnly1(s, File->ID_FullName, TRUE);
715  if (error != ERR_NONE) return error;
716  }
717 
718  error = N6510_GetFileCRC1(s, File->ID_FullName);
719  if (error != ERR_NONE) return error;
720 
721  if (N6510_FindFileCheckSum12(s, File->Buffer, File->Used) != Priv->FileCheckSum) {
722  smprintf(s,"File2 checksum is %i, File checksum is %i\n",N6510_FindFileCheckSum12(s, File->Buffer, File->Used),Priv->FileCheckSum);
723  return ERR_WRONGCRC;
724  }
725 
726  return ERR_EMPTY;
727  }
728 
729  return ERR_NONE;
730 }
731 
733 {
734  if (msg->Buffer[4] == 0x01) {
735  return ERR_NONE;
736  } else if (msg->Buffer[4] == 0x04) {
737  return ERR_FILENOTEXIST;
738  }
739  return ERR_UNKNOWNRESPONSE;
740 }
741 
742 static GSM_Error N6510_PrivDeleteFileFolder1(GSM_StateMachine *s, unsigned char *ID, gboolean file)
743 {
744  GSM_Phone_N6510Data *Priv = &s->Phone.Data.Priv.N6510;
745  GSM_File File;
746  GSM_Error error;
747  unsigned char Delete[40] = {
748  N7110_FRAME_HEADER, 0x1E, 0x00, 0x00, 0x00, 0x01,
749  0x00, 0x35}; /* File ID */
750 
751  memset(&File, 0, sizeof(File));
752 
753  Priv->FilesLocationsUsed = 0;
755  error = N6510_GetFileFolderInfo1(s, &File, TRUE);
756  if (error != ERR_NONE) return error;
757  if (file) {
758  if (File.Folder) return ERR_SHOULDBEFILE;
759  } else {
760  if (!File.Folder) return ERR_SHOULDBEFOLDER;
761  /* dont allow to delete non empty folder */
762  if (Priv->FilesLocationsUsed != 0) return ERR_FOLDERNOTEMPTY;
763  }
764 
765  error = N6510_SetReadOnly1(s, ID, FALSE);
766  if (error != ERR_NONE) return error;
767 
768  /* FIXME: This looks wrong */
769  Delete[8] = atoi(DecodeUnicodeString(ID)) / 256;
770  Delete[9] = atoi(DecodeUnicodeString(ID)) % 256;
771 
772  return GSM_WaitFor (s, Delete, 10, 0x6D, 4, ID_DeleteFile);
773 }
774 
775 static GSM_Error N6510_DeleteFile1(GSM_StateMachine *s, unsigned char *ID)
776 {
777  return N6510_PrivDeleteFileFolder1(s,ID,TRUE);
778 }
779 
780 static GSM_Error N6510_DeleteFolder1(GSM_StateMachine *s, unsigned char *ID)
781 {
782  return N6510_PrivDeleteFileFolder1(s,ID,FALSE);
783 }
784 
786 {
787  unsigned char buffer[5];
788 
789  sprintf(buffer,"%i",msg->Buffer[8]*256+msg->Buffer[9]);
790  EncodeUnicode(s->Phone.Data.File->ID_FullName,buffer,strlen(buffer));
791  return ERR_NONE;
792 }
793 
794 static GSM_Error N6510_AddFolder1(GSM_StateMachine *s, GSM_File *File)
795 {
796  GSM_File File2;
797  GSM_Error error;
798  unsigned char Header[20 + (2 * (GSM_MAX_FILENAME_ID_LENGTH + 1))] = {
799  N7110_FRAME_HEADER, 0x04, 0x00, 0x00, 0x00, 0x01,
800  0x00, 0x0C, /* parent folder ID */
801  0x00, 0x00, 0x00, 0xE8};
802 
803  memset(&File2, 0, sizeof(File2));
804 
805  CopyUnicodeString(File2.ID_FullName,File->ID_FullName);
806  error = N6510_GetFileFolderInfo1(s, &File2, FALSE);
807  if (error != ERR_NONE) return error;
808  if (!File2.Folder) return ERR_SHOULDBEFOLDER;
809 
810  Header[8] = atoi(DecodeUnicodeString(File->ID_FullName)) / 256;
811  Header[9] = atoi(DecodeUnicodeString(File->ID_FullName)) % 256;
812  memset(Header+14, 0x00, 300);
813  CopyUnicodeString(Header+14,File->Name);
814  Header[233] = 0x02;
815  Header[235] = 0x01;
816  Header[236] = atoi(DecodeUnicodeString(File->ID_FullName)) / 256;
817  Header[237] = atoi(DecodeUnicodeString(File->ID_FullName)) % 256;
818 
819  s->Phone.Data.File = File;
820  smprintf(s, "Adding folder\n");
821  error = GSM_WaitFor (s, Header, 246, 0x6D, 4, ID_AddFolder);
822  if (error != ERR_NONE) return error;
823 
824  if (!strcmp(DecodeUnicodeString(File->ID_FullName),"0")) return ERR_FILEALREADYEXIST;
825 
826  /* Can't delete from phone menu */
827  if (File->ReadOnly) {
828  error = N6510_SetReadOnly1(s, File->ID_FullName, TRUE);
829  if (error != ERR_NONE) return error;
830  }
831 
832  return error;
833 }
834 
835 static GSM_Error N6510_GetFolderListing1(GSM_StateMachine *s, GSM_File *File, gboolean start)
836 {
837  GSM_Error error;
838  GSM_Phone_N6510Data *Priv = &s->Phone.Data.Priv.N6510;
839 
840  if (start) {
841  Priv->FilesLocationsUsed = 0;
842 
843  error = N6510_GetFileFolderInfo1(s, File, TRUE);
844  if (error != ERR_NONE) return error;
845 
846  if (!File->Folder) return ERR_SHOULDBEFOLDER;
847  }
848 
849  while (TRUE) {
850  if (Priv->FilesLocationsUsed == 0) return ERR_EMPTY;
851 
852  memcpy(File,&Priv->FilesCache[0],sizeof(GSM_File));
853  error = N6510_GetFileFolderInfo1(s, File, FALSE);
854  if (error != ERR_NONE) return error;
855 
856  error = N6510_ShiftFileCache(s, -1);
857  if (error != ERR_NONE) return error;
858 
859  break;
860  }
861  return error;
862 }
863 
864 /* filesystem 2 */
865 
867 {
868  if (msg->Buffer[4]==0) {
869  smprintf(s,"File opened and handle received\n");
870  s->Phone.Data.FileHandle = msg->Buffer[6]*256*256*256+
871  msg->Buffer[7]*256*256+
872  msg->Buffer[8]*256+
873  msg->Buffer[9];
874  smprintf(s,"File handle: %i\n",
875  msg->Buffer[6]*256*256*256+
876  msg->Buffer[7]*256*256+
877  msg->Buffer[8]*256+
878  msg->Buffer[9]);
879  return ERR_NONE;
880  } else if (msg->Buffer[4] == 0x03) {
881  smprintf(s,"You can't open already existing folder\n");
882  return ERR_FILEALREADYEXIST;
883  } else if (msg->Buffer[4] == 0x06) {
884  smprintf(s,"File not exist\n");
885  return ERR_FILENOTEXIST;
886  }
887  return ERR_UNKNOWNRESPONSE;
888 }
889 
890 static GSM_Error N6510_OpenFile2(GSM_StateMachine *s, char *Name, int *Handle, gboolean Create)
891 {
892  unsigned char req[20 + (2 * (GSM_MAX_FILENAME_ID_LENGTH + 1))] =
893  {N6110_FRAME_HEADER, 0x72,
894  0x00, /* mode 0 - open read only, 0x11 - read write create */
895  0x02,
896  0xFF, 0xFF}; /* name length */
897  int Pos = 8;
898  GSM_Error error;
899 
900  if (Create) req[4] = 0x11;
901  req[6] = (UnicodeLength(Name)*2 + 2)/ 256 ;
902  req[7] = (UnicodeLength(Name)*2 + 2)% 256 ;
903  CopyUnicodeString(req+8,Name);
904  if (req[9] == 'a' || req[9] == 'A') req[9] = 'b';
905  if (req[9] == 'd' || req[9] == 'D') req[9] = 'a';
906  Pos+=UnicodeLength(Name)*2;
907  req[Pos++] = 0;
908  req[Pos++] = 0;
909 
910  smprintf(s, "Opening file\n");
911  error = GSM_WaitFor (s, req, Pos, 0x6D, 4, ID_OpenFile);
912  if (error==ERR_NONE) (*Handle) = s->Phone.Data.FileHandle;
913  return error;
914 }
915 
916 static GSM_Error N6510_CloseFile2(GSM_StateMachine *s, int *Handle)
917 {
918  unsigned char req[200] = {N6110_FRAME_HEADER, 0x74, 0x00, 0x00,
919  0x00, 0x00, 0x00, 0x00}; /* file handle */
920 
921  req[6] = (*Handle) / (256*256*256);
922  req[7] = (*Handle) / (256*256);
923  req[8] = (*Handle) / 256;
924  req[9] = (*Handle) % 256;
925 
926  smprintf(s, "Closing file\n");
927  return GSM_WaitFor (s, req, 10, 0x6D, 4, ID_CloseFile);
928 }
929 
930 static GSM_Error N6510_GetFileCRC2(GSM_StateMachine *s, int *Handle)
931 {
932  unsigned char req2[15000] = {
933  N7110_FRAME_HEADER, 0x66, 0x00, 0x00,
934  0x00, 0x00, 0x00, 0x00}; /* handle */
935 
936  req2[6] = (*Handle) / (256*256*256);
937  req2[7] = (*Handle) / (256*256);
938  req2[8] = (*Handle) / 256;
939  req2[9] = (*Handle) % 256;
940  return GSM_WaitFor (s, req2, 10, 0x6D, 8, ID_GetCRC);
941 }
942 
944 {
945  GSM_Phone_N6510Data *Priv = &s->Phone.Data.Priv.N6510;
946  GSM_File *FileInfo = s->Phone.Data.FileInfo;
947  GSM_File *File;
948  GSM_Error error;
949 
950  switch (msg->Buffer[3]) {
951  case 0x69:
952  case 0x6D:
953  switch (msg->Buffer[4]) {
954  case 0x0C:
955  smprintf(s,"Probably no MMC card\n");
957  Priv->FilesEnd = TRUE;
958  return ERR_MEMORY;
959  case 0x00:
960  case 0x0D:
961  switch (msg->Buffer[5]) {
962  case 0x00:
963  break;
964  case 0x06:
965  smprintf(s,"File not exist\n");
966  return ERR_FILENOTEXIST;
967  case 0x0C:
968  smprintf(s,"Probably no MMC card\n");
969  return ERR_MEMORY;
970  default:
971  smprintf(s,"unknown status code\n");
972  return ERR_UNKNOWNRESPONSE;
973  }
974  smprintf(s,"File or folder details received\n");
975 
976  if (msg->Buffer[3] == 0x69) {
977  /* File/Folder without can not be handled */
978  if (UnicodeLength(msg->Buffer+32) == 0) {
979  smprintf(s, "Ignoring file without name!\n");
980  return ERR_NONE;
981  }
982  error = N6510_AllocFileCache(s, Priv->FilesLocationsUsed + 1);
983  if (error != ERR_NONE) {
984  return error;
985  }
986 
987  error = N6510_ShiftFileCache(s, 1);
988  if (error != ERR_NONE) return error;
989 
990  File = &Priv->FilesCache[1];
991 
992  File->Level = Priv->FilesCache[0].Level + 1;
993 
994  CopyUnicodeString(File->Name,msg->Buffer+32);
995  smprintf(s,"\"%s\"\n",DecodeUnicodeString(File->Name));
996 
997  CopyUnicodeString(File->ID_FullName,FileInfo->ID_FullName);
998  EncodeUnicode(File->ID_FullName+UnicodeLength(File->ID_FullName)*2,"/",1);
1000  smprintf(s,"\"%s\"\n",DecodeUnicodeString(File->ID_FullName));
1001  } else {
1002  File = FileInfo;
1003  }
1004 
1005  smprintf(s, "File type: 0x%02X\n", msg->Buffer[29]);
1006  if ((msg->Buffer[29] & 0x10) == 0x10) {
1007  File->Folder = TRUE;
1008  smprintf(s,"Folder\n");
1009  } else {
1010  File->Folder = FALSE;
1011  smprintf(s,"File\n");
1012  File->Used = msg->Buffer[10]*256*256*256+
1013  msg->Buffer[11]*256*256+
1014  msg->Buffer[12]*256+
1015  msg->Buffer[13];
1016  smprintf(s,"Size %ld bytes\n", (long)File->Used);
1017  }
1018  File->ReadOnly = FALSE;
1019  if ((msg->Buffer[29] & 1) == 1) {
1020  File->ReadOnly = TRUE;
1021  smprintf(s,"Readonly\n");
1022  }
1023  File->Hidden = FALSE;
1024  if ((msg->Buffer[29] & 2) == 2) {
1025  File->Hidden = TRUE;
1026  smprintf(s,"Hidden\n");
1027  }
1028  File->System = FALSE;
1029  if ((msg->Buffer[29] & 4) == 4) {
1030  File->System = TRUE;
1031  smprintf(s,"System\n");
1032  }
1033  File->Protected = FALSE;
1034  if ((msg->Buffer[29] & 0x40) == 0x40) {
1035  File->Protected = TRUE;
1036  smprintf(s,"Protected\n");
1037  }
1038 
1039  File->ModifiedEmpty = FALSE;
1040  NOKIA_DecodeDateTime(s, msg->Buffer+14, &File->Modified, TRUE, FALSE);
1041  if (File->Modified.Year == 0x00) File->ModifiedEmpty = TRUE;
1042  if (File->Modified.Year == 0xffff) File->ModifiedEmpty = TRUE;
1043 
1044  if (msg->Buffer[3] == 0x69 && msg->Buffer[4] == 0) Priv->FilesEnd = TRUE;
1045 
1046  return ERR_NONE;
1047  case 0x06:
1048  smprintf(s,"File or folder details received - not available ?\n");
1050  Priv->FilesEnd = TRUE;
1051  return ERR_FILENOTEXIST;
1052  case 0x0E:
1053  smprintf(s,"File or folder details received - empty\n");
1054  Priv->FilesEnd = TRUE;
1055  return ERR_NONE;
1056  }
1057  }
1058  return ERR_UNKNOWNRESPONSE;
1059 }
1060 
1061 static GSM_Error N6510_GetFileFolderInfo2(GSM_StateMachine *s, GSM_File *File)
1062 {
1063  int Pos=6;
1064  unsigned char req[20 + (2 * (GSM_MAX_FILENAME_ID_LENGTH + 1))] = {
1065  N7110_FRAME_HEADER,0x6C,
1066  0xFF, 0xFF}; /* name length */
1067 
1068  s->Phone.Data.FileInfo = File;
1069 
1070  req[4] = (UnicodeLength(File->ID_FullName)*2 + 2)/256;
1071  req[5] = (UnicodeLength(File->ID_FullName)*2 + 2)%256;
1072  CopyUnicodeString(req+6,File->ID_FullName);
1073  if (req[7] == 'a' || req[7] == 'A') req[7] = 'b';
1074  if (req[7] == 'd' || req[7] == 'D') req[7] = 'a';
1075  Pos+=UnicodeLength(File->ID_FullName)*2;
1076  req[Pos++] = 0;
1077  req[Pos++] = 0;
1078 
1079  smprintf(s,"Getting info for file in filesystem\n");
1080  return GSM_WaitFor (s, req, Pos, 0x6D, 4, ID_GetFileInfo);
1081 }
1082 
1083 static GSM_Error N6510_PrivGetFolderListing2(GSM_StateMachine *s, GSM_File *File)
1084 {
1085  GSM_Error error;
1086  GSM_Phone_N6510Data *Priv = &s->Phone.Data.Priv.N6510;
1087  unsigned char req[20 + (2 * (GSM_MAX_FILENAME_ID_LENGTH + 1))] = {
1088  N6110_FRAME_HEADER, 0x68,
1089  0xFF, 0xFF}; /* name length */
1090  int Pos = 6, i = 0;
1091 
1092  req[4] = (UnicodeLength(File->ID_FullName)*2 + 6)/ 256 ;
1093  req[5] = (UnicodeLength(File->ID_FullName)*2 + 6)% 256 ;
1094  CopyUnicodeString(req+6,File->ID_FullName);
1095  if (req[7] == 'a' || req[7] == 'A') req[7] = 'b';
1096  if (req[7] == 'd' || req[7] == 'D') req[7] = 'a';
1097  Pos+=UnicodeLength(File->ID_FullName)*2;
1098  req[Pos++] = 0;
1099  req[Pos++] = '/';
1100  req[Pos++] = 0;
1101  req[Pos++] = '*';
1102  req[Pos++] = 0;
1103  req[Pos++] = 0;
1104 
1105  smprintf(s, "Getting folder info %s\n",DecodeUnicodeString(File->ID_FullName));
1106 
1107  Priv->filesystem2error = ERR_NONE;
1108  s->Phone.Data.FileInfo = File;
1109  Priv->FilesEnd = FALSE;
1110  error = s->Protocol.Functions->WriteMessage(s, req, Pos, 0x6D);
1111  if (error!=ERR_NONE) return error;
1112 
1113  while (!Priv->FilesEnd) {
1114  usleep(1000);
1115  if (GSM_ReadDevice(s,TRUE) <= 0) {
1116  i++;
1117  } else {
1118  i=0;
1119  }
1120  if (i == 3) {
1121  smprintf(s,"Connection broken or WELL KNOWN phone firmware problem (which makes, that not all files are reported)\n");
1123  return ERR_NONE;
1124  }
1125  }
1126 
1127  return ERR_NONE;
1128 }
1129 
1130 static GSM_Error N6510_GetNextFileFolder2(GSM_StateMachine *s, GSM_File *File, gboolean start)
1131 {
1132  GSM_Phone_N6510Data *Priv = &s->Phone.Data.Priv.N6510;
1133  GSM_Error error;
1134 
1135  if (start) {
1136  error = N6510_AllocFileCache(s, 2);
1137  if (error != ERR_NONE) return error;
1138 
1139  Priv->FilesLocationsUsed = 2;
1140 
1141  Priv->FilesCache[0].Level = 1;
1142  Priv->FilesCache[0].Folder = TRUE;
1143  Priv->FilesCache[0].Level = 1;
1144  Priv->FilesCache[0].ReadOnly = FALSE;
1145  Priv->FilesCache[0].System = FALSE;
1146  Priv->FilesCache[0].Hidden = FALSE;
1147  Priv->FilesCache[0].Protected = FALSE;
1148  EncodeUnicode(Priv->FilesCache[0].ID_FullName,"d:",2);
1149  EncodeUnicode(Priv->FilesCache[0].Name,"D (Permanent_memory 2)",22);
1150 
1151  Priv->FilesCache[1].Level = 1;
1152  Priv->FilesCache[1].Folder = TRUE;
1153  Priv->FilesCache[1].Level = 1;
1154  Priv->FilesCache[1].ReadOnly = FALSE;
1155  Priv->FilesCache[1].System = FALSE;
1156  Priv->FilesCache[1].Hidden = FALSE;
1157  Priv->FilesCache[1].Protected = FALSE;
1158  EncodeUnicode(Priv->FilesCache[1].ID_FullName,"a:",2);
1159  EncodeUnicode(Priv->FilesCache[1].Name,"A (Memory card)",15);
1160  }
1161 
1162  smprintf(s, "Currently %i locations\n",Priv->FilesLocationsUsed);
1163  if (Priv->FilesLocationsUsed == 0) return ERR_EMPTY;
1164 
1165 
1166  if (!Priv->FilesCache[0].Folder) {
1167  memcpy(File,&Priv->FilesCache[0],sizeof(GSM_File));
1168  error = N6510_ShiftFileCache(s, -1);
1169  if (error != ERR_NONE) return error;
1170  smprintf(s, "Returning file %s, level %d\n", DecodeUnicodeString(File->ID_FullName), File->Level);
1171  return ERR_NONE;
1172  }
1173 
1174  memcpy(File,&Priv->FilesCache[0],sizeof(GSM_File));
1175  error = N6510_PrivGetFolderListing2(s, File);
1176  if (error != ERR_NONE) return error;
1177 
1178  memcpy(File,&Priv->FilesCache[0],sizeof(GSM_File));
1179  error = N6510_ShiftFileCache(s, -1);
1180  if (error != ERR_NONE) return error;
1181 
1182  smprintf(s, "Returning folder %s, level %d\n", DecodeUnicodeString(File->ID_FullName), File->Level);
1183 
1184  if (Priv->filesystem2error == ERR_FOLDERPART) return ERR_FOLDERPART;
1185 
1186  return error;
1187 }
1188 
1189 static GSM_Error N6510_GetFilePart2(GSM_StateMachine *s, GSM_File *File, int *Handle, size_t *Size)
1190 {
1191  int old,j;
1192  GSM_Error error;
1193  GSM_Phone_N6510Data *Priv = &s->Phone.Data.Priv.N6510;
1194  unsigned char req[] = {
1195  N7110_FRAME_HEADER, 0x5E, 0x00, 0x00,
1196  0x00, 0x00, 0x00, 0x01, /* file handle */
1197  0x00, 0x00, 0x00, 0x00, /* position */
1198  0x00, 0x00, 0x03, 0xE8, /* length */
1199  0x00, 0x00, 0x03, 0xE8}; /* buffer length */
1200 
1201  if (File->Used == 0x00) {
1202  error = N6510_GetFileFolderInfo2(s, File);
1203  if (error != ERR_NONE) return error;
1204 
1205  if (File->Folder) return ERR_SHOULDBEFILE;
1206 
1207  error = N6510_OpenFile2(s, File->ID_FullName, Handle, FALSE);
1208  if (error != ERR_NONE) return error;
1209 
1210  for (j=UnicodeLength(File->ID_FullName)-1;j>0;j--) {
1211  if (File->ID_FullName[j*2+1] == '\\' || File->ID_FullName[j*2+1] == '/') break;
1212  }
1213  if (File->ID_FullName[j*2+1] == '\\' || File->ID_FullName[j*2+1] == '/') {
1214  CopyUnicodeString(File->Name,File->ID_FullName+j*2+2);
1215  } else {
1216  CopyUnicodeString(File->Name,File->ID_FullName);
1217  }
1218 
1219  (*Size) = File->Used;
1220  File->Used = 0;
1221  }
1222 
1223  req[6] = (*Handle) / (256*256*256);
1224  req[7] = (*Handle) / (256*256);
1225  req[8] = (*Handle) / 256;
1226  req[9] = (*Handle) % 256;
1227 
1228  old = File->Used;
1229  req[10] = old / (256*256*256);
1230  req[11] = old / (256*256);
1231  req[12] = old / 256;
1232  req[13] = old % 256;
1233 
1234  s->Phone.Data.File = File;
1235  smprintf(s, "Getting file part from filesystem\n");
1236  error=GSM_WaitFor (s, req, 22, 0x6D, 4, ID_GetFile);
1237  if (error != ERR_NONE) return error;
1238 
1239  if (File->Used - old != (0x03 * 256 + 0xE8)) {
1240  error = N6510_GetFileCRC2(s, Handle);
1241  if (error != ERR_NONE) return error;
1242 
1243  error = N6510_CloseFile2(s, Handle);
1244  if (error != ERR_NONE) return error;
1245 
1246  if (N6510_FindFileCheckSum12(s, File->Buffer, File->Used) != Priv->FileCheckSum) {
1247  smprintf(s,"File2 checksum is %i, File checksum is %i\n",N6510_FindFileCheckSum12(s, File->Buffer, File->Used),Priv->FileCheckSum);
1248  return ERR_WRONGCRC;
1249  }
1250 
1251  return ERR_EMPTY;
1252  }
1253  return ERR_NONE;
1254 }
1255 
1257 {
1258  return ERR_NONE;
1259 }
1260 
1262 {
1263  if (msg->Buffer[4] == 0x00) {
1264  return ERR_NONE;
1265  } else if (msg->Buffer[4] == 0x06) {
1266  return ERR_FILENOTEXIST;
1267  }
1268  return ERR_UNKNOWNRESPONSE;
1269 }
1270 
1271 static GSM_Error N6510_SetFileAttributes2(GSM_StateMachine *s, GSM_File *File)
1272 {
1273  int P = 10;
1274  GSM_Error error;
1275  GSM_File File2;
1276  unsigned char Header2[20 + (2 * (GSM_MAX_FILENAME_ID_LENGTH + 1))] = {
1277  N7110_FRAME_HEADER, 0x6E,
1278  0x00, 0x0c}; /* name len */
1279 
1280  memcpy(&File2,File,sizeof(GSM_File));
1281 
1282  error = N6510_GetFileFolderInfo2(s, File);
1283  if (error != ERR_NONE) return error;
1284 
1285  /* haven't checked. */
1286  if (File->Folder) return ERR_SHOULDBEFILE;
1287 
1288  Header2[4] = (UnicodeLength(File2.ID_FullName) + 1)/ 256 ;
1289  Header2[5] = (UnicodeLength(File2.ID_FullName) + 1)% 256 ;
1290  Header2[6] = 0x00;
1291  Header2[7] = 0x00;
1292  Header2[8] = 0x00;
1293  Header2[9] = 0x00;
1294  if (File2.ReadOnly) Header2[9] += 1;
1295  if (File2.Hidden) Header2[9] += 2;
1296  if (File2.System) Header2[9] += 4;
1297  if (File2.Protected) Header2[9] += 0x40;
1298  CopyUnicodeString(Header2+10,File2.ID_FullName);
1299  if (Header2[11] == 'a' || Header2[11] == 'A') Header2[11] = 'b';
1300  if (Header2[11] == 'd' || Header2[11] == 'D') Header2[11] = 'a';
1301  P+=UnicodeLength(File2.ID_FullName)*2;
1302  Header2[P++] = 0;
1303  Header2[P++] = 0;
1304  error = GSM_WaitFor (s, Header2, P, 0x6D, 4, ID_SetAttrib);
1305  if (error != ERR_NONE) return error;
1306 
1307  error = N6510_GetFileFolderInfo2(s, File);
1308  if (error != ERR_NONE) return error;
1309 
1310  /* mmc doesn't support protected */
1311  if (File2.System != File->System ||
1312  File2.ReadOnly != File->ReadOnly ||
1313  File2.Hidden != File->Hidden ) {
1314 /* File2.Protected != File->Protected) { */
1315  return ERR_NOTSUPPORTED;
1316  }
1317 
1318  return ERR_NONE;
1319 }
1320 
1321 static GSM_Error N6510_AddFilePart2(GSM_StateMachine *s, GSM_File *File, size_t *Pos, int *Handle)
1322 {
1323  GSM_Error error;
1324  int j,P;
1325 /* GSM_Phone_N6510Data *Priv = &s->Phone.Data.Priv.N6510; */
1326 /* unsigned char buffer[500]; */
1327  unsigned char req[15000] = {
1328  N7110_FRAME_HEADER, 0x58, 0x00, 0x00,
1329  0x00, 0x00, 0x00, 0x00, /* handle */
1330  0x00, 0x00, 0x04, 0x00}; /* buffer len */
1331  unsigned char Header[20 + (2 * (GSM_MAX_FILENAME_ID_LENGTH + 1))] = {
1332  N7110_FRAME_HEADER, 0x86,
1333  0x00, 0x0c}; /* name len */
1334 
1335  s->Phone.Data.File = File;
1336 
1337  if (*Pos == 0) {
1338  EncodeUnicode(File->ID_FullName+UnicodeLength(File->ID_FullName)*2,"/",1);
1340 
1341  error = N6510_GetFileFolderInfo2(s, File);
1342  switch (error) {
1343  case ERR_FILENOTEXIST:
1344  break;
1345  case ERR_NONE:
1346  return ERR_FILEALREADYEXIST;
1347  default:
1348  return error;
1349  }
1350 
1351  error = N6510_OpenFile2(s, File->ID_FullName, Handle, TRUE);
1352  if (error != ERR_NONE) return error;
1353  }
1354 
1355  req[6] = (*Handle) / (256*256*256);
1356  req[7] = (*Handle) / (256*256);
1357  req[8] = (*Handle) / 256;
1358  req[9] = (*Handle) % 256;
1359 
1360  j = 2000;
1361  if (File->Used - *Pos < 2000) j = File->Used - *Pos;
1362  req[10] = j / (256*256*256);
1363  req[11] = j / (256*256);
1364  req[12] = j / 256;
1365  req[13] = j % 256;
1366  memcpy(req+14,File->Buffer+(*Pos),j);
1367 
1368  smprintf(s, "Adding file part %ld %i\n",(long)*Pos,j);
1369  error=GSM_WaitFor (s, req, 14+j, 0x6D, 4, ID_AddFile);
1370  if (error != ERR_NONE) return error;
1371  *Pos = *Pos + j;
1372 
1373  if (j < 2000) {
1374  error = N6510_CloseFile2(s, Handle);
1375  if (error != ERR_NONE) return error;
1376 
1377  P = 14;
1378  Header[4] = (UnicodeLength(File->ID_FullName) + 1)/ 256 ;
1379  Header[5] = (UnicodeLength(File->ID_FullName) + 1)% 256 ;
1380  Header[6] = File->Modified.Year / 256;
1381  Header[7] = File->Modified.Year % 256;
1382  Header[8] = File->Modified.Month;
1383  Header[9] = File->Modified.Day;
1384  Header[10] = 0x00;
1385  Header[11] = File->Modified.Hour;
1386  Header[12] = File->Modified.Minute;
1387  Header[13] = File->Modified.Second;
1388  CopyUnicodeString(Header+14,File->ID_FullName);
1389  if (Header[15] == 'a' || Header[15] == 'A') Header[15] = 'b';
1390  if (Header[15] == 'd' || Header[15] == 'D') Header[15] = 'a';
1391  P+=UnicodeLength(File->ID_FullName)*2;
1392  req[P++] = 0;
1393  req[P++] = 0;
1394  smprintf(s,"Setting file date\n");
1395  error = GSM_WaitFor (s, Header, P, 0x6D, 4, ID_AddFile);
1396  if (error != ERR_NONE) return error;
1397 
1398  error = N6510_SetFileAttributes2(s,File);
1399  if (error != ERR_NONE) return error;
1400 
1401 /* error = N6510_OpenFile2(s, File->ID_FullName, Handle, FALSE); */
1402 /* if (error != ERR_NONE) return error; */
1403 /* if ((*Handle) == 0) { */
1404 /* error = N6510_OpenFile2(s, File->ID_FullName, Handle, FALSE); */
1405 /* if (error != ERR_NONE) return error; */
1406 /* } */
1407 /* error = N6510_GetFileCRC2(s, Handle); */
1408 /* if (error != ERR_NONE) return error; */
1409 /* error = N6510_CloseFile2(s, Handle); */
1410 /* if (error != ERR_NONE) return error; */
1411 /* if (N6510_FindFileCheckSum12(s, File->Buffer, File->Used) != Priv->FileCheckSum) { */
1412 /* smprintf(s,"File2 checksum is %i, File checksum is %i\n",N6510_FindFileCheckSum12(s, File->Buffer, File->Used),Priv->FileCheckSum); */
1413 /* return ERR_WRONGCRC; */
1414 /* } */
1415 
1416  return ERR_EMPTY;
1417  }
1418 
1419  return ERR_NONE;
1420 }
1421 
1422 static GSM_Error N6510_GetFolderListing2(GSM_StateMachine *s, GSM_File *File, gboolean start)
1423 {
1424  GSM_Phone_N6510Data *Priv = &s->Phone.Data.Priv.N6510;
1425  GSM_Error error;
1426 
1427  if (start) {
1428  if (strcasecmp(DecodeUnicodeString(File->ID_FullName),"a:") == 0 ||
1429  strcasecmp(DecodeUnicodeString(File->ID_FullName),"a:\\") == 0 ||
1430  strcasecmp(DecodeUnicodeString(File->ID_FullName),"d:") == 0 ||
1431  strcasecmp(DecodeUnicodeString(File->ID_FullName),"d:\\") == 0) {
1432  } else {
1433  /* we must check, if user gave folder name or not */
1434  error = N6510_GetFileFolderInfo2(s, File);
1435  if (error != ERR_NONE) return error;
1436  if (!File->Folder) return ERR_SHOULDBEFOLDER;
1437  }
1438 
1439  error = N6510_AllocFileCache(s, 1);
1440  if (error != ERR_NONE) return error;
1441 
1442  Priv->FilesLocationsUsed = 1;
1443 
1444  error = N6510_PrivGetFolderListing2(s, File);
1445  if (error != ERR_NONE) return error;
1446 
1447  memcpy(File,&Priv->FilesCache[0],sizeof(GSM_File));
1448 
1449  error = N6510_ShiftFileCache(s, -1);
1450  if (error != ERR_NONE) return error;
1451  }
1452 
1453  if (Priv->FilesLocationsUsed == 0) return ERR_EMPTY;
1454 
1455  memcpy(File,&Priv->FilesCache[0],sizeof(GSM_File));
1456 
1457  error = N6510_ShiftFileCache(s, -1);
1458  if (error != ERR_NONE) return error;
1459 
1460  if (start) {
1461  if (Priv->filesystem2error == ERR_FOLDERPART) return ERR_FOLDERPART;
1462  }
1463  return ERR_NONE;
1464 }
1465 
1467 {
1468  if (msg->Buffer[4] == 0x00) {
1469  return ERR_NONE;
1470  } else if (msg->Buffer[4] == 0x03) {
1471  /* trying to delete read only */
1472  return ERR_UNKNOWN;
1473  } else if (msg->Buffer[4] == 0x06) {
1474  return ERR_FILENOTEXIST;
1475  }
1476 
1477  return ERR_UNKNOWNRESPONSE;
1478 }
1479 
1480 static GSM_Error N6510_DeleteFile2(GSM_StateMachine *s, unsigned char *ID)
1481 {
1482  unsigned char req[20 + (2 * (GSM_MAX_FILENAME_ID_LENGTH + 1))] = {
1483  N7110_FRAME_HEADER, 0x62};
1484  int Pos = 6;
1485  GSM_File file;
1486  GSM_Error error;
1487 
1488  /* first remove readonly */
1489  file.ReadOnly = FALSE;
1490  file.Hidden = FALSE;
1491  file.System = FALSE;
1492  file.Protected = FALSE;
1493 
1494  CopyUnicodeString(file.ID_FullName,ID);
1495  error = N6510_SetFileAttributes2(s,&file);
1496  if (error != ERR_NONE) return error;
1497 
1498  req[4] = (UnicodeLength(ID)*2 + 2)/ 256 ;
1499  req[5] = (UnicodeLength(ID)*2 + 2)% 256 ;
1500  CopyUnicodeString(req+6,ID);
1501  if (req[7] == 'a' || req[7] == 'A') req[7] = 'b';
1502  if (req[7] == 'd' || req[7] == 'D') req[7] = 'a';
1503  Pos+=UnicodeLength(ID)*2;
1504  req[Pos++] = 0;
1505  req[Pos++] = 0;
1506 
1507  smprintf(s,"Deleting file\n");
1508  return GSM_WaitFor (s, req, Pos, 0x6D, 4, ID_DeleteFile);
1509 }
1510 
1512 {
1513  if (msg->Buffer[4] == 0x00) {
1514  return ERR_NONE;
1515  } if (msg->Buffer[4] == 0x04) {
1516  return ERR_FILEALREADYEXIST;
1517  } if (msg->Buffer[4] == 0x06) {
1518  return ERR_FILENOTEXIST;
1519  } if (msg->Buffer[4] == 0x0C) {
1520  return ERR_MEMORY;
1521  }
1522  return ERR_UNKNOWNRESPONSE;
1523 }
1524 
1525 static GSM_Error N6510_AddFolder2(GSM_StateMachine *s, GSM_File *File)
1526 {
1527  GSM_Error error;
1528  unsigned char req[20 + (2 * (GSM_MAX_FILENAME_ID_LENGTH + 1))] = {
1529  N7110_FRAME_HEADER, 0x64};
1530  int Pos = 6;
1531  int Len = 0;
1532 
1533  Len = UnicodeLength(File->ID_FullName)*2 + 2;
1534 
1535  CopyUnicodeString(req+6,File->ID_FullName);
1536  Pos+=UnicodeLength(File->ID_FullName)*2;
1537  if (DecodeUnicodeString(File->ID_FullName)[UnicodeLength(File->ID_FullName)-1] != '\\' &&
1538  DecodeUnicodeString(File->ID_FullName)[UnicodeLength(File->ID_FullName)-1] != '/') {
1539  req[Pos++] = 0;
1540  req[Pos++] = '/';
1541  Len += 2;
1542  }
1543  CopyUnicodeString(req+Pos,File->Name);
1544  if (req[Pos+1] == 'a' || req[Pos+1] == 'A') req[Pos+1] = 'b';
1545  if (req[Pos+1] == 'd' || req[Pos+1] == 'D') req[Pos+1] = 'a';
1546  Pos += UnicodeLength(File->Name)*2;
1547  Len += UnicodeLength(File->Name)*2;
1548  req[Pos++] = 0;
1549  req[Pos++] = 0;
1550  req[4] = Len / 256 ;
1551  req[5] = Len % 256 ;
1552  smprintf(s,"Adding folder\n");
1553  error=GSM_WaitFor (s, req, Pos, 0x6D, 4, ID_AddFolder);
1554  if (error == ERR_NONE) memcpy(File->ID_FullName,req+6,Pos);
1555  return error;
1556 }
1557 
1559 {
1560  if (msg->Buffer[4] == 0x00) {
1561  return ERR_NONE;
1562  } if (msg->Buffer[4] == 0x03) {
1563  return ERR_SHOULDBEFOLDER;
1564  } if (msg->Buffer[4] == 0x06) {
1565  return ERR_FILENOTEXIST;
1566  } if (msg->Buffer[4] == 0x0C) {
1567  return ERR_MEMORY;
1568  }
1569  return ERR_UNKNOWNRESPONSE;
1570 }
1571 
1572 static GSM_Error N6510_DeleteFolder2(GSM_StateMachine *s, unsigned char *ID)
1573 {
1574  GSM_File File2;
1575  GSM_Error error;
1576  unsigned char req[20 + (2 * (GSM_MAX_FILENAME_ID_LENGTH + 1))] = {
1577  N7110_FRAME_HEADER, 0x6A};
1578  int Pos = 6;
1579 
1580  /* we don't want to allow deleting non empty folders */
1581  CopyUnicodeString(File2.ID_FullName,ID);
1582  error = N6510_GetFolderListing2(s, &File2, TRUE);
1583  switch (error) {
1584  case ERR_EMPTY:
1585  break;
1586  case ERR_NONE:
1587  return ERR_FOLDERNOTEMPTY;
1588  default:
1589  return error;
1590  }
1591 
1592  req[4] = (UnicodeLength(ID)*2 + 2)/ 256 ;
1593  req[5] = (UnicodeLength(ID)*2 + 2)% 256 ;
1594  CopyUnicodeString(req+6,ID);
1595  if (req[7] == 'a' || req[7] == 'A') req[7] = 'b';
1596  if (req[7] == 'd' || req[7] == 'D') req[7] = 'a';
1597  Pos+=UnicodeLength(ID)*2;
1598  req[Pos++] = 0;
1599  req[Pos++] = 0;
1600 
1601  smprintf(s,"Deleting folder\n");
1602  return GSM_WaitFor (s, req, Pos, 0x6D, 4, ID_DeleteFolder);
1603 }
1604 
1605 /* shared */
1606 
1608 {
1609  GSM_Error error;
1610  GSM_File File2;
1611 
1613 
1614  if (DecodeUnicodeString(File->ID_FullName)[0] == 'c' ||
1615  DecodeUnicodeString(File->ID_FullName)[0] == 'C') {
1618  return ERR_NOTSUPPORTED;
1619  }
1620 
1621  memcpy(&File2,File,sizeof(GSM_File));
1622  CopyUnicodeString(File2.ID_FullName,File->ID_FullName+3*2);
1623  error = N6510_GetFolderListing1(s,&File2,start);
1624  memcpy(File,&File2,sizeof(GSM_File));
1625  /* GetFolderListing changes ID */
1626  EncodeUnicode(File->ID_FullName,"c:/",3);
1628  return error;
1629  } else {
1631  return N6510_GetFolderListing2(s,File,start);
1632  } else {
1633  return ERR_NOTSUPPORTED;
1634  }
1635  }
1636 }
1637 
1639 {
1640  GSM_Error error;
1641  GSM_Phone_N6510Data *Priv = &s->Phone.Data.Priv.N6510;
1642  char buf[20 + (2 * (GSM_MAX_FILENAME_ID_LENGTH + 1))];
1643 
1645 
1646  if (start) {
1647  Priv->UseFs1 = TRUE;
1649  /* series 40 3.0 don't have filesystem 1 */
1650  Priv->UseFs1 = FALSE;
1651  }
1653  Priv->UseFs1 = FALSE;
1654  }
1655  }
1656  if (Priv->UseFs1) {
1657  error = N6510_GetNextFileFolder1(s,File,start);
1658  if (error == ERR_EMPTY) {
1660  return error;
1661  }
1662  Priv->UseFs1 = FALSE;
1663  start = TRUE;
1664  } else {
1665  if (error == ERR_NONE) {
1666  sprintf(buf,"c:/%s",DecodeUnicodeString(File->ID_FullName));
1667  EncodeUnicode(File->ID_FullName,buf,strlen(buf));
1668 
1669  if (File->Level != 1) return error;
1670 
1671  buf[0] = 0;
1672  buf[1] = 0;
1673  CopyUnicodeString(buf,File->Name);
1674  EncodeUnicode(File->Name,"C (",3);
1675  CopyUnicodeString(File->Name+6,buf);
1676  EncodeUnicode(File->Name+UnicodeLength(File->Name)*2,")",1);
1677  }
1678  return error;
1679  }
1680  }
1681  return N6510_GetNextFileFolder2(s,File,start);
1682 }
1683 
1684 GSM_Error N6510_GetFilePart(GSM_StateMachine *s, GSM_File *File, int *Handle, size_t *Size)
1685 {
1686  GSM_File File2;
1687  char buf[20 + (2 * (GSM_MAX_FILENAME_ID_LENGTH + 1))];
1688  GSM_Error error;
1689 
1691 
1692  if (DecodeUnicodeString(File->ID_FullName)[0] == 'c' ||
1693  DecodeUnicodeString(File->ID_FullName)[0] == 'C') {
1696  return ERR_NOTSUPPORTED;
1697  }
1698  memcpy(&File2,File,sizeof(GSM_File));
1699  CopyUnicodeString(File2.ID_FullName,File->ID_FullName+3*2);
1700  error = N6510_GetFilePart1(s,&File2, Handle, Size);
1701  CopyUnicodeString(buf,File->ID_FullName);
1702  memcpy(File,&File2,sizeof(GSM_File));
1703  CopyUnicodeString(File->ID_FullName,buf);
1704  return error;
1705  } else {
1707  return N6510_GetFilePart2(s,File, Handle, Size);
1708  } else {
1709  return ERR_NOTSUPPORTED;
1710  }
1711  }
1712 }
1713 
1714 GSM_Error N6510_AddFilePart(GSM_StateMachine *s, GSM_File *File, size_t *Pos, int *Handle)
1715 {
1716  GSM_File File2;
1717  GSM_Error error;
1718 
1720 
1721  if (DecodeUnicodeString(File->ID_FullName)[0] == 'c' ||
1722  DecodeUnicodeString(File->ID_FullName)[0] == 'C') {
1725  return ERR_NOTSUPPORTED;
1726  }
1727 
1728  memcpy(&File2,File,sizeof(GSM_File));
1729  CopyUnicodeString(File2.ID_FullName,File->ID_FullName+3*2);
1730  error = N6510_AddFilePart1(s,&File2,Pos,Handle);
1731  memcpy(File,&File2,sizeof(GSM_File));
1732  /* addfilepart returns new ID */
1733  EncodeUnicode(File->ID_FullName,"c:/",3);
1735  return error;
1736  } else {
1738  return N6510_AddFilePart2(s,File,Pos,Handle);
1739  } else {
1740  return ERR_NOTSUPPORTED;
1741  }
1742  }
1743 }
1744 
1745 GSM_Error N6510_DeleteFile(GSM_StateMachine *s, unsigned char *ID)
1746 {
1748 
1749  if (DecodeUnicodeString(ID)[0] == 'c' ||
1750  DecodeUnicodeString(ID)[0] == 'C') {
1753  return ERR_NOTSUPPORTED;
1754  }
1755 
1756  return N6510_DeleteFile1(s,ID+6);
1757  } else {
1759  return N6510_DeleteFile2(s,ID);
1760  } else {
1761  return ERR_NOTSUPPORTED;
1762  }
1763  }
1764 }
1765 
1767 {
1768  GSM_File File2;
1769  GSM_Error error;
1770 
1772 
1773  if (DecodeUnicodeString(File->ID_FullName)[0] == 'c' ||
1774  DecodeUnicodeString(File->ID_FullName)[0] == 'C') {
1777  return ERR_NOTSUPPORTED;
1778  }
1779  memcpy(&File2,File,sizeof(GSM_File));
1780  CopyUnicodeString(File2.ID_FullName,File->ID_FullName+3*2);
1781  error = N6510_AddFolder1(s,&File2);
1782  memcpy(File,&File2,sizeof(GSM_File));
1783  /* addfolder returns new ID */
1784  EncodeUnicode(File->ID_FullName,"c:/",3);
1786  return error;
1787  } else {
1789  return N6510_AddFolder2(s,File);
1790  } else {
1791  return ERR_NOTSUPPORTED;
1792  }
1793  }
1794 }
1795 
1796 GSM_Error N6510_DeleteFolder(GSM_StateMachine *s, unsigned char *ID)
1797 {
1799 
1800  if (DecodeUnicodeString(ID)[0] == 'c' ||
1801  DecodeUnicodeString(ID)[0] == 'C') {
1804  return ERR_NOTSUPPORTED;
1805  }
1806  return N6510_DeleteFolder1(s,ID+6);
1807  } else {
1809  return N6510_DeleteFolder2(s,ID);
1810  } else {
1811  return ERR_NOTSUPPORTED;
1812  }
1813  }
1814 }
1815 
1817 {
1819 
1821  return ERR_NOTSUPPORTED;
1822  } else {
1825  return ERR_NOTSUPPORTED;
1826  }
1827  return N6510_GetFileSystemStatus1(s,status);
1828  }
1829 }
1830 
1832 {
1833  GSM_File File2;
1834  char buf[20 + (2 * (GSM_MAX_FILENAME_ID_LENGTH + 1))];
1835  GSM_Error error;
1836 
1838 
1839  if (DecodeUnicodeString(File->ID_FullName)[0] == 'c' ||
1840  DecodeUnicodeString(File->ID_FullName)[0] == 'C') {
1843  return ERR_NOTSUPPORTED;
1844  }
1845  memcpy(&File2,File,sizeof(GSM_File));
1846  CopyUnicodeString(File2.ID_FullName,File->ID_FullName+3*2);
1847  error = N6510_SetFileAttributes1(s,&File2);
1848  CopyUnicodeString(buf,File->ID_FullName);
1849  memcpy(File,&File2,sizeof(GSM_File));
1850  CopyUnicodeString(File->ID_FullName,buf);
1851  return error;
1852  } else {
1854  return N6510_SetFileAttributes2(s,File);
1855  } else {
1856  return ERR_NOTSUPPORTED;
1857  }
1858  }
1859 }
1860 
1862 {
1863  GSM_Error error;
1864  GSM_File File2;
1865  unsigned char buffer[5];
1866 
1868 
1869  memset(&File2, 0, sizeof(File2));
1870 
1873  if (UnicodeLength(File->ID_FullName) == 0) {
1874  EncodeUnicode(File->ID_FullName,"d:",2);
1875  EncodeUnicode(File->Name,"D (Permanent_memory 2)",22);
1876  } else if (!strcmp(DecodeUnicodeString(File->ID_FullName),"d:")) {
1877  EncodeUnicode(File->ID_FullName,"a:",2);
1878  error = N6510_GetFolderListing2(s, File, TRUE);
1879  if (error != ERR_NONE && error != ERR_EMPTY) return ERR_EMPTY;
1880  EncodeUnicode(File->Name,"A (Memory card)",15);
1881  EncodeUnicode(File->ID_FullName,"a:",2);
1882  } else {
1883  return ERR_EMPTY;
1884  }
1885  return ERR_NONE;
1886  }
1887 
1888  if (UnicodeLength(File->ID_FullName) == 0) {
1889  sprintf(buffer,"%i",0x01);
1890  EncodeUnicode(File2.ID_FullName,buffer,strlen(buffer));
1891  File2.Level = 1;
1892 
1893  error = N6510_GetFileFolderInfo1(s, &File2, FALSE);
1894  if (error != ERR_NONE) return error;
1895  }
1896 
1898  if (UnicodeLength(File->ID_FullName) == 0) {
1899  memcpy(File,&File2,sizeof(GSM_File));
1900  EncodeUnicode(File->Name,"C (",3);
1901  CopyUnicodeString(File->Name+6,File2.Name);
1902  EncodeUnicode(File->Name+UnicodeLength(File->Name)*2,")",1);
1903  sprintf(buffer,"c:\\%i",0x01);
1904  EncodeUnicode(File->ID_FullName,buffer,strlen(buffer));
1905  } else if (!strcmp(DecodeUnicodeString(File->ID_FullName),"c:\\1")) {
1906  EncodeUnicode(File->ID_FullName,"d:",2);
1907  EncodeUnicode(File->Name,"D (Permanent_memory 2)",22);
1908  } else if (!strcmp(DecodeUnicodeString(File->ID_FullName),"d:")) {
1909  EncodeUnicode(File->ID_FullName,"a:",2);
1910  error = N6510_GetFolderListing2(s, File, TRUE);
1911  if (error != ERR_NONE && error != ERR_EMPTY) return ERR_EMPTY;
1912  EncodeUnicode(File->Name,"A (Memory card)",15);
1913  EncodeUnicode(File->ID_FullName,"a:",2);
1914  } else {
1915  return ERR_EMPTY;
1916  }
1917  return ERR_NONE;
1918  }
1919  if (UnicodeLength(File->ID_FullName) == 0) {
1920  memcpy(File,&File2,sizeof(GSM_File));
1921  EncodeUnicode(File->Name,"C (",3);
1922  CopyUnicodeString(File->Name+6,File2.Name);
1923  EncodeUnicode(File->Name+UnicodeLength(File->Name)*2,")",1);
1924  sprintf(buffer,"c:\\%i",0x01);
1925  EncodeUnicode(File->ID_FullName,buffer,strlen(buffer));
1926  } else if (!strcmp(DecodeUnicodeString(File->ID_FullName),"c:\\1")) {
1927  return ERR_EMPTY;
1928  }
1929  return ERR_NONE;
1930 }
1931 
1932 GSM_Error N6510_PrivGet3220FilesystemMMSFolders(GSM_StateMachine *s, GSM_MMSFolders *folders)
1933 {
1934  GSM_Phone_N6510Data *Priv = &s->Phone.Data.Priv.N6510;
1935  gboolean Start = TRUE;
1936  GSM_File Files;
1937  GSM_Error error;
1938 
1939  memset(&Files, 0, sizeof(Files));
1940 
1941  EncodeUnicode(Files.ID_FullName,"d:/predefmessages",17);
1942 
1943  folders->Number = 0;
1944 
1945  smprintf(s, "Getting MMS folders\n");
1946  while (1) {
1947  error = N6510_GetFolderListing(s,&Files,Start);
1948  if (error == ERR_EMPTY) return ERR_NONE;
1949  if (error != ERR_NONE) return error;
1950 
1951  Start = FALSE;
1952 
1953  folders->Folder[folders->Number].InboxFolder = FALSE;
1954  if (!strcmp(DecodeUnicodeString(Files.Name),"predefinbox")) {
1955  folders->Folder[folders->Number].InboxFolder = TRUE;
1956  }
1957 
1958  CopyUnicodeString(Priv->MMSFoldersID2[folders->Number],Files.ID_FullName);
1959 
1960  if (!strcmp(DecodeUnicodeString(Files.Name),"predefinbox")) {
1961  EncodeUnicode(folders->Folder[folders->Number].Name,"Inbox",5);
1962  } else if (!strcmp(DecodeUnicodeString(Files.Name),"predefsent")) {
1963  EncodeUnicode(folders->Folder[folders->Number].Name,"Sent items",10);
1964  } else if (!strcmp(DecodeUnicodeString(Files.Name),"predefoutbox")) {
1965  EncodeUnicode(folders->Folder[folders->Number].Name,"Outbox",6);
1966  } else if (!strcmp(DecodeUnicodeString(Files.Name),"predefdrafts")) {
1967  EncodeUnicode(folders->Folder[folders->Number].Name,"Templates",9);
1968  } else {
1969  continue;
1970  }
1971 
1972  folders->Number++;
1973  }
1974 }
1975 
1976 /* Series 40 3.0 */
1977 GSM_Error N6510_PrivGetFilesystemMMSFolders(GSM_StateMachine *s, GSM_MMSFolders *folders)
1978 {
1979  GSM_Phone_N6510Data *Priv = &s->Phone.Data.Priv.N6510;
1980  gboolean Start = TRUE;
1981  GSM_File Files;
1982  GSM_Error error;
1983 
1984  memset(&Files, 0, sizeof(Files));
1985 
1986  EncodeUnicode(Files.ID_FullName,"d:/predefmessages",17);
1987 
1988  folders->Number = 0;
1989 
1990  smprintf(s, "Getting MMS folders\n");
1991  while (1) {
1992  error = N6510_GetFolderListing(s,&Files,Start);
1993  if (error == ERR_EMPTY) return ERR_NONE;
1994  if (error != ERR_NONE) return error;
1995 
1996  Start = FALSE;
1997 
1998  if (!strcmp(DecodeUnicodeString(Files.Name),"exchange")) {
1999  continue;
2000  } else if (!strcmp(DecodeUnicodeString(Files.Name),"predefdrafts")) {
2001  continue;
2002  } else if (!strcmp(DecodeUnicodeString(Files.Name),"predefsent")) {
2003  continue;
2004  } else if (!strcmp(DecodeUnicodeString(Files.Name),"predefoutbox")) {
2005  continue;
2006  } else if (!strcmp(DecodeUnicodeString(Files.Name),"predefinbox")) {
2007  continue;
2008  }
2009 
2010  folders->Folder[folders->Number].InboxFolder = FALSE;
2011  if (!strcmp(DecodeUnicodeString(Files.Name),"1")) {
2012  folders->Folder[folders->Number].InboxFolder = TRUE;
2013  }
2014 
2015  CopyUnicodeString(Priv->MMSFoldersID2[folders->Number],Files.ID_FullName);
2016 
2017  if (!strcmp(DecodeUnicodeString(Files.Name),"1")) {
2018  EncodeUnicode(folders->Folder[folders->Number].Name,"Inbox",5);
2019  } else if (!strcmp(DecodeUnicodeString(Files.Name),"3")) {
2020  EncodeUnicode(folders->Folder[folders->Number].Name,"Sent items",10);
2021  } else if (!strcmp(DecodeUnicodeString(Files.Name),"4")) {
2022  EncodeUnicode(folders->Folder[folders->Number].Name,"Saved messages",14);
2023  } else if (!strcmp(DecodeUnicodeString(Files.Name),"5")) {
2024  EncodeUnicode(folders->Folder[folders->Number].Name,"Drafts",6);
2025  } else if (!strcmp(DecodeUnicodeString(Files.Name),"6")) {
2026  EncodeUnicode(folders->Folder[folders->Number].Name,"Templates",9);
2027  } else {
2028  CopyUnicodeString(folders->Folder[folders->Number].Name,Files.Name);
2029  }
2030 
2031  folders->Number++;
2032  }
2033 }
2034 
2036 {
2037  GSM_Error error;
2038  GSM_File Files;
2039  gboolean Start = TRUE;
2040  GSM_Phone_N6510Data *Priv = &s->Phone.Data.Priv.N6510;
2041  int i;
2042 
2043 
2045 
2046  memset(&Files, 0, sizeof(Files));
2047 
2048  for (i=0;i<10;i++) {
2049  Priv->MMSFoldersID2[i][0] = 0;
2050  Priv->MMSFoldersID2[i][1] = 0;
2051  }
2052 
2054  return N6510_PrivGet3220FilesystemMMSFolders(s,folders);
2055  }
2056 
2058  return N6510_PrivGetFilesystemMMSFolders(s,folders);
2059  }
2060 
2061  EncodeUnicode(Files.ID_FullName,"c:/1",4);
2062  while (1) {
2063  error = N6510_GetFolderListing(s,&Files,Start);
2064  if (error == ERR_EMPTY) break;
2065  if (error != ERR_NONE) return error;
2066  Start = FALSE;
2067  if (!Files.Folder || strcmp(DecodeUnicodeConsole(Files.Name),"Messages")) {
2068  continue;
2069  }
2070  Start = TRUE;
2071  folders->Number = 0;
2072 
2073  while (1) {
2074  error = N6510_GetFolderListing(s,&Files,Start);
2075  if (error == ERR_EMPTY) return ERR_NONE;
2076  if (error != ERR_NONE) return error;
2077  Start = FALSE;
2078  if (!Files.Folder) continue;
2079  CopyUnicodeString(folders->Folder[folders->Number].Name,Files.Name);
2080  CopyUnicodeString(Priv->MMSFoldersID2[folders->Number],Files.ID_FullName);
2081  folders->Folder[folders->Number].InboxFolder = FALSE;
2082  if (!strcmp(DecodeUnicodeString(Files.Name),"Inbox")) {
2083  folders->Folder[folders->Number].InboxFolder = TRUE;
2084  }
2085  folders->Number++;
2086  }
2087  }
2088 
2089  /* 6230i */
2091  EncodeUnicode(Files.ID_FullName,"d:/predefmessages",17);
2092  folders->Number = 0;
2093  Start = TRUE;
2094  while (1) {
2095  error = N6510_GetFolderListing(s,&Files,Start);
2096  if (error == ERR_EMPTY) break;
2097  if (error != ERR_NONE) return error;
2098  Start = FALSE;
2099  if (!Files.Folder) continue;
2100  folders->Folder[folders->Number].InboxFolder = FALSE;
2101  if (!strcmp(DecodeUnicodeString(Files.Name),"predefinbox")) {
2102  EncodeUnicode(folders->Folder[folders->Number].Name,"Inbox",5);
2103  folders->Folder[folders->Number].InboxFolder = TRUE;
2104  } else if (!strcmp(DecodeUnicodeString(Files.Name),"predefoutbox")) {
2105  EncodeUnicode(folders->Folder[folders->Number].Name,"Outbox",6);
2106  } else if (!strcmp(DecodeUnicodeString(Files.Name),"predefsent")) {
2107  EncodeUnicode(folders->Folder[folders->Number].Name,"Sent items",10);
2108  } else if (!strcmp(DecodeUnicodeString(Files.Name),"predefdrafts")) {
2109  EncodeUnicode(folders->Folder[folders->Number].Name,"Drafts",6);
2110  } else {
2111  CopyUnicodeString(folders->Folder[folders->Number].Name,Files.Name);
2112  }
2113  CopyUnicodeString(Priv->MMSFoldersID2[folders->Number],Files.ID_FullName);
2114  folders->Number++;
2115  }
2116 
2117  return ERR_NONE;
2118  }
2119 
2120  return ERR_NOTSUPPORTED;
2121 }
2122 
2123 GSM_Error N6510_GetNextMMSFileInfo(GSM_StateMachine *s, unsigned char *FileID, int *MMSFolder, gboolean start)
2124 {
2125  GSM_MMSFolders folders;
2126  GSM_Phone_N6510Data *Priv = &s->Phone.Data.Priv.N6510;
2127  GSM_Error error;
2128  GSM_File file;
2129  int Handle;
2130  size_t Size;
2131 
2132  if (start) {
2133  error = N6510_GetMMSFolders(s, &folders);
2134  if (error != ERR_NONE)
2135  return error;
2136 
2137  Priv->MMSFolderNum = 0;
2138  Priv->MMSFolderError = ERR_EMPTY;
2139  }
2140 
2141  while(TRUE) {
2142  if (Priv->MMSFolderError == ERR_NONE) {
2144  if (Priv->MMSFolderError != ERR_EMPTY && Priv->MMSFolderError != ERR_NONE)
2145  return Priv->MMSFolderError;
2146  }
2147 
2148  if (Priv->MMSFolderError == ERR_EMPTY) {
2149  while (1) {
2150  if (UnicodeLength(Priv->MMSFoldersID2[Priv->MMSFolderNum]) == 0)
2151  return ERR_EMPTY;
2152 
2154  Priv->MMSFolderNum++;
2155 
2157  if (Priv->MMSFolderError == ERR_EMPTY)
2158  continue;
2159  if (Priv->MMSFolderError != ERR_NONE)
2160  return Priv->MMSFolderError;
2161  break;
2162  }
2163  }
2164  (*MMSFolder) = Priv->MMSFolderNum;
2165  CopyUnicodeString(FileID,Priv->MMSFile.ID_FullName);
2166 
2168  CopyUnicodeString(file.ID_FullName,FileID);
2169  file.Used = 0;
2170  file.Buffer = NULL;
2171  error = N6510_GetFilePart2(s, &file, &Handle, &Size);
2172  if (error == ERR_NONE) {
2173  error = N6510_CloseFile2(s, &Handle);
2174  if (error != ERR_NONE)
2175  return error;
2176  } else if (error != ERR_EMPTY) {
2177  return error;
2178  }
2179 
2180  /* 0x00 = SMS, 0x01,0x03 = MMS */
2181  if (file.Buffer[6] != 0x00) {
2182  free(file.Buffer);
2183  file.Buffer = NULL;
2184  break;
2185  }
2186  free(file.Buffer);
2187  file.Buffer = NULL;
2188  } else {
2189  break;
2190  }
2191  }
2192 
2193  return ERR_NONE;
2194 }
2195 
2196 /* Series 40 3.0 */
2197 GSM_Error N6510_PrivGetFilesystemSMSFolders(GSM_StateMachine *s, GSM_SMSFolders *folders, gboolean real)
2198 {
2199  gboolean Start = TRUE;
2200  GSM_File Files;
2201  GSM_Error error;
2202 
2203  EncodeUnicode(Files.ID_FullName,"d:/predefmessages",17);
2204 
2205  folders->Number = 0;
2206 
2207  smprintf(s, "Getting SMS folders\n");
2208  while (1) {
2209  error = N6510_GetFolderListing(s,&Files,Start);
2210  if (error == ERR_EMPTY) return ERR_NONE;
2211  if (error != ERR_NONE) return error;
2212 
2213  Start = FALSE;
2214 
2215  smprintf(s, "Folder name: '%s'\n", DecodeUnicodeString(Files.Name));
2216 
2217  if (!strcmp(DecodeUnicodeString(Files.Name),"exchange")) {
2218  continue;
2219  } else if (!strcmp(DecodeUnicodeString(Files.Name),"predefdrafts")) {
2220  continue;
2221  } else if (!strcmp(DecodeUnicodeString(Files.Name),"predefsent")) {
2222  continue;
2223  } else if (!strcmp(DecodeUnicodeString(Files.Name),"predefoutbox")) {
2224  continue;
2225  } else if (!strcmp(DecodeUnicodeString(Files.Name),"predefinbox")) {
2226  continue;
2227  }
2228 
2229  folders->Folder[folders->Number].InboxFolder = FALSE;
2230  if (!strcmp(DecodeUnicodeString(Files.Name),"1")) {
2231  folders->Folder[folders->Number].InboxFolder = TRUE;
2232  }
2233  folders->Folder[folders->Number].OutboxFolder = FALSE;
2234  if (!strcmp(DecodeUnicodeString(Files.Name),"2")) {
2235  folders->Folder[folders->Number].OutboxFolder = TRUE;
2236  }
2237  if (real) {
2238  CopyUnicodeString(folders->Folder[folders->Number].Name,Files.Name);
2239  } else {
2240  if (!strcmp(DecodeUnicodeString(Files.Name),"1")) {
2241  EncodeUnicode(folders->Folder[folders->Number].Name,"Inbox",5);
2242  } else if (!strcmp(DecodeUnicodeString(Files.Name),"2")) {
2243  EncodeUnicode(folders->Folder[folders->Number].Name,"Outbox",6);
2244  } else if (!strcmp(DecodeUnicodeString(Files.Name),"3")) {
2245  EncodeUnicode(folders->Folder[folders->Number].Name,"Sent items",10);
2246  } else if (!strcmp(DecodeUnicodeString(Files.Name),"4")) {
2247  EncodeUnicode(folders->Folder[folders->Number].Name,"Saved messages",14);
2248  } else if (!strcmp(DecodeUnicodeString(Files.Name),"5")) {
2249  EncodeUnicode(folders->Folder[folders->Number].Name,"Drafts",6);
2250  } else if (!strcmp(DecodeUnicodeString(Files.Name),"6")) {
2251  EncodeUnicode(folders->Folder[folders->Number].Name,"Templates",9);
2252  } else {
2253  EncodeUnicode(folders->Folder[folders->Number].Name,"User folder ",12);
2254  CopyUnicodeString(folders->Folder[folders->Number].Name + 24, Files.Name);
2255  }
2256  }
2257  folders->Folder[folders->Number].Memory = MEM_ME;
2258  smprintf(s, "Folder[%d] = \"%s\", memory: %s, inbox: %d, outbox: %d\n",
2259  folders->Number,
2260  DecodeUnicodeString(folders->Folder[folders->Number].Name),
2261  GSM_MemoryTypeToString(folders->Folder[folders->Number].Memory),
2262  folders->Folder[folders->Number].InboxFolder,
2263  folders->Folder[folders->Number].OutboxFolder);
2264  folders->Number++;
2265  }
2266 }
2267 
2268 /* Series 40 3.0 */
2270 {
2271  return N6510_PrivGetFilesystemSMSFolders(s, folders, FALSE);
2272 }
2273 
2274 /* Series 40 3.0 */
2275 static void N26510_GetSMSLocation(GSM_StateMachine *s, GSM_SMSMessage *sms, unsigned char *folderid, int *location)
2276 {
2277  int ifolderid;
2278 
2279  /* simulate flat SMS memory */
2280  if (sms->Folder==0x00) {
2281  ifolderid = sms->Location / GSM_PHONE_MAXSMSINFOLDER;
2282  *folderid = ifolderid + 0x01;
2283  *location = sms->Location - ifolderid * GSM_PHONE_MAXSMSINFOLDER;
2284  } else {
2285  *folderid = sms->Folder;
2286  *location = sms->Location;
2287  }
2288  smprintf(s, "SMS folder %i & location %i -> 6510 folder %i & location %i\n",
2289  sms->Folder,sms->Location,*folderid,*location);
2290 }
2291 
2292 /* Series 40 3.0 */
2293 static void N26510_SetSMSLocation(GSM_StateMachine *s, GSM_SMSMessage *sms, unsigned char folderid, int location)
2294 {
2295  sms->Folder = 0;
2296  sms->Location = (folderid - 0x01) * GSM_PHONE_MAXSMSINFOLDER + location;
2297  smprintf(s, "6510 folder %i & location %i -> SMS folder %i & location %i\n",
2298  folderid,location,sms->Folder,sms->Location);
2299 }
2300 
2301 /* Series 40 3.0 */
2302 GSM_Error N6510_DecodeFilesystemSMS(GSM_StateMachine *s, GSM_MultiSMSMessage *sms, GSM_File *FFF, int location)
2303 {
2304  GSM_Phone_N6510Data *Priv = &s->Phone.Data.Priv.N6510;
2305  size_t parse_len, pos;
2306  int loc;
2307  GSM_Error error;
2308  gboolean unknown, has_number;
2309 
2310  sms->Number = 1;
2311  sms->SMS[0].OtherNumbersNum = 0;
2312 
2313  loc = sms->SMS[0].Location;
2314 
2315  if (FFF->Used < 96) {
2316  smprintf(s, "Too short message data!\n");
2317  return ERR_CORRUPTED;
2318  }
2319 
2320  /* Copy recipient/sender number */
2321  /* Data we get from PDU seem to be bogus */
2322  /* This might be later overwriten using tags at the end of file */
2323  CopyUnicodeString(sms->SMS[0].Number, FFF->Buffer + 94);
2324  smprintf(s, "SMS number: %s\n", DecodeUnicodeString(sms->SMS[0].Number));
2325  has_number = FALSE;
2326 
2327  /* Do we have any PDU data? */
2328  if (FFF->Buffer[7] > 0 && FFF->Used > 176) {
2329  /* Parse PDU data */
2330  error = GSM_DecodePDUFrame(&(s->di), &(sms->SMS[0]), FFF->Buffer + 176, FFF->Used - 176, &parse_len, FALSE);
2331  if (error != ERR_NONE) return error;
2332 
2333  sms->SMS[0].Location = loc;
2334 
2335  switch (sms->SMS[0].PDU) {
2336  case SMS_Deliver:
2337  sms->SMS[0].State = SMS_Read; /* @bug FIXME: this is wrong */
2338  break;
2339  case SMS_Submit:
2340  sms->SMS[0].State = SMS_Sent; /* @bug FIXME: this is wrong */
2341  break;
2342  case SMS_Status_Report:
2343  sms->SMS[0].State = SMS_Read; /* @bug FIXME: this is wrong */
2344  break;
2345  }
2346 
2347  if (parse_len != FFF->Buffer[7]) {
2348  smprintf(s, "ERROR: Parsed PDU data have different length than header says!\n");
2349  return ERR_CORRUPTED;
2350  }
2351  } else {
2353  sms->SMS[0].PDU = SMS_Submit;
2354  sms->SMS[0].State = SMS_Read; /* @bug FIXME: this is wrong */
2355  }
2356 
2357  /* Process structured data */
2358  pos = 176 + FFF->Buffer[7];
2359 
2360  /* No structured data? */
2361  if (pos >= FFF->Used) {
2362  goto done;
2363  }
2364 
2365  /* First master block - 0x01 <WORD LENGTH> */
2366  if (FFF->Buffer[pos] != 0x01) {
2367  smprintf(s, "Unknown block in SMS data after PDU: 0x%02x\n", FFF->Buffer[pos]);
2368  DumpMessage(&(s->di), FFF->Buffer + pos, FFF->Used - pos);
2369  return ERR_UNKNOWN;
2370  }
2371  pos += 3;
2372 
2373  while (pos < FFF->Used) {
2374  unknown = FALSE;
2375  if (pos + 1 >= FFF->Used) {
2376  if (pos + 1 == FFF->Used && FFF->Buffer[pos] == 0x00) {
2377  smprintf(s, "File padded with 0x00, assuming it is okay\n");
2378  break;
2379  }
2380  smprintf(s, "ERROR: Reach end of file before type of block!\n");
2381  return ERR_BUG;
2382  }
2383  if (FFF->Buffer[pos] == 0x00) {
2384  smprintf(s, "WARNING: 0x00 block, assuming rest is just junk!\n");
2385  break;
2386  }
2387  if (pos + 2 == FFF->Used && FFF->Buffer[pos] == 0x01) {
2388  smprintf(s, "WARNING: 0x01 block, assuming rest is just junk!\n");
2389  break;
2390  }
2391  if (pos + 2 >= FFF->Used) {
2392  smprintf(s, "ERROR: Reach end of file before size of block!\n");
2393  return ERR_BUG;
2394  }
2395  switch (FFF->Buffer[pos]) {
2396  case 0x02: /* SMSC number, ASCII */
2397  if (FFF->Buffer[pos + 2] <= 1) break;
2398  if (FFF->Buffer[pos + 2] - 1 > GSM_MAX_NUMBER_LENGTH) {
2399  smprintf(s, "WARNING: Too long SMS number, ignoring!\n");
2400  } else {
2401  EncodeUnicode(sms->SMS[0].SMSC.Number, FFF->Buffer + pos + 3, FFF->Buffer[pos + 2]);
2402  }
2403  break;
2404  case 0x03: /* Name, unicode */
2405  if (FFF->Buffer[pos + 2] <= 1) break;
2406  if (FFF->Buffer[pos + 2]/2 - 1 > GSM_MAX_SMS_NAME_LENGTH) {
2407  smprintf(s, "WARNING: Too long SMS name, ignoring!\n");
2408  } else {
2409  CopyUnicodeString(sms->SMS[0].Name, FFF->Buffer + pos + 3);
2410  }
2411  break;
2412  case 0x04: /* Sender, unicode */
2413  case 0x05: /* Recipient, unicode */
2414  case 0x2b: /* some text (Sender?), unicode */
2415  if (FFF->Buffer[pos + 2] <= 1) break;
2416  if (FFF->Buffer[pos + 2]/2 - 1 > GSM_MAX_NUMBER_LENGTH) {
2417  smprintf(s, "WARNING: Too long SMS number, ignoring!\n");
2418  } else {
2419  if (!has_number) {
2420  CopyUnicodeString(sms->SMS[0].Number, FFF->Buffer + pos + 3);
2421  has_number = TRUE;
2422  } else {
2423  if (sms->SMS[0].OtherNumbersNum < GSM_SMS_OTHER_NUMBERS) {
2424  CopyUnicodeString(sms->SMS[0].OtherNumbers[sms->SMS[0].OtherNumbersNum++], FFF->Buffer + pos + 3);
2425  } else {
2426  smprintf(s, "WARNING: Too many recipients, ignoring some!\n");
2427  }
2428  }
2429  }
2430  break;
2431  case 0x25: /* Some unicode text (Name?) */
2432  case 0x20: /* Some ascii text (GmailId) */
2433  unknown = TRUE;
2434  break;
2435  case 0x01:
2436  /* This is probably 0 = received, 1 = sent */
2437  if (FFF->Buffer[pos + 2] != 1 ||
2438  (FFF->Buffer[pos + 3] != 0x00 && FFF->Buffer[pos + 3] != 0x01)) {
2439  unknown = TRUE;
2440  }
2441  break;
2442  case 0x0c:
2443  /* This seems to be message ID (per number) */
2444  break;
2445  case 0x24:
2446  /* 24$|00 |01 |01 */
2447  /* 24$|00 |01 |00 */
2448  if ((FFF->Buffer[pos + 2] != 1 || FFF->Buffer[pos + 3] != 1) &&
2449  (FFF->Buffer[pos + 2] != 1 || FFF->Buffer[pos + 3] != 0)) {
2450  unknown = TRUE;
2451  }
2452  break;
2453  case 0x07:
2454  if (FFF->Buffer[pos + 2] != 1 || (FFF->Buffer[pos + 3] != 0x00F && FFF->Buffer[pos + 3] != 0x0e)) {
2455  unknown = TRUE;
2456  }
2457  break;
2458  case 0x0b:
2459  case 0x0e:
2460  case 0x22:
2461  /* 22"|00 |01 |84 */
2462  case 0x26:
2463  case 0x27:
2464  case 0x2a:
2465  case 0x2f:
2466  case 0x08:
2467  if (FFF->Buffer[pos + 2] != 1 || FFF->Buffer[pos + 3] != 0x00) {
2468  unknown = TRUE;
2469  }
2470  break;
2471  case 0x06:
2472  case 0x09:
2473  case 0x12:
2474  /* Some ID: 12 |00 |04 |355|EA |6En|D2 */
2475  case 0x23:
2476  /* Some ID: 23#|00 |04 |00 |00 |09 |A6 */
2477  case 0x2D:
2478  /* Some ID: 2D-|00 |04 |00 |00 |00 |00 */
2479  if (FFF->Buffer[pos + 2] != 4 ||
2480  FFF->Buffer[pos + 3] != 0x00 ||
2481  FFF->Buffer[pos + 4] != 0x00 ||
2482  FFF->Buffer[pos + 5] != 0x00 ||
2483  FFF->Buffer[pos + 6] != 0x00
2484  ) {
2485  unknown = TRUE;
2486  }
2487  break;
2488  case 0x0f:
2489  if (FFF->Buffer[pos + 2] != 2 ||
2490  FFF->Buffer[pos + 3] != 0x00 ||
2491  FFF->Buffer[pos + 4] != 0x00
2492  ) {
2493  unknown = TRUE;
2494  }
2495  break;
2496  default:
2497  unknown = TRUE;
2498  break;
2499  }
2500  if (unknown) {
2501  smprintf(s, "WARNING: Unknown block 0x%02x, see <https://wammu.eu/support/bugs/> how to report\n", FFF->Buffer[pos]);
2502  DumpMessage(&(s->di), FFF->Buffer + pos, 3 + (FFF->Buffer[pos + 1] << 8) + FFF->Buffer[pos + 2]);
2503 #ifdef DEBUG
2504  } else {
2505  smprintf(s, "Decoded block 0x%02x\n", FFF->Buffer[pos]);
2506  DumpMessage(&(s->di), FFF->Buffer + pos, 3 + (FFF->Buffer[pos + 1] << 8) + FFF->Buffer[pos + 2]);
2507 #endif
2508  }
2509  pos += 3 + (FFF->Buffer[pos + 1] << 8) + FFF->Buffer[pos + 2];
2510  }
2511 
2512 done:
2513  sms->SMS[0].DateTime = FFF->Modified;
2514  sms->SMS[0].DateTime.Timezone = 0;
2515 
2516  free(FFF->Buffer);
2517  FFF->Buffer = NULL;
2518 
2519  N26510_SetSMSLocation(s, &sms->SMS[0], 0, location);
2520 
2521  sms->SMS[0].Folder = Priv->SMSFileFolder;
2522  smprintf(s, "Folder[%d] %s: %d\n", sms->SMS[0].Folder, DecodeUnicodeString(Priv->LastSMSFolders.Folder[sms->SMS[0].Folder].Name), Priv->LastSMSFolders.Folder[sms->SMS[0].Folder].InboxFolder);
2523  sms->SMS[0].InboxFolder = Priv->LastSMSFolders.Folder[sms->SMS[0].Folder].InboxFolder;
2524  sms->SMS[0].Location = 0; /* fixme */
2525 
2526  return ERR_NONE;
2527 }
2528 
2530 {
2531  GSM_Phone_N6510Data *Priv = &s->Phone.Data.Priv.N6510;
2532  unsigned char folderid;
2533  int location,Handle;
2534  size_t Size;
2535  GSM_Error error;
2536  GSM_File FFF;
2537  gboolean start2=start;
2538 
2540 
2541  while (TRUE) {
2542  if (start2) {
2543  Priv->SMSFileError = ERR_EMPTY;
2544  Priv->SMSFileFolder = 0;
2545  location = 1;
2546  error=N6510_PrivGetFilesystemSMSFolders(s,&Priv->LastSMSFolders,TRUE);
2547  if (error!=ERR_NONE) return error;
2548  } else {
2549  sms->SMS[0].Folder = 0;
2550  N26510_GetSMSLocation(s, &sms->SMS[0], &folderid, &location);
2551  location++;
2552  if (Priv->SMSFileError != ERR_EMPTY) {
2554  }
2555  }
2556  start2 = FALSE;
2557  while (Priv->SMSFileError == ERR_EMPTY) {
2558  Priv->SMSFileFolder++;
2559  /* Too high folder number */
2560  if (Priv->SMSFileFolder > Priv->LastSMSFolders.Number) {
2561  return ERR_EMPTY;
2562  }
2563 
2564  EncodeUnicode(Priv->SMSFile.ID_FullName, "d:/predefmessages/", 18);
2566  smprintf(s,"folder name is %s\n", DecodeUnicodeString(Priv->SMSFile.ID_FullName));
2567 
2568  Priv->SMSFileError = N6510_GetFolderListing(s,&Priv->SMSFile,TRUE);
2569  }
2570 
2571  /* readfile */
2572  FFF.Buffer= NULL;
2573  FFF.Used = 0;
2574  FFF.ID_FullName[0] = 0;
2575  FFF.ID_FullName[1] = 0;
2577  smprintf(s,"sms file name is %s\n",DecodeUnicodeString(FFF.ID_FullName));
2578  error = ERR_NONE;
2579  while (error == ERR_NONE) {
2580  error = N6510_GetFilePart(s,&FFF,&Handle,&Size);
2581  /* if mms, don't read all */
2582  if (error==ERR_NONE && FFF.Used>5 && FFF.Buffer[6] != 0x00) {
2583  error = N6510_CloseFile2(s, &Handle);
2584  if (error != ERR_NONE) return error;
2585  break;
2586  }
2587  }
2588  if (FFF.Buffer != NULL) {
2589  DumpMessage(&s->di, FFF.Buffer, FFF.Used);
2590 
2591  /* 0x00 = SMS, 0x01,0x03 = MMS
2592  * We care only messages with PDU */
2593  if (FFF.Buffer[6] == 0x00 && FFF.Buffer[7] != 0) break;
2594 
2595 
2596  smprintf(s,"mms file");
2597  free(FFF.Buffer);
2598  FFF.Buffer = NULL;
2599  }
2600  }
2601 
2602  return N6510_DecodeFilesystemSMS(s, sms, &FFF, location);
2603 }
2604 #endif
2605 
2606 /* How should editor hadle tabs in this file? Add editor commands here.
2607  * vim: noexpandtab sw=8 ts=8 sts=8:
2608  */
GSM_SMSMessageType PDU
GSM_DateTime DateTime
GSM_File MMSFile
Definition: n6510.h:64
char * DecodeUnicodeConsole(const unsigned char *src)
Definition: coding.c:256
GSM_Error N6510_ReplyDeleteFileFolder1(GSM_Protocol_Message *msg, GSM_StateMachine *s)
void GSM_SetDefaultReceivedSMSData(GSM_SMSMessage *SMS)
Definition: gsmsms.c:1092
GSM_Error N6510_ReplyGetFileFolderInfo1(GSM_Protocol_Message *msg, GSM_StateMachine *s)
unsigned char Name[2 *(GSM_MAX_FILENAME_LENGTH+1)]
Definition: gammu-file.h:74
GSM_Error N6510_ReplyGetFileCRC12(GSM_Protocol_Message *msg, GSM_StateMachine *s)
unsigned char ID_FullName[2 *(GSM_MAX_FILENAME_ID_LENGTH+1)]
Definition: gammu-file.h:90
char * DecodeUnicodeString(const unsigned char *src)
Definition: coding.c:245
void DumpMessage(GSM_Debug_Info *d, const unsigned char *message, const size_t messagesize)
Definition: debug.c:314
unsigned char Number[(GSM_MAX_NUMBER_LENGTH+1) *2]
void CopyUnicodeString(unsigned char *Dest, const unsigned char *Source)
Definition: coding.c:1192
GSM_Error N6510_SetFileAttributes(GSM_StateMachine *s, GSM_File *File)
int Level
Definition: gammu-file.h:82
GSM_Error N6510_AddFilePart(GSM_StateMachine *s, GSM_File *File, size_t *Pos, int *Handle)
GSM_SMS_State State
GSM_Error N6510_ReplySetFileDate2(GSM_Protocol_Message *msg, GSM_StateMachine *s)
int FilesLocationsUsed
Definition: n6510.h:44
GSM_Error N6510_ReplyDeleteFolder2(GSM_Protocol_Message *msg, GSM_StateMachine *s)
#define GSM_PHONE_MAXSMSINFOLDER
Definition: gammu-limits.h:70
GSM_Error N6510_ReplyGetFileSystemStatus1(GSM_Protocol_Message *msg, GSM_StateMachine *s)
#define N6110_FRAME_HEADER
Definition: ncommon.h:8
#define GSM_MAX_NUMBER_LENGTH
Definition: gammu-limits.h:77
GSM_OneMMSFolder Folder[GSM_MAX_MMS_FOLDERS]
GSM_Error N6510_ReplyGetFilePart12(GSM_Protocol_Message *msg, GSM_StateMachine *s)
GSM_Error N6510_ReplyAddFilePart1(GSM_Protocol_Message *msg, GSM_StateMachine *s)
void NOKIA_EncodeDateTime(GSM_StateMachine *s UNUSED, unsigned char *buffer, GSM_DateTime *datetime)
Definition: nfunc.c:1007
GSM_Error N6510_ReplyAddFileHeader1(GSM_Protocol_Message *msg, GSM_StateMachine *s)
GSM_Error
Definition: gammu-error.h:23
gboolean mywstrncasecmp(unsigned const char *a, unsigned const char *b, int num)
Definition: coding.c:1437
GSM_Error GSM_DecodePDUFrame(GSM_Debug_Info *di, GSM_SMSMessage *SMS, const unsigned char *buffer, size_t length, size_t *final_pos, gboolean SMSC)
Definition: gsmsms.c:508
GSM_Debug_Info di
Definition: gsmstate.h:1412
gboolean UseFs1
Definition: n6510.h:50
const char * model
Definition: gammu-info.h:764
GSM_OneSMSFolder Folder[GSM_MAX_SMS_FOLDERS]
#define GSM_MemoryTypeToString(x)
Definition: gammu-memory.h:95
GSM_Error N6510_ReplyAddFolder2(GSM_Protocol_Message *msg, GSM_StateMachine *s)
int GSM_ReadDevice(GSM_StateMachine *s, gboolean waitforreply)
Definition: gsmstate.c:919
GSM_Error N6510_ReplyGetFileFolderInfo2(GSM_Protocol_Message *msg, GSM_StateMachine *s)
size_t UnicodeLength(const unsigned char *str)
Definition: coding.c:186
GSM_Error N6510_AddFolder(GSM_StateMachine *s, GSM_File *File)
GSM_Error N6510_ReplyOpenFile2(GSM_Protocol_Message *msg, GSM_StateMachine *s)
gboolean Folder
Definition: gammu-file.h:78
gboolean ReadOnly
Definition: gammu-file.h:111
#define GSM_MAX_FILENAME_ID_LENGTH
Definition: gammu-limits.h:295
unsigned char OtherNumbers[GSM_SMS_OTHER_NUMBERS][(GSM_MAX_NUMBER_LENGTH+1) *2]
GSM_Error(* WriteMessage)(GSM_StateMachine *s, unsigned const char *buffer, int length, int type)
Definition: gsmstate.h:347
unsigned char * Buffer
Definition: gammu-file.h:94
GSM_FileSystemStatus * FileSystemStatus
Definition: gsmstate.h:646
GSM_SMSFolders LastSMSFolders
Definition: n6510.h:32
GSM_File * File
Definition: gsmstate.h:642
GSM_Error N6510_ReplyDeleteFile2(GSM_Protocol_Message *msg, GSM_StateMachine *s)
GSM_FileType Type
Definition: gammu-file.h:86
gboolean InboxFolder
GSM_PhoneModel * ModelInfo
Definition: gsmstate.h:449
GSM_Error MMSFolderError
Definition: n6510.h:66
GSM_Error N6510_GetMMSFolders(GSM_StateMachine *s, GSM_MMSFolders *folders)
unsigned char Number
GSM_Error N6510_GetNextFileFolder(GSM_StateMachine *s, GSM_File *File, gboolean start)
gboolean FilesEnd
Definition: n6510.h:49
gboolean Protected
Definition: gammu-file.h:107
size_t Used
Definition: gammu-file.h:70
char Name[(GSM_MAX_MMS_FOLDER_NAME_LEN+1) *2]
gboolean System
Definition: gammu-file.h:119
#define GSM_MAX_SMS_NAME_LENGTH
Definition: gammu-limits.h:138
GSM_Error N6510_ReplyAddFolder1(GSM_Protocol_Message *msg, GSM_StateMachine *s)
GSM_Error N6510_GetNextMMSFileInfo(GSM_StateMachine *s, unsigned char *FileID, int *MMSFolder, gboolean start)
int gboolean
Definition: gammu-types.h:23
#define GSM_SMS_OTHER_NUMBERS
Definition: gammu-limits.h:145
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_Error N6510_GetFileSystemStatus(GSM_StateMachine *s, GSM_FileSystemStatus *status)
struct GSM_Phone_Data::@2 Priv
GSM_Error N6510_GetFolderListing(GSM_StateMachine *s, GSM_File *File, gboolean start)
GSM_Error N6510_DeleteFolder(GSM_StateMachine *s, unsigned char *ID)
GSM_Error N6510_GetFilesystemSMSFolders(GSM_StateMachine *s, GSM_SMSFolders *folders)
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
GSM_Error N6510_GetNextFilesystemSMS(GSM_StateMachine *s, GSM_MultiSMSMessage *sms, gboolean start)
char MMSFoldersID2[10][80]
Definition: n6510.h:63
GSM_Error filesystem2error
Definition: n6510.h:51
GSM_DateTime Modified
Definition: gammu-file.h:98
GSM_Phone_RequestID RequestID
Definition: gsmstate.h:685
unsigned char Name[(GSM_MAX_SMS_FOLDER_NAME_LEN+1) *2]
GSM_MemoryType Memory
gboolean OutboxFolder
GSM_Error N6510_GetFilePart(GSM_StateMachine *s, GSM_File *File, int *Handle, size_t *Size)
GSM_SMSMessage SMS[GSM_MAX_MULTI_SMS]
gboolean ModifiedEmpty
Definition: gammu-file.h:102
#define N7110_FRAME_HEADER
Definition: ncommon.h:9
GSM_Protocol Protocol
Definition: gsmstate.h:1430
gboolean InboxFolder
unsigned char Number[(GSM_MAX_NUMBER_LENGTH+1) *2]
int FilesLocationsAvail
Definition: n6510.h:45
GSM_Error SMSFileError
Definition: n6510.h:34
GSM_Phone_Data Data
Definition: gsmstate.h:1369
gboolean GSM_IsPhoneFeatureAvailable(GSM_PhoneModel *model, GSM_Feature feature)
Definition: gsmphones.c:1026
GSM_File * FilesCache
Definition: n6510.h:43
GSM_Error N6510_ReplySetAttrib2(GSM_Protocol_Message *msg, GSM_StateMachine *s)
GSM_Error N6510_DeleteFile(GSM_StateMachine *s, unsigned char *ID)
GSM_Protocol_Functions * Functions
Definition: gsmstate.h:424
#define TRUE
Definition: gammu-types.h:28
void NOKIA_DecodeDateTime(GSM_StateMachine *s, unsigned char *buffer, GSM_DateTime *datetime, gboolean seconds, gboolean DayMonthReverse)
Definition: nfunc.c:976
GSM_Error N6510_GetNextRootFolder(GSM_StateMachine *s, GSM_File *File)
GSM_File * FileInfo
Definition: gsmstate.h:638
unsigned char * Buffer
Definition: protocol.h:22
#define UNUSED
Definition: gammu-misc.h:105
int smprintf(GSM_StateMachine *s, const char *format,...)
Definition: debug.c:261
gboolean Hidden
Definition: gammu-file.h:115
GSM_File SMSFile
Definition: n6510.h:33