📄 nk2110.c
字号:
/* -*- linux-c -*- $Id: nk2110.c,v 1.37 2003/03/06 21:17:12 pkot Exp $ G N O K I I A Linux/Unix toolset and driver for Nokia mobile phones. This file is part of gnokii. Gnokii is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. Gnokii is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with gnokii; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Copyright (C) 2000-2002 Pavel Machek <pavel@ucw.cz> Notice that this code was (partly) converted to "new" structure, but it does not have code for bus separated. I think that separating it would be waste of effort... --pavel*/#ifndef WIN32#include <termios.h>#include <stdio.h>#include <stdlib.h>#include <unistd.h>#include <fcntl.h>#include <ctype.h>#include <signal.h>#include <sys/types.h>#include <sys/time.h>#include <sys/ioctl.h>#include <string.h>#include <pthread.h>#include <errno.h>#include <string.h>#undef DEBUG#include "config.h"#include "compat.h"#include "misc.h"#include "gnokii.h"#include "device.h"#include "phones/generic.h"#include "phones/nk2110.h"#include "phones/nokia.h"#define MYID 0x78#define ddprintf(x...)#define eprintf(x...) fprintf(stderr, x)#undef DEBUGstatic gn_error P2110_Functions(GSM_Operation op, GSM_Data *data, GSM_Statemachine *state);/* Global variables used by code in gsm-api.c to expose the functions supported by this model of phone. */bool N2110_LinkOK;static char PortDevice[GSM_MAX_DEVICE_NAME_LENGTH];static char *Revision = NULL, *RevisionDate = NULL, *Model = NULL, VersionInfo[64];#define INFO \{ \ "2110|2140|6080", /* Models */ \ 100, /* Max RF Level */ \ 0, /* Min RF Level */ \ GRF_Percentage, /* RF level units */ \ 100, /* Max Battery Level */ \ 0, /* Min Battery Level */ \ GBU_Percentage, /* Battery level units */ \ GDT_None, /* No date/time support */ \ GDT_None, /* No alarm support */ \ 0, /* Max alarms = 0 */ \ 0, 0, /* Startup logo size */ \ 0, 0, /* Op logo size */ \ 0, 0 /* Caller logo size */ \}static const SMSMessage_Layout nk2110_deliver = { true, /* Is the SMS type supported */ /* Last ASCIIZ string */ -1, false, false, /* SMSC */ -1, -1, -1, -1, -1, -1, -1, -1, 13, 5, -1, -1, -1, -1, /* Validity */ /* ASCIIZ second from the end */ -1, false, false, /* Remote Number */ 6, -1, /* Time */ 1, 3, 14, false /* Nonstandart fields, User Data */};GSM_Information N2110_Information = INFO;GSM_Phone phone_nokia_2110 = { NULL, NULL, INFO, P2110_Functions, NULL};/* Local variables */static volatile bool RequestTerminate;static u8 TXPacketNumber = 0x01;#define MAX_MODEL_LENGTH 16static volatile unsigned char PacketData[10240];static volatile bool ACKOK = false, PacketOK = false;static volatile int SMSpos = 0;static volatile unsigned char SMSData[10240];static long long LastChar = 0;static long longGetTime(void){ struct timeval tv; gettimeofday(&tv, NULL); return (long long) tv.tv_sec * 1000000 + tv.tv_usec;}static void SigHandler(int status);#define POLLIT do { SigHandler(0); } while (0)static voidyield(void){ usleep(5000);}static voidWait(long long from, int msec){ while (GetTime() < from + ((long long) msec)*1000) { yield(); POLLIT; }}static voidWait2(long long from, int msec){ while (GetTime() < from + ((long long) msec)*1000) { yield(); }}#define msleep(x) do { usleep(x*1000); } while (0)#define msleep_poll(x) do { Wait(GetTime(), x); } while (0)#define waitfor(condition, maxtime) \do { \ long long limit = GetTime() + maxtime*1000; \ if (!maxtime) limit = 0x7fffffffffffffffULL; \ while ((!(condition)) && (limit > GetTime())) { \ yield(); \ POLLIT; \ } \ if (!(limit > GetTime())) eprintf("???? TIMEOUT!"); \} while(0)/* Checksum calculation */static u8GetChecksum( u8 * packet, int len ){ u8 checksum = 0; unsigned int i; for( i = 0; i < len; i++ ) checksum ^= packet[i]; /* calculate checksum */ return checksum;}/* --------------- */static int xread(unsigned char *d, int len){ int res; while (len) { res = device_read(d, len); if (res == -1) { if (errno != EAGAIN) { dprintf("I/O error : %m?!\n"); return -1; } else device_select(NULL); } else { d += res; len -= res; dprintf("(%d)", len); } } return 0;}static int xwrite(unsigned char *d, int len){ int res; while (len) { res = device_write(d, len); if (res == -1) { if (errno != EAGAIN) { dprintf("I/O error : %m?!\n"); return -1; } } else { d += res; len -= res; dprintf("<%d>", len); } } return 0;}/* --------------------------- */static gn_errorSendFrame( u8 *buffer, u8 command, u8 length ){ u8 pkt[10240], pkt2[10240]; int current = 0; pkt[current++] = 0x00; /* Construct the header. */ pkt[current++] = MYID; pkt[current++] = length; /* Set data size */ pkt[current++] = command; memcpy( pkt + current, buffer, length ); /* Copy in data. */ current += length; pkt[current++] = TXPacketNumber; /* Set packet number */ pkt[current++] = GetChecksum( pkt, current); /* Calculate and set checksum */#ifdef DEBUG { int i; u8 b; fprintf( stderr, _("PC : ") ); for( i = 0; i < current; i++ ) { b = pkt[i]; fprintf( stderr, "[%02X %c]", b, b > 0x20 ? b : '.' ); } fprintf( stderr, "\n" ); }#endif /* DEBUG */ /* Send it out... */ ddprintf("("); Wait2(LastChar, 3); /* I should put my messages at least 2msec apart... */ ddprintf(")"); dprintf("writing..."); LastChar = GetTime(); if (xwrite(pkt, current) == -1) return GN_ERR_INTERNALERROR); if (xread(pkt2, current) == -1) return GN_ERR_INTERNALERROR); dprintf("echook"); if (memcmp(pkt, pkt2, current)) { eprintf("Bad echo?!"); msleep(1000); return GN_ERR_TIMEOUT); } return GN_ERR_NONE);}static gn_errorSendCommand( u8 *buffer, u8 command, u8 length ){ int time, retries = 10; char pkt[10240];// msleep(2); while ((time = device_read(pkt, 10240)) != -1) { int j; char b; dprintf("Spurious? (%d)", time); dprintf( _("Phone: ") ); for( j = 0; j < time; j++ ) { b = pkt[j]; dprintf( "[%02X %c]", b, b >= 0x20 ? b : '.' ); } msleep(2); } ACKOK = false; time = 30; while (retries--) { long long now; SendFrame(buffer, command, length); now = GetTime(); while ((GetTime() - now) < time*1000) { if (ACKOK) return GN_ERR_NONE; yield(); POLLIT; } time = 50; /* 5 seems to be enough */ dprintf("[resend]"); } eprintf("Command not okay after 10 retries!\n"); return GN_ERR_BUSY;}/* Applications should call Terminate to close the serial port. */static voidTerminate(void){ /* Request termination of thread */ RequestTerminate = true; device_close();}static gn_errorSMS(GSM_SMSMessage *message, int command){ u8 pkt[] = { 0x10, 0x02, 0, 0 }; SMSpos = 0; memset((void *) &SMSData[0], 0, 255); PacketOK = false; pkt[1] = command; pkt[2] = 1; /* == LM_SMS_MEM_TYPE_DEFAULT or LM_SMS_MEM_TYPE_SIM or LM_SMS_MEM_TYPE_ME */ pkt[3] = message->Number; SendCommand(pkt, LM_SMS_COMMAND, sizeof(pkt)); msleep_poll(300); /* We have to keep acknowledning phone's data */ waitfor(PacketOK, 1000); if (!PacketOK) { eprintf("SMS: No reply came within second!\n"); } if (PacketData[3] != LM_SMS_EVENT) { eprintf("Something is very wrong with SMS\n"); return GN_ERR_BUSY; /* FIXME */ } if ((SMSData[2]) && (SMSData[2] != message->Number)) { eprintf("Wanted message @%d, got message at @%d!\n", message->Number, SMSData[2]); return GN_ERR_BUSY; } SMSpos = 0; return GN_ERR_NONE);}static gn_errorDecodeIncomingSMS(GSM_SMSMessage *m){ gn_error error; int len, i; error = GN_ERR_NONE;/* Should be moved to gsm-sms.c */ /* SMSData[0] == Memory type */ ddprintf("Status: " ); switch (SMSData[3]) { case 7: m->Type = SMS_Submit; /* m->Status = GSS_NOTSENTREAD; */ ddprintf("not sent\n"); break; case 5: m->Type = SMS_Submit; /* m->Status = GSS_SENTREAD; */ ddprintf("sent\n"); break; case 3: m->Type = SMS_Deliver; /* m->Status = GSS_NOTSENTREAD; */ ddprintf("not read\n"); break; case 1: m->Type = SMS_Deliver; /* m->Status = GSS_SENTREAD; */ ddprintf("read\n"); break; } UnpackDateTime((u8 *)SMSData+7, &m->Time); m->Length = len = SMSData[14]; ddprintf("%d bytes: ", len ); for (i = 0; i<len; i++) ddprintf("%c", SMSData[15+i]); ddprintf("\n"); if (len>160) eprintf("Magic not allowed\n"); memset(m->UserData[0].u.Text, 0, 161); strncpy(m->UserData[0].u.Text, (void *) &SMSData[15], len); ddprintf("Text is %s\n", m->UserData[0].u.Text); /* Originator address is at 15+i, followed by message center addres (?) */ { char *s = (char *) &SMSData[15+i]; /* We discard volatile. Make compiler quiet. */ strcpy(m->RemoteNumber.number, s); s+=strlen(s)+1; strcpy(m->MessageCenter.Number, s); ddprintf("Sender = %s, MessageCenter = %s\n", m->Sender, m->MessageCenter.Name); } m->MessageCenter.No = 0; strcpy(m->MessageCenter.Name, "(unknown)"); m->UDH_No = 0; return error;}static gn_errorGetSMSMessage(GSM_Data *data){ GSM_SMSMessage *m = data->SMSMessage; if (m->Number > 10) return GN_ERR_INVALIDSMSLOCATION; if (SMS(m, LM_SMS_READ_STORED_DATA) != GN_ERR_NONE) return GN_ERR_BUSY; /* FIXME */ ddprintf("Have message?\n"); if (SMSData[0] != LM_SMS_FORWARD_STORED_DATA) { ddprintf("No sms there? (%x/%d)\n", SMSData[0], SMSpos); return GN_ERR_EMPTYSMSLOCATION; } data->RawData->Length = 180; data->RawData->Data = calloc(data->RawData->Length, 1); memcpy(data->RawData->Data, (void *)SMSData+1, 180); if (ParseSMS(data, 0)) eprintf("Error in parsesms?\n"); msleep_poll(1000); /* If phone lost our ack, it might retransmit data */ return GN_ERR_NONE);}#if 0static gn_errorSendSMSMessage(GSM_SMSMessage *m){ if (m->Number > 10)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -