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