6 A Linux/Unix toolset and driver for Nokia mobile phones.
8 Copyright (C) 2000 Hugh Blemings & Pavel Janík ml.
9 Copyright (C) 2001 Pawe³ Kot <pkot@linuxnews.pl>
11 Released under the terms of the GNU GPL, see file COPYING for more details.
13 This file provides functions specific to the 6100 series.
14 See README for more details on supported mobile phones.
17 Revision 1.1.1.3 2002/04/03 00:08:09 short
18 Found in "gnokii-working" directory, some November-patches version
20 Revision 1.3 2001/08/17 00:01:53 pkot
21 Fixed a typo in 6100.c (me)
23 Revision 1.2 2001/08/09 12:34:34 pkot
24 3330 and 6250 support - I have no idea if it does work (mygnokii)
26 Revision 1.1 2001/07/09 23:55:35 pkot
27 Initial support for 6100 series in the new structure (me)
35 #define __phones_nk6100_c
37 #include "gsm-common.h"
38 #include "phones/generic.h"
39 #include "phones/nk6100.h"
40 #include "links/fbus.h"
41 #include "links/fbus-phonet.h"
42 #include "phones/nokia.h"
45 #define snprintf _snprintf
50 static unsigned char MagicBytes[4] = { 0x00, 0x00, 0x00, 0x00 };
52 static GSM_IncomingFunctionType IncomingFunctions[] = {
53 { 0x64, IncomingPhoneInfo },
54 { 0xd2, IncomingModelInfo },
55 { 0x03, Incoming0x03 },
56 { 0x0a, Incoming0x0a },
57 { 0x17, Incoming0x17 },
61 GSM_Phone phone_nokia_6100 = {
64 /* Mobile phone information */
66 "6110|6130|6150|6190|5110|5130|5190|3210|3310|3330", /* Supported models */
69 GRF_Arbitrary, /* RF level units */
70 4, /* Max Battery Level */
71 0, /* Min Battery Level */
72 GBU_Arbitrary, /* Battery level units */
73 GDT_DateTime, /* Have date/time support */
74 GDT_TimeOnly, /* Alarm supports time only */
75 1, /* Alarms available - FIXME */
76 48, 84, /* Startup logo size - 7110 is fixed at init*/
77 14, 72, /* Op logo size */
78 14, 72 /* Caller logo size */
83 static GSM_Error Functions(GSM_Operation op, GSM_Data *data, GSM_Statemachine *state)
87 return Initialise(state);
90 return GetModelName(data, state);
93 return GetRevision(data, state);
96 return GetIMEI(data, state);
99 return Identify(data, state);
101 case GOP_GetBatteryLevel:
102 return GetBatteryLevel(data, state);
105 return GetRFLevel(data, state);
107 case GOP_GetMemoryStatus:
108 return GetMemoryStatus(data, state);
111 return GE_NOTIMPLEMENTED;
116 static bool LinkOK = true;
118 /* Initialise is the only function allowed to 'use' state */
119 static GSM_Error Initialise(GSM_Statemachine *state)
124 int try = 0, connected = 0;
126 /* Copy in the phone info */
127 memcpy(&(state->Phone), &phone_nokia_6100, sizeof(GSM_Phone));
130 switch (state->Link.ConnectionType) {
132 if (try > 1) return GE_NOTSUPPORTED;
133 err = FBUS_Initialise(&(state->Link), state);
136 if (try > 0) return GE_NOTSUPPORTED;
137 err = PHONET_Initialise(&(state->Link), state);
140 return GE_NOTSUPPORTED;
144 if (err != GE_NONE) {
145 dprintf("Error in link initialisation\n");
150 SM_Initialise(state);
152 /* Now test the link and get the model */
153 GSM_DataClear(&data);
155 if (state->Phone.Functions(GOP_GetModel, &data, state) != GE_NONE) try++;
161 static GSM_Error GetPhoneInfo(GSM_Data *data, GSM_Statemachine *state)
163 unsigned char req[] = { FBUS_FRAME_HEADER, 0x03, 0x00 };
165 dprintf("Getting phone info...\n");
166 if (SM_SendMessage(state, 5, 0xd1, req) != GE_NONE) return GE_NOTREADY;
167 return (SM_Block(state, data, 0xd2));
170 static GSM_Error GetModelName(GSM_Data *data, GSM_Statemachine *state)
172 dprintf("Getting model...\n");
173 return GetPhoneInfo(data, state);
176 static GSM_Error GetRevision(GSM_Data *data, GSM_Statemachine *state)
178 dprintf("Getting revision...\n");
179 return GetPhoneInfo(data, state);
182 static GSM_Error GetIMEI(GSM_Data *data, GSM_Statemachine *state)
184 unsigned char req[] = {FBUS_FRAME_HEADER, 0x01};
186 dprintf("Getting imei...\n");
187 if (SM_SendMessage(state, 4, 0x1b, req)!=GE_NONE) return GE_NOTREADY;
188 return SM_Block(state, data, 0x1b);
192 static GSM_Error GetBatteryLevel(GSM_Data *data, GSM_Statemachine *state)
194 unsigned char req[] = {FBUS_FRAME_HEADER, 0x02};
196 dprintf("Getting battery level...\n");
197 if (SM_SendMessage(state, 4, 0x17, req) != GE_NONE) return GE_NOTREADY;
198 return SM_Block(state, data, 0x17);
202 static GSM_Error Incoming0x17(int messagetype, unsigned char *message, int length, GSM_Data *data)
204 switch (message[3]) {
206 if (data->BatteryLevel) {
207 *(data->BatteryUnits) = GBU_Percentage;
208 *(data->BatteryLevel) = message[5];
209 dprintf("Battery level %f\n",*(data->BatteryLevel));
214 dprintf("Unknown subtype of type 0x17 (%d)\n", message[3]);
220 static GSM_Error GetRFLevel(GSM_Data *data, GSM_Statemachine *state)
222 unsigned char req[] = {FBUS_FRAME_HEADER, 0x81};
224 dprintf("Getting rf level...\n");
225 if (SM_SendMessage(state, 4, 0x0a, req) != GE_NONE) return GE_NOTREADY;
226 return SM_Block(state, data, 0x0a);
229 static GSM_Error Incoming0x0a(int messagetype, unsigned char *message, int length, GSM_Data *data)
231 switch (message[3]) {
234 *(data->RFUnits) = GRF_Percentage;
235 *(data->RFLevel) = message[4];
236 dprintf("RF level %f\n",*(data->RFLevel));
241 dprintf("Unknown subtype of type 0x0a (%d)\n", message[3]);
247 static GSM_Error GetMemoryStatus(GSM_Data *data, GSM_Statemachine *state)
249 unsigned char req[] = {FBUS_FRAME_HEADER, 0x03, 0x00, 0x00};
251 dprintf("Getting memory status...\n");
252 req[5] = GetMemoryType(data->MemoryStatus->MemoryType);
253 if (SM_SendMessage(state, 6, 0x03, req) != GE_NONE) return GE_NOTREADY;
254 return SM_Block(state, data, 0x03);
257 static GSM_Error Incoming0x03(int messagetype, unsigned char *message, int length, GSM_Data *data)
259 switch (message[3]) {
261 if (data->MemoryStatus) {
262 if (message[5] != 0xff) {
263 data->MemoryStatus->Used = (message[16] << 8) + message[17];
264 data->MemoryStatus->Free = ((message[14] << 8) + message[15]) - data->MemoryStatus->Used;
265 dprintf(_("Memory status - location = %d\n"), (message[8] << 8) + message[9]);
268 dprintf("Unknown error getting mem status\n");
269 return GE_NOTIMPLEMENTED;
276 dprintf("Unknown subtype of type 0x03 (%d)\n", message[3]);
282 static GSM_Error Identify(GSM_Data *data, GSM_Statemachine *state)
284 unsigned char req[] = { FBUS_FRAME_HEADER, 0x10 };
286 dprintf("Identifying...\n");
287 if (SM_SendMessage(state, 4, 0x64, req) != GE_NONE) return GE_NOTREADY;
288 SM_WaitFor(state, data, 0x64);
289 SM_Block(state, data, 0x64); /* waits for all requests */
290 SM_GetError(state, 0x64);
292 /* Check that we are back at state Initialised */
293 if (SM_Loop(state, 0) != Initialised) return GE_UNKNOWN;
297 static GSM_Error IncomingPhoneInfo(int messagetype, unsigned char *message, int length, GSM_Data *data)
300 #if defined WIN32 || !defined HAVE_SNPRINTF
301 sprintf(data->Imei, "%s", message + 4);
303 snprintf(data->Imei, GSM_MAX_IMEI_LENGTH, "%s", message + 4);
305 dprintf("Received imei %s\n", data->Imei);
308 #if defined WIN32 || !defined HAVE_SNPRINTF
309 sprintf(data->Model, "%s", message + 22);
311 snprintf(data->Model, GSM_MAX_MODEL_LENGTH, "%s", message + 22);
313 dprintf("Received model %s\n", data->Model);
315 if (data->Revision) {
316 #if defined WIN32 || !defined HAVE_SNPRINTF
317 sprintf(data->Revision, "%s", message + 7);
319 snprintf(data->Revision, GSM_MAX_REVISION_LENGTH, "%s", message + 7);
321 dprintf("Received revision %s\n", data->Revision);
324 dprintf(_("Message: Mobile phone identification received:\n"));
325 dprintf(_(" IMEI: %s\n"), data->Imei);
326 dprintf(_(" Model: %s\n"), data->Model);
327 dprintf(_(" Production Code: %s\n"), message + 31);
328 dprintf(_(" HW: %s\n"), message + 39);
329 dprintf(_(" Firmware: %s\n"), message + 44);
331 /* These bytes are probably the source of the "Accessory not connected"
332 messages on the phone when trying to emulate NCDS... I hope....
333 UPDATE: of course, now we have the authentication algorithm. */
334 dprintf(_(" Magic bytes: %02x %02x %02x %02x\n"), message[50], message[51], message[52], message[53]);
336 MagicBytes[0] = message[50];
337 MagicBytes[1] = message[51];
338 MagicBytes[2] = message[52];
339 MagicBytes[3] = message[53];
344 static GSM_Error IncomingModelInfo(int messagetype, unsigned char *message, int length, GSM_Data *data)
346 #if defined WIN32 || !defined HAVE_SNPRINTF
347 if (data->Model) sprintf(data->Model, "%s", message + 21);
348 if (data->Revision) sprintf(data->Revision, "SW%s", message + 5);
350 dprintf("%p %p %p\n", data, data->Model, data->Revision);
352 snprintf(data->Model, GSM_MAX_MODEL_LENGTH, "%s", message + 21);
353 data->Model[GSM_MAX_MODEL_LENGTH - 1] = 0;
355 if (data->Revision) {
356 snprintf(data->Revision, GSM_MAX_REVISION_LENGTH, "SW%s", message + 5);
357 data->Revision[GSM_MAX_REVISION_LENGTH - 1] = 0;
360 dprintf(_("Phone info:\n%s\n"), message + 4);
365 static int GetMemoryType(GSM_MemoryType memory_type)
369 switch (memory_type) {
371 result = P6100_MEMORY_MT;
374 result = P6100_MEMORY_ME;
377 result = P6100_MEMORY_SM;
380 result = P6100_MEMORY_FD;
383 result = P6100_MEMORY_ON;
386 result = P6100_MEMORY_EN;
389 result = P6100_MEMORY_DC;
392 result = P6100_MEMORY_RC;
395 result = P6100_MEMORY_MC;
398 result = P6100_MEMORY_XX;