Refactored handling of multiple interfaces
[gsmd2.git] / src / modem.c
blobdeff624085b2a9e1a1d4a28f5e2a3522d6408f7d
1 /*
2 * modem.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 <glib.h>
31 #include <stdio.h>
32 #include <termios.h>
33 #include <fcntl.h>
34 #include <string.h>
35 #include <dlfcn.h>
36 #include "serial.h"
37 #include "modem_internal.h"
38 #include "call.h"
39 #include "call_interface.h"
40 #include "sms.h"
41 #include "sms_impl.h"
42 #include "device.h"
43 #include "pdp.h"
44 #include "network.h"
45 #include "phonebook.h"
46 #include "sim.h"
47 #include "sms_interface.h"
48 #include "pdp_interface.h"
49 #include "network_interface.h"
50 #include "device_interface.h"
51 #include "phonebook_interface.h"
52 #include "sim_interface.h"
53 #include "gsmd-error.h"
54 #include "utils.h"
55 #include <unistd.h>
58 #define TIME_OUT "TIME_OUT\n"
60 /** Default time out value for AT command */
61 #define DEFAULT_TIME_OUT 100
63 /** Time out value for AT command */
64 #define TIME_OUT_PADDING 5000
67 /* static Modem *modem_priv; */
69 /**
70 * @brief Private data used when reading and writing data to/from serial.
72 struct _SerialData {
74 /**
75 * Pointer to modem interface used
77 Modem *modem;
79 /**
80 * Index of the serial device to use
82 guint device_index;
87 typedef struct _SerialData SerialData;
89 typedef struct _SerialDevice {
90 /**
91 * AT command queue
93 GQueue *commandQueue;
94 /**
95 * IOChannel of serial device
97 Serial *serial;
98 /**
99 * Data used by IOChannel
101 SerialData *serial_data;
103 } SerialDevice;
106 * @brief Modem Struct
108 struct _Modem {
110 * time out flag
112 gboolean is_timeout;
115 * vendor lib handle
117 void* vendor_handle;
120 * Serial devices
122 GArray *serial_devices;
125 * AT command table
127 GHashTable *commands_table;
130 * modem interface
132 ModemInterface *modem_if;
135 * Vendor interface
137 VendorInterface *vendor;
142 /*********************service function**************************/
143 static void gsmd_modem_init ( ModemInterface* modem);
144 static AtCommandHandlerStatus gsmd_modem_handler_unsolicite (ModemInterface *modem,
145 AtCommandContext *at,
146 GString *response);
148 static void gsmd_modem_process_next_command (Modem* modem, InterfaceType interface);
149 static gboolean gsmd_modem_timeout_handle (gpointer data);
151 static void gsmd_modem_send_command_raw ( ModemInterface *modem,
152 const gchar *command,
153 InterfaceType interface );
154 static
155 AtCommandHandlerStatus gsmd_modem_handler_alive(ModemInterface *modem,
156 AtCommandContext *at,
157 GString *response);
159 static
160 SerialData *gsmd_modem_get_serial_data(Modem *modem, InterfaceType interface);
162 static
163 AtCommandHandlerStatus gsmd_modem_handler_current_calls(ModemInterface *modem,
164 AtCommandContext *at,
165 GString *response);
167 static void gsmd_modem_current_calls_free(AtCommandContext *at);
168 /********************End service function***********************/
171 static const AtCommand
172 commands[]
174 //Disable command echos
175 { DISABLE_ECHO, "ATE0\r\n", 100,
176 TRUE, 0,
177 gsmd_utils_handler_ok, NULL, SIM_UNKNOWN, NULL},
179 //Enable everything
180 { POWER_ON, "AT+CFUN=1\r\n", 15000,
181 TRUE, 0,
182 gsmd_utils_handler_ok, NULL, SIM_UNKNOWN, NULL},
184 //Enable Report Mobile Equipment Error
185 { ENABLE_CMEE, "AT+CMEE=1\r\n", 100,
186 TRUE, 0,
187 gsmd_utils_handler_ok, NULL, SIM_UNKNOWN, NULL},
189 //Set response of AT+COPS? to respond with operator name
190 { SET_OP_QUERY_REPLY, "AT+COPS=3,0\r\n", 100,
191 TRUE, 0,
192 gsmd_utils_handler_ok, NULL, SIM_READY, NULL},
194 //Enable Report Mobile Equipment Error
195 { ENABLE_CMEE, "AT+CMEE=1\r\n", 100,
196 TRUE, 3,
197 gsmd_utils_handler_ok, NULL, SIM_UNKNOWN, NULL},
199 //Enable call waiting
200 { ENABLE_CCWA, "AT+CCWA=1,1\r\n", 100,
201 TRUE, 0,
202 gsmd_utils_handler_ok, NULL, SIM_READY, NULL},
204 //Enable call waiting
205 { CUR_CALLS_QUERY, "AT+CLCC\r\n", 100,
206 TRUE, 0,
207 gsmd_modem_handler_current_calls, NULL, SIM_READY,
208 gsmd_modem_current_calls_free},
210 //Query if we are muted
211 { MUTE_QUERY, "AT+CMUTE=?\r\n", 5000,
212 TRUE, 0,
213 gsmd_utils_handler_ok, NULL, SIM_READY, NULL},
215 //Enable caller identification
216 { ENABLE_CLIP, "AT+CLIP=1\r\n", 180000,
217 TRUE, 3,
218 gsmd_utils_handler_ok, NULL, SIM_READY, NULL},
220 //Enable new message identification
221 { ENABLE_CNMI, "AT+CNMI=2,1,0,0,0\r\n", 5000,
222 TRUE, 3,
223 gsmd_utils_handler_ok, NULL, SIM_READY, NULL},
225 //Query ring volume
226 { RING_VOLUME_QUERY, "AT+CRSL?\r\n", 5000,
227 TRUE, 0,
228 gsmd_utils_handler_ok, NULL, SIM_READY, NULL},
230 //Escape command
231 { ESCAPE_COMMAND, "+++\r\n", 100,
232 FALSE, 0,
233 gsmd_utils_handler_ok, NULL, SIM_UNKNOWN, NULL},
235 //Just send at command
236 { AT, "AT\r\n", 5000,
237 FALSE, 0,
238 gsmd_utils_handler_ok, NULL, SIM_UNKNOWN, NULL},
240 //Test modem is alive
241 { REPLY_COMMAND, "AT\r\n", 5000,
242 FALSE, 0,
243 gsmd_modem_handler_alive, NULL, SIM_UNKNOWN, NULL},
245 //Set PDU mode
246 { SET_PDU_MODE, "AT+CMGF=0\r\n", 100,
247 FALSE, 0,
248 gsmd_utils_handler_ok, NULL, SIM_READY, NULL},
250 //Test modem is alive
251 { SOFT_RESET, "ATZ\r\n", 5000,
252 FALSE, 3,
253 gsmd_modem_handler_alive, NULL, SIM_UNKNOWN, NULL},
255 { 0, NULL, 100, TRUE, 1,
256 NULL, NULL, SIM_UNKNOWN, NULL },
258 }, *command_p = commands;
261 static const SymbolTable
262 symbols[] = {
263 { "TIME_OUT", SYMBOL_TIME_OUT,},
264 { "OK", SYMBOL_OK, },
265 { "ERROR", SYMBOL_ERROR, },
266 { "RING", SYMBOL_RING, },
267 { "NO", SYMBOL_NO, },
268 { "ANSWER", SYMBOL_ANSWER, },
269 { "CARRIER", SYMBOL_CARRIER, },
270 { "BUSY", SYMBOL_BUSY, },
271 { "READY", SYMBOL_READY, },
272 { "CME", SYMBOL_CME, },
273 { "CMS", SYMBOL_CMS, },
274 { "CPIN", SYMBOL_CPIN, },
275 { "CPAS", SYMBOL_CPAS, },
276 { "CSQ", SYMBOL_CSQ, },
277 { "CMUT", SYMBOL_CMUT, },
278 { "CLIP", SYMBOL_CLIP, },
279 { "CCWA", SYMBOL_CCWA, },
280 { "CRING", SYMBOL_CRING, },
281 { "CMTI", SYMBOL_CMTI, },
282 { "CRSL", SYMBOL_CRSL, },
283 { "CMGW", SYMBOL_CMGW, },
284 { "PIN", SYMBOL_PIN, },
285 { "PUK", SYMBOL_PUK, },
286 { NULL, 0, },
287 }, *symbol_p = symbols;
291 void gsmd_modem_set_up_interface(Modem *modem)
293 modem->modem_if = g_new0(ModemInterface, 1);
294 modem->modem_if->priv = (gpointer)modem;
297 static void gsmd_modem_cache_destroy(gpointer data)
299 GValue *value = data;
300 g_value_unset(value);
301 g_free(value);
304 /*Allocate Modem structure*/
305 /* return NULL, if failed*/
306 Modem* gsmd_modem_allocate()
308 ModemInterface *modem = NULL;
309 Modem *modem_priv = g_try_new0 (Modem, 1);
311 if (!modem_priv) {
312 g_warning("%s : Failed to allocate a modem structure.", __func__);
313 return NULL;
316 gsmd_modem_set_up_interface(modem_priv);
318 modem = modem_priv->modem_if;
320 modem_priv->vendor_handle = NULL;
321 modem_priv->is_timeout = FALSE;
323 modem->status = MODEM_UNINITIALIZED;
324 modem->devices = NULL;
328 modem->calls = NULL;
330 modem->scanner = g_scanner_new (NULL);
331 if (!modem->scanner) {
332 g_warning("%s : Failed to set a scanner for the modem.", __func__);
333 goto error;
336 modem->scanner->config->symbol_2_token = TRUE;
337 modem->scanner->config->numbers_2_int = TRUE;
338 modem->scanner->config->skip_comment_single = FALSE;
339 modem->scanner->config->cpair_comment_single = "";
340 /* the character to skip*/
342 //Add commands list into hash table
343 modem_priv->commands_table = g_hash_table_new(NULL,NULL);
344 if (!modem_priv->commands_table) {
345 g_warning("%s : Failed to set command table for the modem.", __func__);
346 goto error;
348 modem->cache = g_hash_table_new_full(NULL,
349 g_str_equal,
350 NULL,
351 gsmd_modem_cache_destroy);
352 gsmd_utils_table_insert_int(modem->cache,
353 GSMD_MODEM_KEY_NETWORK_STATUS,
354 NETWORK_UNKNOWN);
356 modem->call = g_try_new0 (CallInterface, 1);
357 if (!modem->call)
358 goto error;
359 modem->call_ipc = g_try_new0 (CallIPCInterface, 1);
360 if (!modem->call_ipc)
361 goto error;
362 modem->sms = g_try_new0 (SMSInterface, 1);
363 if (!modem->sms)
364 goto error;
365 modem->sms_ipc = g_try_new0 (SMSIPCInterface, 1);
366 if (!modem->sms_ipc)
367 goto error;
368 modem->device= g_try_new0 (DeviceInterface, 1);
369 if (!modem->device)
370 goto error;
371 modem->device_ipc= g_try_new0 (DeviceIPCInterface, 1);
372 if (!modem->device_ipc)
373 goto error;
375 modem->network = g_try_new0 (NetworkInterface, 1);
376 if (!modem->network)
377 goto error;
378 modem->network_ipc = g_try_new0 (NetworkIPCInterface, 1);
379 if (!modem->network_ipc)
380 goto error;
381 modem->pdp = g_try_new0 (PDPInterface, 1);
382 if (!modem->pdp)
383 goto error;
384 modem->pdp_ipc = g_try_new0 (PDPIPCInterface, 1);
385 if (!modem->pdp_ipc)
386 goto error;
387 modem->phonebook = g_try_new0 (PhonebookInterface, 1);
388 if (!modem->phonebook)
389 goto error;
390 modem->phonebook_ipc = g_try_new0 (PhonebookIPCInterface, 1);
391 if (!modem->phonebook_ipc)
392 goto error;
393 modem->sim = g_try_new0 (SIMInterface, 1);
394 if (!modem->sim)
395 goto error;
396 modem->sim_ipc = g_try_new0 (SIMIPCInterface, 1);
397 if (!modem->sim_ipc)
398 goto error;
401 return modem_priv;
403 error:
404 g_warning("%s: error", __func__);
405 if ( modem ) {
406 g_free (modem->device);
407 g_free (modem->device_ipc);
408 g_free (modem->sms);
409 g_free (modem->sms_ipc);
410 g_free (modem->call);
411 g_free (modem->call_ipc);
412 g_free (modem->network);
413 g_free (modem->network_ipc);
414 g_free (modem->pdp);
415 g_free (modem->pdp_ipc);
416 g_free (modem->phonebook);
417 g_free (modem->phonebook_ipc);
418 g_free (modem->sim);
419 g_hash_table_destroy (modem->cache);
420 g_free (modem);
422 if ( modem_priv ) {
423 if (modem_priv->commands_table)
424 g_hash_table_destroy (modem_priv->commands_table);
425 if (modem_priv->modem_if->scanner)
426 g_scanner_destroy (modem->scanner);
427 g_free (modem_priv);
429 return NULL;
434 * Finds the correct vendor handler
435 * @param modem modem to attach the handler
436 * @param vendor the vendor's name. E.g. "telit"
437 * @return TRUE if load was successful, otherwise FALSE
439 gboolean gsmd_modem_load_vendor_handler (Modem* modem, const gchar* vendor)
441 VendorInit vendor_init;
442 char* error = NULL;
443 GString* vendor_name = NULL;
444 const gchar *plugindir = g_getenv("GSMD2PLUGINDIR");
445 //perform vendor init
446 //vendor_telit_unsolicite_handler_init (modem);
447 if (!vendor)
448 return FALSE;
450 g_debug("%s : Vendor: %s", __func__, vendor);
451 vendor_name = g_string_new ("");
453 if ( !plugindir ) {
454 plugindir = GSMD2PLUGINDIR;
456 g_string_printf (vendor_name, "%s/libvendor%s.so", plugindir, vendor);
457 modem->vendor_handle = dlopen (vendor_name->str ,RTLD_LAZY);
458 g_string_free (vendor_name, TRUE);
459 if (!modem->vendor_handle) {
460 g_debug ("Vendor %s not found from %s",vendor, plugindir);
461 error = dlerror();
462 fprintf (stderr,"%s\n", error);
463 return FALSE;
466 dlerror();
467 vendor_init = dlsym (modem->vendor_handle,"vendor_handle_init");
468 if ((error = dlerror()) != NULL) {
469 fprintf (stderr, "%s\n", error);
470 dlclose (modem->vendor_handle);
471 return FALSE;
474 return vendor_init (modem->modem_if, modem->vendor);
477 void gsmd_modem_init_standard_at_handler(ModemInterface* modem)
479 g_debug("%s", __func__);
481 while (symbol_p->symbol_name) {
482 g_scanner_add_symbol (modem->scanner, symbol_p->symbol_name,
483 GINT_TO_POINTER(symbol_p->symbol_token));
484 symbol_p++;
487 while (command_p->command) {
488 gsmd_modem_register_command (modem,command_p);
489 command_p++;
493 void gsmd_modem_clear_queue_func(gpointer data,
494 gpointer user_data)
496 AtCommandContext *at = (AtCommandContext*)data;
497 gsmd_utils_send_error(at, GSMD_ERROR_RESET, "Reseting modem");
498 if (at->timeout_event_id != 0) {
499 g_debug("%s : Removing timeout id: %d",
500 __func__,
501 at->timeout_event_id);
503 g_source_remove(at->timeout_event_id);
505 gsmd_at_command_context_free(at);
510 * @brief Closes all serial ports
512 * @param modem pointer to modem whose serial ports to close
514 void gsmd_modem_close_serial_ports(Modem *modem)
516 g_debug("%s",__func__);
517 gint i=0;
519 if (modem->serial_devices) {
520 for (i=0;i<modem->serial_devices->len;i++) {
521 SerialDevice *serial = g_array_index(modem->serial_devices,SerialDevice*,i);
522 gsmd_serial_free(serial->serial);
523 g_free(serial->serial_data);
524 g_queue_foreach(serial->commandQueue,gsmd_modem_clear_queue_func,NULL);
525 g_queue_free(serial->commandQueue);
527 g_array_free(modem->serial_devices,TRUE);
528 modem->serial_devices = NULL;
531 modem->modem_if->status = MODEM_UNINITIALIZED;
535 gboolean gsmd_modem_init_serial_ports(Modem *modem)
537 g_debug("%s",__func__);
539 //Make sure we aren't initializing the modem twice
540 if (modem->modem_if->status != MODEM_UNINITIALIZED)
541 return FALSE;
543 modem->modem_if->status = MODEM_SERIAL_INIT;
545 gint i=0;
546 g_assert(modem);
547 g_assert(modem->modem_if);
548 g_assert(modem->modem_if->devices);
550 modem->serial_devices = g_array_new(TRUE,TRUE,sizeof(SerialDevice*));
553 GList *device_it = modem->modem_if->devices;
554 while (device_it) {
555 gchar *device = device_it->data;
556 g_debug("Adding device %s",device);
557 gint device_fd = modem->vendor->init_serial( modem->vendor, device);
559 if ( !device_fd ) {
560 g_warning ("%s : init_serial failed\n",
561 __func__);
562 return FALSE;
565 Serial *serial = gsmd_serial_open_port (device_fd);
566 if (!serial) {
567 g_warning("%s : Failed to open device %s",
568 __func__,
569 device);
570 //open failed, release the resource
571 gsmd_modem_close (modem->modem_if);
572 return FALSE;
574 SerialData *serial_data = g_new0(SerialData,1);
575 serial_data->modem = modem;
576 serial_data->device_index = i;
578 gsmd_serial_register_trigger( serial, "\r\n",
579 &gsmd_modem_data_in,
580 (gpointer)serial_data,
581 FALSE);
582 gsmd_serial_register_trigger( serial, "\r",
583 &gsmd_modem_data_in,
584 (gpointer)serial_data,
585 FALSE);
586 gsmd_serial_register_trigger( serial, "\n",
587 &gsmd_modem_data_in,
588 (gpointer)serial_data,
589 FALSE);
591 SerialDevice *serial_device = g_new0(SerialDevice, 1);
592 serial_device->serial = serial;
593 serial_device->serial_data = serial_data;
594 serial_device->commandQueue = g_queue_new();
595 g_array_append_val(modem->serial_devices,serial_device);
596 device_it = g_list_next(device_it);
597 i++;
600 if ( modem->vendor->wakeup_modem ) {
601 if (modem->vendor->wakeup_modem(modem->vendor)) {
602 gsmd_modem_post_alive_test(modem->modem_if,TRUE);
604 } else {
605 gsmd_modem_post_alive_test(modem->modem_if,TRUE);
608 return TRUE;
612 * @brief Opens a modem device.
614 * Before using modem, this function must be called to open modem and
615 * get modem device struct pointer
617 * @param devices list of device file names
618 * @param vendor The libname name of the vendor
619 * for example "telit"
620 * @param no_cache should caching not be used
621 * @param ipc_init pointer to ipc initialization function
622 * @param interface_devices a list that maps interfaces to devices
623 * @return pointer to modem interface struct
625 ModemInterface* gsmd_modem_open (gchar **devices,
626 const gchar* vendor,
627 gboolean no_cache,
628 GKeyFile *conf,
629 IPCInit ipc_init,
630 int *interface_devices)
632 // g_type_init ();
633 Modem* modem = gsmd_modem_allocate();
634 modem->modem_if->no_cache = no_cache;
635 modem->modem_if->conf_file = conf;
636 gchar *device = NULL;
639 gint i = 0;
642 if (!modem)
643 return NULL;
645 gsmd_modem_init (modem->modem_if);
647 modem->modem_if->ipc_data = ipc_init(modem->modem_if);
649 if (!modem->modem_if->ipc_data) {
650 g_warning("Cannot initialize ipc!\n");
651 return NULL;
655 if (!gsmd_modem_load_vendor_handler (modem, vendor)) {
656 g_warning ("Can't find the vendor or vendor init failed: %s\n", vendor);
657 return NULL;
662 gsmd_modem_init_standard_at_handler(modem->modem_if);
664 i=0;
665 device = devices[i];
666 while (device) {
667 g_debug("%s : '%s'", __func__, device);
668 modem->modem_if->devices = g_list_append(modem->modem_if->devices,device);
669 i++;
670 device = devices[i];
673 if (!gsmd_modem_init_serial_ports(modem))
674 return NULL;
677 if( !gsmd_modem_assign_device_indices(modem->modem_if,interface_devices) ) {
678 gsmd_modem_close(modem->modem_if);
679 return NULL;
682 return modem->modem_if;
685 void gsmd_modem_change_sim_status(ModemInterface *modem, SIMStatus status)
687 g_assert( modem );
688 Modem *modem_priv = (Modem*)modem->priv;
689 if ( modem->sim_status < SIM_READY
690 && status >= SIM_READY) {
691 if ( modem_priv->vendor->init_at_sim_ready ) {
692 modem_priv->vendor->init_at_sim_ready (modem_priv->vendor);
693 } else {
694 gsmd_modem_general_at_init_sim_ready(modem);
697 modem->sim_status = status;
700 void gsmd_modem_serial_devices_free(Modem *modem)
702 gint i=0;
703 if (modem->serial_devices) {
704 for (i=0;i<modem->serial_devices->len;i++) {
705 SerialDevice *device = g_array_index(modem->serial_devices,SerialDevice*,i);
706 /* //ask vendor to close it */
707 /* if (modem->vendor->close_serial) */
708 /* modem->vendor->close_serial(modem->vendor, */
709 /* serial->fd); */
710 /* else //or close it ourselves */
711 /* close(serial->fd); */
712 gsmd_serial_free(device->serial);
713 g_queue_foreach(device->commandQueue,gsmd_modem_clear_queue_func,NULL);
714 g_queue_free(device->commandQueue);
715 g_free(device->serial_data);
719 g_array_free(modem->serial_devices,FALSE);
720 modem->serial_devices = NULL;
725 * @brief Close modem
727 * @param modem The pointer to the modem device struct which to be close
729 void gsmd_modem_close (ModemInterface* modem)
731 Modem *modem_priv = (Modem*)modem->priv;
732 g_assert (modem_priv);
733 g_debug("%s", __func__);
734 g_assert (modem);
735 if (modem_priv->vendor_handle)
736 dlclose (modem_priv->vendor_handle);
737 g_free (modem->call);
738 g_free (modem->call_ipc);
740 g_free (modem->sms);
741 g_free (modem->sms_ipc);
743 gsmd_network_deinitialize(modem);
744 g_free (modem->network);
745 g_free (modem->network_ipc);
747 g_free (modem->device);
748 g_free (modem->device_ipc);
750 g_free (modem->pdp);
751 g_free (modem->pdp_ipc);
754 gsmd_phonebook_deinitialize(modem);
755 g_free (modem->phonebook);
756 g_free (modem->phonebook_ipc);
758 gsmd_sim_deinitialize(modem);
759 g_free (modem->sim);
760 g_free (modem->sim_ipc);
762 g_hash_table_destroy (modem->cache);
764 g_scanner_destroy (modem->scanner);
765 g_hash_table_destroy (modem_priv->commands_table);
767 gsmd_modem_serial_devices_free(modem_priv);
770 GList *list = modem->calls;
771 while ( list ) {
772 Call *call = (Call*)list->data;
773 g_free(call);
774 list = g_list_next( list );
776 g_list_free(modem->calls);
777 modem->calls = NULL;
779 g_key_file_free(modem->conf_file);
781 g_free (modem);
785 /************************service function**************************************/
787 SerialDevice* gsmd_modem_get_serial_device_index(Modem *modem,guint device_index)
789 g_assert(modem);
790 g_assert(modem->serial_devices);
791 if( modem->serial_devices->len > device_index ) {
792 return g_array_index(modem->serial_devices, SerialDevice*, device_index);
793 } else {
794 g_warning("%s : Invalid index: %d. We have %d device(s)",
795 __func__, device_index, modem->serial_devices->len);
796 g_assert(FALSE);
798 return NULL;
800 SerialDevice* gsmd_modem_get_serial_device(Modem *modem,InterfaceType interface)
802 g_assert(modem);
803 g_assert(modem->serial_devices);
804 guint device_index = modem->modem_if->interface_devices[interface];
805 return gsmd_modem_get_serial_device_index(modem, device_index);
809 * @brief Sends initializing at commands to the modem
811 * @param modem modem to initialize
813 void gsmd_modem_general_at_init (ModemInterface* modem)
815 g_assert(modem);
816 gsmd_modem_post_at_command_id (modem,
817 DISABLE_ECHO,
818 NULL, NULL, NULL, NULL,
819 INTERFACE_GENERAL,
820 NULL);
822 gsmd_modem_post_at_command_id (modem,
823 ENABLE_CMEE,
824 NULL, NULL, NULL, NULL,
825 INTERFACE_GENERAL,
826 NULL);
828 gsmd_modem_post_at_command_id( modem,
829 IMEI_QUERY,
830 NULL, NULL, NULL, NULL,
831 INTERFACE_DEVICE,
832 NULL);
834 gsmd_modem_post_at_command_id( modem,
835 MANUFACTURER_QUERY,
836 NULL, NULL, NULL, NULL,
837 INTERFACE_DEVICE,
838 NULL);
840 gsmd_modem_post_at_command_id( modem,
841 SW_REVISION_QUERY,
842 NULL, NULL, NULL, NULL,
843 INTERFACE_DEVICE,
844 NULL);
846 gsmd_modem_post_at_command_id( modem,
847 MODEL_QUERY,
848 NULL, NULL, NULL, NULL,
849 INTERFACE_DEVICE,
850 NULL);
852 gsmd_modem_post_at_command_id (modem,
853 PIN_QUERY,
854 NULL, NULL, NULL, NULL,
855 INTERFACE_GENERAL,
856 NULL);
859 * @brief Sends initializing at commands that need sim_status >=
860 * SIM_READY to the modem
862 * @param modem modem to initialize
864 void gsmd_modem_general_at_init_sim_ready (ModemInterface* modem)
866 g_assert(modem);
867 gsmd_modem_post_at_command_id (modem,
868 ENABLE_CLIP,
869 NULL,NULL,NULL,NULL,
870 INTERFACE_GENERAL,
871 NULL);
873 gsmd_modem_post_at_command_id (modem,
874 ENABLE_CNMI,
875 NULL, NULL, NULL, NULL,
876 INTERFACE_GENERAL,
877 NULL);
879 gsmd_modem_post_at_command_id (modem,
880 SET_PDU_MODE,
881 NULL, NULL, NULL, NULL,
882 INTERFACE_GENERAL,
883 NULL);
884 gsmd_modem_post_at_command_id (modem,
885 SET_OP_QUERY_REPLY,
886 NULL, NULL, NULL, NULL,
887 INTERFACE_GENERAL,
888 NULL);
890 gsmd_modem_post_at_command_id (modem,
891 ENABLE_CCWA,
892 NULL, NULL, NULL, NULL,
893 INTERFACE_GENERAL,
894 NULL);
896 gsmd_modem_post_at_command_id (modem,
897 CUR_CALLS_QUERY,
898 NULL, NULL, NULL, NULL,
899 INTERFACE_GENERAL,
900 NULL);
904 * @brief Gets current command's ipc data
906 * @param modem modem device struct pointer
907 * @return pointer to ipc data
909 gpointer* gsmd_modem_get_current_ipc_data (ModemInterface *modem,
910 InterfaceType interface)
912 g_assert( modem );
913 AtCommandContext* at = gsmd_modem_get_current_at_command(modem,interface);
914 if (at)
915 return at->ipc_data;
916 return NULL;
920 * @brief Get AT command processed currently
922 * @param modem modem device struct pointer
924 * @return atcommand that is currently processed
926 AtCommandContext* gsmd_modem_get_current_at_command_index (ModemInterface *modem,
927 guint device_index)
929 g_assert( modem );
930 Modem *modem_priv = (Modem*)modem->priv;
931 g_assert (modem_priv);
932 g_assert (modem_priv->serial_devices);
933 SerialDevice *device = gsmd_modem_get_serial_device_index( modem_priv, device_index);
934 if (device)
935 return g_queue_peek_head(device->commandQueue);
936 return NULL;
939 * @brief Get AT command processed currently
941 * @param modem modem device struct pointer
943 * @return atcommand that is currently processed
945 AtCommandContext* gsmd_modem_get_current_at_command (ModemInterface *modem,
946 InterfaceType interface)
948 g_assert( modem );
949 Modem *modem_priv = (Modem*)modem->priv;
950 g_assert (modem_priv);
951 g_assert (modem_priv->serial_devices);
952 SerialDevice *device = gsmd_modem_get_serial_device( modem_priv, interface);
953 if (device)
954 return g_queue_peek_head(device->commandQueue);
955 return NULL;
959 * @brief Send AT command to head of the queue
961 * Diffrent from modem_add_command, forces command to be the first in
962 * command queue.
964 * @param modem modem device struct pointer
965 * @param at AT command to send
968 void gsmd_modem_send_command_force_next (Modem *modem,
969 AtCommandContext *at,
970 InterfaceType interface)
973 g_assert( modem );
974 g_assert( at );
975 SerialDevice *device = gsmd_modem_get_serial_device( modem, interface);
977 if (device) {
978 AtCommandContext *current_at = g_queue_pop_head ( device->commandQueue );
979 g_queue_push_tail ( device->commandQueue, at );
980 if ( current_at ) {
981 g_queue_push_head (device->commandQueue, current_at );
988 * @brief Adds an modem alive test command (AT) or soft reset (ATZ) to the first of the queue
989 * ignoring unoverrideable commands and processes it
991 * @param modem pointer to modem device struct
992 * @param reset if TRUE, send ATZ instead of AT
993 * @return TRUE if it was put first
995 gboolean gsmd_modem_post_alive_test (ModemInterface *modem_if, gboolean reset)
997 g_debug("%s",__func__);
998 g_assert(modem_if);
999 Modem *modem = (Modem*)modem_if->priv;
1000 g_assert(modem);
1001 g_assert(modem->serial_devices);
1002 SerialDevice *device = gsmd_modem_get_serial_device( modem, INTERFACE_GENERAL);
1003 g_assert(device);
1005 AtCommandContext *at = NULL;
1006 if (reset) {
1007 g_assert(modem->modem_if->status < MODEM_READY);
1008 at = gsmd_at_command_context_new_from_id(modem->modem_if,
1009 SOFT_RESET,
1010 NULL,
1011 NULL,
1012 NULL,
1013 NULL,
1014 NULL);
1015 } else {
1016 at = gsmd_at_command_context_new_from_id(modem->modem_if,
1017 REPLY_COMMAND,
1018 NULL,
1019 NULL,
1020 NULL,
1021 NULL,
1022 NULL);
1024 g_queue_push_head (device->commandQueue, at);
1025 gsmd_modem_process_next_command(modem,INTERFACE_GENERAL);
1026 return TRUE;
1031 * @brief Add a custom AT command to command queue. Overrides all (overrideable)
1032 * commands in the queue and thus tries to run it as soon as possible.
1034 * @param modem pointer to modem device struct
1035 * @param command AT command string
1036 * for example, "ATD1234567;"
1037 * @param handler The AT command response handler function
1038 * @param data data to write with the command
1039 * @param retry retry times
1040 * @param timeout timeout in milliseconds
1041 * @param overrideable can this command be overriden (true) or must it run
1042 * uninterrupted (false)
1043 * @return TRUE
1045 gboolean gsmd_modem_post_at_command_and_override (ModemInterface *modem,
1046 AtCommandContext *new_at,
1047 InterfaceType interface)
1049 g_assert(modem);
1050 Modem *modem_priv = (Modem*)modem->priv;
1051 g_assert(modem_priv->serial_devices);
1053 SerialDevice *device = gsmd_modem_get_serial_device( modem_priv, interface);
1055 if (!device) {
1056 g_warning("%s : improper device index",__func__);
1057 return FALSE;
1060 AtCommandContext *current_at = gsmd_modem_get_current_at_command ( modem,
1061 interface );
1063 //Most commands require PIN to be set
1064 if (new_at->command->required_state > modem->sim_status) {
1065 if (new_at->error_function) {
1066 gsmd_utils_send_error(new_at,
1067 GSMD_ERROR_UNKNOWN,
1068 "SIM AUTHENTICATION ERROR");
1069 g_debug("%s : Command %s wanted pin state to be %d, but it is only %d",
1070 __func__,
1071 new_at->command->command,
1072 new_at->command->required_state,
1073 modem->sim_status);
1075 return FALSE;
1078 //If no commands in queue, insert this one and process the queue
1079 if (!current_at) {
1080 g_debug("%s : No commands in queue, no need to override",__func__);
1081 g_queue_push_tail (device->commandQueue, new_at);
1082 gsmd_modem_process_next_command(modem_priv,interface);
1083 return TRUE;
1086 //if there are commands in the queue and we can override the first one, break it and push ours first
1087 if (current_at->command->overrideable) {
1088 g_debug("%s : Overriding current command",__func__);
1089 //Remove timeout for the previous command
1090 if (current_at->timeout_event_id != 0) {
1091 g_debug("%s : Removing timeout id: %d", __func__, current_at->timeout_event_id);
1092 g_source_remove(current_at->timeout_event_id);
1095 g_queue_push_head (device->commandQueue, new_at);
1096 gsmd_modem_send_command_raw (modem,"+++\r\n",interface);
1097 //Process the new command
1098 gsmd_modem_process_next_command(modem_priv,interface);
1099 } else { //if the current command isn't overrideable push our new command second in line
1100 g_debug("%s : Current command can't be overridden, moving next in queue",
1101 __func__);
1102 g_queue_pop_head(device->commandQueue);
1103 g_queue_push_head(device->commandQueue, new_at);
1104 g_queue_push_head(device->commandQueue,current_at);
1108 return TRUE;
1114 * @brief Add a custom AT command to command queue
1116 * @param modem pointer to modem device struct
1117 * @param at custom at command to add
1118 * @return TRUE
1120 gboolean gsmd_modem_post_at_command ( ModemInterface *modem,
1121 AtCommandContext *at,
1122 InterfaceType interface)
1124 g_assert(modem);
1125 g_assert (at);
1126 gsmd_utils_print_data(__func__,"command: ",at->command->command);
1128 Modem *modem_priv = (Modem*)modem->priv;
1129 if ( !modem_priv->serial_devices ) {
1130 //If serial ports aren't initialized then initialize them
1131 gsmd_modem_init_serial_ports(modem_priv);
1133 // modem is not ready so fail this request
1137 if (modem->status < MODEM_INITIALIZING) {
1138 gsmd_utils_print_data(__func__,
1139 "Modem is uninitialized, unable to add command: ",
1140 at->command->command);
1142 g_debug("%s : Unable to add command %s because modem is uninitialized",
1143 __func__,at->command->command);
1145 gsmd_utils_send_error(at, GSMD_ERROR_RESET, "Modem not ready yet");
1146 gsmd_at_command_context_free(at);
1147 return TRUE;
1152 AtCommandContext *current_at = gsmd_modem_get_current_at_command(modem,
1153 interface);
1155 SerialDevice *device = gsmd_modem_get_serial_device( modem_priv, interface);
1156 if (!device) {
1157 return FALSE;
1160 if (at) {
1161 g_queue_push_tail (device->commandQueue, at);
1164 if (!current_at) {
1165 g_debug("%s : process next command", __func__);
1166 gsmd_modem_process_next_command(modem_priv,interface);
1169 return TRUE;
1174 gboolean gsmd_modem_post_at_command_id ( ModemInterface* modem,
1175 AtCommandID command_id,
1176 const gchar *param,
1177 gpointer *ipc_data,
1178 ErrorFunction error_function,
1179 gpointer error_data,
1180 InterfaceType interface,
1181 GHashTable *handler_data)
1183 AtCommandContext *at = gsmd_at_command_context_new_from_id( modem,
1184 command_id,
1185 param,
1186 ipc_data,
1187 error_function,
1188 error_data,
1189 handler_data);
1190 return gsmd_modem_post_at_command (modem, at,interface);
1193 gboolean gsmd_modem_post_at_command_id_and_override ( ModemInterface* modem,
1194 AtCommandID command_id,
1195 const gchar *param,
1196 gpointer *ipc_data,
1197 ErrorFunction error_function,
1198 gpointer error_data,
1199 InterfaceType interface,
1200 GHashTable *handler_data)
1202 AtCommandContext *at = gsmd_at_command_context_new_from_id( modem,
1203 command_id,
1204 param,
1205 ipc_data,
1206 error_function,
1207 error_data,
1208 handler_data);
1209 return gsmd_modem_post_at_command_and_override (modem, at,interface);
1214 * @brief Create new AT command struct
1216 * @param command AT command string
1218 AtCommandContext* gsmd_at_command_context_new (AtCommand *at,
1219 const gchar *param,
1220 gpointer ipc_data,
1221 ErrorFunction error_function,
1222 gpointer error_data,
1223 GHashTable *handler_data)
1225 return gsmd_at_command_context_new_full(at,
1226 param,
1227 ipc_data,
1228 handler_data,
1229 error_function,
1230 error_data);
1235 * @brief Create new AT command struct
1237 * @param command AT command string
1239 AtCommandContext* gsmd_at_command_context_new_full (AtCommand *atcmd,
1240 const gchar *param,
1241 gpointer ipc_data,
1242 GHashTable *handler_data,
1243 ErrorFunction error_function,
1244 gpointer error_data)
1246 AtCommandContext *at = NULL;
1247 at = g_slice_new0 (AtCommandContext);
1248 if (!at) {
1249 g_warning ("Failed to create new AtCommandContext.\n");
1250 return NULL;
1252 at->command = atcmd;
1255 at->command_param = g_strdup(param);
1256 at->retry_counter = atcmd->retry;
1257 at->timeout_event_id = 0;
1258 at->ipc_data = ipc_data;
1259 at->error_function = error_function;
1260 at->error_data = error_data;
1261 if (!handler_data)
1262 at->handler_data = gsmd_utils_create_hash_table();
1263 else
1264 at->handler_data = handler_data;
1268 if ( at->error_function && !at->error_data) {
1269 g_warning("%s : AT command '%s' has error function but no error data!",
1270 __func__, atcmd->command);
1273 return at;
1276 AtCommandContext* gsmd_at_command_context_new_from_id (ModemInterface *modem,
1277 AtCommandID cmd_id,
1278 const gchar *param,
1279 gpointer ipc_data,
1280 ErrorFunction error_function,
1281 gpointer error_data,
1282 GHashTable *handler_data)
1284 Modem *modem_priv = (Modem*)modem->priv;
1285 AtCommandContext *at = NULL;
1286 AtCommand *command = (AtCommand *) g_hash_table_lookup(modem_priv->commands_table,
1287 GINT_TO_POINTER(cmd_id));
1289 g_assert(command);
1290 at = gsmd_at_command_context_new_full(command,
1291 param,
1292 ipc_data,
1293 handler_data,
1294 error_function,
1295 error_data);
1296 return at;
1300 * @brief Free the AT command struct
1302 * @param at The AT command pointer
1304 void gsmd_at_command_context_free (AtCommandContext* at)
1306 if (at== NULL) return;
1307 if (at->command_param)
1308 g_free(at->command_param);
1310 if (at->command->free_function) {
1311 at->command->free_function(at);
1314 g_hash_table_destroy(at->handler_data);
1315 g_slice_free (AtCommandContext,at);
1319 * @brief Function called after a command has been finished.
1321 * AtCommand will be removed from queue and freed.
1323 * @param modem pointer to the modem
1324 * @param interface device whose command to finish
1325 * @param test_alive should test alive command be sent
1327 static void gsmd_modem_finish_command (Modem* modem,
1328 InterfaceType interface,
1329 gboolean test_alive)
1331 g_debug("%s\n",__func__);
1332 SerialDevice *device = gsmd_modem_get_serial_device( modem, interface);
1333 if (!device) {
1334 return;
1337 GQueue *queue = device->commandQueue;
1339 AtCommandContext *at = g_queue_pop_head (queue);
1341 if (at) {
1342 gsmd_utils_print_data(__func__,
1343 "Removing command ",
1344 at->command->command);
1346 //g_debug("%s : %s",__func__,at->command->command);
1347 if (at->timeout_event_id != 0) {
1348 g_debug("%s : Removing timeout id: %d", __func__, at->timeout_event_id);
1349 g_source_remove(at->timeout_event_id);
1351 gsmd_at_command_context_free (at);
1353 } else
1354 g_debug("Got no next command to finish\n");
1356 // if command handler (e.g. some vendor command)
1357 // marked the modem not alive
1358 if ( modem->modem_if->status == MODEM_RESET) {
1359 gsmd_modem_close_serial_ports(modem);
1360 gsmd_modem_init_serial_ports(modem);
1361 } else if (test_alive) {
1362 g_debug("%s : testing that modem is alive",__func__);
1363 gsmd_modem_post_alive_test(modem->modem_if, FALSE);
1364 } else {
1365 g_debug("%s : processing next command",__func__);
1366 gsmd_modem_process_next_command(modem,interface);
1371 * @brief Returns serial data from specified device index
1373 * @param modem pointer to modem
1374 * @param interface device whose serial data to get
1375 * @return specified device's serial data or NULL if none found
1377 static SerialData *gsmd_modem_get_serial_data(Modem *modem, InterfaceType interface)
1379 g_assert(modem);
1380 g_assert(modem->serial_devices);
1381 SerialDevice *device = gsmd_modem_get_serial_device(modem, interface);
1382 if (device)
1383 return device->serial_data;
1384 return NULL;
1388 static void gsmd_modem_write_complete(WriteData *write, gpointer data)
1390 g_debug("%s", __func__);
1391 AtCommandContext *at = (AtCommandContext*)data;
1392 at->write_complete = TRUE;
1396 static void gsmd_modem_print_single_command(gpointer data,gpointer user_data)
1398 AtCommandContext* at = data;
1399 g_debug("%s : %s",__func__,at->command->command);
1402 static void gsmd_modem_print_commands(Modem* modem, InterfaceType interface)
1404 g_assert( modem );
1405 GQueue *queue = NULL;
1406 if ( modem->commandQueues->len > device_index ) {
1407 queue = g_array_index(modem->commandQueues,
1408 GQueue*,
1409 device_index);
1411 g_debug("%s : Commands: ",__func__);
1413 if (queue)
1414 g_queue_foreach(queue,gsmd_modem_print_single_command,NULL);
1420 * @brief Takes the next command from command queue and processes it
1422 * @param modem whose next command to process
1424 static void gsmd_modem_process_next_command (Modem* modem, InterfaceType interface)
1426 g_debug("%s: device: %d",__func__,interface);
1427 AtCommandContext *at = gsmd_modem_get_current_at_command ( modem->modem_if,
1428 interface );
1430 if (modem->vendor->command_prepare) {
1431 at = modem->vendor->command_prepare(modem->vendor,modem->modem_if,at);
1432 if ( at ) {
1433 gsmd_utils_print_data(__func__,
1434 "Running command_prepare AT command: ",
1435 at->command->command);
1438 g_debug("%s : Running command_prepare AT command: '%s'",
1439 __func__,
1440 at->command->command);
1442 SerialDevice *device = gsmd_modem_get_serial_device(modem, interface);
1443 g_assert(device);
1444 GQueue *queue = device->commandQueue;
1445 g_queue_push_head (queue, at);
1450 //Get current command again to allow vendor to insert their own command
1451 at = gsmd_modem_get_current_at_command ( modem->modem_if,
1452 interface );
1454 if (!at) {
1455 g_debug("%s : No commands in queue", __func__);
1456 return;
1458 //Most commands require PIN code to be set
1459 if (at->command->required_state > modem->modem_if->sim_status) {
1460 g_debug("%s : sim status: %d, command '%s' requires: %d",
1461 __func__, modem->modem_if->sim_status,
1462 at->command->command, at->command->required_state);
1463 if (at->error_function) {
1464 gsmd_utils_send_error(at,
1465 GSMD_ERROR_UNKNOWN,
1466 "SIM AUTHENTICATION ERROR");
1469 gsmd_modem_finish_command(modem, interface, FALSE);
1470 return;
1473 AtCommandPrepare prepare = at->command->prepare;
1474 gboolean prepare_ok = TRUE;
1476 gsmd_utils_print_data(__func__,
1477 "Processing command ",
1478 at->command->command);
1481 modem->is_timeout = TRUE;//set the timeout flag
1483 GString *command = g_string_new (at->command->command);
1486 if (at->command_param) {
1487 g_string_printf(command,at->command->command,
1488 at->command_param);
1493 if ( prepare ) {
1494 prepare_ok = (*prepare)(modem->modem_if);
1496 // TODO handle failed prepare
1497 if ( !prepare_ok ) {
1498 g_warning("%s: Prepare failed!", __func__);
1501 WriteData *data = g_try_new0(WriteData,1);
1502 data->command = g_strdup(command->str);
1506 data->timeout = at->command->timeout + TIME_OUT_PADDING;
1510 data->timeoutid = &at->timeout_event_id;
1511 data->timeout_data = gsmd_modem_get_serial_data(modem,
1512 interface);
1513 data->timeout_function = &gsmd_modem_timeout_handle;
1514 data->write_complete_data = at;
1515 data->write_complete_function = &gsmd_modem_write_complete;
1516 gsmd_modem_serial_queue_write (modem->modem_if, data,interface);
1517 g_string_free(command,TRUE);
1522 * @brief Initializes scanner for modem's input
1524 * @param modem whose input to scan
1526 static
1527 void gsmd_modem_scanner_init (ModemInterface *modem, GString *str)
1529 GScanner* scanner = modem->scanner;
1530 g_scanner_input_text (scanner, str->str, str->len);
1531 g_scanner_get_next_token (scanner);
1532 g_scanner_peek_next_token (scanner);
1536 * @brief Function to handle reading serial port
1538 * @param io io to read from
1539 * @param condition condition
1540 * @param data pointer to modem struct
1541 * @return always returns true
1543 void gsmd_modem_data_in (GString *buffer, gpointer data )
1545 SerialData *serial = (SerialData*)data;
1546 Modem *modem = serial->modem;
1547 ModemInterface *modem_if = modem->modem_if;
1548 AtCommandHandlerStatus status = AT_HANDLER_DONT_UNDERSTAND;
1549 AtCommandHandler handler = NULL;
1550 AtCommandContext *at = NULL;
1551 g_assert(modem);
1553 at = gsmd_modem_get_current_at_command_index ( modem_if, serial->device_index);
1554 if ( at && !at->write_complete) {
1555 g_debug("%s : Got input, but current command has not been written.", __func__);
1556 at = NULL;
1558 if (at && at->command) {
1559 if ( at->handler ) {
1560 handler = at->handler;
1561 } else if ( at->command->handler ) {
1562 handler = at->command->handler;
1563 } else {
1564 handler = &gsmd_utils_handler_ok;
1567 GString *debug_str = g_string_new("");
1568 g_string_printf(debug_str,"Received from port %d: ",serial->device_index);
1570 gsmd_utils_print_data(__func__,
1571 debug_str->str,
1572 buffer->str);
1573 g_string_free(debug_str,TRUE);
1575 if ( modem->vendor->data_in ) {
1576 modem->vendor->data_in(modem_if, at, buffer);
1578 gsmd_modem_scanner_init (modem_if, buffer);
1580 if ( handler ) {
1582 status = (*handler)(modem_if, at, buffer);
1583 switch ( status ) {
1584 case AT_HANDLER_DONE:
1585 case AT_HANDLER_DONE_ERROR:
1586 //if handled then process next command if there is
1587 modem->is_timeout = FALSE;
1588 g_debug("Done or done error");
1589 gsmd_modem_finish_command(modem,
1590 serial->device_index,
1591 FALSE);
1592 break;
1593 case AT_HANDLER_ERROR:
1594 modem->is_timeout = FALSE;
1595 gsmd_modem_finish_command(modem,
1596 serial->device_index,
1597 FALSE);
1598 // run unsolicite because we don't know if the message
1599 // belonged to handler or not
1600 gsmd_modem_handler_unsolicite( modem_if, NULL, buffer );
1601 break;
1602 case AT_HANDLER_NEED_MORE:
1603 break;
1604 case AT_HANDLER_DONT_UNDERSTAND:
1605 gsmd_modem_handler_unsolicite( modem_if, NULL, buffer );
1606 break;
1607 case AT_HANDLER_RETRY:
1608 gsmd_modem_retry_current_command( modem,
1609 serial->device_index );
1610 break;
1613 } else {
1614 if (gsmd_modem_handler_unsolicite( modem_if, NULL, buffer ) ==
1615 AT_HANDLER_DONE)
1616 modem->is_timeout = FALSE;
1628 * @brief Sms indocator parser
1630 * @param scanner whose data to parse
1631 * @return sms indicator
1633 gint gsmd_modem_sms_indicator_parse (GScanner* scanner)
1635 g_debug("%s",__func__);
1636 //input: CMTI: "SM", 1
1637 gint pos = -1;
1638 if (scanner->token == SYMBOL_CMTI) {
1639 g_scanner_get_next_token (scanner);// get ,
1640 g_scanner_get_next_token (scanner);//get s
1641 g_scanner_get_next_token (scanner);//get m
1642 g_scanner_get_next_token (scanner);//get ,
1643 pos = scanner->value.v_int;
1644 //g_message("sms pos is %d\n",pos);
1647 return pos;
1650 void gsmd_modem_register_command (ModemInterface *modem,
1651 const AtCommand *command)
1653 Modem *modem_priv = (Modem*)modem->priv;
1654 g_hash_table_insert(modem_priv->commands_table,
1655 GINT_TO_POINTER(command->cmd_id),
1656 (gpointer)command);
1659 Trigger* gsmd_modem_serial_register_trigger(ModemInterface *modem,
1660 const gchar *trigger_str,
1661 SerialDataIn handler,
1662 gpointer data,
1663 gboolean onetime,
1664 InterfaceType interface)
1666 Modem *modem_priv = (Modem*)modem->priv;
1667 SerialDevice *device = gsmd_modem_get_serial_device(modem_priv, interface);
1668 if (!device) {
1669 return NULL;
1672 if ( !handler ) {
1673 g_debug("%s : Using default handler/data", __func__);
1674 handler = &gsmd_modem_data_in;
1675 data = device->serial_data;
1678 return gsmd_serial_register_trigger(device->serial,
1679 trigger_str,
1680 handler,
1681 data,
1682 onetime);
1686 * @brief Queue a new write to serial port
1688 * @param modem pointer to modem interface
1689 * @param data writedata that contains timeout information
1690 * and the data to write to serial port
1691 * @param interface_index which interface to be used to write command
1693 void gsmd_modem_serial_queue_write ( ModemInterface *modem,
1694 WriteData *data,
1695 InterfaceType interface)
1697 Modem *modem_priv = (Modem*)modem->priv;
1698 SerialDevice *device = gsmd_modem_get_serial_device(modem_priv, interface);
1699 if (device) {
1700 gsmd_serial_queue_write( device->serial, data);
1701 } else {
1702 g_warning("%s : Writing data to improper serial device %d",
1703 __func__,
1704 device->serial_data->device_index);
1709 * @brief Writes data directly to serial port
1711 * @param modem pointer to modem interface
1712 * @param data writedata that contains timeout information
1713 * and the data to write to serial port
1714 * @param interface_index which interface to be used to write command
1716 void gsmd_modem_serial_write ( ModemInterface *modem,
1717 WriteData *data,
1718 InterfaceType interface)
1720 Modem *modem_priv = (Modem*)modem->priv;
1721 SerialDevice *device = gsmd_modem_get_serial_device(modem_priv, interface);
1722 if (device) {
1723 gsmd_serial_write( device->serial, data);
1724 } else {
1725 g_warning("%s : Writing data to improper serial device %d",
1726 __func__,
1727 device->serial_data->device_index);
1733 * @brief Write command directly to serial port
1735 * @param modem modem device struct pointer
1736 * @param command AT command to write
1737 * @param interface which interface to be used to write command
1739 static void gsmd_modem_send_command_raw ( ModemInterface *modem,
1740 const gchar *command,
1741 InterfaceType interface )
1743 WriteData *data = g_try_new0(WriteData,1);
1744 data->command = g_strdup(command);
1745 data->timeoutid = NULL;
1746 data->timeout = 0;
1747 data->timeout_data = NULL;
1748 data->timeout_function = NULL;
1749 gsmd_modem_serial_write(modem,data,interface);
1753 * @brief Write command directly to serial port
1755 * @param modem modem device struct pointer
1756 * @param command AT command to write
1757 * @param interface which interface to be used to write command
1759 void gsmd_modem_serial_write_simple ( ModemInterface *modem,
1760 const gchar *command,
1761 InterfaceType interface )
1763 WriteData *data = g_try_new0(WriteData,1);
1764 data->command = g_strdup(command);
1765 data->timeoutid = NULL;
1766 data->timeout = 0;
1767 data->timeout_data = NULL;
1768 data->timeout_function = NULL;
1769 gsmd_modem_serial_write(modem,data,interface);
1773 * @brief Initializes modem
1775 * @param modem pointer to modem to initialize
1777 static void gsmd_modem_init (ModemInterface* modem)
1779 Modem *modem_priv = (Modem*)modem->priv;
1781 modem_priv->vendor = g_new0(VendorInterface, 1);
1783 gsmd_device_init (modem);
1784 gsmd_pdp_init (modem);
1785 gsmd_sim_init (modem);
1786 gsmd_phonebook_init (modem);
1787 gsmd_network_init (modem);
1788 gsmd_call_init (modem);
1789 gsmd_sms_init (modem);
1792 GQuark
1793 gsmd_modem_error_quark (void)
1795 static GQuark quark;
1796 if (!quark)
1797 quark = g_quark_from_static_string ("gsmd_error");
1798 return quark;
1803 * @brief Timeout handler
1805 * @param data pointer to Modem, it will be freed by this function
1806 * @return always returns false
1808 static gboolean gsmd_modem_timeout_handle (gpointer data)
1810 SerialData *serial = (SerialData*) data;
1811 guint device_index = serial->device_index;
1812 AtCommandHandlerStatus handled = AT_HANDLER_DONT_UNDERSTAND;
1813 Modem* modem = serial->modem;
1814 AtCommandHandler handler;
1815 AtCommandContext *at = gsmd_modem_get_current_at_command_index ( modem->modem_if,
1816 device_index );
1818 if ( !at ) {
1819 g_warning("%s : No current command!",__func__);
1820 return FALSE;
1822 g_debug("%s: timeout id: %d, userdata: %p",__func__,at->timeout_event_id, data);
1823 // Setting timeout_event_id to 0 as it is removed when we return FALSE here.
1824 at->timeout_event_id = 0;
1825 g_assert( at->command);
1826 handler = at->command->handler;
1828 g_debug("Timeout on command %s\n",at->command->command);
1830 if (modem->is_timeout) {
1831 modem->is_timeout = FALSE;//clear the timeout flag
1833 //If it has a handler, test if it can handle TIME_OUT
1834 if (handler) {
1835 //copy TIME_OUT string to input buffer
1836 GString *timeout_buffer = g_string_new (TIME_OUT) ;//
1837 gsmd_modem_scanner_init (modem->modem_if, timeout_buffer);
1838 g_debug("Running command's handler for TIME_OUT");
1839 handled = (*handler)(modem->modem_if, at, timeout_buffer);
1840 g_string_free (timeout_buffer, TRUE);
1843 //if it couldn't handle it or didn't have a handler, let
1844 //unsolicite handler take care of it
1846 if (!handler || (handled != AT_HANDLER_DONE && handled != AT_HANDLER_DONE_ERROR)) {
1847 gsmd_utils_send_error(at,
1848 GSMD_ERROR_TIMEOUT,
1849 "TIMEOUT");
1853 gsmd_modem_finish_command(modem,device_index, TRUE);
1856 return FALSE;
1858 /***********************end of service function********************************/
1862 * @brief Change network status and use ipc data if new commands are issued
1864 * @param modem pointer to modem struct
1865 * @param status new network status
1866 * @param error_function error function to call if error occurs
1867 * @param error_data data to be supplied to error function call
1869 void gsmd_modem_change_network_status_data(ModemInterface *modem,
1870 NetworkStatus status,
1871 gpointer *ipc_data,
1872 ErrorFunction error_function,
1873 gpointer error_data)
1875 //TODO check that these assumptions are sane
1876 /* Simplified assumptions for actions for new statuses
1877 NETWORK_UNREGISTERED -> clear provider name, send empty status signal
1878 NETWORK_REGISTERED -> ask provider name and signal strength
1879 NETWORK_BUSY -> send empty status signal
1880 NETWORK_DENIED -> send empty status signal
1881 NETWORK_UNKNOWN -> send empty status signal
1882 NETWORK_ROAMING -> ask provider name and signal strength
1885 GString* message = g_string_new ("");
1886 g_string_printf(message, "%d",status);
1890 gsmd_utils_table_insert_int(modem->cache,
1891 GSMD_MODEM_KEY_NETWORK_STATUS,
1892 status);
1894 switch (status) {
1895 case NETWORK_UNREGISTERED:
1896 case NETWORK_BUSY:
1897 case NETWORK_DENIED:
1898 case NETWORK_UNKNOWN:
1899 if (modem->network->provider_name) {
1900 g_string_free(modem->network->provider_name,TRUE);
1902 modem->network->provider_name = g_string_new("");
1903 modem->network_ipc->status(modem->network_ipc,
1904 modem->network->provider_name->str,
1905 message->str,
1907 break;
1908 case NETWORK_ROAMING:
1909 case NETWORK_REGISTERED:
1910 gsmd_modem_post_at_command_id( modem,
1911 CUR_OP_QUERY,
1912 NULL,
1913 ipc_data,
1914 error_function,
1915 error_data,
1916 INTERFACE_NETWORK,
1917 NULL);
1918 break;
1924 g_string_free(message,TRUE);
1928 * @brief Change network status
1930 * @param modem modem interface pointer
1931 * @param new status
1933 void gsmd_modem_change_network_status(ModemInterface *modem,
1934 NetworkStatus status)
1936 gsmd_modem_change_network_status_data(modem,status,
1937 NULL,
1938 NULL,
1939 NULL);
1942 static
1943 void gsmd_modem_handle_network_status(ModemInterface *modem,
1944 GString *response)
1946 GError **error = NULL;
1947 GRegex *regex = g_regex_new ("\\+CREG:\\s(?<status>[0-5]),?(?<lac>\\d*),?(?<id>\\d*)",
1950 error);
1951 GMatchInfo *match_info;
1952 NetworkStatus status = NETWORK_UNKNOWN;
1953 gchar *match = NULL;
1955 if (g_regex_match (regex, response->str, 0, &match_info)) {
1956 if (gsmd_utils_match_exists(match_info,"status")) {
1957 match = g_match_info_fetch_named(match_info,
1958 "status");
1959 status = g_ascii_digit_value(match[0]);
1960 gsmd_modem_change_network_status(modem,status);
1961 g_free(match);
1965 g_match_info_free (match_info);
1966 g_regex_unref (regex);
1971 * @brief Handle's clip messages
1972 * Creates a new call with unknown call id
1974 * @param modem modem whose clip to handle
1975 * @param response string with CLIP
1977 static
1978 void gsmd_modem_handle_incoming_call(ModemInterface *modem,
1979 GString *response)
1981 g_debug("%s",__func__);
1983 +CLIP: "040123456789",128,"",128,"",0
1985 \+CLIP:\s"(\+?\w+)".*
1988 GError **error = NULL;
1989 GRegex *regex = g_regex_new ("\\+CLIP:\\s(?<phone>\"\\+?\\w+\")",
1992 error);
1993 GMatchInfo *match_info;
1994 gchar *match = NULL;
1997 if (g_regex_match (regex, response->str, 0, &match_info)) {
1998 if (gsmd_utils_match_exists(match_info,"phone")) {
1999 match = g_match_info_fetch_named(match_info,
2000 "phone");
2002 gchar *number = NULL;
2003 if (g_str_equal(match,"\"\""))
2004 number = g_strdup("Unknown number");
2005 else {
2006 GString *temp = g_string_new(&match[1]);
2007 g_string_erase(temp,temp->len-1,1);
2008 number = g_strdup(temp->str);
2009 g_string_free(temp,TRUE);
2012 g_debug("%s : incoming call from : %s",__func__,number);
2014 Call *call = gsmd_utils_find_call_number(modem,number);
2015 if ( !call) {
2016 call = gsmd_utils_new_call(modem,
2017 number,
2018 "", //TODO type ignored
2019 CALL_INCOMING);
2022 gsmd_utils_call_send_status(modem,
2023 call,
2024 "incoming",
2025 TRUE);
2027 g_free(match);
2028 g_free(number);
2030 } else {
2031 g_debug("Didn't understand +clip");
2034 g_match_info_free (match_info);
2035 g_regex_unref (regex);
2040 * @brief Finds first call with incoming status and sends call status signal
2041 * Should be called when ring message is received from gsm modem.
2043 * @param modem modem who sent ring message
2045 static
2046 void gsmd_modem_handle_ring(ModemInterface *modem)
2048 Call *call = gsmd_utils_find_first_call_status(modem,CALL_INCOMING);
2049 if (call) {
2050 gsmd_utils_call_send_status(modem,
2051 call,
2052 "incoming",
2053 TRUE);
2058 * @brief Handles CCWA (call waiting) messages from modem
2060 * @param modem modem whose call waiting message to handle
2061 * @param response string with CCWA
2063 static
2064 void gsmd_modem_handle_call_waiting(ModemInterface *modem,
2065 GString *response)
2068 +CCWA: "0401234567",129,1,"",0
2070 \+CCWA:\s"(\+?\d+)"
2073 GError **error = NULL;
2074 GRegex *regex = g_regex_new ("\\+CCWA:\\s\"(?<phone>\\+?\\d+)\"",
2077 error);
2078 GMatchInfo *match_info;
2079 gchar *match = NULL;
2081 if (g_regex_match (regex, response->str, 0, &match_info)) {
2082 if (gsmd_utils_match_exists(match_info,"phone")) {
2083 match = g_match_info_fetch_named(match_info,
2084 "phone");
2086 Call *call = gsmd_utils_find_call_number(modem,match);
2087 if ( !call) {
2088 call = gsmd_utils_new_call(modem,
2089 match,
2090 "", //TODO type ignored
2091 CALL_INCOMING);
2095 gsmd_utils_call_send_status(modem,
2096 call,
2097 "incoming",
2098 TRUE);
2100 g_free(match);
2102 } else {
2103 g_debug("Didn't understand +ccwa");
2106 g_match_info_free (match_info);
2107 g_regex_unref (regex);
2111 * @brief Parses clcc line and applies information to modem's calls
2112 * Can also create new calls if necessary.
2114 * @param modem pointer to modem whose calls to modify
2115 * @param clcc line returned by clcc
2117 void gsmd_modem_apply_current_call(ModemInterface *modem, const gchar *clcc)
2120 Test data with clip and ecam:
2121 +CLIP: "044123456",128,"",128,"",0
2123 #ECAM: 0,6,1,,,
2125 RING
2127 +CLIP: "044123456",128,"",128,"",0
2128 at+clcc
2130 +CLCC: 1,1,4,0,0,"044123456",128,""
2132 Test data with two calls
2133 +CLCC: 1,0,0,0,0,"+35840123456",145,""
2134 +CLCC: 2,1,5,0,0,"044654321",128,""
2138 In the first example #ECAM has call id 0
2139 but CLCC says call id is 1
2140 Call id can't be trusted to be call->vendor_id,
2141 but vendor_id _could_ be clcc's id -1
2143 \+CLCC:\s\d+,(\d),(\d),(\d),\d,"(\+?\d+)"
2146 GError **error = NULL;
2147 GRegex *regex = g_regex_new ("\\+CLCC:\\s(?<index>\\d+),(?<direction>\\d),(?<state>\\d),(?<mode>\\d),\\d,\"(?<number>\\+?\\d+)\"",
2150 error);
2151 GMatchInfo *match_info;
2153 if (g_regex_match (regex, clcc, 0, &match_info)) {
2154 if (gsmd_utils_match_exists(match_info,"index")) {
2155 gint id = gsmd_utils_fetch_match_int(match_info,
2156 "index");
2158 gint state = gsmd_utils_fetch_match_int(match_info,
2159 "state");
2161 gchar *number = g_match_info_fetch_named(match_info,
2162 "number");
2164 //phone number types might cause a problem if modem
2165 //automatically converts them to national/international
2166 //format. This would cause the call to not be found
2167 Call *call = gsmd_utils_find_call_number(modem,number);
2168 if (!call) {
2169 call = gsmd_utils_new_call(modem,number,"",CALL_IDLE);
2171 //this is merely a guess and should be removed
2172 call->vendor_id = id-1;
2175 switch (state) {
2176 case 0:
2177 call->status = CALL_CONNECTED;
2178 break;
2179 case 1:
2180 call->status = CALL_HOLD;
2181 break;
2182 case 2:
2183 case 3:
2184 call->status = CALL_CALLING;
2185 break;
2186 case 4:
2187 case 5:
2188 call->status = CALL_INCOMING;
2189 break;
2192 //Mode is currently ignored
2193 g_debug("%s: Got a call to/from %s with status %s",
2194 __func__,
2195 number,
2196 gsmd_utils_call_status_to_string(call->status));
2198 g_free(number);
2203 g_free(error);
2204 g_match_info_free (match_info);
2205 g_regex_unref (regex);
2210 * @brief Iterates all calls in current calls list in handler data
2211 * and calls gsmd_modem_apply_current_call on each of them
2213 * @param modem modem who own's the calls to parse
2214 * @param table GHashtable containing pointer to current calls list under
2215 * GSMD_MODEM_KEY_CALL_STATUS_ARRAY key
2217 void gsmd_modem_current_calls_parse(ModemInterface *modem,GHashTable *table)
2219 g_assert(table);
2220 g_assert(modem);
2222 GValue *val = g_hash_table_lookup(table,
2223 GSMD_MODEM_KEY_CALL_STATUS_ARRAY);
2225 if (!val)
2226 return;
2228 GList *list = g_value_get_pointer(val);
2230 while (list) {
2231 gchar *line = list->data;
2232 gsmd_modem_apply_current_call(modem,line);
2233 list = g_list_next( list );
2238 * @brief Frees current calls array from given at command
2240 * @param at at command context to free current calls array
2242 static
2243 void gsmd_modem_current_calls_free(AtCommandContext *at)
2245 g_assert(at);
2247 GList *list = NULL;
2248 GValue *val = g_hash_table_lookup(at->handler_data,
2249 GSMD_MODEM_KEY_CALL_STATUS_ARRAY);
2251 if (!val)
2252 return;
2254 list = g_value_get_pointer(val);
2256 while (list) {
2257 g_free(list->data);
2258 list = g_list_next( list );
2261 g_list_free(g_value_get_pointer(val));
2264 static
2265 AtCommandHandlerStatus gsmd_modem_handler_current_calls(ModemInterface *modem,
2266 AtCommandContext *at,
2267 GString *response)
2269 g_debug("%s",__func__);
2270 GError **error = NULL;
2271 GRegex *regex = g_regex_new ("\\+CLCC:\\s(?<index>\\d+),(?<direction>\\d),(?<state>\\d),(?<mode>\\d),\\d,\"(?<number>\\+?\\d+)\"|(?<error>ERROR)|(?<timeout>TIME_OUT)|(?<ok>OK)",
2274 error);
2275 AtCommandHandlerStatus status = AT_HANDLER_DONT_UNDERSTAND;
2276 GMatchInfo *match_info;
2277 GValue *val = NULL;
2280 if (g_regex_match (regex, response->str, 0, &match_info)) {
2281 if (gsmd_utils_match_exists(match_info,"index")) {
2283 GList *list = NULL;
2284 val = g_hash_table_lookup(at->handler_data,
2285 GSMD_MODEM_KEY_CALL_STATUS_ARRAY);
2286 if (val)
2287 list = g_value_get_pointer(val);
2289 list = g_list_append(list,g_strdup(response->str));
2291 gsmd_utils_table_insert_pointer(at->handler_data,
2292 GSMD_MODEM_KEY_CALL_STATUS_ARRAY,
2293 list);
2296 status = AT_HANDLER_NEED_MORE;
2297 } else if (gsmd_utils_match_exists(match_info,"error")) {
2298 gsmd_utils_send_error(at,
2299 GSMD_ERROR_UNKNOWN,
2300 "FAILED TO READ CURRENT CALL LIST");
2301 status = AT_HANDLER_DONE_ERROR;
2302 } else if (gsmd_utils_match_exists(match_info,"timeout")) {
2303 gsmd_utils_send_error(at,
2304 GSMD_ERROR_TIMEOUT,
2305 "TIMEOUT WHEN READING CURRENT CALL LIST");
2306 status = AT_HANDLER_DONE_ERROR;
2307 } else if (gsmd_utils_match_exists(match_info,"ok")) {
2309 val = g_hash_table_lookup(at->handler_data,GSMD_MODEM_KEY_CALL_STATUS_ARRAY);
2311 if (val) {
2312 gsmd_modem_current_calls_parse(modem,at->handler_data);
2316 status = AT_HANDLER_DONE;
2321 g_free(error);
2322 g_match_info_free (match_info);
2323 g_regex_unref (regex);
2326 return status;
2331 * @brief Handler for command to test if modem is alive
2333 * @param modem pointer to modem interface
2334 * @param at current at command's context
2335 * @param response message to handle
2336 * @return handler status
2338 static
2339 AtCommandHandlerStatus gsmd_modem_handler_alive(ModemInterface *modem,
2340 AtCommandContext *at,
2341 GString *response)
2343 g_debug("%s",__func__);
2344 Modem *modem_priv = (Modem*)modem->priv;
2345 GScanner* scanner = modem->scanner;
2347 //we've got a response, modem is alive. Start initializations
2348 if (scanner->token == SYMBOL_OK) {
2349 if (modem->status == MODEM_SERIAL_INIT) {
2350 modem->status = MODEM_INITIALIZING;
2352 if ( modem_priv->vendor->init_at ) {
2353 modem_priv->vendor->init_at (modem_priv->vendor);
2354 } else {
2355 gsmd_modem_general_at_init(modem);
2358 return AT_HANDLER_DONE;
2361 //Modem didn't reply or replied with an error
2362 if (scanner->token == SYMBOL_TIME_OUT ||
2363 scanner->token == SYMBOL_ERROR) {
2364 modem->status = MODEM_UNINITIALIZED;
2365 modem->sim_status = SIM_UNKNOWN;
2367 //Ask vendor if it can deal with an unresponsive modem
2368 if (modem_priv->vendor->not_responding &&
2369 modem_priv->vendor->not_responding(modem_priv->vendor))
2370 return AT_HANDLER_RETRY;
2371 else {
2372 gsmd_modem_close_serial_ports(modem_priv);
2373 return AT_HANDLER_DONE;
2377 return AT_HANDLER_DONT_UNDERSTAND;
2381 * @brief Handles unsolicited messages such as +CREG.
2383 * Unsolicite mesaage is an unexpected message or reply or a reply a
2384 * command's handler didn't understand.
2386 * @param modem pointer to modem interface
2387 * @param at current at command's context
2388 * @param response message to handle
2389 * @return handler status
2391 static
2392 AtCommandHandlerStatus gsmd_modem_handler_unsolicite (ModemInterface *modem,
2393 AtCommandContext *at,
2394 GString *response)
2396 Modem *modem_priv = (Modem*)modem->priv;
2397 GScanner* scanner = modem->scanner;
2398 gint sms_pos;
2399 g_debug("%s", __func__);
2400 Call *call = NULL;
2401 gint call_id = 0;
2403 if (g_scanner_eof(scanner))
2404 return AT_HANDLER_DONE;
2406 //Let vendor override unsolicite messages first
2407 if (modem_priv->vendor->unsolicite_handler) { //if there is vendor handler
2409 AtCommandHandlerStatus status;
2410 g_debug("%s: Running vendor_unsolicite_handler", __func__);
2411 //if vendor handled it, then we dont need to handle it ourselves
2412 status = modem_priv->vendor->unsolicite_handler (modem, NULL, response);
2413 if ( status != AT_HANDLER_DONT_UNDERSTAND ) {
2414 g_debug("%s: vendor_unsolicite_handler understood", __func__);
2415 return status;
2417 //reset the scanner
2418 gsmd_modem_scanner_init (modem, response);
2422 g_debug("%s: Running our default handler", __func__);
2424 switch (scanner->token) {
2425 case '+':
2426 g_scanner_get_next_token (scanner);
2427 switch (scanner->token) {
2428 case SYMBOL_CCWA:
2429 gsmd_modem_handle_call_waiting(modem,response);
2430 case SYMBOL_CLIP://display the incoming call phoneNo
2431 gsmd_modem_handle_incoming_call(modem,response);
2432 break;
2433 case SYMBOL_CRING://display +CRING: VOICE
2434 gsmd_modem_handle_ring(modem);
2435 break;
2436 case SYMBOL_CREG:
2437 gsmd_modem_handle_network_status(modem,response);
2438 break;
2439 case SYMBOL_CMTI://sms indicator
2440 g_debug("%s: CMTI", __func__);
2441 sms_pos = gsmd_modem_sms_indicator_parse (scanner);
2442 if (sms_pos > 0 && modem->sms_ipc->incoming_message) {
2443 modem->sms_ipc->incoming_message(modem->sms_ipc,
2444 sms_pos);
2448 break;
2449 default:
2450 g_warning ("Got unrecognized unsolicited symbol: %s\n",
2451 response->str);
2453 break;
2456 * NOTE! Handling NO CARRIER and BUSY have to be overridden in
2457 * vendor unsolicite handler if multiple concurrent calls are to be
2458 * implemented. By default we assume that only concurrent call
2459 * is possible and we remove the first call in both previously
2460 * mentioned cases.
2462 case SYMBOL_BUSY://remote hangup the call
2463 g_debug("%s: BUSY", __func__);
2464 call = gsmd_utils_call_get_current(modem);
2465 if (call) {
2466 call_id = call->id;
2467 gsmd_utils_remove_call(modem,call_id, TRUE);
2470 break;
2471 case SYMBOL_RING://handled in CLIP
2472 break;
2475 case SYMBOL_NO:
2476 g_scanner_get_next_token(scanner);
2477 if (scanner->token == SYMBOL_CARRIER) {
2478 call = gsmd_utils_call_get_current(modem);
2479 if (call) {
2480 call_id = call->id;
2483 gsmd_utils_remove_call(modem,call_id, TRUE);
2485 } else {
2486 g_scanner_unexp_token (scanner,
2487 SYMBOL_CARRIER,
2488 NULL,
2489 "symbol",
2490 NULL,
2491 NULL,
2492 TRUE);
2495 break;
2496 default:
2497 break;
2501 return AT_HANDLER_DONE;
2503 /**********************End of Default handler**********************************/
2507 * @brief Re-excute current AT command at the tail of command queue
2509 * @param modem Modem device struct pointer
2511 void gsmd_modem_retry_current_command (Modem* modem, InterfaceType interface)
2513 g_debug("%s: device: %d", __func__,interface);
2514 g_assert ( modem );
2515 g_assert ( modem->serial_devices );
2516 AtCommandContext *at = gsmd_modem_get_current_at_command ( modem->modem_if,
2517 interface );
2518 modem->is_timeout = FALSE;
2521 //Remove old timeout
2522 if (at->timeout_event_id != 0) {
2523 g_debug("%s : Removing timeout id: %d", __func__, at->timeout_event_id);
2524 g_source_remove(at->timeout_event_id);
2525 at->timeout_event_id = 0;
2529 if (at->retry_counter > 0) {
2530 g_debug("Retrying command %s",at->command->command);
2531 at->retry_counter--;
2532 gsmd_modem_process_next_command (modem,interface);
2533 } else {
2534 g_debug("Finished retrying command %s",at->command->command);
2535 gsmd_modem_finish_command(modem,interface,FALSE);
2543 gboolean gsmd_modem_cancel_command_id(ModemInterface *modem,
2544 AtCommandID cmd_id,
2545 InterfaceType interface)
2547 Modem * modem_priv = (Modem*)modem->priv;
2548 SerialDevice *device = gsmd_modem_get_serial_device(modem_priv, interface);
2549 g_assert(device);
2550 GQueue* queue = device->commandQueue;
2551 g_assert(queue);
2552 GList* list = NULL;
2553 gboolean res = FALSE;
2555 gint len = g_queue_get_length (queue);
2556 gint i=0;
2557 AtCommandContext* at = NULL;
2558 for (i=0; i < len; i++) { //the tail should not be remove which is handling
2559 at = (AtCommandContext*) g_queue_peek_nth (queue, i);
2560 if ( at->command->cmd_id == cmd_id ) {
2561 //g_queue_remove (queue, (gpointer) at);
2562 list = g_list_append (list, at);
2565 while (list) {
2566 res = TRUE;
2567 g_queue_remove (queue, list->data);
2568 gsmd_at_command_context_free(list->data);
2569 list = g_list_next (list);
2571 return res;
2574 gboolean gsmd_modem_assign_device_indices(ModemInterface *modem, int *indices)
2576 int i=0;
2577 for (i=0;i<INTERFACE_LAST;i++) {
2578 SerialDevice *device = gsmd_modem_get_serial_device_index((Modem*)modem->priv,indices[i]);
2579 if(!device) {
2580 return FALSE;
2582 modem->interface_devices[i]=indices[i];
2584 return TRUE;
2587 guint gsmd_modem_get_interface_device_index(ModemInterface *modem,
2588 InterfaceType interface)
2590 g_assert(modem);
2591 return modem->interface_devices[interface];
2593 AtCommand* gsmd_modem_get_command (ModemInterface *modem,
2594 guint cmd_id)
2596 Modem *modem_priv = (Modem*)modem->priv;
2597 return (AtCommand*)g_hash_table_lookup(modem_priv->commands_table,
2598 GINT_TO_POINTER(cmd_id));
2601 void gsmd_modem_reset(ModemInterface *modem)
2603 g_debug("%s",__func__);
2604 g_assert( modem );
2606 modem->status = MODEM_RESET;