Exemple #1
0
static GSM_Error MBUS2_SendAck(GSM_StateMachine 	*s,
                               unsigned char 		type,
                               unsigned char 		sequence)
{
    GSM_Device_Functions 	*Device		= s->Device.Functions;
    unsigned char 		buffer[6]= {0};
    int 			i=0,length=0,write_data=0;

    buffer[0] = MBUS2_FRAME_ID;
    buffer[1] = MBUS2_DEVICE_PHONE;	/* destination */
    buffer[2] = MBUS2_DEVICE_PC;		/* source */
    buffer[3] = MBUS2_ACK_BYTE;
    buffer[4] = sequence;
    buffer[5] = '\0';
    length=strlen(buffer);

    /* Calculating checksum */
    for (i = 0; i < length; i++) {
        buffer[5] ^= buffer[i];
    }
    smprintf_level(s, D_TEXT, "[Sending Ack of type %02x, seq: %x]\n",type,sequence);

    /* Sending to phone */
    write_data=Device->WriteDevice(s,buffer,length);

    if (write_data!=length) {
        return ERR_DEVICEWRITEERROR;
    }
    return ERR_NONE;
}
Exemple #2
0
static GSM_Error FBUS2_SendAck(GSM_StateMachine 	*s,
			       unsigned char 		MsgType,
			       unsigned char 		MsgSequence)
{
	unsigned char buffer[2]={0};

	buffer[0] = MsgType;
	buffer[1] = MsgSequence;

	smprintf_level(s, D_TEXT, "[Sending Ack of type %02x, seq %x]\n",
			buffer[0],
			buffer[1]);

	/* Sending to phone */
	return FBUS2_WriteFrame(s, buffer, 2, FBUS2_ACK_BYTE);
}
Exemple #3
0
GSM_Error GSM_WaitFor (GSM_StateMachine *s, unsigned const char *buffer,
		       int length, int type, int timeout,
		       GSM_Phone_RequestID request)
{
	GSM_Phone_Data		*Phone = &s->Phone.Data;
	GSM_Error		error;
	int			reply;

	if (s->CurrentConfig->StartInfo) {
		if (Phone->StartInfoCounter > 0) {
			Phone->StartInfoCounter--;
			if (Phone->StartInfoCounter == 0) s->Phone.Functions->ShowStartInfo(s,FALSE);
		}
	}

	Phone->RequestID	= request;
	Phone->DispatchError	= ERR_TIMEOUT;

	for (reply=0;reply<s->ReplyNum;reply++) {
		if (reply!=0) {
			smprintf_level(s, D_ERROR, "[Retrying %i type 0x%02X]\n", reply, type);
		}
		error = s->Protocol.Functions->WriteMessage(s, buffer, length, type);
		if (error!=ERR_NONE) return error;

		/* Special case when no reply is expected */
		if (request == ID_None) {
			return ERR_NONE;
		}

		error = GSM_WaitForOnce(s, buffer, length, type, timeout);
		if (error != ERR_TIMEOUT) return error;
        }

	return ERR_TIMEOUT;
}
Exemple #4
0
static GSM_Error FBUS2_StateMachine(GSM_StateMachine *s, unsigned char rx_char)
{
	GSM_Protocol_FBUS2Data 	*d = &s->Protocol.Data.FBUS2;
	unsigned char 		frm_num, seq_num;
	gboolean			correct = FALSE;

	/* XOR the byte with the earlier checksum */
	d->Msg.CheckSum[d->Msg.Count & 1] ^= rx_char;

	if (d->MsgRXState == RX_GetMessage) {
		d->Msg.Buffer[d->Msg.Count] = rx_char;
		d->Msg.Count++;

		/* This is not last byte in frame */
		if (d->Msg.Count != d->Msg.Length+(d->Msg.Length%2)+2) return ERR_NONE;

		/* Checksum is incorrect */
		if (d->Msg.CheckSum[0] != d->Msg.CheckSum[1]) {
			smprintf_level(s, D_ERROR, "[ERROR: checksum]\n");
			free(d->Msg.Buffer);
			d->Msg.Buffer = NULL;
			d->Msg.Length = 0;
			d->MsgRXState = RX_Sync;
			return ERR_NONE;
		}

		seq_num = d->Msg.Buffer[d->Msg.Length-1];

		if (d->Msg.Type == FBUS2_ACK_BYTE) {
			smprintf_level(s, D_TEXT, "[Received Ack of type %02x, seq %02x]\n",
					d->Msg.Buffer[0], seq_num);
			free(d->Msg.Buffer);
			d->Msg.Buffer = NULL;
			d->Msg.Length = 0;
			d->MsgRXState = RX_Sync;
			return ERR_NONE;
		}

		frm_num = d->Msg.Buffer[d->Msg.Length-2];

		if ((seq_num & 0x40) == 0x40) {
			d->FramesToGo		= frm_num;
			d->MultiMsg.Length	= 0;
			d->MultiMsg.Type	= d->Msg.Type;
			d->MultiMsg.Destination	= d->Msg.Destination;
			d->MultiMsg.Source	= d->Msg.Source;
		}

		if ((seq_num & 0x40) != 0x40 && d->FramesToGo != frm_num) {
			smprintf_level(s, D_ERROR, "[ERROR: Missed part of multiframe msg]\n");
			free(d->Msg.Buffer);
			d->Msg.Buffer = NULL;
			d->Msg.Length = 0;
			d->MsgRXState = RX_Sync;
			return ERR_NONE;
		}

		if ((seq_num & 0x40) != 0x40 && d->Msg.Type != d->MultiMsg.Type) {
			smprintf_level(s, D_ERROR, "[ERROR: Multiframe msg in multiframe msg]\n");
			free(d->Msg.Buffer);
			d->Msg.Buffer = NULL;
			d->Msg.Length = 0;
			d->MsgRXState = RX_Sync;
			return ERR_NONE;
		}

		if (d->MultiMsg.BufferUsed < d->MultiMsg.Length+d->Msg.Length-2) {
			d->MultiMsg.BufferUsed 	= d->MultiMsg.Length+d->Msg.Length-2;
			d->MultiMsg.Buffer 	= (unsigned char *)realloc(d->MultiMsg.Buffer,d->MultiMsg.BufferUsed);
		}
		memcpy(d->MultiMsg.Buffer+d->MultiMsg.Length,d->Msg.Buffer,d->Msg.Length-2);
		d->MultiMsg.Length = d->MultiMsg.Length+d->Msg.Length-2;

		free(d->Msg.Buffer);
		d->Msg.Buffer = NULL;
		d->Msg.Length = 0;
		d->FramesToGo--;

		/* do not ack debug trace, as this could generate a
		 * (feedback loop) flood of which even Noah would be scared.
		 */
		if (d->Msg.Type != 0) {
			FBUS2_SendAck(s,d->Msg.Type,((unsigned char)(seq_num & 0x0f)));
		}

		if (d->FramesToGo == 0) {
			s->Phone.Data.RequestMsg	= &d->MultiMsg;
			s->Phone.Data.DispatchError	= s->Phone.Functions->DispatchMessage(s);
		}
		d->MsgRXState = RX_Sync;
		return ERR_NONE;
	}
	if (d->MsgRXState == RX_GetLength2) {
		d->Msg.Length 	= d->Msg.Length + rx_char;
		d->Msg.Buffer 	= (unsigned char *)malloc(d->Msg.Length+3);
		d->MsgRXState 	= RX_GetMessage;
		return ERR_NONE;
	}
	if (d->MsgRXState == RX_GetLength1) {
		d->Msg.Length = rx_char * 256;
		d->MsgRXState = RX_GetLength2;
		return ERR_NONE;
	}
	if (d->MsgRXState == RX_GetType) {
		d->Msg.Type   = rx_char;
		d->MsgRXState = RX_GetLength1;
		return ERR_NONE;
	}
	if (d->MsgRXState == RX_GetSource) {
		if (rx_char != FBUS2_DEVICE_PHONE) {
			smprintf_level(s, D_ERROR, "[ERROR: incorrect char - %02x, not %02x]\n",
					rx_char, FBUS2_DEVICE_PHONE);

			d->MsgRXState = RX_Sync;
			return ERR_NONE;
		}
		d->Msg.Source = rx_char;

		d->MsgRXState = RX_GetType;
		return ERR_NONE;
	}
	if (d->MsgRXState == RX_GetDestination) {
		if (rx_char != FBUS2_DEVICE_PC) {
			smprintf_level(s, D_ERROR, "[ERROR: incorrect char - %02x, not %02x]\n",
					rx_char, FBUS2_DEVICE_PC);

			d->MsgRXState = RX_Sync;
			return ERR_NONE;
		}
		d->Msg.Destination = rx_char;

		d->MsgRXState 	   = RX_GetSource;
		return ERR_NONE;
	}
	if (d->MsgRXState == RX_Sync) {
		switch (s->ConnectionType) {
			case GCT_FBUS2:
			case GCT_FBUS2DLR3:
			case GCT_DKU5FBUS2:
			case GCT_FBUS2PL2303:
			case GCT_FBUS2BLUE:
			case GCT_BLUEFBUS2:
				if (rx_char == FBUS2_FRAME_ID) correct = TRUE;
				break;
			case GCT_FBUS2IRDA:
				if (rx_char == FBUS2_IRDA_FRAME_ID) correct = TRUE;
				break;
			default:
				break;
		}
		if (!correct) {
			smprintf_level(s, D_ERROR, "[ERROR: incorrect char - %02x, not %02x]\n",
					rx_char,
					(s->ConnectionType == GCT_FBUS2IRDA) ? FBUS2_IRDA_FRAME_ID : FBUS2_FRAME_ID);
			if (rx_char == 0x20) {
				smprintf(s, "0x20 reply detected...\n");
				smprintf(s, "Trying to reinit connection...\n");
				FBUS2_Initialise(s);
			}
			return ERR_NONE;
		}

		d->Msg.CheckSum[0] = rx_char;
		d->Msg.CheckSum[1] = 0;
		d->Msg.Count	   = 0;

		d->MsgRXState	   = RX_GetDestination;
		return ERR_NONE;
	}
	return ERR_NONE;
}
Exemple #5
0
static GSM_Error MBUS2_StateMachine(GSM_StateMachine *s, unsigned char rx_char)
{
    GSM_Phone_Functions 	*Phone	= s->Phone.Functions;
    GSM_Protocol_MBUS2Data 	*d	= &s->Protocol.Data.MBUS2;

    d->Msg.CheckSum[0] = d->Msg.CheckSum[1];
    d->Msg.CheckSum[1] ^= rx_char;

    if (d->MsgRXState == RX_GetMessage) {
        d->Msg.Buffer[d->Msg.Count] = rx_char;
        d->Msg.Count++;

        /* This is not last byte in frame */
        if (d->Msg.Count != d->Msg.Length+2) return ERR_NONE;

        /* Checksum is incorrect */
        if (d->Msg.CheckSum[0] != rx_char) {
            smprintf_level(s, D_ERROR, "[ERROR: checksum]\n");

            d->MsgRXState = RX_Sync;
            return ERR_NONE;
        }

        if (d->Msg.Destination != MBUS2_DEVICE_PHONE) {
            MBUS2_SendAck(s, d->Msg.Type, d->Msg.Buffer[d->Msg.Count-2]);
            s->Phone.Data.RequestMsg	= &d->Msg;
            s->Phone.Data.DispatchError	= Phone->DispatchMessage(s);
        }

        d->MsgRXState = RX_Sync;
        return ERR_NONE;
    }
    if (d->MsgRXState == RX_GetLength2) {
        if (d->Msg.Type == MBUS2_ACK_BYTE) {
            smprintf_level(s, D_TEXT, "[Received Ack]\n");

            d->MsgRXState = RX_Sync;
            return ERR_NONE;
        }

        d->Msg.Length = d->Msg.Length + rx_char;
        if (d->Msg.BufferUsed < d->Msg.Length+2) {
            d->Msg.BufferUsed 	= d->Msg.Length+2;
            d->Msg.Buffer 		= (unsigned char *)realloc(d->Msg.Buffer,d->Msg.BufferUsed);
        }

        d->MsgRXState = RX_GetMessage;
        return ERR_NONE;
    }
    if (d->MsgRXState == RX_GetLength1) {
        d->Msg.Length = rx_char * 256;

        d->MsgRXState = RX_GetLength2;
        return ERR_NONE;
    }
    if (d->MsgRXState == RX_GetType) {
        d->Msg.Type   = rx_char;

        d->MsgRXState = RX_GetLength1;
        return ERR_NONE;
    }
    if (d->MsgRXState == RX_GetSource) {
        if (rx_char != MBUS2_DEVICE_PHONE && rx_char != MBUS2_DEVICE_PC) {
            smprintf_level(s, D_ERROR, "[ERROR: incorrect char - %02x, not %02x and %02x]\n",
                           rx_char, MBUS2_DEVICE_PHONE, MBUS2_DEVICE_PC);
            d->MsgRXState = RX_Sync;
            return ERR_NONE;
        }
        d->Msg.Source = rx_char;

        d->MsgRXState = RX_GetType;
        return ERR_NONE;
    }
    if (d->MsgRXState == RX_GetDestination) {
        if (rx_char != MBUS2_DEVICE_PC && rx_char != MBUS2_DEVICE_PHONE) {
            smprintf_level(s, D_ERROR, "[ERROR: incorrect char - %02x, not %02x and %02x]\n",
                           rx_char, MBUS2_DEVICE_PHONE, MBUS2_DEVICE_PC);
            d->MsgRXState = RX_Sync;
            return ERR_NONE;
        }
        d->Msg.Destination 	= rx_char;

        d->MsgRXState 		= RX_GetSource;
        return ERR_NONE;
    }
    if (d->MsgRXState == RX_Sync) {
        if (rx_char != MBUS2_FRAME_ID) {
            smprintf_level(s, D_ERROR, "[ERROR: incorrect char - %02x, not %02x]\n",
                           rx_char, MBUS2_FRAME_ID);
            return ERR_NONE;
        }
        d->Msg.CheckSum[1] 	= MBUS2_FRAME_ID;
        d->Msg.Count 		= 0;

        d->MsgRXState 		= RX_GetDestination;
        return ERR_NONE;
    }
    return ERR_NONE;
}
Exemple #6
0
GSM_Error GSM_InitConnection_Log(GSM_StateMachine *s, int ReplyNum, GSM_Log_Function log_function, void *user_data)
{
	GSM_Error	error;
	GSM_DateTime	current_time;
	int		i;

	for (i=0;i<s->ConfigNum;i++) {
		s->CurrentConfig		  = &s->Config[i];

		/* Skip non configured sections */
		if (s->CurrentConfig->Connection == NULL) {
			smprintf_level(s, D_ERROR, "[Empty section    - %d]\n", i);
			continue;
		}

		s->Speed			  = 0;
		s->ReplyNum			  = ReplyNum;
		s->Phone.Data.ModelInfo		  = GetModelData(s, "unknown", NULL, NULL);
		s->Phone.Data.Manufacturer[0]	  = 0;
		s->Phone.Data.Model[0]		  = 0;
		s->Phone.Data.Version[0]	  = 0;
		s->Phone.Data.VerDate[0]	  = 0;
		s->Phone.Data.VerNum		  = 0;
		s->Phone.Data.StartInfoCounter	  = 0;
		s->Phone.Data.SentMsg		  = NULL;

		s->Phone.Data.HardwareCache[0]	  = 0;
		s->Phone.Data.ProductCodeCache[0] = 0;
		s->Phone.Data.EnableIncomingCall  = FALSE;
		s->Phone.Data.EnableIncomingSMS	  = FALSE;
		s->Phone.Data.EnableIncomingCB	  = FALSE;
		s->Phone.Data.EnableIncomingUSSD  = FALSE;
		s->User.UserReplyFunctions	  = NULL;
		s->User.IncomingCall		  = NULL;
		s->User.IncomingSMS		  = NULL;
		s->User.IncomingCB		  = NULL;
		s->User.IncomingUSSD		  = NULL;
		s->User.SendSMSStatus		  = NULL;
		s->LockFile			  = NULL;
		s->opened			  = FALSE;
		s->Phone.Functions		  = NULL;

		s->di 				  = GSM_none_debug;
		s->di.use_global 		  = s->CurrentConfig->UseGlobalDebugFile;
		if (!s->di.use_global) {
			GSM_SetDebugFunction(log_function, user_data, &s->di);
			GSM_SetDebugLevel(s->CurrentConfig->DebugLevel, &s->di);
			error = GSM_SetDebugFile(s->CurrentConfig->DebugFile, &s->di);
			if (error != ERR_NONE) {
				GSM_LogError(s, "Init:GSM_SetDebugFile" , error);
				return error;
			}
		}

		smprintf_level(s, D_ERROR, "[Gammu            - %s built %s %s using %s]\n",
				GAMMU_VERSION,
				__TIME__,
				__DATE__,
				GetCompiler()
				);
		StripSpaces(s->CurrentConfig->Connection);
		StripSpaces(s->CurrentConfig->Model);
		StripSpaces(s->CurrentConfig->Device);
		smprintf_level(s, D_ERROR, "[Connection       - \"%s\"]\n",
				s->CurrentConfig->Connection);
		smprintf_level(s, D_ERROR, "[Connection index - %d]\n", i);
		smprintf_level(s, D_ERROR, "[Model type       - \"%s\"]\n",
				s->CurrentConfig->Model);
		smprintf_level(s, D_ERROR, "[Device           - \"%s\"]\n",
				s->CurrentConfig->Device);
		if (strlen(GetOS()) != 0) {
			smprintf_level(s, D_ERROR, "[Running on       - %s]\n",
					GetOS());
		}

		if (GSM_GetDI(s)->dl == DL_BINARY) {
			smprintf(s,"%c",((unsigned char)strlen(GAMMU_VERSION)));
			smprintf(s,"%s",GAMMU_VERSION);
		}

		error = GSM_RegisterAllConnections(s, s->CurrentConfig->Connection);
		if (error != ERR_NONE) {
			GSM_LogError(s, "Init:GSM_RegisterAllConnections" , error);
			return error;
		}

autodetect:
		/* Model auto */
		/* Try to guess correct driver based on model */
		if (s->CurrentConfig->Model[0] == 0 &&
				s->ConnectionType != GCT_NONE &&
				s->ConnectionType != GCT_IRDAOBEX &&
				s->ConnectionType != GCT_BLUEOBEX &&
				s->ConnectionType != GCT_BLUEGNAPBUS &&
				s->ConnectionType != GCT_IRDAGNAPBUS &&
				s->ConnectionType != GCT_BLUES60) {
			error = GSM_TryGetModel(s);
			/* Fall back to other configuraitons if the device is not existing (or similar error) */
			if ((i != s->ConfigNum - 1) && (
				(error == ERR_DEVICEOPENERROR) ||
				(error == ERR_DEVICELOCKED) ||
				(error == ERR_DEVICENOTEXIST) ||
				(error == ERR_DEVICEBUSY) ||
				(error == ERR_DEVICENOPERMISSION) ||
				(error == ERR_DEVICENODRIVER) ||
				(error == ERR_DEVICENOTWORK))) {
				GSM_CloseConnection(s);
				continue;
			}
			if (error != ERR_NONE) {
				GSM_LogError(s, "Init:GSM_TryGetModel" , error);
				return error;
			}
		}

		/* Switching to "correct" module */
		error = GSM_RegisterAllPhoneModules(s);
		/* If user selected soemthing which is not supported, try autodetection */
		if (s->CurrentConfig->Model[0] != 0 && error == ERR_UNKNOWNMODELSTRING) {
			smprintf(s, "Configured model %s is not known, retrying with autodetection!\n",
					s->CurrentConfig->Model);
			s->CurrentConfig->Model[0] = 0;
			goto autodetect;
		}
		if (error != ERR_NONE) {
			GSM_LogError(s, "Init:GSM_RegisterAllPhoneModules" , error);
			return error;
		}

		/* We didn't open device earlier ? Make it now */
		if (!s->opened) {
			error = GSM_OpenConnection(s);
			if ((i != s->ConfigNum - 1) && (
				(error == ERR_DEVICEOPENERROR) ||
				(error == ERR_DEVICELOCKED) ||
				(error == ERR_DEVICENOTEXIST) ||
				(error == ERR_DEVICEBUSY) ||
				(error == ERR_DEVICENOPERMISSION) ||
				(error == ERR_DEVICENODRIVER) ||
				(error == ERR_DEVICENOTWORK))) {
				GSM_CloseConnection(s);
				continue;
			}
			if (error != ERR_NONE) {
				GSM_LogError(s, "Init:GSM_OpenConnection" , error);
				return error;
			}
		}

		/* Initialize phone layer */
		error=s->Phone.Functions->Initialise(s);
		if (error == ERR_TIMEOUT && i != s->ConfigNum - 1) {
			GSM_CloseConnection(s);
			continue;
		}
		if (error != ERR_NONE) {
			GSM_LogError(s, "Init:Phone->Initialise" , error);
			return error;
		}

		if (s->CurrentConfig->StartInfo) {
			s->Phone.Functions->ShowStartInfo(s,TRUE);
			s->Phone.Data.StartInfoCounter = 30;
		}

		if (s->CurrentConfig->SyncTime) {
			GSM_GetCurrentDateTime (&current_time);
			s->Phone.Functions->SetDateTime(s,&current_time);
		}

		/* For debug it's good to have firmware and real model version and manufacturer */
		error=s->Phone.Functions->GetManufacturer(s);
		if (error == ERR_TIMEOUT && i != s->ConfigNum - 1) {
			GSM_CloseConnection(s);
			continue;
		}
		if (error != ERR_NONE && error != ERR_NOTSUPPORTED) {
			GSM_LogError(s, "Init:Phone->GetManufacturer" , error);
			return error;
		}

		error=s->Phone.Functions->GetModel(s);
		if (error != ERR_NONE && error != ERR_NOTSUPPORTED) {
			GSM_LogError(s, "Init:Phone->GetModel" , error);
			return error;
		}

		error=s->Phone.Functions->GetFirmware(s);
		if (error != ERR_NONE && error != ERR_NOTSUPPORTED) {
			GSM_LogError(s, "Init:Phone->GetFirmware" , error);
			return error;
		}

		smprintf(s,"[Connected]\n");
		return ERR_NONE;
	}
	return ERR_UNCONFIGURED;
}
Exemple #7
0
GSM_Error GSM_DispatchMessage(GSM_StateMachine *s)
{
	GSM_Error		error	= ERR_UNKNOWNFRAME;
	GSM_Protocol_Message	*msg 	= s->Phone.Data.RequestMsg;
	GSM_Phone_Data 		*Phone	= &s->Phone.Data;
	gboolean			disp    = FALSE;
	GSM_Reply_Function	*Reply;
	int			reply;

	GSM_DumpMessageLevel2Recv(s, msg->Buffer, msg->Length, msg->Type);
	GSM_DumpMessageLevel3Recv(s, msg->Buffer, msg->Length, msg->Type);

	Reply = s->User.UserReplyFunctions;
	if (Reply != NULL) {
		error = CheckReplyFunctions(s,Reply,&reply);
	}

	if (error == ERR_UNKNOWNFRAME) {
		Reply = s->Phone.Functions->ReplyFunctions;
		error = CheckReplyFunctions(s,Reply,&reply);
	}

	if (error==ERR_NONE) {
		error=Reply[reply].Function(msg, s);
		if (Reply[reply].requestID==Phone->RequestID) {
			if (error == ERR_NEEDANOTHERANSWER) {
				error = ERR_NONE;
			} else {
				Phone->RequestID=ID_None;
			}
		}
	}

	if (strcmp(s->Phone.Functions->models,"NAUTO")) {
		disp = TRUE;
		switch (error) {
		case ERR_UNKNOWNRESPONSE:
			smprintf_level(s, D_ERROR, "\nUNKNOWN response");
			break;
		case ERR_UNKNOWNFRAME:
			smprintf_level(s, D_ERROR, "\nUNKNOWN frame");
			break;
		case ERR_FRAMENOTREQUESTED:
			smprintf_level(s, D_ERROR, "\nFrame not request now");
			break;
		default:
			disp = FALSE;
		}

		if (error == ERR_UNKNOWNFRAME || error == ERR_FRAMENOTREQUESTED) {
			error = ERR_TIMEOUT;
		}
	}

	if (disp) {
		smprintf(s,". Please report the error, see <http://wammu.eu/support/bugs/>. Thank you\n");
		if (Phone->SentMsg != NULL) {
			smprintf(s,"LAST SENT frame ");
			smprintf(s, "type 0x%02X/length %ld", Phone->SentMsg->Type, (long)Phone->SentMsg->Length);
			DumpMessage(GSM_GetDI(s), Phone->SentMsg->Buffer, Phone->SentMsg->Length);
		}
		smprintf(s, "RECEIVED frame ");
		smprintf(s, "type 0x%02X/length 0x%lx/%ld", msg->Type, (long)msg->Length, (long)msg->Length);
		DumpMessage(GSM_GetDI(s), msg->Buffer, msg->Length);
		smprintf(s, "\n");
	}

	return error;
}