Updated SIM interface
[gsmd2.git] / vendor / telit862-gps.c
blobf260b317b12deaea1058bbd3280e180cb36d95bc
1 /*
2 * vendor_telit.c
4 * Copyright(C) 2007,2008 Ixonos Plc
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2, or (at your option)
9 * any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Boston, MA 02111.
22 * Written by
23 * Jukka Honkela
24 * Yi Zheng
25 * Matti Katila
26 * Vesa Pikki
27 * Heikki Paajanen
30 #include <termios.h>
31 #include <fcntl.h>
32 #include <unistd.h>
34 #include <glib.h>
35 #include <glib/gstdio.h>
37 #include "../src/modem.h"
38 #include "../src/utils.h"
39 #include "../src/call_interface.h"
41 #define GSMD_VENDOR_KEY_ECAM "ecam"
43 /**
44 * @brief Call Type
46 typedef enum {
47 CALLTYPE_VOICE = 1, /**< Voice Call*/
48 CALLTYPE_DATA /**< Data Call*/
49 } CallType;
52 typedef enum {
53 ECAM_CALL_IDLE=0,
54 ECAM_CALL_CALLING,
55 ECAM_CONNECTING,
56 ECAM_ACTIVE,
57 ECAM_CALL_HOLD,
58 ECAM_CALL_WAITING,
59 ECAM_ALERTING,
60 ECAM_BUSY
61 } EcamState;
63 enum {
64 ENABLE_ECAM = VENDOR_COMMAND
66 enum {
67 SYMBOL_ECAM = VENDOR_SYMBOL
71 static void vendor_unsolicite_handler_init (ModemInterface* modem,
72 VendorInterface *vendor);
73 static AtCommandHandlerStatus vendor_unsolicite_handler (ModemInterface* modem,
74 AtCommandContext *at,
75 GString *response);
77 static gboolean vendor_at_init_sim_ready (VendorInterface* vendor);
78 static void gsm_ecam_parse (GScanner* scanner,
79 gint* call_id,
80 EcamState* state,
81 CallType* call_type);
83 static void vendor_sim_auth_status (SIMIPCInterface *sim_ipc, const char *status);
85 static AtCommandHandlerStatus telit_call_initiate_handler(ModemInterface *modem,
86 AtCommandContext *at,
87 GString *response);
88 static const AtCommand
89 commands[] = {
90 //Vendor command
91 { ENABLE_ECAM, "AT#ECAM=1\r\n", 100, TRUE, 1,
92 NULL,NULL,SIM_UNKNOWN,NULL }
93 }, *command_p = commands;
95 static const SymbolTable
96 symbols[] = {
97 { "ECAM", SYMBOL_ECAM, },//vendor command
98 { NULL, 0, },
99 }, *symbol_p = symbols;
101 typedef struct _Vendor {
102 ModemInterface *modem;
104 void (*orig_sim_auth_status) (SIMIPCInterface *sim_ipc, const char *status);
105 AtCommandHandlerStatus (*orig_call_initiate_handler) (ModemInterface *modem,
106 AtCommandContext *at,
107 GString *response);
108 } Vendor;
110 static Vendor *vendor_priv = NULL;
112 /** vendor_handle_init should be called from modem.c when the lib loaded*/
113 gboolean vendor_handle_init (VendorInterface *vendor, ModemInterface* modem)
115 if ( vendor_priv ) {
116 g_warning("%s : Already initialized!", __func__);
117 return FALSE;
119 vendor_priv = g_new0(Vendor, 1);
120 g_debug("%s", __func__);
121 vendor->init_at = NULL;
122 vendor->init_at_sim_ready = vendor_at_init_sim_ready;
123 vendor->priv = (gpointer)vendor_priv;
124 vendor_unsolicite_handler_init (modem, vendor);
125 vendor_priv->modem = modem;
127 vendor_priv->orig_sim_auth_status = modem->sim_ipc->auth_status;
128 modem->sim_ipc->auth_status = &vendor_sim_auth_status;
130 AtCommand *call_initiate = gsmd_modem_get_command(modem, INITIATE_CALL);
131 vendor_priv->orig_call_initiate_handler = call_initiate->handler;
132 call_initiate->handler = &telit_call_initiate_handler;
133 return TRUE;
135 /*************************************/
136 /* if need replace default at_command, vendor at_init bellow*/
140 static gboolean vendor_at_init_sim_ready (VendorInterface* vendor)
142 ModemInterface *modem = vendor_priv->modem;
143 g_assert(modem);
144 g_debug("%s", __func__);
146 gsmd_modem_general_at_init_sim_ready (modem);
148 gsmd_modem_post_at_command_id(modem,
149 ENABLE_ECAM,
150 NULL,NULL,NULL,NULL,
151 INTERFACE_GENERAL,
152 NULL);
154 return TRUE;
157 /********************************/
159 static void vendor_sim_auth_status (SIMIPCInterface *sim_ipc, const char *status)
161 g_debug("%s : Status changed to %s", __func__, status);
162 vendor_priv->orig_sim_auth_status( sim_ipc, status);
165 static void vendor_unsolicite_handler_init(ModemInterface *modem,
166 VendorInterface *vendor)
168 g_debug("%s", __func__);
169 //add the symbol to the modem scanner
170 while (symbol_p->symbol_name) {
171 g_scanner_add_symbol (modem->scanner, symbol_p->symbol_name,
172 GINT_TO_POINTER(symbol_p->symbol_token));
173 symbol_p ++;
176 //add the command to the modem command table
177 while (command_p->command) {
178 gsmd_modem_register_command(modem, command_p);
179 command_p++;
181 vendor->unsolicite_handler = vendor_unsolicite_handler;
185 static void gsm_ecam_parse (GScanner* scanner,
186 gint* call_id,
187 EcamState* state,
188 CallType* call_type)
190 //: call_id, call_state, call_type
191 g_scanner_get_next_token (scanner);
192 if (scanner->token == ':') {
193 g_scanner_get_next_token (scanner);
194 *call_id = scanner->value.v_int;
196 g_scanner_get_next_token (scanner);//get ;
197 g_scanner_get_next_token (scanner);
198 *state = scanner->value.v_int;
200 g_scanner_get_next_token (scanner);//get ;
201 g_scanner_get_next_token (scanner);
202 *call_type = scanner->value.v_int;
203 } else {
204 g_warning ("unexpexted symbol in ecam_parse\n");
208 void vendor_handle_voice_ecam(ModemInterface *modem,
209 EcamState state,
210 gint vendor_id)
212 Call *call = NULL;
213 g_debug("%s : call vendor id: %d, state: %d", __func__, vendor_id,state);
215 switch (state) {
216 //Phone call established
217 case ECAM_ACTIVE:
218 g_debug("%s: ECAM_ACTIVE",__func__);
219 call = gsmd_utils_find_call_vendor_id(modem,vendor_id);
220 if (call) {
221 gsmd_utils_call_send_status(modem,
222 call,
223 "active");
225 call->status = CALL_CONNECTED;
227 break;
229 //Got disconnected
230 case ECAM_CALL_IDLE:
231 g_debug("%s: ECAM_CALL_IDLE",__func__);
232 gsmd_utils_remove_call_vendor_id(modem,vendor_id,TRUE);
233 break;
234 //Someone's calling us
235 case ECAM_ALERTING:
236 g_debug("%s: ECAM_ALERTING",__func__);
237 //CLIP didn't have information on call id
238 //So we'll find first call with id -1
239 //and set it call_id
240 gsmd_utils_set_unknown_vendor_id(modem, vendor_id);
243 call = gsmd_utils_find_call_vendor_id(modem,vendor_id);
244 if (call) {
245 gsmd_utils_table_insert_int(call->vendor_properties,GSMD_VENDOR_KEY_ECAM,state);
246 gsmd_utils_call_send_status(modem,
247 call,
248 "incoming");
251 break;
253 //Remote end is busy
254 case ECAM_BUSY:
255 g_debug("%s: ECAM_BUSY",__func__);
256 call = gsmd_utils_find_call_vendor_id(modem,vendor_id);
257 if (call) {
259 //Remove the call
260 if ( call->status == CALL_IDLE ) {
261 gsmd_utils_remove_call_vendor_id(modem,vendor_id,TRUE);
265 break;
266 //We are calling someone
267 case ECAM_CALL_CALLING:
268 g_debug("%s: ECAM_CALL_CALLING",__func__);
269 gsmd_utils_set_unknown_vendor_id(modem,vendor_id);
270 call = gsmd_utils_find_call_vendor_id(modem,vendor_id);
271 if (call) {
272 gsmd_utils_table_insert_int(call->vendor_properties,GSMD_VENDOR_KEY_ECAM,state);
273 gsmd_utils_call_send_status(modem,
274 call,
275 "outgoing");
278 break;
279 //We are waiting on hold
280 case ECAM_CALL_WAITING:
281 g_debug("%s: ECAM_CALL_WAITING",__func__);
282 call = gsmd_utils_find_call_vendor_id(modem,vendor_id);
283 if (call) {
284 gsmd_utils_call_send_status(modem,
285 call,
286 "outgoing");
287 call->status = CALL_WAITING;
289 break;
290 case ECAM_CONNECTING:
291 g_debug("%s: ECAM_CONNECTING",__func__);
292 call = gsmd_utils_find_call_vendor_id(modem,vendor_id);
293 g_assert( call );
294 call->status = CALL_CALLING;
295 gsmd_utils_call_send_status(modem,
296 call,
297 "outgoing");
299 break;
301 case ECAM_CALL_HOLD:
302 g_debug("%s: ECAM_CALL_HOLD",__func__);
303 call = gsmd_utils_find_call_vendor_id(modem,vendor_id);
304 if (call) {
305 gsmd_utils_call_send_status(modem,
306 call,
307 "held");
310 break;
314 static
315 AtCommandHandlerStatus telit_call_initiate_handler(ModemInterface *modem,
316 AtCommandContext *at,
317 GString *response)
319 gint vendor_id = -1;
320 GScanner* scanner = modem->scanner;
321 EcamState state = ECAM_CALL_IDLE;
322 CallType call_type = CALLTYPE_VOICE;
323 g_debug("%s", __func__);
324 switch (scanner->token) {
325 case '#':
326 g_scanner_get_next_token(scanner);
328 switch (scanner->token) {
329 case SYMBOL_ECAM://line status
330 gsm_ecam_parse(scanner,&vendor_id,&state,&call_type);
331 g_debug("%s : call vendor id: %d", __func__, vendor_id);
333 if (call_type == CALLTYPE_VOICE) {
334 vendor_handle_voice_ecam(modem,state,vendor_id);
336 return AT_HANDLER_NEED_MORE;
337 default:
338 g_scanner_input_text (scanner, response->str, response->len);
339 g_scanner_get_next_token (scanner);
340 g_scanner_peek_next_token (scanner);
341 break;
343 break;
344 default:
345 break;
347 return vendor_priv->orig_call_initiate_handler(modem,at,response);
351 AtCommandHandlerStatus vendor_unsolicite_handler (ModemInterface *modem,
352 AtCommandContext *at,
353 GString *response)
355 // only reponse for parse the vendor token such as #ECAM
356 gint vendor_id = -1;
357 GScanner* scanner = modem->scanner;
358 EcamState state = ECAM_CALL_IDLE;
359 CallType call_type = CALLTYPE_VOICE;
360 g_debug("%s",__func__);
362 switch (scanner->token) {
364 //Override busy and no carrier and don't do anything
365 //instead wait for the same information to come from ecam along with
366 //call id
367 /* case SYMBOL_BUSY: */
368 /* return AT_HANDLER_DONE; */
369 /* case SYMBOL_NO: */
370 /* g_scanner_get_next_token(scanner); */
371 /* if (scanner->token == SYMBOL_CARRIER) */
372 /* return AT_HANDLER_DONE; */
374 case '#':
375 g_scanner_get_next_token(scanner);
377 switch (scanner->token) {
378 case SYMBOL_ECAM://line status
379 //#ECAM: 0,3,,,: call start
380 gsm_ecam_parse(scanner,&vendor_id,&state,&call_type);
381 g_debug("%s : call vendor id: %d", __func__, vendor_id);
382 if (call_type == CALLTYPE_VOICE) {
383 vendor_handle_voice_ecam(modem,state,vendor_id);
384 } else {
385 g_message ("data call\n");
387 return AT_HANDLER_DONE;
388 default:
389 break;
391 default:
392 break;
394 return AT_HANDLER_DONT_UNDERSTAND;