r1987 - in trunk/src/host/qemu-neo1973: . gnokiigsm hw

andrew at sita.openmoko.org andrew at sita.openmoko.org
Thu May 17 02:24:58 CEST 2007


Author: andrew
Date: 2007-05-17 02:24:48 +0200 (Thu, 17 May 2007)
New Revision: 1987

Added:
   trunk/src/host/qemu-neo1973/gnokiigsm/
   trunk/src/host/qemu-neo1973/gnokiigsm/at-emulator.c
   trunk/src/host/qemu-neo1973/gnokiigsm/at-emulator.h
   trunk/src/host/qemu-neo1973/gnokiigsm/bitmaps.h
   trunk/src/host/qemu-neo1973/gnokiigsm/call.h
   trunk/src/host/qemu-neo1973/gnokiigsm/common.h
   trunk/src/host/qemu-neo1973/gnokiigsm/compat.h
   trunk/src/host/qemu-neo1973/gnokiigsm/data.h
   trunk/src/host/qemu-neo1973/gnokiigsm/datapump.c
   trunk/src/host/qemu-neo1973/gnokiigsm/datapump.h
   trunk/src/host/qemu-neo1973/gnokiigsm/device.h
   trunk/src/host/qemu-neo1973/gnokiigsm/encoding.h
   trunk/src/host/qemu-neo1973/gnokiigsm/error.h
   trunk/src/host/qemu-neo1973/gnokiigsm/gnokii-internal.h
   trunk/src/host/qemu-neo1973/gnokiigsm/gnokii.h
   trunk/src/host/qemu-neo1973/gnokiigsm/misc.h
   trunk/src/host/qemu-neo1973/gnokiigsm/networks.h
   trunk/src/host/qemu-neo1973/gnokiigsm/ringtones.h
   trunk/src/host/qemu-neo1973/gnokiigsm/rlp-common.c
   trunk/src/host/qemu-neo1973/gnokiigsm/rlp-common.h
   trunk/src/host/qemu-neo1973/gnokiigsm/rlp-crc24.c
   trunk/src/host/qemu-neo1973/gnokiigsm/rlp-crc24.h
   trunk/src/host/qemu-neo1973/gnokiigsm/sms.h
   trunk/src/host/qemu-neo1973/gnokiigsm/statemachine.h
   trunk/src/host/qemu-neo1973/gnokiigsm/virtmodem.c
   trunk/src/host/qemu-neo1973/gnokiigsm/virtmodem.h
   trunk/src/host/qemu-neo1973/gnokiigsm/wappush.h
Modified:
   trunk/src/host/qemu-neo1973/Makefile.target
   trunk/src/host/qemu-neo1973/configure
   trunk/src/host/qemu-neo1973/hw/modem.c
   trunk/src/host/qemu-neo1973/hw/s3c2410.c
Log:
First go at the GSM modem emulator - for the moment uses code from 'gnokii' AT interpreter (dialing, SMS, RLP, ringtones, bitmaps but no GPRS).
Fix S3C-UART FIFO mode.


Modified: trunk/src/host/qemu-neo1973/Makefile.target
===================================================================
--- trunk/src/host/qemu-neo1973/Makefile.target	2007-05-16 22:38:21 UTC (rev 1986)
+++ trunk/src/host/qemu-neo1973/Makefile.target	2007-05-17 00:24:48 UTC (rev 1987)
@@ -420,6 +420,11 @@
 VL_OBJS += pcnet.o
 VL_OBJS += rtl8139.o
 
+# GSM modem
+GNOKIIGSM_OBJS+=virtmodem.o at-emulator.o datapump.o rlp-common.o rlp-crc24.o
+GSM_CPPFLAGS=-I$(SRC_PATH)/gnokiigsm
+GSM_OBJS=$(addprefix gnokiigsm/, $(GNOKIIGSM_OBJS))
+
 ifeq ($(TARGET_BASE_ARCH), i386)
 # Hardware support
 VL_OBJS+= ide.o pckbd.o ps2.o vga.o $(SOUND_HW) dma.o $(AUDIODRV)
@@ -463,8 +468,9 @@
 VL_OBJS+= pxa2xx_lcd.o pxa2xx_mmci.o pxa2xx_pcmcia.o max111x.o max7310.o
 VL_OBJS+= spitz.o ads7846.o ide.o serial.o nand.o $(AUDIODRV) wm8750.o wm8753.o
 VL_OBJS+= s3c2410.o s3c24xx_gpio.o s3c24xx_lcd.o s3c24xx_mmci.o s3c24xx_rtc.o
-VL_OBJS+= s3c24xx_udc.o neo1973.o pcf5060x.o jbt6k74.o modem.o
-CPPFLAGS += -DHAS_AUDIO
+VL_OBJS+= s3c24xx_udc.o neo1973.o pcf5060x.o jbt6k74.o
+VL_OBJS+= $(GSM_OBJS) modem.o
+CPPFLAGS+= -DHAS_AUDIO $(GSM_CPPFLAGS)
 endif
 ifeq ($(TARGET_BASE_ARCH), sh4)
 VL_OBJS+= shix.o sh7750.o sh7750_regnames.o tc58128.o

Modified: trunk/src/host/qemu-neo1973/configure
===================================================================
--- trunk/src/host/qemu-neo1973/configure	2007-05-16 22:38:21 UTC (rev 1986)
+++ trunk/src/host/qemu-neo1973/configure	2007-05-17 00:24:48 UTC (rev 1987)
@@ -928,6 +928,9 @@
 if test "$target_user_only" = "no" ; then
   mkdir -p $target_dir/slirp
 fi
+if test "$target" = "arm-softmmu" ; then
+  mkdir -p $target_dir/gnokiigsm
+fi
 
 #
 # don't use ln -sf as not all "ln -sf" over write the file/link

Added: trunk/src/host/qemu-neo1973/gnokiigsm/at-emulator.c
===================================================================
--- trunk/src/host/qemu-neo1973/gnokiigsm/at-emulator.c	2007-05-16 22:38:21 UTC (rev 1986)
+++ trunk/src/host/qemu-neo1973/gnokiigsm/at-emulator.c	2007-05-17 00:24:48 UTC (rev 1987)
@@ -0,0 +1,1178 @@
+/*
+
+  $Id: at-emulator.c,v 1.45 2006/10/03 21:26:37 pkot Exp $
+
+  G N O K I I
+
+  A Linux/Unix toolset and driver for the 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) 1999-2000  Hugh Blemings & Pavel Janík ml.
+  Copyright (C) 2001-2004  Pawel Kot
+  Copyright (C) 2002-2004  BORBELY Zoltan
+
+  This file provides a virtual modem or "AT" interface to the GSM phone by
+  calling code in gsm-api.c. Inspired by and in places copied from the Linux
+  kernel AT Emulator IDSN code by Fritz Elfert and others.
+
+*/
+
+#include <stdio.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <signal.h>
+#include <grp.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <time.h>
+#include <ctype.h>
+#include <termios.h>
+
+#include "misc.h"
+#include "gnokii.h"
+#include "compat.h"
+#include "at-emulator.h"
+#include "datapump.h"
+
+#define MAX_LINE_LENGTH 256
+
+#define	MAX_CMD_BUFFERS	(2)
+#define	CMD_BUFFER_LENGTH (100)
+
+/* Definition of some special Registers of AT-Emulator, pinched in
+   part from ISDN driver in Linux kernel */
+#define REG_RINGATA   0
+#define REG_RINGCNT   1
+#define REG_ESC       2
+#define REG_CR        3
+#define REG_LF        4
+#define REG_BS        5
+#define	S22          22
+#define S35          35
+#define REG_CTRLZ   100
+#define REG_ESCAPE  101
+
+#define REG_QUIET    14
+#define BIT_QUIET     4
+#define REG_VERBOSE  14
+#define BIT_VERBOSE   8
+#define REG_ECHO     14
+#define BIT_ECHO      2
+
+
+#define	MAX_MODEM_REGISTERS	102
+
+/* Message format definitions */
+#define PDU_MODE      0
+#define TEXT_MODE     1
+#define INTERACT_MODE 2
+
+/* Global variables */
+bool gn_atem_initialised = false;	/* Set to true once initialised */
+extern bool CommandMode;
+extern int ConnectCount;
+
+struct gn_statemachine *sm;
+gn_data data;
+
+static gn_sms sms;
+static gn_call_info callinfo;
+static 	char imei[64], model[64], revision[64], manufacturer[64];
+
+/* Local variables */
+static int	PtyRDFD;	/* File descriptor for reading and writing to/from */
+static int	PtyWRFD;	/* pty interface - only different in debug mode. */
+
+static u8	ModemRegisters[MAX_MODEM_REGISTERS];
+static char	CmdBuffer[MAX_CMD_BUFFERS][CMD_BUFFER_LENGTH];
+static int	CurrentCmdBuffer;
+static int	CurrentCmdBufferIndex;
+static int	IncomingCallNo;
+static int     MessageFormat;          /* Message Format (text or pdu) */
+static int	CallerIDMode;
+
+	/* Current command parser */
+static void 	(*Parser)(char *); /* Current command parser */
+/* void 	(*Parser)(char *) = gn_atem_at_parse; */
+
+static gn_memory_type 	SMSType;
+static int 	SMSNumber;
+
+/* If initialised in debug mode, stdin/out is used instead
+   of ptys for interface. */
+bool gn_atem_initialise(int read_fd, int write_fd, struct gn_statemachine *vmsm)
+{
+	PtyRDFD = read_fd;
+	PtyWRFD = write_fd;
+
+	gn_data_clear(&data);
+	memset(&sms, 0, sizeof(sms));
+	memset(&callinfo, 0, sizeof(callinfo));
+
+	data.sms = &sms;
+	data.call_info = &callinfo;
+	data.manufacturer = manufacturer;
+	data.model = model;
+	data.revision = revision;
+	data.imei = imei;
+
+	sm = vmsm;
+
+	/* Initialise command buffer variables */
+	CurrentCmdBuffer = 0;
+	CurrentCmdBufferIndex = 0;
+
+	/* Initialise registers */
+	gn_atem_registers_init();
+
+	/* Initial parser is AT routine */
+	Parser = gn_atem_at_parse;
+
+	/* Setup defaults for AT*C interpreter. */
+	SMSNumber = 1;
+	SMSType = GN_MT_ME;
+
+	/* Default message format is PDU */
+	MessageFormat = PDU_MODE;
+
+	/* Set the call passup so that we get notified of incoming calls */
+	data.call_notification = gn_atem_call_passup;
+	gn_sm_functions(GN_OP_SetCallNotification, &data, sm);
+
+	/* query model, revision and imei */
+	if (gn_sm_functions(GN_OP_Identify, &data, sm) != GN_ERR_NONE) return false;
+
+	/* We're ready to roll... */
+	gn_atem_initialised = true;
+	return (true);
+}
+
+
+/* Initialise the "registers" used by the virtual modem. */
+void	gn_atem_registers_init(void)
+{
+	memset(ModemRegisters, 0, sizeof(ModemRegisters));
+
+	ModemRegisters[REG_RINGATA] = 0;
+	ModemRegisters[REG_RINGCNT] = 0;
+	ModemRegisters[REG_ESC] = '+';
+	ModemRegisters[REG_CR] = 13;
+	ModemRegisters[REG_LF] = 10;
+	ModemRegisters[REG_BS] = 8;
+	ModemRegisters[S35] = 7;
+	ModemRegisters[REG_ECHO] |= BIT_ECHO;
+	ModemRegisters[REG_VERBOSE] |= BIT_VERBOSE;
+	ModemRegisters[REG_CTRLZ] = 26;
+	ModemRegisters[REG_ESCAPE] = 27;
+
+	CallerIDMode = 0;
+}
+
+
+static void  gn_atem_hangup_phone(void)
+{
+	if (IncomingCallNo > 0) {
+		rlp_user_request_set(Disc_Req, true);
+		gn_sm_loop(10, sm);
+	}
+	if (IncomingCallNo > 0) {
+		data.call_info->call_id = IncomingCallNo;
+		gn_sm_functions(GN_OP_CancelCall, &data, sm);
+		IncomingCallNo = -1;
+	}
+	dp_Initialise(PtyRDFD, PtyWRFD);
+}
+
+
+static void  gn_atem_answer_phone(void)
+{
+	/* For now we'll also initialise the datapump + rlp code again */
+	dp_Initialise(PtyRDFD, PtyWRFD);
+	data.call_notification = dp_CallPassup;
+	gn_sm_functions(GN_OP_SetCallNotification, &data, sm);
+	data.call_info->call_id = IncomingCallNo;
+	gn_sm_functions(GN_OP_AnswerCall, &data, sm);
+	CommandMode = false;
+}
+
+
+/* This gets called to indicate an incoming call */
+void gn_atem_call_passup(gn_call_status CallStatus, gn_call_info *CallInfo, struct gn_statemachine *state)
+{
+	dprintf("gn_atem_call_passup called with %d\n", CallStatus);
+
+	switch (CallStatus) {
+	case GN_CALL_Incoming:
+		gn_atem_modem_result(MR_RING);
+		IncomingCallNo = CallInfo->call_id;
+		ModemRegisters[REG_RINGCNT]++;
+		gn_atem_cid_out(CallInfo);
+		if (ModemRegisters[REG_RINGATA] != 0) gn_atem_answer_phone();
+		break;
+	case GN_CALL_LocalHangup:
+	case GN_CALL_RemoteHangup:
+		IncomingCallNo = -1;
+		break;
+	default:
+		break;
+	}
+}
+
+/* This gets called to output caller id info of incoming call */
+void gn_atem_cid_out(gn_call_info *CallInfo)
+{
+	struct tm *now;
+	time_t nowh;
+	char buf[14]; /* 7 for "DATE = " + 4 digits + \n + \r + \0 */
+
+	nowh = time(NULL);
+	now = localtime(&nowh);
+
+	switch (CallerIDMode) {
+	case 0:	/* no output */
+		break;
+	case 1: /* formatted CID */
+		snprintf(buf, sizeof(buf), "DATE = %02d%02d\r\n", now->tm_mon + 1, now->tm_mday);
+		gn_atem_string_out(buf);
+
+		snprintf(buf, sizeof(buf), "TIME = %02d%02d\r\n", now->tm_hour, now->tm_min);
+		gn_atem_string_out(buf);
+
+		/* TO DO: handle P and O numbers */
+		gn_atem_string_out("NMBR = ");
+		gn_atem_string_out(1 + CallInfo->number); /* skip leading "+" */
+		gn_atem_string_out("\r\nNAME = ");
+		gn_atem_string_out(CallInfo->name);
+		gn_atem_string_out("\r\n");
+
+		/* FIX ME: do a real emulation of rings after the first one (at a lower level than this) */
+		gn_atem_modem_result(MR_RING);
+
+		break;
+
+	}
+}
+
+/* Handler called when characters received from serial port.
+   calls state machine code to process it. */
+void	gn_atem_incoming_data_handle(const char *buffer, int length)
+{
+	int count;
+	unsigned char out_buf[3];
+
+	for (count = 0; count < length ; count++) {
+
+		/* If it's a command terminator character, parse what
+		   we have so far then go to next buffer. */
+		if (buffer[count] == ModemRegisters[REG_CR] ||
+		    buffer[count] == ModemRegisters[REG_LF] ||
+		    buffer[count] == ModemRegisters[REG_CTRLZ] ||
+		    buffer[count] == ModemRegisters[REG_ESCAPE]) {
+
+			/* Echo character if appropriate. */
+			if (buffer[count] == ModemRegisters[REG_CR] &&
+				(ModemRegisters[REG_ECHO] & BIT_ECHO)) {
+				gn_atem_string_out("\r\n");
+			}
+
+			/* Save CTRL-Z and ESCAPE for the parser */
+			if (buffer[count] == ModemRegisters[REG_CTRLZ] ||
+			    buffer[count] == ModemRegisters[REG_ESCAPE])
+				CmdBuffer[CurrentCmdBuffer][CurrentCmdBufferIndex++] = buffer[count];
+
+			CmdBuffer[CurrentCmdBuffer][CurrentCmdBufferIndex] = 0x00;
+
+			Parser(CmdBuffer[CurrentCmdBuffer]);
+
+			CurrentCmdBuffer++;
+			if (CurrentCmdBuffer >= MAX_CMD_BUFFERS) {
+				CurrentCmdBuffer = 0;
+			}
+			CurrentCmdBufferIndex = 0;
+
+		} else if (buffer[count] == ModemRegisters[REG_BS]) {
+			if (CurrentCmdBufferIndex > 0) {
+				/* Echo character if appropriate. */
+				if (ModemRegisters[REG_ECHO] & BIT_ECHO) {
+					gn_atem_string_out("\b \b");
+				}
+
+				CurrentCmdBufferIndex--;
+			}
+		} else {
+			/* Echo character if appropriate. */
+			if (ModemRegisters[REG_ECHO] & BIT_ECHO) {
+				out_buf[0] = buffer[count];
+				out_buf[1] = 0;
+				gn_atem_string_out((char *)out_buf);
+			}
+
+			/* Collect it to command buffer */
+			CmdBuffer[CurrentCmdBuffer][CurrentCmdBufferIndex++] = buffer[count];
+			if (CurrentCmdBufferIndex >= CMD_BUFFER_LENGTH) {
+				CurrentCmdBufferIndex = CMD_BUFFER_LENGTH;
+			}
+		}
+	}
+}
+
+
+/* Parser for standard AT commands.  cmd_buffer must be null terminated. */
+void	gn_atem_at_parse(char *cmd_buffer)
+{
+	char *buf;
+	int regno, val;
+	char str[256];
+
+	if (!cmd_buffer[0]) return;
+
+	if (strncasecmp (cmd_buffer, "AT", 2) != 0) {
+		gn_atem_modem_result(MR_ERROR);
+		return;
+	}
+
+	for (buf = &cmd_buffer[2]; *buf;) {
+		switch (toupper(*buf)) {
+
+		case 'Z':
+			/* Reset modem */
+			buf++;
+			switch (gn_atem_num_get(&buf)) {
+			case -1:
+			case 0:	/* reset and load stored profile 0 */
+			case 1:	/* reset and load stored profile 1 */
+				gn_atem_hangup_phone();
+				gn_atem_registers_init();
+				break;
+			default:
+				gn_atem_modem_result(MR_ERROR);
+				return;
+			}
+			break;
+
+		case 'A':
+		        /* Answer call */
+			buf++;
+			gn_atem_answer_phone();
+			return;
+			break;
+
+		case 'D':
+			/* Dial Data :-) */
+			/* FIXME - should parse this better */
+			/* For now we'll also initialise the datapump + rlp code again */
+			dp_Initialise(PtyRDFD, PtyWRFD);
+			buf++;
+			if (toupper(*buf) == 'T' || toupper(*buf) == 'P') buf++;
+			while (*buf == ' ') buf++;
+			data.call_notification = dp_CallPassup;
+			gn_sm_functions(GN_OP_SetCallNotification, &data, sm);
+			snprintf(data.call_info->number, sizeof(data.call_info->number), "%s", buf);
+			if (ModemRegisters[S35] == 0)
+				data.call_info->type = GN_CALL_DigitalData;
+			else
+				data.call_info->type = GN_CALL_NonDigitalData;
+			data.call_info->send_number = GN_CALL_Default;
+			CommandMode = false;
+			if (gn_sm_functions(GN_OP_MakeCall, &data, sm) != GN_ERR_NONE) {
+				CommandMode = true;
+				dp_CallPassup(GN_CALL_RemoteHangup, NULL, NULL);
+			} else {
+				IncomingCallNo = data.call_info->call_id;
+				gn_sm_loop(10, sm);
+			}
+			return;
+			break;
+
+		case 'H':
+			/* Hang Up */
+			buf++;
+			switch (gn_atem_num_get(&buf)) {
+			case -1:
+			case 0:	/* hook off the phone */
+				gn_atem_hangup_phone();
+				break;
+			case 1:	/* hook on the phone */
+				break;
+			default:
+				gn_atem_modem_result(MR_ERROR);
+				return;
+			}
+			break;
+
+		case 'S':
+			/* Change registers */
+			buf++;
+			regno = gn_atem_num_get(&buf);
+			if (regno < 0 || regno >= MAX_MODEM_REGISTERS) {
+				gn_atem_modem_result(MR_ERROR);
+				return;
+			}
+			if (*buf == '=') {
+				buf++;
+				val = gn_atem_num_get(&buf);
+				if (val < 0 || val > 255) {
+					gn_atem_modem_result(MR_ERROR);
+					return;
+				}
+				ModemRegisters[regno] = val;
+			} else if (*buf == '?') {
+				buf++;
+				snprintf(str, sizeof(str), "%d\r\n", ModemRegisters[regno]);
+				gn_atem_string_out(str);
+			} else {
+				gn_atem_modem_result(MR_ERROR);
+				return;
+			}
+			break;
+
+		case 'E':
+		        /* E - Turn Echo on/off */
+			buf++;
+			switch (gn_atem_num_get(&buf)) {
+			case -1:
+			case 0:
+				ModemRegisters[REG_ECHO] &= ~BIT_ECHO;
+				break;
+			case 1:
+				ModemRegisters[REG_ECHO] |= BIT_ECHO;
+				break;
+			default:
+				gn_atem_modem_result(MR_ERROR);
+				return;
+			}
+			break;
+
+		case 'Q':
+		        /* Q - Turn Quiet on/off */
+			buf++;
+			switch (gn_atem_num_get(&buf)) {
+			case -1:
+			case 0:
+				ModemRegisters[REG_QUIET] &= ~BIT_QUIET;
+				break;
+			case 1:
+				ModemRegisters[REG_QUIET] |= BIT_QUIET;
+				break;
+			default:
+				gn_atem_modem_result(MR_ERROR);
+				return;
+			}
+			break;
+
+		case 'V':
+		        /* V - Turn Verbose on/off */
+			buf++;
+			switch (gn_atem_num_get(&buf)) {
+			case -1:
+			case 0:
+				ModemRegisters[REG_VERBOSE] &= ~BIT_VERBOSE;
+				break;
+			case 1:
+				ModemRegisters[REG_VERBOSE] |= BIT_VERBOSE;
+				break;
+			default:
+				gn_atem_modem_result(MR_ERROR);
+				return;
+			}
+			break;
+
+		case 'X':
+		        /* X - Set verbosity of the result messages */
+			buf++;
+			switch (gn_atem_num_get(&buf)) {
+			case -1:
+			case 0: val = 0x00; break;
+			case 1: val = 0x40; break;
+			case 2: val = 0x50; break;
+			case 3: val = 0x60; break;
+			case 4: val = 0x70; break;
+			case 5: val = 0x10; break;
+			default:
+				gn_atem_modem_result(MR_ERROR);
+				return;
+			}
+			ModemRegisters[S22] = (ModemRegisters[S22] & 0x8f) | val;
+			break;
+
+		case 'I':
+		        /* I - info */
+			buf++;
+			switch (gn_atem_num_get(&buf)) {
+			case -1:
+			case 0:	/* terminal id */
+				snprintf(str, sizeof(str), "%d\r\n", ModemRegisters[39]);
+				gn_atem_string_out(str);
+				break;
+			case 1:	/* serial number (IMEI) */
+				snprintf(str, sizeof(str), "%s\r\n", imei);
+				gn_atem_string_out(str);
+				break;
+			case 2: /* phone revision */
+				snprintf(str, sizeof(str), "%s\r\n", revision);
+				gn_atem_string_out(str);
+				break;
+			case 3: /* modem revision */
+				gn_atem_string_out(VERSION "\r\n");
+				break;
+			case 4: /* OEM string */
+				snprintf(str, sizeof(str), "%s %s\r\n", manufacturer, model);
+				gn_atem_string_out(str);
+				break;
+			default:
+				gn_atem_modem_result(MR_ERROR);
+				return;
+			}
+			break;
+
+		  /* Handle AT* commands (Nokia proprietary I think) */
+		case '*':
+			buf++;
+			if (!strcasecmp(buf, "NOKIATEST")) {
+				gn_atem_modem_result(MR_OK); /* FIXME? */
+				return;
+			} else {
+				if (!strcasecmp(buf, "C")) {
+					gn_atem_modem_result(MR_OK);
+					Parser = gn_atem_sms_parse;
+					return;
+				}
+			}
+			break;
+
+		/* + is the precursor to another set of commands */
+		case '+':
+			buf++;
+			switch (toupper(*buf)) {
+			case 'C':
+				buf++;
+				/* Returns true if error occured */
+				if (gn_atem_command_plusc(&buf) == true) {
+					gn_atem_modem_result(MR_ERROR);
+					return;
+				}
+				break;
+
+			case 'G':
+				buf++;
+				/* Returns true if error occured */
+				if (gn_atem_command_plusg(&buf) == true) {
+					gn_atem_modem_result(MR_ERROR);
+					return;
+				}
+				break;
+
+			default:
+				gn_atem_modem_result(MR_ERROR);
+				return;
+			}
+			break;
+
+		/* # is the precursor to another set of commands */
+		case '#':
+			buf++;
+			/* Returns true if error occured */
+			if (gn_atem_command_diesis(&buf) == true) {
+				gn_atem_modem_result(MR_ERROR);
+				return;
+			}
+			break;
+
+		default:
+			gn_atem_modem_result(MR_ERROR);
+			return;
+		}
+	}
+
+	gn_atem_modem_result(MR_OK);
+}
+
+
+static void gn_atem_sms_print(char *line, gn_sms *message, int mode)
+{
+	switch (mode) {
+	case INTERACT_MODE:
+		gsprintf(line, MAX_LINE_LENGTH,
+			_("\r\nDate/time: %d/%d/%d %d:%02d:%02d Sender: %s Msg Center: %s\r\nText: %s\r\n"),
+			message->smsc_time.day, message->smsc_time.month, message->smsc_time.year,
+			message->smsc_time.hour, message->smsc_time.minute, message->smsc_time.second,
+			message->remote.number, message->smsc.number, message->user_data[0].u.text);
+		break;
+	case TEXT_MODE:
+		if ((message->dcs.type == GN_SMS_DCS_GeneralDataCoding) &&
+		    (message->dcs.u.general.alphabet == GN_SMS_DCS_8bit))
+			gsprintf(line, MAX_LINE_LENGTH,
+				_("\"%s\",\"%s\",,\"%02d/%02d/%02d,%02d:%02d:%02d+%02d\"\r\n%s"),
+				(message->status ? _("REC READ") : _("REC UNREAD")),
+				message->remote.number,
+				message->smsc_time.year, message->smsc_time.month, message->smsc_time.day,
+				message->smsc_time.hour, message->smsc_time.minute, message->smsc_time.second,
+				message->time.timezone, _("<Not implemented>"));
+		else
+			gsprintf(line, MAX_LINE_LENGTH,
+				_("\"%s\",\"%s\",,\"%02d/%02d/%02d,%02d:%02d:%02d+%02d\"\r\n%s"),
+				(message->status ? _("REC READ") : _("REC UNREAD")),
+				message->remote.number,
+				message->smsc_time.year, message->smsc_time.month, message->smsc_time.day,
+				message->smsc_time.hour, message->smsc_time.minute, message->smsc_time.second,
+				message->time.timezone, message->user_data[0].u.text);
+		break;
+	case PDU_MODE:
+		gsprintf(line, MAX_LINE_LENGTH, _("0,<Not implemented>"));
+		break;
+	default:
+		gsprintf(line, MAX_LINE_LENGTH, _("<Unknown mode>"));
+		break;
+	}
+}
+
+
+static void gn_atem_sms_handle()
+{
+	gn_error	error;
+	char		buffer[MAX_LINE_LENGTH];
+
+	data.sms->memory_type = SMSType;
+	data.sms->number = SMSNumber;
+	error = gn_sms_get(&data, sm);
+
+	switch (error) {
+	case GN_ERR_NONE:
+		gn_atem_sms_print(buffer, data.sms, INTERACT_MODE);
+		gn_atem_string_out(buffer);
+		break;
+	default:
+		gsprintf(buffer, MAX_LINE_LENGTH, _("\r\nNo message under number %d\r\n"), SMSNumber);
+		gn_atem_string_out(buffer);
+		break;
+	}
+	return;
+}
+
+/* Parser for SMS interactive mode */
+void	gn_atem_sms_parse(char *buff)
+{
+	if (!strcasecmp(buff, "HELP")) {
+		gn_atem_string_out(_("\r\nThe following commands work...\r\n"));
+		gn_atem_string_out("DIR\r\n");
+		gn_atem_string_out("EXIT\r\n");
+		gn_atem_string_out("HELP\r\n");
+		return;
+	}
+
+	if (!strcasecmp(buff, "DIR")) {
+		SMSNumber = 1;
+		gn_atem_sms_handle();
+		Parser = gn_atem_dir_parse;
+		return;
+	}
+	if (!strcasecmp(buff, "EXIT")) {
+		Parser = gn_atem_at_parse;
+		gn_atem_modem_result(MR_OK);
+		return;
+	}
+	gn_atem_modem_result(MR_ERROR);
+}
+
+/* Parser for DIR sub mode of SMS interactive mode. */
+void	gn_atem_dir_parse(char *buff)
+{
+	switch (toupper(*buff)) {
+		case 'P':
+			SMSNumber--;
+			gn_atem_sms_handle();
+			return;
+		case 'N':
+			SMSNumber++;
+			gn_atem_sms_handle();
+			return;
+		case 'D':
+			data.sms->memory_type = SMSType;
+			data.sms->number = SMSNumber;
+			if (gn_sm_functions(GN_OP_DeleteSMS, &data, sm) == GN_ERR_NONE) {
+				gn_atem_modem_result(MR_OK);
+			} else {
+				gn_atem_modem_result(MR_ERROR);
+			}
+			return;
+		case 'Q':
+			Parser= gn_atem_sms_parse;
+			gn_atem_modem_result(MR_OK);
+			return;
+	}
+	gn_atem_modem_result(MR_ERROR);
+}
+
+/* Parser for entering message content (+CMGS) */
+void	gn_atem_sms_parseText(char *buff)
+{
+	static int index = 0;
+	int i, length;
+	char buffer[MAX_LINE_LENGTH];
+	gn_error error;
+
+	length = strlen(buff);
+
+	sms.user_data[0].type = GN_SMS_DATA_Text;
+
+	for (i = 0; i < length; i++) {
+
+		if (buff[i] == ModemRegisters[REG_CTRLZ]) {
+			/* Exit SMS text mode with sending */
+			sms.user_data[0].u.text[index] = 0;
+			sms.user_data[0].length = index;
+			index = 0;
+			Parser = gn_atem_at_parse;
+			dprintf("Sending SMS to %s (text: %s)\n", data.sms->remote.number, data.sms->user_data[0].u.text);
+
+			/* FIXME: set more SMS fields before sending */
+			error = gn_sms_send(&data, sm);
+
+			if (error == GN_ERR_NONE) {
+				gsprintf(buffer, MAX_LINE_LENGTH, "+CMGS: %d\r\n", data.sms->number);
+				gn_atem_string_out(buffer);
+				gn_atem_modem_result(MR_OK);
+			} else {
+				gn_atem_modem_result(MR_ERROR);
+			}
+			return;
+		} else if (buff[i] == ModemRegisters[REG_ESCAPE]) {
+			/* Exit SMS text mode without sending */
+			sms.user_data[0].u.text[index] = 0;
+			sms.user_data[0].length = index;
+			index = 0;
+			Parser = gn_atem_at_parse;
+			gn_atem_modem_result(MR_OK);
+			return;
+		} else {
+			/* Appent next char to message text */
+			sms.user_data[0].u.text[index++] = buff[i];
+		}
+	}
+
+	/* reached the end of line so insert \n and wait for more */
+	sms.user_data[0].u.text[index++] = '\n';
+	gn_atem_string_out("\r\n> ");
+}
+
+/* Handle AT+C commands, this is a quick hack together at this
+   stage. */
+bool	gn_atem_command_plusc(char **buf)
+{
+	float		rflevel = -1;
+	gn_rf_unit	rfunits = GN_RF_CSQ;
+	char		buffer[MAX_LINE_LENGTH], buffer2[MAX_LINE_LENGTH];
+	int		status, index;
+	gn_error	error;
+
+	if (strncasecmp(*buf, "SQ", 2) == 0) {
+		buf[0] += 2;
+
+		data.rf_unit = &rfunits;
+		data.rf_level = &rflevel;
+		if (gn_sm_functions(GN_OP_GetRFLevel, &data, sm) == GN_ERR_NONE) {
+			gsprintf(buffer, MAX_LINE_LENGTH, "+CSQ: %0.0f, 99\r\n", *(data.rf_level));
+			gn_atem_string_out(buffer);
+			return (false);
+		} else {
+			return (true);
+		}
+	}
+
+	/* AT+CGMI is Manufacturer information for the ME (phone) so
+	   it should be Nokia rather than gnokii... */
+	if (strncasecmp(*buf, "GMI", 3) == 0) {
+		buf[0] += 3;
+		gsprintf(buffer, MAX_LINE_LENGTH, "%s\r\n", data.manufacturer);
+		gn_atem_string_out(buffer);
+		return (false);
+	}
+
+	/* AT+CGSN is IMEI */
+	if (strncasecmp(*buf, "GSN", 3) == 0) {
+		buf[0] += 3;
+		strcpy(data.imei, "+CME ERROR: 0");
+		if (gn_sm_functions(GN_OP_GetImei, &data, sm) == GN_ERR_NONE) {
+			gsprintf(buffer, MAX_LINE_LENGTH, "%s\r\n", data.imei);
+			gn_atem_string_out(buffer);
+			return (false);
+		} else {
+			return (true);
+		}
+	}
+
+	/* AT+CGMR is Revision (hardware) */
+	if (strncasecmp(*buf, "GMR", 3) == 0) {
+		buf[0] += 3;
+		strcpy(data.revision, "+CME ERROR: 0");
+		if (gn_sm_functions(GN_OP_GetRevision, &data, sm) == GN_ERR_NONE) {
+			gsprintf(buffer, MAX_LINE_LENGTH, "%s\r\n", data.revision);
+			gn_atem_string_out(buffer);
+			return (false);
+		} else {
+			return (true);
+		}
+	}
+
+	/* AT+CGMM is Model code  */
+	if (strncasecmp(*buf, "GMM", 3) == 0) {
+		buf[0] += 3;
+		strcpy(data.model, "+CME ERROR: 0");
+		if (gn_sm_functions(GN_OP_GetModel, &data, sm) == GN_ERR_NONE) {
+			gsprintf(buffer, MAX_LINE_LENGTH, "%s\r\n", data.model);
+			gn_atem_string_out(buffer);
+			return (false);
+		} else {
+			return (true);
+		}
+	}
+
+	/* AT+CMGD is deleting a message */
+	if (strncasecmp(*buf, "MGD", 3) == 0) {
+		buf[0] += 3;
+		switch (**buf) {
+		case '=':
+			buf[0]++;
+			index = atoi(*buf);
+			buf[0] += strlen(*buf);
+
+			data.sms->memory_type = SMSType;
+			data.sms->number = index;
+			error = gn_sm_functions(GN_OP_DeleteSMS, &data, sm);
+
+			switch (error) {
+			case GN_ERR_NONE:
+				break;
+			default:
+				gsprintf(buffer, MAX_LINE_LENGTH, "\r\n+CMS ERROR: %d\r\n", error);
+				gn_atem_string_out(buffer);
+				return (true);
+			}
+			break;
+		default:
+			return (true);
+		}
+		return (false);
+	}
+
+	/* AT+CMGF is mode selection for message format  */
+	if (strncasecmp(*buf, "MGF", 3) == 0) {
+		buf[0] += 3;
+		switch (**buf) {
+		case '=':
+			buf[0]++;
+			switch (**buf) {
+			case '0':
+				buf[0]++;
+				MessageFormat = PDU_MODE;
+				break;
+			case '1':
+				buf[0]++;
+				MessageFormat = TEXT_MODE;
+				break;
+			default:
+				return (true);
+			}
+			break;
+		case '?':
+			buf[0]++;
+			gsprintf(buffer, MAX_LINE_LENGTH, "+CMGF: %d\r\n", MessageFormat);
+			gn_atem_string_out(buffer);
+			break;
+		default:
+			return (true);
+		}
+		return (false);
+	}
+
+	/* AT+CMGR is reading a message */
+	if (strncasecmp(*buf, "MGR", 3) == 0) {
+		buf[0] += 3;
+		switch (**buf) {
+		case '=':
+			buf[0]++;
+			index = atoi(*buf);
+			buf[0] += strlen(*buf);
+
+			data.sms->memory_type = SMSType;
+			data.sms->number = index;
+			error = gn_sms_get(&data, sm);
+
+			switch (error) {
+			case GN_ERR_NONE:
+				gn_atem_sms_print(buffer2, data.sms, MessageFormat);
+				gsprintf(buffer, MAX_LINE_LENGTH, "+CMGR: %s\r\n", buffer2);
+				gn_atem_string_out(buffer);
+				break;
+			default:
+				gsprintf(buffer, MAX_LINE_LENGTH, "\r\n+CMS ERROR: %d\r\n", error);
+				gn_atem_string_out(buffer);
+				return (true);
+			}
+			break;
+		default:
+			return (true);
+		}
+		return (false);
+	}
+
+	/* AT+CMGS is sending a message */
+	if (strncasecmp(*buf, "MGS", 3) == 0) {
+		buf[0] += 3;
+		switch (**buf) {
+		case '=':
+			buf[0]++;
+			if (sscanf(*buf, "\"%[+0-9a-zA-Z ]\"", sms.remote.number)) {
+				Parser = gn_atem_sms_parseText;
+				buf[0] += strlen(*buf);
+				gn_atem_string_out("\r\n> ");
+			}
+			return (true);
+		default:
+			return (true);
+		}
+		return (false);
+	}
+
+	/* AT+CMGL is listing messages */
+	if (strncasecmp(*buf, "MGL", 3) == 0) {
+		buf[0] += 3;
+		status = -1;
+
+		switch (**buf) {
+		case 0:
+		case '=':
+			buf[0]++;
+			/* process <stat> parameter */
+			if (*(*buf-1) == 0 || /* i.e. no parameter given */
+				strcasecmp(*buf, "1") == 0 ||
+				strcasecmp(*buf, "3") == 0 ||
+				strcasecmp(*buf, "\"REC READ\"") == 0 ||
+				strcasecmp(*buf, "\"STO SENT\"") == 0) {
+				status = GN_SMS_Sent;
+			} else if (strcasecmp(*buf, "0") == 0 ||
+				strcasecmp(*buf, "2") == 0 ||
+				strcasecmp(*buf, "\"REC UNREAD\"") == 0 ||
+				strcasecmp(*buf, "\"STO UNSENT\"") == 0) {
+				status = GN_SMS_Unsent;
+			} else if (strcasecmp(*buf, "4") == 0 ||
+				strcasecmp(*buf, "\"ALL\"") == 0) {
+				status = 4; /* ALL */
+			} else {
+				return true;
+			}
+			buf[0] += strlen(*buf);
+
+			/* check all message storages */
+			for (index = 1; index <= 20; index++) {
+
+				data.sms->memory_type = SMSType;
+				data.sms->number = index;
+				error = gn_sms_get(&data, sm);
+
+				switch (error) {
+				case GN_ERR_NONE:
+					/* print messsage if it has the required status */
+					if (data.sms->status == status || status == 4 /* ALL */) {
+						gn_atem_sms_print(buffer2, data.sms, MessageFormat);
+						gsprintf(buffer, MAX_LINE_LENGTH, "+CMGL: %d,%s\r\n", index, buffer2);
+						gn_atem_string_out(buffer);
+					}
+					break;
+				case GN_ERR_EMPTYLOCATION:
+					/* don't care if this storage is empty */
+					break;
+				default:
+					/* print other error codes and quit */
+					gsprintf(buffer, MAX_LINE_LENGTH, "\r\n+CMS ERROR: %d\r\n", error);
+					gn_atem_string_out(buffer);
+					return (true);
+				}
+			}
+			break;
+		default:
+			return (true);
+		}
+		return (false);
+	}
+
+	return (true);
+}
+
+/* AT+G commands.  Some of these responses are a bit tongue in cheek... */
+bool	gn_atem_command_plusg(char **buf)
+{
+	char		buffer[MAX_LINE_LENGTH];
+
+	/* AT+GMI is Manufacturer information for the TA (Terminal Adaptor) */
+	if (strncasecmp(*buf, "MI", 3) == 0) {
+		buf[0] += 2;
+
+		gn_atem_string_out(_("Hugh Blemings, Pavel Janik ml. and others...\r\n"));
+		return (false);
+	}
+
+	/* AT+GMR is Revision information for the TA (Terminal Adaptor) */
+	if (strncasecmp(*buf, "MR", 3) == 0) {
+		buf[0] += 2;
+		gsprintf(buffer, MAX_LINE_LENGTH, "%s %s %s\r\n", VERSION, __TIME__, __DATE__);
+
+		gn_atem_string_out(buffer);
+		return (false);
+	}
+
+	/* AT+GMM is Model information for the TA (Terminal Adaptor) */
+	if (strncasecmp(*buf, "MM", 3) == 0) {
+		buf[0] += 2;
+
+		gsprintf(buffer, MAX_LINE_LENGTH, _("gnokii configured on %s for models %s\r\n"), sm->config.port_device, sm->driver.phone.models);
+		gn_atem_string_out(buffer);
+		return (false);
+	}
+
+	/* AT+GSN is Serial number for the TA (Terminal Adaptor) */
+	if (strncasecmp(*buf, "SN", 3) == 0) {
+		buf[0] += 2;
+
+		gsprintf(buffer, MAX_LINE_LENGTH, _("none built in, choose your own\r\n"));
+		gn_atem_string_out(buffer);
+		return (false);
+	}
+
+	return (true);
+}
+
+/* Handle AT# commands */
+bool	gn_atem_command_diesis(char **buf)
+{
+	int	number;
+	char	buffer[MAX_LINE_LENGTH];
+
+	if (strncasecmp(*buf, "CID", 3) == 0) {
+		buf[0] += 3;
+		switch (**buf) {
+		case '?':
+			buf[0]++;
+			gsprintf(buffer, MAX_LINE_LENGTH, "%d\r\n", CallerIDMode);
+			gn_atem_string_out(buffer);
+			return (false);
+		case '=':
+			buf[0]++;
+			if (**buf == '?') {
+				buf[0]++;
+				gn_atem_string_out("0,1\r\n");
+				return (false);
+			} else {
+				number = gn_atem_num_get(buf);
+				if ( number == 0 || number == 1 ) {
+					CallerIDMode = number;
+					return (false);
+				}
+			}
+		}
+	}
+	return (true);
+}
+
+/* Send a result string back.  There is much work to do here, see
+   the code in the isdn driver for an idea of where it's heading... */
+void	gn_atem_modem_result(int code)
+{
+	char	buffer[16];
+
+	if (!(ModemRegisters[REG_VERBOSE] & BIT_VERBOSE)) {
+		sprintf(buffer, "%d\r\n", code);
+		gn_atem_string_out(buffer);
+	} else {
+		switch (code) {
+			case MR_OK:
+					gn_atem_string_out("OK\r\n");
+					break;
+
+			case MR_ERROR:
+					gn_atem_string_out("ERROR\r\n");
+					break;
+
+			case MR_CARRIER:
+					gn_atem_string_out("CARRIER\r\n");
+					break;
+
+			case MR_CONNECT:
+					gn_atem_string_out("CONNECT\r\n");
+					break;
+
+			case MR_NOCARRIER:
+					gn_atem_string_out("NO CARRIER\r\n");
+					break;
+		        case MR_RING:
+					gn_atem_string_out("RING\r\n");
+					break;
+			default:
+					gn_atem_string_out(_("\r\nUnknown Result Code!\r\n"));
+					break;
+		}
+	}
+
+}
+
+
+/* Get integer from char-pointer, set pointer to end of number
+   stolen basically verbatim from ISDN code.  */
+int gn_atem_num_get(char **p)
+{
+	int v = -1;
+
+	while (*p[0] >= '0' && *p[0] <= '9') {
+		v = ((v < 0) ? 0 : (v * 10)) + (int) ((*p[0]++) - '0');
+	}
+
+	return v;
+}
+
+/* Write string to virtual modem port, either pty or
+   STDOUT as appropriate.  This function is only used during
+   command mode - data pump is used when connected.  */
+void	gn_atem_string_out(char *buffer)
+{
+	int	count = 0;
+	char	out_char;
+
+	while (count < strlen(buffer)) {
+
+		/* Translate CR/LF/BS as appropriate */
+		switch (buffer[count]) {
+			case '\r':
+				out_char = ModemRegisters[REG_CR];
+				break;
+			case '\n':
+				out_char = ModemRegisters[REG_LF];
+				break;
+			case '\b':
+				out_char = ModemRegisters[REG_BS];
+				break;
+			default:
+				out_char = buffer[count];
+				break;
+		}
+
+		sm->info->write(sm->info->opaque, "%c", out_char);
+		count++;
+	}
+}

Added: trunk/src/host/qemu-neo1973/gnokiigsm/at-emulator.h
===================================================================
--- trunk/src/host/qemu-neo1973/gnokiigsm/at-emulator.h	2007-05-16 22:38:21 UTC (rev 1986)
+++ trunk/src/host/qemu-neo1973/gnokiigsm/at-emulator.h	2007-05-17 00:24:48 UTC (rev 1987)
@@ -0,0 +1,71 @@
+/*
+
+  $Id: at-emulator.h,v 1.12 2004/09/20 16:05:38 bozo 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) 1999, 2000 Hugh Blemings & Pavel Janík ml.
+
+  Header file for AT emulator code.
+
+*/
+
+#ifndef _gnokii_data_at_emulator_h
+#define _gnokii_data_at_emulator_h
+
+#include "compat.h"
+#include "gnokii.h"
+
+	/* Prototypes */
+bool	gn_atem_initialise(int read_fd, int write_fd, struct gn_statemachine *sm);
+void	gn_atem_incoming_data_handle(const char *buffer, int length);
+void	gn_atem_registers_init(void);
+void	gn_atem_string_out(char *buffer);
+void	gn_atem_at_parse(char *cmd_buffer);
+void	gn_atem_sms_parse(char *cmd_buffer);
+void	gn_atem_dir_parse(char *cmd_buffer);
+bool	gn_atem_command_plusc(char **buf);
+bool	gn_atem_command_plusg(char **buf);
+int	gn_atem_num_get(char **p);
+void	gn_atem_modem_result(int code);
+void    gn_atem_call_passup(gn_call_status call_status, gn_call_info *call_info, struct gn_statemachine *state);
+void	gn_atem_cid_out(gn_call_info *callinfo);
+bool	gn_atem_command_diesis(char **buf);
+
+	/* Global variables */
+extern bool gn_atem_initialised;
+extern struct gn_statemachine	*sm;
+extern gn_data		data;
+
+	/* Definition of modem result codes - these are returned to "terminal"
+       numerically or as a string depending on the setting of S12 */
+
+	/* FIX ME - Numeric values for everything except OK and ERROR
+	   are guesses as I've not got an AT reference handy.   HAB */
+
+#define 	MR_OK			(0)
+#define		MR_ERROR		(4)
+#define		MR_NOCARRIER	(5)
+#define		MR_CARRIER		(2)
+#define		MR_CONNECT		(3)
+#define         MR_RING                 (6)
+
+#endif	/* _gnokii_data_at_emulator_h */

Added: trunk/src/host/qemu-neo1973/gnokiigsm/bitmaps.h
===================================================================
--- trunk/src/host/qemu-neo1973/gnokiigsm/bitmaps.h	2007-05-16 22:38:21 UTC (rev 1986)
+++ trunk/src/host/qemu-neo1973/gnokiigsm/bitmaps.h	2007-05-17 00:24:48 UTC (rev 1987)
@@ -0,0 +1,92 @@
+/*
+
+  $Id: bitmaps.h,v 1.31 2006/11/08 19:45:37 dforsi Exp $
+
+  G N O K I I
+
+  A Linux/Unix toolset and driver for the 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) 1999-2000 Hugh Blemings & Pavel Janík ml.
+  Copyright (C) 2000      Marcin Wiacek, Chris Kemp
+  Copyright (C) 2001-2003 Pawel Kot
+  Copyright (C) 2002      Pavel Machek
+
+  Functions for common bitmap operations.
+
+*/
+
+#ifndef _gnokii_bitmaps_h
+#define _gnokii_bitmaps_h
+
+#include <stdio.h>
+
+#include <error.h>
+#include <common.h>
+
+/* Bitmap types. These do *not* correspond to headers[] in gsm-sms.c. */
+
+typedef enum {
+	GN_BMP_None = 0,
+	GN_BMP_StartupLogo = 50,
+	GN_BMP_PictureMessage,
+	GN_BMP_OperatorLogo,
+	GN_BMP_CallerLogo,
+	GN_BMP_WelcomeNoteText,
+	GN_BMP_DealerNoteText,
+	GN_BMP_NewOperatorLogo,
+	GN_BMP_EMSPicture,
+	GN_BMP_EMSAnimation,	/* First bitmap in animation should have this type */
+	GN_BMP_EMSAnimation2,	/* ...second, third and fourth should have this type */
+} gn_bmp_types;
+
+#define GN_BMP_MAX_SIZE 1000
+
+/* Structure to hold incoming/outgoing bitmaps (and welcome-notes). */
+
+typedef struct {
+	unsigned char height;    /* Bitmap height (pixels) */
+	unsigned char width;     /* Bitmap width (pixels) */
+	unsigned int size;       /* Bitmap size (bytes) */
+	gn_bmp_types type;       /* Bitmap type */
+	char netcode[7];         /* Network operator code */
+	char text[256];          /* Text used for welcome-note or callergroup name */
+	char dealertext[256];    /* Text used for dealer welcome-note */
+	int dealerset;           /* Is dealer welcome-note set now ? */
+	unsigned char bitmap[GN_BMP_MAX_SIZE]; /* Actual Bitmap */
+	char number;             /* Caller group number */
+	int ringtone;            /* Ringtone no sent with caller group */
+	unsigned char ringtone_id[6];
+} gn_bmp;
+
+GNOKII_API gn_error gn_file_bitmap_read(char *filename, gn_bmp *bitmap, gn_phone *info);
+GNOKII_API gn_error gn_file_bitmap_save(char *filename, gn_bmp *bitmap, gn_phone *info);
+GNOKII_API gn_error gn_file_bitmap_show(char *filename);
+
+GNOKII_API gn_error gn_bmp_null(gn_bmp *bmp, gn_phone *info);
+GNOKII_API void gn_bmp_point_set(gn_bmp *bmp, int x, int y);
+GNOKII_API void gn_bmp_point_clear(gn_bmp *bmp, int x, int y);
+GNOKII_API int  gn_bmp_point(gn_bmp *bmp, int x, int y);
+GNOKII_API void gn_bmp_clear(gn_bmp *bmp);
+GNOKII_API void gn_bmp_resize(gn_bmp *bitmap, gn_bmp_types target, gn_phone *info);
+GNOKII_API void gn_bmp_print(gn_bmp *bitmap, FILE *f);
+
+GNOKII_API int gn_bmp_sms_encode(gn_bmp *bitmap, unsigned char *message);
+GNOKII_API gn_error gn_bmp_sms_read(int type, unsigned char *message, unsigned char *code, gn_bmp *bitmap);
+
+#endif /* _gnokii_bitmaps_h */

Added: trunk/src/host/qemu-neo1973/gnokiigsm/call.h
===================================================================
--- trunk/src/host/qemu-neo1973/gnokiigsm/call.h	2007-05-16 22:38:21 UTC (rev 1986)
+++ trunk/src/host/qemu-neo1973/gnokiigsm/call.h	2007-05-17 00:24:48 UTC (rev 1987)
@@ -0,0 +1,98 @@
+/*
+
+  $Id: call.h,v 1.13 2006/06/11 16:39:11 deller Exp $
+
+  G N O K I I
+
+  A Linux/Unix toolset and driver for the 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) 1999-2000 Hugh Blemings, Pavel Janik
+  Copyright (C) 2002-2003 Pawel Kot, BORBELY Zoltan <bozo at andrews.hu>
+
+  Include file for the call management library.
+
+*/
+
+#ifndef _gnokii_call_h
+#define _gnokii_call_h
+
+#include <error.h>
+
+typedef enum {
+	GN_CALL_Voice,		/* Voice call */
+	GN_CALL_NonDigitalData,	/* Data call on non digital line */
+	GN_CALL_DigitalData	/* Data call on digital line */
+} gn_call_type;
+
+typedef enum {
+	GN_CALL_Never,			/* Never send my number */
+	GN_CALL_Always,			/* Always send my number */
+	GN_CALL_Default			/* Use the network default settings */
+} gn_call_send_number;
+
+typedef enum {
+	GN_CALL_Idle,
+	GN_CALL_Ringing,
+	GN_CALL_Dialing,
+	GN_CALL_Incoming,		/* Incoming call */
+	GN_CALL_LocalHangup,		/* Local end terminated the call */
+	GN_CALL_RemoteHangup,		/* Remote end terminated the call */
+	GN_CALL_Established,		/* Remote end answered the call */
+	GN_CALL_Held,			/* Call placed on hold */
+	GN_CALL_Resumed			/* Held call resumed */
+} gn_call_status;
+
+typedef struct {
+	gn_call_type type;
+	char number[GN_PHONEBOOK_NUMBER_MAX_LENGTH + 1];
+	char name[GN_PHONEBOOK_NAME_MAX_LENGTH + 1];
+	gn_call_send_number send_number;
+	int call_id;
+} gn_call_info;
+
+typedef struct {
+	int call_id;
+	int channel;
+	char number[GN_PHONEBOOK_NUMBER_MAX_LENGTH + 1];
+	char name[GN_PHONEBOOK_NAME_MAX_LENGTH + 1];
+	gn_call_status state;
+	gn_call_status prev_state;
+} gn_call_active;
+
+/* Call functions and structs */
+typedef struct {
+	struct gn_statemachine *state;
+	int call_id;
+	gn_call_status status;
+	gn_call_type type;
+	char remote_number[GN_PHONEBOOK_NUMBER_MAX_LENGTH + 1];
+	char remote_name[GN_PHONEBOOK_NAME_MAX_LENGTH + 1];
+	struct timeval start_time;
+	struct timeval answer_time;
+	int local_originated;
+} gn_call;
+
+#define	GN_CALL_MAX_PARALLEL 2
+
+GNOKII_API void gn_call_notifier(gn_call_status call_status, gn_call_info *call_info, struct gn_statemachine *state);
+GNOKII_API gn_call *gn_call_get_active(int call_id);
+GNOKII_API gn_error gn_call_answer(int call_id);
+GNOKII_API gn_error gn_call_cancel(int call_id);
+
+#endif /* _gnokii_call_h */

Added: trunk/src/host/qemu-neo1973/gnokiigsm/common.h
===================================================================
--- trunk/src/host/qemu-neo1973/gnokiigsm/common.h	2007-05-16 22:38:21 UTC (rev 1986)
+++ trunk/src/host/qemu-neo1973/gnokiigsm/common.h	2007-05-17 00:24:48 UTC (rev 1987)
@@ -0,0 +1,806 @@
+/*
+
+  $Id: common.h,v 1.152 2007/05/04 19:41:34 pkot Exp $
+
+  G N O K I I
+
+  A Linux/Unix toolset and driver for Nokia the 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) 1999-2000 Hugh Blemings & Pavel Janík ml.
+  Copyright (C) 2001-2004 Pawel Kot, BORBELY Zoltan
+  Copyright (C) 2001      Manfred Jonsson, Marian Jancar, Chris Kemp, Marcin Wiacek
+  Copyright (C) 2001-2002 Pavel Machek
+  Copyright (C) 2002      Markus Plail
+
+  Header file for the definitions, enums etc. that are used by all models of
+  handset.
+
+*/
+
+#ifndef _gnokii_common_h
+#define _gnokii_common_h
+
+#include <rlp-common.h>
+
+/* Type of connection. Now we support serial connection with FBUS cable and
+   IR (only with 61x0 models) */
+typedef enum {
+        GN_CT_NONE = -1,/* no connection type (error) */
+	GN_CT_Serial,   /* Serial connection. */
+	GN_CT_DAU9P,    /* Serial connection using DAU9P cable; use only with 6210/7110 if you want faster initialization */
+	GN_CT_DLR3P,    /* Serial connection using DLR3P cable */
+	GN_CT_Infrared, /* Infrared connection. */
+	GN_CT_Irda,     /* Linux IrDA support */
+	GN_CT_Bluetooth,/* Linux Bluetooth support */
+	GN_CT_Tekram,   /* Tekram Ir-Dongle */
+	GN_CT_TCP,      /* TCP network connection */
+	GN_CT_M2BUS,	/* Serial connection with M2BUS protocol */
+	GN_CT_DKU2,	/* DKU2 usb connection using nokia_dku2 kernel driver */
+	GN_CT_DKU2LIBUSB /* DKU2 usb connection using libusb */
+} gn_connection_type;
+
+/* Maximum length of device name for serial port */
+
+#define GN_DEVICE_NAME_MAX_LENGTH (32)
+
+/* Define an enum for specifying memory types for retrieving phonebook
+   entries, SMS messages etc. This type is not mobile specific - the model
+   code should take care of translation to mobile specific numbers - see 6110
+   code.
+   01/07/99:  Two letter codes follow GSM 07.07 release 6.2.0
+*/
+typedef enum {
+	GN_MT_ME, /* Internal memory of the mobile equipment */
+	GN_MT_SM, /* SIM card memory */
+	GN_MT_FD, /* Fixed dial numbers */
+	GN_MT_ON, /* Own numbers */
+	GN_MT_EN, /* Emergency numbers */
+	GN_MT_DC, /* Dialled numbers */
+	GN_MT_RC, /* Received numbers */
+	GN_MT_MC, /* Missed numbers */
+	GN_MT_LD, /* Last dialed */
+	GN_MT_MT, /* combined ME and SIM phonebook */
+	GN_MT_TA, /* for compatibility only: TA=computer memory */
+	GN_MT_CB, /* Currently selected memory */
+	GN_MT_IN, /* Inbox for folder aware phones */
+	GN_MT_OU, /* Outbox  */
+	GN_MT_AR, /* Archive */
+	GN_MT_TE, /* Templates */
+	GN_MT_F1, /* 1st CUSTOM FOLDER */
+	GN_MT_F2,
+	GN_MT_F3,
+	GN_MT_F4,
+	GN_MT_F5,
+	GN_MT_F6,
+	GN_MT_F7,
+	GN_MT_F8,
+	GN_MT_F9,
+	GN_MT_F10,
+	GN_MT_F11,
+	GN_MT_F12,
+	GN_MT_F13,
+	GN_MT_F14,
+	GN_MT_F15,
+	GN_MT_F16,
+	GN_MT_F17,
+	GN_MT_F18,
+	GN_MT_F19,
+	GN_MT_F20, /* 20th CUSTOM FOLDER */
+	GN_MT_XX = 0xff	/* Error code for unknown memory type (returned by fbus-xxxx functions). */
+} gn_memory_type;
+
+/* Power source types */
+typedef enum {
+	GN_PS_ACDC = 1, /* AC/DC powered (charging) */
+	GN_PS_BATTERY   /* Internal battery */
+} gn_power_source;
+
+/* Definition of security codes. */
+typedef enum {
+	GN_SCT_SecurityCode = 0x01, /* Security code. */
+	GN_SCT_Pin,                 /* PIN. */
+	GN_SCT_Pin2,                /* PIN 2. */
+	GN_SCT_Puk,                 /* PUK. */
+	GN_SCT_Puk2,                /* PUK 2. */
+	GN_SCT_None                 /* Code not needed. */
+} gn_security_code_type;
+
+/* Security code definition. */
+typedef struct {
+	gn_security_code_type type; /* Type of the code. */
+	char code[10];              /* Actual code. */
+	char new_code[10];          /* New code. */
+} gn_security_code;
+
+/* This structure is used to get the current network status */
+typedef struct {
+	char network_code[10];     /* GSM network code */
+	unsigned char cell_id[10]; /* CellID */
+	unsigned char LAC[10];     /* LAC */
+} gn_network_info;
+
+/* Limits for sizing of array in gn_phonebook_entry. Individual handsets may
+   not support these lengths so they have their own limits set. */
+#define GN_PHONEBOOK_NAME_MAX_LENGTH            61   /* For 6510 */
+#define GN_PHONEBOOK_NUMBER_MAX_LENGTH          49   /* For 6510 */
+#define GN_PHONEBOOK_SUBENTRIES_MAX_NUMBER      64   /* it was 10 for 6510, but modern phones supports more */
+						     /* 7110 is able to have in one
+						      * entry 5 numbers and 4
+						      * texts [email,notice,postal,url].
+						      * Dirk reported on gnokii-users that N70 has the following additional fields:
+						      * - Company
+						      * - Position
+						      * - Aliasname
+						      * - DTMF
+						      * - User ID 
+						      * - all postal fields:
+						      *  - PO Box
+						      *  - Addition
+						      *  - Street
+						      *  - Zip Code
+						      *  - City
+						      *  - State/Province
+						      *  - Country
+						      *  - Birthday
+						      */
+#define GN_PHONEBOOK_CALLER_GROUPS_MAX_NUMBER    5
+#define GN_PHONEBOOK_ENTRY_MAX_LENGTH 1024
+
+/* This data type is used to report the number of used and free positions in
+   memory (sim or internal). */
+typedef struct {
+	gn_memory_type memory_type; /* Type of the memory */
+	int used;                   /* Number of used positions */
+	int free;                   /* Number of free positions */
+} gn_memory_status;
+
+/* General date and time structure. It is used for the SMS, calendar, alarm
+ * settings, clock etc. */
+typedef struct {
+	int year;           /* The complete year specification - e.g. 1999. Y2K :-) */
+	int month;          /* January = 1 */
+	int day;
+	int hour;
+	int minute;
+	int second;
+	int timezone;      /* The difference between local time and GMT.
+			      Note that different SMSC software treat this field
+			      in the different ways. */
+} gn_timestamp;
+
+/* Some phones (at the moment 7110/6510 series) supports extended phonebook
+   with additional data.  Here we have structures for them */
+typedef enum {
+	GN_PHONEBOOK_NUMBER_None    = 0x00,
+	GN_PHONEBOOK_NUMBER_Common  = 0x01,
+	GN_PHONEBOOK_NUMBER_Home    = 0x02,
+	GN_PHONEBOOK_NUMBER_Mobile  = 0x03,
+	GN_PHONEBOOK_NUMBER_Fax     = 0x04,
+	GN_PHONEBOOK_NUMBER_Work    = 0x06,
+	GN_PHONEBOOK_NUMBER_General = 0x0a,
+} gn_phonebook_number_type;
+
+typedef enum {
+	GN_PHONEBOOK_ENTRY_Name            = 0x07,
+	GN_PHONEBOOK_ENTRY_Email           = 0x08,
+	GN_PHONEBOOK_ENTRY_Postal          = 0x09,
+	GN_PHONEBOOK_ENTRY_Note            = 0x0a,
+	GN_PHONEBOOK_ENTRY_Number          = 0x0b,
+	GN_PHONEBOOK_ENTRY_Ringtone        = 0x0c,
+	GN_PHONEBOOK_ENTRY_Date            = 0x13, /* Date is used for DC,RC,etc (last calls) */
+	GN_PHONEBOOK_ENTRY_Pointer         = 0x1a, /* Pointer to the other memory */
+	GN_PHONEBOOK_ENTRY_Logo            = 0x1b,
+	GN_PHONEBOOK_ENTRY_LogoSwitch      = 0x1c,
+	GN_PHONEBOOK_ENTRY_Group           = 0x1e,
+	GN_PHONEBOOK_ENTRY_URL             = 0x2c,
+	GN_PHONEBOOK_ENTRY_Location        = 0x2f, /* ??? */
+	GN_PHONEBOOK_ENTRY_Image           = 0x33,
+	GN_PHONEBOOK_ENTRY_RingtoneAdv     = 0x37,
+	GN_PHONEBOOK_ENTRY_UserID          = 0x38,
+	GN_PHONEBOOK_ENTRY_PTTAddress      = 0x3f, /* string */
+	GN_PHONEBOOK_ENTRY_FirstName       = 0x46,
+	GN_PHONEBOOK_ENTRY_LastName        = 0x47,
+	GN_PHONEBOOK_ENTRY_PostalAddress   = 0x4a,
+	GN_PHONEBOOK_ENTRY_ExtendedAddress = 0x4b,
+	GN_PHONEBOOK_ENTRY_Street          = 0x4c,
+	GN_PHONEBOOK_ENTRY_City            = 0x4d,
+	GN_PHONEBOOK_ENTRY_StateProvince   = 0x4e,
+	GN_PHONEBOOK_ENTRY_ZipCode         = 0x4f,
+	GN_PHONEBOOK_ENTRY_Country         = 0x50,
+	GN_PHONEBOOK_ENTRY_FormalName      = 0x52,
+	GN_PHONEBOOK_ENTRY_JobTitle        = 0x54,
+	GN_PHONEBOOK_ENTRY_Company         = 0x55,
+	GN_PHONEBOOK_ENTRY_Nickname        = 0x56,
+	GN_PHONEBOOK_ENTRY_Birthday        = 0x57,
+} gn_phonebook_entry_type;
+
+typedef enum {
+	GN_PHONEBOOK_GROUP_Family,
+	GN_PHONEBOOK_GROUP_Vips,
+	GN_PHONEBOOK_GROUP_Friends,
+	GN_PHONEBOOK_GROUP_Work,
+	GN_PHONEBOOK_GROUP_Others, 
+	GN_PHONEBOOK_GROUP_None,
+} gn_phonebook_group_type;
+
+#define GN_PHONEBOOK_PERSON_MAX_LENGTH 64
+
+typedef struct {
+	int has_person;
+	char family_name[GN_PHONEBOOK_PERSON_MAX_LENGTH + 1];		/* GN_PHONEBOOK_ENTRY_LastName */
+	char given_name[GN_PHONEBOOK_PERSON_MAX_LENGTH + 1];            /* GN_PHONEBOOK_ENTRY_FirstName */
+	char additional_names[GN_PHONEBOOK_PERSON_MAX_LENGTH + 1];
+	char honorific_prefixes[GN_PHONEBOOK_PERSON_MAX_LENGTH + 1];    /* GN_PHONEBOOK_ENTRY_FormalName */
+	char honorific_suffixes[GN_PHONEBOOK_PERSON_MAX_LENGTH + 1];
+} gn_phonebook_person;
+
+#define GN_PHONEBOOK_ADDRESS_MAX_LENGTH 64
+
+typedef struct {
+	int has_address;
+	char post_office_box[GN_PHONEBOOK_ADDRESS_MAX_LENGTH + 1];	/* GN_PHONEBOOK_ENTRY_PostalAddress */
+	char extended_address[GN_PHONEBOOK_ADDRESS_MAX_LENGTH + 1];	/* GN_PHONEBOOK_ENTRY_ExtendedAddress */
+	char street[GN_PHONEBOOK_ADDRESS_MAX_LENGTH + 1];		/* GN_PHONEBOOK_ENTRY_Street */
+	char city[GN_PHONEBOOK_ADDRESS_MAX_LENGTH + 1];			/* GN_PHONEBOOK_ENTRY_City */
+	char state_province[GN_PHONEBOOK_ADDRESS_MAX_LENGTH + 1];	/* GN_PHONEBOOK_ENTRY_StateProvince */
+	char zipcode[GN_PHONEBOOK_ADDRESS_MAX_LENGTH + 1];		/* GN_PHONEBOOK_ENTRY_ZipCode */
+	char country[GN_PHONEBOOK_ADDRESS_MAX_LENGTH + 1];		/* GN_PHONEBOOK_ENTRY_Country */
+} gn_phonebook_address;
+
+typedef struct {
+	gn_phonebook_entry_type entry_type;
+	gn_phonebook_number_type number_type;
+	union {
+		char number[GN_PHONEBOOK_NAME_MAX_LENGTH + 1];   /* Number, Name, Address, eMail... */
+		/* GN_PHONEBOOK_ENTRY_Date
+		 * GN_PHONEBOOK_ENTRY_Birthday
+		 */
+		gn_timestamp date;                               /* or the last calls list */
+		/* GN_PHONEBOOK_ENTRY_Image
+		 * GN_PHONEBOOK_ENTRY_RingtoneAdv
+		 */
+		char fileid[6];                                  /* Bitmap or rigntone fileid */
+	} data;
+	int id;
+} gn_phonebook_subentry;
+
+/* Define datatype for phonebook entry, used for getting/writing phonebook
+   entries. */
+typedef struct {
+	int empty;                                        /* Is this entry empty? */
+	char name[GN_PHONEBOOK_NAME_MAX_LENGTH + 1];      /* Plus 1 for
+							     nullterminator. */
+	char number[GN_PHONEBOOK_NUMBER_MAX_LENGTH + 1];  /* Number */
+	gn_memory_type memory_type;                       /* Type of memory */
+	gn_phonebook_group_type caller_group;             /* Caller group - gn_phonebook_group_type */
+	int location;                                     /* Location */
+	gn_timestamp date;                                /* The record date and time
+							     of the number. */
+	gn_phonebook_person person;                       /* Personal information */
+	gn_phonebook_address address;                     /* Address information */
+	gn_phonebook_subentry subentries[GN_PHONEBOOK_SUBENTRIES_MAX_NUMBER];
+	/* For phones with
+	 * additional phonebook
+	 * entries */
+	int subentries_count;                             /* Should be set to 0, if extended
+							     phonebook is not used */
+} gn_phonebook_entry;
+
+/* This define speed dialing entries. */
+typedef struct {
+	int number;                 /* Which number is used to dialing? */
+	gn_memory_type memory_type; /* Memory type of the number. */
+	int location;               /* Location of the number in MemoryType. */
+} gn_speed_dial;
+
+/* Define enum used to describe what sort of date/time support is
+   available. */
+typedef enum {
+	GN_DT_None,     /* The mobile phone doesn't support time and date. */
+	GN_DT_TimeOnly, /* The mobile phone supports only time. */
+	GN_DT_DateOnly, /* The mobile phone supports only date. */
+	GN_DT_DateTime  /* Wonderful phone - it supports date and time. */
+} gn_datetime_support;
+
+/* Define enums for RF units. GRF_CSQ asks for units in form used
+   in AT+CSQ command as defined by GSM 07.07 */
+typedef enum {
+	GN_RF_Arbitrary,
+	GN_RF_dBm,
+	GN_RF_mV,
+	GN_RF_uV,
+	GN_RF_CSQ,
+	GN_RF_Percentage
+} gn_rf_unit;
+
+/* Define enums for Battery units. */
+
+typedef enum {
+	GN_BU_Arbitrary,
+	GN_BU_Volts,
+	GN_BU_Minutes,
+	GN_BU_Percentage
+} gn_battery_unit;
+
+/* Define enums for Calendar Note types */
+typedef enum {
+	GN_CALNOTE_MEETING  = 0x01, /* Meeting */
+	GN_CALNOTE_CALL     = 0x02, /* Call */
+	GN_CALNOTE_BIRTHDAY = 0x04, /* Birthday */
+	GN_CALNOTE_REMINDER = 0x08, /* Reminder */
+	GN_CALNOTE_MEMO     = 0x16, /* Memo */
+} gn_calnote_type;
+
+typedef enum {
+	GN_CALNOTE_NEVER   = 0,
+	GN_CALNOTE_DAILY   = 24,
+	GN_CALNOTE_WEEKLY  = 168,
+	GN_CALNOTE_2WEEKLY = 336,
+	GN_CALNOTE_MONTHLY = 65534,
+	GN_CALNOTE_YEARLY  = 65535
+} gn_calnote_recurrence;
+
+#define GN_CALNOTE_MAX_NUMBER       1024 /* FIXME how many are possible? */
+#define GN_CALNOTE_MAX_LENGTH        258
+#define GN_CALNOTE_NUMBER_MAX_LENGTH  49
+
+typedef struct {
+	int enabled; /* Is alarm set? */
+	int tone; /* Is alarm tone enabled? */
+	gn_timestamp timestamp;
+} gn_calnote_alarm;
+
+/* Calendar note type */
+typedef struct {
+	int location;                                    /* The number of the note in the phone memory */
+	gn_calnote_type type;                            /* The type of the note */
+	gn_timestamp time;                               /* The time of the note */
+	gn_timestamp end_time;                           /* The end time of the note */
+	gn_calnote_alarm alarm;                          /* The alarm of the note */
+	char text[GN_CALNOTE_MAX_LENGTH];                /* The text of the note */
+	char phone_number[GN_CALNOTE_NUMBER_MAX_LENGTH]; /* For Call only: the phone number */
+	char mlocation[GN_CALNOTE_MAX_LENGTH];           /* For Meeting only: the location field */
+	gn_calnote_recurrence recurrence;                /* Recurrence of the note */
+} gn_calnote;
+
+/* List of Calendar Notes in phone */
+typedef struct {
+	unsigned int number;                          /* The number of notes in phone */
+	unsigned int location[GN_CALNOTE_MAX_NUMBER]; /* Location of the nth note */
+	unsigned int last;                            /* Index of the last allocated note */
+} gn_calnote_list;
+
+/* ToDo things. It is only supported by the newer phones. */
+#define GN_TODO_MAX_LENGTH	256
+#define GN_TODO_MAX_NUMBER	512
+
+typedef enum {
+	GN_TODO_LOW = 3,
+	GN_TODO_MEDIUM = 2,
+	GN_TODO_HIGH = 1
+} gn_todo_priority;
+
+typedef struct {
+	int location;			/* The number of the note in the phone memory */
+	char text[GN_TODO_MAX_LENGTH];		/* The text of the note */
+	gn_todo_priority priority;
+} gn_todo;
+
+/* List of ToDo Notes in phone */
+typedef struct {
+	int number;                       /* The number of notes in phone */
+	int location[GN_TODO_MAX_NUMBER]; /* Location of the nth note */
+} gn_todo_list;
+
+
+/* WAP */
+#define WAP_URL_MAX_LENGTH              258
+#define WAP_NAME_MAX_LENGTH              52
+#define WAP_SETTING_USERNAME_MAX_LENGTH  34
+#define WAP_SETTING_NAME_MAX_LENGTH      22
+#define WAP_SETTING_HOME_MAX_LENGTH      95
+#define WAP_SETTING_APN_MAX_LENGTH      102
+
+/* bookmarks */
+typedef struct {
+	int location;
+	char name[WAP_NAME_MAX_LENGTH];
+	char URL[WAP_URL_MAX_LENGTH];
+} gn_wap_bookmark;
+
+/* settings */
+typedef enum {
+	GN_WAP_SESSION_TEMPORARY = 0,
+	GN_WAP_SESSION_PERMANENT
+} gn_wap_session;
+
+typedef enum {
+	GN_WAP_AUTH_NORMAL = 0,
+	GN_WAP_AUTH_SECURE
+} gn_wap_authentication;
+
+typedef enum {
+	GN_WAP_BEARER_GSMDATA = 1,
+	GN_WAP_BEARER_GPRS    = 3,
+	GN_WAP_BEARER_SMS     = 7,
+	GN_WAP_BEARER_USSD    = 9 /* FIXME real value? */
+} gn_wap_bearer;
+
+typedef enum {
+	GN_WAP_CALL_ANALOGUE,
+	GN_WAP_CALL_ISDN
+} gn_wap_call_type;
+
+typedef enum {
+	GN_WAP_CALL_AUTOMATIC,
+	GN_WAP_CALL_9600,
+	GN_WAP_CALL_14400
+} gn_wap_call_speed;
+
+typedef enum {
+	GN_WAP_LOGIN_MANUAL,
+	GN_WAP_LOGIN_AUTOLOG
+} gn_wap_login;
+
+typedef enum {
+	GN_WAP_GPRS_ALWAYS,
+	GN_WAP_GPRS_WHENNEEDED
+} gn_wap_gprs;
+
+typedef struct {
+	int read_before_write;
+	int location;
+	int successors[4];
+	char number             [WAP_SETTING_NAME_MAX_LENGTH];
+	char gsm_data_ip        [WAP_SETTING_NAME_MAX_LENGTH];
+	char gprs_ip            [WAP_SETTING_NAME_MAX_LENGTH];
+	char name               [WAP_SETTING_NAME_MAX_LENGTH];
+	char home               [WAP_SETTING_HOME_MAX_LENGTH];
+	char gsm_data_username  [WAP_SETTING_USERNAME_MAX_LENGTH];
+	char gsm_data_password  [WAP_SETTING_NAME_MAX_LENGTH];
+	char gprs_username      [WAP_SETTING_USERNAME_MAX_LENGTH];
+	char gprs_password      [WAP_SETTING_NAME_MAX_LENGTH];
+	char access_point_name  [WAP_SETTING_APN_MAX_LENGTH];
+	char sms_service_number [WAP_SETTING_NAME_MAX_LENGTH];
+	char sms_server_number  [WAP_SETTING_NAME_MAX_LENGTH];
+	gn_wap_session session;
+	int security;
+	gn_wap_bearer bearer;
+	gn_wap_authentication gsm_data_authentication;
+	gn_wap_authentication gprs_authentication;
+	gn_wap_call_type call_type;
+	gn_wap_call_speed call_speed;
+	gn_wap_login gsm_data_login;
+	gn_wap_login gprs_login;
+	gn_wap_gprs gprs_connection;
+} gn_wap_setting;
+
+/* This structure is provided to allow common information about the particular
+   model to be looked up in a model independant way. Some of the values here
+   define minimum and maximum levels for values retrieved by the various Get
+   functions for example battery level. They are not defined as constants to
+   allow model specific code to set them during initialisation */
+typedef struct {
+	unsigned char *models; /* Models covered by this type, pipe '|' delimited. */
+
+	/* Minimum and maximum levels for RF signal strength. Units are as per the
+	   setting of RFLevelUnits.  The setting of RFLevelUnits indicates the
+	   default or "native" units used.  In the case of the 3110 and 6110 series
+	   these are arbitrary, ranging from 0 to 4. */
+	float max_rf_level;
+	float min_rf_level;
+	gn_rf_unit rf_level_unit;
+
+	/* Minimum and maximum levels for battery level. Again, units are as per the
+	   setting of GSM_BatteryLevelUnits.  The value that BatteryLevelUnits is set
+	   to indicates the "native" or default value that the phone supports.  In the
+	   case of the 3110 and 6110 series these are arbitrary, ranging from 0 to 4. */
+	float max_battery_level;
+	float min_battery_level;
+	gn_battery_unit battery_level_unit;
+
+	/* Information about date, time and alarm support. In case of alarm
+	   information we provide value for the number of alarms supported. */
+	gn_datetime_support datetime_support;
+	gn_datetime_support alarm_support;
+	int maximum_alarms_number;
+	
+	unsigned int startup_logo_height;   /* Logo widths and heights - if supported */
+	unsigned int startup_logo_width;
+	unsigned int operator_logo_height;
+	unsigned int operator_logo_width;
+	unsigned int caller_logo_height;
+	unsigned int caller_logo_width;
+} gn_phone;
+
+typedef enum {
+	GN_PROFILE_MESSAGE_NoTone	= 0x00,
+	GN_PROFILE_MESSAGE_Standard	= 0x01,
+	GN_PROFILE_MESSAGE_Special	= 0x02,
+	GN_PROFILE_MESSAGE_BeepOnce	= 0x03,
+	GN_PROFILE_MESSAGE_Ascending	= 0x04
+} gn_profile_message_type;
+
+typedef enum {
+	GN_PROFILE_WARNING_Off		= 0xff,
+	GN_PROFILE_WARNING_On		= 0x04
+} gn_profile_warning_type;
+
+typedef enum {
+	GN_PROFILE_VIBRATION_Off	= 0x00,
+	GN_PROFILE_VIBRATION_On		= 0x01
+} gn_profile_vibration_type;
+
+typedef enum {
+	GN_PROFILE_CALLALERT_Ringing		= 0x01,
+	GN_PROFILE_CALLALERT_BeepOnce		= 0x02,
+	GN_PROFILE_CALLALERT_Off		= 0x04,
+	GN_PROFILE_CALLALERT_RingOnce		= 0x05,
+	GN_PROFILE_CALLALERT_Ascending		= 0x06,
+	GN_PROFILE_CALLALERT_CallerGroups	= 0x07
+} gn_profile_callalert_type;
+
+typedef enum {
+	GN_PROFILE_KEYVOL_Off		= 0xff,
+	GN_PROFILE_KEYVOL_Level1	= 0x00,
+	GN_PROFILE_KEYVOL_Level2	= 0x01,
+	GN_PROFILE_KEYVOL_Level3	= 0x02
+} gn_profile_keyvol_type;
+
+typedef enum {
+	GN_PROFILE_VOLUME_Level1	= 0x06,
+	GN_PROFILE_VOLUME_Level2	= 0x07,
+	GN_PROFILE_VOLUME_Level3	= 0x08,
+	GN_PROFILE_VOLUME_Level4	= 0x09,
+	GN_PROFILE_VOLUME_Level5	= 0x0a,
+} gn_profile_volume_type;
+
+/* Structure to hold profile entries. */
+typedef struct {
+	int number;           /* The number of the profile. */
+	char name[40];        /* The name of the profile. */
+	int default_name;     /* 0-6, when default name is used, -1, when not. */
+	int keypad_tone;      /* Volume level for keypad tones. */
+	int lights;           /* Lights on/off. */
+	int call_alert;       /* Incoming call alert. */
+	int ringtone;         /* Ringtone for incoming call alert. */
+	int volume;           /* Volume of the ringing. */
+	int message_tone;     /* The tone for message indication. */
+	int warning_tone;     /* The tone for warning messages. */
+	int vibration;        /* Vibration? */
+	int caller_groups;    /* CallerGroups. */
+	int automatic_answer; /* Does the phone auto-answer incoming call? */
+} gn_profile;
+
+/* Limits for IMEI, Revision, Model and Manufacturer string storage. */
+#define GN_IMEI_MAX_LENGTH         20
+#define GN_REVISION_MAX_LENGTH     20
+#define GN_MODEL_MAX_LENGTH        32
+#define GN_MANUFACTURER_MAX_LENGTH 32
+
+#define GN_BCD_STRING_MAX_LENGTH 40
+
+/* This data-type is used to specify the type of the number. See the official
+   GSM specification 03.40, version 6.1.0, section 9.1.2.5, page 35-37. */
+typedef enum {
+	GN_GSM_NUMBER_Unknown       = 0x81, /* Unknown number */
+	GN_GSM_NUMBER_International = 0x91, /* International number */
+	GN_GSM_NUMBER_National      = 0xa1, /* National number */
+	GN_GSM_NUMBER_Network       = 0xb1, /* Network specific number */
+	GN_GSM_NUMBER_Subscriber    = 0xc1, /* Subscriber number */
+	GN_GSM_NUMBER_Alphanumeric  = 0xd0, /* Alphanumeric number */
+	GN_GSM_NUMBER_Abbreviated   = 0xe1  /* Abbreviated number */
+} gn_gsm_number_type;
+
+typedef struct {
+	gn_gsm_number_type type;
+	char number[GN_BCD_STRING_MAX_LENGTH];
+} gn_gsm_number;
+
+/* Data structures for the call divert */
+typedef enum {
+	GN_CDV_Busy = 0x01,
+	GN_CDV_NoAnswer,
+	GN_CDV_OutOfReach,
+	GN_CDV_NotAvailable,
+	GN_CDV_AllTypes
+} gn_call_divert_type;
+
+typedef enum {
+	GN_CDV_VoiceCalls = 0x01,
+	GN_CDV_FaxCalls,
+	GN_CDV_DataCalls,
+	GN_CDV_AllCalls
+} gn_call_divert_call_type;
+
+typedef enum {
+	GN_CDV_Disable  = 0x00,
+	GN_CDV_Enable   = 0x01,
+	GN_CDV_Query    = 0x02,
+	GN_CDV_Register = 0x03,
+	GN_CDV_Erasure  = 0x04
+} gn_call_divert_operation;
+
+typedef struct {
+	gn_call_divert_type           type;
+	gn_call_divert_call_type     ctype;
+	gn_call_divert_operation operation;
+	gn_gsm_number               number;
+	unsigned int               timeout;
+} gn_call_divert;
+
+typedef struct {
+	int full; /* indicates if we have full data read */
+	unsigned int length;
+	unsigned char *data;
+} gn_raw_data;
+
+/* This enum is used for display status. */
+typedef enum {
+	GN_DISP_Call_In_Progress, /* Call in progress. */
+	GN_DISP_Unknown,          /* The meaning is unknown now :-( */
+	GN_DISP_Unread_SMS,       /* There is Unread SMS. */
+	GN_DISP_Voice_Call,       /* Voice call active. */
+	GN_DISP_Fax_Call,         /* Fax call active. */
+	GN_DISP_Data_Call,        /* Data call active. */
+	GN_DISP_Keyboard_Lock,    /* Keyboard lock status. */
+	GN_DISP_SMS_Storage_Full  /* Full SMS Memory. */
+} gn_display_status;
+
+#define	GN_DRAW_SCREEN_MAX_WIDTH  27
+#define	GN_DRAW_SCREEN_MAX_HEIGHT  6
+
+typedef enum {
+	GN_DISP_DRAW_Clear,
+	GN_DISP_DRAW_Text,
+	GN_DISP_DRAW_Status
+} gn_display_draw_command;
+
+typedef struct {
+	int x;
+	int y;
+	unsigned char text[GN_DRAW_SCREEN_MAX_WIDTH + 1];
+} gn_display_text;
+
+typedef struct {
+	gn_display_draw_command cmd;
+	union {
+		gn_display_text text;
+		gn_display_status status;
+	} data;
+} gn_display_draw_msg;
+
+typedef struct {
+	void (*output_fn)(gn_display_draw_msg *draw);
+	int state;
+	struct timeval last;
+} gn_display_output;
+
+typedef enum {
+	GN_KEY_NONE = 0x00,
+	GN_KEY_1 = 0x01,
+	GN_KEY_2,
+	GN_KEY_3,
+	GN_KEY_4,
+	GN_KEY_5,
+	GN_KEY_6,
+	GN_KEY_7,
+	GN_KEY_8,
+	GN_KEY_9,
+	GN_KEY_0,
+	GN_KEY_HASH,
+	GN_KEY_ASTERISK,
+	GN_KEY_POWER,
+	GN_KEY_GREEN,
+	GN_KEY_RED,
+	GN_KEY_INCREASEVOLUME,
+	GN_KEY_DECREASEVOLUME,
+	GN_KEY_UP = 0x17,
+	GN_KEY_DOWN,
+	GN_KEY_MENU,
+	GN_KEY_NAMES
+} gn_key_code;
+
+typedef struct {
+	int field;
+	char screen[50];
+} gn_netmonitor;
+
+typedef struct {
+	int  userlock;		/* TRUE = user lock, FALSE = factory lock */
+	int  closed;
+	char  data[12];
+	int   counter;
+} gn_locks_info;
+
+typedef struct {
+	int frequency;
+	int volume;
+} gn_tone;
+
+#define GN_RINGTONE_MAX_NAME 20
+#define GN_RINGTONE_MAX_COUNT 256
+
+typedef struct {
+	int location;
+	char name[20];
+	int user_defined;
+	int readable;
+	int writable;
+} gn_ringtone_info;
+
+typedef struct {
+	int count;
+	int userdef_location;
+	int userdef_count;
+	gn_ringtone_info ringtone[GN_RINGTONE_MAX_COUNT];
+} gn_ringtone_list;
+
+typedef enum {
+	GN_LOG_T_NONE = 0,
+	GN_LOG_T_STDERR = 1
+} gn_log_target;
+
+
+typedef enum {
+	GN_FT_None = 0,
+	GN_FT_NOL,
+	GN_FT_NGG,
+	GN_FT_NSL,
+	GN_FT_NLM,
+	GN_FT_BMP,
+	GN_FT_OTA,
+	GN_FT_XPMF,
+	GN_FT_RTTTL,
+	GN_FT_OTT,
+	GN_FT_MIDI,
+	GN_FT_NOKRAW_TONE,
+	GN_FT_GIF,
+	GN_FT_JPG,
+	GN_FT_MID,
+	GN_FT_NRT,
+	GN_FT_PNG,
+} gn_filetypes;
+
+typedef struct {
+	gn_filetypes filetype;   /* file type */
+	unsigned char *id;	/* file id */
+	char name[512];		/* file name */
+	int year;		/* datetime of creation/modification */
+	int month;
+	int day;
+	int hour;
+	int minute;
+	int second;
+	int file_length;	/* size of the file */
+	int togo;		/* amount of bytes to be sent yet */
+	int just_sent;		/* ??? */
+	int folderId;           /* folder id of the file */
+	unsigned char *file;	/* file contents */
+} gn_file;
+
+#define GN_FILES_MAX_COUNT 1024
+
+typedef struct {
+	char path[512];
+	gn_file *files[GN_FILES_MAX_COUNT];
+	int file_count;
+} gn_file_list;
+
+#endif	/* _gnokii_common_h */

Added: trunk/src/host/qemu-neo1973/gnokiigsm/compat.h
===================================================================
--- trunk/src/host/qemu-neo1973/gnokiigsm/compat.h	2007-05-16 22:38:21 UTC (rev 1986)
+++ trunk/src/host/qemu-neo1973/gnokiigsm/compat.h	2007-05-17 00:24:48 UTC (rev 1987)
@@ -0,0 +1,130 @@
+/*
+ * Copyright (c) 2007 OpenMoko, Inc.
+ * Modified for use in QEMU by Andrzej Zaborowski <andrew at openedhand.com>
+ */
+/*
+
+  $Id: compat.h,v 1.54 2007/05/08 19:41:35 pkot Exp $
+
+  G N O K I I
+
+  A Linux/Unix toolset and driver for the 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) 1999-2000 Hugh Blemings, Pavel Janik
+  Copyright (C) 2002-2004 BORBELY Zoltan, Pawel Kot
+  Copyright (C) 2002      Feico de Boer, Markus Plail
+  Copyright (C) 2003      Marcus Godehardt, Ladis Michl
+
+  Header file for various platform compatibility.
+
+*/
+
+#ifndef	_gnokii_compat_h
+#define	_gnokii_compat_h
+
+#include <stdlib.h>
+
+#include <stdarg.h>
+#include <strings.h>
+#include <string.h>
+#include <stdint.h>
+#include <inttypes.h>
+#include <sys/types.h>
+#include <ctype.h>
+#include <sys/file.h>
+#include <sys/time.h>
+#include <sys/socket.h>
+#include <limits.h>
+#include <unistd.h>
+#include <termios.h>
+
+typedef uint8_t		u8;
+typedef uint16_t	u16;
+typedef uint32_t	u32;
+
+#include "config-host.h"
+#define VERSION	"QEMU " QEMU_VERSION
+
+struct gsmmodem_info_s {
+	void (*write)(void *opaque, const char *fmt, ...);
+	void *opaque;
+};
+
+#define GNOKII_API
+
+#undef timerisset
+#undef timerclear
+#undef timercmp
+#undef timeradd
+#undef timersub
+
+/* The following code is borrowed from glibc, please don't reindent it */
+
+/* Convenience macros for operations on timevals.
+   NOTE: `timercmp' does not work for >= or <=.  */
+# define timerisset(tvp)	((tvp)->tv_sec || (tvp)->tv_usec)
+# define timerclear(tvp)	((tvp)->tv_sec = (tvp)->tv_usec = 0)
+# define timercmp(a, b, CMP) 						      \
+  (((a)->tv_sec == (b)->tv_sec) ? 					      \
+   ((a)->tv_usec CMP (b)->tv_usec) : 					      \
+   ((a)->tv_sec CMP (b)->tv_sec))
+# define timeradd(a, b, result)						      \
+  do {									      \
+    (result)->tv_sec = (a)->tv_sec + (b)->tv_sec;			      \
+    (result)->tv_usec = (a)->tv_usec + (b)->tv_usec;			      \
+    if ((result)->tv_usec >= 1000000)					      \
+      {									      \
+	++(result)->tv_sec;						      \
+	(result)->tv_usec -= 1000000;					      \
+      }									      \
+  } while (0)
+# define timersub(a, b, result)						      \
+  do {									      \
+    (result)->tv_sec = (a)->tv_sec - (b)->tv_sec;			      \
+    (result)->tv_usec = (a)->tv_usec - (b)->tv_usec;			      \
+    if ((result)->tv_usec < 0) {					      \
+      --(result)->tv_sec;						      \
+      (result)->tv_usec += 1000000;					      \
+    }									      \
+  } while (0)
+
+/*
+ * The following code was taken from W. Richard Stevens'
+ * "UNIX Network Programming", Volume 1, Second Edition.
+ *
+ * We need the newer CMSG_LEN() and CMSG_SPACE() macros, but few
+ * implementations support them today.  These two macros really need
+ * an ALIGN() macro, but each implementation does this differently.
+ */
+
+#ifndef CMSG_LEN
+#  define CMSG_LEN(size) (sizeof(struct cmsghdr) + (size))
+#endif
+
+#ifndef CMSG_SPACE
+#  define CMSG_SPACE(size) (sizeof(struct cmsghdr) + (size))
+#endif
+
+/* Get rid of long defines. Use #if __unices__ */
+#define __unices__ defined(__svr4__) || defined(__FreeBSD__) || defined(__bsdi__) || defined(__MACH__) || defined(__OpenBSD__) || defined(__NetBSD__)
+
+#define _(x) (x)
+#define N_(x) (x)
+
+#endif

Added: trunk/src/host/qemu-neo1973/gnokiigsm/data.h
===================================================================
--- trunk/src/host/qemu-neo1973/gnokiigsm/data.h	2007-05-16 22:38:21 UTC (rev 1986)
+++ trunk/src/host/qemu-neo1973/gnokiigsm/data.h	2007-05-17 00:24:48 UTC (rev 1987)
@@ -0,0 +1,279 @@
+/*
+
+  $Id: data.h,v 1.80 2007/01/10 19:31:35 pkot Exp $
+
+  G N O K I I
+
+  A Linux/Unix toolset and driver for the 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) 1999-2000 Hugh Blemings & Pavel Janík ml.
+  Copyright (C) 2002-2004 BORBELY Zoltan, Pawel Kot
+  Copyright (C) 2002      Ladis Michl, Markus Plail, Pavel Machek, Chris Kemp
+
+*/
+
+#ifndef _gnokii_data_h
+#define _gnokii_data_h
+
+#include <common.h>
+#include <sms.h>
+#include <call.h>
+#include <error.h>
+#include <rlp-common.h>
+
+/* For models table */
+typedef struct {
+	const char *model;	  /* e.g. 6310 */
+	const char *product_name; /* e.g. NPE-4 */
+	int flags;
+} gn_phone_model;
+
+/* For all 'AT+XXXX=?' commands */
+typedef char gn_choice[10];
+
+/* This is a generic holder for high level information - eg a gn_bmp */
+typedef struct {
+	gn_sms_folder *sms_folder;
+	gn_sms_folder_list *sms_folder_list;
+	gn_sms_raw *raw_sms;         /* This is for phone driver, application using libgnokii should not touch this */
+	gn_sms *sms;                 /* This is for user communication, phone driver should not have to touch this one */
+	gn_phonebook_entry *phonebook_entry;
+	gn_speed_dial *speed_dial;
+	gn_memory_status *memory_status;
+	gn_sms_message_list *message_list[GN_SMS_MESSAGE_MAX_NUMBER][GN_SMS_FOLDER_MAX_NUMBER];
+	gn_sms_status *sms_status;
+	gn_sms_folder_stats *folder_stats[GN_SMS_FOLDER_MAX_NUMBER];
+	gn_sms_message_center *message_center;
+	char *imei;
+	char *revision;
+	char *model;
+	char *manufacturer;
+	gn_network_info *network_info;
+	gn_wap_bookmark *wap_bookmark;
+	gn_wap_setting *wap_setting;
+	gn_todo *todo;
+	gn_todo_list *todo_list;
+	gn_calnote *calnote;
+	gn_calnote_list *calnote_list;
+	gn_bmp *bitmap;
+	gn_ringtone *ringtone;
+	gn_profile *profile;
+	gn_battery_unit *battery_unit;
+	float *battery_level;
+	gn_rf_unit *rf_unit;
+	float *rf_level;
+	gn_display_output *display_output;
+	char *incoming_call_nr;
+	gn_power_source *power_source;
+	gn_timestamp *datetime;
+	gn_calnote_alarm *alarm;
+	gn_raw_data *raw_data;
+	gn_call_divert *call_divert;
+	gn_error (*on_sms)(gn_sms *message, struct gn_statemachine *state);
+	int *display_status;
+	void (*on_cell_broadcast)(gn_cb_message *message);
+	gn_netmonitor *netmonitor;
+	gn_call_info *call_info;
+	void (*call_notification)(gn_call_status call_status, gn_call_info *call_info,
+				  struct gn_statemachine *state);
+	gn_rlp_f96_frame *rlp_frame;
+	int rlp_out_dtx;
+	void (*rlp_rx_callback)(gn_rlp_f96_frame *frame);
+	gn_security_code *security_code;
+	const char *dtmf_string;
+	unsigned char reset_type;
+	gn_key_code key_code;
+	unsigned char character;
+	gn_phone_model *phone;
+	gn_locks_info *locks_info;
+	gn_tone *tone;
+	gn_ringtone_list *ringtone_list;
+	gn_call_active *call_active;
+	gn_file_list *file_list;
+	gn_file *file;
+
+	gn_choice cscs;
+	gn_choice cmux;
+	gn_choice ws46;
+	gn_choice csta;
+	gn_choice cbst;
+	gn_choice crlp;
+	gn_choice cr;
+	gn_choice csns;
+	gn_choice creg;
+	gn_choice cpas;
+	gn_choice cops;
+	gn_choice cfun;
+	gn_choice cbc;
+	gn_choice band;
+	gn_choice cssn;
+} gn_data;
+
+/* 
+ * A structure to hold information about the particular link
+ * The link comes 'under' the phone
+ */
+typedef struct {
+	/* A regularly called loop function. Timeout can be used to make the
+	 * function block or not */
+	gn_error (*loop)(struct timeval *timeout, struct gn_statemachine *state);
+	/* A pointer to the function used to send out a message. This is used
+	 * by the phone specific code to send a message over the link */
+	gn_error (*send_message)(unsigned int messagesize, unsigned char messagetype, unsigned char *message,
+				 struct gn_statemachine *state);
+	void *link_instance;
+} gn_link;
+
+typedef struct {
+	char model[GN_MODEL_MAX_LENGTH];		/* Phone model */
+	char irda_string[GN_MODEL_MAX_LENGTH];		/* If IrDA connection used, string shown in the discovery log */
+	char port_device[GN_DEVICE_NAME_MAX_LENGTH];	/* Port device to use (e.g. /dev/ttyS0) */
+	gn_connection_type connection_type;		/* Connection type (e.g. serial, ir) */
+	int init_length;				/* Number of chars sent to sync the serial port */
+	int serial_baudrate;				/* Baud rate to use */
+	int serial_write_usleep;			/* Inter character delay or <0 to disable */
+	int hardware_handshake;				/* Select between hardware and software handshake */
+	int require_dcd;				/* DCD signal check */
+	int smsc_timeout;				/* How many seconds should we wait for the SMSC response, defaults to 10 seconds */
+	char connect_script[256];			/* Script to run when device connection established */
+	char disconnect_script[256];			/* Script to run when device connection closed */
+	uint8_t rfcomm_cn;				/* RFCOMM channel number to connect */
+	unsigned int sm_retry;				/* Indicates whether statemachine should do retries. Defaults to off. */
+							/* Use with caution -- may break newer DCT4 phones */
+
+	/* do not change the following values from userspace */
+	char m_model[GN_MODEL_MAX_LENGTH];
+	char m_manufacturer[GN_MANUFACTURER_MAX_LENGTH];
+	char m_revision[GN_REVISION_MAX_LENGTH];
+	char m_imei[GN_IMEI_MAX_LENGTH];
+	
+} gn_config;
+
+typedef struct {
+	int fd;
+	gn_connection_type type;
+	void *device_instance;
+} gn_device;
+
+typedef enum {
+	GN_OP_Init,
+	GN_OP_Terminate,
+	GN_OP_GetModel,
+	GN_OP_GetRevision,
+	GN_OP_GetImei,
+	GN_OP_GetManufacturer,
+	GN_OP_Identify,
+	GN_OP_GetBitmap,
+	GN_OP_SetBitmap,
+	GN_OP_GetBatteryLevel,
+	GN_OP_GetRFLevel,
+	GN_OP_DisplayOutput,
+	GN_OP_GetMemoryStatus,
+	GN_OP_ReadPhonebook,
+	GN_OP_WritePhonebook,
+	GN_OP_DeletePhonebook,
+	GN_OP_GetPowersource,
+	GN_OP_GetAlarm,
+	GN_OP_GetSMSStatus,
+	GN_OP_GetIncomingCallNr,
+	GN_OP_GetNetworkInfo,
+	GN_OP_GetSecurityCode,
+	GN_OP_CreateSMSFolder,
+	GN_OP_DeleteSMSFolder,
+	GN_OP_GetSMS,
+	GN_OP_GetSMSnoValidate,
+	GN_OP_GetSMSFolders,
+	GN_OP_GetSMSFolderStatus,
+	GN_OP_GetIncomingSMS,
+	GN_OP_GetUnreadMessages,
+	GN_OP_GetNextSMS,
+	GN_OP_DeleteSMSnoValidate,
+	GN_OP_DeleteSMS,
+	GN_OP_SendSMS,
+	GN_OP_GetSpeedDial,
+	GN_OP_GetSMSCenter,
+	GN_OP_SetSMSCenter,
+	GN_OP_GetDateTime,
+	GN_OP_GetToDo,
+	GN_OP_GetCalendarNote,
+	GN_OP_CallDivert,
+	GN_OP_OnSMS,
+	GN_OP_PollSMS,
+	GN_OP_SetAlarm,
+	GN_OP_SetDateTime,
+	GN_OP_GetProfile,
+	GN_OP_SetProfile,
+	GN_OP_WriteToDo,
+	GN_OP_DeleteAllToDos,
+	GN_OP_WriteCalendarNote,
+	GN_OP_DeleteCalendarNote,
+	GN_OP_SetSpeedDial,
+	GN_OP_GetDisplayStatus,
+	GN_OP_PollDisplay,
+	GN_OP_SaveSMS,
+	GN_OP_SetCellBroadcast,
+	GN_OP_NetMonitor,
+	GN_OP_MakeCall,
+	GN_OP_AnswerCall,
+	GN_OP_CancelCall,
+	GN_OP_SetCallNotification,
+	GN_OP_SendRLPFrame,
+	GN_OP_SetRLPRXCallback,
+	GN_OP_EnterSecurityCode,
+	GN_OP_GetSecurityCodeStatus,
+	GN_OP_ChangeSecurityCode,
+	GN_OP_SendDTMF,
+	GN_OP_Reset,
+	GN_OP_GetRingtone,
+	GN_OP_SetRingtone,
+	GN_OP_GetRawRingtone,
+	GN_OP_SetRawRingtone,
+	GN_OP_PressPhoneKey,
+	GN_OP_ReleasePhoneKey,
+	GN_OP_EnterChar,
+	GN_OP_Subscribe,
+	GN_OP_GetWAPBookmark,
+	GN_OP_WriteWAPBookmark,
+	GN_OP_DeleteWAPBookmark,
+	GN_OP_GetWAPSetting,
+	GN_OP_ActivateWAPSetting,
+	GN_OP_WriteWAPSetting,
+	GN_OP_GetLocksInfo,
+	GN_OP_GetActiveProfile,
+	GN_OP_SetActiveProfile,
+	GN_OP_PlayTone,
+	GN_OP_GetRingtoneList,
+	GN_OP_DeleteRingtone,
+	GN_OP_GetActiveCalls,
+	GN_OP_GetFileList,
+	GN_OP_GetFileId,
+	GN_OP_GetFile,
+	GN_OP_PutFile,
+	GN_OP_DeleteFile,
+	GN_OP_GetFileDetailsById,
+	GN_OP_GetFileById,
+	GN_OP_DeleteFileById,
+	GN_OP_Max,	/* don't append anything after this entry */
+} gn_operation;
+
+/* Undefined functions in fbus/mbus files */
+extern gn_error gn_unimplemented(void);
+#define GN_UNIMPLEMENTED (void *) gn_unimplemented
+
+#endif	/* _gnokii_data_h */

Added: trunk/src/host/qemu-neo1973/gnokiigsm/datapump.c
===================================================================
--- trunk/src/host/qemu-neo1973/gnokiigsm/datapump.c	2007-05-16 22:38:21 UTC (rev 1986)
+++ trunk/src/host/qemu-neo1973/gnokiigsm/datapump.c	2007-05-17 00:24:48 UTC (rev 1987)
@@ -0,0 +1,191 @@
+/*
+
+  $Id: datapump.c,v 1.25 2006/10/03 21:26:37 pkot Exp $
+
+  G N O K I I
+
+  A Linux/Unix toolset and driver for the 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) 1999-2000  Hugh Blemings & Pavel Janík ml.
+  Copyright (C) 2001-2004  Pawel Kot
+  Copyright (C) 2002-2004  BORBELY Zoltan
+
+  This file provides routines to handle processing of data when connected in
+  fax or data mode. Converts data from/to GSM phone to virtual modem
+  interface.
+
+*/
+
+#define		__data_datapump_c
+
+
+#include <stdio.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <signal.h>
+#include <termios.h>
+#include <grp.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+
+
+#include "misc.h"
+#include "gnokii.h"
+#include "compat.h"
+#include "device.h"
+#include "at-emulator.h"
+#include "datapump.h"
+
+/* Prototypes */
+static int	DP_CallBack(rlp_user_inds ind, u8 *buffer, int length);
+static int	DP_SendRLPFrame(gn_rlp_f96_frame *frame, bool out_dtx);
+
+/* Global variables */
+extern bool CommandMode;
+
+/* Local variables */
+static int	PtyRDFD;	/* File descriptor for reading and writing to/from */
+static int	PtyWRFD;	/* pty interface - only different in debug mode. */
+u8 pluscount;
+bool connected;
+
+bool dp_Initialise(int read_fd, int write_fd)
+{
+	PtyRDFD = read_fd;
+	PtyWRFD = write_fd;
+	rlp_initialise(DP_SendRLPFrame, DP_CallBack);
+	rlp_user_request_set(Attach_Req, true);
+	pluscount = 0;
+	connected = false;
+	data.rlp_rx_callback = rlp_f96_frame_display;
+	gn_sm_functions(GN_OP_SetRLPRXCallback, &data, sm);
+
+	return true;
+}
+
+
+static int DP_CallBack(rlp_user_inds ind, u8 *buffer, int length)
+{
+	int i, temp;
+
+	switch(ind) {
+	case Data:
+		if (CommandMode == false) write(PtyWRFD, buffer, length);
+		break;
+	case Conn_Ind:
+		if (CommandMode == false) gn_atem_modem_result(MR_CARRIER);
+		rlp_user_request_set(Conn_Req, true);
+		break;
+	case StatusChange:
+		if (buffer[0] == 0) {
+			connected = true;
+			if (CommandMode == false) gn_atem_modem_result(MR_CONNECT);
+		}
+		break;
+	case Disc_Ind:
+		if (CommandMode == false) gn_atem_modem_result(MR_NOCARRIER);
+		connected = false;
+		/* Set the call passup back to the at emulator */
+		data.call_notification = gn_atem_call_passup;
+		gn_sm_functions(GN_OP_SetCallNotification, &data, sm);
+		CommandMode = true;
+		break;
+	case Reset_Ind:
+		rlp_user_request_set(Reset_Resp, true);
+		break;
+	case GetData:
+		if (queue.n > 0) {
+			temp = queue.n < sizeof(buffer) ? queue.n : sizeof(buffer);
+			for (i = 0; i < temp; i++) {
+				buffer[i] = queue.buf[queue.head++];
+				queue.head %= sizeof(queue.buf);
+				queue.n--;
+			}
+
+			/* This will only check +++ and the beginning of a read */
+			/* But there should be a pause before it anyway */
+
+			if (buffer[0] == '+') {
+				pluscount++;
+				if (temp > 1) {
+					if (buffer[1] == '+') pluscount++;
+					else pluscount = 0;
+					if (temp > 2) {
+						if (buffer[2] == '+') pluscount++;
+						else pluscount = 0;
+						if (temp > 3) pluscount = 0;
+					}
+				}
+			} else pluscount = 0;
+
+			if (pluscount == 3) {
+				CommandMode = true;
+				/* Set the call passup back to the at emulator */
+				data.call_notification = gn_atem_call_passup;
+				gn_sm_functions(GN_OP_SetCallNotification, &data, sm);
+				gn_atem_string_out("\r\n");
+				gn_atem_modem_result(MR_OK);
+				break;
+			}
+
+			return temp;
+		}
+		break;
+	default:
+		break;
+	}
+	return 0;
+}
+
+void dp_CallPassup(gn_call_status CallStatus, gn_call_info *CallInfo, struct gn_statemachine *state)
+{
+	dprintf("dp_CallPassup called with %d\n", CallStatus);
+
+	switch (CallStatus) {
+	case GN_CALL_Established:
+		if (CommandMode == false) gn_atem_modem_result(MR_CARRIER);
+		rlp_user_request_set(Conn_Req, true);
+		connected = true;
+		break;
+	case GN_CALL_LocalHangup:
+	case GN_CALL_RemoteHangup:
+		CommandMode = true;
+		/* Set the call passup back to the at emulator */
+		data.call_notification = gn_atem_call_passup;
+		gn_sm_functions(GN_OP_SetCallNotification, &data, sm);
+		gn_atem_modem_result(MR_NOCARRIER);
+		rlp_user_request_set(Disc_Req, true);
+		connected = false;
+		/* send the hangup event to the at emulator */
+		gn_atem_call_passup(CallStatus, CallInfo, state);
+		break;
+	default:
+		break;
+	}
+}
+
+static int DP_SendRLPFrame(gn_rlp_f96_frame *frame, bool out_dtx)
+{
+	data.rlp_frame = frame;
+	data.rlp_out_dtx = out_dtx;
+
+	return gn_sm_functions(GN_OP_SendRLPFrame, &data, sm);
+}

Added: trunk/src/host/qemu-neo1973/gnokiigsm/datapump.h
===================================================================
--- trunk/src/host/qemu-neo1973/gnokiigsm/datapump.h	2007-05-16 22:38:21 UTC (rev 1986)
+++ trunk/src/host/qemu-neo1973/gnokiigsm/datapump.h	2007-05-17 00:24:48 UTC (rev 1987)
@@ -0,0 +1,41 @@
+/*
+
+  $Id: datapump.h,v 1.12 2003/03/06 21:31:08 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) 1999, 2000 Hugh Blemings & Pavel Janík ml.
+
+  Header file for data pump code.
+
+*/
+
+#ifndef _gnokii_data_datapump_h
+#define _gnokii_data_datapump_h
+
+#include "compat.h"
+#include "gnokii.h"
+
+/* Prototypes */
+bool	dp_Initialise(int read_fd, int write_fd);
+void    dp_CallPassup(gn_call_status call_status, gn_call_info *call_info, struct gn_statemachine *state);
+
+#endif	/* _gnokii_data_datapump_h */

Added: trunk/src/host/qemu-neo1973/gnokiigsm/device.h
===================================================================
--- trunk/src/host/qemu-neo1973/gnokiigsm/device.h	2007-05-16 22:38:21 UTC (rev 1986)
+++ trunk/src/host/qemu-neo1973/gnokiigsm/device.h	2007-05-17 00:24:48 UTC (rev 1987)
@@ -0,0 +1,57 @@
+/*
+
+  $Id: device.h,v 1.27 2006/10/03 21:26:38 pkot Exp $
+
+  G N O K I I
+
+  A Linux/Unix toolset and driver for the 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) 1999-2000 Hugh Blemings & Pavel Janík ml.
+  Copyright (C) 2002      BORBELY Zoltan, Ladis Michl, Pawel Kot, Chris Kemp
+  Header file device access code.
+
+*/
+
+#ifndef _gnokii_device_h
+#define _gnokii_device_h
+
+#include "compat.h"
+#include "misc.h"
+#include "gnokii.h"
+
+GNOKII_API int device_getfd(struct gn_statemachine *state);
+
+int device_open(const char *file, int with_odd_parity, int with_async,
+		int with_hw_handshake, gn_connection_type device_type,
+		struct gn_statemachine *state);
+void device_close(struct gn_statemachine *state);
+void device_reset(struct gn_statemachine *state);
+
+void device_setdtrrts(int dtr, int rts, struct gn_statemachine *state);
+void device_changespeed(int speed, struct gn_statemachine *state);
+
+size_t device_read(__ptr_t buf, size_t nbytes, struct gn_statemachine *state);
+size_t device_write(const __ptr_t buf, size_t n, struct gn_statemachine *state);
+
+int device_select(struct timeval *timeout, struct gn_statemachine *state);
+
+gn_error device_nreceived(int *n, struct gn_statemachine *state);
+gn_error device_flush(struct gn_statemachine *state);
+
+#endif  /* _gnokii_device_h */

Added: trunk/src/host/qemu-neo1973/gnokiigsm/encoding.h
===================================================================
--- trunk/src/host/qemu-neo1973/gnokiigsm/encoding.h	2007-05-16 22:38:21 UTC (rev 1986)
+++ trunk/src/host/qemu-neo1973/gnokiigsm/encoding.h	2007-05-17 00:24:48 UTC (rev 1987)
@@ -0,0 +1,58 @@
+/*
+
+  $Id: encoding.h,v 1.20 2006/06/11 16:39:11 deller Exp $
+
+  G N O K I I
+
+  A Linux/Unix toolset and driver for the 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) 1999-2000 Hugh Blemings, Pavel Janik
+  Copyright (C) 2001-2004 Pawel Kot
+
+  Include file for encoding functions.
+
+*/
+
+#ifndef _gnokii_encoding_h
+#define _gnokii_encoding_h
+
+GNOKII_API int gn_char_def_alphabet(unsigned char *string);
+
+/*
+ *
+ * Set encoding to use for exchanging data between Gnokii and the application
+ *
+ * Normally, when communicating with the application, Gnokii uses the
+ * encoding set with the setlocale() call. For the (standard) call
+ * setlocale(LC_ALL, ""), this is the encoding specified by the user in the
+ * LANG variable. This function can be used to override this behaviour. E.g.,
+ * to make Gnokii always interpret and return string values using the UTF-8
+ * charset, call gn_set_encoding("UTF-8").
+ * 
+ * This has nothing to do with the encoding used to communicate with the
+ * phone itself, which is a totally different issue.
+ *
+ * Parameters:
+ *     encoding     The name of the encoding (length must not exceed 63 chars)
+ *
+ */
+GNOKII_API void gn_char_set_encoding(const char* encoding);
+GNOKII_API const char *gn_char_get_encoding();
+
+#endif /* _gnokii_encoding_h */

Added: trunk/src/host/qemu-neo1973/gnokiigsm/error.h
===================================================================
--- trunk/src/host/qemu-neo1973/gnokiigsm/error.h	2007-05-16 22:38:21 UTC (rev 1986)
+++ trunk/src/host/qemu-neo1973/gnokiigsm/error.h	2007-05-17 00:24:48 UTC (rev 1987)
@@ -0,0 +1,94 @@
+/*
+
+  $Id: error.h,v 1.21 2006/08/09 19:36:58 pkot Exp $
+
+  G N O K I I
+
+  A Linux/Unix toolset and driver for the 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) 1999-2000 Hugh Blemings, Pavel Janik
+  Copyright (C) 2001-2004 BORBELY Zoltan, Pawel Kot
+
+  Error codes.
+
+*/
+
+#ifndef _gnokii_error_h
+#define _gnokii_error_h
+
+/* 
+ * Define standard GSM error/return code values. These codes are also used for
+ * some internal functions such as SIM read/write in the model specific code. 
+ */
+typedef enum {
+	/* General codes */
+	GN_ERR_NONE = 0,		/* No error. */
+	GN_ERR_FAILED,			/* Command failed. */
+	GN_ERR_UNKNOWNMODEL,		/* Model specified isn't known/supported. */
+	GN_ERR_INVALIDSECURITYCODE,	/* Invalid Security code. */
+	GN_ERR_INTERNALERROR,		/* Problem occured internal to model specific code. */
+	GN_ERR_NOTIMPLEMENTED,		/* Command called isn't implemented in model. */
+	GN_ERR_NOTSUPPORTED,		/* Function not supported by the phone */
+	GN_ERR_USERCANCELED,		/* User aborted the action. */
+	GN_ERR_UNKNOWN,			/* Unknown error - well better than nothing!! */
+	GN_ERR_MEMORYFULL,		/* The specified memory is full. */
+
+	/* Statemachine */
+	GN_ERR_NOLINK,			/* Couldn't establish link with phone. */
+	GN_ERR_TIMEOUT,			/* Command timed out. */
+	GN_ERR_TRYAGAIN,		/* Try again. */
+	GN_ERR_WAITING,			/* Waiting for the next part of the message. */
+	GN_ERR_NOTREADY,		/* Device not ready. */
+	GN_ERR_BUSY,			/* Command is still being executed. */
+	
+	/* Locations */
+	GN_ERR_INVALIDLOCATION,		/* The given memory location has not valid location. */
+	GN_ERR_INVALIDMEMORYTYPE,	/* Invalid type of memory. */
+	GN_ERR_EMPTYLOCATION,		/* The given location is empty. */
+
+	/* Format */
+	GN_ERR_ENTRYTOOLONG, 		/* The given entry is too long */
+	GN_ERR_WRONGDATAFORMAT,		/* Data format is not valid */
+	GN_ERR_INVALIDSIZE,		/* Wrong size of the object */
+
+	/* The following are here in anticipation of data call requirements. */
+	GN_ERR_LINEBUSY,		/* Outgoing call requested reported line busy */
+	GN_ERR_NOCARRIER,		/* No Carrier error during data call setup ? */
+
+	/* The following value signals the current frame is unhandled */
+	GN_ERR_UNHANDLEDFRAME,		/* The current frame isn't handled by the incoming function */
+	GN_ERR_UNSOLICITED,		/* Unsolicited message received. */
+
+	/* Other */
+	GN_ERR_NONEWCBRECEIVED,		/* Attempt to read CB when no new CB received */
+	GN_ERR_SIMPROBLEM,		/* SIM card missing or damaged */
+	GN_ERR_CODEREQUIRED,		/* PIN or PUK code required */
+	GN_ERR_NOTAVAILABLE,		/* The requested information is not available */
+
+	/* Config */
+	GN_ERR_NOCONFIG,		/* Config file cannot be found */
+	GN_ERR_NOPHONE,			/* Either global or given phone section cannot be found */
+	GN_ERR_NOLOG,			/* Incorrect logging section configuration */
+	GN_ERR_NOMODEL,			/* No phone model specified */
+	GN_ERR_NOPORT			/* No port specified */
+} gn_error;
+
+GNOKII_API char *gn_error_print(gn_error e);
+
+#endif /* _gnokii_error_h */

Added: trunk/src/host/qemu-neo1973/gnokiigsm/gnokii-internal.h
===================================================================
--- trunk/src/host/qemu-neo1973/gnokiigsm/gnokii-internal.h	2007-05-16 22:38:21 UTC (rev 1986)
+++ trunk/src/host/qemu-neo1973/gnokiigsm/gnokii-internal.h	2007-05-17 00:24:48 UTC (rev 1987)
@@ -0,0 +1,175 @@
+/*
+
+  $Id: gnokii-internal.h,v 1.35 2007/04/14 19:36:35 pkot Exp $
+
+  G N O K I I
+
+  A Linux/Unix toolset and driver for the 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) 1999-2000 Hugh Blemings, Pavel Janik
+  Copyright (C) 2000-2004 Pawel Kot, BORBELY Zoltan
+  Copyright (C) 2000      Marcin Wiacek, Chris Kemp
+  Copyright (C) 2002      Ladis Michl
+  Copyright (C) 2003      Osma Suominen, Martin Goldhahn
+
+  Internal API for libgnokii
+
+*/
+
+#ifndef _gnokii_internal_h
+#define _gnokii_internal_h
+
+#include "compat.h"
+#include "misc.h"
+
+#if !defined(GNOKII_DEPRECATED)
+#  define GNOKII_DEPRECATED /* do not warn about deprecated functions here */
+#endif
+
+#include "gnokii.h"
+
+/* utils */
+gn_connection_type gn_get_connectiontype(const char *connection_type_string);
+
+/* SMS */
+gn_error sms_parse(int offset, gn_data *data);
+gn_error sms_request(gn_data *data, struct gn_statemachine *state);
+gn_error sms_prepare(gn_sms *sms, gn_sms_raw *rawsms);
+gn_timestamp *sms_timestamp_unpack(unsigned char *number, gn_timestamp *dt);
+unsigned char *sms_timestamp_pack(gn_timestamp *dt, unsigned char *number);
+
+/* Statemachine */
+gn_error sm_initialise(struct gn_statemachine *state);
+gn_error sm_message_send(u16 messagesize, u8 messagetype, void *message, struct gn_statemachine *state);
+gn_error sm_wait_for(unsigned char messagetype, gn_data *data, struct gn_statemachine *state);
+void sm_incoming_function(u8 messagetype, void *message, u16 messagesize, struct gn_statemachine *state);
+void sm_incoming_acknowledge(struct gn_statemachine *state);
+void sm_reset(struct gn_statemachine *state);
+gn_error sm_error_get(unsigned char messagetype, struct gn_statemachine *state);
+gn_error sm_block_timeout(int waitfor, int t, gn_data *data, struct gn_statemachine *state);
+gn_error sm_block(int waitfor, gn_data *data, struct gn_statemachine *state);
+gn_error sm_block_no_retry_timeout(int waitfor, int t, gn_data *data, struct gn_statemachine *state);
+gn_error sm_block_no_retry(int waitfor, gn_data *data, struct gn_statemachine *state);
+gn_error sm_block_ack(struct gn_statemachine *state);
+void sm_message_dump(gn_log_func_t lfunc, int messagetype, unsigned char *message, int length);
+void sm_unhandled_frame_dump(int messagetype, unsigned char *message, int length, struct gn_statemachine *state);
+
+extern void hex2bin(unsigned char *dest, const unsigned char *src, unsigned int len);
+extern void bin2hex(unsigned char *dest, const unsigned char *src, unsigned int len);
+
+int char_7bit_unpack(unsigned int offset, unsigned int in_length, unsigned int out_length,
+		     unsigned char *input, unsigned char *output);
+int char_7bit_pack(unsigned int offset, unsigned char *input, unsigned char *output,
+		   unsigned int *in_len);
+
+int char_mblen(const char *src);
+
+unsigned int char_unicode_decode(unsigned char* dest, const unsigned char* src, int len);
+unsigned int char_unicode_encode(unsigned char* dest, const unsigned char* src, int len);
+
+void char_ascii_decode(unsigned char* dest, const unsigned char* src, int len);
+size_t char_ascii_encode(char *dest, size_t dest_len, const char *src, size_t len);
+
+void char_hex_decode(unsigned char* dest, const unsigned char* src, int len);
+size_t char_hex_encode(char *dest, size_t dest_len, const char *src, size_t len);
+
+void char_ucs2_decode(unsigned char* dest, const unsigned char* src, int len);
+size_t char_ucs2_encode(char *dest, size_t dest_len, const char *src, size_t len);
+
+unsigned char char_def_alphabet_encode(unsigned char value);
+unsigned char char_def_alphabet_decode(unsigned char value);
+
+extern char *char_bcd_number_get(u8 *number);
+extern int char_semi_octet_pack(char *number, unsigned char *output, gn_gsm_number_type type);
+
+/* Ringtones */
+int vcal_time_get(gn_timestamp *dt, char *time);
+int calnote_fill(gn_calnote *note, char *type, char *text, char *desc,
+		 char *time, char *alarm);
+int todo_fill(gn_todo *note, char *text, char *todo_priority);
+
+/* Ringtone Files */
+gn_error file_rtttl_save(FILE *file, gn_ringtone *ringtone);
+gn_error file_ott_save(FILE *file, gn_ringtone *ringtone);
+gn_error file_midi_save(FILE *file, gn_ringtone *ringtone);
+gn_error file_nokraw_save(FILE *file, gn_ringtone *ringtone, int dct4);
+
+gn_error file_rtttl_load(FILE *file, gn_ringtone *ringtone);
+gn_error file_ott_load(FILE *file, gn_ringtone *ringtone);
+gn_error file_midi_load(FILE *file, gn_ringtone *ringtone);
+gn_error file_nokraw_load(FILE *file, gn_ringtone *ringtone);
+
+/* Bitmap Files */
+
+void file_nol_save(FILE *file, gn_bmp *bitmap, gn_phone *info);
+void file_ngg_save(FILE *file, gn_bmp *bitmap, gn_phone *info);
+void file_nsl_save(FILE *file, gn_bmp *bitmap, gn_phone *info);
+void file_nlm_save(FILE *file, gn_bmp *bitmap);
+void file_ota_save(FILE *file, gn_bmp *bitmap);
+void file_bmp_save(FILE *file, gn_bmp *bitmap);
+
+#ifdef XPM
+void file_xpm_save(char *filename, gn_bmp *bitmap);
+#endif
+
+gn_error file_ngg_load(FILE *file, gn_bmp *bitmap, gn_phone *info);
+gn_error file_nol_load(FILE *file, gn_bmp *bitmap, gn_phone *info);
+gn_error file_nsl_load(FILE *file, gn_bmp *bitmap);
+gn_error file_nlm_load(FILE *file, gn_bmp *bitmap);
+gn_error file_ota_load(FILE *file, gn_bmp *bitmap, gn_phone *info);
+gn_error file_bmp_load(FILE *file, gn_bmp *bitmap);
+
+#ifdef XPM
+gn_error file_xpm_load(char *filename, gn_bmp *bitmap);
+#endif
+
+int ringtone_sms_encode(unsigned char *message, gn_ringtone *ringtone);
+int imelody_sms_encode(unsigned char *imelody, unsigned char *message);
+gn_error phonebook_decode(unsigned char *blockstart, int length,
+			  gn_data *data, int blocks, int memtype, int speeddial_pos);
+gn_error calnote_decode(unsigned char *message, int length, gn_data *data);
+gn_error calnote_get_alarm(int alarmdiff, gn_timestamp *time, gn_timestamp *alarm);
+
+int sms_nokia_smart_message_part_pack(unsigned char *msg, unsigned int size,
+				      unsigned int type, bool first);
+int sms_nokia_text_encode(unsigned char *text, unsigned char *message, bool first);
+int sms_nokia_bitmap_encode(gn_bmp *bitmap, unsigned char *message, bool first);
+
+struct gn_cfg_header *cfg_file_read(const char *filename);
+typedef void (*cfg_foreach_func)(const char *section, const char *key, const char *value);
+void cfg_foreach(const char *section, cfg_foreach_func func);
+char *cfg_set(struct gn_cfg_header *cfg, const char *section, const char *key, const char *value);
+int cfg_file_write(struct gn_cfg_header *cfg, const char *filename);
+
+gn_error isdn_cause2gn_error(char **src, char **msg, unsigned char loc, unsigned char cause);
+
+int utf8_decode(char *dest, size_t destlen, const char *src, size_t inlen);
+int utf8_encode(char *dest, int destlen, const char *src, int inlen);
+
+int string_base64(const char *instring);
+int base64_decode(char *dest, int destlen, const char *src, int inlen);
+int base64_encode(char *dest, int destlen, const char *src, int inlen);
+
+int utf8_base64_decode(char *dest, int destlen, const char *src, int inlen);
+int utf8_base64_encode(char *dest, int destlen, const char *src, int inlen);
+
+int add_slashes(char *dest, char *src, int maxlen, int len);
+int strip_slashes(char *dest, char *src, int maxlen, int len);
+
+#endif /* _gnokii_internal_h */

Added: trunk/src/host/qemu-neo1973/gnokiigsm/gnokii.h
===================================================================
--- trunk/src/host/qemu-neo1973/gnokiigsm/gnokii.h	2007-05-16 22:38:21 UTC (rev 1986)
+++ trunk/src/host/qemu-neo1973/gnokiigsm/gnokii.h	2007-05-17 00:24:48 UTC (rev 1987)
@@ -0,0 +1,306 @@
+/*
+
+  $Id: gnokii.h,v 1.108 2006/11/26 16:24:24 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) 1999-2000 Hugh Blemings & Pavel Janík ml.
+  Copyright (C) 2001-2005 Pawel Kot
+  Copyright (C) 2001      Chris Kemp
+  copyright (C) 2002      Markus Plail
+  Copyright (C) 2002-2003 BORBELY Zoltan, Ladis Michl
+  Copyright (C) 2004      Martin Goldhahn
+  Copyright (C) 2006      Helge Deller
+  
+  Main header file for gnokii. Include just this file in your app.
+*/
+
+#ifndef _gnokii_h
+#define _gnokii_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Some portability definitions first */
+#if defined(__linux__) || defined(__GLIBC__)
+#  include <stdint.h>
+#  include <sys/time.h>
+#elif defined(__svr4__) || defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__bsdi__) || defined(__MACH__)
+#  include <inttypes.h>
+#  include <sys/time.h>
+#elif defined(_MSC_VER) && defined(WIN32)
+#  include <Winsock.h>	/* for struct timeval */
+typedef unsigned char uint8_t;
+#endif
+
+#include <stdarg.h>
+	
+#ifndef GNOKII_API
+# define GNOKII_API
+#endif
+
+struct gn_statemachine;
+
+#include <error.h>
+#include <common.h>
+#include <data.h>
+#include <encoding.h>
+#include <sms.h>
+#include <call.h>
+#include <networks.h>
+#include <bitmaps.h>
+#include <ringtones.h>
+#include <virtmodem.h>
+#include <rlp-common.h>
+#include <wappush.h>
+
+#include <statemachine.h>
+
+/* Gnokii library functions - they all start with gn_lib_ */
+/* Get the current runtime version (LIBGNOKII_VERSION) of libgnokii - see LIBGNOKII_MAKE_VERSION() */
+GNOKII_API unsigned int gn_lib_version();
+
+/* free any resources which were used by libgnokii */
+GNOKII_API void gn_lib_library_free( void );
+
+/* return last error code from functions below */
+GNOKII_API gn_error gn_lib_lasterror( struct gn_statemachine *state );
+
+/* initialize gnokii library and structures for given phone.
+   configname is the name of the profile, if empty or NULL, [global] will be taken.
+   gn_lib_phoneprofile_load assumes default config file. */
+GNOKII_API gn_error gn_lib_phoneprofile_load_from_file( const char *configfile, const char *configname, struct gn_statemachine **state );
+GNOKII_API gn_error gn_lib_phoneprofile_load( const char *configname, struct gn_statemachine **state );
+
+/* Free any structures and resources which were loaded in this state machine. */
+GNOKII_API gn_error gn_lib_phoneprofile_free( struct gn_statemachine **state );
+
+/* opens connection to the phone. Necessary locking will be made */
+GNOKII_API gn_error gn_lib_phone_open( struct gn_statemachine *state );
+
+/* closes the connection to the phone */
+GNOKII_API gn_error gn_lib_phone_close( struct gn_statemachine *state );
+
+/* ask phone for static information (model, manufacturer, revision and imei) */
+GNOKII_API const char *gn_lib_get_phone_model       ( struct gn_statemachine *state ); /* e.g. 6310 */
+GNOKII_API const char *gn_lib_get_phone_product_name( struct gn_statemachine *state ); /* e.g. NPE-4 */
+GNOKII_API const char *gn_lib_get_phone_manufacturer( struct gn_statemachine *state ); /* e.g. Nokia */
+GNOKII_API const char *gn_lib_get_phone_revision    ( struct gn_statemachine *state ); /* e.g. V 04.20 */
+GNOKII_API const char *gn_lib_get_phone_imei        ( struct gn_statemachine *state );
+
+/* Get the key value from the given section and the key name */
+GNOKII_API const char *gn_lib_cfg_get(const char *section, const char *key);
+
+/* Phone Addressbook functions */
+/* get number of used/free phone addressbook memory slots */
+GNOKII_API gn_error gn_lib_addressbook_memstat( struct gn_statemachine *state,
+		const gn_memory_type memory_type,
+		int *num_used, int *num_free );
+
+/* remove an addressbook entry physically from phone. */
+GNOKII_API gn_error gn_lib_phonebook_entry_delete( struct gn_statemachine *state,
+		const gn_memory_type memory_type, const int index );
+
+/* check if given addressbook entry is empty. Returns "true" if empty, 0 if not. */
+GNOKII_API int gn_lib_phonebook_entry_isempty( struct gn_statemachine *state,
+		const gn_memory_type memory_type, const int index );
+
+/* read given addressbook entry into internal structure. Afterwards ask for each value with functions below */
+GNOKII_API gn_error gn_lib_phonebook_read_entry( struct gn_statemachine *state,
+		const gn_memory_type memory_type, const int index );
+
+/* after reading an entry with gn_lib_phonebook_read_entry() ask for the values of the phonebook entry */
+GNOKII_API const char *            gn_lib_get_pb_name           ( struct gn_statemachine *state ); /* Mr. Miller */
+GNOKII_API const char *            gn_lib_get_pb_number         ( struct gn_statemachine *state ); /* +18001189383 */
+GNOKII_API gn_phonebook_group_type gn_lib_get_pb_caller_group   ( struct gn_statemachine *state ); /* */
+GNOKII_API gn_memory_type          gn_lib_get_pb_memtype        ( struct gn_statemachine *state ); /* */
+GNOKII_API int                     gn_lib_get_pb_location       ( struct gn_statemachine *state ); /* 1*/
+GNOKII_API gn_timestamp            gn_lib_get_pb_date           ( struct gn_statemachine *state ); /* */
+GNOKII_API int                     gn_lib_get_pb_num_subentries ( struct gn_statemachine *state ); /* */
+GNOKII_API gn_error	gn_lib_get_pb_subentry( struct gn_statemachine *state, const int index, 
+			gn_phonebook_entry_type *entry_type, gn_phonebook_number_type *number_type, const char **number );
+
+/* How to write to a phonebook entry with 3 steps:
+   a) call gn_lib_phonebook_prepare_write_entry() to initialize structures
+   b) call gn_lib_set_pb_*() to set values (do this for each value you want to set)
+   c) call gn_lib_phonebook_write_entry() to write it physically to phone
+ */
+
+/* initialize gnokii internal phonebook structure */
+GNOKII_API gn_error gn_lib_phonebook_prepare_write_entry( struct gn_statemachine *state );
+
+/* call each of the functions to set a specific value in current internal memory */
+GNOKII_API gn_error gn_lib_set_pb_name        ( struct gn_statemachine *state, const char *name ); /* Mr. Miller */
+GNOKII_API gn_error gn_lib_set_pb_number      ( struct gn_statemachine *state, const char *number ); /* +18001189383 */
+GNOKII_API gn_error gn_lib_set_pb_caller_group( struct gn_statemachine *state, gn_phonebook_group_type grouptype ); /* */
+GNOKII_API gn_error gn_lib_set_pb_memtype     ( struct gn_statemachine *state, gn_memory_type memtype ); /* */
+GNOKII_API gn_error gn_lib_set_pb_location    ( struct gn_statemachine *state, int location ); /* 1*/
+GNOKII_API gn_error gn_lib_set_pb_date        ( struct gn_statemachine *state, gn_timestamp timestamp ); /* */
+GNOKII_API gn_error gn_lib_set_pb_subentry    ( struct gn_statemachine *state, const int index, /* index=-1 appends it */
+	gn_phonebook_entry_type entry_type, gn_phonebook_number_type number_type, const char *number );
+
+/* and now write the addressbook entry physically to phone. */
+GNOKII_API gn_error gn_lib_phonebook_write_entry( struct gn_statemachine *state,
+        const gn_memory_type memory_type, const int index );
+
+GNOKII_API char *gn_subentrytype2string(gn_phonebook_entry_type entry_type, gn_phonebook_number_type number_type);
+
+/* standard helper functions */
+
+/* use this function to get list of all supported phone models.
+   Just start with num=0 and increase until you get back NULL */
+GNOKII_API const char *gn_lib_get_supported_phone_model( const int num );
+
+/* use this function to get list of all supported connection type strings.
+   Just start with num=0 and increase until you get back NULL */
+GNOKII_API const char *gn_lib_get_supported_connection( const int num );
+
+/* use this function to search for a phone which is connected to this
+   computer. Currently libgnokii will search only on IRDA and bluetooth.
+   The state variable will be initialized if a phone was found. */
+GNOKII_API gn_error gn_lib_search_one_connected_phone( struct gn_statemachine **state );
+
+/* Misc */
+GNOKII_API gn_memory_type gn_str2memory_type(const char *s);
+GNOKII_API const char *gn_memory_type2str(gn_memory_type mt);
+GNOKII_API int gn_timestamp_isvalid(const gn_timestamp dt);
+GNOKII_API void gn_timestamp_set(gn_timestamp *dt, int year, int month, int day,
+			int hour, int minute, int second, int timezone);
+GNOKII_API void gn_timestamp_get(gn_timestamp *dt, int *year, int *month, int *day,
+			int *hour, int *minute, int *second, int *timezone);
+
+
+
+/****************************************************************************/
+/* ALL FOLLOWING FUNCTIONS SHOULD BE USED BY GNOKII INTERNAL PROGRAMS ONLY  */
+/****************************************************************************/
+
+#ifndef GNOKII_DEPRECATED
+#if __GNUC__ - 0 > 3 || (__GNUC__ - 0 == 3 && __GNUC_MINOR__ - 0 >= 2)
+  /* gcc >= 3.2 */
+# define GNOKII_DEPRECATED __attribute__ ((deprecated))
+#elif defined(_MSC_VER) && (_MSC_VER >= 1300) && (_MSC_VER < 1400)
+  /* msvc >= 7 */
+# define GNOKII_DEPRECATED __declspec(deprecated)
+#elif defined(_MSV_VER) && (_MSC_VER >= 1400)
+  /* MS Visual Studio 2005 */
+# define GNOKII_DEPRECATED
+#else
+# define GNOKII_DEPRECATED
+#endif
+#endif
+
+/* The global variable that keeps the current configuration. This should be
+ * filled in before the phone initialization */
+extern GNOKII_API struct gn_cfg_header *gn_cfg_info GNOKII_DEPRECATED;
+
+/* Files */
+GNOKII_API int gn_file_text_save(char *filename, char *text, int mode) GNOKII_DEPRECATED;
+
+/* Zero the gn_data structure */
+GNOKII_API void gn_data_clear(gn_data *data);
+extern GNOKII_API gn_phone *gn_gsm_info;
+extern GNOKII_API gn_error (*gn_gsm_f)(gn_operation op, gn_data *data,
+			 struct gn_statemachine *state);
+/* Initialise the connection and setup the driver according to the current
+ * configuration */
+GNOKII_API gn_error gn_gsm_initialise(struct gn_statemachine *sm) GNOKII_DEPRECATED;
+
+/* Config handling */
+/* Get the key value from the given config, given section and the key name */
+GNOKII_API char *gn_cfg_get(struct gn_cfg_header *cfg, const char *section, const char *key) GNOKII_DEPRECATED;
+GNOKII_API gn_error gn_cfg_read(char **bindir) GNOKII_DEPRECATED;
+/* Read the config from the file filename */
+GNOKII_API gn_error gn_cfg_file_read(const char *filename) GNOKII_DEPRECATED;
+/* Read the config from the file already put into the memory */
+GNOKII_API gn_error gn_cfg_memory_read(const char **lines) GNOKII_DEPRECATED;
+/* Read the config from the standard $HOME/.gnokiirc or /etc/gnokiirc locations */
+GNOKII_API gn_error gn_cfg_read_default() GNOKII_DEPRECATED;
+/* free any resources which were used by libgnokii */
+GNOKII_API void gn_cfg_free_default() GNOKII_DEPRECATED;
+/* Use phone_iname section for the communication. Default is the global section */
+GNOKII_API gn_error gn_cfg_phone_load(const char *iname, struct gn_statemachine *state) GNOKII_DEPRECATED;
+
+/* In/Out routines, file formats */
+GNOKII_API int gn_phonebook2vcard(FILE *f, gn_phonebook_entry *entry, char *location);
+GNOKII_API int gn_vcard2phonebook(FILE *f, gn_phonebook_entry *entry);
+
+GNOKII_API int gn_phonebook2ldif(FILE *f, gn_phonebook_entry *entry);
+GNOKII_API int gn_ldif2phonebook(FILE *f, gn_phonebook_entry *entry);
+
+/* reads internal gnokii raw phonebook format */
+GNOKII_API gn_error gn_file_phonebook_raw_parse(gn_phonebook_entry *entry, char *buffer);
+GNOKII_API gn_error gn_file_phonebook_raw_write(FILE *f, gn_phonebook_entry *entry, char *memory_type_string);
+
+/* DEPRECATED */
+GNOKII_API int gn_vcal_file_event_read(char *filename, gn_calnote *cnote, int number) GNOKII_DEPRECATED;
+GNOKII_API int gn_vcal_file_todo_read(char *filename, gn_todo *ctodo, int number) GNOKII_DEPRECATED;
+
+GNOKII_API int gn_calnote2ical(FILE *f, gn_calnote *calnote);
+GNOKII_API int gn_ical2calnote(FILE *f, gn_calnote *calnote, int id);
+
+GNOKII_API int gn_todo2ical(FILE *f, gn_todo *ctodo);
+GNOKII_API int gn_ical2todo(FILE *f, gn_todo *ctodo, int id);
+
+GNOKII_API void gn_number_sanitize(char *number, int maxlen);
+GNOKII_API void gn_phonebook_entry_sanitize(gn_phonebook_entry *entry);
+
+/* Debugging */
+extern GNOKII_API gn_log_target gn_log_debug_mask;
+extern GNOKII_API gn_log_target gn_log_rlpdebug_mask;
+extern GNOKII_API gn_log_target gn_log_xdebug_mask;
+extern GNOKII_API void (*gn_elog_handler)(const char *fmt, va_list ap);
+GNOKII_API void gn_log_debug(const char *fmt, ...);
+GNOKII_API void gn_log_rlpdebug(const char *fmt, ...);
+GNOKII_API void gn_log_xdebug(const char *fmt, ...);
+GNOKII_API void gn_elog_write(const char *fmt, ...);
+typedef void (*gn_log_func_t)(const char *fmt, ...);
+
+GNOKII_API int gn_line_get(FILE *file, char *line, int count) GNOKII_DEPRECATED;
+
+/* Place a lock for the given device in /var/lock or /var/run */
+GNOKII_API char *gn_device_lock(const char *) GNOKII_DEPRECATED;
+/* Remove a lock for the given device from /var/lock or /var/run */
+GNOKII_API int gn_device_unlock(char *) GNOKII_DEPRECATED;
+
+GNOKII_API const char *gn_model_get(const char *product_name);
+GNOKII_API gn_phone_model *gn_phone_model_get(const char *product_name);
+
+/* SMS */
+GNOKII_API gn_error gn_sms_send(gn_data *data, struct gn_statemachine *state);
+GNOKII_API gn_error gn_sms_save(gn_data *data, struct gn_statemachine *state);
+GNOKII_API gn_error gn_sms_get(gn_data *data, struct gn_statemachine *state);
+GNOKII_API gn_error gn_sms_get_no_validate(gn_data *data, struct gn_statemachine *state);
+GNOKII_API gn_error gn_sms_get_folder_changes(gn_data *data, struct gn_statemachine *state,
+				       int has_folders);
+GNOKII_API gn_error gn_sms_delete(gn_data *data, struct gn_statemachine *state);
+GNOKII_API gn_error gn_sms_delete_no_validate(gn_data *data, struct gn_statemachine *state);
+
+/* Call service */
+GNOKII_API gn_error gn_call_dial(int *call_id, gn_data *data, struct gn_statemachine *state);
+GNOKII_API gn_error gn_call_check_active(struct gn_statemachine *state);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif	/* _gnokii_h */

Added: trunk/src/host/qemu-neo1973/gnokiigsm/misc.h
===================================================================
--- trunk/src/host/qemu-neo1973/gnokiigsm/misc.h	2007-05-16 22:38:21 UTC (rev 1986)
+++ trunk/src/host/qemu-neo1973/gnokiigsm/misc.h	2007-05-17 00:24:48 UTC (rev 1987)
@@ -0,0 +1,135 @@
+/*
+
+  $Id: misc.h,v 1.54 2006/12/17 16:02:07 pkot Exp $
+
+  G N O K I I
+
+  A Linux/Unix toolset and driver for the 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) 1999-2000 Hugh Blemings & Pavel Janík ml.
+  Copyright (C) 2000      Jan Derfinak
+  Copyright (C) 2001-2002 Chris Kemp, Pavel Machek
+  Copyright (C) 2001-2004 Pawel Kot, BORBELY Zoltan
+
+  Header file for miscellaneous defines, typedefs etc.
+
+*/
+
+#ifndef _gnokii_misc_h
+#define _gnokii_misc_h
+
+#include <stdio.h>
+#include <sys/types.h>
+
+#include "compat.h"
+
+/* Some general defines. */
+
+#ifndef false
+#  define false (0)
+#endif
+
+#ifndef true
+#  define true (!false)
+#endif
+
+#ifndef bool
+#  define bool int
+#endif
+
+#define ARRAY_LEN(x) (sizeof((x)) / sizeof((x)[0]))
+
+#define SAFE_STRNCPY(dest, src, n) do { \
+	strncpy((dest), (src), (n)); \
+	if ((n) > 0) \
+		(dest)[(n)-1] = '\0'; \
+	} while (0)
+
+#define SAFE_STRNCPY_SIZEOF(dest,src) \
+	SAFE_STRNCPY((dest), (src), sizeof((dest)))
+
+/* If glib.h is included, G_GNUC_PRINTF is already defined. */
+#ifndef G_GNUC_PRINTF
+/* Stolen from <glib.h>: */
+#  if	__GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ > 4)
+#    define G_GNUC_PRINTF( format_idx, arg_idx )	\
+      __attribute__((format (printf, format_idx, arg_idx)))
+#  else	/* !__GNUC__ */
+#    define G_GNUC_PRINTF( format_idx, arg_idx )
+#  endif	/* !__GNUC__ */
+#endif
+
+
+#define GNOKII_MAX(a, b)  (((a) > (b)) ? (a) : (b))
+#define GNOKII_MIN(a, b)  (((a) < (b)) ? (a) : (b))
+
+/* A define to make debug printfs neat */
+#ifdef __GNUC__
+#  ifndef DEBUG
+#    define dprintf(a...) do { } while (0)
+#  else
+#    define dprintf(a...) do { gn_log_debug(a); } while (0)
+#  endif /* DEBUG */
+#  /* Use it for error reporting */
+#  define dump(a...) do { gn_elog_write(a); } while (0)
+#else
+#  ifndef DEBUG
+#    define dump while (0)
+#    define dprintf while (0)
+#  else
+#    define dump gn_elog_write
+#    define dprintf gn_log_debug
+#  endif /* DEBUG */
+#endif /* __GNUC__ */
+
+/* Use gsprintf instead of sprintf and sprintf */
+#define gsprintf		snprintf
+#define gvsprintf		vsnprintf
+#define gasprintf		asprintf
+#define gvasprintf		vasprintf
+
+/* This is for the bitmaps mostly, but may be useful also for the other
+ * things. Counts how many octets we need to cover the given ammount of
+ * the bits.
+ */
+#define ceiling_to_octet(x) ((x) + 7) / 8
+
+#define PM_OLD_DEFAULT		PM_SPEEDDIAL | PM_SMS | PM_DTMF | PM_KEYBOARD | PM_CALENDAR
+#define PM_DEFAULT		PM_OLD_DEFAULT | PM_CALLERGROUP | PM_EXTPBK | PM_FOLDERS
+
+#define PM_CALLERGROUP		0x0001
+#define PM_NETMONITOR		0x0002
+#define PM_KEYBOARD		0x0004
+#define PM_SMS			0x0008
+#define PM_CALENDAR		0x0010
+#define PM_DTMF			0x0020
+#define PM_DATA			0x0040
+#define PM_SPEEDDIAL		0x0080
+#define PM_EXTPBK		0x0100
+#define PM_AUTHENTICATION	0x0200
+#define PM_FOLDERS		0x0400
+#define PM_FULLPBK		0x0800
+/* This one indicated reported cases of breaking the phone by xgnokii
+ * in FBUS orver IrDA mode */
+#define PM_XGNOKIIBREAKAGE	0x8000
+
+char **gnokii_strsplit(const char *string, const char *delimiter, int tokens);
+void gnokii_strfreev(char **str_array);
+
+#endif /* _gnokii_misc_h */

Added: trunk/src/host/qemu-neo1973/gnokiigsm/networks.h
===================================================================
--- trunk/src/host/qemu-neo1973/gnokiigsm/networks.h	2007-05-16 22:38:21 UTC (rev 1986)
+++ trunk/src/host/qemu-neo1973/gnokiigsm/networks.h	2007-05-17 00:24:48 UTC (rev 1987)
@@ -0,0 +1,59 @@
+/*
+
+  $Id: networks.h,v 1.14 2006/06/11 16:39:11 deller Exp $
+
+  G N O K I I
+
+  A Linux/Unix toolset and driver for the 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) 1999-2000 Hugh Blemings & Pavel Janík ml.
+  Copyright (C) 2002      Pawel Kot
+
+  Header file for GSM networks.
+
+*/
+
+#ifndef _gnokii_networks_h
+#define _gnokii_networks_h
+
+/* This type is used to hold information about various GSM networks. */
+typedef struct {
+	char *code; /* GSM network code */
+	char *name; /* GSM network name */
+} gn_network;
+
+/* This type is used to hold information about various GSM countries. */
+typedef struct {
+	char *code; /* GSM country code */
+	char *name; /* GSM country name */
+} gn_country;
+
+GNOKII_API char *gn_network_name_get(char *network_code);
+GNOKII_API char *gn_network_code_get(char *network_name);
+GNOKII_API char *gn_network_code_find(char *network_name, char *country_name);
+
+GNOKII_API char *gn_country_name_get(char *country_code);
+GNOKII_API char *gn_country_code_get(char *country_name);
+
+GNOKII_API int gn_network_get(gn_network *network, int index);
+GNOKII_API int gn_country_get(gn_country *country, int index);
+
+GNOKII_API char *gn_network2country(char *network);
+
+#endif	/* _gnokii_networks_h */

Added: trunk/src/host/qemu-neo1973/gnokiigsm/ringtones.h
===================================================================
--- trunk/src/host/qemu-neo1973/gnokiigsm/ringtones.h	2007-05-16 22:38:21 UTC (rev 1986)
+++ trunk/src/host/qemu-neo1973/gnokiigsm/ringtones.h	2007-05-17 00:24:48 UTC (rev 1987)
@@ -0,0 +1,161 @@
+/*
+
+  $Id: ringtones.h,v 1.21 2006/06/11 16:39:11 deller Exp $
+
+  G N O K I I
+
+  A Linux/Unix toolset and driver for the 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) 1999-2000 Hugh Blemings & Pavel Janík ml.
+  Copyright (C) 2000      Marcin Wiacek, Chris Kemp
+  Copyright (C) 2001-2003 Pawel Kot
+  Copyright (C) 2002-2003 BORBELY Zoltan
+
+  This file provides definitions of macros from the Smart Messaging
+  Specification. It is mainly rewrite of the spec to C :-) Viva Nokia!
+
+*/
+
+#ifndef _gnokii_ringtones_h
+#define _gnokii_ringtones_h
+
+#include <error.h>
+
+/* NoteValue is encoded as octave(scale)*14 + note */
+/* where for note: c=0, d=2, e=4 .... */
+/* ie. c#=1 and 5 and 13 are invalid */
+/* note=255 means a pause */
+
+#define GN_RINGTONE_MAX_NOTES 1024
+
+/* Structure to hold note of ringtone. */
+
+typedef struct {
+	unsigned char duration;
+	unsigned char note;
+} gn_ringtone_note;
+
+/* Structure to hold ringtones. */
+typedef struct {
+	int location;
+	char name[20];
+	unsigned char tempo;
+	unsigned int notes_count;
+	gn_ringtone_note notes[GN_RINGTONE_MAX_NOTES];
+} gn_ringtone;
+
+#define gn_ringtone_get_bit(stream, bitno) stream[(bitno) / 8]   &  1   << (7 - ((bitno) % 8))
+#define gn_ringtone_set_bit(stream, bitno) stream[(bitno) / 8]   |= 1   << (7 - ((bitno) % 8))
+#define gn_ringtone_clear_bit(stream, bitno) stream[(bitno) / 8] &= 255 -  (1 << (7 - ((bitno) % 8)))
+
+/* These values are from Smart Messaging Specification Revision 2.0.0 pages
+   3-23, ..., 3-29 */
+
+/* Command-Part Encoding */
+#define GN_RINGTONE_CancelCommand          (0x05 << 1) /* binary 0000 101 */
+#define GN_RINGTONE_Programming            (0x25 << 1) /* binary 0100 101 */
+#define GN_RINGTONE_Sound                  (0x1d << 1) /* binary 0011 101 */
+#define GN_RINGTONE_Unicode                (0x22 << 1) /* binary 0100 010 */
+
+/* Song-Type Encoding */
+#define GN_RINGTONE_BasicSongType     (0x01 << 5) /* binary 001 */
+#define GN_RINGTONE_TemporarySongType (0x02 << 5) /* binary 010 */
+#define GN_RINGTONE_MidiSongType      (0x03 << 5) /* binary 011 */
+#define GN_RINGTONE_DigitizedSongType (0x04 << 5) /* binary 100 */
+
+/* Instruction ID Encoding */
+#define GN_RINGTONE_PatternHeaderId      (0x00 << 5) /* binary 000 */
+#define GN_RINGTONE_NoteInstructionId    (0x01 << 5) /* binary 001 */
+#define GN_RINGTONE_ScaleInstructionId   (0x02 << 5) /* binary 010 */
+#define GN_RINGTONE_StyleInstructionId   (0x03 << 5) /* binary 011 */
+#define GN_RINGTONE_TempoInstructionId   (0x04 << 5) /* binary 100 */
+#define GN_RINGTONE_VolumeInstructionId  (0x05 << 5) /* binary 101 */
+
+/* Style-Value Encoding*/
+#define GN_RINGTONE_NaturalStyle    (0x00 << 6) /* binary 00 */
+#define GN_RINGTONE_ContinuousStyle (0x01 << 6) /* binary 01 */
+#define GN_RINGTONE_StaccatoStyle   (0x02 << 6) /* binary 11 */
+
+/* Note-Scale Encoding  */
+#define GN_RINGTONE_Scale1 (0x00 << 6) /* binary 00 */
+#define GN_RINGTONE_Scale2 (0x01 << 6) /* binary 01 */
+#define GN_RINGTONE_Scale3 (0x02 << 6) /* binary 10 */
+#define GN_RINGTONE_Scale4 (0x03 << 6) /* binary 11 */
+
+/* Note-Value Encoding */
+#define GN_RINGTONE_Note_Pause (0x00 << 4) /* binary 0000 */
+#define GN_RINGTONE_Note_C     (0x01 << 4) /* binary 0001 */
+#define GN_RINGTONE_Note_Cis   (0x02 << 4) /* binary 0010 */
+#define GN_RINGTONE_Note_D     (0x03 << 4) /* binary 0011 */
+#define GN_RINGTONE_Note_Dis   (0x04 << 4) /* binary 0100 */
+#define GN_RINGTONE_Note_E     (0x05 << 4) /* binary 0101 */
+#define GN_RINGTONE_Note_F     (0x06 << 4) /* binary 0110 */
+#define GN_RINGTONE_Note_Fis   (0x07 << 4) /* binary 0111 */
+#define GN_RINGTONE_Note_G     (0x08 << 4) /* binary 1000 */
+#define GN_RINGTONE_Note_Gis   (0x09 << 4) /* binary 1001 */
+#define GN_RINGTONE_Note_A     (0x0a << 4) /* binary 1010 */
+#define GN_RINGTONE_Note_Ais   (0x0b << 4) /* binary 1011 */
+#define GN_RINGTONE_Note_H     (0x0c << 4) /* binary 1100 */
+
+/* Note-Duration Encoding */
+#define GN_RINGTONE_Duration_Full (0x00 << 5) /* binary 000 */
+#define GN_RINGTONE_Duration_1_2  (0x01 << 5) /* binary 001 */
+#define GN_RINGTONE_Duration_1_4  (0x02 << 5) /* binary 010 */
+#define GN_RINGTONE_Duration_1_8  (0x03 << 5) /* binary 011 */
+#define GN_RINGTONE_Duration_1_16 (0x04 << 5) /* binary 100 */
+#define GN_RINGTONE_Duration_1_32 (0x05 << 5) /* binary 101 */
+
+/* Note-Duration-Specifier Encoding */
+#define GN_RINGTONE_NoSpecialDuration (0x00 << 6) /* binary 00 */
+#define GN_RINGTONE_DottedNote        (0x01 << 6) /* binary 01 */
+#define GN_RINGTONE_DoubleDottedNote  (0x02 << 6) /* binary 10 */
+#define GN_RINGTONE_Length_2_3        (0x03 << 6) /* binary 11 */
+
+/* Pattern ID Encoding */
+#define GN_RINGTONE_A_part (0x00 << 6) /* binary 00 */
+#define GN_RINGTONE_B_part (0x01 << 6) /* binary 01 */
+#define GN_RINGTONE_C_part (0x02 << 6) /* binary 10 */
+#define GN_RINGTONE_D_part (0x03 << 6) /* binary 11 */
+
+/* Command-End */
+#define GN_RINGTONE_CommandEnd (0x00) /* binary 00000000 */
+
+/* Definition of the Note type */
+typedef struct {
+	int scale;
+	int note_id;
+	int duration;
+	int duration_specifier;
+} gn_note;
+
+#define GN_RINGTONE_PACKAGE_MAX_LENGTH 200
+
+/* From PC Composer help */
+#define GN_RINGTONE_NOTES_MAX_NUMBER 130
+
+GNOKII_API gn_error gn_file_ringtone_read(char *filename, gn_ringtone *ringtone);
+GNOKII_API gn_error gn_file_ringtone_save(char *filename, gn_ringtone *ringtone);
+
+GNOKII_API unsigned char gn_ringtone_pack(gn_ringtone *ringtone, unsigned char *package, int *maxlength);
+GNOKII_API gn_error gn_ringtone_unpack(gn_ringtone *ringtone, unsigned char *package, int maxlength);
+GNOKII_API int gn_note_get(int number);
+GNOKII_API void gn_ringtone_get_tone(const gn_ringtone *ringtone, int n, int *freq, int *ulen);
+GNOKII_API void gn_ringtone_set_duration(gn_ringtone *ringtone, int n, int ulen);
+
+#endif	/* _gnokii_ringtones_h */

Added: trunk/src/host/qemu-neo1973/gnokiigsm/rlp-common.c
===================================================================
--- trunk/src/host/qemu-neo1973/gnokiigsm/rlp-common.c	2007-05-16 22:38:21 UTC (rev 1986)
+++ trunk/src/host/qemu-neo1973/gnokiigsm/rlp-common.c	2007-05-17 00:24:48 UTC (rev 1987)
@@ -0,0 +1,1823 @@
+/*
+
+  $Id: rlp-common.c,v 1.16 2005/04/20 20:30:18 pkot Exp $
+
+  G N O K I I
+
+  A Linux/Unix toolset and driver for the 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) 1999-2000  Hugh Blemings & Pavel Janík ml.
+  Copyright (C) 2001       Chris Kemp
+  Copyright (C) 2002-2004  BORBELY Zoltan
+
+  The development of RLP protocol is sponsored by SuSE CR, s.r.o. (Pavel use
+  the SIM card from SuSE for testing purposes).
+
+  Actual implementation of RLP protocol. Based on GSM 04.22 version 7.1.0,
+  downloadable from www.etsi.org (if you register with them)
+
+*/
+
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+#include <stdlib.h>
+
+#include "compat.h"
+#include "gnokii.h"
+#include "rlp-crc24.h"
+#include "misc.h" /* For u8, u32 etc. */
+
+#define INLINE inline
+
+#ifndef RLP_DEBUG
+#  define rlpprintf(a...) do { } while (0)
+#else
+#  define rlpprintf(a...) do { gn_log_rlpdebug(a); } while (0)
+#endif
+
+/* Our state machine which handles all of nine possible states of RLP
+   machine. */
+void MAIN_STATE_MACHINE(gn_rlp_f96_frame *frame, rlp_f96_header *header);
+
+/* This is the type we are just handling. */
+rlp_frame_types CurrentFrameType;
+
+/* Current state of RLP state machine. */
+rlp_state      CurrentState=RLP_S0; /* We start at ADM and Detached */
+
+/* Next state of RLP state machine. */
+rlp_state      NextState;
+
+/* Pointer to Send function that sends frame to phone. */
+bool      (*RLP_SendFunction)(gn_rlp_f96_frame *frame, bool out_dtx);
+
+/* Pointer to Passup function which returns data/inds */
+int      (*RLP_Passup)(rlp_user_inds ind, u8 *buffer, int length);
+
+
+/* State variables - see GSM 04.22, Annex A, section A.1.2 */
+
+rlp_state_variable UA_State;
+rlp_state_variable UI_State;
+rlp_state_variable Ackn_State;
+rlp_state_variable Poll_State;
+rlp_state_variable Poll_xchg;
+rlp_state_variable SABM_State;
+rlp_state_variable DISC_State;
+rlp_state_variable DM_State;  /* FIXME - not handled */
+rlp_state_variable XI_R_State;
+rlp_state_variable XID_C_State;
+rlp_state_variable XID_R_State;
+rlp_state_variable TEST_R_State;
+
+u8 VR=0;
+u8 VA=0;
+u8 VS=0;
+u8 VD=0;
+u8 DISC_Count;
+
+u8 DTX_VR;
+rlp_frame_types DTX_SF;
+
+#define RLP_M 62
+
+rlp_data R[RLP_M];
+rlp_data S[RLP_M];
+
+rlp_state_variable SABM_State;
+int SABM_Count;
+
+rlp_user_request_store UserRequests;
+
+u8 Poll_Count = 0;
+
+/* For now timing is done based on a frame reception rate of 20ms */
+/* Serge has measured it as 18.4ms */
+#define RLP_T_Scaling 2
+
+/* Timers - a value of -1 means not set */
+/* To set, timer is loaded with RLP_Timeout1_Limit/RLP_T_Scaling. */
+/* Each received frame (including NULLS / errors) any >0 timer is decrease */
+
+int T;
+int T_RCVS[RLP_M];
+
+bool UA_FBit = true;
+bool Ackn_FBit = false;
+bool DM_FBit = false;  /* FIXME - not handled */
+bool RRReady = false;
+bool LRReady = true;   /* FIXME - not handled (as if we couldn't keep up with 9600bps :-) */
+bool DISC_PBit = false;
+
+u8 LastStatus = 0xff;   /* Last Status byte */
+
+
+/* RLP Parameters. FIXME: Reset these - e.g. when entering state 0 */
+
+u8 RLP_SEND_WS = RLP_M-1;
+u8 RLP_RCV_WS = RLP_M-1;
+u8 RLP_Timeout1_Limit = 55;
+u8 RLP_N2 = 15; /* Maximum number of retransmisions. GSM spec says 6 here, but
+		   Nokia will XID this. */
+u8 RLP_T2 = 0;
+u8 RLP_VersionNumber = 0;
+
+
+/****** Externally called functions ********/
+/*******************************************/
+
+
+/* Function to initialise RLP code.  Main purpose for now is
+   to set the address of the RLP send function in the API code. */
+
+void rlp_initialise(bool (*rlp_send_function)(gn_rlp_f96_frame *frame, bool out_dtx), int (*rlp_passup)(rlp_user_inds ind, u8 *buffer, int length))
+{
+	int i;
+
+	RLP_SendFunction = rlp_send_function;
+	RLP_Passup = rlp_passup;
+	UserRequests.Conn_Req = false;
+	UserRequests.Attach_Req = false;
+	UserRequests.Conn_Req_Neg = false;
+	UserRequests.Reset_Resp = false;
+	UserRequests.Disc_Req = false;
+	CurrentState = RLP_S0;
+	T = -1;
+	for (i = 0; i < RLP_M; i++) T_RCVS[i] = -1;
+
+	UA_FBit = true;
+	Ackn_FBit = false;
+	DISC_PBit = false;
+	LastStatus = 0xff;
+	Poll_Count = 0;
+	VR = 0;
+	VA = 0;
+	VS = 0;
+	VD = 0;
+
+	RLP_SEND_WS = RLP_M-1;
+	RLP_RCV_WS = RLP_M-1;
+	RLP_Timeout1_Limit = 55;
+	RLP_N2 = 15;
+	RLP_T2 = 0;
+	RLP_VersionNumber = 0;
+}
+
+/* Set a user event */
+/* Called by user program for now */
+
+void rlp_user_request_set(rlp_user_requests type, bool value)
+{
+	switch (type) {
+	case Conn_Req:
+		UserRequests.Conn_Req = value;
+		break;
+	case Attach_Req:
+		UserRequests.Attach_Req = value;
+		break;
+	case Conn_Req_Neg:
+		UserRequests.Conn_Req_Neg = value;
+		break;
+	case Reset_Resp:
+		UserRequests.Reset_Resp = value;
+		break;
+	case Disc_Req:
+		UserRequests.Disc_Req = value;
+		break;
+	default:
+		break;
+	}
+}
+
+
+/***** Internal functions **********/
+/***********************************/
+
+
+/* Check whether a user event is set */
+
+bool rlp_user_request_get(rlp_user_requests type) {
+
+	bool result = false, *x;
+
+	switch (type) {
+	case Conn_Req:
+		x = &UserRequests.Conn_Req;
+		break;
+	case Attach_Req:
+		x = &UserRequests.Attach_Req;
+		break;
+	case Conn_Req_Neg:
+		x = &UserRequests.Conn_Req_Neg;
+		break;
+	case Reset_Resp:
+		x = &UserRequests.Reset_Resp;
+		break;
+	case Disc_Req:
+		x = &UserRequests.Disc_Req;
+		break;
+	default:
+		x = &result;
+		break;
+	}
+
+	result = *x;
+
+	if (*x == true)
+		*x = false;
+
+	return result;
+}
+
+void RLP_SetTimer(int *timer)
+{
+	*timer = (int)(RLP_Timeout1_Limit/RLP_T_Scaling);
+}
+
+
+/* Previous sequence number. */
+static INLINE u8 Decr(u8 x)
+{
+	if (x == 0)
+		return (RLP_M-1);
+	else
+		return (x-1);
+}
+
+/* Next sequence number. */
+static INLINE u8 Incr(u8 x)
+{
+	if (x == RLP_M-1)
+		return 0;
+	else
+		return (x+1);
+}
+
+/* Difference between sequence numbers. */
+
+/* FIXME: Not used now, so I have commented it out. PJ
+ * static INLINE u8 Diff(u8 x, u8 y)
+ * {
+ *   int result = x-y;
+ *   return (result >= 0) ? result : result + RLP_M;
+ * }
+*/
+
+/* Check value is within range */
+static bool InWindow(u8 val, u8 lower, u8 upper)
+{
+	/* allow for one level of wrapping round */
+	if (lower >= RLP_M) lower -= RLP_M;
+	if (upper >= RLP_M) upper -= RLP_M;
+	if (val >= RLP_M)   val -= RLP_M;
+
+	/*   .......L*****U....... */
+	if (lower <= upper)
+		return (val >= lower) && (val <= upper);
+
+	/*  ******U.........L***** */
+	return (val <= upper) || (val >= lower);
+}
+
+void RLP_Init_link_vars(void)
+{
+	int i;
+
+	Ackn_State = _idle;
+	Poll_State = _idle;
+	Poll_Count = 0;
+	Poll_xchg = _idle;
+	SABM_State = _idle;
+	DISC_State = _idle;
+	RRReady = true;  /* This seems a bit strange but it's what the spec says... */
+	VA = 0;
+	VR = 0;
+	VS = 0;
+	VD = 0;
+	LastStatus = 0xff;
+
+	for (i = 0; i < RLP_M; i++) {
+		R[i].State = _idle;
+		S[i].State = _idle;
+	}
+}
+
+
+void RLP_AddRingBufferDataToSlots(void)
+{
+	u8 buffer[24];
+	int size;
+
+	while ((S[VD].State == _idle)
+	       && ((size = RLP_Passup(GetData,buffer,24)) != 0)) {
+		memset(S[VD].Data, 0xff, 25);    /* FIXME - this isn't necessary - but makes debugging easier! */
+		if (size > 23) {
+			S[VD].Data[0] = 0x1e;
+			size = 24;
+		} else S[VD].Data[0] = size;
+
+		memcpy(&S[VD].Data[1], buffer, size);
+
+		if (size != 24) S[VD].Data[size+1] = 0x1f;
+
+		S[VD].State = _send;
+		VD = Incr(VD);
+	}
+}
+
+
+static void  RLP_DumpF96Frame(gn_rlp_f96_frame *frame)
+{
+	rlp_f96_header header;
+
+	rlp_f96_header_decode(frame, &header);
+
+	switch (header.Type) {
+
+	case RLP_FT_U: /* Unnumbered frames. */
+		rlpprintf("Unnumbered Frame [$%02x%02x] M=%02x ", frame->Header[0],
+			  frame->Header[1],
+			  header.M);
+
+		switch (header.M) {
+		case RLP_U_SABM :
+			rlpprintf("Set Asynchronous Balanced Mode (SABM) ");
+			break;
+
+		case RLP_U_UA:
+			rlpprintf("Unnumbered Acknowledge (UA) ");
+			break;
+
+		case RLP_U_DISC:
+			rlpprintf("Disconnect (DISC) ");
+			break;
+
+		case RLP_U_DM:
+			rlpprintf("Disconnected Mode (DM) ");
+			break;
+
+		case RLP_U_UI:
+			rlpprintf("Unnumbered Information (UI) ");
+			break;
+
+		case RLP_U_XID:
+			rlpprintf("Exchange Information (XID) \n");
+			rlp_xid_display(frame->Data);
+			break;
+
+		case RLP_U_TEST:
+			rlpprintf("Test (TEST) ");
+			break;
+
+		case RLP_U_NULL:
+			rlpprintf("Null information (NULL) ");
+			break;
+
+		case RLP_U_REMAP:
+			rlpprintf("Remap (REMAP) ");
+			break;
+
+		default:
+			rlpprintf("Unknown!!! ");
+			break;
+		}
+		break;
+
+	case RLP_FT_S: /* Supervisory frames. */
+		rlpprintf("Supervisory Frame [$%02x%02x] S=0x%x N(R)=%d ",
+			  frame->Header[0],
+			  frame->Header[1],
+			  header.S,
+			  header.Nr);
+
+		switch (header.S) {
+		case RLP_S_RR:
+			rlpprintf("RR");
+			break;
+
+		case RLP_S_REJ:
+			rlpprintf("REJ");
+			break;
+
+		case RLP_S_RNR:
+			rlpprintf("RNR");
+			break;
+
+		case RLP_S_SREJ:
+			rlpprintf("SREJ");
+			break;
+
+		default:
+			rlpprintf("BAD");
+			break;
+		}
+		break;
+
+	default:
+		rlpprintf("Info+Supervisory Frame [$%02x%02x] S=0x%x N(S)=%d N(R)=%d ",
+			  frame->Header[0],
+			  frame->Header[1],
+			  header.S,
+			  header.Ns,
+			  header.Nr);
+
+		switch (header.S) {
+		case RLP_S_RR:
+			rlpprintf("RR");
+			break;
+
+		case RLP_S_REJ:
+			rlpprintf("REJ");
+			break;
+
+		case RLP_S_RNR:
+			rlpprintf("RNR");
+			break;
+
+		case RLP_S_SREJ:
+			rlpprintf("SREJ");
+			break;
+
+		default:
+			rlpprintf("BAD");
+			break;
+		}
+
+		break;
+	}
+
+	/* Command/Response and Poll/Final bits. */
+	rlpprintf(" C/R=%d P/F=%d", header.CR, header.PF);
+
+	/* Information. */
+	/*
+	if (CurrentFrameType != RLP_FT_U_NULL) {
+
+		dprintf("\n");
+
+		for (count = 0; count < 25; count ++) {
+
+			if (isprint(frame->Data[count]))
+				dprintf("[%02x%c]", frame->Data[count], frame->Data[count]);
+			else
+				dprintf("[%02x ]", frame->Data[count]);
+
+			if (count == 15)
+				dprintf("\n");
+		}
+	}
+	*/
+
+	/* FCS. */
+	rlpprintf(" FCS: %02x %02x %02x\n\n", frame->FCS[0],
+		  frame->FCS[1],
+		  frame->FCS[2]);
+}
+
+/* FIXME: Remove this after finishing. */
+void X(gn_rlp_f96_frame *frame)
+{
+	int i;
+
+	for (i = 0; i < 30; i++)
+		dprintf("byte[%2d]: %02x\n", i, *( (u8 *)frame + i));
+}
+
+
+void ResetAllT_RCVS(void)
+{
+	int i;
+	for (i = 0; i < RLP_M; i++) T_RCVS[i] = -1;
+}
+
+
+/* This function is used for sending RLP frames to the phone. */
+void RLP_SendF96Frame(rlp_frame_types FrameType,
+		      bool OutCR, bool OutPF,
+		      u8 OutNR, u8 OutNS,
+		      u8 *OutData, u8 OutDTX)
+{
+
+	gn_rlp_f96_frame frame;
+	int i;
+
+	frame.Header[0] = 0;
+	frame.Header[1] = 0;
+
+#define SetCRBit frame.Header[0] |= 0x01;
+#define SetPFBit frame.Header[1] |= 0x02;
+
+#define ClearCRBit frame.Header[0] &= (~0x01);
+#define ClearPFBit frame.Header[1] &= (~0x02);
+
+	/* If Command/Response bit is set, set it in the header. */
+	if (OutCR) SetCRBit;
+
+	/* If Poll/Final bit is set, set it in the header. */
+	if (OutPF) SetPFBit;
+
+	/* If OutData is not specified (ie. is NULL) we want to clear frame.Data
+	   array for the user. */
+	if (!OutData) {
+		frame.Data[0] = 0x00; /* 0x1f */
+		for (i = 1; i < 25; i++)
+			frame.Data[i] = 0;
+	} else {
+		for (i = 0; i < 25; i++)
+			frame.Data[i] = OutData[i];
+	}
+
+#define PackM(x)  frame.Header[1] |= ((x) << 2);
+#define PackS(x)  frame.Header[0]|=((x) << 1);
+#define PackNR frame.Header[1] |= (OutNR << 2);
+#define PackNS frame.Header[0] |= (OutNS << 3); frame.Header[1] |= (OutNS >> 5);
+
+	switch (FrameType) {
+
+	/* Unnumbered frames. Be careful - some commands are used as commands
+	   only, so we have to set C/R bit later. We should not allow user for
+	   example to send SABM as response because in the spec is: The SABM
+	   encoding is used as command only. */
+	case RLP_FT_U_SABM:
+		frame.Header[0] |= 0xf8; /* See page 11 of the GSM 04.22 spec - 0 X X 1 1 1 1 1 */
+		frame.Header[1] |= 0x01; /* 1 P/F M1 M2 M3 M4 M5 X */
+		SetCRBit; /* The SABM encoding is used as a command only. */
+		SetPFBit; /* It is always used with the P-bit set to "1". */
+		PackM(RLP_U_SABM);
+		break;
+
+	case RLP_FT_U_UA:
+		frame.Header[0] |= 0xf8;
+		frame.Header[1] |= 0x01;
+		ClearCRBit; /* The UA encoding is used as a response only. */
+		PackM(RLP_U_UA);
+		break;
+
+	case RLP_FT_U_DISC:
+		frame.Header[0] |= 0xf8;
+		frame.Header[1] |= 0x01;
+		SetCRBit; /* The DISC encoding is used as a command only. */
+		PackM(RLP_U_DISC);
+		break;
+
+	case RLP_FT_U_DM:
+		frame.Header[0] |= 0xf8;
+		frame.Header[1] |= 0x01;
+		ClearCRBit; /* The DM encoding is used as a response only. */
+		PackM(RLP_U_DM);
+		break;
+
+	case RLP_FT_U_NULL:
+		frame.Header[0] |= 0xf8;
+		frame.Header[1] |= 0x01;
+		PackM(RLP_U_NULL);
+		break;
+
+	case RLP_FT_U_UI:
+		frame.Header[0] |= 0xf8;
+		frame.Header[1] |= 0x01;
+		PackM(RLP_U_UI);
+		break;
+
+	case RLP_FT_U_XID:
+		frame.Header[0] |= 0xf8;
+		frame.Header[1] |= 0x01;
+		SetPFBit; /* XID frames are always used with the P/F-bit set to "1". */
+		PackM(RLP_U_XID);
+		break;
+
+	case RLP_FT_U_TEST:
+		frame.Header[0] |= 0xf8;
+		frame.Header[1] |= 0x01;
+		PackM(RLP_U_TEST);
+		break;
+
+	case RLP_FT_U_REMAP:
+		frame.Header[0] |= 0xf8;
+		frame.Header[1] |= 0x01;
+		ClearPFBit; /* REMAP frames are always used with P/F-bit set to "0". */
+		PackM(RLP_U_REMAP);
+		break;
+
+	case RLP_FT_S_RR:
+		frame.Header[0] |= 0xf0;  /* See page 11 of the GSM 04.22 spec - 0 X X 1 1 1 1 1 */
+		frame.Header[1] |= 0x01; /* 1 P/F ...N(R)... */
+		PackNR;
+		PackS(RLP_S_RR);
+		break;
+
+	case RLP_FT_S_REJ:
+		frame.Header[0] |= 0xf0;
+		frame.Header[1] |= 0x01;
+		PackNR;
+		PackS(RLP_S_REJ);
+		break;
+
+	case RLP_FT_S_RNR:
+		frame.Header[0] |= 0xf0;
+		frame.Header[1] |= 0x01;
+		PackNR;
+		PackS(RLP_S_RNR);
+		break;
+
+	case RLP_FT_S_SREJ:
+		frame.Header[0] |= 0xf0;
+		frame.Header[1] |= 0x01;
+		PackNR;
+		PackS(RLP_S_SREJ);
+		break;
+
+	case RLP_FT_SI_RR:
+		PackNR;
+		PackNS;
+		PackS(RLP_S_RR);
+		break;
+
+	case RLP_FT_SI_REJ:
+		PackNR;
+		PackNS;
+		PackS(RLP_S_REJ);
+		break;
+
+	case RLP_FT_SI_RNR:
+		PackNR;
+		PackNS;
+		PackS(RLP_S_RNR);
+		break;
+
+	case RLP_FT_SI_SREJ:
+		PackNR;
+		PackNS;
+		PackS(RLP_S_SREJ);
+		break;
+
+	default:
+		break;
+	}
+
+	/* Store FCS in the frame. */
+	rlp_crc24checksum_calculate((u8 *)&frame, 27, frame.FCS);
+
+	/* X(&frame); */
+
+	rlpprintf("S ");
+	RLP_DumpF96Frame(&frame);
+
+	if (RLP_SendFunction)
+		RLP_SendFunction(&frame, OutDTX);
+}
+
+/* Check_input_PDU in Serge's code. */
+void rlp_f96_frame_display(gn_rlp_f96_frame *frame)
+{
+	int count;
+	rlp_f96_header header;
+
+	if (T >= 0) T--;
+	for (count = 0; count < RLP_M; count++)
+		if (T_RCVS[count] >= 0) T_RCVS[count]--;
+
+	CurrentFrameType = RLP_FT_BAD;
+
+	if (!frame) {
+		/* no frame provided, drop through to state machine anyway */
+	} else if (rlp_crc24fcs_check((u8 *)frame, 30) == true) {
+
+		/* Here we have correct RLP frame so we can parse the field of the header
+		   to out structure. */
+
+		rlpprintf("R ");
+		RLP_DumpF96Frame(frame);
+
+		rlp_f96_header_decode(frame, &header);
+
+		switch (header.Type) {
+
+		case RLP_FT_U: /* Unnumbered frames. */
+
+			switch (header.M) {
+			case RLP_U_SABM :
+				if (header.CR == 0 || header.PF == 0) break;
+				CurrentFrameType = RLP_FT_U_SABM;
+				break;
+
+			case RLP_U_UA:
+				if (header.CR == 1) break;
+				CurrentFrameType = RLP_FT_U_UA;
+				break;
+
+			case RLP_U_DISC:
+				if (header.CR == 0) break;
+				CurrentFrameType = RLP_FT_U_DISC;
+				break;
+
+			case RLP_U_DM:
+				if (header.CR == 1) break;
+				CurrentFrameType = RLP_FT_U_DM;
+				break;
+
+			case RLP_U_UI:
+				CurrentFrameType = RLP_FT_U_UI;
+				break;
+
+			case RLP_U_XID:
+				CurrentFrameType = RLP_FT_U_XID;
+				break;
+
+			case RLP_U_TEST:
+				CurrentFrameType = RLP_FT_U_TEST;
+				break;
+
+			case RLP_U_NULL:
+				CurrentFrameType = RLP_FT_U_NULL;
+				break;
+
+			case RLP_U_REMAP:
+				CurrentFrameType = RLP_FT_U_REMAP;
+				break;
+
+			default:
+				CurrentFrameType = RLP_FT_BAD;
+				break;
+			}
+			break;
+
+		case RLP_FT_S: /* Supervisory frames. */
+
+			switch (header.S) {
+			case RLP_S_RR:
+				CurrentFrameType = RLP_FT_S_RR;
+				break;
+
+			case RLP_S_REJ:
+				CurrentFrameType = RLP_FT_S_REJ;
+				break;
+
+			case RLP_S_RNR:
+				CurrentFrameType = RLP_FT_S_RNR;
+				break;
+
+			case RLP_S_SREJ:
+				CurrentFrameType = RLP_FT_S_SREJ;
+				break;
+
+			default:
+				CurrentFrameType = RLP_FT_BAD;
+				break;
+			}
+			break;
+
+		default:
+
+			switch (header.S) {
+			case RLP_S_RR:
+				CurrentFrameType = RLP_FT_SI_RR;
+				break;
+
+			case RLP_S_REJ:
+				CurrentFrameType = RLP_FT_SI_REJ;
+				break;
+
+			case RLP_S_RNR:
+				CurrentFrameType = RLP_FT_SI_RNR;
+				break;
+
+			case RLP_S_SREJ:
+				CurrentFrameType = RLP_FT_SI_SREJ;
+				break;
+
+			default:
+				CurrentFrameType = RLP_FT_BAD;
+				break;
+			}
+
+			break;
+		}
+
+	} else {
+		/* RLP Checksum failed - don't we need some statistics about these
+		   failures? Nothing is printed, because in the first stage of connection
+		   there are too many bad RLP frames... */
+		dprintf("Frame FCS is bad. Ignoring...\n");
+	}
+
+	MAIN_STATE_MACHINE(frame, &header);
+	/*
+	  Y:= outblock();
+	*/
+	return;
+}
+
+/* FIXME: real TEST_Handling - we do not handle TEST yet. */
+void TEST_Handling()
+{
+	return;
+}
+
+/* FIXME: better XID_handling - but this will answer a XID command. */
+bool XID_Handling (gn_rlp_f96_frame *frame, rlp_f96_header *header)
+{
+	u8 count;
+	u8 type;
+	u8 length;
+
+	if (CurrentFrameType == RLP_FT_U_XID) {
+		count = 0;
+		while (frame->Data[count] != 0) {
+
+			type = frame->Data[count] >> 4;
+			length = frame->Data[count] & 0x0f;
+			count++;
+
+			switch (type) {
+
+			case 0x01: /* RLP Version Number */
+				RLP_VersionNumber = frame->Data[count];
+				count += length;
+				break;
+			case 0x02: /* Interworking Function (IWF) to Mobile Station (MS) window size */
+				if (frame->Data[count] >= 1 && frame->Data[count] < RLP_M)
+					RLP_RCV_WS = frame->Data[count];
+				count += length;
+				break;
+			case 0x03: /* MS to IWF window size */
+				if (frame->Data[count] >= 1 && frame->Data[count] < RLP_M)
+					RLP_SEND_WS = frame->Data[count];
+				count += length;
+				break;
+			case 0x04: /* Acknowledgement Timer (T1). */
+				RLP_Timeout1_Limit = frame->Data[count];
+				count += length;
+				break;
+			case 0x05: /* Retransmission attempts (N2). */
+				RLP_N2 = frame->Data[count];
+				count += length;
+				break;
+			case 0x06: /* Reply delay (T2). */
+				RLP_T2 = frame->Data[count];
+				count += length;
+				break;
+			case 0x07: /* Compression - not yet! */
+				break;
+			default:
+				count += length;
+				break;
+			}
+		}
+
+		/* Now reassemble a reply */
+		count = 0;
+		memset(frame->Data, 0x00, 25);  /* Makes debugging easier */
+
+		/* Version Number - force to 0 for now */
+		RLP_VersionNumber = 0;
+		frame->Data[count++] = 0x11;
+		frame->Data[count++] = RLP_VersionNumber;
+
+		/* Window sizes */
+		frame->Data[count++] = 0x21;
+		frame->Data[count++] = RLP_RCV_WS;
+		frame->Data[count++] = 0x31;
+		frame->Data[count++] = RLP_SEND_WS;
+
+		/* Acknowledgement Timer (T1). */
+		frame->Data[count++] = 0x41;
+		frame->Data[count++] = RLP_Timeout1_Limit;
+
+		/* Retransmission attempts (N2). */
+		frame->Data[count++] = 0x51;
+		frame->Data[count++] = RLP_N2;
+
+		/* Reply delay (T2). */
+		frame->Data[count++] = 0x61;
+		frame->Data[count++] = RLP_T2;
+
+		XID_R_State = _send;
+
+		return true;
+	}
+
+	return false;
+}
+
+
+bool Send_TXU(gn_rlp_f96_frame *frame, rlp_f96_header *header)
+{
+	dprintf("Send_TXU()\n");
+	dprintf("XID_R_State=%d\n", XID_R_State);
+
+	/*
+	if (RLP_UserEvent(TEST_R_State)) {
+		RLP_SendF96Frame(RLP_FT_U_TEST, false, TEST_R_FBit, 0, 0, TEST_R_Data, false);
+		return true;
+	}  else
+	*/
+
+	if (XID_R_State == _send && frame) {
+		RLP_SendF96Frame(RLP_FT_U_XID, false, true, 0, 0, frame->Data, false);
+		XID_R_State = _idle;
+		return true;
+	}
+
+	/*
+	else if ((XID_C_State == _send ) && (Poll_xchg == _idle)) {
+		RLP_SendF96Frame(RLP_FT_U_XID, true, true, 0, 0, XID_C_Data, false);
+		XID_C_State = _wait;
+		T_XID = 1;
+		Poll_xchg = _wait;
+		return true;
+	} else if (RLP_UserEvent(UI_State)) {
+		RLP_SendF96Frame(RLP_FT_U_UI, true, false, 0, 0, NULL, false);
+		return true;
+	}
+	*/
+
+	return false;
+}
+
+
+/* Deliver data */
+
+void RLP_DeliverAllInSeqIF()
+{
+	int i,j;
+
+	do {
+		if ((R[VR].Data[0] & 0xE0) != LastStatus) {
+			LastStatus = (R[VR].Data[0] & 0xE0);
+			RLP_Passup(StatusChange, &LastStatus, 0);
+		}
+
+		j = 0;
+		i = R[VR].Data[0] & 0x1f;
+		if (i == 0x1e) j = 24;
+		if (i < 0x18) j = i;
+
+		/* FIXME - should check for more data in the frame */
+
+		RLP_Passup(Data, R[VR].Data+1, j);
+
+		R[VR].State = _idle;
+		VR = Incr(VR);
+
+	} while (R[VR].State == _rcvd);
+}
+
+
+/* Mark any missing information frames between VR and Ns */
+void RLP_MarkMissingIF(u8 Ns)
+{
+	u8 i;
+	for (i = VR; i != Ns; i = Incr(i)) {
+		if (R[i].State == _idle) R[i].State = _srej;  /* bug in spec, fig A.23 */
+	}
+}
+
+
+/* Information frame handler */
+
+bool RLP_I_Handler(gn_rlp_f96_frame *frame, rlp_f96_header *header)
+{
+	if ((header->CR) && (header->PF))
+		return true;
+
+	/* If the window size is 61, a received frame must have a sequence
+	   number between VR and VR+60 */
+	if (!InWindow(header->Ns, VR, VR + RLP_RCV_WS - 1))
+		return true;
+
+	if (header->Ns == VR) {
+		/* This is not in the spec but I think it is necessary */
+		if (R[header->Ns].State == _wait) T_RCVS[header->Ns] = -1;
+		R[VR].State = _rcvd;
+		memcpy(R[VR].Data, frame->Data, 25);
+		RLP_DeliverAllInSeqIF();
+		Ackn_State = _send;
+	} else {  /* Out of sequence, cause a SREJ */
+		if (R[header->Ns].State == _wait) T_RCVS[header->Ns] = -1;
+		R[header->Ns].State = _rcvd;
+		memcpy(R[header->Ns].Data, frame->Data, 25);
+		RLP_MarkMissingIF(header->Ns);
+	}
+	return false;
+}
+
+
+/* Mark acknowledged send frames */
+void RLP_AdvanceVA(u8 Nr)
+{
+	while (VA != Nr) {
+		S[VA].State = _idle;
+		VA = Incr(VA);
+	}
+}
+
+
+/* Decrease VS back down to Nr since these have not been acknowledged */
+void RLP_DecreaseVS(u8 Nr)
+{
+	while (VS != Nr) {
+		VS = Decr(VS);
+		S[VS].State = _send;
+	}
+}
+
+/* Supervisory frame handling */
+void RLP_S_Handler(gn_rlp_f96_frame *frame, rlp_f96_header *header)
+{
+	u8 i;
+
+	if ((header->CR) && (header->PF)) {
+		/* Special exchange (ie. error) - counter? */
+		rlpprintf("Got Poll command\n");
+		Ackn_State = _send;
+		Ackn_FBit = true;
+		for (i = 0; i < RLP_M; i++) R[i].State = _idle;
+		ResetAllT_RCVS();
+	}
+	if (Poll_State != _idle) {
+		if (header->PF == 0) return;
+		if ((CurrentFrameType == RLP_FT_S_SREJ) || (CurrentFrameType == RLP_FT_S_REJ) ||
+		    (CurrentFrameType == RLP_FT_SI_SREJ) || (CurrentFrameType == RLP_FT_SI_REJ)) return;
+		RLP_DecreaseVS(header->Nr);
+		Poll_State = _idle;
+		Poll_xchg = _idle;
+	}
+
+	switch (CurrentFrameType) {
+	case RLP_FT_S_RR:
+	case RLP_FT_SI_RR:
+		RLP_AdvanceVA(header->Nr);
+		RRReady = true;
+		break;
+	case RLP_FT_S_RNR:
+	case RLP_FT_SI_RNR:
+		RLP_AdvanceVA(header->Nr);
+		RRReady = false;
+		break;
+	case RLP_FT_S_REJ:
+	case RLP_FT_SI_REJ:
+		RLP_AdvanceVA(header->Nr);
+		RRReady = true;
+		RLP_DecreaseVS(header->Nr);
+		break;
+	case RLP_FT_S_SREJ:
+	case RLP_FT_SI_SREJ:
+		S[header->Nr].State = _send;
+		T = -1;
+		return;
+	default:
+		break;
+	}
+
+	if (VA == VS) T = -1;
+}
+
+
+/* Find the first SREJ frame */
+bool RLP_SREJSlot(u8 *x)
+{
+	u8 i;
+
+	for (i = Incr(VR); i != VR; i = Incr(i))
+		if (R[i].State == _srej) {
+			*x = i;
+			return true;
+		}
+
+	return false;
+}
+
+
+/* Check if any SREJ frames need sending, if not send the next in line */
+bool RLP_PrepareDataToTransmit(u8 *p)
+{
+	u8 i;
+
+	for (i = VA; i != VS; i = Incr(i))
+		if (S[i].State == _send) {
+			*p = i;
+			S[i].State = _wait;
+			return true;
+		}
+	if (S[VS].State != _send) return false;
+	if (!InWindow(VS, VA, VA + RLP_SEND_WS - 1))
+		return false;
+	*p = VS;
+	S[VS].State = _wait;
+	VS = Incr(VS);
+	return true;
+}
+
+
+/* Send a SREJ command */
+void RLP_SendSREJ(u8 x)
+{
+	u8 k;
+
+	if ((Poll_xchg == _idle) && (Poll_State == _send)) {
+		rlpprintf("Sending SREJ with poll\n");
+		RLP_SendF96Frame(RLP_FT_S_SREJ, true, true, x, 0, NULL, false);
+		R[x].State = _wait;
+		RLP_SetTimer(&T_RCVS[x]);
+		Poll_Count++;
+		Poll_State = _wait;
+		Poll_xchg = _wait;
+		RLP_SetTimer(&T);
+	} else if (RRReady && RLP_PrepareDataToTransmit(&k)) {
+		rlpprintf("Sending SREJ for %d along with frame %d\n", x, k);
+		RLP_SendF96Frame(RLP_FT_SI_SREJ, true, false, x , k , S[k].Data, false);
+		R[x].State = _wait;
+		RLP_SetTimer(&T_RCVS[x]);
+		RLP_SetTimer(&T);
+	} else {
+		rlpprintf("Sending SREJ for %d\n",x);
+		RLP_SendF96Frame(RLP_FT_S_SREJ, true, false, x, 0, NULL, false);
+		R[x].State = _wait;
+		RLP_SetTimer(&T_RCVS[x]);
+	}
+}
+
+
+/* Send a command */
+void RLP_Send_XX_Cmd(rlp_frame_types type)
+{
+	u8 k;
+
+	if ((Poll_xchg != _wait) && (Poll_State == _send)) {
+		RLP_SendF96Frame(type, true, true, VR, 0, NULL, false);
+		rlpprintf("Sending Comd %x with Poll\n",type);
+		Ackn_State = _idle;
+		Poll_Count++;
+		Poll_State = _wait;
+		Poll_xchg = _wait;
+		RLP_SetTimer(&T);
+	} else if (RRReady && RLP_PrepareDataToTransmit(&k)) {
+		rlpprintf("Sending Comd %x with frame %d\n", type, k);
+		RLP_SendF96Frame(type + 4, true, false, VR, k, S[k].Data, false);
+		Ackn_State = _idle;
+		RLP_SetTimer(&T);
+	} else {
+		if (type != 9)
+			rlpprintf("Sending Comd %x\n",type);
+		RLP_SendF96Frame(type, true, false, VR, 0, NULL, false);
+		Ackn_State = _idle;
+		DTX_SF = type;
+		DTX_VR = VR;   /* As v7.1.0 spec */
+	}
+}
+
+
+/* Send a Response */
+void RLP_Send_XX_Resp(rlp_frame_types type)
+{
+	u8 k;
+
+	if (RRReady && RLP_PrepareDataToTransmit(&k)) {
+		rlpprintf("Sending Resp %x with frame %d\n",type+4,k);
+		RLP_SendF96Frame(type + 4, false, true, VR, k, S[k].Data, false);
+		Ackn_State = _idle;
+		Ackn_FBit = false;
+		RLP_SetTimer(&T);
+	} else {
+		rlpprintf("Sending Resp %x\n",type);
+		RLP_SendF96Frame(type, false, true, VR, 0, NULL, false);
+		Ackn_State = _idle;
+		Ackn_FBit = false;
+	}
+}
+
+
+/* Decide which frame to use and send it - currently only used in state 4 */
+void RLP_SendData()
+{
+	u8 x;
+
+	if (UA_State == _send) {
+		RLP_SendF96Frame(RLP_FT_U_UA, false, UA_FBit, 0, 0, NULL, false);
+		UA_State = _idle;
+	} else if (Ackn_FBit == true) {
+		rlpprintf("About to send Poll resp\n");
+		if (LRReady) RLP_Send_XX_Resp(RLP_FT_S_RR);
+		else RLP_Send_XX_Resp(RLP_FT_S_RNR);
+	} else if (RLP_SREJSlot(&x)) RLP_SendSREJ(x);
+	else if (LRReady) RLP_Send_XX_Cmd(RLP_FT_S_RR);
+	else RLP_Send_XX_Cmd(RLP_FT_S_RNR);
+}
+
+void MAIN_STATE_MACHINE(gn_rlp_f96_frame *frame, rlp_f96_header *header)
+{
+	int i;
+
+	switch (CurrentState) {
+	/***** RLP State 0. *****/
+
+	/* ADM and Detached.
+
+	   This is the initial state after power on.
+
+	   As long as the RLP entity is "Detached", DISC(P) and/or SABM at the
+	   lower interface is acted upon by sending DM(P) or DM(1). Any other
+	   stimulus at the lower interface is ignored.
+
+	   This state can be exited only with Attach_Req. */
+
+	case RLP_S0:
+		dprintf("RLP state 0.\n");
+
+		switch (CurrentFrameType) {
+
+		case RLP_FT_U_DISC:
+			RLP_SendF96Frame(RLP_FT_U_DM, false, header->PF, 0, 0, NULL, false);
+			break;
+
+		case RLP_FT_U_SABM:
+			RLP_SendF96Frame(RLP_FT_U_DM, false, true, 0, 0, NULL, false);
+			break;
+
+		default:
+			RLP_SendF96Frame(RLP_FT_U_NULL, false, false, 0, 0, NULL, false);
+			if (rlp_user_request_get(Attach_Req)) {
+				NextState = RLP_S1;
+				UA_State = _idle;
+			}
+			break;
+		}
+
+		break;
+
+	/***** RLP State 1. *****/
+
+	/* ADM and Attached.
+
+	   The RLP entity is ready to established a connection, either by
+	   initiating the connection itself (Conn_Req) or by responding to an
+	   incoming connection request (SABM).
+
+	   Upon receiving a DISC PDU, the handling of the UA response is
+	   initiated. */
+
+	case RLP_S1:
+		dprintf("RLP state 1.\n");
+
+		if (!XID_Handling(frame, header)) {
+
+			switch(CurrentFrameType) {
+
+			case RLP_FT_U_TEST:
+				TEST_Handling();
+				break;
+
+			case RLP_FT_U_SABM:
+				RLP_Passup(Conn_Ind, NULL, 0);
+				NextState = RLP_S3;
+				break;
+
+			case RLP_FT_U_DISC:
+				UA_State = _send;
+				UA_FBit = header->PF;
+				break;
+
+			case RLP_FT_BAD:  /* If we get a bad frame we can still respond with SABM */
+			default:
+				if (rlp_user_request_get(Conn_Req)) {
+					SABM_State = _send;
+					SABM_Count = 0;
+					NextState = RLP_S2;
+				}
+				break;
+			}
+
+		}
+		if (!Send_TXU(frame, header)) {
+
+			if (UA_State == _send) {
+				RLP_SendF96Frame(RLP_FT_U_UA, false, UA_FBit, 0, 0, NULL, false);
+				UA_State = _idle;
+			} else
+				RLP_SendF96Frame(RLP_FT_U_NULL, false, false, 0, 0, NULL, false);
+		}
+		break;
+
+	/***** RLP State 2. *****/
+
+	case RLP_S2:
+		dprintf("RLP state 2.\n");
+
+		if (!XID_Handling(frame, header)) {
+
+			switch(CurrentFrameType) {
+
+			case RLP_FT_U_TEST:
+				TEST_Handling();
+				break;
+
+			case RLP_FT_U_SABM:
+				/*
+				  Conn_Conf = true;
+				*/
+				T = -1;
+				UA_State = _send;
+				UA_FBit = true;
+				RLP_Init_link_vars();
+				NextState = RLP_S4;
+				break;
+
+			case RLP_FT_U_DISC:
+				T = -1;
+				RLP_Passup(Disc_Ind, NULL, 0);
+				UA_State = _send;
+				UA_FBit = header->PF;
+				NextState = RLP_S1;
+				break;
+
+			case RLP_FT_U_UA:
+				dprintf("UA received in RLP state 2.\n");
+
+				if (SABM_State == _wait && header->PF) {
+					T = -1;
+					/* Conn_Conf = true; */
+					RLP_Init_link_vars();
+					NextState = RLP_S4;
+				}
+				break;
+
+			case RLP_FT_U_DM:
+				if (SABM_State == _wait && header->PF) {
+					Poll_xchg = _idle;
+					/* Conn_Conf_Neg = true; */
+					NextState = RLP_S1;
+				}
+				break;
+
+			default:
+				if (T == RLP_Timeout1_Limit || T == 0) {
+					Poll_xchg = _idle;
+					if (SABM_Count > RLP_N2)
+						NextState = RLP_S8;
+					SABM_State = _send;
+				}
+				break;
+			}
+		}
+
+		if (!Send_TXU(frame, header)) {
+
+			if (SABM_State == _send && Poll_xchg == _idle) {
+				RLP_SendF96Frame(RLP_FT_U_SABM, true, true, 0, 0, NULL, false);
+				SABM_State = _wait;
+				SABM_Count++;
+				Poll_xchg = _wait;
+				RLP_SetTimer(&T);
+			} else
+				RLP_SendF96Frame(RLP_FT_U_NULL, false, false, 0, 0, NULL, false);
+		}
+
+		if (rlp_user_request_get(Disc_Req)) {
+			T = -1;
+			DISC_State = _send;
+			DISC_Count = 0;
+			DISC_PBit = (Poll_xchg == _idle);
+			NextState = 5;
+		}
+
+		break;
+
+	/***** RLP State 3. *****/
+
+	case RLP_S3:
+		dprintf("RLP state 3.\n");
+
+		if (!XID_Handling(frame, header)) {
+
+			switch(CurrentFrameType) {
+
+			case RLP_FT_U_TEST:
+				TEST_Handling();
+				break;
+
+			case RLP_FT_U_DISC:
+				RLP_Passup(Disc_Ind, NULL, 0);
+				UA_State = _send;
+				UA_FBit = header->PF;
+				NextState = RLP_S1;
+				break;
+
+			default:
+				if (rlp_user_request_get(Conn_Req)) {
+					UA_State = _send;
+					UA_FBit = true;
+					NextState = RLP_S4;
+					RLP_Init_link_vars();
+				} else if (rlp_user_request_get(Conn_Req_Neg)) {
+					DM_State = _send;  /* FIXME - code to handle DM_State - missing from spec? */
+					DM_FBit = true;
+					NextState = RLP_S1;
+				}
+				break;
+			}
+		}
+
+		if (!Send_TXU(frame, header)) {
+			if (UA_State == _send) {
+				RLP_SendF96Frame(RLP_FT_U_UA, false, UA_FBit, 0, 0, NULL, false);
+				UA_State = _idle;
+			} else
+				RLP_SendF96Frame(RLP_FT_U_NULL, false, false, 0, 0, NULL, false);
+		}
+
+		if (rlp_user_request_get(Disc_Req)) {
+			T = -1;
+			DISC_State = _send;
+			DISC_Count = 0;
+			DISC_PBit = (Poll_xchg == _idle);
+			NextState = 5;
+		}
+		break;
+
+	/***** RLP State 4. *****/
+
+	case RLP_S4:
+		dprintf("RLP state 4.\n");
+
+		if (!XID_Handling(frame, header)) {
+
+			switch (CurrentFrameType) {
+
+			case RLP_FT_U_TEST:
+				TEST_Handling();
+				break;
+			case RLP_FT_U_DISC:
+				T = -1;
+				ResetAllT_RCVS();
+				RLP_Passup(Disc_Ind, NULL, 0);
+				UA_State = _send;
+				UA_FBit = header->PF;
+				NextState = RLP_S1;
+				break;
+			case RLP_FT_U_SABM:
+				T = -1;
+				ResetAllT_RCVS();
+				RLP_Passup(Reset_Ind, NULL, 0);
+				NextState = RLP_S7;
+				break;
+			case RLP_FT_S_RR:
+			case RLP_FT_S_RNR:
+			case RLP_FT_S_REJ:
+			case RLP_FT_S_SREJ:
+				/* Should check here for unsolicited Fbit */
+				/* Spec says: "Nr must be within the set of not yet
+				   acknowledged I-frames or it must be the next possible
+				   frame number." That's VA..VS-1 or VS, i.e. VA..VS */
+				if (!InWindow(header->Nr, VA, VS))
+					break;
+				RLP_S_Handler(frame, header);
+				break;
+			case RLP_FT_SI_RR:
+			case RLP_FT_SI_RNR:
+			case RLP_FT_SI_REJ:
+			case RLP_FT_SI_SREJ:
+				/* Should check here for unsolicited Fbit */
+				if (!InWindow(header->Nr, VA, VS))
+					break;
+				if (!RLP_I_Handler(frame, header)) RLP_S_Handler(frame, header);
+				break;
+			default:
+				break;
+			}
+		}
+		for (i = 0; i < RLP_M; i++)
+			if (T_RCVS[i] == 0) {
+				rlpprintf("T_RCVS[%d] Timeout in State 4\n", i);
+				R[i].State = _srej;
+			}
+		if (T == 0) {
+			T = -1;
+			rlpprintf("T Timeout in State 4\n");
+
+			Poll_xchg = _idle;
+			if (Poll_State == _idle) {
+				Poll_State = _send;
+				Poll_Count = 0;
+			} else {
+				if (Poll_Count > RLP_N2)
+					rlpprintf("N2 Errors in State 4\n");
+				Poll_State = _send;
+				Poll_Count++;
+			}
+		}
+
+		if (!Send_TXU(frame, header)) {
+			if (UA_State == _send) {
+				RLP_SendF96Frame(RLP_FT_U_UA, false, UA_FBit, 0, 0, NULL, false);
+				UA_State = _idle;
+			} else RLP_SendData();
+		}
+
+		/* Load any data from the Send ringbuffer into the send slots */
+		RLP_AddRingBufferDataToSlots();
+
+		rlpprintf("VD=%d, VA=%d, VS=%d, VR=%d\n", VD, VA, VS, VR);
+#ifdef RLP_DEBUG_STATE
+		{
+			int zzz;
+
+			if (UA_State != _idle) rlpprintf("[UA_State %d]", UA_State);
+			if (UI_State != _idle) rlpprintf("[UI_State %d]", UI_State);
+			if (Ackn_State != _idle) rlpprintf("[Ackn_State %d]", Ackn_State);
+			if (Poll_State != _idle) rlpprintf("[Poll_State %d]", Poll_State);
+			if (Poll_xchg != _idle) rlpprintf("[Poll_xchg %d]", Poll_xchg);
+			if (SABM_State != _idle) rlpprintf("[SABM_State %d]", SABM_State);
+			if (DISC_State != _idle) rlpprintf("[DISC_State %d]", DISC_State);
+			if (DM_State != _idle) rlpprintf("[DM_State %d]", DM_State);
+			if (XI_R_State != _idle) rlpprintf("[XI_R_State %d]", XI_R_State);
+			if (XID_C_State != _idle) rlpprintf("[XID_C_State %d]", XID_C_State);
+			if (XID_R_State != _idle) rlpprintf("[XID_R_State %d]", XID_R_State);
+			if (TEST_R_State != _idle) rlpprintf("[TEST_R_State %d]", TEST_R_State);
+
+			rlpprintf("S: ");
+			for (zzz = 0; zzz < RLP_M; zzz++) rlpprintf("%d ", S[zzz].State);
+			rlpprintf("\nR: ");
+			for (zzz = 0; zzz < RLP_M; zzz++) rlpprintf("%d ", R[zzz].State);
+			rlpprintf("\nT: %d, T_RCVS: ", T);
+			for (zzz = 0; zzz < RLP_M; zzz++) rlpprintf("%d ", T_RCVS[zzz]);
+			rlpprintf("\n");
+		}
+#endif
+
+		if (rlp_user_request_get(Disc_Req)) {
+			T = -1;
+			ResetAllT_RCVS();
+			DISC_State = _send;
+			DISC_Count = 0;
+			DISC_PBit = (Poll_xchg == _idle);
+			NextState = 5;
+		}
+
+		break;
+
+	/***** RLP State 5. *****/
+
+	case RLP_S5:
+		dprintf("RLP state 5.\n");
+
+		if (!XID_Handling(frame, header)) {
+
+			switch (CurrentFrameType) {
+
+			case RLP_FT_U_UA:
+			case RLP_FT_U_DM:
+				if ((DISC_State == _wait) && (DISC_PBit == header->PF)) {
+					if (DISC_PBit == true) Poll_xchg = _idle;
+					T = -1;
+					NextState = 1;
+				}
+				break;
+			case RLP_FT_U_DISC:
+				T = -1;
+				UA_State = _send;
+				UA_FBit = header->PF;
+				NextState = 1;
+				break;
+			default:
+				break;
+			}
+		}
+
+		if (!Send_TXU(frame, header)) {
+			if ((DISC_State != _wait) && !((DISC_PBit == true) && (Poll_xchg == _wait))) {
+				RLP_SendF96Frame(RLP_FT_U_DISC, true, DISC_PBit, 0, 0, NULL, false);
+				if (DISC_PBit == true) Poll_xchg = _wait;
+				DISC_State = _wait;
+				DISC_Count++;
+				RLP_SetTimer(&T);
+			} else
+				RLP_SendF96Frame(RLP_FT_U_NULL, false, false, 0, 0, NULL, false);
+		}
+
+		if (T == 0) {
+			if (DISC_PBit == 1) Poll_xchg = _idle;
+			DISC_Count++;
+			if (DISC_Count > RLP_N2)
+				rlpprintf("N2 error in State 5!\n");
+			DISC_State = _send;
+		}
+
+		break;
+
+	/***** RLP State 6. *****/
+	/* We should only get here after a Reset_Req which is not yet supported */
+
+	case RLP_S6:
+		dprintf("RLP state 6 - not yet implemented!\n");
+
+		if (!XID_Handling(frame, header)) {
+
+			switch (CurrentFrameType) {
+			default:
+				break;
+			}
+
+		}
+
+		if (!Send_TXU(frame,header)) {
+		}
+
+		if (rlp_user_request_get(Disc_Req)) {
+			T = -1;
+			DISC_State = _send;
+			DISC_Count = 0;
+			DISC_PBit = (Poll_xchg == _idle);
+			NextState = 5;
+		}
+
+		break;
+
+	/***** RLP State 7. *****/
+
+	case RLP_S7:
+		dprintf("RLP state 7.\n");
+
+		if (!XID_Handling(frame, header)) {
+
+			switch (CurrentFrameType) {
+			case RLP_FT_U_DISC:
+				RLP_Passup(Disc_Ind, NULL, 0);
+				UA_State = _send;
+				UA_FBit = header->PF;
+				NextState = RLP_S1;
+				break;
+			default:
+				break;
+			}
+		}
+
+		if (rlp_user_request_get(Reset_Resp)) {
+			UA_State = _send;
+			UA_FBit = 1;
+			RLP_Init_link_vars();
+			NextState = RLP_S4;
+		}
+
+		if (!Send_TXU(frame, header)) {
+			RLP_SendF96Frame(RLP_FT_U_NULL, false, false, 0, 0, NULL, false);
+		}
+
+		if (rlp_user_request_get(Disc_Req)) {
+			T = -1;
+			DISC_State = _send;
+			DISC_Count = 0;
+			DISC_PBit = (Poll_xchg == _idle);
+			NextState = 5;
+		}
+		break;
+
+	default:
+		dprintf("DEBUG: Unknown RLP state!\n");
+		break;
+	}
+
+	CurrentState = NextState;
+}
+
+/* Given a pointer to an RLP XID frame, display contents in human readable
+   form.  Note for now only Version 0 and 1 are supported.  Fields can appear
+   in any order and are delimited by a zero type field. This function is the
+   exact implementation of section 5.2.2.6, Exchange Identification, XID of
+   the GSM specification 04.22. */
+void rlp_xid_display(u8 *frame)
+{
+	int count = 25;  /* Sanity check */
+	u8  type, length;
+
+	fprintf(stdout, "XID: ");
+
+	while ((*frame != 0) && (count >= 0)) {
+		type = *frame >> 4;
+		length = *frame & 0x0f;
+
+		switch (type) {
+
+		case 0x01: /* RLP Version Number, probably 1 for Nokia. */
+			frame += length;
+			fprintf(stdout, "Ver %d ", *frame);
+			break;
+
+		case 0x02: /* IWF to MS window size */
+			frame += length;
+			fprintf(stdout, "IWF-MS %d ", *frame);
+			break;
+
+		case 0x03: /* MS to IWF window size. */
+			frame += length;
+			fprintf(stdout, "MS-IWF %d ", *frame);
+			break;
+
+		case 0x04: /* Acknowledgement Timer (T1). */
+			frame += length;
+			fprintf(stdout, "T1 %dms ", *frame * 10);
+			break;
+
+		case 0x05: /* Retransmission attempts (N2). */
+			frame += length;
+			fprintf(stdout, "N2 %d ", *frame);
+			break;
+
+		case 0x06: /* Reply delay (T2). */
+			frame += length;
+			fprintf(stdout, "T2 %dms ", *frame * 10);
+			break;
+
+		case 0x07: /* Compression. */
+			frame ++;
+			fprintf(stdout, "Comp [Pt=%d ", (*frame >> 4) );
+			fprintf(stdout, "P0=%d ", (*frame & 0x03) );
+			frame ++;
+			fprintf(stdout, "P1l=%d ", *frame);
+			frame ++;
+			fprintf(stdout, "P1h=%d ", *frame);
+			frame ++;
+			fprintf(stdout, "P2=%d] ", *frame);
+			break;
+
+		default:
+			frame += length;
+			fprintf(stdout, "Unknown! type=%02x, length=%02x", type, length);
+			break;
+		}
+		count--;
+		frame++;
+	}
+
+	fprintf(stdout, "\n");
+
+	return;
+}
+
+/* Given a pointer to an F9.6 Frame, split data out into component parts of
+   header and determine frame type. */
+void rlp_f96_header_decode(gn_rlp_f96_frame *frame, rlp_f96_header *header)
+{
+	/* Poll/Final bit. */
+	if ((frame->Header[1] & 0x02))
+		header->PF = true;
+	else
+		header->PF = false;
+
+	/* Command/Response bit. */
+	if ((frame->Header[0] & 0x01))
+		header->CR = true;
+	else
+		header->CR = false;
+
+	/* Send Sequence Number. */
+	header->Ns = frame->Header[0] >> 3;
+
+	if ((frame->Header[1] & 0x01))
+		header->Ns |= 0x20; /* Most significant bit. */
+
+	/* Determine frame type. See the section 5.2.1 in the GSM 04.22
+	   specification. */
+	switch (header->Ns) {
+
+	case 0x3f: /* Frames of type U, unnumbered frames. */
+		/* U frames have M1, ..., M5 stored in the place of N(R). */
+		header->Type = RLP_FT_U;
+		header->M = (frame->Header[1] >> 2) & 0x1f;
+		return; /* For U frames, we do not need N(R) and bits S1 and S2. */
+
+	case 0x3e: /* Frames of type S, supervisory frames. */
+		header->Type = RLP_FT_S;
+		break;
+
+	default: /* Frames of type I+S, numbered information transfer ans
+		    supervisory frames combined. */
+		header->Type = RLP_FT_IS;
+		break;
+	}
+
+	/* Receive Sequence Number N(R). */
+	header->Nr = frame->Header[1] >> 2;
+
+	/* Status bits (S1 and S2). */
+	header->S = (frame->Header[0] >> 1) & 0x03;
+
+	return;
+}

Added: trunk/src/host/qemu-neo1973/gnokiigsm/rlp-common.h
===================================================================
--- trunk/src/host/qemu-neo1973/gnokiigsm/rlp-common.h	2007-05-16 22:38:21 UTC (rev 1986)
+++ trunk/src/host/qemu-neo1973/gnokiigsm/rlp-common.h	2007-05-17 00:24:48 UTC (rev 1987)
@@ -0,0 +1,176 @@
+/*
+
+  $Id: rlp-common.h,v 1.12 2005/04/24 19:41:23 pkot Exp $
+
+  G N O K I I
+
+  A Linux/Unix toolset and driver for the 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) 1999-2000 Hugh Blemings & Pavel Janík ml.
+  Copyright (C) 2001      Chris Kemp, Pavel Machek
+  Copyright (C) 2003      Pawel Kot
+
+  The development of RLP protocol was sponsored by SuSE CR, s.r.o. (Pavel use
+  the SIM card from SuSE for testing purposes).
+
+  Header file for RLP protocol.
+
+*/
+
+#ifndef _gnokii_rlp_common_h
+#define _gnokii_rlp_common_h
+
+/* Typedef for frame type - they are the same for RLP version 0, 1 and 2. */
+typedef enum {
+	RLP_FT_X, /* Unknown. */
+	RLP_FT_U, /* Unnumbered frame. */
+	RLP_FT_S, /* Supervisory frame. */
+	RLP_FT_IS /* Information plus Supervisory (I+S) frame. */
+} rlp_frame_type;
+
+/* Define the various Unnumbered frame types. Numbering is bit reversed
+   relative to ETSI GSM 04.22 for easy parsing. */
+typedef enum {
+	RLP_U_SABM  = 0x07, /* Set Asynchronous Balanced Mode. */
+	RLP_U_UA    = 0x0c, /* Unnumbered Acknowledge. */
+	RLP_U_DISC  = 0x08, /* Disconnect. */
+	RLP_U_DM    = 0x03, /* Disconnected Mode. */
+	RLP_U_NULL  = 0x0f, /* Null information. */
+	RLP_U_UI    = 0x00, /* Unnumbered Information. */
+	RLP_U_XID   = 0x17, /* Exchange Identification. */
+	RLP_U_TEST  = 0x1c, /* Test. */
+	RLP_U_REMAP = 0x11  /* Remap. */
+} rlp_uframe_type;
+
+/* Define supervisory frame field. */
+typedef enum {
+	RLP_S_RR   = 0x00, /* Receive Ready. */
+	RLP_S_REJ  = 0x02, /* Reject. */
+	RLP_S_RNR  = 0x01, /* Receive Not Ready. */
+	RLP_S_SREJ = 0x03  /* Selective Reject. */
+} rlp_sframe_field;
+
+/* Used for CurrentFrameType. */
+typedef enum {
+	RLP_FT_U_SABM = 0x00,
+	RLP_FT_U_UA,
+	RLP_FT_U_DISC,
+	RLP_FT_U_DM,
+	RLP_FT_U_NULL,
+	RLP_FT_U_UI,
+	RLP_FT_U_XID,
+	RLP_FT_U_TEST,
+	RLP_FT_U_REMAP,
+	RLP_FT_S_RR,
+	RLP_FT_S_REJ,
+	RLP_FT_S_RNR,
+	RLP_FT_S_SREJ,
+	RLP_FT_SI_RR,
+	RLP_FT_SI_REJ,
+	RLP_FT_SI_RNR,
+	RLP_FT_SI_SREJ,
+	RLP_FT_BAD
+} rlp_frame_types;
+
+/* Frame definition for TCH/F9.6 frame. */
+typedef struct {
+	unsigned char Header[2];
+	unsigned char Data[25];
+	unsigned char FCS[3];
+} gn_rlp_f96_frame;
+
+/* Header data "split up" for TCH/F9.6 frame. */
+typedef struct {
+	unsigned char Ns;	/* Send sequence number. */
+	unsigned char Nr;	/* Receive sequence number. */
+	unsigned char M;	/* Unumbered frame type. */
+	unsigned char S;	/* Status. */
+	int PF;			/* Poll/Final. */
+	int CR;			/* Command/Response. */
+	rlp_frame_type Type;	/* Frame type. */
+} rlp_f96_header;
+
+
+/* RLP User requests */
+typedef struct {
+	int Conn_Req;
+	int Attach_Req;
+	int Conn_Req_Neg;
+	int Reset_Resp;
+	int Disc_Req;
+} rlp_user_request_store;
+
+typedef enum {
+	Conn_Req,
+	Attach_Req,
+	Conn_Req_Neg,
+	Reset_Resp,
+	Disc_Req
+} rlp_user_requests;
+
+typedef enum {
+	Conn_Ind,
+	Conn_Conf,
+	Disc_Ind,
+	Reset_Ind,
+	Data,		/* FIXME: This should really be called RLP_Data, otherwise it hogs name "Data"! */
+	StatusChange,
+	GetData
+} rlp_user_inds;
+
+/* RLP (main) states. See GSM specification 04.22 Annex A, Section A.1.1. */
+typedef enum {
+	RLP_S0, /* ADM and Detached */
+	RLP_S1, /* ADM and Attached */
+	RLP_S2, /* Pending Connect Request */
+	RLP_S3, /* Pending Connect Indication */
+	RLP_S4, /* ABM and Connection Established */
+	RLP_S5, /* Disconnect Initiated */
+	RLP_S6, /* Pending Reset Request */
+	RLP_S7, /* Pending Reset Indication */
+	RLP_S8  /* Error */
+} rlp_state;
+
+/* RLP specification defines several states in which variables can be. */
+typedef enum {
+	_idle=0,
+	_send,
+	_wait,
+	_rcvd,
+	_ackn,
+	_rej,
+	_srej
+} rlp_state_variable;
+
+/* RLP Data */
+typedef struct {
+	unsigned char Data[25];
+	rlp_state_variable State;
+} rlp_data;
+
+/* Prototypes for functions. */
+void rlp_f96_frame_display(gn_rlp_f96_frame *frame);
+void rlp_f96_header_decode(gn_rlp_f96_frame *frame, rlp_f96_header *header);
+void rlp_xid_display(unsigned char *frame);
+void rlp_initialise(int (*rlp_send_function)(gn_rlp_f96_frame *frame, int out_dtx), int (*rlp_passup)(rlp_user_inds ind, unsigned char *buffer, int length));
+void rlp_link_vars_init(void);
+void rlp_user_request_set(rlp_user_requests type, int value);
+void rlp_send(char *buffer, int length);
+
+#endif	/* _gnokii_rlp_common_h */

Added: trunk/src/host/qemu-neo1973/gnokiigsm/rlp-crc24.c
===================================================================
--- trunk/src/host/qemu-neo1973/gnokiigsm/rlp-crc24.c	2007-05-16 22:38:21 UTC (rev 1986)
+++ trunk/src/host/qemu-neo1973/gnokiigsm/rlp-crc24.c	2007-05-17 00:24:48 UTC (rev 1987)
@@ -0,0 +1,124 @@
+/*
+
+  $Id: rlp-crc24.c,v 1.7 2005/04/20 20:30:18 pkot Exp $
+
+  G N O K I I
+
+  A Linux/Unix toolset and driver for the 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) 1999-2000  Hugh Blemings & Pavel Janík ml.
+  Copyright (C) 2001-2004  Pawel Kot
+  Copyright (C) 2002-2004  BORBELY Zoltan
+
+  CRC24 (aka FCS) implementation in RLP.
+
+*/
+
+#include "rlp-crc24.h"
+
+/* CRC-24 table is used for computation of RLP checksum. */
+
+const u32 CRC24_Table[256] = {
+	0x00000000, 0x00D6A776, 0x00F64557, 0x0020E221, 0x00B78115, 0x00612663,
+	0x0041C442, 0x00976334, 0x00340991, 0x00E2AEE7, 0x00C24CC6, 0x0014EBB0,
+	0x00838884, 0x00552FF2, 0x0075CDD3, 0x00A36AA5, 0x00681322, 0x00BEB454,
+	0x009E5675, 0x0048F103, 0x00DF9237, 0x00093541, 0x0029D760, 0x00FF7016,
+	0x005C1AB3, 0x008ABDC5, 0x00AA5FE4, 0x007CF892, 0x00EB9BA6, 0x003D3CD0,
+	0x001DDEF1, 0x00CB7987, 0x00D02644, 0x00068132, 0x00266313, 0x00F0C465,
+	0x0067A751, 0x00B10027, 0x0091E206, 0x00474570, 0x00E42FD5, 0x003288A3,
+	0x00126A82, 0x00C4CDF4, 0x0053AEC0, 0x008509B6, 0x00A5EB97, 0x00734CE1,
+	0x00B83566, 0x006E9210, 0x004E7031, 0x0098D747, 0x000FB473, 0x00D91305,
+	0x00F9F124, 0x002F5652, 0x008C3CF7, 0x005A9B81, 0x007A79A0, 0x00ACDED6,
+	0x003BBDE2, 0x00ED1A94, 0x00CDF8B5, 0x001B5FC3, 0x00FB4733, 0x002DE045,
+	0x000D0264, 0x00DBA512, 0x004CC626, 0x009A6150, 0x00BA8371, 0x006C2407,
+	0x00CF4EA2, 0x0019E9D4, 0x00390BF5, 0x00EFAC83, 0x0078CFB7, 0x00AE68C1,
+	0x008E8AE0, 0x00582D96, 0x00935411, 0x0045F367, 0x00651146, 0x00B3B630,
+	0x0024D504, 0x00F27272, 0x00D29053, 0x00043725, 0x00A75D80, 0x0071FAF6,
+	0x005118D7, 0x0087BFA1, 0x0010DC95, 0x00C67BE3, 0x00E699C2, 0x00303EB4,
+	0x002B6177, 0x00FDC601, 0x00DD2420, 0x000B8356, 0x009CE062, 0x004A4714,
+	0x006AA535, 0x00BC0243, 0x001F68E6, 0x00C9CF90, 0x00E92DB1, 0x003F8AC7,
+	0x00A8E9F3, 0x007E4E85, 0x005EACA4, 0x00880BD2, 0x00437255, 0x0095D523,
+	0x00B53702, 0x00639074, 0x00F4F340, 0x00225436, 0x0002B617, 0x00D41161,
+	0x00777BC4, 0x00A1DCB2, 0x00813E93, 0x005799E5, 0x00C0FAD1, 0x00165DA7,
+	0x0036BF86, 0x00E018F0, 0x00AD85DD, 0x007B22AB, 0x005BC08A, 0x008D67FC,
+	0x001A04C8, 0x00CCA3BE, 0x00EC419F, 0x003AE6E9, 0x00998C4C, 0x004F2B3A,
+	0x006FC91B, 0x00B96E6D, 0x002E0D59, 0x00F8AA2F, 0x00D8480E, 0x000EEF78,
+	0x00C596FF, 0x00133189, 0x0033D3A8, 0x00E574DE, 0x007217EA, 0x00A4B09C,
+	0x008452BD, 0x0052F5CB, 0x00F19F6E, 0x00273818, 0x0007DA39, 0x00D17D4F,
+	0x00461E7B, 0x0090B90D, 0x00B05B2C, 0x0066FC5A, 0x007DA399, 0x00AB04EF,
+	0x008BE6CE, 0x005D41B8, 0x00CA228C, 0x001C85FA, 0x003C67DB, 0x00EAC0AD,
+	0x0049AA08, 0x009F0D7E, 0x00BFEF5F, 0x00694829, 0x00FE2B1D, 0x00288C6B,
+	0x00086E4A, 0x00DEC93C, 0x0015B0BB, 0x00C317CD, 0x00E3F5EC, 0x0035529A,
+	0x00A231AE, 0x007496D8, 0x005474F9, 0x0082D38F, 0x0021B92A, 0x00F71E5C,
+	0x00D7FC7D, 0x00015B0B, 0x0096383F, 0x00409F49, 0x00607D68, 0x00B6DA1E,
+	0x0056C2EE, 0x00806598, 0x00A087B9, 0x007620CF, 0x00E143FB, 0x0037E48D,
+	0x001706AC, 0x00C1A1DA, 0x0062CB7F, 0x00B46C09, 0x00948E28, 0x0042295E,
+	0x00D54A6A, 0x0003ED1C, 0x00230F3D, 0x00F5A84B, 0x003ED1CC, 0x00E876BA,
+	0x00C8949B, 0x001E33ED, 0x008950D9, 0x005FF7AF, 0x007F158E, 0x00A9B2F8,
+	0x000AD85D, 0x00DC7F2B, 0x00FC9D0A, 0x002A3A7C, 0x00BD5948, 0x006BFE3E,
+	0x004B1C1F, 0x009DBB69, 0x0086E4AA, 0x005043DC, 0x0070A1FD, 0x00A6068B,
+	0x003165BF, 0x00E7C2C9, 0x00C720E8, 0x0011879E, 0x00B2ED3B, 0x00644A4D,
+	0x0044A86C, 0x00920F1A, 0x00056C2E, 0x00D3CB58, 0x00F32979, 0x00258E0F,
+	0x00EEF788, 0x003850FE, 0x0018B2DF, 0x00CE15A9, 0x0059769D, 0x008FD1EB,
+	0x00AF33CA, 0x007994BC, 0x00DAFE19, 0x000C596F, 0x002CBB4E, 0x00FA1C38,
+	0x006D7F0C, 0x00BBD87A, 0x009B3A5B, 0x004D9D2D
+};
+
+void rlp_crc24polinomial_calculate(u8 *data, int length, u32 *polinomial)
+{
+
+	int i;
+	u8 cur;
+
+	*polinomial = 0x00ffffff;
+
+	for (i = 0; i < length; i++) {
+		cur = (*polinomial & 0x0000ffff) ^ data[i];
+		*polinomial = (*polinomial >> 8) ^ CRC24_Table[cur];
+	}
+
+	*polinomial = ((~*polinomial) & 0x00ffffff);
+}
+
+
+void rlp_crc24checksum_calculate(u8 *data, int length, u8 *crc)
+{
+	u32 polinomial;
+
+	rlp_crc24polinomial_calculate(data, length, &polinomial);
+	crc[0] = polinomial & 0x0000ffff;
+	crc[1] = (polinomial >> 8) & 0x0000ffff;
+	crc[2] = (polinomial >> 16) & 0x0000ffff;
+
+}
+
+bool rlp_crc24fcs_check(u8 *data, int length)
+{
+
+	u8 crc[] = { 0x00, 0x00, 0x00 };
+
+	rlp_crc24checksum_calculate(data, length - 3, crc);
+
+	if (((data[length - 3] == crc[0]) &&
+		(data[length - 2] == crc[1]) &&
+		(data[length - 1] == crc[2]))) {
+		return (true);
+	}
+	return (false);
+}

Added: trunk/src/host/qemu-neo1973/gnokiigsm/rlp-crc24.h
===================================================================
--- trunk/src/host/qemu-neo1973/gnokiigsm/rlp-crc24.h	2007-05-16 22:38:21 UTC (rev 1986)
+++ trunk/src/host/qemu-neo1973/gnokiigsm/rlp-crc24.h	2007-05-17 00:24:48 UTC (rev 1987)
@@ -0,0 +1,40 @@
+/*
+
+  $Id: rlp-crc24.h,v 1.5 2002/12/10 23:27:19 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) 1999, 2000 Hugh Blemings & Pavel Janík ml.
+
+  Header file for CRC24 (aka FCS) implementation in RLP.
+
+*/
+
+#ifndef _gnokii_data_rlp_crc24_h
+#define _gnokii_data_rlp_crc24_h
+
+#include "misc.h"
+
+/* Prototypes for functions */
+void rlp_crc24checksum_calculate(u8 *data, int length, u8 *crc);
+bool rlp_crc24fcs_check(u8 *data, int length);
+
+#endif

Added: trunk/src/host/qemu-neo1973/gnokiigsm/sms.h
===================================================================
--- trunk/src/host/qemu-neo1973/gnokiigsm/sms.h	2007-05-16 22:38:21 UTC (rev 1986)
+++ trunk/src/host/qemu-neo1973/gnokiigsm/sms.h	2007-05-17 00:24:48 UTC (rev 1987)
@@ -0,0 +1,488 @@
+/*
+
+  $Id: sms.h,v 1.67 2006/11/08 19:45:37 dforsi Exp $
+
+  G N O K I I
+
+  A Linux/Unix toolset and driver for the 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) 1999-2000 Hugh Blemings, Pavel Janik
+  Copyright (C) 2001-2003 Pawel Kot
+  Copyright (C) 2002      Pavel Machek, Markus Plail, BORBELY Zoltan
+  Copyright (C) 2003      Ladis Michl
+
+  Include file for the SMS library.
+
+*/
+
+#ifndef _gnokii_sms_h
+#define _gnokii_sms_h
+
+#include <error.h>
+#include <common.h>
+#include <bitmaps.h>
+#include <ringtones.h>
+#include <encoding.h>
+
+/* Maximum length of SMS center name */
+#define GN_SMS_CENTER_NAME_MAX_LENGTH  20
+
+/* Limits of SMS messages. */
+#define GN_SMS_MAX_LENGTH             160
+#define GN_SMS_8BIT_MAX_LENGTH        140
+#define GN_SMS_LONG_MAX_LENGTH	    10240
+
+#define GN_SMS_PART_MAX_NUMBER          3
+
+/* FIXME: what value should be here? (Pawel Kot) */
+#define GN_SMS_UDH_MAX_NUMBER          10
+
+/* Maximal number of SMS folders */
+#define GN_SMS_FOLDER_MAX_NUMBER       24
+#define GN_SMS_MESSAGE_MAX_NUMBER     190
+
+#define GN_SMS_DATETIME_MAX_LENGTH      7
+#define GN_SMS_SMSC_NUMBER_MAX_LENGTH  20
+#define GN_SMS_NUMBER_MAX_LENGTH       20
+#define GN_SMS_USER_DATA_MAX_LENGTH   512
+#define GN_SMS_VP_MAX_LENGTH            8
+
+/*** MEMORY INFO ***/
+typedef struct {
+	int Unread;		/* Number of unread messages */
+	int Number;		/* Number of all messages */
+} gn_sms_memory_status;
+
+typedef struct {
+	/* Number of message we get from GetSMSStatus */
+	unsigned int number;
+	/* Number of unread messages we get from GetSMSStatus */
+	unsigned int unread;
+	/* when a message is moved between folders status wouldn't change */
+	unsigned int changed;
+	/* Number of Folders we get from GetFolders */
+	unsigned int folders_count;
+	/* Message store used for new received messages (this is used
+	 * internally by AT_SetSMSMemoryType() in common/phones/atgen.c). */
+	gn_memory_type new_message_store;
+} gn_sms_status;
+
+
+/*** USER DATA HEADER ***/
+/* types of User Data Header */
+typedef enum {
+	GN_SMS_UDH_None                 = 0x00,
+	GN_SMS_UDH_ConcatenatedMessages = 0x01,
+	GN_SMS_UDH_Ringtone             = 0x02,
+	GN_SMS_UDH_OpLogo               = 0x03,
+	GN_SMS_UDH_CallerIDLogo         = 0x04,
+	GN_SMS_UDH_MultipartMessage     = 0x05,
+	GN_SMS_UDH_WAPvCard             = 0x06,
+	GN_SMS_UDH_WAPvCalendar         = 0x07,
+	GN_SMS_UDH_WAPvCardSecure       = 0x08,
+	GN_SMS_UDH_WAPvCalendarSecure   = 0x09,
+	GN_SMS_UDH_VoiceMessage         = 0x0a,
+	GN_SMS_UDH_FaxMessage           = 0x0b,
+	GN_SMS_UDH_EmailMessage         = 0x0c,
+	GN_SMS_UDH_WAPPush              = 0x0d,
+	GN_SMS_UDH_OtherMessage         = 0x0e,
+	GN_SMS_UDH_Unknown              = 0x0f
+} gn_sms_udh_type;
+
+typedef struct {
+	gn_sms_udh_type type;
+	union {
+		struct {
+			unsigned short reference_number;
+			unsigned short maximum_number;
+			unsigned short current_number;
+		} concatenated_short_message; /* SMS_ConcatenatedMessages */
+		struct {
+			int store;
+			unsigned short message_count;
+		} special_sms_message_indication; /* GN_SMS_VoiceMessage, GN_SMS_FaxMessage,
+						     GN_SMS_EmailMessage, GN_SMS_OtherMessage */
+		struct {
+			char network_code[6];
+			unsigned int width, height;
+		} logo; /* GN_SMS_OpLogo, GN_SMS_CallerIDLogo */
+		struct {
+			unsigned int notes; /* Number of the notes */
+		} ringtone; /* GN_SMS_Ringtone */
+	} u;
+} gn_sms_udh_info;
+
+typedef struct {
+	unsigned int number; /* Number of the present UDH */
+	unsigned int length;
+	gn_sms_udh_info udh[GN_SMS_UDH_MAX_NUMBER];
+} gn_sms_udh;
+
+typedef enum {
+	GN_SMS_MW_PID,  /* Set Protocol Identifier to `Return Call Message' */
+	GN_SMS_MW_DCS,  /* Set Data Coding Scheme "to indicate the type of
+			 * message waiting and whether there are some messages
+			 * or no messages" */
+	GN_SMS_MW_UDH   /* Use User Data Header - Special SMS Message
+			 * Indication; the maximium level of information,
+			 * may not be supported	by all phones */
+} gn_sms_message_waiting_type;
+
+/*** DATA CODING SCHEME ***/
+typedef enum {
+	GN_SMS_DCS_GeneralDataCoding,
+	GN_SMS_DCS_MessageWaiting
+} gn_sms_dcs_type;
+
+typedef enum {
+	GN_SMS_DCS_DefaultAlphabet = 0x00,
+	GN_SMS_DCS_8bit            = 0x01,
+	GN_SMS_DCS_UCS2            = 0x02
+} gn_sms_dcs_alphabet_type;
+
+typedef enum {
+	GN_SMS_DCS_VoiceMail = 0x00,
+	GN_SMS_DCS_Fax       = 0x01,
+	GN_SMS_DCS_Email     = 0x02,
+	GN_SMS_DCS_Text      = 0x03,
+	GN_SMS_DCS_Other     = 0x04
+} gn_sms_dcs_indication_type;
+
+typedef struct {
+	gn_sms_dcs_type type;
+	union {
+		struct {
+			/* Message class: 
+			 * 0 - no class
+			 * 1 - Class 0
+			 * 2 - Class 1
+			 * 3 - Class 2
+			 * 4 - Class 3 */
+			unsigned short m_class;
+			int compressed;
+			gn_sms_dcs_alphabet_type alphabet;
+		} general;
+		struct {
+			int discard;
+			gn_sms_dcs_alphabet_type alphabet; /* ucs16 not supported */
+			int active;
+			gn_sms_dcs_indication_type type;
+		} message_waiting;
+	} u;
+} gn_sms_dcs;
+
+/*** VALIDITY PERIOD ***/
+typedef enum {
+	GN_SMS_VP_None           = 0x00,
+	GN_SMS_VP_EnhancedFormat = 0x01,
+	GN_SMS_VP_RelativeFormat = 0x02,
+	GN_SMS_VP_AbsoluteFormat = 0x03
+} gn_sms_vp_format;
+
+typedef enum {
+	GN_SMS_VPE_None              = 0x00,
+	GN_SMS_VPE_RelativeFormat    = 0x01,
+	GN_SMS_VPE_RelativeSeconds   = 0x02, /* Only one octet more is used */
+	GN_SMS_VPE_RelativeSemiOctet = 0x03  /* 3 octets contain relative time in hours, minutes and seconds in semi-octet representation */
+} gn_sms_vp_enhanced_type;
+
+typedef struct {
+	int extension; /* we need to set it to 0 at the moment; FIXME: how to handle `1' here? */
+	int single_shot;
+	gn_sms_vp_enhanced_type type;
+	union {
+		unsigned short relative;
+		unsigned short seconds;
+		gn_timestamp hms;
+	} period;
+} gn_sms_vp_enhanced;
+
+/* Validity of SMS Messages. */
+typedef enum {
+	GN_SMS_VP_1H   = 0x0b,
+	GN_SMS_VP_6H   = 0x47,
+	GN_SMS_VP_24H  = 0xa7,
+	GN_SMS_VP_72H  = 0xa9,
+	GN_SMS_VP_1W   = 0xad,
+	GN_SMS_VP_Max  = 0xff
+} gn_sms_vp_time;
+
+typedef struct {
+	gn_sms_vp_format vpf;
+	union {
+		gn_sms_vp_enhanced enhanced;
+		gn_sms_vp_time relative;	/* 8 bit */
+		gn_timestamp absolute;
+	} u;
+} gn_sms_vp;
+
+
+/*** MESSAGE CENTER ***/
+
+typedef enum {
+	GN_SMS_MF_Text   = 0x00, /* Plain text message. */
+	GN_SMS_MF_Fax    = 0x22, /* Fax message. */
+	GN_SMS_MF_Voice  = 0x24, /* Voice mail message. */
+	GN_SMS_MF_ERMES  = 0x25, /* ERMES message. */
+	GN_SMS_MF_Paging = 0x26, /* Paging. */
+	GN_SMS_MF_UCI    = 0x2d, /* Email message in 8110i. */
+	GN_SMS_MF_Email  = 0x32, /* Email message. */
+	GN_SMS_MF_X400   = 0x31  /* X.400 message. */
+} gn_sms_message_format;
+
+typedef struct {
+	int id;				/* Number of the SMSC in the phone memory. */
+	char name[GN_SMS_CENTER_NAME_MAX_LENGTH];	/* Name of the SMSC. */
+	int default_name;		/* >= 1 if default name used, otherwise -1 */
+	gn_sms_message_format format;	/* SMS is sent as text/fax/paging/email. */
+	gn_sms_vp_time validity;	/* Validity of SMS Message. */
+	gn_gsm_number smsc;		/* Number of the SMSC. */
+	gn_gsm_number recipient;	/* Number of the default recipient. */
+} gn_sms_message_center;
+
+/*** SHORT MESSAGE CORE ***/
+
+typedef enum {
+	/* First 2 digits are taken from GSM 03.40 version 6.1.0 Release 1997
+	 * Section 9.2.3.1; 3rd digit is to mark a report. */
+	GN_SMS_MT_Deliver         = 0x00, /* 00 0 */
+	GN_SMS_MT_DeliveryReport  = 0x01, /* 00 1 */
+	GN_SMS_MT_Submit          = 0x02, /* 01 0 */
+	GN_SMS_MT_SubmitReport    = 0x03, /* 01 1 */
+	GN_SMS_MT_Command         = 0x04, /* 10 0 */
+	GN_SMS_MT_StatusReport    = 0x05, /* 10 1 */
+	/* Looks like Happy N*kia Engineers invention. Text, picture, outbox
+	 * sent templates are needed for Nokia 6510 and family. */
+	GN_SMS_MT_Picture         = 0x07,
+	GN_SMS_MT_TextTemplate    = 0x08,
+	GN_SMS_MT_PictureTemplate = 0x09,
+	GN_SMS_MT_SubmitSent      = 0x0a
+} gn_sms_message_type;
+
+typedef enum {
+	GN_SMS_CT_Enquiry            = 0x00, /* Enquiry relating to previosly
+						submitted short message; sets
+						SRR to 1 */
+	GN_SMS_CT_CancelStatusReport = 0x01, /* Cancel Status Report Request
+						relating to previously submitted
+						short message; sets SRR to 0 */
+	GN_SMS_CT_DeleteSM           = 0x02, /* Delete previously submitted
+						Short Message; sets SRR to 0 */
+	GN_SMS_CT_EnableStatusReport = 0x03  /* Enable Status Report Request
+						relating to previously submitted
+						short message; sets SRR to 0 */
+} gn_sms_command_type;
+
+typedef struct {
+	gn_sms_command_type type;
+} gn_sms_message_command;
+
+/* Datatype for SMS status */
+typedef enum {
+	GN_SMS_Read   = 0x01,
+	GN_SMS_Unread = 0x03,
+	GN_SMS_Sent   = 0x05,
+	GN_SMS_Unsent = 0x07
+} gn_sms_message_status;
+
+typedef enum {
+	GN_SMS_DATA_None      = 0x00,
+	GN_SMS_DATA_Text      = 0x01,
+	GN_SMS_DATA_Bitmap    = 0x02,
+	GN_SMS_DATA_Ringtone  = 0x03,
+	GN_SMS_DATA_iMelody   = 0x04,
+	GN_SMS_DATA_Multi     = 0x05,
+	GN_SMS_DATA_NokiaText = 0x06,
+	GN_SMS_DATA_Animation = 0x07,
+	GN_SMS_DATA_Concat    = 0x08,
+	GN_SMS_DATA_WAPPush   = 0x09,
+	GN_SMS_DATA_Other     = 0x0a
+} gn_sms_data_type;
+
+/*** FOLDER INFO ***/
+
+typedef enum {
+	GN_SMS_FLD_Old            = 0x00,
+	GN_SMS_FLD_New            = 0x01,
+	GN_SMS_FLD_Deleted        = 0x02,
+	GN_SMS_FLD_ToBeRemoved    = 0x03,
+	GN_SMS_FLD_NotRead        = 0x04,
+	GN_SMS_FLD_NotReadHandled = 0x05,
+	GN_SMS_FLD_Changed        = 0x06
+} gn_sms_location_status;
+
+typedef struct {
+	gn_sms_location_status status;	/* deleted, new, old, ToBeRemoved */
+	unsigned int location;
+	gn_sms_message_type message_type;
+} gn_sms_message_list;
+
+typedef struct {
+	int number;		/* -1 if folder is not supported by the phone */
+	unsigned int unread;	/* only valid for INBOX */
+	unsigned int changed;
+	unsigned int used;	/* because 'Used' can vary from 'Number' when we have deleted messages */
+} gn_sms_folder_stats;
+
+typedef struct {
+	unsigned char binary[GN_SMS_MAX_LENGTH];
+	int curr, total;	/* Number of this part, total number of parts */
+} gn_sms_multi;
+
+typedef struct {
+	int curr, total, serial;
+} gn_sms_concat;
+
+typedef struct {
+	gn_sms_data_type type;
+	unsigned int length;
+	union {
+		unsigned char text[10 * GN_SMS_MAX_LENGTH + 1];
+		gn_sms_multi multi;
+		gn_bmp bitmap;
+		gn_ringtone ringtone;
+		gn_bmp animation[4];
+		gn_sms_concat concat;
+	} u;
+} gn_sms_user_data;
+
+/* Define datatype for SMS messages exported to the user applications. */
+typedef struct {
+	/* General fields */
+	gn_sms_message_type type;           /* Type of the message. */
+	int delivery_report;                /* Do we request the delivery report? Only for setting. */
+	gn_sms_message_status status;       /* Status of the message read/unread/sent/unsent. */
+	unsigned int validity;              /* Message validity in minutes. Only for setting. */
+	gn_memory_type memory_type  ;       /* Memory type where the message is/should be stored. */
+	unsigned int number;                /* Location of the message in the memory/folder. */
+
+	/* Number related fields */
+	gn_gsm_number smsc;                 /* SMSC Number. */
+	gn_gsm_number remote;               /* Remote (sender/recipient) number. */
+
+	/* Data format fields */
+	gn_sms_dcs dcs;
+	gn_sms_user_data user_data[GN_SMS_PART_MAX_NUMBER];
+	gn_sms_udh udh;
+
+	/* Date fields */
+	gn_timestamp smsc_time;             /* SMSC Timestamp. Only for reading. */
+	gn_timestamp time;                  /* Delivery timestamp. Only for reading. */
+} gn_sms;
+
+/* Define datatype for SMS messages, describes precisely GSM Spec 03.40 */
+typedef struct {
+	unsigned int type;		/* Message Type Indicator - 2 bits (9.2.3.1) */
+	int more_messages;		/* More Messages to Send (9.2.3.2) */
+	int reply_via_same_smsc;	/* Reply Path (9.2.3.17) - `Reply via same centre' in the phone */
+	int reject_duplicates;		/* Reject Duplicates (9.2.3.25) */
+	int report;			/* Status Report (9.2.3.4, 9.2.3.5 & 9.2.3.26) - `Delivery reports' in the phone */
+
+	unsigned int number;		/* Message Number - 8 bits (9.2.3.18) */
+	unsigned int reference;		/* Message Reference - 8 bit (9.2.3.6) */
+	unsigned int pid;		/* Protocol Identifier - 8 bit (9.2.3.9) */
+	unsigned int report_status;	/* Status - 8 bit (9.2.3.15), Failure Cause (9.2.3.22) */
+
+	unsigned char smsc_time[GN_SMS_DATETIME_MAX_LENGTH];   /* Service Centre Time Stamp (9.2.3.11) */
+	unsigned char time[GN_SMS_DATETIME_MAX_LENGTH];       /* Discharge Time (9.2.3.13) */
+	unsigned char message_center[GN_SMS_SMSC_NUMBER_MAX_LENGTH];/* SMSC Address (9.2.3.7, 9.2.3.8, 9.2.3.14) */
+	unsigned char remote_number[GN_SMS_NUMBER_MAX_LENGTH];    /* Origination, destination, Recipient Address (9.2.3.7, 9.2.3.8, 9.2.3.14) */
+
+	unsigned int dcs;		/* Data Coding Scheme (9.2.3.10) */
+	unsigned int length;		/* User Data Length (9.2.3.16), Command Data Length (9.2.3.20) */
+	int udh_indicator;
+	unsigned char user_data[GN_SMS_LONG_MAX_LENGTH];      /* User Data (9.2.3.24), Command Data (9.2.3.21), extended to Nokia Multipart Messages from Smart Messaging Specification 3.0.0 */
+	int user_data_length;		/* Length of just previous field */
+
+	gn_sms_vp_format validity_indicator;
+	unsigned char validity[GN_SMS_VP_MAX_LENGTH];   /* Validity Period Format & Validity Period (9.2.3.3 & 9.2.3.12) - `Message validity' in the phone */
+
+	/* Other fields */
+	unsigned int memory_type;	/* MemoryType (for 6210/7110): folder indicator */
+	unsigned int status;		/* Status of the message: sent/read or unsent/unread */
+} gn_sms_raw;
+
+
+/*** FOLDERS ***/
+
+/*** Datatype for SMS folders in 6210/7110 ***/
+/* Max name length is 15 characters and trailing \0 */
+#define GN_SMS_FOLDER_NAME_MAX_LENGTH	16
+typedef struct {
+	/* Name for SMS folder. */
+	char name[GN_SMS_FOLDER_NAME_MAX_LENGTH];
+	/* if folder contains sender, SMSC number and sending date */
+	int sms_data;
+	/* locations of SMS messages in that folder (6210 specific) */
+	unsigned int locations[GN_SMS_MESSAGE_MAX_NUMBER];
+	/* number of SMS messages in that folder*/
+	unsigned int number;
+	/* ID od fthe current folder */
+	unsigned int folder_id;
+} gn_sms_folder;
+
+typedef struct {
+	gn_sms_folder folder[GN_SMS_FOLDER_MAX_NUMBER];
+	/* ID specific for this folder and phone. Used in internal functions.
+	 * Do not use it. */
+	unsigned int folder_id[GN_SMS_FOLDER_MAX_NUMBER];
+	/* number of SMS folders */
+	unsigned int number;
+} gn_sms_folder_list;
+
+/*** CELL BROADCAST ***/
+
+#define GN_CM_MESSAGE_MAX_LENGTH         160
+
+/* Define datatype for Cell Broadcast message */
+typedef struct {
+	int channel;
+	char message[GN_CM_MESSAGE_MAX_LENGTH + 1];
+	int is_new;
+} gn_cb_message;
+
+GNOKII_API void gn_sms_default_submit(gn_sms *sms);
+GNOKII_API void gn_sms_default_deliver(gn_sms *sms);
+
+/* WAPPush */
+
+typedef struct {
+	unsigned char wsp_tid;
+	unsigned char wsp_pdu;
+	unsigned char wsp_hlen;
+	unsigned char wsp_content_type;
+
+    	unsigned char version; /* wbxml version */
+    	unsigned char public_id;
+    	unsigned char charset; /* default 106 = UTF-8 */
+    	unsigned char stl;
+} gn_wap_push_header;
+
+typedef struct {
+	gn_wap_push_header header;
+	char *url;
+    	char *text;
+	char *data;
+	int data_len; 
+} gn_wap_push;
+
+GNOKII_API void gn_wap_push_init(gn_wap_push *wp);
+GNOKII_API gn_error gn_wap_push_encode(gn_wap_push *wp);
+
+#endif /* _gnokii_sms_h */

Added: trunk/src/host/qemu-neo1973/gnokiigsm/statemachine.h
===================================================================
--- trunk/src/host/qemu-neo1973/gnokiigsm/statemachine.h	2007-05-16 22:38:21 UTC (rev 1986)
+++ trunk/src/host/qemu-neo1973/gnokiigsm/statemachine.h	2007-05-17 00:24:48 UTC (rev 1987)
@@ -0,0 +1,106 @@
+/*
+
+  $Id: statemachine.h,v 1.25 2006/06/11 16:39:11 deller Exp $
+
+  G N O K I I
+
+  A Linux/Unix toolset and driver for the 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) 1999-2000 Hugh Blemings & Pavel Janík ml.
+  Copyright (C) 2002-2003 Pawel Kot, BORBELY Zoltan
+
+  Header file for the statemachine.
+
+*/
+
+#ifndef _gnokii_statemachine_h
+#define _gnokii_statemachine_h
+
+#include <error.h>
+#include <data.h>
+
+/* Small structure used in gn_driver */
+/* Messagetype is passed to the function in case it is a 'generic' one */
+typedef struct {
+	unsigned char message_type;
+	gn_error (*functions)(int messagetype, unsigned char *buffer, int length,
+			      gn_data *data, struct gn_statemachine *state);
+} gn_incoming_function_type;
+
+/* This structure contains the 'callups' needed by the statemachine */
+/* to deal with messages from the phone and other information */
+typedef struct {
+	/* These make up a list of functions, one for each message type and NULL terminated */
+	gn_incoming_function_type *incoming_functions;
+	gn_error (*default_function)(int messagetype, unsigned char *buffer, int length, struct gn_statemachine *state);
+	gn_phone phone;
+	gn_error (*functions)(gn_operation op, gn_data *data, struct gn_statemachine *state);
+	void *driver_instance;
+} gn_driver;
+
+/* How many message types we can wait for at one moment */
+#define GN_SM_WAITINGFOR_MAX_NUMBER 3
+
+/* The states the statemachine can take */
+typedef enum {
+	GN_SM_Startup,            /* Not yet initialised */
+	GN_SM_Initialised,        /* Ready! */
+	GN_SM_MessageSent,        /* A command has been sent to the link(phone) */
+	GN_SM_WaitingForResponse, /* We are waiting for a response from the link(phone) */
+	GN_SM_ResponseReceived    /* A response has been received - waiting for the phone layer to collect it */
+} gn_state;
+
+/* All properties of the state machine */
+struct gn_statemachine {
+	gn_state current_state;
+	gn_config config;
+	gn_device device;
+	gn_link link;
+	gn_driver driver;
+	char *lockfile;
+	
+	/* Store last message for resend purposes */
+	unsigned char last_msg_type;
+	unsigned int last_msg_size;
+	void *last_msg;
+
+	/* The responses we are waiting for */
+	unsigned char waiting_for_number;
+	unsigned char received_number;
+	unsigned char waiting_for[GN_SM_WAITINGFOR_MAX_NUMBER];
+	gn_error response_error[GN_SM_WAITINGFOR_MAX_NUMBER];
+	/* Data structure to be filled in with the response */
+	gn_data *data[GN_SM_WAITINGFOR_MAX_NUMBER];
+
+	/* libfunctions internal data structure */
+	gn_error lasterror;
+	gn_data sm_data;
+	union {
+		gn_phonebook_entry pb_entry;
+	} u;
+
+	struct gsmmodem_info_s *info;
+};
+
+GNOKII_API gn_state gn_sm_loop(int timeout, struct gn_statemachine *state);
+
+/* General way to call any driver function */
+GNOKII_API gn_error gn_sm_functions(gn_operation op, gn_data *data, struct gn_statemachine *sm);
+
+#endif	/* _gnokii_statemachine_h */

Added: trunk/src/host/qemu-neo1973/gnokiigsm/virtmodem.c
===================================================================
--- trunk/src/host/qemu-neo1973/gnokiigsm/virtmodem.c	2007-05-16 22:38:21 UTC (rev 1986)
+++ trunk/src/host/qemu-neo1973/gnokiigsm/virtmodem.c	2007-05-17 00:24:48 UTC (rev 1987)
@@ -0,0 +1,218 @@
+/*
+
+  $Id: virtmodem.c,v 1.49 2006/10/19 16:05:35 dforsi Exp $
+
+  G N O K I I
+
+  A Linux/Unix toolset and driver for the 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) 1999-2000  Hugh Blemings & Pavel Janík ml.
+  Copyright (C) 2002       Ladis Michl, Manfred Jonsson, Jan Kratochvil
+  Copyright (C) 2001-2004  Pawel Kot
+  Copyright (C) 2002-2003  BORBELY Zoltan
+
+  This file provides a virtual modem interface to the GSM phone by calling
+  code in gsm-api.c, at-emulator.c and datapump.c. The code here provides
+  the overall framework and coordinates switching between command mode
+  (AT-emulator) and "online" mode where the data pump code translates data
+  from/to the GSM handset and the modem data/fax stream.
+
+*/
+
+#include <sys/types.h>
+#include <stdio.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <signal.h>
+#include <termios.h>
+#include <grp.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <sys/socket.h>
+#include <sys/wait.h>
+#include <sys/uio.h>
+#include <sys/param.h>
+
+#include "compat.h"
+#include "misc.h"
+#include "gnokii-internal.h"
+#include "at-emulator.h"
+#include "datapump.h"
+#include "device.h"
+
+/* Defines */
+
+#ifndef AF_LOCAL 
+#  ifdef AF_UNIX
+#    define AF_LOCAL AF_UNIX
+#  else
+#    error AF_LOCAL not defined
+#  endif
+#endif
+
+/* Prototypes */
+static int  VM_PtySetup();
+static gn_error VM_GSMInitialise(struct gn_statemachine *sm);
+
+/* Global variables */
+
+extern bool GTerminateThread;
+int ConnectCount;
+bool CommandMode;
+
+/* Local variables */
+
+static int PtyRDFD;	/* File descriptor for reading and writing to/from */
+static int PtyWRFD;	/* pty interface - only different in debug mode. */
+
+struct vm_queue queue;
+
+/* If initialised in debug mode, stdin/out is used instead
+   of ptys for interface. */
+bool gn_vm_initialise(const char *iname, bool GSMInit)
+{
+	static struct gn_statemachine State;
+	sm = &State;
+	queue.n = 0;
+	queue.head = 0;
+	queue.tail = 0;
+
+	CommandMode = true;
+
+	if (GSMInit) {
+		dprintf("Initialising GSM\n");
+		if (gn_cfg_phone_load(iname, sm) != GN_ERR_NONE) return false;
+		if ((VM_GSMInitialise(sm) != GN_ERR_NONE)) {
+			fprintf (stderr, _("gn_vm_initialise - VM_GSMInitialise failed!\n"));
+			return (false);
+		}
+	}
+	GSMInit = false;
+
+	if (VM_PtySetup() < 0) {
+		fprintf (stderr, _("gn_vm_initialise - VM_PtySetup failed!\n"));
+		return (false);
+	}
+
+	if (gn_atem_initialise(PtyRDFD, PtyWRFD, sm) != true) {
+		fprintf (stderr, _("gn_vm_initialise - gn_atem_initialise failed!\n"));
+		return (false);
+	}
+
+	if (dp_Initialise(PtyRDFD, PtyWRFD) != true) {
+		fprintf (stderr, _("gn_vm_Initialise - dp_Initialise failed!\n"));
+		return (false);
+	}
+
+	return (true);
+}
+
+void gn_vm_loop(void)
+{
+	fd_set rfds;
+	struct timeval tv;
+	int res;
+	int nfd;
+	int i, n;
+	char buf[256], *d;
+
+	nfd = PtyRDFD + 1;
+
+	while (!GTerminateThread) {
+		if (CommandMode && gn_atem_initialised && queue.n > 0) {
+			d = queue.buf + queue.head;
+			queue.head = (queue.head + 1) % sizeof(queue.buf);
+			queue.n--;
+			gn_atem_incoming_data_handle(d, 1);
+			continue;
+		}
+
+		FD_ZERO(&rfds);
+		if ( queue.n < sizeof(queue.buf) ) {
+			FD_SET(PtyRDFD, &rfds);
+		}
+		tv.tv_sec = 0;
+		tv.tv_usec = 500000;
+		res = select(nfd, &rfds, NULL, NULL, &tv);
+
+		switch (res) {
+		case 0: /* Timeout */
+			continue;
+
+		case -1:
+			perror("gn_vm_loop - select");
+			exit (-1);
+
+		default:
+			break;
+		}
+
+		if (FD_ISSET(PtyRDFD, &rfds)) {
+			n = sizeof(queue.buf) - queue.n < sizeof(buf) ?
+				sizeof(queue.buf) - queue.n :
+				sizeof(buf);
+			if ( (n = read(PtyRDFD, buf, n)) <= 0 ) gn_vm_terminate();
+
+			for (i = 0; i < n; i++) {
+				queue.buf[queue.tail++] = buf[i];
+				queue.tail %= sizeof(queue.buf);
+				queue.n++;
+			}
+		}
+	}
+}
+
+/* Application should call gn_vm_terminate to shut down
+   the virtual modem thread */
+void gn_vm_terminate(void)
+{
+	/* Request termination of thread */
+	GTerminateThread = true;
+
+	close (PtyRDFD);
+	close (PtyWRFD);
+
+	/* Shutdown device */
+	gn_sm_functions(GN_OP_Terminate, NULL, sm);
+}
+
+/* Open pseudo tty interface and (in due course create a symlink
+   to be /dev/gnokii etc. ) */
+static int VM_PtySetup()
+{
+	PtyRDFD = STDIN_FILENO;
+	PtyWRFD = STDOUT_FILENO;
+	return (0);
+}
+
+/* Initialise GSM interface, returning gn_error as appropriate  */
+static gn_error VM_GSMInitialise(struct gn_statemachine *sm)
+{
+	gn_error error;
+
+	/* Initialise the code for the GSM interface. */
+	error = gn_gsm_initialise(sm);
+
+	if (error != GN_ERR_NONE)
+		fprintf(stderr, _("GSM/FBUS init failed! (Unknown model?). Quitting.\n"));
+
+	return (error);
+}

Added: trunk/src/host/qemu-neo1973/gnokiigsm/virtmodem.h
===================================================================
--- trunk/src/host/qemu-neo1973/gnokiigsm/virtmodem.h	2007-05-16 22:38:21 UTC (rev 1986)
+++ trunk/src/host/qemu-neo1973/gnokiigsm/virtmodem.h	2007-05-17 00:24:48 UTC (rev 1987)
@@ -0,0 +1,50 @@
+/*
+
+  $Id: virtmodem.h,v 1.18 2006/06/11 16:39:11 deller Exp $
+
+  G N O K I I
+
+  A Linux/Unix toolset and driver for the 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) 1999-2000 Hugh Blemings & Pavel Janík ml.
+  Copyright (C) 2001      Chris Kemp
+  Copyright (C) 2002-2003 Pawel Kot, BORBELY Zoltan
+
+  Header file for virtmodem code in virtmodem.c
+
+*/
+
+#ifndef _gnokii_virtmodem_h
+#define _gnokii_virtmodem_h
+
+struct vm_queue {
+	int n;
+	int head;
+	int tail;
+	unsigned char buf[256];
+};
+
+extern struct vm_queue queue;
+
+/* Prototypes */
+GNOKII_API int gn_vm_initialise(const char *iname, int gn_init);
+GNOKII_API void gn_vm_loop(void);
+GNOKII_API void gn_vm_terminate(void);
+
+#endif	/* _gnokii_virtmodem_h */

Added: trunk/src/host/qemu-neo1973/gnokiigsm/wappush.h
===================================================================
--- trunk/src/host/qemu-neo1973/gnokiigsm/wappush.h	2007-05-16 22:38:21 UTC (rev 1986)
+++ trunk/src/host/qemu-neo1973/gnokiigsm/wappush.h	2007-05-17 00:24:48 UTC (rev 1987)
@@ -0,0 +1,70 @@
+/*
+  $Id: wappush.h,v 1.1 2006/07/05 12:57:13 thrull Exp $
+
+  G N O K I I
+
+  A Linux/Unix toolset and driver for the 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) 2006 Igor Popik
+
+  Include file for the binary SMS push functions. 
+  
+  Based on wapforum document WAP-167-ServiceInd-20010731-a
+
+*/
+
+#define WBXML_VERSION 0x01
+#define WAPPush_CHARSET 0x6a /* UTF-8 106 */
+#define PDU_TYPE_Push 0x06
+#define CONTENT_TYPE 0xae /* application/vnd.wap.sic */
+
+/* wbxml tag tokens masks */
+typedef enum {
+	TOKEN_KNOWN		= 0x00, /* token known */
+	TOKEN_KNOWN_C		= 0x40, /* token known with content */
+	TOKEN_KNOWN_A		= 0x80, /* token known with attributes */
+	TOKEN_KNOWN_AC		= 0xC0	/* token known with attr & content */	
+} gn_wap_push_tokens_masks;
+
+/* Service indication tag tokens */
+typedef enum {
+	TAG_END			= 0x01,		/* end of TAG,ATTR list */
+	TAG_INLINE		= 0x03,		/* inline string */
+	TAG_SI			= 0x05,		/* public ID */
+	TAG_INDICATION 		= 0x06, 	/* indication */
+	TAG_INFO 		= 0x07,		/* info */
+	TAG_ITEM 		= 0x08	 	/* item */
+} gn_wap_push_tag_tokens;
+
+typedef enum {
+	ATTR_ACT_SIGNAL_NONE = 0x05,	/* action - signal-none */
+	ATTR_ACT_SIGNAL_LOW = 0x06,	/* action - signal-low */
+	ATTR_ACT_SIGNAL_MEDIUM = 0x07,	/* action - signal-medium */
+	ATTR_ACT_SIGNAL_HIGH = 0x08,	/* action - signal-high */
+	ATTR_ACT_DELETE = 0x09,		/* action - delete */
+	ATTR_CREATED = 0x0a,		/* created */
+	ATTR_HREF = 0x0b,		/* href */
+	ATTR_HREF_HTTP = 0x0c,		/* http:// */
+	ATTR_HREF_HTTP_WWW = 0x0d,	/* http://www. */
+	ATTR_HREF_HTTPS = 0x0e,		/* https:// */
+	ATTR_HREF_HTTPS_WWW = 0x0f,	/* https://www. */
+	ATTR_SI_EXPRES = 0x10,
+	ATTR_SI_ID = 0x11,
+	ATTR_CLASS = 0x12
+} gn_wap_push_tag_attr;

Modified: trunk/src/host/qemu-neo1973/hw/modem.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/modem.c	2007-05-16 22:38:21 UTC (rev 1986)
+++ trunk/src/host/qemu-neo1973/hw/modem.c	2007-05-17 00:24:48 UTC (rev 1987)
@@ -1,5 +1,5 @@
 /*
- * AT commands interpreter. (Fake GSM modem)
+ * Fake GSM modem.  Tries to be Texas Instruments "Calypso" compatible.
  *
  * Copyright (c) 2007 OpenMoko, Inc.
  * Author: Andrzej Zaborowski <andrew at openedhand.com>
@@ -8,22 +8,117 @@
  */
 #include "vl.h"
 
+#include "misc.h"
+#include "gnokii.h"
+#include "compat.h"
+#include "at-emulator.h"
+#include "datapump.h"
+
+#define TICALYPSO_MANF	"<manufacturer>"
+#define TICALYPSO_MODEL	"<model>"
+#define TICALYPSO_REV	"<revision>"
+#define TICALYPSO_IMEI	"<serial number>"
+
+bool GTerminateThread = false;
+
+GNOKII_API gn_error gn_cfg_phone_load(const char *iname,
+		struct gn_statemachine *state)
+{
+	return GN_ERR_NOTSUPPORTED;
+}
+
+GNOKII_API gn_error gn_sm_functions(gn_operation op, gn_data *data,
+		struct gn_statemachine *sm)
+{
+	switch (op) {
+	case GN_OP_MakeCall:
+		fprintf(stderr, "%s: calling %s: busy.\n", __FUNCTION__,
+				data->call_info->number);
+		return GN_ERR_LINEBUSY;
+
+	case GN_OP_CancelCall:
+		fprintf(stderr, "%s: hangup.\n", __FUNCTION__);
+		break;
+
+	case GN_OP_DeleteSMS:
+		fprintf(stderr, "%s: deleting SMS number %i\n", __FUNCTION__,
+				data->sms->number);
+		return GN_ERR_EMPTYLOCATION;
+
+	case GN_OP_GetRFLevel:
+		*data->rf_level = 32.0f;	/* Some -50 dBm */
+		break;
+
+	case GN_OP_GetImei:
+		strcpy(data->imei, TICALYPSO_IMEI);
+		break;
+
+	case GN_OP_GetRevision:
+		strcpy(data->revision, TICALYPSO_REV);
+		break;
+
+	case GN_OP_GetModel:
+		strcpy(data->revision, TICALYPSO_MODEL);
+		break;
+
+	case GN_OP_Identify:
+		strcpy(data->model, TICALYPSO_MODEL);
+		strcpy(data->revision, TICALYPSO_REV);
+		strcpy(data->imei, TICALYPSO_IMEI);
+		strcpy(data->manufacturer, TICALYPSO_MANF);
+		break;
+
+	default:
+		return GN_ERR_NOTSUPPORTED;
+	}
+	return GN_ERR_NONE;
+}
+
+GNOKII_API gn_error gn_gsm_initialise(struct gn_statemachine *sm)
+{
+	return GN_ERR_NOTSUPPORTED;
+}
+
+GNOKII_API void gn_data_clear(gn_data *data)
+{
+	memset(data, 0, sizeof(gn_data));
+}
+
+GNOKII_API gn_state gn_sm_loop(int timeout, struct gn_statemachine *state)
+{
+	return GN_ERR_NOTSUPPORTED;
+}
+
+GNOKII_API gn_error gn_sms_get(gn_data *data, struct gn_statemachine *state)
+{
+	fprintf(stderr, "%s: SMS number %i requested\n",
+			__FUNCTION__, data->sms->number);
+	return GN_ERR_EMPTYLOCATION;
+}
+
+GNOKII_API gn_error gn_sms_send(gn_data *data, struct gn_statemachine *state)
+{
+	fprintf(stderr, "%s: SMS type 0x%02x sent\n",
+			__FUNCTION__, data->sms->type);
+	return GN_ERR_NOTSUPPORTED;
+}
+
 struct modem_s {
     int enable;
     CharDriverState chr;
-    int cmd_len;
-    char cmd[1024];
 #define FIFO_LEN	4096
     int out_start;
     int out_len;
     char outfifo[FIFO_LEN];
     QEMUTimer *out_tm;
     int64_t baud_delay;
+
+    struct gn_statemachine state;
+    struct gsmmodem_info_s info;
 };
 
 static void modem_reset(struct modem_s *s)
 {
-    s->cmd_len = 0;
     s->out_len = 0;
     s->baud_delay = ticks_per_sec;
 }
@@ -45,10 +140,11 @@
         qemu_mod_timer(s->out_tm, qemu_get_clock(vm_clock) + s->baud_delay);
 }
 
-static void modem_resp(struct modem_s *s, const char *fmt, ...)
+static void modem_resp(void *opaque, const char *fmt, ...)
         __attribute__ ((__format__ (__printf__, 2, 3)));
-static void modem_resp(struct modem_s *s, const char *fmt, ...)
+static void modem_resp(void *opaque, const char *fmt, ...)
 {
+    struct modem_s *s = (struct modem_s *) opaque;
     static char buf[FIFO_LEN];
     int len, off;
     va_list ap;
@@ -69,319 +165,14 @@
     modem_fifo_wake(s);
 }
 
-static struct modem_cmd_s {
-    const char *cmd;
-    enum { modem_ok, modem_error, modem_call, modem_str } action;
-    int (*call)(struct modem_s *s, const char *param);
-    const char *resp;
-} modem_cmds[] = {
-    { "AT+CACM", modem_error },
-    { "AT+CAMM", modem_error },
-    { "AT+CAOC", modem_error },
-    { "AT+CBC", modem_error },
-    { "AT+CBST", modem_error },
-    { "AT+CCFC", modem_error },
-    { "AT+CCUG", modem_error },
-    { "AT+CCWA", modem_error },
-    { "AT+CCWE", modem_error },
-    { "AT+CEER", modem_error },
-    { "AT+CFUN", modem_error },
-    { "AT+CGACT", modem_error },
-    { "AT+CGANS", modem_error },
-    { "AT+CGATT", modem_error },
-    { "AT+CGAUTO", modem_error },
-    { "AT+CGCLASS", modem_error },
-    { "AT+CGDATA", modem_error },
-    { "AT+CGDCONT", modem_error },
-    { "AT+CGEREP", modem_error },
-    { "AT+CGMI", modem_str, 0, "<manufacturer>\n\n" },
-    { "AT+CGMM", modem_str, 0, "<model>\n\n" },
-    { "AT+CGMR", modem_str, 0, "<revision>\n\n" },
-    { "AT+CGPADDR", modem_error },
-    { "AT+CGQMIN", modem_error },
-    { "AT+CGQREQ", modem_error },
-    { "AT+CGREG", modem_error },
-    { "AT+CGSMS", modem_error },
-    { "AT+CGSN", modem_str, 0, "<serial number>\n\n" },
-    { "AT+CHLD", modem_error },
-    { "AT+CHUP", modem_error },
-    { "AT+CIMI", modem_error },
-    { "AT+CLAC", modem_error },
-    { "AT+CLAE", modem_error },
-    { "AT+CLAN", modem_error },
-    { "AT+CLCC", modem_error },
-    { "AT+CLCK", modem_error },
-    { "AT+CLIP", modem_error },
-    { "AT+CDIP", modem_error },
-    { "AT+CLIR", modem_error },
-    { "AT+CLVL", modem_error },
-    { "AT+CMEE", modem_error },
-    { "AT+CMGC", modem_error },
-    { "AT+CMGD", modem_error },
-    { "AT+CMGF", modem_error },
-    { "AT+CMGL", modem_error },
-    { "AT+CMGR", modem_error },
-    { "AT+CMGS", modem_error },
-    { "AT+CMGW", modem_error },
-    { "AT+CMOD", modem_error },
-    { "AT+CMSS", modem_error },
-    { "AT+CMMS", modem_error },
-    { "AT+CMUT", modem_error },
-    { "AT+CMUX", modem_error },
-    { "AT+CNMA", modem_error },
-    { "AT+CNMI", modem_error },
-    { "AT+CNUM", modem_error },
-    { "AT+COLP", modem_error },
-    { "AT+COPN", modem_error },
-    { "AT+COPS", modem_ok },
-    { "AT+CPAS", modem_error },
-    { "AT+CPBF", modem_error },
-    { "AT+CPBR", modem_error },
-    { "AT+CPBS", modem_error },
-    { "AT+CPBW", modem_error },
-    { "AT+CPIN", modem_ok },
-    { "AT+CPMS", modem_error },
-    { "AT+CPOL", modem_error },
-    { "AT+CPUC", modem_error },
-    { "AT+CPWD", modem_error },
-    { "AT+CR", modem_error },
-    { "AT+CRC", modem_error },
-    { "AT+CREG", modem_error },
-    { "AT+CRES", modem_error },
-    { "AT+CRLP", modem_error },
-    { "AT+CRSL", modem_error },
-    { "AT+CRSM", modem_error },
-    { "AT+CSAS", modem_error },
-    { "AT+CSCA", modem_error },
-    { "AT+CSCB", modem_error },
-    { "AT+CSCS", modem_error },
-    { "AT+CSDH", modem_error },
-    { "AT+CSIM", modem_error },
-    { "AT+CSMP", modem_error },
-    { "AT+CSMS", modem_error },
-    { "AT+CSNS", modem_error },
-    { "AT+CSQ", modem_error },
-    { "AT%CSQ", modem_error },
-    { "AT+CSSN", modem_error },
-    { "AT+CSTA", modem_error },
-    { "AT+CSVM", modem_error },
-    { "AT+CTFR", modem_error },
-    { "AT+CUSD", modem_error },
-    { "AT+DR", modem_error },
-    { "AT+FAP", modem_error },
-    { "AT+FBO", modem_error },
-    { "AT+FBS", modem_error },
-    { "AT+FBU", modem_error },
-    { "AT+FCC", modem_error },
-    { "AT+FCLASS", modem_error },
-    { "AT+FCQ", modem_error },
-    { "AT+FCR", modem_error },
-    { "AT+FCS", modem_error },
-    { "AT+FCT", modem_error },
-    { "AT+FDR", modem_error },
-    { "AT+FDT", modem_error },
-    { "AT+FEA", modem_error },
-    { "AT+FFC", modem_error },
-    { "AT+FHS", modem_error },
-    { "AT+FIE", modem_error },
-    { "AT+FIP", modem_error },
-    { "AT+FIS", modem_error },
-    { "AT+FIT", modem_error },
-    { "AT+FKS", modem_error },
-    { "AT+FLI", modem_error },
-    { "AT+FLO", modem_error },
-    { "AT+FLP", modem_error },
-    { "AT+FMI", modem_error },
-    { "AT+FMM", modem_error },
-    { "AT+FMR", modem_error },
-    { "AT+FMS", modem_error },
-    { "AT+FND", modem_error },
-    { "AT+FNR", modem_error },
-    { "AT+FNS", modem_error },
-    { "AT+FPA", modem_error },
-    { "AT+FPI", modem_error },
-    { "AT+FPS", modem_error },
-    { "AT+FPW", modem_error },
-    { "AT+FRQ", modem_error },
-    { "AT+FSA", modem_error },
-    { "AT+FSP", modem_error },
-    { "AT+GCAP", modem_error },
-    { "AT+GCI", modem_error },
-    { "AT+GMI", modem_error },
-    { "AT+GMM", modem_error },
-    { "AT+GMR", modem_error },
-    { "AT+GSN", modem_error },
-    { "AT+ICF", modem_error },
-    { "AT+IFC", modem_error },
-    { "AT+ILRR", modem_error },
-    { "AT+IPR", modem_error },
-    { "AT+VTS", modem_error },
-    { "AT+WS46", modem_error },
-    { "AT%ALS", modem_error },
-    { "AT%ATR", modem_error },
-    { "AT%BAND", modem_error },
-    { "AT%CACM", modem_error },
-    { "AT%CAOC", modem_error },
-    { "AT%CCBS", modem_error },
-    { "AT%STDR", modem_error },
-    { "AT%CGAATT", modem_error },
-    { "AT%CGMM", modem_error },
-    { "AT%CGREG", modem_error },
-    { "AT%CNAP", modem_error },
-    { "AT%CPI", modem_error },
-    { "AT%COLR", modem_error },
-    { "AT%CPRIM", modem_error },
-    { "AT%CTV", modem_error },
-    { "AT%CUNS", modem_error },
-    { "AT%NRG", modem_error },
-    { "AT%SATC", modem_error },
-    { "AT%SATE", modem_error },
-    { "AT%SATR", modem_error },
-    { "AT%SATT", modem_error },
-    { "AT%SNCNT", modem_error },
-    { "AT%VER", modem_error },
-    { "AT%CGCLASS", modem_error },
-    { "AT%CGPCO", modem_error },
-    { "AT%CGPPP", modem_error },
-    { "AT%EM", modem_error },
-    { "AT%EMET", modem_error },
-    { "AT%EMETS", modem_error },
-    { "AT%CBHZ", modem_error },
-    { "AT%CPHS", modem_error },
-    { "AT%CPNUMS", modem_error },
-    { "AT%CPALS", modem_error },
-    { "AT%CPVWI", modem_error },
-    { "AT%CPOPN", modem_error },
-    { "AT%CPCFU", modem_error },
-    { "AT%CPINF", modem_error },
-    { "AT%CPMB", modem_error },
-    { "AT%CPRI", modem_error },
-    { "AT%DATA", modem_error },
-    { "AT%DINF", modem_error },
-    { "AT%CLCC", modem_error },
-    { "AT%DBGINFO", modem_error },
-    { "AT%VTS", modem_error },
-    { "AT%CHPL", modem_error },
-    { "AT%CREG", modem_error },
-    { "AT+CTZR", modem_error },
-    { "AT+CTZU", modem_error },
-    { "AT%CTZV", modem_error },
-    { "AT%CNIV", modem_error },
-    { "AT%PVRF", modem_error },
-    { "AT%CWUP", modem_error },
-    { "AT%DAR", modem_error },
-    { "AT+CIND", modem_error },
-    { "AT+CMER", modem_error },
-    { "AT%CSCN", modem_error },
-    { "AT%RDL", modem_error },
-    { "AT%RDLB", modem_error },
-    { "AT%CSTAT", modem_error },
-    { "AT%CPRSM", modem_error },
-    { "AT%CHLD", modem_error },
-    { "AT%SIMIND", modem_error },
-    { "AT%SECP", modem_error },
-    { "AT%SECS", modem_error },
-    { "AT%CSSN", modem_error },
-    { "AT+CCLK", modem_error },
-    { "AT%CSSD", modem_error },
-    { "AT%COPS", modem_error },
-    { "AT%CPMBW", modem_error },
-    { "AT%CUST", modem_error },
-    { "AT%SATCC", modem_error },
-    { "AT%COPN", modem_error },
-    { "AT%CGEREP", modem_error },
-    { "AT%CUSCFG", modem_error },
-    { "AT%CUSDR", modem_error },
-    { "AT%CPBS", modem_error },
-    { "AT%PBCF", modem_error },
-    { "AT%SIMEF", modem_error },
-    { "AT%EFRSLT", modem_error },
-    { "AT%CMGMDU", modem_error },
-    { "AT%CMGL", modem_error },
-    { "AT%CMGR", modem_error },
-    { "ATA", modem_ok },
-    { "ATB", modem_error },
-    { "AT&C", modem_error },
-    { "ATD", modem_ok },
-    { "AT&D", modem_error },
-    { "ATE", modem_ok },
-    { "ATF", modem_error },
-    { "AT&F", modem_error },
-    { "ATH", modem_ok },
-    { "ATI", modem_error },
-    { "AT&K", modem_error },
-    { "ATL", modem_error },
-    { "ATM", modem_error },
-    { "ATO", modem_error },
-    { "ATP", modem_error },
-    { "ATQ", modem_error },
-    { "ATS", modem_error },
-    { "ATT", modem_error },
-    { "ATV", modem_error },
-    { "ATW", modem_error },
-    { "AT&W", modem_error },
-    { "ATX", modem_error },
-    { "ATZ", modem_error },
-    { 0 }
-};
-
-static void modem_cmd(struct modem_s *s, const char *cmd)
-{
-    struct modem_cmd_s *entry;
-    const char *eq, *param;
-    int ok;
-    eq = strchr(cmd, '=');
-    if (eq)
-        param = eq + 1;
-    else
-        param = 0;
-    ok = 0;
-    for (entry = modem_cmds; entry->cmd; entry ++)
-        if (!strncmp(cmd, entry->cmd, strlen(entry->cmd))) {
-            switch (entry->action) {
-            case modem_ok:
-                ok = 1;
-                break;
-            case modem_error:
-                ok = 0;
-                break;
-            case modem_call:
-                ok = entry->call(s, param);
-                break;
-            case modem_str:
-                modem_resp(s, entry->resp);
-                ok = 1;
-                break;
-            }
-            return;
-        }
-    if (ok)
-        modem_resp(s, "OK\n");
-    else
-        modem_resp(s, "ERROR\n");
-}
-
 static int modem_write(struct CharDriverState *chr,
                 const uint8_t *buf, int len)
 {
     struct modem_s *s = (struct modem_s *) chr->opaque;
-    char *eol;
     if (!s->enable)
         return 0;
 
-    len = MIN(len, 1023 - s->cmd_len);
-    memcpy(s->cmd + s->cmd_len, buf, len);
-    s->cmd_len += len;
-    s->cmd[s->cmd_len] = 0;
-
-    eol = strchr(s->cmd, '\n');
-    if (eol) {
-        s->cmd_len -= eol - s->cmd;
-        *eol = 0;
-        modem_cmd(s, s->cmd);
-        memcpy(s->cmd, eol + 1, s->cmd_len --);
-    } else if (s->cmd_len >= 1023)
-        s->cmd_len = 0;
+    gn_atem_incoming_data_handle(buf, len);
     return len;
 }
 
@@ -399,7 +190,7 @@
         if (!s->enable)
             return -ENOTSUP;
         if (*(int *) arg)
-            modem_resp(s, "AT-Command Interpreter Ready\nOK\n");
+            modem_resp(s, "AT-Command Interpreter Ready\r\nOK\r\n");
         break;
 
     default:
@@ -430,5 +221,18 @@
     s->chr.chr_ioctl = modem_ioctl;
     s->out_tm = qemu_new_timer(vm_clock, modem_out_tick, s);
 
+    s->state.info = &s->info;
+    s->info.write = modem_resp;
+    s->info.opaque = s;
+
+    if (!gn_atem_initialise(0, 1, &s->state))
+        goto fail;
+
+    if (!dp_Initialise(0, 1))
+        goto fail;
+
     return &s->chr;
+fail:
+    fprintf(stderr, "%s: GSM modem initialisation failed\n", __FUNCTION__);
+    exit(-1);
 }

Modified: trunk/src/host/qemu-neo1973/hw/s3c2410.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/s3c2410.c	2007-05-16 22:38:21 UTC (rev 1986)
+++ trunk/src/host/qemu-neo1973/hw/s3c2410.c	2007-05-17 00:24:48 UTC (rev 1987)
@@ -133,6 +133,19 @@
     [S3C_PICS_ADC  & 31] = S3C_PIC_ADC,
 };
 
+static void s3c_pic_subupdate(struct s3c_pic_state_s *s)
+{
+    int next;
+    const int *sub = &s3c_sub_src_map[-1];
+    uint32_t pnd = s->subsrcpnd & ~s->intsubmsk;
+    while ((next = ffs(pnd))) {
+        sub += next;
+        pnd >>= next;
+        s->srcpnd |= 1 << *sub;
+    }
+    s3c_pic_arbitrate(s);
+}
+
 static void s3c_pic_set_irq(void *opaque, int irq, int req)
 {
     struct s3c_pic_state_s *s = (struct s3c_pic_state_s *) opaque;
@@ -145,10 +158,10 @@
     if (irq & 32) {
         irq &= 31;
         s->subsrcpnd |= 1 << irq;
-        if (~s->intsubmsk & (1 << irq))
+        if (s->intsubmsk & (1 << irq))
+            return;
+        else
             irq = s3c_sub_src_map[irq];
-        else
-            return;
     }
     s->srcpnd |= (mask = 1 << irq);
 
@@ -255,6 +268,7 @@
         break;
     case S3C_INTSUBMSK:
         s->intsubmsk = value;
+        s3c_pic_subupdate(s);
         break;
     default:
         printf("%s: Bad register 0x%lx\n", __FUNCTION__, addr);
@@ -1106,37 +1120,6 @@
     s->rxlen = 0;
 }
 
-static void s3c_uart_params_update(struct s3c_uart_state_s *s)
-{
-    QEMUSerialSetParams ssp;
-    int i;
-    if (!s->chr)
-        return;
-
-    /* XXX Calculate PCLK frequency from clock manager registers */
-    ssp.speed = (S3C_PCLK_FREQ >> 4) / (s->brdiv + 1);
-
-    switch ((s->lcontrol >> 3) & 7) {
-    case 4:
-    case 6:
-        ssp.parity = 'O';
-        break;
-    case 5:
-    case 7:
-        ssp.parity = 'E';
-        break;
-    default:
-        ssp.parity = 'N';
-    }
-
-    ssp.data_bits = 5 + (s->lcontrol & 3);
-
-    ssp.stop_bits = (s->lcontrol & (1 << 2)) ? 2 : 1;
-
-    for (i = 0; i < s->chr_num; i ++)
-        qemu_chr_ioctl(s->chr[i], CHR_IOCTL_SERIAL_SET_PARAMS, &ssp);
-}
-
 static void s3c_uart_err(struct s3c_uart_state_s *s, int err)
 {
     s->errstat |= err;
@@ -1144,7 +1127,7 @@
         qemu_irq_raise(s->irq[2]);
 }
 
-static void s3c_uart_full(struct s3c_uart_state_s *s)
+inline static void s3c_uart_full(struct s3c_uart_state_s *s, int pulse)
 {
     if (s->fcontrol & 1)			/* FIFOEnable */
         if (s->rxlen < (((s->fcontrol >> 4) & 3) + 1) * 4)
@@ -1152,7 +1135,8 @@
 
     switch ((s->control >> 0) & 3) {		/* ReceiveMode */
     case 1:
-        qemu_irq_raise(s->irq[0]);
+        if ((s->control & (1 << 8)) || pulse)	/* RxInterruptType */
+            qemu_irq_raise(s->irq[0]);
         break;
     case 2:
     case 3:
@@ -1161,11 +1145,12 @@
     }
 }
 
-static void s3c_uart_empty(struct s3c_uart_state_s *s)
+inline static void s3c_uart_empty(struct s3c_uart_state_s *s, int pulse)
 {
     switch ((s->control >> 2) & 3) {		/* TransmitMode */
     case 1:
-        qemu_irq_raise(s->irq[1]);
+        if ((s->control & (1 << 9)) || pulse)	/* TxInterruptType */
+            qemu_irq_raise(s->irq[1]);
         break;
     case 2:
     case 3:
@@ -1174,6 +1159,43 @@
     }
 }
 
+inline static void s3c_uart_update(struct s3c_uart_state_s *s)
+{
+    s3c_uart_empty(s, 0);
+    s3c_uart_full(s, 0);
+}
+
+static void s3c_uart_params_update(struct s3c_uart_state_s *s)
+{
+    QEMUSerialSetParams ssp;
+    int i;
+    if (!s->chr)
+        return;
+
+    /* XXX Calculate PCLK frequency from clock manager registers */
+    ssp.speed = (S3C_PCLK_FREQ >> 4) / (s->brdiv + 1);
+
+    switch ((s->lcontrol >> 3) & 7) {
+    case 4:
+    case 6:
+        ssp.parity = 'O';
+        break;
+    case 5:
+    case 7:
+        ssp.parity = 'E';
+        break;
+    default:
+        ssp.parity = 'N';
+    }
+
+    ssp.data_bits = 5 + (s->lcontrol & 3);
+
+    ssp.stop_bits = (s->lcontrol & (1 << 2)) ? 2 : 1;
+
+    for (i = 0; i < s->chr_num; i ++)
+        qemu_chr_ioctl(s->chr[i], CHR_IOCTL_SERIAL_SET_PARAMS, &ssp);
+}
+
 static int s3c_uart_is_empty(void *opaque)
 {
     struct s3c_uart_state_s *s = (struct s3c_uart_state_s *) opaque;
@@ -1206,7 +1228,7 @@
         s->rxlen = 1;
         s->data = buf[0];
     }
-    s3c_uart_full(s);
+    s3c_uart_full(s, 1);
 }
 
 /* S3C2410 UART doesn't seem to understand break conditions.  */
@@ -1244,14 +1266,19 @@
     case S3C_UTRSTAT:
         return 6 | !!s->rxlen;
     case S3C_UERSTAT:
+        /* XXX: UERSTAT[3] is Reserved but Linux thinks it is BREAK */
         ret = s->errstat;
         s->errstat = 0;
+        s3c_uart_update(s);
         return ret;
     case S3C_UFSTAT:
-        return ((!!s->rxlen) << 8) | s->rxlen;
+        s3c_uart_update(s);
+        return s->rxlen ? s->rxlen | (1 << 8) : 0;
     case S3C_UMSTAT:
-        return 1;
+        s3c_uart_update(s);
+        return 0x11;
     case S3C_URXH:
+        s3c_uart_update(s);
         if (s->rxlen) {
             s->rxlen --;
             if (s->fcontrol & 1) {		/* FIFOEnable */
@@ -1286,17 +1313,21 @@
                             (value & (1 << 6)) ? "on" : "off");
         s->lcontrol = value;
         s3c_uart_params_update(s);
+        s3c_uart_update(s);
         break;
     case S3C_UCON:
+        /* XXX: UCON[4] is Reserved but Linux thinks it is BREAK */
         if ((s->control ^ value) & (1 << 5))
             printf("%s: UART loopback test mode %s\n", __FUNCTION__,
                             (value & (1 << 5)) ? "on" : "off");
         s->control = value & 0x7ef;
+        s3c_uart_update(s);
         break;
     case S3C_UFCON:
         if (value & (1 << 1))			/* RxReset */
             s->rxlen = 0;
         s->fcontrol = value & 0xf1;
+        s3c_uart_update(s);
         break;
     case S3C_UMCON:
         if ((s->mcontrol ^ value) & (1 << 4)) {
@@ -1305,16 +1336,19 @@
                 qemu_chr_ioctl(s->chr[i], CHR_IOCTL_MODEM_HANDSHAKE, &afc);
         }
         s->mcontrol = value & 0x11;
+        s3c_uart_update(s);
         break;
     case S3C_UTXH:
         ch = value & 0xff;
         for (i = 0; i < s->chr_num; i ++)
             qemu_chr_write(s->chr[i], &ch, 1);
-        s3c_uart_empty(s);
+        s3c_uart_empty(s, 1);
+        s3c_uart_update(s);
         break;
     case S3C_UBRDIV:
         s->brdiv = value & 0xffff;
         s3c_uart_params_update(s);
+        s3c_uart_update(s);
         break;
     default:
         printf("%s: Bad register 0x%lx\n", __FUNCTION__, addr);





More information about the commitlog mailing list