1 /* This program is free software; you can redistribute it and/or modify
2  * it under the terms of the GNU General Public License as published by
3  * the Free Software Foundation; either version 2 of the License, or
4  * (at your option) any later version.
5  *
6  * This program is distributed in the hope that it will be useful,
7  * but WITHOUT ANY WARRANTY; without even the implied warranty of
8  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
9  * GNU General Public License for more details.
10  *
11  * You should have received a copy of the GNU General Public License along
12  * with this program; if not, write to the Free Software Foundation, Inc.,
13  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
14  *
15  * Copyright (c) 2011 Michal Cihar <michal@cihar.com>
16  */
17 
18 
19 #include "../../gsmstate.h"
20 
21 #if defined(GSM_ENABLE_S60)
22 
23 #include <stdio.h>
24 #include <string.h>
25 #include <stdlib.h>
26 
27 #include "../../gsmcomon.h"
28 #include "s60.h"
29 #include "s60-ids.h"
30 
S60_WriteMessage(GSM_StateMachine * s,unsigned const char * MsgBuffer,size_t MsgLength,int MsgType)31 static GSM_Error S60_WriteMessage (GSM_StateMachine *s, unsigned const char *MsgBuffer,
32 				    size_t MsgLength, int MsgType)
33 {
34 	unsigned char	*buffer=NULL;
35 	int pos, sent, length, buflen, bufpos;
36 	GSM_Error error;
37 
38 	/* No type */
39 	if (MsgType == 0) {
40 		return ERR_NONE;
41 	}
42 
43 	/* Allocate buffer for composing message */
44 	buflen = MIN(MAX_LENGTH, MsgLength) + 10;
45 	buffer = (unsigned char *)malloc(buflen);
46 	if (buffer == NULL) {
47 		return ERR_MOREMEMORY;
48 	}
49 
50 	/* Send message parts */
51 	for (pos = 0; MsgLength - pos > MAX_LENGTH; pos += MAX_LENGTH) {
52 		error = S60_WriteMessage(s, MsgBuffer + pos, MAX_LENGTH, NUM_PARTIAL_MESSAGE);
53 		if (error != ERR_NONE) {
54 			free(buffer);
55 			return ERR_DEVICEWRITEERROR;
56 		}
57 	}
58 
59 	/* Send final message */
60 	buffer[0] = MsgType;
61 	length = MsgLength - pos;
62 
63 	bufpos = snprintf(buffer, buflen, "%d%c", MsgType, NUM_END_HEADER);
64 	memcpy(buffer + bufpos, MsgBuffer + pos, length);
65 	buffer[bufpos + length] = '\n';
66 	length += bufpos + 1;
67 
68 	/* Debugging */
69 	GSM_DumpMessageBinary(s, buffer, length, MsgType);
70 	GSM_DumpMessageText(s, buffer, length, MsgType);
71 
72 	sent = s->Device.Functions->WriteDevice(s, buffer, length);
73 	free(buffer);
74 	if (sent != length) {
75 		return ERR_DEVICEWRITEERROR;
76 	}
77 
78 	return ERR_NONE;
79 }
80 
S60_StateMachine(GSM_StateMachine * s,unsigned char rxchar)81 static GSM_Error S60_StateMachine(GSM_StateMachine *s, unsigned char rxchar)
82 {
83 	GSM_Protocol_S60Data *d = &s->Protocol.Data.S60;
84 
85 	/* Did we complete part of packet? */
86 	switch (d->State) {
87 		case S60_Header:
88 			if (rxchar == NUM_END_HEADER) {
89 				d->Msg.Type = atoi(d->idbuffer);
90 				d->State = S60_Data;
91 				d->idpos = 0;
92 			} else {
93 				d->idbuffer[d->idpos++] = rxchar;
94 				d->idbuffer[d->idpos] = 0;
95 			}
96 			break;
97 		case S60_Data:
98 			if (rxchar == NUM_END_TEXT) {
99 				d->State = S60_Header;
100 				/* Should we wait for other parts? */
101 				if (d->Msg.Type == NUM_PARTIAL_MESSAGE) {
102 					return ERR_NONE;
103 				}
104 
105 				/* We've got data to process */
106 				s->Phone.Data.RequestMsg = &d->Msg;
107 				s->Phone.Data.DispatchError = s->Phone.Functions->DispatchMessage(s);
108 
109 				/* Reset message length */
110 				d->Msg.Length = 0;
111 			} else {
112 				/* Allocate buffer */
113 				if (d->Msg.BufferUsed < d->Msg.Length + 2) {
114 					d->Msg.BufferUsed = d->Msg.Length + 2;
115 					d->Msg.Buffer = (unsigned char *)realloc(d->Msg.Buffer, d->Msg.BufferUsed);
116 					if (d->Msg.Buffer == NULL) {
117 						return ERR_MOREMEMORY;
118 					}
119 				}
120 
121 				/* Store received byte */
122 				d->Msg.Buffer[d->Msg.Length++] = rxchar;
123 				d->Msg.Buffer[d->Msg.Length] = 0;
124 			}
125 			break;
126 	}
127 
128 	return ERR_NONE;
129 }
130 
S60_Initialise(GSM_StateMachine * s)131 static GSM_Error S60_Initialise(GSM_StateMachine *s)
132 {
133 	GSM_Protocol_S60Data *d = &s->Protocol.Data.S60;
134 
135 	d->Msg.BufferUsed	= 0;
136 	d->Msg.Buffer 		= NULL;
137 	d->Msg.Length		= 0;
138 	d->State = S60_Header;
139 	d->idpos = 0;
140 
141 	return ERR_NONE;
142 }
143 
S60_Terminate(GSM_StateMachine * s)144 static GSM_Error S60_Terminate(GSM_StateMachine *s)
145 {
146 	free(s->Protocol.Data.S60.Msg.Buffer);
147 	s->Protocol.Data.S60.Msg.Buffer = NULL;
148 
149 	return ERR_NONE;
150 }
151 
152 GSM_Protocol_Functions S60Protocol = {
153 	S60_WriteMessage,
154 	S60_StateMachine,
155 	S60_Initialise,
156 	S60_Terminate
157 };
158 
159 #endif
160 
161 
162 /* How should editor hadle tabs in this file? Add editor commands here.
163  * vim: noexpandtab sw=8 ts=8 sts=8:
164  */
165