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