Diffstat (limited to 'gammu/emb/common/phone/at/samsung.c') (more/less context) (show whitespace changes)
-rw-r--r-- | gammu/emb/common/phone/at/samsung.c | 447 |
1 files changed, 447 insertions, 0 deletions
diff --git a/gammu/emb/common/phone/at/samsung.c b/gammu/emb/common/phone/at/samsung.c new file mode 100644 index 0000000..55a42e5 --- a/dev/null +++ b/gammu/emb/common/phone/at/samsung.c | |||
@@ -0,0 +1,447 @@ | |||
1 | /* Samsung-specific functions | ||
2 | * Copyright (C) 2004 Claudio Matsuoka <cmatsuoka@gmail.com> | ||
3 | * Tested with S300 only! | ||
4 | */ | ||
5 | |||
6 | #include "../../gsmstate.h" | ||
7 | |||
8 | #ifdef GSM_ENABLE_ATGEN | ||
9 | |||
10 | #include <string.h> | ||
11 | #include <time.h> | ||
12 | #include <ctype.h> | ||
13 | |||
14 | #include "../../misc/coding/coding.h" | ||
15 | #include "../../gsmcomon.h" | ||
16 | #include "../../service/sms/gsmsms.h" | ||
17 | #include "../pfunc.h" | ||
18 | |||
19 | #include "atgen.h" | ||
20 | #include "samsung.h" | ||
21 | |||
22 | /* Binary frame size */ | ||
23 | #define BLKSZ 1024 | ||
24 | |||
25 | struct ModelRes { | ||
26 | char *model; | ||
27 | int width; | ||
28 | int height; | ||
29 | }; | ||
30 | |||
31 | static struct ModelRes modres[] = { | ||
32 | { "S100", 128, 128 }, | ||
33 | { "S200", 128, 113 }, | ||
34 | { "S300", 128, 97 }, | ||
35 | { "S500", 128, 128 }, | ||
36 | { "T100", 128, 128 }, | ||
37 | { "E700", 128, 128 }, | ||
38 | { NULL, 0, 0 } | ||
39 | }; | ||
40 | |||
41 | /* | ||
42 | * CRC functions from the Granch SBNI12 Linux driver by | ||
43 | * Denis I. Timofeev <timofeev@granch.ru> | ||
44 | */ | ||
45 | static unsigned int crc32tab[] = { | ||
46 | 0xD202EF8D, 0xA505DF1B, 0x3C0C8EA1, 0x4B0BBE37, | ||
47 | 0xD56F2B94, 0xA2681B02, 0x3B614AB8, 0x4C667A2E, | ||
48 | 0xDCD967BF, 0xABDE5729, 0x32D70693, 0x45D03605, | ||
49 | 0xDBB4A3A6, 0xACB39330, 0x35BAC28A, 0x42BDF21C, | ||
50 | 0xCFB5FFE9, 0xB8B2CF7F, 0x21BB9EC5, 0x56BCAE53, | ||
51 | 0xC8D83BF0, 0xBFDF0B66, 0x26D65ADC, 0x51D16A4A, | ||
52 | 0xC16E77DB, 0xB669474D, 0x2F6016F7, 0x58672661, | ||
53 | 0xC603B3C2, 0xB1048354, 0x280DD2EE, 0x5F0AE278, | ||
54 | 0xE96CCF45, 0x9E6BFFD3, 0x0762AE69, 0x70659EFF, | ||
55 | 0xEE010B5C, 0x99063BCA, 0x000F6A70, 0x77085AE6, | ||
56 | 0xE7B74777, 0x90B077E1, 0x09B9265B, 0x7EBE16CD, | ||
57 | 0xE0DA836E, 0x97DDB3F8, 0x0ED4E242, 0x79D3D2D4, | ||
58 | 0xF4DBDF21, 0x83DCEFB7, 0x1AD5BE0D, 0x6DD28E9B, | ||
59 | 0xF3B61B38, 0x84B12BAE, 0x1DB87A14, 0x6ABF4A82, | ||
60 | 0xFA005713, 0x8D076785, 0x140E363F, 0x630906A9, | ||
61 | 0xFD6D930A, 0x8A6AA39C, 0x1363F226, 0x6464C2B0, | ||
62 | 0xA4DEAE1D, 0xD3D99E8B, 0x4AD0CF31, 0x3DD7FFA7, | ||
63 | 0xA3B36A04, 0xD4B45A92, 0x4DBD0B28, 0x3ABA3BBE, | ||
64 | 0xAA05262F, 0xDD0216B9, 0x440B4703, 0x330C7795, | ||
65 | 0xAD68E236, 0xDA6FD2A0, 0x4366831A, 0x3461B38C, | ||
66 | 0xB969BE79, 0xCE6E8EEF, 0x5767DF55, 0x2060EFC3, | ||
67 | 0xBE047A60, 0xC9034AF6, 0x500A1B4C, 0x270D2BDA, | ||
68 | 0xB7B2364B, 0xC0B506DD, 0x59BC5767, 0x2EBB67F1, | ||
69 | 0xB0DFF252, 0xC7D8C2C4, 0x5ED1937E, 0x29D6A3E8, | ||
70 | 0x9FB08ED5, 0xE8B7BE43, 0x71BEEFF9, 0x06B9DF6F, | ||
71 | 0x98DD4ACC, 0xEFDA7A5A, 0x76D32BE0, 0x01D41B76, | ||
72 | 0x916B06E7, 0xE66C3671, 0x7F6567CB, 0x0862575D, | ||
73 | 0x9606C2FE, 0xE101F268, 0x7808A3D2, 0x0F0F9344, | ||
74 | 0x82079EB1, 0xF500AE27, 0x6C09FF9D, 0x1B0ECF0B, | ||
75 | 0x856A5AA8, 0xF26D6A3E, 0x6B643B84, 0x1C630B12, | ||
76 | 0x8CDC1683, 0xFBDB2615, 0x62D277AF, 0x15D54739, | ||
77 | 0x8BB1D29A, 0xFCB6E20C, 0x65BFB3B6, 0x12B88320, | ||
78 | 0x3FBA6CAD, 0x48BD5C3B, 0xD1B40D81, 0xA6B33D17, | ||
79 | 0x38D7A8B4, 0x4FD09822, 0xD6D9C998, 0xA1DEF90E, | ||
80 | 0x3161E49F, 0x4666D409, 0xDF6F85B3, 0xA868B525, | ||
81 | 0x360C2086, 0x410B1010, 0xD80241AA, 0xAF05713C, | ||
82 | 0x220D7CC9, 0x550A4C5F, 0xCC031DE5, 0xBB042D73, | ||
83 | 0x2560B8D0, 0x52678846, 0xCB6ED9FC, 0xBC69E96A, | ||
84 | 0x2CD6F4FB, 0x5BD1C46D, 0xC2D895D7, 0xB5DFA541, | ||
85 | 0x2BBB30E2, 0x5CBC0074, 0xC5B551CE, 0xB2B26158, | ||
86 | 0x04D44C65, 0x73D37CF3, 0xEADA2D49, 0x9DDD1DDF, | ||
87 | 0x03B9887C, 0x74BEB8EA, 0xEDB7E950, 0x9AB0D9C6, | ||
88 | 0x0A0FC457, 0x7D08F4C1, 0xE401A57B, 0x930695ED, | ||
89 | 0x0D62004E, 0x7A6530D8, 0xE36C6162, 0x946B51F4, | ||
90 | 0x19635C01, 0x6E646C97, 0xF76D3D2D, 0x806A0DBB, | ||
91 | 0x1E0E9818, 0x6909A88E, 0xF000F934, 0x8707C9A2, | ||
92 | 0x17B8D433, 0x60BFE4A5, 0xF9B6B51F, 0x8EB18589, | ||
93 | 0x10D5102A, 0x67D220BC, 0xFEDB7106, 0x89DC4190, | ||
94 | 0x49662D3D, 0x3E611DAB, 0xA7684C11, 0xD06F7C87, | ||
95 | 0x4E0BE924, 0x390CD9B2, 0xA0058808, 0xD702B89E, | ||
96 | 0x47BDA50F, 0x30BA9599, 0xA9B3C423, 0xDEB4F4B5, | ||
97 | 0x40D06116, 0x37D75180, 0xAEDE003A, 0xD9D930AC, | ||
98 | 0x54D13D59, 0x23D60DCF, 0xBADF5C75, 0xCDD86CE3, | ||
99 | 0x53BCF940, 0x24BBC9D6, 0xBDB2986C, 0xCAB5A8FA, | ||
100 | 0x5A0AB56B, 0x2D0D85FD, 0xB404D447, 0xC303E4D1, | ||
101 | 0x5D677172, 0x2A6041E4, 0xB369105E, 0xC46E20C8, | ||
102 | 0x72080DF5, 0x050F3D63, 0x9C066CD9, 0xEB015C4F, | ||
103 | 0x7565C9EC, 0x0262F97A, 0x9B6BA8C0, 0xEC6C9856, | ||
104 | 0x7CD385C7, 0x0BD4B551, 0x92DDE4EB, 0xE5DAD47D, | ||
105 | 0x7BBE41DE, 0x0CB97148, 0x95B020F2, 0xE2B71064, | ||
106 | 0x6FBF1D91, 0x18B82D07, 0x81B17CBD, 0xF6B64C2B, | ||
107 | 0x68D2D988, 0x1FD5E91E, 0x86DCB8A4, 0xF1DB8832, | ||
108 | 0x616495A3, 0x1663A535, 0x8F6AF48F, 0xF86DC419, | ||
109 | 0x660951BA, 0x110E612C, 0x88073096, 0xFF000000 | ||
110 | }; | ||
111 | |||
112 | static unsigned int GetCRC(char *data, int size) | ||
113 | { | ||
114 | unsigned int crc = 0; | ||
115 | |||
116 | while (size--) | ||
117 | crc = crc32tab[(crc ^ *data++) & 0xff] ^ ((crc >> 8) & 0x00FFFFFF); | ||
118 | |||
119 | return crc; | ||
120 | } | ||
121 | |||
122 | /* | ||
123 | * Frame transfer | ||
124 | */ | ||
125 | |||
126 | static GSM_Error WaitFor(GSM_StateMachine *s, char *t, int ttl) | ||
127 | { | ||
128 | char readbuf[100]; | ||
129 | int n; | ||
130 | unsigned int sec; | ||
131 | GSM_DateTime Date; | ||
132 | |||
133 | GSM_GetCurrentDateTime (&Date); | ||
134 | sec = Date.Second; | ||
135 | |||
136 | n = s->Device.Functions->ReadDevice(s, readbuf, 80); | ||
137 | readbuf[n] = 0; | ||
138 | while (strstr(readbuf, t) == NULL && (sec + ttl) >= Date.Second) { | ||
139 | my_sleep(5000); | ||
140 | n = s->Device.Functions->ReadDevice(s, readbuf, 80); | ||
141 | readbuf[n] = 0; | ||
142 | GSM_GetCurrentDateTime (&Date); | ||
143 | } | ||
144 | |||
145 | return (sec + ttl) >= Date.Second ? ERR_NONE : ERR_TIMEOUT; | ||
146 | } | ||
147 | |||
148 | static GSM_Error SetSamsungFrame(GSM_StateMachine *s, unsigned char *buff, int size, GSM_Phone_RequestID id) | ||
149 | { | ||
150 | GSM_Phone_Data *Phone = &s->Phone.Data; | ||
151 | GSM_Error error; | ||
152 | int i, count; | ||
153 | |||
154 | count = size / BLKSZ; | ||
155 | |||
156 | for (i = 0; i < count; i++) { | ||
157 | error = WaitFor(s, ">", 4); | ||
158 | if (error!=ERR_NONE) return error; | ||
159 | |||
160 | error = s->Protocol.Functions->WriteMessage(s, | ||
161 | buff + i * BLKSZ, BLKSZ, 0x00); | ||
162 | if (error!=ERR_NONE) return error; | ||
163 | } | ||
164 | |||
165 | error = WaitFor(s, ">", 4); | ||
166 | if (error!=ERR_NONE) return error; | ||
167 | error = s->Protocol.Functions->WriteMessage(s, | ||
168 | buff + i * BLKSZ, size%BLKSZ, 0x00); | ||
169 | if (error!=ERR_NONE) return error; | ||
170 | |||
171 | error = GSM_WaitFor(s, "", 0, 0x00, 4, id); | ||
172 | if (error!=ERR_NONE) return error; | ||
173 | |||
174 | return Phone->DispatchError; | ||
175 | } | ||
176 | |||
177 | /* Answer format for binary data transfer | ||
178 | * | ||
179 | * SDNDCRC = 0xa : RECEIVECRC = 0xcbf53a1c : BINSIZE = 5 | ||
180 | * CRCERR | ||
181 | */ | ||
182 | static GSM_Error ReplySetSamsungFrame(GSM_Protocol_Message msg, GSM_StateMachine *s) | ||
183 | { | ||
184 | unsigned long txcrc, rxcrc; | ||
185 | int binsize; | ||
186 | char *pos; | ||
187 | |||
188 | /* Parse SDNDCRC */ | ||
189 | pos = strchr(msg.Buffer, '='); | ||
190 | if (!pos) return ERR_UNKNOWN; | ||
191 | pos++; | ||
192 | txcrc = strtoul(pos, NULL, 0); | ||
193 | smprintf(s, "Sent CRC : 0x%lx\n", txcrc); | ||
194 | |||
195 | /* Parse RECEIVECRC */ | ||
196 | pos = strchr(pos, '='); | ||
197 | if (!pos) return ERR_UNKNOWN; | ||
198 | pos++; | ||
199 | rxcrc = strtoul(pos, NULL, 0); | ||
200 | smprintf(s, "Reveived CRC : 0x%lx\n", rxcrc); | ||
201 | |||
202 | /* Parse BINSIZE */ | ||
203 | pos = strchr(pos, '='); | ||
204 | if (!pos) return ERR_UNKNOWN; | ||
205 | pos++; | ||
206 | binsize = strtoul(pos, NULL, 0); | ||
207 | smprintf(s, "Binary size : %d\n", binsize); | ||
208 | |||
209 | return txcrc == rxcrc ? ERR_NONE : ERR_WRONGCRC; | ||
210 | } | ||
211 | |||
212 | /* | ||
213 | * Bitmaps | ||
214 | */ | ||
215 | |||
216 | GSM_Error SAMSUNG_ReplyGetBitmap(GSM_Protocol_Message msg, GSM_StateMachine *s) | ||
217 | { | ||
218 | GSM_Phone_ATGENData *Priv = &s->Phone.Data.Priv.ATGEN; | ||
219 | unsigned char buffer[32]; | ||
220 | char *pos; | ||
221 | int location, count; | ||
222 | |||
223 | switch (Priv->ReplyState) { | ||
224 | case AT_Reply_OK: | ||
225 | smprintf(s, "Bitmap info received\n"); | ||
226 | /* Parse +IMGR:location,name,0,0,0,0 */ | ||
227 | |||
228 | /* Parse location */ | ||
229 | pos = strchr(msg.Buffer, ':'); | ||
230 | if (!pos) return ERR_UNKNOWN; | ||
231 | pos++; | ||
232 | location = atoi(pos); | ||
233 | smprintf(s, "Location : %d\n", location); | ||
234 | |||
235 | /* Parse name */ | ||
236 | pos = strchr(pos, '"'); | ||
237 | if (!pos) return ERR_UNKNOWN; | ||
238 | pos++; | ||
239 | for (count = 0; count < 31; count++) { | ||
240 | if (pos[count] == '"') | ||
241 | break; | ||
242 | buffer[count] = pos[count]; | ||
243 | } | ||
244 | buffer[count] = 0; | ||
245 | smprintf(s, "Name : %s\n", buffer); | ||
246 | s->Phone.Data.Bitmap->Name = malloc((strlen(buffer) + 1) * 2); | ||
247 | if (s->Phone.Data.Bitmap->Name == NULL) | ||
248 | return ERR_MOREMEMORY; | ||
249 | EncodeUnicode(s->Phone.Data.Bitmap->Name, buffer, strlen(buffer)); | ||
250 | |||
251 | s->Phone.Data.Bitmap->Location = location; | ||
252 | |||
253 | return ERR_NONE; | ||
254 | case AT_Reply_Error: | ||
255 | return ERR_UNKNOWN; | ||
256 | case AT_Reply_CMSError: | ||
257 | return ATGEN_HandleCMSError(s); | ||
258 | case AT_Reply_CMEError: | ||
259 | return ATGEN_HandleCMEError(s); | ||
260 | default: | ||
261 | return ERR_UNKNOWNRESPONSE; | ||
262 | } | ||
263 | } | ||
264 | |||
265 | GSM_Error SAMSUNG_ReplySetBitmap(GSM_Protocol_Message msg, GSM_StateMachine *s) | ||
266 | { | ||
267 | smprintf(s, "Bitmap sent\n"); | ||
268 | return ReplySetSamsungFrame(msg, s); | ||
269 | } | ||
270 | |||
271 | GSM_Error SAMSUNG_GetBitmap(GSM_StateMachine *s, GSM_Bitmap *Bitmap) | ||
272 | { | ||
273 | unsigned char req[100]; | ||
274 | |||
275 | s->Phone.Data.Bitmap=Bitmap; | ||
276 | smprintf(s, "Getting bitmap\n"); | ||
277 | sprintf(req, "AT+IMGR=%d\r", Bitmap->Location-1); | ||
278 | return GSM_WaitFor (s, req, strlen(req), 0x00, 4, ID_GetBitmap); | ||
279 | } | ||
280 | |||
281 | GSM_Error SAMSUNG_SetBitmap(GSM_StateMachine *s, GSM_Bitmap *Bitmap) | ||
282 | { | ||
283 | unsigned charreq[100]; | ||
284 | unsigned longcrc; | ||
285 | GSM_Errorerror; | ||
286 | char name[50], *dot, *model; | ||
287 | GSM_Phone_Data *Data = &s->Phone.Data; | ||
288 | int i; | ||
289 | |||
290 | s->Phone.Data.Bitmap = Bitmap; | ||
291 | smprintf(s, "Setting bitmap\n"); | ||
292 | |||
293 | if (Bitmap->Type != GSM_PictureBinary) { | ||
294 | smprintf(s, "Invalid picture type\n"); | ||
295 | return ERR_INVALIDDATA; | ||
296 | } | ||
297 | |||
298 | if (Bitmap->BinaryPic.Type != PICTURE_GIF) { | ||
299 | smprintf(s, "Invalid binary picture type\n"); | ||
300 | return ERR_INVALIDDATA; | ||
301 | } | ||
302 | |||
303 | /* Check if picture size matches phone model */ | ||
304 | model = GetModelData(NULL,Data->Model,NULL)->model; | ||
305 | smprintf(s, "Checking picture size for %s\n", model); | ||
306 | for (i = 0; modres[i].model; i++) { | ||
307 | if (!strcmp(model, modres[i].model)) { | ||
308 | if (Bitmap->BitmapWidth != modres[i].width || | ||
309 | Bitmap->BitmapHeight != modres[i].height) { | ||
310 | smprintf(s, "Model %s must use %d x %d picture size\n", | ||
311 | modres[i].model, modres[i].width, | ||
312 | modres[i].height); | ||
313 | return ERR_INVALIDDATA; | ||
314 | } | ||
315 | break; | ||
316 | } | ||
317 | } | ||
318 | if (modres[i].model == NULL) { | ||
319 | smprintf(s, "Model \"%s\" is not supported.\n", Data->Model); | ||
320 | return ERR_NOTSUPPORTED; | ||
321 | } | ||
322 | |||
323 | crc = GetCRC(Bitmap->BinaryPic.Buffer, Bitmap->BinaryPic.Length); | ||
324 | |||
325 | /* Remove extension from file name */ | ||
326 | strncpy(name, DecodeUnicodeString(Bitmap->Name), 50); | ||
327 | if ((dot = strrchr(name, '.')) != NULL) | ||
328 | *dot = 0; | ||
329 | |||
330 | sprintf(req, "AT+IMGW=0,\"%s\",2,0,0,0,0,100,%d,%u\r", name, | ||
331 | Bitmap->BinaryPic.Length, (unsigned int)crc); | ||
332 | |||
333 | error = s->Protocol.Functions->WriteMessage(s, req, strlen(req), 0x00); | ||
334 | if (error!=ERR_NONE) return error; | ||
335 | |||
336 | return SetSamsungFrame(s, Bitmap->BinaryPic.Buffer, | ||
337 | Bitmap->BinaryPic.Length, ID_SetBitmap); | ||
338 | } | ||
339 | |||
340 | /* | ||
341 | * Ringtones | ||
342 | */ | ||
343 | |||
344 | GSM_Error SAMSUNG_ReplyGetRingtone(GSM_Protocol_Message msg, GSM_StateMachine *s) | ||
345 | { | ||
346 | GSM_Phone_ATGENData *Priv = &s->Phone.Data.Priv.ATGEN; | ||
347 | unsigned char buffer[32]; | ||
348 | char *pos; | ||
349 | int location, length, count; | ||
350 | |||
351 | switch (Priv->ReplyState) { | ||
352 | case AT_Reply_OK: | ||
353 | smprintf(s, "Ringtone info received\n"); | ||
354 | /* Parse +MELR:location,name,size */ | ||
355 | |||
356 | /* Parse location */ | ||
357 | pos = strchr(msg.Buffer, ':'); | ||
358 | if (!pos) return ERR_UNKNOWN; | ||
359 | pos++; | ||
360 | location = atoi(pos); | ||
361 | smprintf(s, "Location : %d\n", location); | ||
362 | |||
363 | /* Parse name */ | ||
364 | pos = strchr(pos, '"'); | ||
365 | if (!pos) return ERR_UNKNOWN; | ||
366 | pos++; | ||
367 | /* Ringtone.Name size is 20 chars */ | ||
368 | for (count = 0; count < 19; count++) { | ||
369 | if (pos[count] == '"') | ||
370 | break; | ||
371 | buffer[count] = pos[count]; | ||
372 | } | ||
373 | buffer[count] = 0; | ||
374 | smprintf(s, "Name : %s\n", buffer); | ||
375 | EncodeUnicode(s->Phone.Data.Ringtone->Name,buffer,strlen(buffer)); | ||
376 | |||
377 | /* Parse ringtone length */ | ||
378 | pos = strchr(pos, ','); | ||
379 | if (!pos) return ERR_UNKNOWN; | ||
380 | pos++; | ||
381 | length = atoi(pos); | ||
382 | smprintf(s, "Length : %d\n", length); | ||
383 | |||
384 | /* S300 ringtones are always MMF */ | ||
385 | s->Phone.Data.Ringtone->Format = RING_MMF; | ||
386 | s->Phone.Data.Ringtone->Location = location; | ||
387 | s->Phone.Data.Ringtone->BinaryTone.Length = length; | ||
388 | |||
389 | return ERR_NONE; | ||
390 | case AT_Reply_Error: | ||
391 | return ERR_UNKNOWN; | ||
392 | case AT_Reply_CMSError: | ||
393 | return ATGEN_HandleCMSError(s); | ||
394 | case AT_Reply_CMEError: | ||
395 | return ATGEN_HandleCMEError(s); | ||
396 | default: | ||
397 | return ERR_UNKNOWNRESPONSE; | ||
398 | } | ||
399 | } | ||
400 | |||
401 | GSM_Error SAMSUNG_GetRingtone(GSM_StateMachine *s, GSM_Ringtone *Ringtone, bool PhoneRingtone) | ||
402 | { | ||
403 | unsigned char req[100]; | ||
404 | |||
405 | s->Phone.Data.Ringtone = Ringtone; | ||
406 | smprintf(s, "Getting ringtone\n"); | ||
407 | sprintf(req, "AT+MELR=%d\r", Ringtone->Location-1); | ||
408 | return GSM_WaitFor (s, req, strlen(req), 0x00, 4, ID_GetRingtone); | ||
409 | } | ||
410 | |||
411 | GSM_Error SAMSUNG_ReplySetRingtone(GSM_Protocol_Message msg, GSM_StateMachine *s) | ||
412 | { | ||
413 | smprintf(s, "Ringtone sent\n"); | ||
414 | return ReplySetSamsungFrame(msg, s); | ||
415 | } | ||
416 | |||
417 | GSM_Error SAMSUNG_SetRingtone(GSM_StateMachine *s, GSM_Ringtone *Ringtone, int *maxlength) | ||
418 | { | ||
419 | unsigned charreq[100]; | ||
420 | unsigned longcrc; | ||
421 | GSM_Errorerror; | ||
422 | char name[50], *dot; | ||
423 | |||
424 | s->Phone.Data.Ringtone = Ringtone; | ||
425 | smprintf(s, "Setting ringtone\n"); | ||
426 | |||
427 | if (Ringtone->Format != RING_MMF) { | ||
428 | smprintf(s, "Not MMF ringtone\n"); | ||
429 | return ERR_INVALIDDATA; | ||
430 | } | ||
431 | |||
432 | /* Remove extension from file name */ | ||
433 | strncpy(name, DecodeUnicodeString(Ringtone->Name), 50); | ||
434 | if ((dot = strrchr(name, '.')) != NULL) *dot = 0; | ||
435 | |||
436 | crc = GetCRC(Ringtone->BinaryTone.Buffer, Ringtone->BinaryTone.Length); | ||
437 | sprintf(req, "AT+MELW=0,\"%s\",4,%d,%u\r", name, | ||
438 | Ringtone->BinaryTone.Length, (unsigned int)crc); | ||
439 | |||
440 | error = s->Protocol.Functions->WriteMessage(s, req, strlen(req), 0x00); | ||
441 | if (error!=ERR_NONE) return error; | ||
442 | |||
443 | return SetSamsungFrame(s, Ringtone->BinaryTone.Buffer, | ||
444 | Ringtone->BinaryTone.Length, ID_SetRingtone); | ||
445 | } | ||
446 | |||
447 | #endif | ||