author | zautrix <zautrix> | 2004-08-07 17:24:40 (UTC) |
---|---|---|
committer | zautrix <zautrix> | 2004-08-07 17:24:40 (UTC) |
commit | 88b0d33b8b0b1f6ae320cfc863ca6a47fa8fec22 (patch) (unidiff) | |
tree | 6331418973714243beb674abc87692277b83869d /gammu/emb/common/phone/obex | |
parent | ef8a09ce74ad3f0a51484d03fdf009bd5b3677bf (diff) | |
download | kdepimpi-88b0d33b8b0b1f6ae320cfc863ca6a47fa8fec22.zip kdepimpi-88b0d33b8b0b1f6ae320cfc863ca6a47fa8fec22.tar.gz kdepimpi-88b0d33b8b0b1f6ae320cfc863ca6a47fa8fec22.tar.bz2 |
Initial revision
-rw-r--r-- | gammu/emb/common/phone/obex/obexgen.c | 851 | ||||
-rw-r--r-- | gammu/emb/common/phone/obex/obexgen.h | 38 |
2 files changed, 889 insertions, 0 deletions
diff --git a/gammu/emb/common/phone/obex/obexgen.c b/gammu/emb/common/phone/obex/obexgen.c new file mode 100644 index 0000000..dd14f8e --- a/dev/null +++ b/gammu/emb/common/phone/obex/obexgen.c | |||
@@ -0,0 +1,851 @@ | |||
1 | /* (c) 2003 by Marcin Wiacek */ | ||
2 | /* www.irda.org OBEX specs 1.3 */ | ||
3 | |||
4 | /* Module connects to F9EC7BC4-953c-11d2-984E-525400DC9E09 UUID and in the | ||
5 | * future there will required implementing reconnecting. See "ifdef xxxx" | ||
6 | */ | ||
7 | |||
8 | #include <string.h> | ||
9 | #include <time.h> | ||
10 | |||
11 | #include "../../misc/coding/coding.h" | ||
12 | #include "../../gsmcomon.h" | ||
13 | #include "../../gsmstate.h" | ||
14 | #include "../../service/gsmmisc.h" | ||
15 | #include "../../protocol/obex/obex.h" | ||
16 | |||
17 | #ifdef GSM_ENABLE_OBEXGEN | ||
18 | |||
19 | static GSM_Error OBEXGEN_GetNextFileFolder(GSM_StateMachine *s, GSM_File *File, bool start); | ||
20 | |||
21 | static void OBEXGEN_FindNextDir(unsigned char *Path, int *Pos, unsigned char *Return) | ||
22 | { | ||
23 | unsigned char buff[200]; | ||
24 | |||
25 | buff[0] = 0; | ||
26 | while(1) { | ||
27 | if (Path[*Pos] == 0x00) break; | ||
28 | if (Path[*Pos] == '\\') { | ||
29 | (*Pos)++; | ||
30 | break; | ||
31 | } | ||
32 | buff[strlen(buff)+1] = 0; | ||
33 | buff[strlen(buff)] = Path[(*Pos)]; | ||
34 | (*Pos)++; | ||
35 | } | ||
36 | EncodeUnicode(Return,buff,strlen(buff)); | ||
37 | } | ||
38 | |||
39 | static GSM_Error OBEXGEN_ReplyConnect(GSM_Protocol_Message msg, GSM_StateMachine *s) | ||
40 | { | ||
41 | switch (msg.Type) { | ||
42 | case 0xA0: | ||
43 | smprintf(s,"Connected/disconnected OK\n"); | ||
44 | if (msg.Length != 0) { | ||
45 | s->Phone.Data.Priv.OBEXGEN.FrameSize = msg.Buffer[2]*256+msg.Buffer[3]; | ||
46 | smprintf(s,"Maximal size of frame is %i 0x%x\n",s->Phone.Data.Priv.OBEXGEN.FrameSize,s->Phone.Data.Priv.OBEXGEN.FrameSize); | ||
47 | } | ||
48 | return ERR_NONE; | ||
49 | } | ||
50 | return ERR_UNKNOWNRESPONSE; | ||
51 | } | ||
52 | |||
53 | GSM_Error OBEXGEN_Disconnect(GSM_StateMachine *s) | ||
54 | { | ||
55 | smprintf(s, "Disconnecting\n"); | ||
56 | return GSM_WaitFor (s, NULL, 0, 0x81, 2, ID_Initialise); | ||
57 | } | ||
58 | |||
59 | GSM_Error OBEXGEN_Connect(GSM_StateMachine *s, OBEX_Service service) | ||
60 | { | ||
61 | int Current=4; | ||
62 | unsigned char req2[200]; | ||
63 | unsigned char req[200] = { | ||
64 | 0x10, /* Version 1.0 */ | ||
65 | 0x00, /* no flags */ | ||
66 | 0x20,0x00}; /* 0x2000 max size of packet */ | ||
67 | |||
68 | if (service == s->Phone.Data.Priv.OBEXGEN.Service) return ERR_NONE; | ||
69 | |||
70 | switch (service) { | ||
71 | case OBEX_None: | ||
72 | break; | ||
73 | case OBEX_BrowsingFolders: | ||
74 | /* Server ID */ | ||
75 | req2[0] = 0xF9; req2[1] = 0xEC; req2[2] = 0x7B; | ||
76 | req2[3] = 0xC4; req2[4] = 0x95; req2[5] = 0x3C; | ||
77 | req2[6] = 0x11; req2[7] = 0xD2; req2[8] = 0x98; | ||
78 | req2[9] = 0x4E; req2[10]= 0x52; req2[11]= 0x54; | ||
79 | req2[12]= 0x00; req2[13]= 0xDC; req2[14]= 0x9E; | ||
80 | req2[15]= 0x09; | ||
81 | |||
82 | /* Target block */ | ||
83 | OBEXAddBlock(req, &Current, 0x46, req2, 16); | ||
84 | } | ||
85 | |||
86 | #ifndef xxxx | ||
87 | //disconnect old service | ||
88 | #else | ||
89 | if (s->Phone.Data.Priv.OBEXGEN.Service != 0) return ERR_NONE; | ||
90 | #endif | ||
91 | |||
92 | s->Phone.Data.Priv.OBEXGEN.Service = service; | ||
93 | |||
94 | smprintf(s, "Connecting\n"); | ||
95 | return GSM_WaitFor (s, req, Current, 0x80, 2, ID_Initialise); | ||
96 | } | ||
97 | |||
98 | |||
99 | GSM_Error OBEXGEN_Initialise(GSM_StateMachine *s) | ||
100 | { | ||
101 | // GSM_File File; | ||
102 | // GSM_Errorerror = ERR_NONE; | ||
103 | |||
104 | s->Phone.Data.Priv.OBEXGEN.Service = 0; | ||
105 | |||
106 | strcpy(s->Phone.Data.Model,"obex"); | ||
107 | |||
108 | s->Phone.Data.VerNum = 0; | ||
109 | s->Phone.Data.Version[0] = 0; | ||
110 | s->Phone.Data.Manufacturer[0] = 0; | ||
111 | |||
112 | // File.Used = 0; | ||
113 | // File.ID_FullName[0] = 0; | ||
114 | // File.Buffer = NULL; | ||
115 | //while (error == ERR_NONE) error = OBEXGEN_GetFilePart(s,&File); | ||
116 | |||
117 | return ERR_NONE; | ||
118 | } | ||
119 | |||
120 | static GSM_Error OBEXGEN_ReplyChangePath(GSM_Protocol_Message msg, GSM_StateMachine *s) | ||
121 | { | ||
122 | switch (msg.Type) { | ||
123 | case 0xA0: | ||
124 | smprintf(s,"Path set OK\n"); | ||
125 | return ERR_NONE; | ||
126 | case 0xA1: | ||
127 | smprintf(s,"Folder created\n"); | ||
128 | return ERR_NONE; | ||
129 | case 0xC3: | ||
130 | smprintf(s,"Security error\n"); | ||
131 | return ERR_SECURITYERROR; | ||
132 | } | ||
133 | return ERR_UNKNOWNRESPONSE; | ||
134 | } | ||
135 | |||
136 | static GSM_Error OBEXGEN_ChangePath(GSM_StateMachine *s, char *Name, unsigned char Flag1) | ||
137 | { | ||
138 | unsigned char req[400]; | ||
139 | int Current = 2; | ||
140 | |||
141 | /* Flags */ | ||
142 | req[0] = Flag1; | ||
143 | req[1] = 0x00; | ||
144 | |||
145 | /* Name block */ | ||
146 | if (Name != NULL && UnicodeLength(Name) != 0) { | ||
147 | OBEXAddBlock(req, &Current, 0x01, Name, UnicodeLength(Name)*2+2); | ||
148 | } else { | ||
149 | OBEXAddBlock(req, &Current, 0x01, NULL, 0); | ||
150 | } | ||
151 | |||
152 | /* connection ID block */ | ||
153 | req[Current++] = 0xCB; // ID | ||
154 | req[Current++] = 0x00; req[Current++] = 0x00; | ||
155 | req[Current++] = 0x00; req[Current++] = 0x01; | ||
156 | |||
157 | return GSM_WaitFor (s, req, Current, 0x85, 4, ID_SetPath); | ||
158 | } | ||
159 | |||
160 | static GSM_Error OBEXGEN_ReplyAddFilePart(GSM_Protocol_Message msg, GSM_StateMachine *s) | ||
161 | { | ||
162 | switch (msg.Type) { | ||
163 | case 0x90: | ||
164 | smprintf(s,"Last part of file added OK\n"); | ||
165 | return ERR_NONE; | ||
166 | case 0xA0: | ||
167 | smprintf(s,"Part of file added OK\n"); | ||
168 | return ERR_NONE; | ||
169 | case 0xC0: | ||
170 | smprintf(s,"Not understand. Probably not supported\n"); | ||
171 | return ERR_NOTSUPPORTED; | ||
172 | } | ||
173 | return ERR_UNKNOWNRESPONSE; | ||
174 | } | ||
175 | |||
176 | GSM_Error OBEXGEN_AddFilePart(GSM_StateMachine *s, GSM_File *File, int *Pos) | ||
177 | { | ||
178 | GSM_Error error; | ||
179 | int j; | ||
180 | unsigned int Pos2, Current = 0; | ||
181 | unsigned char req[2000],req2[200]; | ||
182 | |||
183 | s->Phone.Data.File = File; | ||
184 | |||
185 | if (*Pos == 0) { | ||
186 | if (!strcmp(File->ID_FullName,"")) { | ||
187 | #ifndef xxxx | ||
188 | error = OBEXGEN_Connect(s,OBEX_None); | ||
189 | #else | ||
190 | error = OBEXGEN_Connect(s,OBEX_BrowsingFolders); | ||
191 | #endif | ||
192 | if (error != ERR_NONE) return error; | ||
193 | } else { | ||
194 | error = OBEXGEN_Connect(s,OBEX_BrowsingFolders); | ||
195 | if (error != ERR_NONE) return error; | ||
196 | |||
197 | if (strcmp(s->CurrentConfig->Model,"seobex")) { | ||
198 | smprintf(s,"Changing to root\n"); | ||
199 | error = OBEXGEN_ChangePath(s, NULL, 2); | ||
200 | if (error != ERR_NONE) return error; | ||
201 | |||
202 | Pos2 = 0; | ||
203 | do { | ||
204 | OBEXGEN_FindNextDir(File->ID_FullName, &Pos2, req2); | ||
205 | smprintf(s,"%s %i %i\n",DecodeUnicodeString(req2),Pos2,strlen(File->ID_FullName)); | ||
206 | smprintf(s,"Changing path down\n"); | ||
207 | error=OBEXGEN_ChangePath(s, req2, 2); | ||
208 | if (error != ERR_NONE) return error; | ||
209 | if (Pos2 == strlen(File->ID_FullName)) break; | ||
210 | } while (1); | ||
211 | } | ||
212 | } | ||
213 | |||
214 | /* Name block */ | ||
215 | OBEXAddBlock(req, &Current, 0x01, File->Name, UnicodeLength(File->Name)*2+2); | ||
216 | |||
217 | /* File size block */ | ||
218 | req[Current++] = 0xC3; // ID | ||
219 | req[Current++] = 0; | ||
220 | req[Current++] = 0; | ||
221 | req[Current++] = File->Used / 256; | ||
222 | req[Current++] = File->Used % 256; | ||
223 | } | ||
224 | |||
225 | if (s->Phone.Data.Priv.OBEXGEN.Service == OBEX_BrowsingFolders) { | ||
226 | /* connection ID block */ | ||
227 | req[Current++] = 0xCB; // ID | ||
228 | req[Current++] = 0x00; req[Current++] = 0x00; | ||
229 | req[Current++] = 0x00; req[Current++] = 0x01; | ||
230 | } | ||
231 | |||
232 | j = s->Phone.Data.Priv.OBEXGEN.FrameSize - Current - 20; | ||
233 | if (j > 1000) j = 1000; | ||
234 | |||
235 | if (File->Used - *Pos < j) { | ||
236 | j = File->Used - *Pos; | ||
237 | /* End of file body block */ | ||
238 | OBEXAddBlock(req, &Current, 0x49, File->Buffer+(*Pos), j); | ||
239 | smprintf(s, "Adding file part %i %i\n",*Pos,j); | ||
240 | *Pos = *Pos + j; | ||
241 | error = GSM_WaitFor (s, req, Current, 0x82, 4, ID_AddFile); | ||
242 | if (error != ERR_NONE) return error; | ||
243 | return ERR_EMPTY; | ||
244 | } else { | ||
245 | /* File body block */ | ||
246 | OBEXAddBlock(req, &Current, 0x48, File->Buffer+(*Pos), j); | ||
247 | smprintf(s, "Adding file part %i %i\n",*Pos,j); | ||
248 | *Pos = *Pos + j; | ||
249 | error=GSM_WaitFor (s, req, Current, 0x02, 4, ID_AddFile); | ||
250 | } | ||
251 | return error; | ||
252 | } | ||
253 | |||
254 | static GSM_Error OBEXGEN_ReplyGetFilePart(GSM_Protocol_Message msg, GSM_StateMachine *s) | ||
255 | { | ||
256 | int old,Pos=0; | ||
257 | |||
258 | switch (msg.Type) { | ||
259 | case 0xA0: | ||
260 | smprintf(s,"File part received\n"); | ||
261 | s->Phone.Data.Priv.OBEXGEN.FileLastPart = true; | ||
262 | case 0x90: | ||
263 | // if (msg.Length < 11) return ERR_NONE; | ||
264 | if (msg.Type == 0x90) smprintf(s,"Last file part received\n"); | ||
265 | while(1) { | ||
266 | if (Pos >= msg.Length) break; | ||
267 | switch (msg.Buffer[Pos]) { | ||
268 | case 0x48: | ||
269 | case 0x49: | ||
270 | smprintf(s,"File part received\n"); | ||
271 | old = s->Phone.Data.File->Used; | ||
272 | s->Phone.Data.File->Used += msg.Buffer[Pos+1]*256+msg.Buffer[Pos+2]-3; | ||
273 | smprintf(s,"Length of file part: %i\n", | ||
274 | msg.Buffer[Pos+1]*256+msg.Buffer[Pos+2]-3); | ||
275 | s->Phone.Data.File->Buffer = (unsigned char *)realloc(s->Phone.Data.File->Buffer,s->Phone.Data.File->Used); | ||
276 | memcpy(s->Phone.Data.File->Buffer+old,msg.Buffer+Pos+3,s->Phone.Data.File->Used-old); | ||
277 | return ERR_NONE; | ||
278 | default: | ||
279 | break; | ||
280 | } | ||
281 | Pos+=msg.Buffer[Pos+1]*256+msg.Buffer[Pos+2]; | ||
282 | } | ||
283 | return ERR_UNKNOWNRESPONSE; | ||
284 | case 0xC3: | ||
285 | return ERR_NOTSUPPORTED; | ||
286 | case 0xC4: | ||
287 | smprintf(s,"Not found\n"); | ||
288 | return ERR_SECURITYERROR; | ||
289 | } | ||
290 | return ERR_UNKNOWNRESPONSE; | ||
291 | } | ||
292 | |||
293 | static GSM_Error OBEXGEN_ReplyGetFileInfo(GSM_Protocol_Message msg, GSM_StateMachine *s) | ||
294 | { | ||
295 | int old,Pos=0; | ||
296 | |||
297 | switch (msg.Type) { | ||
298 | case 0x83: | ||
299 | smprintf(s,"Not available ?\n"); | ||
300 | return ERR_NONE; | ||
301 | case 0x90: | ||
302 | smprintf(s,"Last part of file info received\n"); | ||
303 | return ERR_NONE; | ||
304 | case 0xA0: | ||
305 | while(1) { | ||
306 | if (Pos >= msg.Length) break; | ||
307 | switch (msg.Buffer[Pos]) { | ||
308 | case 0x48: | ||
309 | case 0x49: | ||
310 | /* SE T310 */ | ||
311 | smprintf(s,"File part received\n"); | ||
312 | old = s->Phone.Data.File->Used; | ||
313 | s->Phone.Data.File->Used += msg.Buffer[Pos+1]*256+msg.Buffer[Pos+2]-3; | ||
314 | smprintf(s,"Length of file part: %i\n", | ||
315 | msg.Buffer[Pos+1]*256+msg.Buffer[Pos+2]-3); | ||
316 | s->Phone.Data.File->Buffer = (unsigned char *)realloc(s->Phone.Data.File->Buffer,s->Phone.Data.File->Used); | ||
317 | memcpy(s->Phone.Data.File->Buffer+old,msg.Buffer+Pos+3,s->Phone.Data.File->Used-old); | ||
318 | return ERR_EMPTY; | ||
319 | default: | ||
320 | break; | ||
321 | } | ||
322 | Pos+=msg.Buffer[Pos+1]*256+msg.Buffer[Pos+2]; | ||
323 | } | ||
324 | return ERR_UNKNOWNRESPONSE; | ||
325 | } | ||
326 | return ERR_UNKNOWNRESPONSE; | ||
327 | } | ||
328 | |||
329 | static GSM_Error OBEXGEN_PrivGetFilePart(GSM_StateMachine *s, GSM_File *File, bool FolderList) | ||
330 | { | ||
331 | unsigned int Current = 0, Pos; | ||
332 | GSM_Error error; | ||
333 | unsigned char req[2000], req2[200]; | ||
334 | |||
335 | s->Phone.Data.File = File; | ||
336 | File->ReadOnly = false; | ||
337 | File->Protected = false; | ||
338 | File->Hidden = false; | ||
339 | File->System = false; | ||
340 | |||
341 | if (File->Used == 0x00) { | ||
342 | if (FolderList) { | ||
343 | /* Type block */ | ||
344 | strcpy(req2,"x-obex/folder-listing"); | ||
345 | OBEXAddBlock(req, &Current, 0x42, req2, strlen(req2)+1); | ||
346 | |||
347 | /* Name block */ | ||
348 | if (UnicodeLength(File->Name) == 0x00) { | ||
349 | OBEXAddBlock(req, &Current, 0x01, NULL, 0); | ||
350 | } else { | ||
351 | CopyUnicodeString(req2,File->Name); | ||
352 | OBEXAddBlock(req, &Current, 0x01, req2, UnicodeLength(req2)*2+2); | ||
353 | } | ||
354 | } else { | ||
355 | File->Folder = false; | ||
356 | |||
357 | if (File->ID_FullName[0] == 0x00) { | ||
358 | #ifndef xxxx | ||
359 | error = OBEXGEN_Connect(s,OBEX_None); | ||
360 | #else | ||
361 | error = OBEXGEN_Connect(s,OBEX_BrowsingFolders); | ||
362 | #endif | ||
363 | if (error != ERR_NONE) return error; | ||
364 | |||
365 | EncodeUnicode(File->Name,"one",3); | ||
366 | |||
367 | if (strcmp(s->CurrentConfig->Model,"seobex")) { | ||
368 | strcpy(req2,"x-obex/capability"); | ||
369 | // strcpy(req2,"x-obex/object-profile"); | ||
370 | |||
371 | /* Type block */ | ||
372 | OBEXAddBlock(req, &Current, 0x42, req2, strlen(req2)+1); | ||
373 | } else { | ||
374 | EncodeUnicode(req2,"telecom/devinfo.txt",19); | ||
375 | |||
376 | /* Name block */ | ||
377 | OBEXAddBlock(req, &Current, 0x01, req2, UnicodeLength(req2)*2+2); | ||
378 | } | ||
379 | } else { | ||
380 | // error = OBEXGEN_Connect(s,OBEX_None); | ||
381 | error = OBEXGEN_Connect(s,OBEX_BrowsingFolders); | ||
382 | if (error != ERR_NONE) return error; | ||
383 | |||
384 | if (strcmp(s->CurrentConfig->Model,"seobex")) { | ||
385 | smprintf(s,"Changing to root\n"); | ||
386 | error = OBEXGEN_ChangePath(s, NULL, 2); | ||
387 | if (error != ERR_NONE) return error; | ||
388 | |||
389 | Pos = 0; | ||
390 | do { | ||
391 | OBEXGEN_FindNextDir(File->ID_FullName, &Pos, req2); | ||
392 | smprintf(s,"%s %i %i\n",DecodeUnicodeString(req2),Pos,strlen(File->ID_FullName)); | ||
393 | if (Pos == strlen(File->ID_FullName)) break; | ||
394 | smprintf(s,"Changing path down\n"); | ||
395 | error=OBEXGEN_ChangePath(s, req2, 2); | ||
396 | if (error != ERR_NONE) return error; | ||
397 | } while (1); | ||
398 | } else { | ||
399 | EncodeUnicode(req2,File->ID_FullName,strlen(File->ID_FullName)); | ||
400 | } | ||
401 | CopyUnicodeString(File->Name,req2); | ||
402 | |||
403 | s->Phone.Data.File = File; | ||
404 | |||
405 | Current = 0; | ||
406 | /* Name block */ | ||
407 | OBEXAddBlock(req, &Current, 0x01, req2, UnicodeLength(req2)*2+2); | ||
408 | } | ||
409 | } | ||
410 | } | ||
411 | |||
412 | if (s->Phone.Data.Priv.OBEXGEN.Service == OBEX_BrowsingFolders) { | ||
413 | /* connection ID block */ | ||
414 | req[Current++] = 0xCB; // ID | ||
415 | req[Current++] = 0x00; req[Current++] = 0x00; | ||
416 | req[Current++] = 0x00; req[Current++] = 0x01; | ||
417 | } | ||
418 | |||
419 | smprintf(s, "Getting file info from filesystem\n"); | ||
420 | error=GSM_WaitFor (s, req, Current, 0x03, 4, ID_GetFileInfo); | ||
421 | if (error != ERR_NONE) return error; | ||
422 | |||
423 | s->Phone.Data.Priv.OBEXGEN.FileLastPart = false; | ||
424 | |||
425 | while (!s->Phone.Data.Priv.OBEXGEN.FileLastPart) { | ||
426 | Current = 0; | ||
427 | if (s->Phone.Data.Priv.OBEXGEN.Service == OBEX_BrowsingFolders) { | ||
428 | /* connection ID block */ | ||
429 | req[Current++] = 0xCB; // ID | ||
430 | req[Current++] = 0x00; req[Current++] = 0x00; | ||
431 | req[Current++] = 0x00; req[Current++] = 0x01; | ||
432 | } | ||
433 | smprintf(s, "Getting file part from filesystem\n"); | ||
434 | error=GSM_WaitFor (s, req, Current, 0x83, 4, ID_GetFile); | ||
435 | if (error != ERR_NONE) return error; | ||
436 | } | ||
437 | return ERR_EMPTY; | ||
438 | } | ||
439 | |||
440 | GSM_Error OBEXGEN_GetFilePart(GSM_StateMachine *s, GSM_File *File) | ||
441 | { | ||
442 | return OBEXGEN_PrivGetFilePart(s,File,false); | ||
443 | } | ||
444 | |||
445 | static GSM_Error OBEXGEN_GetNextFileFolder(GSM_StateMachine *s, GSM_File *File, bool start) | ||
446 | { | ||
447 | GSM_Phone_OBEXGENData*Priv = &s->Phone.Data.Priv.OBEXGEN; | ||
448 | GSM_Error error; | ||
449 | unsigned char Line[500],Line2[500],*name,*size; | ||
450 | int Pos,i,j,num,pos2,Current,z; | ||
451 | |||
452 | if (start) { | ||
453 | if (!strcmp(s->CurrentConfig->Model,"seobex")) return ERR_NOTSUPPORTED; | ||
454 | |||
455 | Priv->Files[0].Folder = true; | ||
456 | Priv->Files[0].Level = 1; | ||
457 | Priv->Files[0].Name[0] = 0; | ||
458 | Priv->Files[0].Name[1] = 0; | ||
459 | Priv->Files[0].ID_FullName[0]= 0; | ||
460 | Priv->Files[0].ID_FullName[1]= 0; | ||
461 | |||
462 | Priv->FilesLocationsUsed = 1; | ||
463 | Priv->FilesLocationsCurrent = 0; | ||
464 | Priv->FileLev = 1; | ||
465 | |||
466 | error = OBEXGEN_Connect(s,OBEX_BrowsingFolders); | ||
467 | if (error != ERR_NONE) return error; | ||
468 | |||
469 | smprintf(s,"Changing to root\n"); | ||
470 | error = OBEXGEN_ChangePath(s, NULL, 2); | ||
471 | if (error != ERR_NONE) return error; | ||
472 | |||
473 | Current = 0; | ||
474 | } | ||
475 | |||
476 | while (1) { | ||
477 | if (Priv->FilesLocationsCurrent == Priv->FilesLocationsUsed) { | ||
478 | dbgprintf("Last file\n"); | ||
479 | return ERR_EMPTY; | ||
480 | } | ||
481 | |||
482 | strcpy(File->ID_FullName,Priv->Files[Priv->FilesLocationsCurrent].ID_FullName); | ||
483 | File->Level= Priv->Files[Priv->FilesLocationsCurrent].Level; | ||
484 | File->Folder= Priv->Files[Priv->FilesLocationsCurrent].Folder; | ||
485 | CopyUnicodeString(File->Name,Priv->Files[Priv->FilesLocationsCurrent].Name); | ||
486 | Priv->FilesLocationsCurrent++; | ||
487 | |||
488 | if (File->Folder) { | ||
489 | if (File->Level < Priv->FileLev) { | ||
490 | for (i=0;i<File->Level;i++) { | ||
491 | smprintf(s,"Changing path up\n"); | ||
492 | error=OBEXGEN_ChangePath(s, NULL, 2); | ||
493 | if (error != ERR_NONE) return error; | ||
494 | } | ||
495 | } | ||
496 | |||
497 | smprintf(s,"Level %i %i\n",File->Level,Priv->FileLev); | ||
498 | |||
499 | File->Buffer = NULL; | ||
500 | File->Used = 0; | ||
501 | OBEXGEN_PrivGetFilePart(s, File,true); | ||
502 | |||
503 | num = 0; | ||
504 | Pos = 0; | ||
505 | while (1) { | ||
506 | MyGetLine(File->Buffer, &Pos, Line, File->Used); | ||
507 | if (strlen(Line) == 0) break; | ||
508 | name = strstr(Line,"folder name=\""); | ||
509 | if (name != NULL) { | ||
510 | name += 13; | ||
511 | j = 0; | ||
512 | while(1) { | ||
513 | if (name[j] == '"') break; | ||
514 | j++; | ||
515 | } | ||
516 | name[j] = 0; | ||
517 | |||
518 | if (strcmp(name,".")) num++; | ||
519 | } | ||
520 | name = strstr(Line,"file name=\""); | ||
521 | if (name != NULL) num++; | ||
522 | } | ||
523 | if (num != 0) { | ||
524 | i = Priv->FilesLocationsUsed-1; | ||
525 | while (1) { | ||
526 | if (i==Priv->FilesLocationsCurrent-1) break; | ||
527 | memcpy(&Priv->Files[i+num],&Priv->Files[i],sizeof(GSM_File)); | ||
528 | i--; | ||
529 | } | ||
530 | } | ||
531 | |||
532 | Pos = 0; | ||
533 | pos2 = 0; | ||
534 | while (1) { | ||
535 | MyGetLine(File->Buffer, &Pos, Line, File->Used); | ||
536 | if (strlen(Line) == 0) break; | ||
537 | strcpy(Line2,Line); | ||
538 | name = strstr(Line2,"folder name=\""); | ||
539 | if (name != NULL) { | ||
540 | name += 13; | ||
541 | j = 0; | ||
542 | while(1) { | ||
543 | if (name[j] == '"') break; | ||
544 | j++; | ||
545 | } | ||
546 | name[j] = 0; | ||
547 | if (strcmp(name,".")) { | ||
548 | dbgprintf("copying folder %s to %i parent %i\n",name,Priv->FilesLocationsCurrent+pos2,Priv->FilesLocationsCurrent); | ||
549 | strcpy(Priv->Files[Priv->FilesLocationsCurrent+pos2].ID_FullName,File->ID_FullName); | ||
550 | if (strlen(File->ID_FullName) != 0) strcat(Priv->Files[Priv->FilesLocationsCurrent+pos2].ID_FullName,"\\"); | ||
551 | strcat(Priv->Files[Priv->FilesLocationsCurrent+pos2].ID_FullName,name); | ||
552 | Priv->Files[Priv->FilesLocationsCurrent+pos2].Level = File->Level+1; | ||
553 | Priv->Files[Priv->FilesLocationsCurrent+pos2].Folder = true; | ||
554 | EncodeUnicode(Priv->Files[Priv->FilesLocationsCurrent+pos2].Name,name,strlen(name)); | ||
555 | Priv->FilesLocationsUsed++; | ||
556 | pos2++; | ||
557 | } | ||
558 | } | ||
559 | strcpy(Line2,Line); | ||
560 | name = strstr(Line2,"file name=\""); | ||
561 | if (name != NULL) { | ||
562 | name += 11; | ||
563 | j = 0; | ||
564 | while(1) { | ||
565 | if (name[j] == '"') break; | ||
566 | j++; | ||
567 | } | ||
568 | name[j] = 0; | ||
569 | dbgprintf("copying file %s to %i\n",name,Priv->FilesLocationsCurrent+pos2); | ||
570 | Priv->Files[Priv->FilesLocationsCurrent+pos2].Level= File->Level+1; | ||
571 | Priv->Files[Priv->FilesLocationsCurrent+pos2].Folder = false; | ||
572 | strcpy(Priv->Files[Priv->FilesLocationsCurrent+pos2].ID_FullName,File->ID_FullName); | ||
573 | if (strlen(File->ID_FullName) != 0) strcat(Priv->Files[Priv->FilesLocationsCurrent+pos2].ID_FullName,"\\"); | ||
574 | strcat(Priv->Files[Priv->FilesLocationsCurrent+pos2].ID_FullName,name); | ||
575 | EncodeUnicode(Priv->Files[Priv->FilesLocationsCurrent+pos2].Name,name,strlen(name)); | ||
576 | |||
577 | Priv->Files[Priv->FilesLocationsCurrent+pos2].Used = 0; | ||
578 | strcpy(Line2,Line); | ||
579 | size = strstr(Line2,"size=\""); | ||
580 | if (size != NULL) Priv->Files[Priv->FilesLocationsCurrent+pos2].Used = atoi(size+6); | ||
581 | |||
582 | Priv->Files[Priv->FilesLocationsCurrent+pos2].ModifiedEmpty = true; | ||
583 | strcpy(Line2,Line); | ||
584 | size = strstr(Line2,"modified=\""); | ||
585 | if (size != NULL) { | ||
586 | Priv->Files[Priv->FilesLocationsCurrent+pos2].ModifiedEmpty = false; | ||
587 | ReadVCALDateTime(size+10, &Priv->Files[Priv->FilesLocationsCurrent+pos2].Modified); | ||
588 | } | ||
589 | Priv->FilesLocationsUsed++; | ||
590 | pos2++; | ||
591 | } | ||
592 | } | ||
593 | |||
594 | z = Priv->FilesLocationsCurrent; | ||
595 | if (z != 1) { | ||
596 | while (1) { | ||
597 | if (z == Priv->FilesLocationsUsed) break; | ||
598 | if (Priv->Files[z].Folder) { | ||
599 | if (Priv->Files[z].Level > File->Level) { | ||
600 | smprintf(s,"Changing path down\n"); | ||
601 | error=OBEXGEN_ChangePath(s, File->Name, 2); | ||
602 | if (error != ERR_NONE) return error; | ||
603 | } | ||
604 | break; | ||
605 | } | ||
606 | z++; | ||
607 | } | ||
608 | } | ||
609 | |||
610 | Priv->FileLev = File->Level; | ||
611 | free(File->Buffer); | ||
612 | } else { | ||
613 | File->Used = Priv->Files[Priv->FilesLocationsCurrent-1].Used; | ||
614 | File->ModifiedEmpty = Priv->Files[Priv->FilesLocationsCurrent-1].ModifiedEmpty; | ||
615 | if (!File->ModifiedEmpty) { | ||
616 | memcpy(&File->Modified,&Priv->Files[Priv->FilesLocationsCurrent-1].Modified,sizeof(GSM_DateTime)); | ||
617 | } | ||
618 | File->ReadOnly = false; | ||
619 | File->Protected = false; | ||
620 | File->Hidden = false; | ||
621 | File->System = false; | ||
622 | |||
623 | } | ||
624 | return ERR_NONE; | ||
625 | } | ||
626 | } | ||
627 | |||
628 | static GSM_Error OBEXGEN_DeleteFile(GSM_StateMachine *s, unsigned char *ID) | ||
629 | { | ||
630 | GSM_Error error; | ||
631 | unsigned int Current = 0, Pos; | ||
632 | unsigned char req[200],req2[200]; | ||
633 | |||
634 | if (!strcmp(s->CurrentConfig->Model,"seobex")) return ERR_NOTSUPPORTED; | ||
635 | |||
636 | error = OBEXGEN_Connect(s,OBEX_BrowsingFolders); | ||
637 | if (error != ERR_NONE) return error; | ||
638 | |||
639 | smprintf(s,"Changing to root\n"); | ||
640 | error = OBEXGEN_ChangePath(s, NULL, 2); | ||
641 | if (error != ERR_NONE) return error; | ||
642 | |||
643 | Pos = 0; | ||
644 | do { | ||
645 | OBEXGEN_FindNextDir(ID, &Pos, req2); | ||
646 | smprintf(s,"%s %i %i\n",DecodeUnicodeString(req2),Pos,strlen(ID)); | ||
647 | if (Pos == strlen(ID)) break; | ||
648 | smprintf(s,"Changing path down\n"); | ||
649 | error=OBEXGEN_ChangePath(s, req2, 2); | ||
650 | if (error != ERR_NONE) return error; | ||
651 | } while (1); | ||
652 | |||
653 | /* Name block */ | ||
654 | OBEXAddBlock(req, &Current, 0x01, req2, UnicodeLength(req2)*2+2); | ||
655 | |||
656 | /* connection ID block */ | ||
657 | req[Current++] = 0xCB; // ID | ||
658 | req[Current++] = 0x00; req[Current++] = 0x00; | ||
659 | req[Current++] = 0x00; req[Current++] = 0x01; | ||
660 | |||
661 | return GSM_WaitFor (s, req, Current, 0x82, 4, ID_AddFile); | ||
662 | } | ||
663 | |||
664 | static GSM_Error OBEXGEN_AddFolder(GSM_StateMachine *s, GSM_File *File) | ||
665 | { | ||
666 | GSM_Error error; | ||
667 | unsigned char req2[200]; | ||
668 | unsigned int Pos; | ||
669 | |||
670 | if (!strcmp(s->CurrentConfig->Model,"seobex")) return ERR_NOTSUPPORTED; | ||
671 | |||
672 | error = OBEXGEN_Connect(s,OBEX_BrowsingFolders); | ||
673 | if (error != ERR_NONE) return error; | ||
674 | |||
675 | smprintf(s,"Changing to root\n"); | ||
676 | error = OBEXGEN_ChangePath(s, NULL, 2); | ||
677 | if (error != ERR_NONE) return error; | ||
678 | |||
679 | Pos = 0; | ||
680 | do { | ||
681 | OBEXGEN_FindNextDir(File->ID_FullName, &Pos, req2); | ||
682 | smprintf(s,"%s %i %i\n",DecodeUnicodeString(req2),Pos,strlen(File->ID_FullName)); | ||
683 | smprintf(s,"Changing path down\n"); | ||
684 | error=OBEXGEN_ChangePath(s, req2, 2); | ||
685 | if (error != ERR_NONE) return error; | ||
686 | if (Pos == strlen(File->ID_FullName)) break; | ||
687 | } while (1); | ||
688 | |||
689 | smprintf(s,"Adding directory\n"); | ||
690 | return OBEXGEN_ChangePath(s, File->Name, 0); | ||
691 | } | ||
692 | |||
693 | GSM_Reply_Function OBEXGENReplyFunctions[] = { | ||
694 | /* CONTINUE block */ | ||
695 | {OBEXGEN_ReplyAddFilePart, "\x90",0x00,0x00,ID_AddFile }, | ||
696 | {OBEXGEN_ReplyGetFilePart, "\x90",0x00,0x00,ID_GetFile }, | ||
697 | {OBEXGEN_ReplyGetFileInfo, "\x90",0x00,0x00,ID_GetFileInfo }, | ||
698 | |||
699 | /* OK block */ | ||
700 | {OBEXGEN_ReplyChangePath, "\xA0",0x00,0x00,ID_SetPath }, | ||
701 | {OBEXGEN_ReplyConnect, "\xA0",0x00,0x00,ID_Initialise }, | ||
702 | {OBEXGEN_ReplyAddFilePart, "\xA0",0x00,0x00,ID_AddFile }, | ||
703 | {OBEXGEN_ReplyGetFilePart, "\xA0",0x00,0x00,ID_GetFile }, | ||
704 | {OBEXGEN_ReplyGetFileInfo, "\xA0",0x00,0x00,ID_GetFileInfo }, | ||
705 | |||
706 | /* FOLDER CREATED block */ | ||
707 | {OBEXGEN_ReplyChangePath, "\xA1",0x00,0x00,ID_SetPath }, | ||
708 | |||
709 | /* NOT UNDERSTAND block */ | ||
710 | {OBEXGEN_ReplyAddFilePart, "\xC0",0x00,0x00,ID_AddFile }, | ||
711 | |||
712 | /* FORBIDDEN block */ | ||
713 | {OBEXGEN_ReplyChangePath, "\xC3",0x00,0x00,ID_SetPath }, | ||
714 | {OBEXGEN_ReplyGetFilePart, "\xC3",0x00,0x00,ID_GetFile }, | ||
715 | |||
716 | /* NOT FOUND block */ | ||
717 | {OBEXGEN_ReplyGetFilePart, "\xC4",0x00,0x00,ID_GetFile }, | ||
718 | |||
719 | {NULL, "\x00",0x00,0x00,ID_None } | ||
720 | }; | ||
721 | |||
722 | GSM_Phone_Functions OBEXGENPhone = { | ||
723 | "obex|seobex", | ||
724 | OBEXGENReplyFunctions, | ||
725 | OBEXGEN_Initialise, | ||
726 | NONEFUNCTION, /* Terminate */ | ||
727 | GSM_DispatchMessage, | ||
728 | NOTIMPLEMENTED, /* ShowStartInfo */ | ||
729 | NONEFUNCTION, /* GetManufacturer */ | ||
730 | NONEFUNCTION, /* GetModel */ | ||
731 | NONEFUNCTION, /* GetFirmware */ | ||
732 | NOTIMPLEMENTED, /* GetIMEI */ | ||
733 | NOTIMPLEMENTED, /* GetOriginalIMEI */ | ||
734 | NOTIMPLEMENTED, /* GetManufactureMonth*/ | ||
735 | NOTIMPLEMENTED, /* GetProductCode */ | ||
736 | NOTIMPLEMENTED, /* GetHardware */ | ||
737 | NOTIMPLEMENTED, /* GetPPM */ | ||
738 | NOTIMPLEMENTED, /* GetSIMIMSI */ | ||
739 | NOTIMPLEMENTED, /* GetDateTime */ | ||
740 | NOTIMPLEMENTED, /* SetDateTime */ | ||
741 | NOTIMPLEMENTED, /* GetAlarm */ | ||
742 | NOTIMPLEMENTED, /* SetAlarm */ | ||
743 | NOTSUPPORTED, /* GetLocale */ | ||
744 | NOTSUPPORTED, /* SetLocale */ | ||
745 | NOTIMPLEMENTED, /* PressKey */ | ||
746 | NOTIMPLEMENTED, /* Reset */ | ||
747 | NOTIMPLEMENTED, /* ResetPhoneSettings*/ | ||
748 | NOTIMPLEMENTED, /* EnterSecurityCode*/ | ||
749 | NOTIMPLEMENTED, /* GetSecurityStatus*/ | ||
750 | NOTIMPLEMENTED, /* GetDisplayStatus*/ | ||
751 | NOTIMPLEMENTED, /* SetAutoNetworkLogin*/ | ||
752 | NOTIMPLEMENTED, /* GetBatteryCharge*/ | ||
753 | NOTIMPLEMENTED, /* GetSignalQuality*/ | ||
754 | NOTIMPLEMENTED, /* GetNetworkInfo */ | ||
755 | NOTIMPLEMENTED, /* GetCategory */ | ||
756 | NOTSUPPORTED, /* AddCategory */ | ||
757 | NOTIMPLEMENTED, /* GetCategoryStatus */ | ||
758 | NOTIMPLEMENTED, /* GetMemoryStatus */ | ||
759 | NOTIMPLEMENTED, /* GetMemory */ | ||
760 | NOTIMPLEMENTED, /* GetNextMemory */ | ||
761 | NOTIMPLEMENTED, /* SetMemory */ | ||
762 | NOTIMPLEMENTED, /* AddMemory */ | ||
763 | NOTIMPLEMENTED, /* DeleteMemory */ | ||
764 | NOTIMPLEMENTED, /* DeleteAllMemory */ | ||
765 | NOTIMPLEMENTED, /* GetSpeedDial */ | ||
766 | NOTIMPLEMENTED, /* SetSpeedDial */ | ||
767 | NOTIMPLEMENTED, /* GetSMSC */ | ||
768 | NOTIMPLEMENTED, /* SetSMSC */ | ||
769 | NOTIMPLEMENTED, /* GetSMSStatus */ | ||
770 | NOTIMPLEMENTED, /* GetSMS */ | ||
771 | NOTIMPLEMENTED, /* GetNextSMS */ | ||
772 | NOTIMPLEMENTED, /* SetSMS */ | ||
773 | NOTIMPLEMENTED, /* AddSMS */ | ||
774 | NOTIMPLEMENTED, /* DeleteSMS */ | ||
775 | NOTIMPLEMENTED, /* SendSMSMessage */ | ||
776 | NOTSUPPORTED, /* SendSavedSMS */ | ||
777 | NOTIMPLEMENTED, /* SetIncomingSMS */ | ||
778 | NOTIMPLEMENTED, /* SetIncomingCB */ | ||
779 | NOTIMPLEMENTED, /* GetSMSFolders */ | ||
780 | NOTIMPLEMENTED, /* AddSMSFolder */ | ||
781 | NOTIMPLEMENTED, /* DeleteSMSFolder */ | ||
782 | NOTIMPLEMENTED, /* DialVoice */ | ||
783 | NOTIMPLEMENTED, /* AnswerCall */ | ||
784 | NOTIMPLEMENTED, /* CancelCall */ | ||
785 | NOTIMPLEMENTED, /* HoldCall */ | ||
786 | NOTIMPLEMENTED, /* UnholdCall */ | ||
787 | NOTIMPLEMENTED, /* ConferenceCall */ | ||
788 | NOTIMPLEMENTED, /* SplitCall */ | ||
789 | NOTIMPLEMENTED, /* TransferCall */ | ||
790 | NOTIMPLEMENTED, /* SwitchCall */ | ||
791 | NOTIMPLEMENTED, /* GetCallDivert */ | ||
792 | NOTIMPLEMENTED, /* SetCallDivert */ | ||
793 | NOTIMPLEMENTED, /* CancelAllDiverts*/ | ||
794 | NOTIMPLEMENTED, /* SetIncomingCall */ | ||
795 | NOTIMPLEMENTED, /* SetIncomingUSSD */ | ||
796 | NOTIMPLEMENTED, /* SendDTMF */ | ||
797 | NOTIMPLEMENTED, /* GetRingtone */ | ||
798 | NOTIMPLEMENTED, /* SetRingtone */ | ||
799 | NOTIMPLEMENTED, /* GetRingtonesInfo*/ | ||
800 | NOTIMPLEMENTED, /* DeleteUserRingtones*/ | ||
801 | NOTIMPLEMENTED, /* PlayTone */ | ||
802 | NOTIMPLEMENTED, /* GetWAPBookmark */ | ||
803 | NOTIMPLEMENTED, /* SetWAPBookmark */ | ||
804 | NOTIMPLEMENTED, /* DeleteWAPBookmark */ | ||
805 | NOTIMPLEMENTED, /* GetWAPSettings */ | ||
806 | NOTIMPLEMENTED, /* SetWAPSettings */ | ||
807 | NOTIMPLEMENTED, /* GetMMSSettings */ | ||
808 | NOTIMPLEMENTED, /* SetMMSSettings */ | ||
809 | NOTSUPPORTED, /* GetSyncMLSettings*/ | ||
810 | NOTSUPPORTED, /* SetSyncMLSettings*/ | ||
811 | NOTSUPPORTED, /* GetChatSettings */ | ||
812 | NOTSUPPORTED, /* SetChatSettings */ | ||
813 | NOTIMPLEMENTED, /* GetBitmap */ | ||
814 | NOTIMPLEMENTED, /* SetBitmap */ | ||
815 | NOTIMPLEMENTED, /* GetToDoStatus */ | ||
816 | NOTIMPLEMENTED, /* GetToDo */ | ||
817 | NOTIMPLEMENTED, /* GetNextToDo */ | ||
818 | NOTIMPLEMENTED, /* SetToDo */ | ||
819 | NOTIMPLEMENTED, /* AddToDo */ | ||
820 | NOTIMPLEMENTED, /* DeleteToDo */ | ||
821 | NOTIMPLEMENTED, /* DeleteAllToDo */ | ||
822 | NOTIMPLEMENTED, /* GetCalendarStatus*/ | ||
823 | NOTIMPLEMENTED, /* GetCalendar */ | ||
824 | NOTIMPLEMENTED, /* GetNextCalendar */ | ||
825 | NOTIMPLEMENTED, /* SetCalendar */ | ||
826 | NOTIMPLEMENTED, /* AddCalendar */ | ||
827 | NOTIMPLEMENTED, /* DeleteCalendar */ | ||
828 | NOTIMPLEMENTED, /* DeleteAllCalendar*/ | ||
829 | NOTSUPPORTED, /* GetCalendarSettings*/ | ||
830 | NOTSUPPORTED, /* SetCalendarSettings*/ | ||
831 | NOTSUPPORTED, /* GetNote */ | ||
832 | NOTIMPLEMENTED, /* GetProfile */ | ||
833 | NOTIMPLEMENTED, /* SetProfile */ | ||
834 | NOTIMPLEMENTED, /* GetFMStation */ | ||
835 | NOTIMPLEMENTED, /* SetFMStation */ | ||
836 | NOTIMPLEMENTED, /* ClearFMStations */ | ||
837 | OBEXGEN_GetNextFileFolder, | ||
838 | OBEXGEN_GetFilePart, | ||
839 | OBEXGEN_AddFilePart, | ||
840 | NOTIMPLEMENTED, /* GetFileSystemStatus*/ | ||
841 | OBEXGEN_DeleteFile, | ||
842 | OBEXGEN_AddFolder, | ||
843 | NOTIMPLEMENTED, /* GetGPRSAccessPoint*/ | ||
844 | NOTIMPLEMENTED /* SetGPRSAccessPoint*/ | ||
845 | }; | ||
846 | |||
847 | #endif | ||
848 | |||
849 | /* How should editor hadle tabs in this file? Add editor commands here. | ||
850 | * vim: noexpandtab sw=8 ts=8 sts=8: | ||
851 | */ | ||
diff --git a/gammu/emb/common/phone/obex/obexgen.h b/gammu/emb/common/phone/obex/obexgen.h new file mode 100644 index 0000000..466fef5 --- a/dev/null +++ b/gammu/emb/common/phone/obex/obexgen.h | |||
@@ -0,0 +1,38 @@ | |||
1 | /* (c) 2003 by Marcin Wiacek */ | ||
2 | |||
3 | #ifndef obexgen_h | ||
4 | #define obexgen_h | ||
5 | |||
6 | #include "../../gsmcomon.h" | ||
7 | #include "../../gsmstate.h" | ||
8 | #include "../../service/gsmmisc.h" | ||
9 | #include "../../service/sms/gsmsms.h" | ||
10 | |||
11 | #ifndef GSM_USED_IRDAOBEX | ||
12 | # define GSM_USED_IRDAOBEX | ||
13 | #endif | ||
14 | #ifndef GSM_USED_BLUEOBEX | ||
15 | # define GSM_USED_BLUEOBEX | ||
16 | #endif | ||
17 | |||
18 | typedef enum { | ||
19 | OBEX_None = 1, | ||
20 | OBEX_BrowsingFolders | ||
21 | } OBEX_Service; | ||
22 | |||
23 | typedef struct { | ||
24 | int FileLev; | ||
25 | int FilesLocationsUsed; | ||
26 | int FilesLocationsCurrent; | ||
27 | GSM_File Files[500]; | ||
28 | bool FileLastPart; | ||
29 | |||
30 | int FrameSize; | ||
31 | OBEX_Service Service; | ||
32 | } GSM_Phone_OBEXGENData; | ||
33 | |||
34 | #endif | ||
35 | |||
36 | /* How should editor hadle tabs in this file? Add editor commands here. | ||
37 | * vim: noexpandtab sw=8 ts=8 sts=8: | ||
38 | */ | ||