1 /*
2
3 G N O K I I
4
5 A Linux/Unix toolset and driver for the mobile phones.
6
7 This file is part of gnokii.
8
9 Gnokii is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
13
14 Gnokii is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with gnokii; if not, write to the Free Software
21 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22
23 Copyright (C) 2000 Hugh Blemings & Pavel Janik ml.
24 Copyright (C) 2000 Chris Kemp
25 Copyright (C) 2001 Ladis Michl, Marian Jancar
26 Copyright (C) 2001-2002 Markus Plail
27 Copyright (C) 2001-2004 Pawel Kot
28 Copyright (C) 2002-2003 BORBELY Zoltan
29 Copyright (C) 2002-2003 Ladis Michl
30 Copyright (C) 2002 Marcin Wiacek
31
32 This file provides functions specific to the Nokia 7110 series.
33 See README for more details on supported mobile phones.
34
35 The various routines are called NK7110_(whatever).
36
37 */
38
39 #include "config.h"
40
41 #include <string.h>
42 #include <stdlib.h>
43 #include <ctype.h>
44
45 #include "compat.h"
46 #include "gnokii.h"
47 #include "nokia-decoding.h"
48 #include "phones/nk7110.h"
49 #include "phones/generic.h"
50 #include "phones/nokia.h"
51 #include "links/fbus.h"
52 #include "links/fbus-phonet.h"
53 #include "links/m2bus.h"
54
55 #include "gnokii-internal.h"
56
57 #define DRVINSTANCE(s) (*((nk7110_driver_instance **)(&(s)->driver.driver_instance)))
58 #define FREE(p) do { free(p); (p) = NULL; } while (0)
59
60 #define SEND_MESSAGE_BLOCK(type, length) \
61 do { \
62 if (sm_message_send(length, type, req, state)) return GN_ERR_NOTREADY; \
63 return sm_block(type, data, state); \
64 } while (0)
65
66 #define SEND_MESSAGE_WAITFOR(type, length) \
67 do { \
68 if (sm_message_send(length, type, req, state)) return GN_ERR_NOTREADY; \
69 return sm_wait_for(type, data, state); \
70 } while (0)
71
72 /* Functions prototypes */
73 static gn_error NK7110_Functions(gn_operation op, gn_data *data, struct gn_statemachine *state);
74 static gn_error NK7110_Initialise(struct gn_statemachine *state);
75 static gn_error NK7110_GetModel(gn_data *data, struct gn_statemachine *state);
76 static gn_error NK7110_GetRevision(gn_data *data, struct gn_statemachine *state);
77 static gn_error NK7110_GetIMEI(gn_data *data, struct gn_statemachine *state);
78 static gn_error NK7110_Identify(gn_data *data, struct gn_statemachine *state);
79 static gn_error NK7110_GetBatteryLevel(gn_data *data, struct gn_statemachine *state);
80 static gn_error NK7110_GetRFLevel(gn_data *data, struct gn_statemachine *state);
81 static gn_error NK7110_GetMemoryStatus(gn_data *data, struct gn_statemachine *state);
82 static gn_error NK7110_SetBitmap(gn_data *data, struct gn_statemachine *state);
83 static gn_error NK7110_GetBitmap(gn_data *data, struct gn_statemachine *state);
84 static gn_error NK7110_WritePhonebookLocation(gn_data *data, struct gn_statemachine *state);
85 static gn_error NK7110_ReadPhonebook(gn_data *data, struct gn_statemachine *state);
86 static gn_error NK7110_DeletePhonebookLocation(gn_data *data, struct gn_statemachine *state);
87 static gn_error NK7110_GetNetworkInfo(gn_data *data, struct gn_statemachine *state);
88 static gn_error NK7110_GetSpeedDial(gn_data *data, struct gn_statemachine *state);
89 static gn_error NK7110_GetSMSCenter(gn_data *data, struct gn_statemachine *state);
90 static gn_error NK7110_GetClock(char req_type, gn_data *data, struct gn_statemachine *state);
91 static gn_error NK7110_SetClock(gn_data *data, struct gn_statemachine *state);
92 static gn_error NK7110_SetAlarm(gn_data *data, struct gn_statemachine *state);
93 static gn_error NK7110_GetCalendarNote(gn_data *data, struct gn_statemachine *state);
94 static gn_error NK7110_WriteCalendarNote(gn_data *data, struct gn_statemachine *state);
95 static gn_error NK7110_DeleteCalendarNote(gn_data *data, struct gn_statemachine *state);
96 static gn_error NK7110_SendSMS(gn_data *data, struct gn_statemachine *state);
97 static gn_error NK7110_SaveSMS(gn_data *data, struct gn_statemachine *state);
98 static gn_error NK7110_GetSMS(gn_data *data, struct gn_statemachine *state);
99 static gn_error NK7110_GetSMSnoValidate(gn_data *data, struct gn_statemachine *state);
100 static gn_error NK7110_DeleteSMS(gn_data *data, struct gn_statemachine *state);
101 static gn_error NK7110_DeleteSMSnoValidate(gn_data *data, struct gn_statemachine *state);
102 static gn_error NK7110_GetPictureList(gn_data *data, struct gn_statemachine *state);
103 static gn_error NK7110_GetSMSFolders(gn_data *data, struct gn_statemachine *state);
104 static gn_error NK7110_GetSMSFolderStatus(gn_data *data, struct gn_statemachine *state);
105 static gn_error NK7110_GetSMSStatus(gn_data *data, struct gn_statemachine *state);
106 static gn_error NK7110_GetSecurityCode(gn_data *data, struct gn_statemachine *state);
107 static gn_error NK7110_PressOrReleaseKey(gn_data *data, struct gn_statemachine *state, bool press);
108 static gn_error NK7110_GetRawRingtone(gn_data *data, struct gn_statemachine *state);
109 static gn_error NK7110_SetRawRingtone(gn_data *data, struct gn_statemachine *state);
110 static gn_error NK7110_GetRingtone(gn_data *data, struct gn_statemachine *state);
111 static gn_error NK7110_SetRingtone(gn_data *data, struct gn_statemachine *state);
112 static gn_error NK7110_GetRingtoneList(gn_data *data, struct gn_statemachine *state);
113 static gn_error NK7110_GetProfile(gn_data *data, struct gn_statemachine *state);
114 static gn_error NK7110_SetProfile(gn_data *data, struct gn_statemachine *state);
115
116 static gn_error NK7110_GetActiveCalls(gn_data *data, struct gn_statemachine *state);
117 static gn_error NK7110_MakeCall(gn_data *data, struct gn_statemachine *state);
118 static gn_error NK7110_CancelCall(gn_data *data, struct gn_statemachine *state);
119 static gn_error NK7110_AnswerCall(gn_data *data, struct gn_statemachine *state);
120
121 static gn_error NK7110_DeleteWAPBookmark(gn_data *data, struct gn_statemachine *state);
122 static gn_error NK7110_GetWAPBookmark(gn_data *data, struct gn_statemachine *state);
123 static gn_error NK7110_WriteWAPBookmark(gn_data *data, struct gn_statemachine *state);
124 static gn_error NK7110_GetWAPSetting(gn_data *data, struct gn_statemachine *state);
125 static gn_error NK7110_ActivateWAPSetting(gn_data *data, struct gn_statemachine *state);
126 static gn_error NK7110_WriteWAPSetting(gn_data *data, struct gn_statemachine *state);
127
128 static gn_error NK7110_IncomingIdentify(int messagetype, unsigned char *buffer, int length, gn_data *data, struct gn_statemachine *state);
129 static gn_error NK7110_IncomingPhonebook(int messagetype, unsigned char *buffer, int length, gn_data *data, struct gn_statemachine *state);
130 static gn_error NK7110_IncomingNetwork(int messagetype, unsigned char *buffer, int length, gn_data *data, struct gn_statemachine *state);
131 static gn_error NK7110_IncomingBattLevel(int messagetype, unsigned char *buffer, int length, gn_data *data, struct gn_statemachine *state);
132 static gn_error NK7110_IncomingStartup(int messagetype, unsigned char *buffer, int length, gn_data *data, struct gn_statemachine *state);
133 static gn_error NK7110_IncomingSMS(int messagetype, unsigned char *buffer, int length, gn_data *data, struct gn_statemachine *state);
134 static gn_error NK7110_IncomingFolder(int messagetype, unsigned char *buffer, int length, gn_data *data, struct gn_statemachine *state);
135 static gn_error NK7110_IncomingClock(int messagetype, unsigned char *message, int length, gn_data *data, struct gn_statemachine *state);
136 static gn_error NK7110_IncomingCalendar(int messagetype, unsigned char *message, int length, gn_data *data, struct gn_statemachine *state);
137 static gn_error NK7110_IncomingSecurity(int messagetype, unsigned char *message, int length, gn_data *data, struct gn_statemachine *state);
138 static gn_error NK7110_IncomingWAP(int messagetype, unsigned char *message, int length, gn_data *data, struct gn_statemachine *state);
139 static gn_error NK7110_IncomingKeypress(int messagetype, unsigned char *message, int length, gn_data *data, struct gn_statemachine *state);
140 static gn_error NK7110_IncomingProfile(int messagetype, unsigned char *message, int length, gn_data *data, struct gn_statemachine *state);
141 static gn_error NK7110_IncomingRingtone(int messagetype, unsigned char *message, int length, gn_data *data, struct gn_statemachine *state);
142 static gn_error NK7110_IncomingCommstatus(int messagetype, unsigned char *message, int length, gn_data *data, struct gn_statemachine *state);
143
144 static int get_memory_type(gn_memory_type memory_type);
145 static gn_memory_type get_gn_memory_type(int memory_type);
146
147 static gn_incoming_function_type nk7110_incoming_functions[] = {
148 { NK7110_MSG_FOLDER, NK7110_IncomingFolder },
149 { NK7110_MSG_SMS, NK7110_IncomingSMS },
150 { NK7110_MSG_PHONEBOOK, NK7110_IncomingPhonebook },
151 { NK7110_MSG_NETSTATUS, NK7110_IncomingNetwork },
152 { NK7110_MSG_CALENDAR, NK7110_IncomingCalendar },
153 { NK7110_MSG_BATTERY, NK7110_IncomingBattLevel },
154 { NK7110_MSG_CLOCK, NK7110_IncomingClock },
155 { NK7110_MSG_IDENTITY, NK7110_IncomingIdentify },
156 { NK7110_MSG_STLOGO, NK7110_IncomingStartup },
157 { NK7110_MSG_DIVERT, pnok_call_divert_incoming },
158 { NK7110_MSG_SECURITY, NK7110_IncomingSecurity },
159 { NK7110_MSG_WAP, NK7110_IncomingWAP },
160 { NK7110_MSG_KEYPRESS_RESP, NK7110_IncomingKeypress },
161 { NK7110_MSG_PROFILE, NK7110_IncomingProfile },
162 { NK7110_MSG_RINGTONE, NK7110_IncomingRingtone },
163 { NK7110_MSG_COMMSTATUS, NK7110_IncomingCommstatus },
164 { 0, NULL }
165 };
166
167 gn_driver driver_nokia_7110 = {
168 nk7110_incoming_functions,
169 pgen_incoming_default,
170 /* Mobile phone information */
171 {
172 "7110|6210|6250|7190", /* Supported models */
173 7, /* Max RF Level */
174 0, /* Min RF Level */
175 GN_RF_Percentage, /* RF level units */
176 7, /* Max Battery Level */
177 0, /* Min Battery Level */
178 GN_BU_Percentage, /* Battery level units */
179 GN_DT_DateTime, /* Have date/time support */
180 GN_DT_TimeOnly, /* Alarm supports time only */
181 1, /* Alarms available - FIXME */
182 60, 96, /* Startup logo size - 7110 is fixed at init */
183 21, 78, /* Op logo size */
184 14, 72 /* Caller logo size */
185 },
186 NK7110_Functions,
187 NULL
188 };
189
190 /* FIXME - a little macro would help here... */
NK7110_Functions(gn_operation op,gn_data * data,struct gn_statemachine * state)191 static gn_error NK7110_Functions(gn_operation op, gn_data *data, struct gn_statemachine *state)
192 {
193 if (!DRVINSTANCE(state) && op != GN_OP_Init) return GN_ERR_INTERNALERROR;
194
195 switch (op) {
196 case GN_OP_Init:
197 return NK7110_Initialise(state);
198 case GN_OP_Terminate:
199 FREE(DRVINSTANCE(state));
200 return pgen_terminate(data, state);
201 case GN_OP_GetModel:
202 return NK7110_GetModel(data, state);
203 case GN_OP_GetRevision:
204 return NK7110_GetRevision(data, state);
205 case GN_OP_GetImei:
206 return NK7110_GetIMEI(data, state);
207 case GN_OP_Identify:
208 return NK7110_Identify(data, state);
209 case GN_OP_GetBatteryLevel:
210 return NK7110_GetBatteryLevel(data, state);
211 case GN_OP_GetRFLevel:
212 return NK7110_GetRFLevel(data, state);
213 case GN_OP_GetMemoryStatus:
214 return NK7110_GetMemoryStatus(data, state);
215 case GN_OP_GetBitmap:
216 return NK7110_GetBitmap(data, state);
217 case GN_OP_SetBitmap:
218 return NK7110_SetBitmap(data, state);
219 case GN_OP_ReadPhonebook:
220 return NK7110_ReadPhonebook(data, state);
221 case GN_OP_WritePhonebook:
222 return NK7110_WritePhonebookLocation(data, state);
223 case GN_OP_DeletePhonebook:
224 return NK7110_DeletePhonebookLocation(data, state);
225 case GN_OP_GetNetworkInfo:
226 return NK7110_GetNetworkInfo(data, state);
227 case GN_OP_GetSpeedDial:
228 return NK7110_GetSpeedDial(data, state);
229 case GN_OP_GetSMSCenter:
230 return NK7110_GetSMSCenter(data, state);
231 case GN_OP_GetDateTime:
232 return NK7110_GetClock(NK7110_SUBCLO_GET_DATE, data, state);
233 case GN_OP_SetDateTime:
234 return NK7110_SetClock(data, state);
235 case GN_OP_GetAlarm:
236 return NK7110_GetClock(NK7110_SUBCLO_GET_ALARM, data, state);
237 case GN_OP_SetAlarm:
238 return NK7110_SetAlarm(data, state);
239 case GN_OP_GetCalendarNote:
240 return NK7110_GetCalendarNote(data, state);
241 case GN_OP_WriteCalendarNote:
242 return NK7110_WriteCalendarNote(data, state);
243 case GN_OP_DeleteCalendarNote:
244 return NK7110_DeleteCalendarNote(data, state);
245 case GN_OP_GetSMS:
246 dprintf("Getting SMS (validating)...\n");
247 return NK7110_GetSMS(data, state);
248 case GN_OP_GetSMSnoValidate:
249 dprintf("Getting SMS (no validating)...\n");
250 return NK7110_GetSMSnoValidate(data, state);
251 case GN_OP_OnSMS:
252 DRVINSTANCE(state)->on_sms = data->on_sms;
253 DRVINSTANCE(state)->sms_callback_data = data->callback_data;
254 /* Register notify when running for the first time */
255 if (data->on_sms) {
256 DRVINSTANCE(state)->new_sms = true;
257 return GN_ERR_NONE; /* FIXME NK7110_GetIncomingSMS(data, state); */
258 }
259 break;
260 case GN_OP_PollSMS:
261 if (DRVINSTANCE(state)->new_sms)
262 return GN_ERR_NONE; /* FIXME NK7110_GetIncomingSMS(data, state); */
263 break;
264 case GN_OP_SendSMS:
265 return NK7110_SendSMS(data, state);
266 case GN_OP_SaveSMS:
267 return NK7110_SaveSMS(data, state);
268 case GN_OP_DeleteSMSnoValidate:
269 return NK7110_DeleteSMSnoValidate(data, state);
270 case GN_OP_DeleteSMS:
271 return NK7110_DeleteSMS(data, state);
272 case GN_OP_GetSMSStatus:
273 return NK7110_GetSMSStatus(data, state);
274 case GN_OP_CallDivert:
275 return pnok_call_divert(data, state);
276 case GN_OP_NetMonitor:
277 return pnok_netmonitor(data, state);
278 case GN_OP_GetActiveCalls:
279 return NK7110_GetActiveCalls(data, state);
280 case GN_OP_MakeCall:
281 return NK7110_MakeCall(data, state);
282 case GN_OP_AnswerCall:
283 return NK7110_AnswerCall(data, state);
284 case GN_OP_CancelCall:
285 return NK7110_CancelCall(data, state);
286 case GN_OP_GetSecurityCode:
287 return NK7110_GetSecurityCode(data, state);
288 case GN_OP_GetSMSFolders:
289 return NK7110_GetSMSFolders(data, state);
290 case GN_OP_GetSMSFolderStatus:
291 return NK7110_GetSMSFolderStatus(data, state);
292 case GN_OP_NK7110_GetPictureList:
293 return NK7110_GetPictureList(data, state);
294 case GN_OP_DeleteWAPBookmark:
295 return NK7110_DeleteWAPBookmark(data, state);
296 case GN_OP_GetWAPBookmark:
297 return NK7110_GetWAPBookmark(data, state);
298 case GN_OP_WriteWAPBookmark:
299 return NK7110_WriteWAPBookmark(data, state);
300 case GN_OP_GetWAPSetting:
301 return NK7110_GetWAPSetting(data, state);
302 case GN_OP_ActivateWAPSetting:
303 return NK7110_ActivateWAPSetting(data, state);
304 case GN_OP_WriteWAPSetting:
305 return NK7110_WriteWAPSetting(data, state);
306 case GN_OP_PressPhoneKey:
307 return NK7110_PressOrReleaseKey(data, state, true);
308 case GN_OP_ReleasePhoneKey:
309 return NK7110_PressOrReleaseKey(data, state, false);
310 case GN_OP_GetRawRingtone:
311 return NK7110_GetRawRingtone(data, state);
312 case GN_OP_SetRawRingtone:
313 return NK7110_SetRawRingtone(data, state);
314 case GN_OP_GetRingtone:
315 return NK7110_GetRingtone(data, state);
316 case GN_OP_SetRingtone:
317 return NK7110_SetRingtone(data, state);
318 case GN_OP_GetRingtoneList:
319 return NK7110_GetRingtoneList(data, state);
320 case GN_OP_PlayTone:
321 return pnok_play_tone(data, state);
322 case GN_OP_GetLocksInfo:
323 return pnok_get_locks_info(data, state);
324 case GN_OP_GetProfile:
325 return NK7110_GetProfile(data, state);
326 case GN_OP_SetProfile:
327 return NK7110_SetProfile(data, state);
328 default:
329 return GN_ERR_NOTIMPLEMENTED;
330 }
331 return GN_ERR_NONE;
332 }
333
334 /* Initialise is the only function allowed to 'use' state */
NK7110_Initialise(struct gn_statemachine * state)335 static gn_error NK7110_Initialise(struct gn_statemachine *state)
336 {
337 gn_data data;
338 char model[GN_MODEL_MAX_LENGTH+1];
339 gn_error err = GN_ERR_NONE;
340 bool connected = false;
341 unsigned int attempt = 0;
342
343 /* Copy in the phone info */
344 memcpy(&(state->driver), &driver_nokia_7110, sizeof(gn_driver));
345
346 if (!(DRVINSTANCE(state) = calloc(1, sizeof(nk7110_driver_instance))))
347 return GN_ERR_INTERNALERROR;
348
349 dprintf("Connecting\n");
350 while (!connected) {
351 if (attempt > 2) break;
352 switch (state->config.connection_type) {
353 case GN_CT_Bluetooth:
354 case GN_CT_DAU9P:
355 attempt++;
356 case GN_CT_DLR3P:
357 if (attempt > 1) {
358 attempt = 3;
359 break;
360 }
361 case GN_CT_Serial:
362 case GN_CT_TCP:
363 err = fbus_initialise(attempt++, state);
364 break;
365 case GN_CT_Infrared:
366 case GN_CT_Irda:
367 err = phonet_initialise(state);
368 attempt = 3;
369 break;
370 case GN_CT_M2BUS:
371 err = m2bus_initialise(state);
372 break;
373 default:
374 FREE(DRVINSTANCE(state));
375 return GN_ERR_NOTSUPPORTED;
376 }
377
378 if (err != GN_ERR_NONE) {
379 dprintf("Error in link initialisation: %d\n", err);
380 continue;
381 }
382
383 sm_initialise(state);
384
385 /* Now test the link and get the model */
386 gn_data_clear(&data);
387 data.model = model;
388 err = state->driver.functions(GN_OP_GetModel, &data, state);
389 if (err == GN_ERR_NONE) {
390 connected = true;
391 } else {
392 /* ignore return value from pgen_terminate(), will use previous error code instead */
393 pgen_terminate(&data, state);
394 }
395 }
396 if (!connected) {
397 FREE(DRVINSTANCE(state));
398 return err;
399 }
400
401 /* Check for 7110 and alter the startup logo size */
402 if (strcmp(model, "NSE-5") == 0) {
403 state->driver.phone.startup_logo_height = 65;
404 dprintf("7110 detected - startup logo height set to 65\n");
405 DRVINSTANCE(state)->userdef_location = 0x75;
406 } else {
407 DRVINSTANCE(state)->userdef_location = 0x8a;
408 }
409
410 pnok_extended_cmds_enable(0x01, &data, state);
411
412 return GN_ERR_NONE;
413 }
414
415 /*****************************/
416 /********* IDENTIFY **********/
417 /*****************************/
NK7110_IncomingIdentify(int messagetype,unsigned char * message,int length,gn_data * data,struct gn_statemachine * state)418 static gn_error NK7110_IncomingIdentify(int messagetype, unsigned char *message, int length, gn_data *data, struct gn_statemachine *state)
419 {
420 switch (message[3]) {
421 case 0x02:
422 if (data->imei) {
423 int n;
424 unsigned char *s = strchr(message + 4, '\n');
425
426 if (s) n = s - message - 3;
427 else n = GN_IMEI_MAX_LENGTH;
428 snprintf(data->imei, GNOKII_MIN(n, GN_IMEI_MAX_LENGTH), "%s", message + 4);
429 dprintf("Received imei %s\n", data->imei);
430 }
431 break;
432 case 0x04:
433 if (data->model) {
434 int n;
435 unsigned char *s = strchr(message + 22, '\n');
436
437 n = s ? s - message - 21 : GN_MODEL_MAX_LENGTH;
438 snprintf(data->model, GNOKII_MIN(n, GN_MODEL_MAX_LENGTH), "%s", message + 22);
439 dprintf("Received model %s\n", data->model);
440 }
441 if (data->revision) {
442 int n;
443 unsigned char *s = strchr(message + 7, '\n');
444
445 n = s ? s - message - 6 : GN_REVISION_MAX_LENGTH;
446 snprintf(data->revision, GNOKII_MIN(n, GN_REVISION_MAX_LENGTH), "%s", message + 7);
447 dprintf("Received revision %s\n", data->revision);
448 }
449 break;
450 default:
451 dprintf("Unknown subtype of type 0x1b (%d)\n", message[3]);
452 return GN_ERR_UNHANDLEDFRAME;
453 }
454 return GN_ERR_NONE;
455 }
456
457 /* Just as an example.... */
458 /* But note that both requests are the same type which isn't very 'proper' */
NK7110_Identify(gn_data * data,struct gn_statemachine * state)459 static gn_error NK7110_Identify(gn_data *data, struct gn_statemachine *state)
460 {
461 unsigned char req[] = {FBUS_FRAME_HEADER, 0x01};
462 unsigned char req2[] = {FBUS_FRAME_HEADER, 0x03, 0x01, 0x32};
463
464 dprintf("Identifying...\n");
465 pnok_manufacturer_get(data->manufacturer);
466 if (sm_message_send(4, NK7110_MSG_IDENTITY, req, state)) return GN_ERR_NOTREADY;
467 if (sm_message_send(6, NK7110_MSG_IDENTITY, req2, state)) return GN_ERR_NOTREADY;
468 sm_wait_for(NK7110_MSG_IDENTITY, data, state);
469 sm_block(NK7110_MSG_IDENTITY, data, state); /* waits for all requests - returns req2 error */
470 sm_error_get(NK7110_MSG_IDENTITY, state);
471
472 /* Check that we are back at state Initialised */
473 if (gn_sm_loop(0, state) != GN_SM_Initialised) return GN_ERR_UNKNOWN;
474 return GN_ERR_NONE;
475 }
476
NK7110_GetModel(gn_data * data,struct gn_statemachine * state)477 static gn_error NK7110_GetModel(gn_data *data, struct gn_statemachine *state)
478 {
479 unsigned char req[] = {FBUS_FRAME_HEADER, 0x03, 0x01, 0x32};
480
481 dprintf("Getting model...\n");
482 SEND_MESSAGE_BLOCK(NK7110_MSG_IDENTITY, 6);
483 }
484
NK7110_GetRevision(gn_data * data,struct gn_statemachine * state)485 static gn_error NK7110_GetRevision(gn_data *data, struct gn_statemachine *state)
486 {
487 unsigned char req[] = {FBUS_FRAME_HEADER, 0x03, 0x01, 0x32};
488
489 dprintf("Getting revision...\n");
490 SEND_MESSAGE_BLOCK(NK7110_MSG_IDENTITY, 6);
491 }
492
NK7110_GetIMEI(gn_data * data,struct gn_statemachine * state)493 static gn_error NK7110_GetIMEI(gn_data *data, struct gn_statemachine *state)
494 {
495 unsigned char req[] = {FBUS_FRAME_HEADER, 0x01};
496
497 dprintf("Getting imei...\n");
498 SEND_MESSAGE_BLOCK(NK7110_MSG_IDENTITY, 4);
499 }
500
501 /*****************************/
502 /********** BATTERY **********/
503 /*****************************/
NK7110_IncomingBattLevel(int messagetype,unsigned char * message,int length,gn_data * data,struct gn_statemachine * state)504 static gn_error NK7110_IncomingBattLevel(int messagetype, unsigned char *message, int length, gn_data *data, struct gn_statemachine *state)
505 {
506 switch (message[3]) {
507 case 0x03:
508 if (data->battery_level) {
509 *(data->battery_unit) = GN_BU_Percentage;
510 *(data->battery_level) = message[5];
511 dprintf("Battery level %f\n",*(data->battery_level));
512 }
513 break;
514 default:
515 dprintf("Unknown subtype of type 0x17 (%d)\n", message[3]);
516 return GN_ERR_UNKNOWN;
517 }
518 return GN_ERR_NONE;
519 }
520
NK7110_GetBatteryLevel(gn_data * data,struct gn_statemachine * state)521 static gn_error NK7110_GetBatteryLevel(gn_data *data, struct gn_statemachine *state)
522 {
523 unsigned char req[] = {FBUS_FRAME_HEADER, 0x02};
524
525 dprintf("Getting battery level...\n");
526 SEND_MESSAGE_BLOCK(NK7110_MSG_BATTERY, 4);
527 }
528
529 /*****************************/
530 /********** NETWORK **********/
531 /*****************************/
NK7110_IncomingNetwork(int messagetype,unsigned char * message,int length,gn_data * data,struct gn_statemachine * state)532 static gn_error NK7110_IncomingNetwork(int messagetype, unsigned char *message, int length, gn_data *data, struct gn_statemachine *state)
533 {
534 unsigned char *blockstart;
535 gn_error error = GN_ERR_NONE;
536 int i;
537
538 switch (message[3]) {
539 case 0x71:
540 blockstart = message + 6;
541 for (i = 0; i < message[4]; i++) {
542 switch (blockstart[0]) {
543 case 0x01: /* Operator details */
544 /* Network code is stored as 0xBA 0xXC 0xED ("ABC DE"). */
545 if (data->network_info) {
546 /* Is this correct? */
547 data->network_info->cell_id[0] = blockstart[4];
548 data->network_info->cell_id[1] = blockstart[5];
549 data->network_info->LAC[0] = blockstart[6];
550 data->network_info->LAC[1] = blockstart[7];
551 data->network_info->network_code[0] = '0' + (blockstart[8] & 0x0f);
552 data->network_info->network_code[1] = '0' + (blockstart[8] >> 4);
553 data->network_info->network_code[2] = '0' + (blockstart[9] & 0x0f);
554 data->network_info->network_code[3] = ' ';
555 data->network_info->network_code[4] = '0' + (blockstart[10] & 0x0f);
556 data->network_info->network_code[5] = '0' + (blockstart[10] >> 4);
557 data->network_info->network_code[6] = 0;
558 }
559 if (data->bitmap) {
560 data->bitmap->netcode[0] = '0' + (blockstart[8] & 0x0f);
561 data->bitmap->netcode[1] = '0' + (blockstart[8] >> 4);
562 data->bitmap->netcode[2] = '0' + (blockstart[9] & 0x0f);
563 data->bitmap->netcode[3] = ' ';
564 data->bitmap->netcode[4] = '0' + (blockstart[10] & 0x0f);
565 data->bitmap->netcode[5] = '0' + (blockstart[10] >> 4);
566 data->bitmap->netcode[6] = 0;
567 dprintf("Operator %s\n", data->bitmap->netcode);
568 }
569 break;
570 case 0x04: /* Logo */
571 if (data->bitmap) {
572 dprintf("Op logo received ok\n");
573 data->bitmap->type = GN_BMP_OperatorLogo;
574 data->bitmap->size = blockstart[5]; /* Probably + [4]<<8 */
575 data->bitmap->height = blockstart[3];
576 data->bitmap->width = blockstart[2];
577 memcpy(data->bitmap->bitmap, blockstart + 8, data->bitmap->size);
578 dprintf("Logo (%dx%d)\n", data->bitmap->height, data->bitmap->width);
579 }
580 break;
581 default:
582 dprintf("Unknown operator block %d\n", blockstart[0]);
583 break;
584 }
585 blockstart += blockstart[1];
586 }
587 break;
588 case 0x82:
589 if (data->rf_level) {
590 *(data->rf_unit) = GN_RF_Percentage;
591 *(data->rf_level) = message[4];
592 dprintf("RF level %f\n", *(data->rf_level));
593 }
594 break;
595 case 0xa4:
596 dprintf("Op Logo Set OK\n");
597 break;
598 case 0xa5:
599 dprintf("Op Logo Set failed\n");
600 /* Perhaps this should be WRONGFORMAT */
601 error = GN_ERR_FAILED;
602 break;
603 default:
604 dprintf("Unknown subtype of type 0x0a (%d)\n", message[3]);
605 error = GN_ERR_UNHANDLEDFRAME;
606 }
607 return error;
608 }
609
610
NK7110_GetRFLevel(gn_data * data,struct gn_statemachine * state)611 static gn_error NK7110_GetRFLevel(gn_data *data, struct gn_statemachine *state)
612 {
613 unsigned char req[] = {FBUS_FRAME_HEADER, 0x81};
614
615 dprintf("Getting rf level...\n");
616 SEND_MESSAGE_BLOCK(NK7110_MSG_NETSTATUS, 4);
617 }
618
NK7110_GetNetworkInfo(gn_data * data,struct gn_statemachine * state)619 static gn_error NK7110_GetNetworkInfo(gn_data *data, struct gn_statemachine *state)
620 {
621 unsigned char req[] = {FBUS_FRAME_HEADER, 0x70};
622
623 dprintf("Getting Network Info...\n");
624 SEND_MESSAGE_BLOCK(NK7110_MSG_NETSTATUS, 4);
625 }
626
SetOperatorBitmap(gn_data * data,struct gn_statemachine * state)627 static gn_error SetOperatorBitmap(gn_data *data, struct gn_statemachine *state)
628 {
629 unsigned char req[500] = { FBUS_FRAME_HEADER, 0xa3, 0x01,
630 0x00, /* logo enabled */
631 0x00, 0xf0, 0x00, /* network code (000 00) */
632 0x00 ,0x04,
633 0x08, /* length of rest */
634 0x00, 0x00, /* Bitmap width / height */
635 0x00,
636 0x00, /* Bitmap size */
637 0x00, 0x00 };
638 int count = 18;
639
640 if ((data->bitmap->width != state->driver.phone.operator_logo_width) ||
641 (data->bitmap->height != state->driver.phone.operator_logo_height)) {
642 dprintf("Invalid image size - expecting (%dx%d) got (%dx%d)\n",
643 state->driver.phone.operator_logo_height,
644 state->driver.phone.operator_logo_width,
645 data->bitmap->height, data->bitmap->width);
646 return GN_ERR_INVALIDSIZE;
647 }
648
649 if (strcmp(data->bitmap->netcode, "000 00")) { /* set logo */
650 req[5] = 0x01; /* Logo enabled */
651 req[6] = ((data->bitmap->netcode[1] & 0x0f) << 4) | (data->bitmap->netcode[0] & 0x0f);
652 req[7] = 0xf0 | (data->bitmap->netcode[2] & 0x0f);
653 req[8] = ((data->bitmap->netcode[5] & 0x0f) << 4) | (data->bitmap->netcode[4] & 0x0f);
654 req[11] = 8 + data->bitmap->size;
655 req[12] = data->bitmap->width;
656 req[13] = data->bitmap->height;
657 req[15] = data->bitmap->size;
658 memcpy(req + count, data->bitmap->bitmap, data->bitmap->size);
659 count += data->bitmap->size;
660 }
661 dprintf("Setting op logo...\n");
662 SEND_MESSAGE_BLOCK(NK7110_MSG_NETSTATUS, count);
663 }
664
GetOperatorBitmap(gn_data * data,struct gn_statemachine * state)665 static gn_error GetOperatorBitmap(gn_data *data, struct gn_statemachine *state)
666 {
667 unsigned char req[] = {FBUS_FRAME_HEADER, 0x70};
668
669 dprintf("Getting op logo...\n");
670 SEND_MESSAGE_BLOCK(NK7110_MSG_NETSTATUS, 4);
671 }
672
673
674 /*****************************/
675 /********* PHONEBOOK *********/
676 /*****************************/
NK7110_IncomingPhonebook(int messagetype,unsigned char * message,int length,gn_data * data,struct gn_statemachine * state)677 static gn_error NK7110_IncomingPhonebook(int messagetype, unsigned char *message, int length, gn_data *data, struct gn_statemachine *state)
678 {
679 nk7110_driver_instance *drvinst = DRVINSTANCE(state);
680 unsigned char *blockstart;
681 unsigned char blocks;
682 int memtype, location, memtype_req;
683
684 switch (message[3]) {
685 case 0x04: /* Get status response */
686 if (data->memory_status) {
687 if (message[5] != 0xff) {
688 data->memory_status->used = (message[16] << 8) + message[17];
689 data->memory_status->free = ((message[14] << 8) + message[15]) - data->memory_status->used;
690 dprintf("Memory status - location = %d\n", (message[8] << 8) + message[9]);
691 } else {
692 dprintf("Unknown error getting mem status\n");
693 return GN_ERR_NOTIMPLEMENTED;
694 }
695 }
696 break;
697 case 0x08: /* Read Memory response */
698 memtype = message[11];
699 location = (message[12] << 8) + message[13];
700 if (data->phonebook_entry) {
701 data->phonebook_entry->empty = true;
702 data->phonebook_entry->caller_group = 5; /* no group */
703 data->phonebook_entry->name[0] = '\0';
704 data->phonebook_entry->number[0] = '\0';
705 data->phonebook_entry->subentries_count = 0;
706 data->phonebook_entry->date.year = 0;
707 data->phonebook_entry->date.month = 0;
708 data->phonebook_entry->date.day = 0;
709 data->phonebook_entry->date.hour = 0;
710 data->phonebook_entry->date.minute = 0;
711 data->phonebook_entry->date.second = 0;
712 }
713 if (data->bitmap) {
714 data->bitmap->text[0] = '\0';
715 }
716 if (message[6] == 0x0f) { /* not found */
717 switch (message[10]) {
718 case 0x30:
719 if (data->phonebook_entry)
720 memtype_req = data->phonebook_entry->memory_type;
721 else
722 memtype_req = GN_MT_XX;
723 /*
724 * this message has two meanings: "invalid
725 * location" and "memory is empty"
726 */
727 switch (memtype_req) {
728 case GN_MT_SM:
729 case GN_MT_ME:
730 return GN_ERR_EMPTYLOCATION;
731 default:
732 break;
733 }
734 return GN_ERR_INVALIDMEMORYTYPE;
735 case 0x33:
736 return GN_ERR_EMPTYLOCATION;
737 case 0x34:
738 return GN_ERR_INVALIDLOCATION;
739 default:
740 return GN_ERR_NOTIMPLEMENTED;
741 }
742 }
743 if (drvinst->ll_memtype != memtype || drvinst->ll_location != location) {
744 dprintf("skipping entry: ll_memtype: %d, memtype: %d, ll_location: %d, location: %d\n",
745 drvinst->ll_memtype, memtype, drvinst->ll_location, location);
746 return GN_ERR_UNSOLICITED;
747 }
748 dprintf("Received phonebook info\n");
749 blocks = message[17];
750 blockstart = message + 18;
751 return phonebook_decode(blockstart, length - 17, data, blocks, message[11], 8);
752 case 0x0c:
753 if (message[6] == 0x0f) {
754 switch (message[10]) {
755 case 0x34: return GN_ERR_FAILED; /* invalid location ? */
756 case 0x3d: return GN_ERR_FAILED;
757 case 0x3e: return GN_ERR_FAILED;
758 default: return GN_ERR_UNHANDLEDFRAME;
759 }
760 }
761 break;
762 case 0x10:
763 dprintf("Entry successfully deleted!\n");
764 break;
765 default:
766 dprintf("Unknown subtype of type 0x03 (%d)\n", message[3]);
767 return GN_ERR_UNHANDLEDFRAME;
768 }
769 return GN_ERR_NONE;
770 }
771
NK7110_GetMemoryStatus(gn_data * data,struct gn_statemachine * state)772 static gn_error NK7110_GetMemoryStatus(gn_data *data, struct gn_statemachine *state)
773 {
774 unsigned char req[] = {FBUS_FRAME_HEADER, 0x03, 0x00, 0x00};
775
776 dprintf("Getting memory status...\n");
777 req[5] = get_memory_type(data->memory_status->memory_type);
778 SEND_MESSAGE_BLOCK(NK7110_MSG_PHONEBOOK, 6);
779 }
780
GetCallerBitmap(gn_data * data,struct gn_statemachine * state)781 static gn_error GetCallerBitmap(gn_data *data, struct gn_statemachine *state)
782 {
783 nk7110_driver_instance *drvinst = DRVINSTANCE(state);
784 unsigned char req[] = {FBUS_FRAME_HEADER, 0x07, 0x01, 0x01, 0x00, 0x01,
785 0x00, 0x10 , /* memory type */
786 0x00, 0x00, /* location */
787 0x00, 0x00};
788
789 req[11] = GNOKII_MIN(data->bitmap->number + 1, GN_PHONEBOOK_CALLER_GROUPS_MAX_NUMBER);
790 drvinst->ll_memtype = 0x10;
791 drvinst->ll_location = req[11];
792 dprintf("Getting caller(%d) logo...\n", req[11]);
793 SEND_MESSAGE_BLOCK(NK7110_MSG_PHONEBOOK, 14);
794 }
795
PackBlock(u8 id,u8 size,u8 no,u8 * buf,u8 * block)796 static unsigned char PackBlock(u8 id, u8 size, u8 no, u8 *buf, u8 *block)
797 {
798 *(block++) = id;
799 *(block++) = 0;
800 *(block++) = 0;
801 *(block++) = size + 6;
802 *(block++) = no;
803 memcpy(block, buf, size);
804 block += size;
805 *(block++) = 0;
806 return (size + 6);
807 }
808
SetCallerBitmap(gn_data * data,struct gn_statemachine * state)809 static gn_error SetCallerBitmap(gn_data *data, struct gn_statemachine *state)
810 {
811 unsigned char req[500] = {FBUS_FRAME_HEADER, 0x0b, 0x00, 0x01, 0x01, 0x00, 0x00, 0x0c,
812 0x00, 0x10, /* memory type */
813 0x00, 0x00, /* location */
814 0x00, 0x00, 0x00};
815 char string[500];
816 int block, i;
817 unsigned int count = 18;
818
819 if ((data->bitmap->width != state->driver.phone.caller_logo_width) ||
820 (data->bitmap->height != state->driver.phone.caller_logo_height)) {
821 dprintf("Invalid image size - expecting (%dx%d) got (%dx%d)\n",state->driver.phone.caller_logo_height, state->driver.phone.caller_logo_width, data->bitmap->height, data->bitmap->width);
822 return GN_ERR_INVALIDSIZE;
823 }
824
825 req[13] = data->bitmap->number + 1;
826 dprintf("Setting caller(%d) bitmap...\n",data->bitmap->number);
827 block = 1;
828 /* Name */
829 i = strlen(data->bitmap->text);
830 i = char_unicode_encode((string + 1), data->bitmap->text, i);
831 string[0] = i;
832 count += PackBlock(0x07, i + 1, block++, string, req + count);
833 /* Ringtone */
834 string[0] = data->bitmap->ringtone;
835 string[1] = 0;
836 count += PackBlock(0x0c, 2, block++, string, req + count);
837 /* Number */
838 string[0] = data->bitmap->number+1;
839 string[1] = 0;
840 count += PackBlock(0x1e, 2, block++, string, req + count);
841 /* Logo on/off - assume on for now */
842 string[0] = 1;
843 string[1] = 0;
844 count += PackBlock(0x1c, 2, block++, string, req + count);
845 /* Logo */
846 string[0] = data->bitmap->width;
847 string[1] = data->bitmap->height;
848 string[2] = 0;
849 string[3] = 0;
850 string[4] = 0x7e; /* Size */
851 memcpy(string + 5, data->bitmap->bitmap, data->bitmap->size);
852 count += PackBlock(0x1b, data->bitmap->size + 5, block++, string, req + count);
853 req[17] = block - 1;
854
855 SEND_MESSAGE_BLOCK(NK7110_MSG_PHONEBOOK, count);
856 }
857
NK7110_DeletePhonebookLocation(gn_data * data,struct gn_statemachine * state)858 static gn_error NK7110_DeletePhonebookLocation(gn_data *data, struct gn_statemachine *state)
859 {
860 unsigned char req[] = {FBUS_FRAME_HEADER, 0x0f, 0x00, 0x01, 0x04, 0x00, 0x00, 0x0c, 0x01, 0xff,
861 0x00, 0x00, /* location */
862 0x00, /* memory type */
863 0x00, 0x00, 0x00};
864 gn_phonebook_entry *entry;
865
866 if (data->phonebook_entry) entry = data->phonebook_entry;
867 else return GN_ERR_TRYAGAIN;
868 /* Two octets for the memory location */
869 req[12] = (entry->location >> 8);
870 req[13] = entry->location & 0xff;
871 req[14] = get_memory_type(entry->memory_type);
872
873 SEND_MESSAGE_BLOCK(NK7110_MSG_PHONEBOOK, 18);
874 }
875
NK7110_WritePhonebookLocation(gn_data * data,struct gn_statemachine * state)876 static gn_error NK7110_WritePhonebookLocation(gn_data *data, struct gn_statemachine *state)
877 {
878 unsigned char req[500] = {FBUS_FRAME_HEADER, 0x0b, 0x00, 0x01, 0x01, 0x00, 0x00, 0x0c,
879 0x00, 0x00, /* memory type */
880 0x00, 0x00, /* location */
881 0x00, 0x00, 0x00, 0x00};
882
883 char string[500];
884 int block, i, j, defaultn;
885 unsigned int count = 18;
886 gn_phonebook_entry *entry;
887
888 if (data->phonebook_entry) entry = data->phonebook_entry;
889 else return GN_ERR_TRYAGAIN;
890
891 req[11] = get_memory_type(entry->memory_type);
892 /* Two octets for the memory location */
893 req[12] = (entry->location >> 8);
894 req[13] = entry->location & 0xff;
895 block = 1;
896 if (!entry->empty) {
897 /* Name */
898 i = strlen(entry->name);
899 i = char_unicode_encode((string + 1), entry->name, i);
900 /* Length of the string + length field + terminating 0 */
901 string[0] = i + 2;
902 count += PackBlock(0x07, i + 2, block++, string, req + count);
903 /* Group */
904 string[0] = entry->caller_group + 1;
905 string[1] = 0;
906 count += PackBlock(0x1e, 2, block++, string, req + count);
907 /* We don't require the application to fill in any subentry.
908 * if it is not filled in, let's take just one number we have.
909 */
910 if (!entry->subentries_count) {
911 string[0] = GN_PHONEBOOK_ENTRY_Number;
912 string[1] = string[2] = string[3] = 0;
913 j = strlen(entry->number);
914 j = char_unicode_encode((string + 5), entry->number, j);
915 string[j + 1] = 0;
916 string[4] = j;
917 count += PackBlock(0x0b, j + 6, block++, string, req + count);
918 } else {
919 /* Default Number */
920 defaultn = 999;
921 for (i = 0; i < entry->subentries_count; i++)
922 if (entry->subentries[i].entry_type == GN_PHONEBOOK_ENTRY_Number)
923 if (!strcmp(entry->number, entry->subentries[i].data.number))
924 defaultn = i;
925 if (defaultn < i) {
926 string[0] = entry->subentries[defaultn].number_type;
927 string[1] = string[2] = string[3] = 0;
928 j = strlen(entry->subentries[defaultn].data.number);
929 j = char_unicode_encode((string + 5), entry->subentries[defaultn].data.number, j);
930 string[j + 1] = 0;
931 string[4] = j;
932 count += PackBlock(0x0b, j + 6, block++, string, req + count);
933 }
934 /* Rest of the numbers */
935 for (i = 0; i < entry->subentries_count; i++)
936 if (entry->subentries[i].entry_type == GN_PHONEBOOK_ENTRY_Number) {
937 if (i != defaultn) {
938 string[0] = entry->subentries[i].number_type;
939 string[1] = string[2] = string[3] = 0;
940 j = strlen(entry->subentries[i].data.number);
941 j = char_unicode_encode((string + 5), entry->subentries[i].data.number, j);
942 string[j + 1] = 0;
943 string[4] = j;
944 count += PackBlock(0x0b, j + 6, block++, string, req + count);
945 }
946 } else {
947 j = strlen(entry->subentries[i].data.number);
948 j = char_unicode_encode((string + 1), entry->subentries[i].data.number, j);
949 string[j + 1] = 0;
950 string[0] = j;
951 count += PackBlock(entry->subentries[i].entry_type, j + 2, block++, string, req + count);
952 }
953 }
954 req[17] = block - 1;
955 dprintf("Writing phonebook entry %s...\n", entry->name);
956 } else {
957 return NK7110_DeletePhonebookLocation(data, state);
958 }
959 SEND_MESSAGE_BLOCK(NK7110_MSG_PHONEBOOK, count);
960 }
961
NK7110_ReadPhonebookLL(gn_data * data,struct gn_statemachine * state)962 static gn_error NK7110_ReadPhonebookLL(gn_data *data, struct gn_statemachine *state)
963 {
964 nk7110_driver_instance *drvinst = DRVINSTANCE(state);
965 unsigned char req[2000] = {FBUS_FRAME_HEADER, 0x07, 0x01, 0x01, 0x00, 0x01,
966 0x00, 0x00, /* memory type; was: 0x02, 0x05 */
967 0x00, 0x00, /* location */
968 0x00, 0x00};
969
970 dprintf("Reading phonebook location (%d)\n", drvinst->ll_location);
971
972 req[9] = drvinst->ll_memtype;
973 req[10] = drvinst->ll_location >> 8;
974 req[11] = drvinst->ll_location & 0xff;
975
976 SEND_MESSAGE_BLOCK(NK7110_MSG_PHONEBOOK, 14);
977 }
978
NK7110_ReadPhonebook(gn_data * data,struct gn_statemachine * state)979 static gn_error NK7110_ReadPhonebook(gn_data *data, struct gn_statemachine *state)
980 {
981 nk7110_driver_instance *drvinst = DRVINSTANCE(state);
982
983 drvinst->ll_memtype = get_memory_type(data->phonebook_entry->memory_type);
984 drvinst->ll_location = data->phonebook_entry->location;
985
986 return NK7110_ReadPhonebookLL(data, state);
987 }
988
NK7110_GetSpeedDial(gn_data * data,struct gn_statemachine * state)989 static gn_error NK7110_GetSpeedDial(gn_data *data, struct gn_statemachine *state)
990 {
991 nk7110_driver_instance *drvinst = DRVINSTANCE(state);
992
993 drvinst->ll_memtype = NK7110_MEMORY_SPEEDDIALS;
994 drvinst->ll_location = data->speed_dial->number;
995
996 return NK7110_ReadPhonebookLL(data, state);
997 }
998
999 /*****************************/
1000 /********** FOLDER ***********/
1001 /*****************************/
get_data(gn_sms_message_type t,unsigned int a,unsigned int b,unsigned int c,unsigned int d)1002 static inline unsigned int get_data(gn_sms_message_type t, unsigned int a,
1003 unsigned int b, unsigned int c,
1004 unsigned int d)
1005 {
1006 switch (t) {
1007 case GN_SMS_MT_Deliver: return a;
1008 case GN_SMS_MT_Submit: return b;
1009 case GN_SMS_MT_StatusReport: return c;
1010 case GN_SMS_MT_Picture: return d;
1011 default: return 0;
1012 }
1013 }
1014
1015 /**
1016 * NK7110_IncomingFolder - handle SMS and folder related messages (0x14 type)
1017 * @messagetype: message type, 0x14 (NK7110_MSG_FOLDER)
1018 * @message: a pointer to the raw message returned by the statemachine
1019 * @length: length of the received message
1020 * @data: gn_data structure where the handler saves parsed data
1021 *
1022 * This function parses all incoming events of the 0x14 type. This type is
1023 * known as the answer to the SMS and folder relates requests. Subtypes
1024 * handled by this function contain:
1025 * o GetSMS (0x08, 0x09)
1026 * o DeleteSMS (0x0b, 0x0c)
1027 * o SMSStatus (0x37)
1028 * o FolderStatus (0x6c)
1029 * o FolderList (0x7b)
1030 * o PictureMessagesList (0x97)
1031 * Unknown but reported errors:
1032 * o 0xc9 -- unknown command?
1033 * o 0xca -- phone not ready?
1034 */
NK7110_IncomingFolder(int messagetype,unsigned char * message,int length,gn_data * data,struct gn_statemachine * state)1035 static gn_error NK7110_IncomingFolder(int messagetype, unsigned char *message, int length, gn_data *data, struct gn_statemachine *state)
1036 {
1037 unsigned int i, j, T, offset = 47;
1038 int nextfolder = 0x10;
1039
1040 /* Message subtype */
1041 switch (message[3]) {
1042 /* save sms succeeded */
1043 case 0x05:
1044 dprintf("Message stored in folder %i at location %i\n", message[4], (message[5] << 8) | message[6]);
1045 if (data->raw_sms) data->raw_sms->number = (message[5] << 8) | message[6];
1046 break;
1047 /* save sms failed */
1048 case 0x06:
1049 dprintf("SMS saving failed:\n");
1050 switch (message[4]) {
1051 case 0x02:
1052 dprintf("\tAll locations busy.\n");
1053 return GN_ERR_MEMORYFULL;
1054 case 0x03:
1055 dprintf("\tInvalid location!\n");
1056 return GN_ERR_INVALIDLOCATION;
1057 default:
1058 dprintf("\tUnknown reason.\n");
1059 return GN_ERR_UNHANDLEDFRAME;
1060 }
1061 case NK7110_SUBSMS_READ_OK: /* GetSMS OK, 0x08 */
1062 dprintf("Trying to get message # %i from the folder # %i\n", (message[6] << 8) | message[7], message[5]);
1063 if (!data->raw_sms)
1064 return GN_ERR_INTERNALERROR;
1065
1066 memset(data->raw_sms, 0, sizeof(gn_sms_raw));
1067 T = data->raw_sms->type = message[8];
1068 data->raw_sms->number = (message[6] << 8) | message[7];
1069 data->raw_sms->memory_type = message[5];
1070 data->raw_sms->status = message[4];
1071
1072 data->raw_sms->more_messages = 0;
1073 data->raw_sms->reply_via_same_smsc = message[21];
1074 data->raw_sms->reject_duplicates = 0;
1075 data->raw_sms->report = 0;
1076
1077 data->raw_sms->reference = 0;
1078 data->raw_sms->pid = 0;
1079 data->raw_sms->report_status = 0;
1080
1081 if (T != GN_SMS_MT_Submit) {
1082 memcpy(data->raw_sms->smsc_time, message + get_data(T, 37, 38, 36, 34), 7);
1083 memcpy(data->raw_sms->message_center, message + 9, 12);
1084 memcpy(data->raw_sms->remote_number, message + get_data(T, 25, 26, 24, 22), 12);
1085 }
1086 if (T == GN_SMS_MT_StatusReport)
1087 memcpy(data->raw_sms->time, message + 43, 7);
1088
1089 data->raw_sms->dcs = message[23];
1090 /* This is ugly hack. But the picture message format in 6210
1091 * is the real pain in the ass. */
1092 if (T == GN_SMS_MT_Picture && (message[47] == 0x48) && (message[48] == 0x1c))
1093 /* 47 (User Data offset) + 256 (72 * 28 / 8 + 4) = 303 */
1094 offset = 303;
1095 data->raw_sms->length = message[get_data(T, 24, 25, 0, offset)];
1096 if (T == GN_SMS_MT_Picture)
1097 data->raw_sms->length += 256;
1098 data->raw_sms->udh_indicator = message[get_data(T, 21, 23, 0, 21)];
1099 memcpy(data->raw_sms->user_data, message + get_data(T, 44, 45, 0, 47), data->raw_sms->length);
1100
1101 data->raw_sms->user_data_length = length - get_data(T, 44, 45, 0, 47);
1102
1103 data->raw_sms->validity_indicator = 0;
1104 memset(data->raw_sms->validity, 0, sizeof(data->raw_sms->validity));
1105 break;
1106 case NK7110_SUBSMS_READ_FAIL: /* GetSMS FAIL, 0x09 */
1107 dprintf("SMS reading failed:\n");
1108 switch (message[4]) {
1109 case 0x02:
1110 dprintf("\tInvalid location!\n");
1111 return GN_ERR_INVALIDLOCATION;
1112 case 0x07:
1113 dprintf("\tEmpty SMS location.\n");
1114 return GN_ERR_EMPTYLOCATION;
1115 default:
1116 dprintf("\tUnknown reason.\n");
1117 return GN_ERR_UNHANDLEDFRAME;
1118 }
1119
1120 case NK7110_SUBSMS_DELETE_OK: /* DeleteSMS OK, 0x0b */
1121 dprintf("SMS deleted\n");
1122 break;
1123
1124 case NK7110_SUBSMS_DELETE_FAIL: /* DeleteSMS FAIL, 0x0c */
1125 switch (message[4]) {
1126 case 0x02:
1127 dprintf("Invalid location\n");
1128 return GN_ERR_INVALIDLOCATION;
1129 default:
1130 dprintf("Unknown reason.\n");
1131 return GN_ERR_UNHANDLEDFRAME;
1132 }
1133
1134 case NK7110_SUBSMS_SMS_STATUS_OK: /* SMS status received, 0x37 */
1135 dprintf("SMS Status received\n");
1136 /* FIXME: Don't count messages in fixed locations together with other */
1137 data->sms_status->number = ((message[10] << 8) | message[11]) +
1138 ((message[14] << 8) | message[15]) +
1139 (data->sms_folder->number);
1140 data->sms_status->unread = ((message[12] << 8) | message[13]) +
1141 ((message[16] << 8) | message[17]);
1142 break;
1143
1144 case NK7110_SUBSMS_FOLDER_STATUS_OK: /* Folder status OK, 0x6C */
1145 dprintf("Message: SMS Folder status received\n");
1146 if (!data->sms_folder) return GN_ERR_INTERNALERROR;
1147
1148 data->sms_folder->sms_data = 0;
1149 memset(data->sms_folder->locations, 0, sizeof(data->sms_folder->locations));
1150 data->sms_folder->number = (message[4] << 8) | message[5];
1151
1152 dprintf("Message: Number of Entries: %i\n" , data->sms_folder->number);
1153 dprintf("Message: IDs of Entries : ");
1154 for (i = 0; i < data->sms_folder->number; i++) {
1155 data->sms_folder->locations[i] = (message[(i * 2) + 6] << 8) | message[(i * 2) + 7];
1156 dprintf("%d, ", data->sms_folder->locations[i]);
1157 }
1158 dprintf("\n");
1159 break;
1160
1161 case NK7110_SUBSMS_FOLDER_LIST_OK: /* Folder list OK, 0x7B */
1162 if (!data->sms_folder_list)
1163 return GN_ERR_INTERNALERROR;
1164 i = 5;
1165 memset(data->sms_folder_list, 0, sizeof(gn_sms_folder_list));
1166 dprintf("Message: %d SMS Folders received:\n", message[4]);
1167
1168 snprintf(data->sms_folder_list->folder[1].name,
1169 sizeof(data->sms_folder_list->folder[1].name),
1170 "%s", " ");
1171 data->sms_folder_list->number = message[4];
1172
1173 for (j = 0; j < message[4]; j++) {
1174 int len;
1175 snprintf(data->sms_folder_list->folder[j].name,
1176 sizeof(data->sms_folder_list->folder[j].name),
1177 "%s", " ");
1178 data->sms_folder_list->folder_id[j] = get_gn_memory_type(message[i]);
1179 data->sms_folder_list->folder[j].folder_id = data->sms_folder_list->folder_id[j];
1180 dprintf("Folder Index: %d", data->sms_folder_list->folder_id[j]);
1181 i += 2;
1182 dprintf("\tFolder name: ");
1183 len = 0;
1184 /* search for the next folder's index number, i.e. length of the folder name */
1185 while (i + 1 < length && message[i + 1] != nextfolder) {
1186 i += 2;
1187 len += 2;
1188 }
1189 /* see Docs/protocol/nk7110.txt */
1190 nextfolder += 0x08;
1191 if (nextfolder == 0x28) nextfolder++;
1192 i -= len + 1;
1193 char_unicode_decode(data->sms_folder_list->folder[j].name, message + i, len);
1194 dprintf("%s\n", data->sms_folder_list->folder[j].name);
1195 i += len + 2;
1196 }
1197 break;
1198
1199 case NK7110_SUBSMS_PICTURE_LIST_OK: /* Picture messages list OK, 0x97 */
1200 dprintf("Getting list of SMS pictures...\n");
1201 break;
1202
1203 /* Some errors */
1204 case 0xc9:
1205 dprintf("Unknown command???\n");
1206 return GN_ERR_UNHANDLEDFRAME;
1207
1208 case 0xca:
1209 dprintf("Phone not ready???\n");
1210 return GN_ERR_UNHANDLEDFRAME;
1211
1212 default:
1213 dprintf("Message: Unknown message of type 14 : %02x length: %d\n", message[3], length);
1214 return GN_ERR_UNHANDLEDFRAME;
1215 }
1216 return GN_ERR_NONE;
1217 }
1218
NK7110_GetSMSnoValidate(gn_data * data,struct gn_statemachine * state)1219 static gn_error NK7110_GetSMSnoValidate(gn_data *data, struct gn_statemachine *state)
1220 {
1221 unsigned char req[] = {FBUS_FRAME_HEADER, 0x07,
1222 0x08, /* FolderID */
1223 0x00,
1224 0x01, /* Location */
1225 0x01, 0x65, 0x01};
1226
1227 req[4] = get_memory_type(data->raw_sms->memory_type);
1228 req[5] = (data->raw_sms->number & 0xff00) >> 8;
1229 req[6] = data->raw_sms->number & 0x00ff;
1230 SEND_MESSAGE_BLOCK(NK7110_MSG_FOLDER, 10);
1231 }
1232
ValidateSMS(gn_data * data,struct gn_statemachine * state)1233 static gn_error ValidateSMS(gn_data *data, struct gn_statemachine *state)
1234 {
1235 gn_error error;
1236
1237 if (data->raw_sms->number < 1)
1238 return GN_ERR_INVALIDLOCATION;
1239
1240 /* Handle memory_type = 0 explicitely, because sms_folder->folder_id = 0 by default */
1241 if (data->raw_sms->memory_type == 0) return GN_ERR_INVALIDMEMORYTYPE;
1242
1243 /* see if the message we want is from the last read folder, i.e. */
1244 /* we don't have to get folder status again */
1245 if ((!data->sms_folder) || (!data->sms_folder_list))
1246 return GN_ERR_INTERNALERROR;
1247
1248 if (data->raw_sms->memory_type != data->sms_folder->folder_id) {
1249 if ((error = NK7110_GetSMSFolders(data, state)) != GN_ERR_NONE) return error;
1250 if ((data->raw_sms->memory_type >
1251 data->sms_folder_list->folder_id[data->sms_folder_list->number - 1]) ||
1252 (data->raw_sms->memory_type < 12))
1253 return GN_ERR_INVALIDMEMORYTYPE;
1254 data->sms_folder->folder_id = data->raw_sms->memory_type;
1255 if ((error = NK7110_GetSMSFolderStatus(data, state)) != GN_ERR_NONE) return error;
1256 }
1257
1258 if (data->sms_folder->number + 2 < data->raw_sms->number) {
1259 if (data->raw_sms->number > GN_SMS_MESSAGE_MAX_NUMBER)
1260 return GN_ERR_INVALIDLOCATION;
1261 else
1262 return GN_ERR_EMPTYLOCATION;
1263 } else {
1264 data->raw_sms->number = data->sms_folder->locations[data->raw_sms->number - 1];
1265 }
1266 return GN_ERR_NONE;
1267 }
1268
1269
NK7110_GetSMS(gn_data * data,struct gn_statemachine * state)1270 static gn_error NK7110_GetSMS(gn_data *data, struct gn_statemachine *state)
1271 {
1272 gn_error error;
1273
1274 error = ValidateSMS(data, state);
1275 if (error != GN_ERR_NONE) return error;
1276
1277 return NK7110_GetSMSnoValidate(data, state);
1278 }
1279
1280
NK7110_DeleteSMS(gn_data * data,struct gn_statemachine * state)1281 static gn_error NK7110_DeleteSMS(gn_data *data, struct gn_statemachine *state)
1282 {
1283 unsigned char req[] = {FBUS_FRAME_HEADER, 0x0a, 0x00, 0x00, 0x00, 0x01};
1284 gn_error error;
1285
1286 if (!data->raw_sms) return GN_ERR_INTERNALERROR;
1287 dprintf("Removing SMS %d\n", data->raw_sms->number);
1288
1289 error = ValidateSMS(data, state);
1290 if (error != GN_ERR_NONE) return error;
1291
1292 req[4] = get_memory_type(data->raw_sms->memory_type);
1293 req[5] = (data->raw_sms->number & 0xff00) >> 8;
1294 req[6] = data->raw_sms->number & 0x00ff;
1295 SEND_MESSAGE_BLOCK(NK7110_MSG_FOLDER, 8);
1296 }
1297
NK7110_DeleteSMSnoValidate(gn_data * data,struct gn_statemachine * state)1298 static gn_error NK7110_DeleteSMSnoValidate(gn_data *data, struct gn_statemachine *state)
1299 {
1300 unsigned char req[] = {FBUS_FRAME_HEADER, 0x0a, 0x00, 0x00, 0x00, 0x01};
1301
1302 if (!data->raw_sms) return GN_ERR_INTERNALERROR;
1303 dprintf("Removing SMS (no validate) %d\n", data->raw_sms->number);
1304
1305 req[4] = get_memory_type(data->raw_sms->memory_type);
1306 req[5] = (data->raw_sms->number & 0xff00) >> 8;
1307 req[6] = data->raw_sms->number & 0x00ff;
1308 SEND_MESSAGE_BLOCK(NK7110_MSG_FOLDER, 8);
1309 }
1310
NK7110_GetPictureList(gn_data * data,struct gn_statemachine * state)1311 static gn_error NK7110_GetPictureList(gn_data *data, struct gn_statemachine *state)
1312 {
1313 unsigned char req[] = {FBUS_FRAME_HEADER, 0x96,
1314 0x09, /* location */
1315 0x0f, 0x07};
1316
1317 dprintf("Getting picture messages list...\n");
1318 SEND_MESSAGE_BLOCK(NK7110_MSG_FOLDER, 7);
1319 }
1320
NK7110_GetSMSFolders(gn_data * data,struct gn_statemachine * state)1321 static gn_error NK7110_GetSMSFolders(gn_data *data, struct gn_statemachine *state)
1322 {
1323 unsigned char req[] = {FBUS_FRAME_HEADER, 0x7a, 0x00, 0x00};
1324
1325 dprintf("Getting SMS Folders...\n");
1326 SEND_MESSAGE_BLOCK(NK7110_MSG_FOLDER, 6);
1327 }
1328
NK7110_GetSMSStatus(gn_data * data,struct gn_statemachine * state)1329 static gn_error NK7110_GetSMSStatus(gn_data *data, struct gn_statemachine *state)
1330 {
1331 unsigned char req[] = {FBUS_FRAME_HEADER, 0x36, 0x64};
1332 gn_sms_folder status_fld, *old_fld;
1333 gn_error error;
1334
1335 dprintf("Getting SMS Status...\n");
1336
1337 /* Nokia 6210 and family does not show not "fixed" messages from the
1338 * Templates folder, ie. when you save a message to the Templates folder,
1339 * SMSStatus does not change! Workaround: get Templates folder status, which
1340 * does show these messages.
1341 */
1342
1343 old_fld = data->sms_folder;
1344
1345 data->sms_folder = &status_fld;
1346 data->sms_folder->folder_id = GN_MT_TE;
1347
1348 error = NK7110_GetSMSFolderStatus(data, state);
1349 if (error) goto out;
1350
1351 error = sm_message_send(6, NK7110_MSG_FOLDER, req, state);
1352 if (error) goto out;
1353
1354 error = sm_block(NK7110_MSG_FOLDER, data, state);
1355 out:
1356 data->sms_folder = old_fld;
1357 return error;
1358 }
1359
NK7110_GetSMSFolderStatus(gn_data * data,struct gn_statemachine * state)1360 static gn_error NK7110_GetSMSFolderStatus(gn_data *data, struct gn_statemachine *state)
1361 {
1362 unsigned char req[] = {FBUS_FRAME_HEADER, 0x6B,
1363 0x08, /* Folder ID */
1364 0x0F, 0x01};
1365 gn_error error;
1366 gn_sms_folder read;
1367 int i;
1368
1369 req[4] = get_memory_type(data->sms_folder->folder_id);
1370
1371 dprintf("Getting SMS Folder (%i) status ...\n", req[4]);
1372
1373 if (req[4] == NK7110_MEMORY_IN) { /* special case INBOX */
1374
1375 dprintf("Special case INBOX in GetSMSFolderStatus!\n");
1376
1377 if (sm_message_send(7, NK7110_MSG_FOLDER, req, state)) return GN_ERR_NOTREADY;
1378 error = sm_block(NK7110_MSG_FOLDER, data, state);
1379 if (error) return error;
1380
1381 memcpy(&read, data->sms_folder, sizeof(gn_sms_folder));
1382
1383 req[4] = 0xf8; /* unread messages from INBOX */
1384 if (sm_message_send(7, NK7110_MSG_FOLDER, req, state)) return GN_ERR_NOTREADY;
1385 error = sm_block(NK7110_MSG_FOLDER, data, state);
1386
1387 for (i = 0; i < read.number; i++) {
1388 data->sms_folder->locations[data->sms_folder->number] = read.locations[i];
1389 data->sms_folder->number++;
1390 }
1391 return GN_ERR_NONE;
1392 }
1393
1394 SEND_MESSAGE_BLOCK(NK7110_MSG_FOLDER, 7);
1395 }
1396
NK7110_SaveSMS(gn_data * data,struct gn_statemachine * state)1397 static gn_error NK7110_SaveSMS(gn_data *data, struct gn_statemachine *state)
1398 {
1399 unsigned char req[256] = { FBUS_FRAME_HEADER, 0x04,
1400 0x07, /* sms state */
1401 0x10, /* folder */
1402 0x00,0x00, /* location */
1403 0x00 }; /* type */
1404 int len;
1405
1406 dprintf("Saving sms\n");
1407
1408 switch (data->raw_sms->type) {
1409 case GN_SMS_MT_Submit:
1410 if (data->raw_sms->status == GN_SMS_Sent)
1411 req[4] = 0x05;
1412 else
1413 req[4] = 0x07;
1414 req[8] = 0x02;
1415 break;
1416 case GN_SMS_MT_Deliver:
1417 if (data->raw_sms->status == GN_SMS_Sent)
1418 req[4] = 0x01;
1419 else
1420 req[4] = 0x03;
1421 req[8] = 0x00;
1422 break;
1423 default:
1424 req[4] = 0x07;
1425 req[8] = 0x00;
1426 break;
1427 }
1428
1429 if ((data->raw_sms->memory_type != GN_MT_ME) && (data->raw_sms->memory_type != GN_MT_SM))
1430 req[5] = get_memory_type(data->raw_sms->memory_type);
1431 else
1432 req[5] = NK7110_MEMORY_OU;
1433
1434 req[6] = data->raw_sms->number / 256;
1435 req[7] = data->raw_sms->number % 256;
1436
1437 if (req[5] == NK7110_MEMORY_TE) return GN_ERR_INVALIDLOCATION;
1438
1439 len = pnok_fbus_sms_encode(req + 9, data, state);
1440 len += 9;
1441
1442 SEND_MESSAGE_BLOCK(NK7110_MSG_FOLDER, len);
1443 }
1444
1445
1446
1447 /*****************************/
1448 /*********** S M S *********/
1449 /*****************************/
NK7110_IncomingSMS(int messagetype,unsigned char * message,int length,gn_data * data,struct gn_statemachine * state)1450 static gn_error NK7110_IncomingSMS(int messagetype, unsigned char *message, int length, gn_data *data, struct gn_statemachine *state)
1451 {
1452 gn_error e = GN_ERR_NONE;
1453
1454 if (!data) return GN_ERR_INTERNALERROR;
1455
1456 switch (message[3]) {
1457 case NK7110_SUBSMS_SMSC_RCVD: /* 0x34 */
1458 dprintf("SMSC Received\n");
1459 data->message_center->id = message[4];
1460 data->message_center->format = message[6];
1461 data->message_center->validity = message[8]; /* due to changes in format */
1462
1463 snprintf(data->message_center->name, sizeof(data->message_center->name), "%s", message + 33);
1464 data->message_center->default_name = -1;
1465
1466 if (message[9] % 2) message[9]++;
1467 message[9] = message[9] / 2 + 1;
1468 dprintf("%d\n", message[9]);
1469 snprintf(data->message_center->recipient.number,
1470 sizeof(data->message_center->recipient.number),
1471 "%s", char_bcd_number_get(message + 9));
1472 data->message_center->recipient.type = message[10];
1473 snprintf(data->message_center->smsc.number,
1474 sizeof(data->message_center->smsc.number),
1475 "%s", char_bcd_number_get(message + 21));
1476 data->message_center->smsc.type = message[22];
1477 /* Set a default SMSC name if none was received */
1478 if (!data->message_center->name[0]) {
1479 snprintf(data->message_center->name, sizeof(data->message_center->name), _("Set %d"), data->message_center->id);
1480 data->message_center->default_name = data->message_center->id;
1481 }
1482
1483 break;
1484
1485 case NK7110_SUBSMS_SEND_OK: /* 0x02 */
1486 dprintf("SMS sent\n");
1487 e = GN_ERR_NONE;
1488 break;
1489
1490 case NK7110_SUBSMS_SEND_FAIL: /* 0x03 */
1491 dprintf("SMS sending failed\n");
1492 e = GN_ERR_FAILED;
1493 break;
1494
1495 case 0x0e:
1496 dprintf("Ack for request on Incoming SMS\n");
1497 break;
1498
1499 case 0x11:
1500 dprintf("SMS received\n");
1501 /* We got here the whole SMS */
1502 DRVINSTANCE(state)->new_sms = true;
1503 break;
1504
1505 case NK7110_SUBSMS_SMS_RCVD: /* 0x10 */
1506 case NK7110_SUBSMS_CELLBRD_OK: /* 0x21 */
1507 case NK7110_SUBSMS_CELLBRD_FAIL: /* 0x22 */
1508 case NK7110_SUBSMS_READ_CELLBRD: /* 0x23 */
1509 case NK7110_SUBSMS_SMSC_OK: /* 0x31 */
1510 case NK7110_SUBSMS_SMSC_FAIL: /* 0x32 */
1511 case NK7110_SUBSMS_SMSC_RCVFAIL: /* 0x35 */
1512 dprintf("Subtype 0x%02x of type 0x%02x (SMS handling) not implemented\n", message[3], NK7110_MSG_SMS);
1513 return GN_ERR_NOTIMPLEMENTED;
1514
1515 default:
1516 dprintf("Unknown subtype of type 0x%02x (SMS handling): 0x%02x\n", NK7110_MSG_SMS, message[3]);
1517 return GN_ERR_UNHANDLEDFRAME;
1518 }
1519 return e;
1520 }
1521
NK7110_GetSMSCenter(gn_data * data,struct gn_statemachine * state)1522 static gn_error NK7110_GetSMSCenter(gn_data *data, struct gn_statemachine *state)
1523 {
1524 unsigned char req[] = {FBUS_FRAME_HEADER, NK7110_SUBSMS_GET_SMSC, 0x64, 0x00};
1525
1526 req[5] = data->message_center->id;
1527
1528 SEND_MESSAGE_BLOCK(NK7110_MSG_SMS, 6);
1529 }
1530
1531 #if 0
1532 static gn_error NK7110_PollSMS(gn_data *data, struct gn_statemachine *state)
1533 {
1534 unsigned char req[] = {FBUS_FRAME_HEADER, 0x0d, 0x00, 0x00, 0x02};
1535 dprintf("Requesting for the notify of the incoming SMS\n");
1536 SEND_MESSAGE_BLOCK(NK7110_MSG_SMS, 8);
1537 }
1538 #endif
1539
NK7110_SendSMS(gn_data * data,struct gn_statemachine * state)1540 static gn_error NK7110_SendSMS(gn_data *data, struct gn_statemachine *state)
1541 {
1542 unsigned char req[256] = {FBUS_FRAME_HEADER, 0x01, 0x02, 0x00};
1543 gn_error error;
1544 int len;
1545
1546 len = pnok_fbus_sms_encode(req + 6, data, state);
1547 len += 6;
1548
1549 if (sm_message_send(len, PNOK_MSG_ID_SMS, req, state)) return GN_ERR_NOTREADY;
1550 do {
1551 error = sm_block_no_retry_timeout(PNOK_MSG_ID_SMS, state->config.smsc_timeout, data, state);
1552 } while (!state->config.smsc_timeout && error == GN_ERR_TIMEOUT);
1553
1554 return error;
1555 }
1556
1557 /**********************************/
1558 /************* CLOCK **************/
1559 /**********************************/
NK7110_IncomingClock(int messagetype,unsigned char * message,int length,gn_data * data,struct gn_statemachine * state)1560 static gn_error NK7110_IncomingClock(int messagetype, unsigned char *message, int length, gn_data *data, struct gn_statemachine *state)
1561 {
1562 gn_error e = GN_ERR_NONE;
1563
1564 if (!data) return GN_ERR_INTERNALERROR;
1565 switch (message[3]) {
1566 case NK7110_SUBCLO_DATE_RCVD:
1567 if (!data->datetime) return GN_ERR_INTERNALERROR;
1568 data->datetime->year = (((unsigned int)message[8]) << 8) + message[9];
1569 data->datetime->month = message[10];
1570 data->datetime->day = message[11];
1571 data->datetime->hour = message[12];
1572 data->datetime->minute = message[13];
1573 data->datetime->second = message[14];
1574
1575 break;
1576 case NK7110_SUBCLO_DATE_SET:
1577 break;
1578 case NK7110_SUBCLO_ALARM_RCVD:
1579 if (!data->alarm) return GN_ERR_INTERNALERROR;
1580 switch(message[8]) {
1581 case NK7110_ALARM_ENABLED:
1582 data->alarm->enabled = true;
1583 break;
1584 case NK7110_ALARM_DISABLED:
1585 data->alarm->enabled = false;
1586 break;
1587 default:
1588 data->alarm->enabled = false;
1589 dprintf("Unknown value of alarm enable byte: 0x%02x\n", message[8]);
1590 e = GN_ERR_UNKNOWN;
1591 break;
1592 }
1593
1594 data->alarm->timestamp.hour = message[9];
1595 data->alarm->timestamp.minute = message[10];
1596
1597 break;
1598 case NK7110_SUBCLO_ALARM_SET:
1599 break;
1600 default:
1601 dprintf("Unknown subtype of type 0x%02x (clock handling): 0x%02x\n", NK7110_MSG_CLOCK, message[3]);
1602 e = GN_ERR_UNHANDLEDFRAME;
1603 break;
1604 }
1605 return e;
1606 }
1607
NK7110_GetClock(char req_type,gn_data * data,struct gn_statemachine * state)1608 static gn_error NK7110_GetClock(char req_type, gn_data *data, struct gn_statemachine *state)
1609 {
1610 unsigned char req[] = {FBUS_FRAME_HEADER, req_type};
1611
1612 SEND_MESSAGE_BLOCK(NK7110_MSG_CLOCK, 4);
1613 }
1614
NK7110_SetClock(gn_data * data,struct gn_statemachine * state)1615 static gn_error NK7110_SetClock(gn_data *data, struct gn_statemachine *state)
1616 {
1617 unsigned char req[] = {FBUS_FRAME_HEADER, 0x60, 0x01, 0x01, 0x07,
1618 0x00, 0x00, /* year hi/lo */
1619 0x00, 0x00, /* month, day */
1620 0x00, 0x00, /* hour, minute */
1621 0x00};
1622
1623 if (!data->datetime) return GN_ERR_INTERNALERROR;
1624
1625 req[7] = data->datetime->year >> 8;
1626 req[8] = data->datetime->year & 0xff;
1627 req[9] = data->datetime->month;
1628 req[10] = data->datetime->day;
1629 req[11] = data->datetime->hour;
1630 req[12] = data->datetime->minute;
1631
1632 SEND_MESSAGE_BLOCK(NK7110_MSG_CLOCK, 14);
1633 }
1634
NK7110_SetAlarm(gn_data * data,struct gn_statemachine * state)1635 static gn_error NK7110_SetAlarm(gn_data *data, struct gn_statemachine *state)
1636 {
1637 unsigned char req[] = {FBUS_FRAME_HEADER, 0x6b, 0x01, 0x20, 0x03,
1638 0x02, /* should be alarm on/off */
1639 0x00, 0x00, /* hours, minutes */
1640 0x00};
1641
1642 if (!data->alarm) return GN_ERR_INTERNALERROR;
1643
1644 if (data->alarm->enabled) {
1645 req[7] = NK7110_ALARM_ENABLED;
1646 req[8] = data->alarm->timestamp.hour;
1647 req[9] = data->alarm->timestamp.minute;
1648 } else {
1649 req[7] = NK7110_ALARM_DISABLED;
1650 }
1651
1652 SEND_MESSAGE_BLOCK(NK7110_MSG_CLOCK, 11);
1653 }
1654
1655
1656 /**********************************/
1657 /*********** CALENDAR *************/
1658 /**********************************/
1659
NK7110_IncomingCalendar(int messagetype,unsigned char * message,int length,gn_data * data,struct gn_statemachine * state)1660 static gn_error NK7110_IncomingCalendar(int messagetype, unsigned char *message, int length, gn_data *data, struct gn_statemachine *state)
1661 {
1662 gn_error e = GN_ERR_NONE;
1663 int i;
1664
1665 if (!data || !data->calnote) return GN_ERR_INTERNALERROR;
1666
1667 switch (message[3]) {
1668 case NK7110_SUBCAL_NOTE_RCVD:
1669 calnote_decode(message, length, data);
1670 break;
1671 case NK7110_SUBCAL_INFO_RCVD:
1672 if (!data->calnote_list) return GN_ERR_INTERNALERROR;
1673 dprintf("Calendar Notes Info received! %i\n", message[4] * 256 + message[5]);
1674 data->calnote_list->number = message[4] * 256 + message[5];
1675 dprintf("Location of Notes: ");
1676 for (i = 0; i < data->calnote_list->number; i++) {
1677 if (8 + 2 * i >= length) break;
1678 data->calnote_list->location[data->calnote_list->last+i] = message[8 + 2 * i] * 256 + message[9 + 2 * i];
1679 dprintf("%i ", data->calnote_list->location[data->calnote_list->last+i]);
1680 }
1681 data->calnote_list->last += i;
1682 dprintf("\n");
1683 break;
1684 case NK7110_SUBCAL_FREEPOS_RCVD:
1685 dprintf("First free position received: %i!\n", message[4] * 256 + message[5]);
1686 data->calnote->location = (((unsigned int)message[4]) << 8) + message[5];
1687 break;
1688 case NK7110_SUBCAL_DEL_NOTE_RESP:
1689 dprintf("Succesfully deleted calendar note: %i!\n", message[4] * 256 + message[5]);
1690 for (i = 0; i < length; i++) dprintf("%02x ", message[i]);
1691 dprintf("\n");
1692 break;
1693
1694 case NK7110_SUBCAL_ADD_MEETING_RESP:
1695 case NK7110_SUBCAL_ADD_CALL_RESP:
1696 case NK7110_SUBCAL_ADD_BIRTHDAY_RESP:
1697 case NK7110_SUBCAL_ADD_REMINDER_RESP:
1698 if (message[6]) e = GN_ERR_FAILED;
1699 dprintf("Attempt to write calendar note at %i. Status: %i\n",
1700 (message[4] << 8) | message[5],
1701 1 - message[6]);
1702 break;
1703 default:
1704 dprintf("Unknown subtype of type 0x%02x (calendar handling): 0x%02x\n", NK7110_MSG_CALENDAR, message[3]);
1705 e = GN_ERR_UNHANDLEDFRAME;
1706 break;
1707 }
1708 return e;
1709 }
1710
NK7110_GetNoteAlarmDiff(gn_timestamp * time,gn_timestamp * alarm)1711 long NK7110_GetNoteAlarmDiff(gn_timestamp *time, gn_timestamp *alarm)
1712 {
1713 time_t t_alarm;
1714 time_t t_time;
1715 struct tm tm_alarm;
1716 struct tm tm_time;
1717
1718 tzset();
1719
1720 tm_alarm.tm_year = alarm->year-1900;
1721 tm_alarm.tm_mon = alarm->month-1;
1722 tm_alarm.tm_mday = alarm->day;
1723 tm_alarm.tm_hour = alarm->hour;
1724 tm_alarm.tm_min = alarm->minute;
1725 tm_alarm.tm_sec = alarm->second;
1726 tm_alarm.tm_isdst = 0;
1727 t_alarm = mktime(&tm_alarm);
1728
1729 tm_time.tm_year = time->year-1900;
1730 tm_time.tm_mon = time->month-1;
1731 tm_time.tm_mday = time->day;
1732 tm_time.tm_hour = time->hour;
1733 tm_time.tm_min = time->minute;
1734 tm_time.tm_sec = time->second;
1735 tm_time.tm_isdst = 0;
1736 t_time = mktime(&tm_time);
1737
1738 dprintf("\tAlarm: %02i-%02i-%04i %02i:%02i:%02i\n",
1739 alarm->day, alarm->month, alarm->year,
1740 alarm->hour, alarm->minute, alarm->second);
1741 dprintf("\tDate: %02i-%02i-%04i %02i:%02i:%02i\n",
1742 time->day, time->month, time->year,
1743 time->hour, time->minute, time->second);
1744 dprintf("Difference in alarm time is %f\n", difftime(t_time, t_alarm) + 3600);
1745
1746 return difftime(t_time, t_alarm) + 3600;
1747 }
1748
NK7110_FirstCalendarFreePos(gn_data * data,struct gn_statemachine * state)1749 static gn_error NK7110_FirstCalendarFreePos(gn_data *data, struct gn_statemachine *state)
1750 {
1751 unsigned char req[] = { FBUS_FRAME_HEADER, 0x31 };
1752
1753 SEND_MESSAGE_BLOCK(NK7110_MSG_CALENDAR, 4);
1754 }
1755
1756
NK7110_WriteCalendarNote(gn_data * data,struct gn_statemachine * state)1757 static gn_error NK7110_WriteCalendarNote(gn_data *data, struct gn_statemachine *state)
1758 {
1759 unsigned char req[512] = { FBUS_FRAME_HEADER,
1760 0x01, /* note type ... */
1761 0x00, 0x00, /* location */
1762 0x00, /* entry type */
1763 0x00, /* fixed */
1764 0x00, 0x00, 0x00, 0x00, /* year(2bytes), month, day */
1765 /* here starts block */
1766 0x00, 0x00, 0x00, 0x00,0x00, 0x00}; /* ... depends on note type ... */
1767
1768 gn_calnote *calnote;
1769 int count = 0;
1770 long seconds, minutes;
1771 int len = 0;
1772 gn_error error;
1773
1774 if (!data->calnote) return GN_ERR_INTERNALERROR;
1775 calnote = data->calnote;
1776
1777 /* 6210/7110 needs to seek the first free pos to inhabit with next note */
1778 error = NK7110_FirstCalendarFreePos(data, state);
1779 if (error != GN_ERR_NONE) return error;
1780
1781 /* Location */
1782 req[4] = calnote->location >> 8;
1783 req[5] = calnote->location & 0xff;
1784
1785 dprintf("Location: %d\n", calnote->location);
1786
1787 switch (calnote->type) {
1788 case GN_CALNOTE_MEETING:
1789 dprintf("Type: meeting\n");
1790 req[6] = 0x01;
1791 req[3] = 0x01;
1792 break;
1793 case GN_CALNOTE_CALL:
1794 dprintf("Type: call\n");
1795 req[6] = 0x02;
1796 req[3] = 0x03;
1797 break;
1798 case GN_CALNOTE_BIRTHDAY:
1799 dprintf("Type: birthday\n");
1800 req[6] = 0x04;
1801 req[3] = 0x05;
1802 break;
1803 case GN_CALNOTE_REMINDER:
1804 dprintf("Type: reminder\n");
1805 req[6] = 0x08;
1806 req[3] = 0x07;
1807 break;
1808 default:
1809 return GN_ERR_NOTIMPLEMENTED;
1810 }
1811
1812 req[8] = calnote->time.year >> 8;
1813 req[9] = calnote->time.year & 0xff;
1814 req[10] = calnote->time.month;
1815 req[11] = calnote->time.day;
1816
1817 /* From here starts BLOCK */
1818 count = 12;
1819 switch (calnote->type) {
1820
1821 case GN_CALNOTE_MEETING:
1822 req[count++] = calnote->time.hour; /* Field 12 */
1823 req[count++] = calnote->time.minute; /* Field 13 */
1824 /* Alarm .. */
1825 req[count++] = 0xff; /* Field 14 */
1826 req[count++] = 0xff; /* Field 15 */
1827 if (calnote->alarm.timestamp.year) {
1828 seconds = NK7110_GetNoteAlarmDiff(&calnote->time,
1829 &calnote->alarm.timestamp);
1830 if (seconds >= 0L) { /* Otherwise it's an error condition.... */
1831 minutes = seconds / 60L;
1832 count -= 2;
1833 req[count++] = minutes >> 8;
1834 req[count++] = minutes & 0xff;
1835 }
1836 }
1837 /* Recurrence */
1838 if (calnote->recurrence >= 8760)
1839 calnote->recurrence = 0xffff; /* setting 1 year repeat */
1840 req[count++] = calnote->recurrence >> 8; /* Field 16 */
1841 req[count++] = calnote->recurrence & 0xff; /* Field 17 */
1842 /* len of the text */
1843 req[count++] = strlen(calnote->text); /* Field 18 */
1844 /* fixed 0x00 */
1845 req[count++] = 0x00; /* Field 19 */
1846
1847 /* Text */
1848 dprintf("Count before encode = %d\n", count);
1849 dprintf("Meeting Text is = \"%s\"\n", calnote->text);
1850
1851 len = char_unicode_encode(req + count, calnote->text, strlen(calnote->text)); /* Fields 20->N */
1852 count += len;
1853 break;
1854
1855 case GN_CALNOTE_CALL:
1856 req[count++] = calnote->time.hour; /* Field 12 */
1857 req[count++] = calnote->time.minute; /* Field 13 */
1858 /* Alarm .. */
1859 req[count++] = 0xff; /* Field 14 */
1860 req[count++] = 0xff; /* Field 15 */
1861 if (calnote->alarm.timestamp.year) {
1862 seconds = NK7110_GetNoteAlarmDiff(&calnote->time,
1863 &calnote->alarm.timestamp);
1864 if (seconds >= 0L) { /* Otherwise it's an error condition.... */
1865 minutes = seconds / 60L;
1866 count -= 2;
1867 req[count++] = minutes >> 8;
1868 req[count++] = minutes & 0xff;
1869 }
1870 }
1871 /* Recurrence */
1872 if (calnote->recurrence >= 8760)
1873 calnote->recurrence = 0xffff; /* setting 1 year repeat */
1874 req[count++] = calnote->recurrence >> 8; /* Field 16 */
1875 req[count++] = calnote->recurrence & 0xff; /* Field 17 */
1876 /* len of text */
1877 req[count++] = strlen(calnote->text); /* Field 18 */
1878 /* fixed 0x00 */
1879 req[count++] = strlen(calnote->phone_number); /* Field 19 */
1880 /* Text */
1881 len = char_unicode_encode(req + count, calnote->text, strlen(calnote->text)); /* Fields 20->N */
1882 count += len;
1883 len = char_unicode_encode(req + count, calnote->phone_number, strlen(calnote->phone_number)); /* Fields (N+1)->n */
1884 count += len;
1885 break;
1886
1887 case GN_CALNOTE_BIRTHDAY:
1888 req[count++] = 0x00; /* Field 12 Fixed */
1889 req[count++] = 0x00; /* Field 13 Fixed */
1890
1891 /* Alarm .. */
1892 req[count++] = 0x00;
1893 req[count++] = 0x00; /* Fields 14, 15 */
1894 req[count++] = 0xff; /* Field 16 */
1895 req[count++] = 0xff; /* Field 17 */
1896 if (calnote->alarm.timestamp.year) {
1897 /* First I try time.year = alarm.year. If negative, I increase year by one,
1898 but only once! This is because I may have alarm period across
1899 the year border, eg. birthday on 2001-01-10 and alarm on 2000-12-27 */
1900 calnote->time.year = calnote->alarm.timestamp.year;
1901 if ((seconds= NK7110_GetNoteAlarmDiff(&calnote->time,
1902 &calnote->alarm.timestamp)) < 0L) {
1903 calnote->time.year++;
1904 seconds = NK7110_GetNoteAlarmDiff(&calnote->time,
1905 &calnote->alarm.timestamp);
1906 }
1907 if (seconds >= 0L) { /* Otherwise it's an error condition.... */
1908 count -= 4;
1909 req[count++] = seconds >> 24; /* Field 14 */
1910 req[count++] = (seconds >> 16) & 0xff; /* Field 15 */
1911 req[count++] = (seconds >> 8) & 0xff; /* Field 16 */
1912 req[count++] = seconds & 0xff; /* Field 17 */
1913 }
1914 }
1915
1916 req[count++] = 0x00; /* FIXME: calnote->AlarmType; 0x00 tone, 0x01 silent 18 */
1917
1918 /* len of text */
1919 req[count++] = strlen(calnote->text); /* Field 19 */
1920
1921 /* Text */
1922 dprintf("Count before encode = %d\n", count);
1923
1924 len = char_unicode_encode(req + count, calnote->text, strlen(calnote->text)); /* Fields 22->N */
1925 count += len;
1926 break;
1927
1928 case GN_CALNOTE_REMINDER:
1929 /* Recurrence */
1930 if (calnote->recurrence >= 8760)
1931 calnote->recurrence = 0xffff; /* setting 1 year repeat */
1932 req[count++] = calnote->recurrence >> 8; /* Field 12 */
1933 req[count++] = calnote->recurrence & 0xff; /* Field 13 */
1934 /* len of text */
1935 req[count++] = strlen(calnote->text); /* Field 14 */
1936 /* fixed 0x00 */
1937 req[count++] = 0x00; /* Field 15 */
1938 dprintf("Count before encode = %d\n", count);
1939 dprintf("Reminder Text is = \"%s\"\n", calnote->text);
1940 /* Text */
1941 len = char_unicode_encode(req + count, calnote->text, strlen(calnote->text)); /* Fields 16->N */
1942 count += len;
1943 break;
1944
1945 default:
1946 return GN_ERR_NOTIMPLEMENTED;
1947 }
1948
1949 /* padding */
1950 req[count] = 0x00;
1951
1952 dprintf("Count after padding = %d\n", count);
1953
1954 SEND_MESSAGE_BLOCK(NK7110_MSG_CALENDAR, count);
1955 }
1956
1957 #define LAST_INDEX (data->calnote_list->last > 0 ? data->calnote_list->last - 1 : 0)
NK7110_GetCalendarNotesInfo(gn_data * data,struct gn_statemachine * state)1958 static gn_error NK7110_GetCalendarNotesInfo(gn_data *data, struct gn_statemachine *state)
1959 {
1960 unsigned char req[] = {FBUS_FRAME_HEADER, NK7110_SUBCAL_GET_INFO, 0xff, 0xfe};
1961 gn_error error;
1962
1963 /* Some magic: we need to set req[4-5] to {0xff, 0xfe} with the first loop */
1964 data->calnote_list->location[0] = 0xff * 256 + 0xfe;
1965 /* Be sure it is 0 */
1966 data->calnote_list->last = 0;
1967 do {
1968 dprintf("Read %d of %d calendar entries\n", data->calnote_list->last, data->calnote_list->number);
1969 req[4] = data->calnote_list->location[LAST_INDEX] / 256;
1970 req[5] = data->calnote_list->location[LAST_INDEX] % 256;
1971 if (sm_message_send(6, NK7110_MSG_CALENDAR, req, state)) return GN_ERR_NOTREADY;
1972 error = sm_block(NK7110_MSG_CALENDAR, data, state);
1973 if (error != GN_ERR_NONE) return error;
1974 } while (data->calnote_list->last < data->calnote_list->number);
1975 return error;
1976 }
1977 #undef LAST_INDEX
1978
NK7110_GetCalendarNote(gn_data * data,struct gn_statemachine * state)1979 static gn_error NK7110_GetCalendarNote(gn_data *data, struct gn_statemachine *state)
1980 {
1981 gn_error error = GN_ERR_NOTREADY;
1982 unsigned char req[] = {FBUS_FRAME_HEADER, NK7110_SUBCAL_GET_NOTE, 0x00, 0x00};
1983 unsigned char date[] = {FBUS_FRAME_HEADER, NK7110_SUBCLO_GET_DATE};
1984 gn_data tmpdata;
1985 gn_timestamp tmptime;
1986 gn_calnote_list list;
1987
1988 dprintf("Getting calendar note...\n");
1989 if (data->calnote->location < 1) {
1990 error = GN_ERR_INVALIDLOCATION;
1991 } else {
1992 data->calnote_list = &list;
1993 tmpdata.datetime = &tmptime;
1994 error = NK7110_GetCalendarNotesInfo(data, state);
1995 if (error == GN_ERR_NONE) {
1996 if (!data->calnote_list->number ||
1997 data->calnote->location > data->calnote_list->number) {
1998 error = GN_ERR_EMPTYLOCATION;
1999 } else {
2000 error = sm_message_send(4, NK7110_MSG_CLOCK, date, state);
2001 if (error == GN_ERR_NONE) {
2002 sm_block(NK7110_MSG_CLOCK, &tmpdata, state);
2003 req[4] = data->calnote_list->location[data->calnote->location - 1] >> 8;
2004 req[5] = data->calnote_list->location[data->calnote->location - 1] & 0xff;
2005 data->calnote->time.year = tmptime.year;
2006
2007 error = sm_message_send(6, NK7110_MSG_CALENDAR, req, state);
2008 if (error == GN_ERR_NONE) {
2009 error = sm_block(NK7110_MSG_CALENDAR, data, state);
2010 }
2011 }
2012 }
2013 }
2014 }
2015 return error;
2016 }
2017
NK7110_DeleteCalendarNote(gn_data * data,struct gn_statemachine * state)2018 static gn_error NK7110_DeleteCalendarNote(gn_data *data, struct gn_statemachine *state)
2019 {
2020 unsigned char req[] = { FBUS_FRAME_HEADER,
2021 0x0b, /* delete calendar note */
2022 0x00, 0x00}; /*location */
2023 gn_calnote_list list;
2024 bool own_list = true;
2025
2026 if (data->calnote_list)
2027 own_list = false;
2028 else {
2029 memset(&list, 0, sizeof(gn_calnote_list));
2030 data->calnote_list = &list;
2031 }
2032
2033 if (data->calnote_list->number == 0)
2034 NK7110_GetCalendarNotesInfo(data, state);
2035
2036 if (data->calnote->location < data->calnote_list->number + 1 &&
2037 data->calnote->location > 0) {
2038 req[4] = data->calnote_list->location[data->calnote->location - 1] >> 8;
2039 req[5] = data->calnote_list->location[data->calnote->location - 1] & 0xff;
2040 } else {
2041 return GN_ERR_INVALIDLOCATION;
2042 }
2043
2044 if (own_list) data->calnote_list = NULL;
2045 SEND_MESSAGE_BLOCK(NK7110_MSG_CALENDAR, 6);
2046 }
2047
2048 #if 0
2049 static gn_error NK7110_DialVoice(char *Number)
2050 {
2051 /* Doesn't work (yet) */ /* 3 2 1 5 2 30 35 */
2052
2053 unsigned char req0[100] = { 0x00, 0x01, 0x64, 0x01 };
2054
2055 unsigned char req[] = {FBUS_FRAME_HEADER, 0x01, 0x01, 0x01, 0x01, 0x05, 0x00, 0x01, 0x03, 0x02, 0x91, 0x00, 0x031, 0x32, 0x00};
2056 /* unsigned char req[100]={0x00, 0x01, 0x7c, 0x01, 0x31, 0x37, 0x30, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01};
2057 unsigned char req[100] = {FBUS_FRAME_HEADER, 0x01, 0x00, 0x20, 0x01, 0x46};
2058 unsigned char req_end[] = {0x05, 0x01, 0x01, 0x05, 0x81, 0x01, 0x00, 0x00, 0x01}; */
2059 int len = 0;
2060
2061 req[4] = strlen(Number);
2062 for(i = 0; i < strlen(Number); i++)
2063 req[5+i] = Number[i];
2064 memcpy(req + 5 + strlen(Number), req_end, 10);
2065 len = 6 + strlen(Number);
2066 len = 4;
2067 PGEN_CommandResponse(&link, req0, &len, 0x40, 0x40, 100);
2068 len = 17;
2069 if (PGEN_CommandResponse(&link, req, &len, 0x01, 0x01, 100) == GN_ERR_NONE)
2070 return GN_ERR_NONE;
2071 else
2072 return GN_ERR_NOTIMPLEMENTED;
2073 while(1) link.Loop(NULL);
2074
2075 return GN_ERR_NOTIMPLEMENTED;
2076 }
2077 #endif
2078
2079
2080 /*****************************/
2081 /********* STARTUP ***********/
2082 /*****************************/
NK7110_IncomingStartup(int messagetype,unsigned char * message,int length,gn_data * data,struct gn_statemachine * state)2083 static gn_error NK7110_IncomingStartup(int messagetype, unsigned char *message, int length, gn_data *data, struct gn_statemachine *state)
2084 {
2085 /*
2086 01 13 00 ed 1c 00 39 35 32 37 32 00
2087 01 13 00 ed 15 00 00 00 00 04 c0 02 00 3c c0 03
2088 */
2089 switch (message[4]) {
2090 case 0x02:
2091 dprintf("Startup logo set ok\n");
2092 return GN_ERR_NONE;
2093 break;
2094 case 0x15:
2095 if (data->bitmap) {
2096 /* I'm sure there are blocks here but never mind! */
2097 data->bitmap->type = GN_BMP_StartupLogo;
2098 data->bitmap->height = message[13];
2099 data->bitmap->width = message[17];
2100 data->bitmap->size = ((data->bitmap->height / 8) + (data->bitmap->height % 8 > 0)) * data->bitmap->width; /* Can't see this coded anywhere */
2101 memcpy(data->bitmap->bitmap, message + 22, data->bitmap->size);
2102 dprintf("Startup logo got ok - height(%d) width(%d)\n", data->bitmap->height, data->bitmap->width);
2103 }
2104 return GN_ERR_NONE;
2105 break;
2106 case 0x1c:
2107 dprintf("Succesfully got security code: ");
2108 memcpy(data->security_code->code, message + 6, 5);
2109 dprintf("%s \n", data->security_code->code);
2110 return GN_ERR_NONE;
2111 break;
2112 default:
2113 dprintf("Unknown subtype of type 0x7a (%d)\n", message[3]);
2114 return GN_ERR_UNHANDLEDFRAME;
2115 break;
2116 }
2117 }
2118
GetStartupBitmap(gn_data * data,struct gn_statemachine * state)2119 static gn_error GetStartupBitmap(gn_data *data, struct gn_statemachine *state)
2120 {
2121 unsigned char req[] = {FBUS_FRAME_HEADER, 0xee, 0x15};
2122
2123 dprintf("Getting startup logo...\n");
2124 SEND_MESSAGE_BLOCK(NK7110_MSG_STLOGO, 5);
2125 }
2126
NK7110_GetSecurityCode(gn_data * data,struct gn_statemachine * state)2127 static gn_error NK7110_GetSecurityCode(gn_data *data, struct gn_statemachine *state)
2128 {
2129 unsigned char req[] = {FBUS_FRAME_HEADER,
2130 0xEE,
2131 0x1c}; /* SecurityCode */
2132
2133 SEND_MESSAGE_BLOCK(NK7110_MSG_STLOGO, 5);
2134 }
2135
SetStartupBitmap(gn_data * data,struct gn_statemachine * state)2136 static gn_error SetStartupBitmap(gn_data *data, struct gn_statemachine *state)
2137 {
2138 unsigned char req[1000] = {FBUS_FRAME_HEADER, 0xec, 0x15, 0x00, 0x00, 0x00, 0x04, 0xc0, 0x02, 0x00,
2139 0x00, /* Height */
2140 0xc0, 0x03, 0x00,
2141 0x00, /* Width */
2142 0xc0, 0x04, 0x03, 0x00 };
2143 int count = 21;
2144
2145 if ((data->bitmap->width != state->driver.phone.startup_logo_width) ||
2146 (data->bitmap->height != state->driver.phone.startup_logo_height)) {
2147
2148 dprintf("Invalid image size - expecting (%dx%d) got (%dx%d)\n", state->driver.phone.startup_logo_height, state->driver.phone.startup_logo_width, data->bitmap->height, data->bitmap->width);
2149 return GN_ERR_INVALIDSIZE;
2150 }
2151
2152 req[12] = data->bitmap->height;
2153 req[16] = data->bitmap->width;
2154 memcpy(req + count, data->bitmap->bitmap, data->bitmap->size);
2155 count += data->bitmap->size;
2156 dprintf("Setting startup logo...\n");
2157
2158 SEND_MESSAGE_BLOCK(NK7110_MSG_STLOGO, count);
2159 }
2160
2161 /*****************************/
2162 /********* SECURITY **********/
2163 /*****************************/
NK7110_IncomingSecurity(int messagetype,unsigned char * message,int length,gn_data * data,struct gn_statemachine * state)2164 static gn_error NK7110_IncomingSecurity(int messagetype, unsigned char *message, int length, gn_data *data, struct gn_statemachine *state)
2165 {
2166 switch(message[2]) {
2167 default:
2168 dprintf("Unknown security command\n");
2169 return pnok_security_incoming(messagetype, message, length, data, state);
2170 }
2171 return GN_ERR_NONE;
2172 }
2173
2174 /*****************/
2175 /****** WAP ******/
2176 /*****************/
NK7110_IncomingWAP(int messagetype,unsigned char * message,int length,gn_data * data,struct gn_statemachine * state)2177 static gn_error NK7110_IncomingWAP(int messagetype, unsigned char *message, int length, gn_data *data, struct gn_statemachine *state)
2178 {
2179 int string_length, pos;
2180
2181 switch (message[3]) {
2182 case 0x02:
2183 case 0x05:
2184 case 0x08:
2185 case 0x0b:
2186 case 0x0e:
2187 case 0x11:
2188 case 0x14:
2189 case 0x17:
2190 case 0x1a:
2191 case 0x20:
2192 switch (message[4]) {
2193 case 0x00:
2194 dprintf("WAP not activated?\n");
2195 return GN_ERR_UNKNOWN;
2196 case 0x01:
2197 dprintf("Security error. Inside WAP bookmarks menu\n");
2198 return GN_ERR_UNKNOWN;
2199 case 0x02:
2200 dprintf("Invalid or empty\n");
2201 return GN_ERR_INVALIDLOCATION;
2202 default:
2203 dprintf("ERROR: unknown %i\n",message[4]);
2204 return GN_ERR_UNHANDLEDFRAME;
2205 }
2206 break;
2207 case 0x01:
2208 case 0x04:
2209 case 0x10:
2210 break;
2211 case 0x07:
2212 if (!data->wap_bookmark) return GN_ERR_INTERNALERROR;
2213 dprintf("WAP bookmark received\n");
2214 string_length = message[6] << 1;
2215
2216 char_unicode_decode(data->wap_bookmark->name, message + 7, string_length);
2217 dprintf("Name: %s\n", data->wap_bookmark->name);
2218 pos = string_length + 7;
2219
2220 string_length = message[pos++] << 1;
2221 char_unicode_decode(data->wap_bookmark->URL, message + pos, string_length);
2222 dprintf("URL: %s\n", data->wap_bookmark->URL);
2223 break;
2224 case 0x0a:
2225 dprintf("WAP bookmark successfully set!\n");
2226 data->wap_bookmark->location = message[5];
2227 break;
2228 case 0x0d:
2229 dprintf("WAP bookmark successfully deleted!\n");
2230 break;
2231 case 0x13:
2232 dprintf("WAP setting successfully activated!\n");
2233 break;
2234 case 0x16:
2235 if (!data->wap_setting) return GN_ERR_INTERNALERROR;
2236 dprintf("WAP setting received\n");
2237 /* If ReadBeforeWrite is set we only want the successors */
2238
2239 string_length = message[4] << 1;
2240 if (!data->wap_setting->read_before_write)
2241 char_unicode_decode(data->wap_setting->name, message + 5, string_length);
2242 dprintf("Name: %s\n", data->wap_setting->name);
2243 pos = string_length + 5;
2244
2245 string_length = message[pos++] << 1;
2246 if (!data->wap_setting->read_before_write)
2247 char_unicode_decode(data->wap_setting->home, message + pos, string_length);
2248 dprintf("Home: %s\n", data->wap_setting->home);
2249 pos += string_length;
2250
2251 if (!data->wap_setting->read_before_write) {
2252 data->wap_setting->session = message[pos++];
2253 switch (message[pos]) {
2254 case 0x06:
2255 data->wap_setting->bearer = GN_WAP_BEARER_GSMDATA;
2256 break;
2257 case 0x07:
2258 data->wap_setting->bearer = GN_WAP_BEARER_SMS;
2259 break;
2260 default:
2261 data->wap_setting->bearer = GN_WAP_BEARER_USSD;
2262 break;
2263 }
2264 if (message[pos + 12] == 0x01)
2265 data->wap_setting->security = true;
2266 else
2267 data->wap_setting->security = false;
2268 } else
2269 pos ++;
2270
2271 data->wap_setting->successors[0] = message[pos + 2];
2272 data->wap_setting->successors[1] = message[pos + 3];
2273 data->wap_setting->successors[2] = message[pos + 8];
2274 data->wap_setting->successors[3] = message[pos + 9];
2275 break;
2276 case 0x1c:
2277 switch (message[5]) {
2278 case 0x00:
2279 dprintf("SMS:\n");
2280 pos = 6;
2281 string_length = message[pos++] << 1;
2282 char_unicode_decode(data->wap_setting->sms_service_number, message + pos, string_length);
2283 dprintf(" Service number: %s\n", data->wap_setting->sms_service_number);
2284 pos += string_length;
2285
2286 string_length = message[pos++] << 1;
2287 char_unicode_decode(data->wap_setting->sms_server_number, message + pos, string_length);
2288 dprintf(" Server number: %s\n", data->wap_setting->sms_server_number);
2289 pos += string_length;
2290 break;
2291 case 0x01:
2292 dprintf("GSM data:\n");
2293 pos = 6;
2294 data->wap_setting->gsm_data_authentication = message[pos++];
2295 data->wap_setting->call_type = message[pos++];
2296 data->wap_setting->call_speed = message[pos++];
2297 pos++;
2298
2299 string_length = message[pos++] << 1;
2300 char_unicode_decode(data->wap_setting->gsm_data_ip, message + pos, string_length);
2301 dprintf(" IP: %s\n", data->wap_setting->gsm_data_ip);
2302 pos += string_length;
2303
2304 string_length = message[pos++] << 1;
2305 char_unicode_decode(data->wap_setting->number, message + pos, string_length);
2306 dprintf(" Number: %s\n", data->wap_setting->number);
2307 pos += string_length;
2308
2309 string_length = message[pos++] << 1;
2310 char_unicode_decode(data->wap_setting->gsm_data_username, message + pos, string_length);
2311 dprintf(" Username: %s\n", data->wap_setting->gsm_data_username);
2312 pos += string_length;
2313
2314 string_length = message[pos++] << 1;
2315 char_unicode_decode(data->wap_setting->gsm_data_password, message + pos, string_length);
2316 dprintf(" Password: %s\n", data->wap_setting->gsm_data_password);
2317 pos += string_length;
2318 break;
2319 default:
2320 break;
2321 }
2322 break;
2323 case 0x1f:
2324 case 0x19:
2325 dprintf("WAP setting successfully written!\n");
2326 break;
2327 default:
2328 dprintf("Unknown subtype of type 0x3f (%d)\n", message[3]);
2329 return GN_ERR_UNHANDLEDFRAME;
2330 break;
2331 }
2332 return GN_ERR_NONE;
2333 }
2334
SendWAPFrame(gn_data * data,struct gn_statemachine * state,int frame)2335 static gn_error SendWAPFrame(gn_data *data, struct gn_statemachine *state, int frame)
2336 {
2337 unsigned char req[] = { FBUS_FRAME_HEADER, 0x00 };
2338
2339 dprintf("Sending WAP frame\n");
2340 req[3] = frame;
2341 SEND_MESSAGE_BLOCK(NK7110_MSG_WAP, 4);
2342 }
2343
PrepareWAP(gn_data * data,struct gn_statemachine * state)2344 static gn_error PrepareWAP(gn_data *data, struct gn_statemachine *state)
2345 {
2346 dprintf("Preparing WAP\n");
2347 return SendWAPFrame(data, state, 0x00);
2348 }
2349
FinishWAP(gn_data * data,struct gn_statemachine * state)2350 static gn_error FinishWAP(gn_data *data, struct gn_statemachine *state)
2351 {
2352 gn_error error;
2353
2354 dprintf("Finishing WAP\n");
2355
2356 error = SendWAPFrame(data, state, 0x03);
2357 if (error != GN_ERR_NONE) return error;
2358
2359 error = SendWAPFrame(data, state, 0x00);
2360 if (error != GN_ERR_NONE) return error;
2361
2362 error = SendWAPFrame(data, state, 0x0f);
2363 if (error != GN_ERR_NONE) return error;
2364
2365 return SendWAPFrame(data, state, 0x03);
2366 }
2367
PackWAPString(unsigned char * dest,unsigned char * string,int length_size)2368 static int PackWAPString(unsigned char *dest, unsigned char *string, int length_size)
2369 {
2370 int length;
2371
2372 length = strlen(string);
2373 if (length_size == 2) {
2374 dest[0] = length / 256;
2375 dest[1] = length % 256;
2376 } else {
2377 dest[0] = length % 256;
2378 }
2379
2380 length = char_unicode_encode(dest + length_size, string, length);
2381 return length + length_size;
2382 }
2383
NK7110_WriteWAPSetting(gn_data * data,struct gn_statemachine * state)2384 static gn_error NK7110_WriteWAPSetting(gn_data *data, struct gn_statemachine *state)
2385 {
2386 unsigned char req[200] = { FBUS_FRAME_HEADER, 0x18,
2387 0x00 }; /* Location */
2388 unsigned char req1[200] = { FBUS_FRAME_HEADER, 0x1e,
2389 0x00 }; /* Location */
2390 unsigned char req2[] = { FBUS_FRAME_HEADER, 0x15,
2391 0x00 }; /* Location */
2392
2393 gn_error error;
2394 int i = 0, pos = 5;
2395
2396 dprintf("Writing WAP setting\n");
2397 memset(req + pos, 0, 200 - pos);
2398 req[4] = data->wap_setting->location;
2399
2400 if (PrepareWAP(data, state) != GN_ERR_NONE) {
2401 SendWAPFrame(data, state, 0x03);
2402 if ((error = PrepareWAP(data, state))) return error;
2403 }
2404
2405 /* First we need to get WAP setting from the location we want to write to
2406 because we need wap_setting->successors */
2407 req2[4] = data->wap_setting->location;
2408 data->wap_setting->read_before_write = true;
2409 if (sm_message_send(5, NK7110_MSG_WAP, req2, state)) return GN_ERR_NOTREADY;
2410 error = sm_block(NK7110_MSG_WAP, data, state);
2411 if (error != GN_ERR_NONE) return error;
2412
2413 /* Name */
2414 pos += PackWAPString(req + pos, data->wap_setting->name, 1);
2415 /* Home */
2416 pos += PackWAPString(req + pos, data->wap_setting->home, 1);
2417
2418 req[pos++] = data->wap_setting->session;
2419 req[pos++] = data->wap_setting->bearer;
2420
2421 req[pos++] = 0x0a;
2422 if (data->wap_setting->security) req[pos] = 0x01;
2423 pos++;
2424 memcpy(req + pos, "\x00\x80\x00\x00\x00\x00\x00\x00\x00", 9);
2425 pos += 9;
2426
2427 if (sm_message_send(pos, NK7110_MSG_WAP, req, state)) return GN_ERR_NOTREADY;
2428 error = sm_block(NK7110_MSG_WAP, data, state);
2429 if (error) return error;
2430
2431 for (i = 0; i < 4; i++) {
2432 pos = 4;
2433 memset(req1 + pos, 0, 200 - pos);
2434 if (i == 0 || i== 2) { /* SMS/USSD */
2435 req1[pos++] = data->wap_setting->successors[i];
2436 req1[pos++] = 0x02;
2437 req1[pos++] = 0x00; /* SMS */
2438 /* SMS Service */
2439 pos += PackWAPString(req1 + pos, data->wap_setting->sms_service_number, 1);
2440 /* SMS Server */
2441 pos += PackWAPString(req1 + pos, data->wap_setting->sms_server_number, 1);
2442 } else { /* GSMdata */
2443 req1[pos++] = data->wap_setting->successors[i];
2444 req1[pos++] = 0x02;
2445 req1[pos++] = 0x01; /* GSMdata */
2446 req1[pos++] = data->wap_setting->gsm_data_authentication;
2447 req1[pos++] = data->wap_setting->call_type;
2448 req1[pos++] = data->wap_setting->call_speed;
2449 req1[pos++] = 0x01;
2450 /* IP */
2451 pos += PackWAPString(req1 + pos, data->wap_setting->gsm_data_ip, 1);
2452 /* Number */
2453 pos += PackWAPString(req1 + pos, data->wap_setting->number, 1);
2454 /* Username */
2455 pos += PackWAPString(req1 + pos, data->wap_setting->gsm_data_username, 1);
2456 /* Password */
2457 pos += PackWAPString(req1 + pos, data->wap_setting->gsm_data_password, 1);
2458 }
2459 memcpy(req1 + pos, "\x80\x00\x00\x00\x00\x00\x00\x00", 8);
2460 pos += 8;
2461
2462 if (sm_message_send(pos, NK7110_MSG_WAP, req1, state)) return GN_ERR_NOTREADY;
2463 error = sm_block(NK7110_MSG_WAP, data, state);
2464 if (error) return error;
2465 }
2466
2467 return FinishWAP(data, state);
2468 }
2469
NK7110_DeleteWAPBookmark(gn_data * data,struct gn_statemachine * state)2470 static gn_error NK7110_DeleteWAPBookmark(gn_data *data, struct gn_statemachine *state)
2471 {
2472 unsigned char req[] = { FBUS_FRAME_HEADER, 0x0C,
2473 0x00, 0x00}; /* Location */
2474 gn_error error;
2475
2476 dprintf("Deleting WAP bookmark\n");
2477 req[5] = data->wap_bookmark->location + 1;
2478
2479 if (PrepareWAP(data, state) != GN_ERR_NONE) {
2480 FinishWAP(data, state);
2481 if ((error = PrepareWAP(data, state))) return error;
2482 }
2483
2484 if (sm_message_send(6, NK7110_MSG_WAP, req, state)) return GN_ERR_NOTREADY;
2485 error = sm_block(NK7110_MSG_WAP, data, state);
2486 if (error) return error;
2487
2488 return FinishWAP(data, state);
2489 }
2490
NK7110_GetWAPBookmark(gn_data * data,struct gn_statemachine * state)2491 static gn_error NK7110_GetWAPBookmark(gn_data *data, struct gn_statemachine *state)
2492 {
2493 unsigned char req[] = { FBUS_FRAME_HEADER, 0x06,
2494 0x00, 0x00}; /* Location */
2495 gn_error error;
2496
2497 dprintf("Getting WAP bookmark\n");
2498 req[5] = data->wap_bookmark->location;
2499
2500 if (PrepareWAP(data, state) != GN_ERR_NONE) {
2501 FinishWAP(data, state);
2502 if ((error = PrepareWAP(data, state))) return error;
2503 }
2504
2505 if (sm_message_send(6, NK7110_MSG_WAP, req, state)) return GN_ERR_NOTREADY;
2506 error = sm_block(NK7110_MSG_WAP, data, state);
2507 if (error) return error;
2508
2509 return FinishWAP(data, state);
2510 }
2511
NK7110_WriteWAPBookmark(gn_data * data,struct gn_statemachine * state)2512 static gn_error NK7110_WriteWAPBookmark(gn_data *data, struct gn_statemachine *state)
2513 {
2514 unsigned char req[350] = { FBUS_FRAME_HEADER, 0x09,
2515 0xFF, 0xFF}; /* Location */
2516 gn_error error;
2517 int pos = 6;
2518
2519 dprintf("Writing WAP bookmark\n");
2520
2521 if (PrepareWAP(data, state) != GN_ERR_NONE) {
2522 FinishWAP(data, state);
2523 if ((error = PrepareWAP(data, state))) return error;
2524 }
2525
2526 pos += PackWAPString(req + pos, data->wap_bookmark->name, 1);
2527 pos += PackWAPString(req + pos, data->wap_bookmark->URL, 1);
2528
2529 if (sm_message_send(pos, NK7110_MSG_WAP, req, state)) return GN_ERR_NOTREADY;
2530 error = sm_block(NK7110_MSG_WAP, data, state);
2531 if (error) return error;
2532
2533 return FinishWAP(data, state);
2534 }
2535
NK7110_GetWAPSetting(gn_data * data,struct gn_statemachine * state)2536 static gn_error NK7110_GetWAPSetting(gn_data *data, struct gn_statemachine *state)
2537 {
2538 unsigned char req[] = { FBUS_FRAME_HEADER, 0x15,
2539 0x00 }; /* location */
2540 unsigned char req2[] = { FBUS_FRAME_HEADER, 0x1b,
2541 0x00 }; /* location */
2542 gn_error error;
2543 int i;
2544
2545 dprintf("Getting WAP setting\n");
2546 if (!data->wap_setting) return GN_ERR_INTERNALERROR;
2547
2548 req[4] = data->wap_setting->location;
2549 memset(data->wap_setting, 0, sizeof(gn_wap_setting));
2550 data->wap_setting->location = req[4];
2551
2552 if (PrepareWAP(data, state) != GN_ERR_NONE) {
2553 FinishWAP(data, state);
2554 if ((error = PrepareWAP(data, state))) return error;
2555 }
2556
2557 if (sm_message_send(5, NK7110_MSG_WAP, req, state)) return GN_ERR_NOTREADY;
2558 error = sm_block(NK7110_MSG_WAP, data, state);
2559 if (error) return error;
2560
2561 for (i = 0; i < 4; i++) {
2562 req2[4] = data->wap_setting->successors[i];
2563 if (sm_message_send(5, NK7110_MSG_WAP, req2, state)) return GN_ERR_NOTREADY;
2564 error = sm_block(NK7110_MSG_WAP, data, state);
2565 if (error) return error;
2566 }
2567
2568 return FinishWAP(data, state);
2569 }
2570
NK7110_ActivateWAPSetting(gn_data * data,struct gn_statemachine * state)2571 static gn_error NK7110_ActivateWAPSetting(gn_data *data, struct gn_statemachine *state)
2572 {
2573 unsigned char req[] = { FBUS_FRAME_HEADER, 0x12,
2574 0x00 }; /* Location */
2575 gn_error error;
2576
2577 dprintf("Activating WAP setting\n");
2578 req[4] = data->wap_setting->location;
2579
2580 if (PrepareWAP(data, state) != GN_ERR_NONE) {
2581 FinishWAP(data, state);
2582 if ((error = PrepareWAP(data, state))) return error;
2583 }
2584
2585 if (sm_message_send(5, NK7110_MSG_WAP, req, state)) return GN_ERR_NOTREADY;
2586 error = sm_block(NK7110_MSG_WAP, data, state);
2587 if (error) return error;
2588
2589 return FinishWAP(data, state);
2590 }
2591
2592 /*****************************/
2593 /********** KEYPRESS *********/
2594 /*****************************/
NK7110_IncomingKeypress(int messagetype,unsigned char * message,int length,gn_data * data,struct gn_statemachine * state)2595 static gn_error NK7110_IncomingKeypress(int messagetype, unsigned char *message, int length, gn_data *data, struct gn_statemachine *state)
2596 {
2597 switch(message[2]) {
2598 case 0x46:
2599 dprintf("Key successfully pressed\n");
2600 break;
2601 case 0x47:
2602 dprintf("Key successfully released\n");
2603 break;
2604 default:
2605 dprintf("Unknown keypress command\n");
2606 return GN_ERR_UNHANDLEDFRAME;
2607 }
2608 return GN_ERR_NONE;
2609 }
2610
NK7110_PressKey(gn_data * data,struct gn_statemachine * state)2611 static gn_error NK7110_PressKey(gn_data *data, struct gn_statemachine *state)
2612 {
2613 unsigned char req[] = {0x00, 0x01, 0x46, 0x00, 0x01,
2614 0x0a}; /* keycode */
2615
2616 dprintf("Pressing key...\n");
2617 req[5] = data->key_code;
2618 if (sm_message_send(6, NK7110_MSG_KEYPRESS, req, state)) return GN_ERR_NOTREADY;
2619 return sm_block(NK7110_MSG_KEYPRESS_RESP, data, state);
2620 }
2621
NK7110_ReleaseKey(gn_data * data,struct gn_statemachine * state)2622 static gn_error NK7110_ReleaseKey(gn_data *data, struct gn_statemachine *state)
2623 {
2624 unsigned char req[] = {0x00, 0x01, 0x47, 0x00, 0x01, 0x0c};
2625
2626 dprintf("Releasing key...\n");
2627 if (sm_message_send(6, NK7110_MSG_KEYPRESS, req, state)) return GN_ERR_NOTREADY;
2628 return sm_block(NK7110_MSG_KEYPRESS_RESP, data, state);
2629 }
2630
NK7110_PressOrReleaseKey(gn_data * data,struct gn_statemachine * state,bool press)2631 static gn_error NK7110_PressOrReleaseKey(gn_data *data, struct gn_statemachine *state, bool press)
2632 {
2633 if (press)
2634 return NK7110_PressKey(data, state);
2635 else
2636 return NK7110_ReleaseKey(data, state);
2637 }
2638
2639 /*****************************/
2640 /********** PROFILE **********/
2641 /*****************************/
NK7110_IncomingProfile(int messagetype,unsigned char * message,int length,gn_data * data,struct gn_statemachine * state)2642 static gn_error NK7110_IncomingProfile(int messagetype, unsigned char *message, int length, gn_data *data, struct gn_statemachine *state)
2643 {
2644 switch (message[3]) {
2645 case 0x02:
2646 if (!data->profile) return GN_ERR_INTERNALERROR;
2647 switch (message[6]) {
2648 case 0xff:
2649 char_unicode_decode(data->profile->name, message + 10, message[9]);
2650 data->profile->default_name = -1; //!!!FIXME
2651 break;
2652 case 0x00:
2653 data->profile->keypad_tone = (unsigned char)(message[10] - 1);
2654 break;
2655 case 0x01:
2656 //!!!FIXME
2657 data->profile->lights = message[10];
2658 break;
2659 case 0x02:
2660 switch (message[10]) {
2661 case 0x00: data->profile->call_alert = GN_PROFILE_CALLALERT_Ringing; break;
2662 case 0x01: data->profile->call_alert = GN_PROFILE_CALLALERT_Ascending; break;
2663 case 0x02: data->profile->call_alert = GN_PROFILE_CALLALERT_RingOnce; break;
2664 case 0x03: data->profile->call_alert = GN_PROFILE_CALLALERT_BeepOnce; break;
2665 case 0x04: data->profile->call_alert = GN_PROFILE_CALLALERT_CallerGroups; break;
2666 case 0x05: data->profile->call_alert = GN_PROFILE_CALLALERT_Off; break;
2667 default: return GN_ERR_UNHANDLEDFRAME; break;
2668 }
2669 break;
2670 case 0x03:
2671 //!!!FIXME: check it!
2672 data->profile->ringtone = message[10];
2673 break;
2674 case 0x04:
2675 data->profile->volume = message[10] + 6;
2676 break;
2677 case 0x05:
2678 data->profile->message_tone = message[10];
2679 break;
2680 case 0x06:
2681 data->profile->vibration = message[10];
2682 break;
2683 case 0x07:
2684 data->profile->warning_tone = message[10] ? GN_PROFILE_WARNING_On : GN_PROFILE_WARNING_Off;
2685 break;
2686 case 0x08:
2687 data->profile->caller_groups = message[10];
2688 break;
2689 case 0x09:
2690 data->profile->automatic_answer = message[10];
2691 break;
2692 default:
2693 return GN_ERR_UNHANDLEDFRAME;
2694 break;
2695 }
2696 break;
2697 default:
2698 dprintf("Unknown subtype of type 0x39 (%d)\n", message[3]);
2699 return GN_ERR_UNHANDLEDFRAME;
2700 break;
2701 }
2702 return GN_ERR_NONE;
2703 }
2704
NK7110_GetProfile(gn_data * data,struct gn_statemachine * state)2705 static gn_error NK7110_GetProfile(gn_data *data, struct gn_statemachine *state)
2706 {
2707 char req[] = {FBUS_FRAME_HEADER, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00};
2708 unsigned char i;
2709 gn_error err;
2710
2711 if (!data->profile) return GN_ERR_INTERNALERROR;
2712
2713 req[7] = data->profile->number + 1;
2714 for (i = 0xff; i != 0x0a; i++) {
2715 req[8] = i;
2716 if (sm_message_send(9, NK7110_MSG_PROFILE, req, state)) return GN_ERR_NOTREADY;
2717 if ((err = sm_block(NK7110_MSG_PROFILE, data, state)) != GN_ERR_NONE) return err;
2718 }
2719
2720 return GN_ERR_NONE;
2721 }
2722
NK7110_SetProfileFeature(gn_data * data,struct gn_statemachine * state,int id,unsigned char value)2723 static gn_error NK7110_SetProfileFeature(gn_data *data, struct gn_statemachine *state, int id, unsigned char value)
2724 {
2725 unsigned char req[] = {FBUS_FRAME_HEADER, 0x03, 0x01, 0x01, 0x03, 0x00, 0x00, 0x01, 0x00};
2726
2727 if (!data->profile) return GN_ERR_INTERNALERROR;
2728
2729 req[7] = id;
2730 req[8] = data->profile->number;
2731 req[10] = value;
2732
2733 if (sm_message_send(11, NK7110_MSG_PROFILE, req, state)) return GN_ERR_NOTREADY;
2734 return sm_block(NK7110_MSG_PROFILE, data, state);
2735 }
2736
NK7110_SetProfile(gn_data * data,struct gn_statemachine * state)2737 static gn_error NK7110_SetProfile(gn_data *data, struct gn_statemachine *state)
2738 {
2739 gn_profile *p;
2740 gn_error err;
2741
2742 if (!(p = data->profile)) return GN_ERR_INTERNALERROR;
2743 dprintf("Setting profile %d (%s)\n", p->number, p->name);
2744
2745 if (p->default_name < 0 ) {
2746 /* FIXME: set profile name */
2747 }
2748 if ((err = NK7110_SetProfileFeature(data, state, 0x00, p->keypad_tone + 1)) != GN_ERR_NONE)
2749 return err;
2750
2751 if ((err = NK7110_SetProfileFeature(data, state, 0x01, p->lights)) != GN_ERR_NONE)
2752 return err;
2753
2754 switch (p->call_alert) {
2755 case GN_PROFILE_CALLALERT_Ringing: err = NK7110_SetProfileFeature(data, state, 0x02, 0x00); break;
2756 case GN_PROFILE_CALLALERT_Ascending: err = NK7110_SetProfileFeature(data, state, 0x02, 0x01); break;
2757 case GN_PROFILE_CALLALERT_RingOnce: err = NK7110_SetProfileFeature(data, state, 0x02, 0x02); break;
2758 case GN_PROFILE_CALLALERT_BeepOnce: err = NK7110_SetProfileFeature(data, state, 0x02, 0x03); break;
2759 case GN_PROFILE_CALLALERT_CallerGroups: err = NK7110_SetProfileFeature(data, state, 0x02, 0x04); break;
2760 case GN_PROFILE_CALLALERT_Off: err = NK7110_SetProfileFeature(data, state, 0x02, 0x05); break;
2761 default: return GN_ERR_UNKNOWN;
2762 }
2763 if (err != GN_ERR_NONE) return err;
2764
2765 if ((err = NK7110_SetProfileFeature(data, state, 0x03, p->ringtone)) != GN_ERR_NONE)
2766 return err;
2767
2768 if ((err = NK7110_SetProfileFeature(data, state, 0x04, p->volume - 6)) != GN_ERR_NONE)
2769 return err;
2770
2771 if ((err = NK7110_SetProfileFeature(data, state, 0x05, p->message_tone)) != GN_ERR_NONE)
2772 return err;
2773
2774 if ((err = NK7110_SetProfileFeature(data, state, 0x06, p->vibration)) != GN_ERR_NONE)
2775 return err;
2776
2777 switch (p->warning_tone) {
2778 case GN_PROFILE_WARNING_Off: err = NK7110_SetProfileFeature(data, state, 0x07, 0x00); break;
2779 case GN_PROFILE_WARNING_On: err = NK7110_SetProfileFeature(data, state, 0x07, 0x01); break;
2780 default: return GN_ERR_UNKNOWN;
2781 }
2782 if (err != GN_ERR_NONE) return err;
2783
2784 if ((err = NK7110_SetProfileFeature(data, state, 0x08, p->caller_groups)) != GN_ERR_NONE)
2785 return err;
2786
2787 if ((err = NK7110_SetProfileFeature(data, state, 0x09, p->automatic_answer)) != GN_ERR_NONE)
2788 return err;
2789
2790 return GN_ERR_NONE;
2791 }
2792
2793 /*****************************/
2794 /********* RINGTONE **********/
2795 /*****************************/
NK7110_IncomingRingtone(int messagetype,unsigned char * message,int length,gn_data * data,struct gn_statemachine * state)2796 static gn_error NK7110_IncomingRingtone(int messagetype, unsigned char *message, int length, gn_data *data, struct gn_statemachine *state)
2797 {
2798 switch (message[3]) {
2799 case 0x23:
2800 if (!data->ringtone || !data->raw_data) return GN_ERR_INTERNALERROR;
2801 data->ringtone->location = message[5];
2802 char_unicode_decode(data->ringtone->name, message + 6, 2 * 15);
2803 if (data->raw_data->length < length - 36) return GN_ERR_MEMORYFULL;
2804 if (data->raw_data && data->raw_data->data) {
2805 memcpy(data->raw_data->data, message + 36, length - 36);
2806 data->raw_data->length = length - 35;
2807 }
2808 break;
2809
2810 case 0x24:
2811 return GN_ERR_INVALIDLOCATION;
2812
2813 default:
2814 return GN_ERR_UNHANDLEDFRAME;
2815 }
2816
2817 return GN_ERR_NONE;
2818 }
2819
NK7110_GetRawRingtone(gn_data * data,struct gn_statemachine * state)2820 static gn_error NK7110_GetRawRingtone(gn_data *data, struct gn_statemachine *state)
2821 {
2822 unsigned char req[] = {FBUS_FRAME_HEADER, 0x22, 0x00, 0x00};
2823
2824 if (!data || !data->ringtone || !data->raw_data) return GN_ERR_INTERNALERROR;
2825 if (data->ringtone->location < 0) return GN_ERR_INVALIDLOCATION;
2826
2827 req[5] = data->ringtone->location;
2828
2829 SEND_MESSAGE_BLOCK(NK7110_MSG_RINGTONE, 6);
2830 }
2831
NK7110_SetRawRingtone(gn_data * data,struct gn_statemachine * state)2832 static gn_error NK7110_SetRawRingtone(gn_data *data, struct gn_statemachine *state)
2833 {
2834 unsigned char req[512] = {FBUS_FRAME_HEADER, 0x1f, 0x00, 0x00};
2835 int len;
2836
2837 if (!data || !data->ringtone || !data->raw_data || !data->raw_data->data)
2838 return GN_ERR_INTERNALERROR;
2839 if (sizeof(req) < 36 + data->raw_data->length) return GN_ERR_MEMORYFULL;
2840 if (data->ringtone->location < 0) {
2841 /* FIXME: search first free location */
2842 data->ringtone->location = DRVINSTANCE(state)->userdef_location;
2843 }
2844
2845 req[5] = data->ringtone->location;
2846 char_unicode_encode(req + 6, data->ringtone->name, strlen(data->ringtone->name));
2847 memcpy(req + 36, data->raw_data->data, data->raw_data->length);
2848 len = 36 + data->raw_data->length;
2849
2850 if (sm_message_send(len, NK7110_MSG_RINGTONE, req, state)) return GN_ERR_NOTREADY;
2851 return sm_block_ack(state);
2852 }
2853
NK7110_GetRingtone(gn_data * data,struct gn_statemachine * state)2854 static gn_error NK7110_GetRingtone(gn_data *data, struct gn_statemachine *state)
2855 {
2856 gn_data d;
2857 gn_error err;
2858 gn_raw_data rawdata;
2859 char buf[4096];
2860
2861 if (!data->ringtone) return GN_ERR_INTERNALERROR;
2862
2863 memset(&rawdata, 0, sizeof(gn_raw_data));
2864 rawdata.data = buf;
2865 rawdata.length = sizeof(buf);
2866 gn_data_clear(&d);
2867 d.ringtone = data->ringtone;
2868 d.raw_data = &rawdata;
2869
2870 if ((err = NK7110_GetRawRingtone(&d, state)) != GN_ERR_NONE) return err;
2871
2872 return pnok_ringtone_from_raw(data->ringtone, rawdata.data, rawdata.length);
2873 }
2874
NK7110_SetRingtone(gn_data * data,struct gn_statemachine * state)2875 static gn_error NK7110_SetRingtone(gn_data *data, struct gn_statemachine *state)
2876 {
2877 gn_data d;
2878 gn_error err;
2879 gn_raw_data rawdata;
2880 char buf[4096];
2881
2882 if (!data->ringtone) return GN_ERR_INTERNALERROR;
2883
2884 memset(&rawdata, 0, sizeof(gn_raw_data));
2885 rawdata.data = buf;
2886 rawdata.length = sizeof(buf);
2887 gn_data_clear(&d);
2888 d.ringtone = data->ringtone;
2889 d.raw_data = &rawdata;
2890
2891 if ((err = pnok_ringtone_to_raw(rawdata.data, &rawdata.length, data->ringtone, 0)) != GN_ERR_NONE)
2892 return err;
2893
2894 return NK7110_SetRawRingtone(&d, state);
2895 }
2896
NK7110_GetRingtoneList(gn_data * data,struct gn_statemachine * state)2897 static gn_error NK7110_GetRingtoneList(gn_data *data, struct gn_statemachine *state)
2898 {
2899 gn_ringtone_list *rl;
2900 gn_ringtone ringtone;
2901 gn_data d;
2902 int i;
2903
2904 #define ADDRINGTONE(id, str) \
2905 rl->ringtone[rl->count].location = (id); \
2906 snprintf(rl->ringtone[rl->count].name, sizeof(rl->ringtone[rl->count].name), "%s", (str)); \
2907 rl->ringtone[rl->count].user_defined = 0; \
2908 rl->ringtone[rl->count].readable = 0; \
2909 rl->ringtone[rl->count].writable = 0; \
2910 rl->count++;
2911
2912 if (!(rl = data->ringtone_list)) return GN_ERR_INTERNALERROR;
2913 rl->count = 0;
2914 rl->userdef_location = DRVINSTANCE(state)->userdef_location;
2915 rl->userdef_count = 5;
2916
2917 /* tested on 6210 -- bozo */
2918 ADDRINGTONE(65, "Ring ring");
2919 ADDRINGTONE(66, "Low");
2920 ADDRINGTONE(67, "Do-mi-so");
2921 ADDRINGTONE(68, "Bee");
2922 ADDRINGTONE(69, "Cicada");
2923 ADDRINGTONE(70, "Trio");
2924 ADDRINGTONE(71, "Intro");
2925 ADDRINGTONE(72, "Persuasion");
2926 ADDRINGTONE(73, "Attraction");
2927 ADDRINGTONE(74, "Playground");
2928 ADDRINGTONE(75, "Mosquito");
2929 ADDRINGTONE(76, "Circles");
2930 ADDRINGTONE(77, "Nokia tune");
2931 ADDRINGTONE(78, "Sunny walks");
2932 ADDRINGTONE(79, "Samba");
2933 ADDRINGTONE(80, "Basic rock");
2934 ADDRINGTONE(81, "Reveille");
2935 ADDRINGTONE(82, "Groovy Blue");
2936 ADDRINGTONE(83, "Brave Scotland");
2937 ADDRINGTONE(84, "Matilda");
2938 ADDRINGTONE(85, "Bumblebee");
2939 ADDRINGTONE(86, "Menuet");
2940 ADDRINGTONE(87, "Elise");
2941 ADDRINGTONE(88, "William Tell");
2942 ADDRINGTONE(89, "Charleston");
2943 ADDRINGTONE(90, "Fuga");
2944 ADDRINGTONE(91, "Etude");
2945 ADDRINGTONE(92, "Hungarian");
2946 ADDRINGTONE(93, "Valkyrie");
2947 ADDRINGTONE(94, "Badinerie");
2948 ADDRINGTONE(95, "Bach #3");
2949 ADDRINGTONE(96, "Toreador");
2950 ADDRINGTONE(97, "9th Symphony");
2951 ADDRINGTONE(98, "WalzeBrilliant");
2952
2953 memset(&ringtone, 0, sizeof(ringtone));
2954 gn_data_clear(&d);
2955 d.ringtone = &ringtone;
2956 for (i = 0; i < rl->userdef_count; i++) {
2957 ringtone.location = rl->userdef_location + i;
2958 if (NK7110_GetRingtone(&d, state) == GN_ERR_NONE) {
2959 rl->ringtone[rl->count].location = ringtone.location;
2960 snprintf(rl->ringtone[rl->count].name, sizeof(rl->ringtone[rl->count].name), "%s", ringtone.name);
2961 rl->ringtone[rl->count].user_defined = 1;
2962 rl->ringtone[rl->count].readable = 1;
2963 rl->ringtone[rl->count].writable = 1;
2964 rl->count++;
2965 }
2966 }
2967
2968 #undef ADDRINGTONE
2969
2970 return GN_ERR_NONE;
2971 }
2972
2973
2974 /*****************************/
2975 /********** OTHERS ***********/
2976 /*****************************/
NK7110_GetBitmap(gn_data * data,struct gn_statemachine * state)2977 static gn_error NK7110_GetBitmap(gn_data *data, struct gn_statemachine *state)
2978 {
2979 switch(data->bitmap->type) {
2980 case GN_BMP_CallerLogo:
2981 return GetCallerBitmap(data, state);
2982 case GN_BMP_StartupLogo:
2983 return GetStartupBitmap(data, state);
2984 case GN_BMP_OperatorLogo:
2985 return GetOperatorBitmap(data, state);
2986 default:
2987 return GN_ERR_NOTIMPLEMENTED;
2988 }
2989 }
2990
NK7110_SetBitmap(gn_data * data,struct gn_statemachine * state)2991 static gn_error NK7110_SetBitmap(gn_data *data, struct gn_statemachine *state)
2992 {
2993 switch(data->bitmap->type) {
2994 case GN_BMP_CallerLogo:
2995 return SetCallerBitmap(data, state);
2996 case GN_BMP_StartupLogo:
2997 return SetStartupBitmap(data, state);
2998 case GN_BMP_OperatorLogo:
2999 return SetOperatorBitmap(data, state);
3000 default:
3001 return GN_ERR_NOTIMPLEMENTED;
3002 }
3003 }
3004
get_memory_type(gn_memory_type memory_type)3005 static int get_memory_type(gn_memory_type memory_type)
3006 {
3007 int result;
3008
3009 switch (memory_type) {
3010 case GN_MT_MT:
3011 result = NK7110_MEMORY_MT;
3012 break;
3013 case GN_MT_ME:
3014 result = NK7110_MEMORY_ME;
3015 break;
3016 case GN_MT_SM:
3017 result = NK7110_MEMORY_SM;
3018 break;
3019 case GN_MT_FD:
3020 result = NK7110_MEMORY_FD;
3021 break;
3022 case GN_MT_ON:
3023 result = NK7110_MEMORY_ON;
3024 break;
3025 case GN_MT_EN:
3026 result = NK7110_MEMORY_EN;
3027 break;
3028 case GN_MT_DC:
3029 result = NK7110_MEMORY_DC;
3030 break;
3031 case GN_MT_RC:
3032 result = NK7110_MEMORY_RC;
3033 break;
3034 case GN_MT_MC:
3035 result = NK7110_MEMORY_MC;
3036 break;
3037 case GN_MT_IN:
3038 result = NK7110_MEMORY_IN;
3039 break;
3040 case GN_MT_OU:
3041 result = NK7110_MEMORY_OU;
3042 break;
3043 case GN_MT_AR:
3044 result = NK7110_MEMORY_AR;
3045 break;
3046 case GN_MT_TE:
3047 result = NK7110_MEMORY_TE;
3048 break;
3049 case GN_MT_F1:
3050 result = NK7110_MEMORY_F1;
3051 break;
3052 case GN_MT_F2:
3053 result = NK7110_MEMORY_F2;
3054 break;
3055 case GN_MT_F3:
3056 result = NK7110_MEMORY_F3;
3057 break;
3058 case GN_MT_F4:
3059 result = NK7110_MEMORY_F4;
3060 break;
3061 case GN_MT_F5:
3062 result = NK7110_MEMORY_F5;
3063 break;
3064 case GN_MT_F6:
3065 result = NK7110_MEMORY_F6;
3066 break;
3067 case GN_MT_F7:
3068 result = NK7110_MEMORY_F7;
3069 break;
3070 case GN_MT_F8:
3071 result = NK7110_MEMORY_F8;
3072 break;
3073 case GN_MT_F9:
3074 result = NK7110_MEMORY_F9;
3075 break;
3076 case GN_MT_F10:
3077 result = NK7110_MEMORY_F10;
3078 break;
3079 case GN_MT_F11:
3080 result = NK7110_MEMORY_F11;
3081 break;
3082 case GN_MT_F12:
3083 result = NK7110_MEMORY_F12;
3084 break;
3085 case GN_MT_F13:
3086 result = NK7110_MEMORY_F13;
3087 break;
3088 case GN_MT_F14:
3089 result = NK7110_MEMORY_F14;
3090 break;
3091 case GN_MT_F15:
3092 result = NK7110_MEMORY_F15;
3093 break;
3094 case GN_MT_F16:
3095 result = NK7110_MEMORY_F16;
3096 break;
3097 case GN_MT_F17:
3098 result = NK7110_MEMORY_F17;
3099 break;
3100 case GN_MT_F18:
3101 result = NK7110_MEMORY_F18;
3102 break;
3103 case GN_MT_F19:
3104 result = NK7110_MEMORY_F19;
3105 break;
3106 case GN_MT_F20:
3107 result = NK7110_MEMORY_F20;
3108 break;
3109 default:
3110 result = NK7110_MEMORY_XX;
3111 break;
3112 }
3113 return result;
3114 }
3115
get_gn_memory_type(int memory_type)3116 static gn_memory_type get_gn_memory_type(int memory_type)
3117 {
3118 int result;
3119
3120 switch (memory_type) {
3121 case NK7110_MEMORY_MT:
3122 result = GN_MT_MT;
3123 break;
3124 case NK7110_MEMORY_ME:
3125 result = GN_MT_ME;
3126 break;
3127 case NK7110_MEMORY_SM:
3128 result = GN_MT_SM;
3129 break;
3130 case NK7110_MEMORY_FD:
3131 result = GN_MT_FD;
3132 break;
3133 case NK7110_MEMORY_ON:
3134 result = GN_MT_ON;
3135 break;
3136 case NK7110_MEMORY_DC:
3137 result = GN_MT_DC;
3138 break;
3139 case NK7110_MEMORY_RC:
3140 result = GN_MT_RC;
3141 break;
3142 case NK7110_MEMORY_MC:
3143 result = GN_MT_MC;
3144 break;
3145 case NK7110_MEMORY_IN:
3146 result = GN_MT_IN;
3147 break;
3148 case NK7110_MEMORY_OU:
3149 result = GN_MT_OU;
3150 break;
3151 case NK7110_MEMORY_AR:
3152 result = GN_MT_AR;
3153 break;
3154 case NK7110_MEMORY_TE:
3155 result = GN_MT_TE;
3156 break;
3157 case NK7110_MEMORY_F1:
3158 result = GN_MT_F1;
3159 break;
3160 case NK7110_MEMORY_F2:
3161 result = GN_MT_F2;
3162 break;
3163 case NK7110_MEMORY_F3:
3164 result = GN_MT_F3;
3165 break;
3166 case NK7110_MEMORY_F4:
3167 result = GN_MT_F4;
3168 break;
3169 case NK7110_MEMORY_F5:
3170 result = GN_MT_F5;
3171 break;
3172 case NK7110_MEMORY_F6:
3173 result = GN_MT_F6;
3174 break;
3175 case NK7110_MEMORY_F7:
3176 result = GN_MT_F7;
3177 break;
3178 case NK7110_MEMORY_F8:
3179 result = GN_MT_F8;
3180 break;
3181 case NK7110_MEMORY_F9:
3182 result = GN_MT_F9;
3183 break;
3184 case NK7110_MEMORY_F10:
3185 result = GN_MT_F10;
3186 break;
3187 case NK7110_MEMORY_F11:
3188 result = GN_MT_F11;
3189 break;
3190 case NK7110_MEMORY_F12:
3191 result = GN_MT_F12;
3192 break;
3193 case NK7110_MEMORY_F13:
3194 result = GN_MT_F13;
3195 break;
3196 case NK7110_MEMORY_F14:
3197 result = GN_MT_F14;
3198 break;
3199 case NK7110_MEMORY_F15:
3200 result = GN_MT_F15;
3201 break;
3202 case NK7110_MEMORY_F16:
3203 result = GN_MT_F16;
3204 break;
3205 case NK7110_MEMORY_F17:
3206 result = GN_MT_F17;
3207 break;
3208 case NK7110_MEMORY_F18:
3209 result = GN_MT_F18;
3210 break;
3211 case NK7110_MEMORY_F19:
3212 result = GN_MT_F19;
3213 break;
3214 case NK7110_MEMORY_F20:
3215 result = GN_MT_F20;
3216 break;
3217 default:
3218 result = GN_MT_XX;
3219 break;
3220 }
3221 return result;
3222 }
3223
3224 #if 0
3225 static gn_error NBSUpload(gn_data *data, struct gn_statemachine *state, gn_sms_data_type type)
3226 {
3227 unsigned char req[512] = {0x7c, 0x01, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
3228 gn_sms sms;
3229 gn_sms_raw rawsms;
3230 gn_error err;
3231 int n;
3232
3233 gn_sms_default_submit(&sms);
3234 sms.user_data[0].type = type;
3235 sms.user_data[1].type = GN_SMS_DATA_None;
3236
3237 switch (type) {
3238 case GN_SMS_DATA_Ringtone:
3239 memcpy(&sms.user_data[0].u.ringtone, data->ringtone, sizeof(gn_ringtone));
3240 break;
3241 default:
3242 return GN_ERR_INTERNALERROR;
3243 }
3244
3245 memset(&rawsms, 0, sizeof(rawsms));
3246
3247 if ((err = sms_prepare(&sms, &rawsms)) != GN_ERR_NONE) return err;
3248
3249 req[10] = rawsms.user_data_length;
3250 n = 11 + rawsms.user_data_length;
3251 if (n > sizeof(req)) return GN_ERR_INTERNALERROR;
3252 memcpy(req + 11, rawsms.user_data, rawsms.user_data_length);
3253
3254 return sm_message_send(n, 0x00, req, state);
3255 }
3256 #endif
3257
3258 /*****************************/
3259 /******* COMM STATUS *********/
3260 /*****************************/
NK7110_IncomingCommstatus(int messagetype,unsigned char * message,int length,gn_data * data,struct gn_statemachine * state)3261 static gn_error NK7110_IncomingCommstatus(int messagetype, unsigned char *message, int length, gn_data *data, struct gn_statemachine *state)
3262 {
3263 unsigned char *pos;
3264 int i;
3265 gn_call_active *ca;
3266
3267 switch (message[3]) {
3268 /* get call status */
3269 case 0x21:
3270 if (!data->call_active) return GN_ERR_INTERNALERROR;
3271 if (message[5] != 0xff) return GN_ERR_UNHANDLEDFRAME;
3272 pos = message + 6;
3273 ca = data->call_active;
3274 memset(ca, 0x00, 2 * sizeof(gn_call_active));
3275 for (i = 0; i < message[4]; i++) {
3276 if (pos[0] != 0x64) return GN_ERR_UNHANDLEDFRAME;
3277 ca[i].call_id = pos[2];
3278 ca[i].channel = pos[3];
3279 switch (pos[4]) {
3280 case 0x00: ca[i].state = GN_CALL_Idle; break; /* missing number, wait a little */
3281 case 0x02: ca[i].state = GN_CALL_Dialing; break;
3282 case 0x03: ca[i].state = GN_CALL_Ringing; break;
3283 case 0x04: ca[i].state = GN_CALL_Incoming; break;
3284 case 0x05: ca[i].state = GN_CALL_Established; break;
3285 case 0x06: ca[i].state = GN_CALL_Held; break;
3286 case 0x07: ca[i].state = GN_CALL_RemoteHangup; break;
3287 default: return GN_ERR_UNHANDLEDFRAME;
3288 }
3289 switch (pos[5]) {
3290 case 0x00: ca[i].prev_state = GN_CALL_Idle; break; /* missing number, wait a little */
3291 case 0x02: ca[i].prev_state = GN_CALL_Dialing; break;
3292 case 0x03: ca[i].prev_state = GN_CALL_Ringing; break;
3293 case 0x04: ca[i].prev_state = GN_CALL_Incoming; break;
3294 case 0x05: ca[i].prev_state = GN_CALL_Established; break;
3295 case 0x06: ca[i].prev_state = GN_CALL_Held; break;
3296 case 0x07: ca[i].prev_state = GN_CALL_RemoteHangup; break;
3297 default: return GN_ERR_UNHANDLEDFRAME;
3298 }
3299 char_unicode_decode(ca[i].name, pos + 12, 2 * pos[10]);
3300 char_unicode_decode(ca[i].number, pos + 112, 2 * pos[11]);
3301 pos += pos[1];
3302 }
3303 dprintf("Call status:\n");
3304 for (i = 0; i < 2; i++) {
3305 if (ca[i].state == GN_CALL_Idle) continue;
3306 dprintf("ch#%d: id#%d st#%d pst#%d %s (%s)\n",
3307 ca[i].channel, ca[i].call_id, ca[i].state, ca[i].prev_state, ca[i].number, ca[i].name);
3308 }
3309 break;
3310
3311 /* hangup */
3312 case 0x04:
3313 dprintf("Hangup!\n");
3314 dprintf("Call ID: %i\n", message[4]);
3315 dprintf("Cause Type: %i\n", message[5]);
3316 dprintf("Cause ID: %i\n", message[6]);
3317 return GN_ERR_UNKNOWN;
3318
3319 default:
3320 return GN_ERR_UNHANDLEDFRAME;
3321 }
3322 return GN_ERR_NONE;
3323 }
3324
NK7110_GetActiveCalls(gn_data * data,struct gn_statemachine * state)3325 static gn_error NK7110_GetActiveCalls(gn_data *data, struct gn_statemachine *state)
3326 {
3327 unsigned char req[] = {FBUS_FRAME_HEADER, 0x20};
3328
3329 if (!data->call_active) return GN_ERR_INTERNALERROR;
3330
3331 if (sm_message_send(4, NK7110_MSG_COMMSTATUS, req, state)) return GN_ERR_NOTREADY;
3332 return sm_block(NK7110_MSG_COMMSTATUS, data, state);
3333 }
3334
NK7110_MakeCall(gn_data * data,struct gn_statemachine * state)3335 static gn_error NK7110_MakeCall(gn_data *data, struct gn_statemachine *state)
3336 {
3337 unsigned char req[100] = {FBUS_FRAME_HEADER, 0x01};
3338 unsigned char voice_end[] = {0x05, 0x01, 0x05, 0x00, 0x02, 0x00, 0x00, 0x00};
3339 int pos = 4, len;
3340 gn_call_active active[2];
3341 gn_data d;
3342
3343 if (!data->call_info) return GN_ERR_INTERNALERROR;
3344
3345 switch (data->call_info->type) {
3346 case GN_CALL_Voice:
3347 break;
3348
3349 case GN_CALL_NonDigitalData:
3350 case GN_CALL_DigitalData:
3351 dprintf("Unsupported call type %d\n", data->call_info->type);
3352 return GN_ERR_NOTSUPPORTED;
3353
3354 default:
3355 dprintf("Invalid call type %d\n", data->call_info->type);
3356 return GN_ERR_INTERNALERROR;
3357 }
3358
3359 len = strlen(data->call_info->number);
3360 if (len > GN_PHONEBOOK_NUMBER_MAX_LENGTH) {
3361 dprintf("number too long\n");
3362 return GN_ERR_ENTRYTOOLONG;
3363 }
3364 len = char_unicode_encode(req + pos + 1, data->call_info->number, len);
3365 req[pos++] = len / 2;
3366 pos += len;
3367
3368 switch (data->call_info->send_number) {
3369 case GN_CALL_Never: voice_end[5] = 0x01; break;
3370 case GN_CALL_Always: voice_end[5] = 0x00; break;
3371 case GN_CALL_Default: voice_end[5] = 0x00; break;
3372 default: return GN_ERR_INTERNALERROR;
3373 }
3374 memcpy(req + pos, voice_end, sizeof(voice_end));
3375 pos += sizeof(voice_end);
3376
3377 if (sm_message_send(pos, NK7110_MSG_COMMSTATUS, req, state)) return GN_ERR_NOTREADY;
3378 if (sm_block_ack(state) != GN_ERR_NONE) return GN_ERR_NOTREADY;
3379
3380 memset(active, 0, sizeof(*active));
3381 gn_data_clear(&d);
3382 d.call_active = active;
3383 if (NK7110_GetActiveCalls(&d, state) != GN_ERR_NONE) return GN_ERR_NOTREADY;
3384 data->call_info->call_id = active[0].call_id;
3385
3386 return GN_ERR_NONE;
3387 }
3388
NK7110_CancelCall(gn_data * data,struct gn_statemachine * state)3389 static gn_error NK7110_CancelCall(gn_data *data, struct gn_statemachine *state)
3390 {
3391 unsigned char req[] = {FBUS_FRAME_HEADER, 0x08, 0x00};
3392
3393 if (!data->call_info) return GN_ERR_INTERNALERROR;
3394
3395 req[4] = data->call_info->call_id;
3396
3397 if (sm_message_send(5, NK7110_MSG_COMMSTATUS, req, state)) return GN_ERR_NOTREADY;
3398 return sm_block_ack(state);
3399 }
3400
NK7110_AnswerCall(gn_data * data,struct gn_statemachine * state)3401 static gn_error NK7110_AnswerCall(gn_data *data, struct gn_statemachine *state)
3402 {
3403 unsigned char req[] = {FBUS_FRAME_HEADER, 0x06, 0x00};
3404
3405 if (!data->call_info) return GN_ERR_INTERNALERROR;
3406
3407 req[4] = data->call_info->call_id;
3408
3409 if (sm_message_send(5, NK7110_MSG_COMMSTATUS, req, state)) return GN_ERR_NOTREADY;
3410 return sm_block_ack(state);
3411 }
3412