Add .gitignore files
[gsmd2.git] / vendor / telit862-gps.c
blob5650eae3a1a740fefc117d379c684006c58d74f4
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"
40 #include "telit862-gps.h"
43 static void vendor_unsolicite_handler_init (ModemInterface* modem,
44 VendorInterface *vendor);
45 static AtCommandHandlerStatus vendor_unsolicite_handler (ModemInterface* modem,
46 AtCommandContext *at,
47 GString *response);
49 static gboolean vendor_at_init_sim_ready (VendorInterface* vendor);
50 static gint vendor_serial_init (VendorInterface *vendor, const gchar *device);
51 static void gsm_ecam_parse (GScanner* scanner,
52 gint* call_id,
53 EcamState* state,
54 CallType* call_type);
56 static void vendor_sim_auth_status (SIMIPCInterface *sim_ipc, const char *status);
58 static AtCommandHandlerStatus telit_call_initiate_handler(ModemInterface *modem,
59 AtCommandContext *at,
60 GString *response);
61 static const AtCommand
62 commands[] = {
63 //Vendor command
64 { ENABLE_ECAM, "AT#ECAM=1\r\n", 100, TRUE, 1,
65 NULL }
66 }, *command_p = commands;
68 static const SymbolTable
69 symbols[] = {
70 { "ECAM", SYMBOL_ECAM, },//vendor command
71 { NULL, 0, },
72 }, *symbol_p = symbols;
74 typedef struct _Vendor {
75 ModemInterface *modem;
77 void (*orig_sim_auth_status) (SIMIPCInterface *sim_ipc, const char *status);
78 AtCommandHandlerStatus (*orig_call_initiate_handler) (ModemInterface *modem,
79 AtCommandContext *at,
80 GString *response);
81 } Vendor;
83 static Vendor *vendor_priv = NULL;
85 /** vendor_handle_init should be called from modem.c when the lib loaded*/
86 gboolean vendor_handle_init (ModemInterface* modem, VendorInterface *vendor)
88 if ( vendor_priv ) {
89 g_warning("%s : Already initialized!", __func__);
90 return FALSE;
92 vendor_priv = g_new0(Vendor, 1);
93 g_debug("%s", __func__);
94 vendor->init_at = NULL;
95 vendor->init_at_sim_ready = vendor_at_init_sim_ready;
96 vendor->init_serial = vendor_serial_init;
97 vendor->priv = (gpointer)vendor_priv;
98 vendor_unsolicite_handler_init (modem, vendor);
99 vendor_priv->modem = modem;
101 vendor_priv->orig_sim_auth_status = modem->sim_ipc->auth_status;
102 modem->sim_ipc->auth_status = &vendor_sim_auth_status;
104 AtCommand *call_initiate = gsmd_modem_get_command(modem, INITIATE_CALL);
105 vendor_priv->orig_call_initiate_handler = call_initiate->handler;
106 call_initiate->handler = &telit_call_initiate_handler;
107 return TRUE;
109 /*************************************/
110 /* if need replace default at_command, vendor at_init bellow*/
114 static gboolean vendor_at_init_sim_ready (VendorInterface* vendor)
116 ModemInterface *modem = vendor_priv->modem;
117 g_assert(modem);
118 g_debug("%s", __func__);
120 gsmd_modem_general_at_init_sim_ready (modem);
122 gsmd_modem_post_at_command_id(modem,
123 ENABLE_ECAM,
124 NULL,NULL,NULL,NULL,
125 INTERFACE_GENERAL,
126 NULL);
128 return TRUE;
130 static gint vendor_serial_init (VendorInterface *vendor, const gchar *device)
132 g_debug("%s", __func__);
133 struct termios t;
134 gint fd = g_open (device, O_RDWR, 0);
135 if ( !fd ) {
136 g_warning("%s : open failed: '%s'", __func__, device);
137 return 0;
139 if (tcgetattr(fd, &t) < 0) {
140 g_warning("%s : get attr failed '%s'", __func__, device);
141 goto error;
144 cfsetispeed(&t, B115200);
145 cfsetospeed(&t, B115200);
148 t.c_cflag = CS8 | CLOCAL | CREAD | B115200;
149 t.c_iflag = 0; // ICRNL;
150 t.c_oflag = 0;
151 t.c_lflag = 0;
152 t.c_cc[VMIN] = 1;
153 t.c_cc[VTIME] = 0;
154 t.c_cc[VSUSP] = 0;
156 if (tcsetattr (fd, TCSANOW, &t) < 0) {
157 g_warning("%s : setattr failed", __func__);
158 goto error;
160 return fd;
161 error:
162 close( fd );
163 return 0;
166 /********************************/
168 static void vendor_sim_auth_status (SIMIPCInterface *sim_ipc, const char *status)
170 g_debug("%s : Status changed to %s", __func__, status);
171 vendor_priv->orig_sim_auth_status( sim_ipc, status);
174 static void vendor_unsolicite_handler_init(ModemInterface *modem,
175 VendorInterface *vendor)
177 g_debug("%s", __func__);
178 //add the symbol to the modem scanner
179 while (symbol_p->symbol_name) {
180 g_scanner_add_symbol (modem->scanner, symbol_p->symbol_name,
181 GINT_TO_POINTER(symbol_p->symbol_token));
182 symbol_p ++;
185 //add the command to the modem command table
186 while (command_p->command) {
187 gsmd_modem_register_command(modem, command_p);
188 command_p++;
190 vendor->unsolicite_handler = vendor_unsolicite_handler;
194 static void gsm_ecam_parse (GScanner* scanner,
195 gint* call_id,
196 EcamState* state,
197 CallType* call_type)
199 //: call_id, call_state, call_type
200 g_scanner_get_next_token (scanner);
201 if (scanner->token == ':') {
202 g_scanner_get_next_token (scanner);
203 *call_id = scanner->value.v_int;
205 g_scanner_get_next_token (scanner);//get ;
206 g_scanner_get_next_token (scanner);
207 *state = scanner->value.v_int;
209 g_scanner_get_next_token (scanner);//get ;
210 g_scanner_get_next_token (scanner);
211 *call_type = scanner->value.v_int;
212 } else {
213 g_warning ("unexpexted symbol in ecam_parse\n");
217 void vendor_handle_voice_ecam(ModemInterface *modem,
218 EcamState state,
219 gint vendor_id)
221 Call *call = NULL;
222 g_debug("%s : call vendor id: %d, state: %d", __func__, vendor_id,state);
223 GHashTable *properties = gsmd_at_command_create_handler_data();
226 gsmd_utils_cache_insert_int(properties,GSMD_VENDOR_KEY_ECAM,state);
230 switch (state) {
231 //Phone call established
232 case ECAM_ACTIVE:
233 g_debug("%s: ECAM_ACTIVE",__func__);
234 call = gsmd_utils_find_call_vendor_id(modem,vendor_id);
235 g_assert( call );
238 if (modem->call_ipc->call_status) {
239 //TODO add properties
240 modem->call_ipc->call_status(modem->call_ipc,
241 call->id,
242 "active",
243 properties);
246 call->status = CONNECTED;
247 break;
249 //Got disconnected
250 case ECAM_IDLE:
251 g_debug("%s: ECAM_IDLE",__func__);
252 call = gsmd_utils_find_call_vendor_id(modem,vendor_id);
253 g_assert( call );
254 gsmd_utils_remove_call_vendor_id(modem,vendor_id,TRUE);
255 break;
256 //Someone's calling us
257 case ECAM_ALERTING:
258 g_debug("%s: ECAM_ALERTING",__func__);
259 //CLIP didn't have information on call id
260 //So we'll find first call with id -1
261 //and set it call_id
262 gsmd_utils_set_unknown_vendor_id(modem, vendor_id);
263 call = gsmd_utils_find_call_vendor_id(modem,vendor_id);
264 if (modem->call_ipc->call_status) {
265 modem->call_ipc->call_status(modem->call_ipc,
266 call->id,
267 "incoming",
268 properties);
270 g_assert( call );
271 break;
273 //Remote end is busy
274 case ECAM_BUSY:
275 g_debug("%s: ECAM_BUSY",__func__);
276 call = gsmd_utils_find_call_vendor_id(modem,vendor_id);
277 g_assert( call );
279 //Remove the call
280 if ( call->status == IDLE ) {
281 gsmd_utils_remove_call_vendor_id(modem,vendor_id,TRUE);
284 break;
285 //We are calling someone
286 case ECAM_CALLING:
287 g_debug("%s: ECAM_CALLING",__func__);
288 gsmd_utils_set_unknown_vendor_id(modem,vendor_id);
289 call = gsmd_utils_find_call_vendor_id(modem,vendor_id);
290 if (modem->call_ipc->call_status) {
291 gsmd_utils_cache_insert_string(properties,
292 GSMD_MODEM_KEY_PHONE_NUMBER,
293 call->number->str);
295 modem->call_ipc->call_status(modem->call_ipc,
296 call->id,
297 "outgoing",
298 properties);
300 g_assert( call );
301 break;
302 //We are waiting on hold
303 case ECAM_WAITING:
304 g_debug("%s: ECAM_WAITING",__func__);
305 call = gsmd_utils_find_call_vendor_id(modem,vendor_id);
306 g_assert( call );
307 if (modem->call_ipc->call_status) {
308 //TODO add waiting to properties
310 call->status = WAITING;
311 break;
312 case ECAM_CONNECTING:
313 g_debug("%s: ECAM_CONNECTING",__func__);
314 call = gsmd_utils_find_call_vendor_id(modem,vendor_id);
315 g_assert( call );
316 call->status = CALLING;
317 if (modem->call_ipc->call_status) {
318 //TODO add connecting to properties
319 modem->call_ipc->call_status(modem->call_ipc,
320 call->id,
321 "outgoing",
322 properties);
325 break;
327 case ECAM_HOLD:
328 g_debug("%s: ECAM_HOLD",__func__);
329 call = gsmd_utils_find_call_vendor_id(modem,vendor_id);
330 g_assert( call );
331 if (modem->call_ipc->call_status) {
332 //TODO add properties
333 modem->call_ipc->call_status(modem->call_ipc,
334 call->id,
335 "held",
336 properties);
339 break;
342 g_hash_table_destroy(properties);
345 static
346 AtCommandHandlerStatus telit_call_initiate_handler(ModemInterface *modem,
347 AtCommandContext *at,
348 GString *response)
350 gint vendor_id = -1;
351 GScanner* scanner = modem->scanner;
352 EcamState state = ECAM_IDLE;
353 CallType call_type = CALLTYPE_VOICE;
354 g_debug("%s", __func__);
355 switch (scanner->token) {
356 case '#':
357 g_scanner_get_next_token(scanner);
359 switch (scanner->token) {
360 case SYMBOL_ECAM://line status
361 gsm_ecam_parse(scanner,&vendor_id,&state,&call_type);
362 g_debug("%s : call vendor id: %d", __func__, vendor_id);
364 if (call_type == CALLTYPE_VOICE) {
365 vendor_handle_voice_ecam(modem,state,vendor_id);
367 return AT_HANDLER_NEED_MORE;
368 default:
369 g_scanner_input_text (scanner, response->str, response->len);
370 g_scanner_get_next_token (scanner);
371 g_scanner_peek_next_token (scanner);
372 break;
374 break;
375 default:
376 break;
378 return vendor_priv->orig_call_initiate_handler(modem,at,response);
380 AtCommandHandlerStatus vendor_unsolicite_handler (ModemInterface *modem,
381 AtCommandContext *at,
382 GString *response)
384 // only reponse for parse the vendor token such as #ECAM
385 gint vendor_id = -1;
386 GScanner* scanner = modem->scanner;
387 EcamState state = ECAM_IDLE;
388 CallType call_type = CALLTYPE_VOICE;
389 g_debug("%s",__func__);
391 switch (scanner->token) {
393 //Override busy and no carrier and don't do anything
394 //instead wait for the same information to come from ecam along with
395 //call id
396 /* case SYMBOL_BUSY: */
397 /* return AT_HANDLER_DONE; */
398 /* case SYMBOL_NO: */
399 /* g_scanner_get_next_token(scanner); */
400 /* if (scanner->token == SYMBOL_CARRIER) */
401 /* return AT_HANDLER_DONE; */
403 case '#':
404 g_scanner_get_next_token(scanner);
406 switch (scanner->token) {
407 case SYMBOL_ECAM://line status
408 //#ECAM: 0,3,,,: call start
409 gsm_ecam_parse(scanner,&vendor_id,&state,&call_type);
410 g_debug("%s : call vendor id: %d", __func__, vendor_id);
411 if (call_type == CALLTYPE_VOICE) {
412 vendor_handle_voice_ecam(modem,state,vendor_id);
413 } else {
414 g_message ("data call\n");
416 return AT_HANDLER_DONE;
417 default:
418 break;
420 default:
421 break;
423 return AT_HANDLER_DONT_UNDERSTAND;