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.1 2001/11/25 21:59:12 short
18 :pserver:cvs@pserver.samba.org:/cvsroot - gnokii - Sun Nov 25 22:56 CET 2001
20 Revision 1.8 2001/11/17 20:19:29 pkot
21 smslib cleanups, fixes and debugging
23 Revision 1.7 2001/11/17 16:44:07 pkot
24 Cleanup. Reading SMS for 6100 series. Not that it has some bugs more and does not support UDH yet
26 Revision 1.6 2001/11/15 12:15:04 pkot
27 smslib updates. begin work on sms in 6100 series
29 Revision 1.5 2001/11/15 12:12:34 pkot
30 7110 and 6110 series phones introduce as Nokia
32 Revision 1.4 2001/11/15 12:04:06 pkot
33 Faster initialization for 6100 series (don't check for dlr3 cable)
35 Revision 1.3 2001/08/17 00:01:53 pkot
36 Fixed a typo in 6100.c (me)
38 Revision 1.2 2001/08/09 12:34:34 pkot
39 3330 and 6250 support - I have no idea if it does work (mygnokii)
41 Revision 1.1 2001/07/09 23:55:35 pkot
42 Initial support for 6100 series in the new structure (me)
50 #define __phones_nk6100_c
52 #include "gsm-common.h"
53 #include "phones/generic.h"
54 #include "phones/nk6100.h"
55 #include "links/fbus.h"
56 #include "links/fbus-phonet.h"
57 #include "phones/nokia.h"
60 #define snprintf _snprintf
65 static unsigned char MagicBytes[4] = { 0x00, 0x00, 0x00, 0x00 };
67 static GSM_IncomingFunctionType IncomingFunctions[] = {
68 { 0x64, IncomingPhoneInfo },
69 { 0xd2, IncomingModelInfo },
70 { 0x14, IncomingSMS },
71 { 0x03, Incoming0x03 },
72 { 0x0a, Incoming0x0a },
73 { 0x17, Incoming0x17 },
77 GSM_Phone phone_nokia_6100 = {
80 /* Mobile phone information */
82 "6110|6130|6150|6190|5110|5130|5190|3210|3310|3330", /* Supported models */
85 GRF_Arbitrary, /* RF level units */
86 4, /* Max Battery Level */
87 0, /* Min Battery Level */
88 GBU_Arbitrary, /* Battery level units */
89 GDT_DateTime, /* Have date/time support */
90 GDT_TimeOnly, /* Alarm supports time only */
91 1, /* Alarms available - FIXME */
92 48, 84, /* Startup logo size - 7110 is fixed at init*/
93 14, 72, /* Op logo size */
94 14, 72 /* Caller logo size */
99 static GSM_Error Functions(GSM_Operation op, GSM_Data *data, GSM_Statemachine *state)
103 return Initialise(state);
105 return GetModelName(data, state);
106 case GOP_GetRevision:
107 return GetRevision(data, state);
109 return GetIMEI(data, state);
111 return Identify(data, state);
112 case GOP_GetBatteryLevel:
113 return GetBatteryLevel(data, state);
115 return GetRFLevel(data, state);
116 case GOP_GetMemoryStatus:
117 return GetMemoryStatus(data, state);
119 return GetSMSMessage(data, state);
121 return GE_NOTIMPLEMENTED;
125 /* static bool LinkOK = true; */
127 /* Initialise is the only function allowed to 'use' state */
128 static GSM_Error Initialise(GSM_Statemachine *state)
134 /* Copy in the phone info */
135 memcpy(&(state->Phone), &phone_nokia_6100, sizeof(GSM_Phone));
137 switch (state->Link.ConnectionType) {
139 err = FBUS_Initialise(&(state->Link), state, 0);
142 err = PHONET_Initialise(&(state->Link), state);
145 return GE_NOTSUPPORTED;
148 if (err != GE_NONE) {
149 dprintf("Error in link initialisation\n");
150 return GE_NOTSUPPORTED;
153 SM_Initialise(state);
155 /* Now test the link and get the model */
156 GSM_DataClear(&data);
158 if (state->Phone.Functions(GOP_GetModel, &data, state) != GE_NONE) return GE_NOTSUPPORTED;
162 static GSM_Error GetPhoneInfo(GSM_Data *data, GSM_Statemachine *state)
164 unsigned char req[] = { FBUS_FRAME_HEADER, 0x03, 0x00 };
166 dprintf("Getting phone info...\n");
167 if (SM_SendMessage(state, 5, 0xd1, req) != GE_NONE) return GE_NOTREADY;
168 return (SM_Block(state, data, 0xd2));
171 static GSM_Error GetModelName(GSM_Data *data, GSM_Statemachine *state)
173 dprintf("Getting model...\n");
174 return GetPhoneInfo(data, state);
177 static GSM_Error GetRevision(GSM_Data *data, GSM_Statemachine *state)
179 dprintf("Getting revision...\n");
180 return GetPhoneInfo(data, state);
183 static GSM_Error GetIMEI(GSM_Data *data, GSM_Statemachine *state)
185 unsigned char req[] = {FBUS_FRAME_HEADER, 0x01};
187 dprintf("Getting imei...\n");
188 if (SM_SendMessage(state, 4, 0x1b, req)!=GE_NONE) return GE_NOTREADY;
189 return SM_Block(state, data, 0x1b);
193 static GSM_Error GetBatteryLevel(GSM_Data *data, GSM_Statemachine *state)
195 unsigned char req[] = {FBUS_FRAME_HEADER, 0x02};
197 dprintf("Getting battery level...\n");
198 if (SM_SendMessage(state, 4, 0x17, req) != GE_NONE) return GE_NOTREADY;
199 return SM_Block(state, data, 0x17);
203 static GSM_Error Incoming0x17(int messagetype, unsigned char *message, int length, GSM_Data *data)
205 switch (message[3]) {
207 if (data->BatteryLevel) {
208 *(data->BatteryUnits) = GBU_Percentage;
209 *(data->BatteryLevel) = message[5];
210 dprintf("Battery level %f\n",*(data->BatteryLevel));
215 dprintf("Unknown subtype of type 0x17 (%d)\n", message[3]);
221 static GSM_Error GetRFLevel(GSM_Data *data, GSM_Statemachine *state)
223 unsigned char req[] = {FBUS_FRAME_HEADER, 0x81};
225 dprintf("Getting rf level...\n");
226 if (SM_SendMessage(state, 4, 0x0a, req) != GE_NONE) return GE_NOTREADY;
227 return SM_Block(state, data, 0x0a);
230 static GSM_Error Incoming0x0a(int messagetype, unsigned char *message, int length, GSM_Data *data)
232 switch (message[3]) {
235 *(data->RFUnits) = GRF_Percentage;
236 *(data->RFLevel) = message[4];
237 dprintf("RF level %f\n",*(data->RFLevel));
242 dprintf("Unknown subtype of type 0x0a (%d)\n", message[3]);
248 static GSM_Error GetMemoryStatus(GSM_Data *data, GSM_Statemachine *state)
250 unsigned char req[] = {FBUS_FRAME_HEADER, 0x03, 0x00, 0x00};
252 dprintf("Getting memory status...\n");
253 req[5] = GetMemoryType(data->MemoryStatus->MemoryType);
254 if (SM_SendMessage(state, 6, 0x03, req) != GE_NONE) return GE_NOTREADY;
255 return SM_Block(state, data, 0x03);
258 static GSM_Error Incoming0x03(int messagetype, unsigned char *message, int length, GSM_Data *data)
260 switch (message[3]) {
262 if (data->MemoryStatus) {
263 if (message[5] != 0xff) {
264 data->MemoryStatus->Used = (message[16] << 8) + message[17];
265 data->MemoryStatus->Free = ((message[14] << 8) + message[15]) - data->MemoryStatus->Used;
266 dprintf("Memory status - location = %d\n", (message[8] << 8) + message[9]);
269 dprintf("Unknown error getting mem status\n");
270 return GE_NOTIMPLEMENTED;
277 dprintf("Unknown subtype of type 0x03 (%d)\n", message[3]);
283 static GSM_Error Identify(GSM_Data *data, GSM_Statemachine *state)
285 unsigned char req[] = { FBUS_FRAME_HEADER, 0x10 };
287 dprintf("Identifying...\n");
288 PNOK_GetManufacturer(data->Manufacturer);
289 if (SM_SendMessage(state, 4, 0x64, req) != GE_NONE) return GE_NOTREADY;
290 SM_WaitFor(state, data, 0x64);
291 SM_Block(state, data, 0x64); /* waits for all requests */
292 SM_GetError(state, 0x64);
294 /* Check that we are back at state Initialised */
295 if (SM_Loop(state, 0) != Initialised) return GE_UNKNOWN;
299 static GSM_Error IncomingPhoneInfo(int messagetype, unsigned char *message, int length, GSM_Data *data)
302 #if defined WIN32 || !defined HAVE_SNPRINTF
303 sprintf(data->Imei, "%s", message + 4);
305 snprintf(data->Imei, GSM_MAX_IMEI_LENGTH, "%s", message + 4);
307 dprintf("Received imei %s\n", data->Imei);
310 #if defined WIN32 || !defined HAVE_SNPRINTF
311 sprintf(data->Model, "%s", message + 22);
313 snprintf(data->Model, GSM_MAX_MODEL_LENGTH, "%s", message + 22);
315 dprintf("Received model %s\n", data->Model);
317 if (data->Revision) {
318 #if defined WIN32 || !defined HAVE_SNPRINTF
319 sprintf(data->Revision, "%s", message + 7);
321 snprintf(data->Revision, GSM_MAX_REVISION_LENGTH, "%s", message + 7);
323 dprintf("Received revision %s\n", data->Revision);
326 dprintf("Message: Mobile phone identification received:\n");
327 dprintf(" IMEI: %s\n", data->Imei);
328 dprintf(" Model: %s\n", data->Model);
329 dprintf(" Production Code: %s\n", message + 31);
330 dprintf(" HW: %s\n", message + 39);
331 dprintf(" Firmware: %s\n", message + 44);
333 /* These bytes are probably the source of the "Accessory not connected"
334 messages on the phone when trying to emulate NCDS... I hope....
335 UPDATE: of course, now we have the authentication algorithm. */
336 dprintf(_(" Magic bytes: %02x %02x %02x %02x\n"), message[50], message[51], message[52], message[53]);
338 MagicBytes[0] = message[50];
339 MagicBytes[1] = message[51];
340 MagicBytes[2] = message[52];
341 MagicBytes[3] = message[53];
346 static GSM_Error IncomingModelInfo(int messagetype, unsigned char *message, int length, GSM_Data *data)
348 #if defined WIN32 || !defined HAVE_SNPRINTF
349 if (data->Model) sprintf(data->Model, "%s", message + 21);
350 if (data->Revision) sprintf(data->Revision, "SW%s", message + 5);
352 dprintf("%p %p %p\n", data, data->Model, data->Revision);
354 snprintf(data->Model, GSM_MAX_MODEL_LENGTH, "%s", message + 21);
355 data->Model[GSM_MAX_MODEL_LENGTH - 1] = 0;
357 if (data->Revision) {
358 snprintf(data->Revision, GSM_MAX_REVISION_LENGTH, "SW%s", message + 5);
359 data->Revision[GSM_MAX_REVISION_LENGTH - 1] = 0;
362 dprintf("Phone info:\n%s\n", message + 4);
367 static int GetMemoryType(GSM_MemoryType memory_type)
371 switch (memory_type) {
373 result = P6100_MEMORY_MT;
376 result = P6100_MEMORY_ME;
379 result = P6100_MEMORY_SM;
382 result = P6100_MEMORY_FD;
385 result = P6100_MEMORY_ON;
388 result = P6100_MEMORY_EN;
391 result = P6100_MEMORY_DC;
394 result = P6100_MEMORY_RC;
397 result = P6100_MEMORY_MC;
400 result = P6100_MEMORY_XX;
406 static GSM_Error GetSMSMessage(GSM_Data *data, GSM_Statemachine *state)
408 unsigned char req[] = { FBUS_FRAME_HEADER, 0x07, 0x02 /* Unknown */, 0x00 /* Location */, 0x01, 0x64};
410 req[5] = data->SMSMessage->Number;
412 if (SM_SendMessage(state, 8, 0x02, req) != GE_NONE) return GE_NOTREADY;
413 return SM_Block(state, data, 0x14);
416 static GSM_Error IncomingSMS(int messagetype, unsigned char *message, int length, GSM_Data *data)
420 switch (message[3]) {
421 /* save sms succeeded */
423 dprintf("Message stored at %d\n", message[5]);
425 /* save sms failed */
427 dprintf("SMS saving failed:\n");
428 switch (message[4]) {
430 dprintf("\tAll locations busy.\n");
431 return GE_MEMORYFULL;
433 dprintf("\tInvalid location!\n");
434 return GE_INVALIDSMSLOCATION;
436 dprintf("\tUnknown reason.\n");
441 for (i = 0; i < length; i ++)
442 if (isprint(message[i]))
443 dprintf("[%02x%c]", message[i], message[i]);
445 dprintf("[%02x ]", message[i]);
448 memset(data->SMSMessage, 0, sizeof(GSM_SMSMessage));
450 /* These offsets are 6210/7110 series specific */
451 /* Short Message status */
452 data->SMSMessage->Status = message[4];
453 dprintf("\tStatus: ");
454 switch (data->SMSMessage->Status) {
468 dprintf("UNKNOWN\n");
472 DecodePDUSMS(message + 5, data->SMSMessage, length);
475 /* read sms failed */
477 dprintf("SMS reading failed:\n");
478 switch (message[4]) {
480 dprintf("\tInvalid location!\n");
481 return GE_INVALIDSMSLOCATION;
483 dprintf("\tEmpty SMS location.\n");
484 return GE_EMPTYSMSLOCATION;
486 dprintf("\tUnknown reason.\n");
489 /* delete sms succeeded */
491 dprintf("Message: SMS deleted successfully.\n");
493 /* sms status succeded */
495 dprintf("Message: SMS Status Received\n");
496 dprintf("\tThe number of messages: %d\n", message[10]);
497 dprintf("\tUnread messages: %d\n", message[11]);
498 data->SMSStatus->Unread = message[11];
499 data->SMSStatus->Number = message[10];
501 /* sms status failed */
503 dprintf("Message: SMS Status error, probably not authorized by PIN\n");
504 return GE_INTERNALERROR;
507 dprintf("Unknown message.\n");