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)
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.
39 #include "modem_internal.h"
41 #include "call_interface.h"
48 #include "sms_interface.h"
49 #include "pdp_interface.h"
50 #include "network_interface.h"
51 #include "device_interface.h"
52 #include "sim_interface.h"
53 #include "gsmd-error.h"
57 #define TIME_OUT "TIME_OUT\n"
59 /** Default time out value for AT command */
60 #define DEFAULT_TIME_OUT 100
62 /** Time out value for AT command */
63 #define TIME_OUT_PADDING 5000
66 /* static Modem *modem_priv; */
69 * @brief Serial device
70 * Modem can have multiple serial devices, each of them has their own Serial
74 typedef struct _SerialDevice
81 * IOChannel of serial device
86 * Pointer to modem interface used
91 * Index of the serial device to use
110 GArray
*serial_devices
;
115 GHashTable
*commands_table
;
120 ModemInterface
*modem_if
;
125 GModule
* vendor_handle
;
130 VendorInterface
*vendor
;
133 * Serial plugin handle
135 GModule
* serial_plugin_handle
;
138 * SerialPlugin interface
140 SerialInterface
*serial_if
;
145 /*********************service function**************************/
146 static void gsmd_modem_init ( ModemInterface
* modem
);
147 static AtCommandHandlerStatus
gsmd_modem_handler_unsolicite (ModemInterface
*modem
,
148 AtCommandContext
*at
,
151 static void gsmd_modem_process_next_command (Modem
* modem
, InterfaceType interface
);
152 static gboolean
gsmd_modem_timeout_handle (gpointer data
);
155 SerialDevice
*gsmd_modem_get_serial_device(Modem
*modem
, InterfaceType interface
);
158 AtCommandHandlerStatus
gsmd_modem_handler_alive(ModemInterface
*modem
,
159 AtCommandContext
*at
,
163 AtCommandHandlerStatus
gsmd_modem_handler_current_calls(ModemInterface
*modem
,
164 AtCommandContext
*at
,
167 static void gsmd_modem_current_calls_free(AtCommandContext
*at
);
168 /********************End service function***********************/
171 static const AtCommand
175 //Disable command echos
176 { DISABLE_ECHO
, "ATE0\r\n", 100,
178 gsmd_utils_handler_ok
, NULL
, SIM_UNKNOWN
, NULL
},
181 { POWER_ON
, "AT+CFUN=1\r\n", 15000,
183 gsmd_utils_handler_ok
, NULL
, SIM_UNKNOWN
, NULL
},
185 //Enable Report Mobile Equipment Error
186 { ENABLE_CMEE
, "AT+CMEE=1\r\n", 100,
188 gsmd_utils_handler_ok
, NULL
, SIM_UNKNOWN
, NULL
},
190 //Set response of AT+COPS? to respond with operator name
191 { SET_OP_QUERY_REPLY
, "AT+COPS=3,0\r\n", 100,
193 gsmd_utils_handler_ok
, NULL
, SIM_READY
, NULL
},
195 //Enable Report Mobile Equipment Error
196 { ENABLE_CMEE
, "AT+CMEE=1\r\n", 100,
198 gsmd_utils_handler_ok
, NULL
, SIM_UNKNOWN
, NULL
},
200 //Enable call waiting
201 { ENABLE_CCWA
, "AT+CCWA=1,1\r\n", 100,
203 gsmd_utils_handler_ok
, NULL
, SIM_READY
, NULL
},
205 //Enable call waiting
206 { CUR_CALLS_QUERY
, "AT+CLCC\r\n", 100,
208 gsmd_modem_handler_current_calls
, NULL
, SIM_READY
,
209 gsmd_modem_current_calls_free
},
211 //Query if we are muted
212 { MUTE_QUERY
, "AT+CMUTE=?\r\n", 5000,
214 gsmd_utils_handler_ok
, NULL
, SIM_READY
, NULL
},
216 //Enable caller identification
217 { ENABLE_CLIP
, "AT+CLIP=1\r\n", 180000,
219 gsmd_utils_handler_ok
, NULL
, SIM_READY
, NULL
},
221 //Enable new message identification
222 { ENABLE_CNMI
, "AT+CNMI=2,1,0,0,0\r\n", 5000,
224 gsmd_utils_handler_ok
, NULL
, SIM_READY
, NULL
},
227 { RING_VOLUME_QUERY
, "AT+CRSL?\r\n", 5000,
229 gsmd_utils_handler_ok
, NULL
, SIM_READY
, NULL
},
232 { ESCAPE_COMMAND
, "+++\r\n", 100,
234 gsmd_utils_handler_ok
, NULL
, SIM_UNKNOWN
, NULL
},
236 //Just send at command
237 { AT
, "AT\r\n", 5000,
239 gsmd_utils_handler_ok
, NULL
, SIM_UNKNOWN
, NULL
},
241 //Test modem is alive
242 { REPLY_COMMAND
, "AT\r\n", 5000,
244 gsmd_modem_handler_alive
, NULL
, SIM_UNKNOWN
, NULL
},
247 { SET_PDU_MODE
, "AT+CMGF=0\r\n", 100,
249 gsmd_utils_handler_ok
, NULL
, SIM_READY
, NULL
},
251 //Test modem is alive
252 { SOFT_RESET
, "ATZ\r\n", 5000,
254 gsmd_modem_handler_alive
, NULL
, SIM_UNKNOWN
, NULL
},
256 { 0, NULL
, 100, TRUE
, 1,
257 NULL
, NULL
, SIM_UNKNOWN
, NULL
},
259 }, *command_p
= commands
;
262 static const SymbolTable
265 { "TIME_OUT", SYMBOL_TIME_OUT
,},
266 { "OK", SYMBOL_OK
, },
267 { "ERROR", SYMBOL_ERROR
, },
268 { "RING", SYMBOL_RING
, },
269 { "NO", SYMBOL_NO
, },
270 { "ANSWER", SYMBOL_ANSWER
, },
271 { "CARRIER", SYMBOL_CARRIER
, },
272 { "BUSY", SYMBOL_BUSY
, },
273 { "READY", SYMBOL_READY
, },
274 { "CME", SYMBOL_CME
, },
275 { "CMS", SYMBOL_CMS
, },
276 { "CPIN", SYMBOL_CPIN
, },
277 { "CPAS", SYMBOL_CPAS
, },
278 { "CSQ", SYMBOL_CSQ
, },
279 { "CMUT", SYMBOL_CMUT
, },
280 { "CLIP", SYMBOL_CLIP
, },
281 { "CCWA", SYMBOL_CCWA
, },
282 { "CRING", SYMBOL_CRING
, },
283 { "CMTI", SYMBOL_CMTI
, },
284 { "CRSL", SYMBOL_CRSL
, },
285 { "CMGW", SYMBOL_CMGW
, },
286 { "PIN", SYMBOL_PIN
, },
287 { "PUK", SYMBOL_PUK
, },
289 }, *symbol_p
= symbols
;
293 * @brief Creates modem interface and sets pointers
295 * @param modem modem whose interface to create
298 void gsmd_modem_set_up_interface(Modem
*modem
)
300 modem
->modem_if
= g_new0(ModemInterface
, 1);
301 modem
->modem_if
->priv
= (gpointer
)modem
;
305 * @brief Function used to free gvalues stored in modem's cache
307 * @param data pointer to gvalue to be freed
309 static void gsmd_modem_cache_destroy(gpointer data
)
311 GValue
*value
= data
;
312 g_value_unset(value
);
317 * @brief Allocates a new modem struct
319 * @return newly created modem struct
321 Modem
* gsmd_modem_allocate()
323 ModemInterface
*modem
= NULL
;
324 Modem
*modem_priv
= g_try_new0 (Modem
, 1);
328 g_warning("%s : Failed to allocate a modem structure.", __func__
);
332 gsmd_modem_set_up_interface(modem_priv
);
334 modem
= modem_priv
->modem_if
;
336 modem_priv
->vendor_handle
= NULL
;
337 modem_priv
->is_timeout
= FALSE
;
339 modem
->status
= MODEM_UNINITIALIZED
;
340 //modem->sim_status = SIM_UNKNOWN;
341 modem
->devices
= NULL
;
347 modem
->scanner
= g_scanner_new (NULL
);
350 g_warning("%s : Failed to set a scanner for the modem.", __func__
);
354 modem
->scanner
->config
->symbol_2_token
= TRUE
;
355 modem
->scanner
->config
->numbers_2_int
= TRUE
;
356 modem
->scanner
->config
->skip_comment_single
= FALSE
;
357 modem
->scanner
->config
->cpair_comment_single
= "";
358 /* the character to skip*/
360 //Add commands list into hash table
361 modem_priv
->commands_table
= g_hash_table_new(NULL
,NULL
);
362 if (!modem_priv
->commands_table
)
364 g_warning("%s : Failed to set command table for the modem.", __func__
);
368 for (i
=0; i
< INTERFACE_LAST
; i
++)
370 modem
->caches
[i
] = g_hash_table_new_full(NULL
,
373 gsmd_modem_cache_destroy
);
375 gsmd_utils_table_insert_int(modem
->caches
[INTERFACE_NETWORK
],
376 GSMD_MODEM_KEY_NETWORK_STATUS
,
379 modem
->call
= g_try_new0 (CallInterface
, 1);
382 modem
->call_ipc
= g_try_new0 (CallIPCInterface
, 1);
383 if (!modem
->call_ipc
)
385 modem
->sms
= g_try_new0 (SMSInterface
, 1);
388 modem
->sms_ipc
= g_try_new0 (SMSIPCInterface
, 1);
391 modem
->device
= g_try_new0 (DeviceInterface
, 1);
394 modem
->device_ipc
= g_try_new0 (DeviceIPCInterface
, 1);
395 if (!modem
->device_ipc
)
398 modem
->network
= g_try_new0 (NetworkInterface
, 1);
401 modem
->network_ipc
= g_try_new0 (NetworkIPCInterface
, 1);
402 if (!modem
->network_ipc
)
404 modem
->pdp
= g_try_new0 (PDPInterface
, 1);
407 modem
->pdp_ipc
= g_try_new0 (PDPIPCInterface
, 1);
410 modem
->sim
= g_try_new0 (SIMInterface
, 1);
413 modem
->sim_ipc
= g_try_new0 (SIMIPCInterface
, 1);
421 g_warning("%s: error", __func__
);
424 g_free (modem
->device
);
425 g_free (modem
->device_ipc
);
427 g_free (modem
->sms_ipc
);
428 g_free (modem
->call
);
429 g_free (modem
->call_ipc
);
430 g_free (modem
->network
);
431 g_free (modem
->network_ipc
);
433 g_free (modem
->pdp_ipc
);
436 for (i
=0; i
< INTERFACE_LAST
; i
++)
438 g_hash_table_destroy (modem
->caches
[i
]);
444 if (modem_priv
->commands_table
)
445 g_hash_table_destroy (modem_priv
->commands_table
);
446 if (modem_priv
->modem_if
->scanner
)
447 g_scanner_destroy (modem
->scanner
);
455 * @brief Loads and initializes vendor
456 * @param modem modem to attach the handler
457 * @param vendor the vendor's name. E.g. "telit"
458 * @return TRUE if load was successful, otherwise FALSE
460 gboolean
gsmd_modem_load_vendor_handler (Modem
* modem
, const gchar
* vendor
)
462 VendorInit vendor_init
;
463 gpointer vendor_init_symbol
= NULL
;;
464 GString
* vendor_name
= NULL
;
465 const gchar
*plugindir
= g_getenv("GSMD2VENDORPLUGINDIR");
466 //perform vendor init
467 //vendor_telit_unsolicite_handler_init (modem);
471 g_debug("%s : Vendor: %s", __func__
, vendor
);
472 vendor_name
= g_string_new ("");
476 plugindir
= GSMD2PLUGINDIR
;
478 g_string_printf (vendor_name
, "vendor%s", vendor
);
479 gchar
*plugin_path
= g_module_build_path(plugindir
, vendor_name
->str
);
480 modem
->vendor_handle
= g_module_open (plugin_path
,G_MODULE_BIND_MASK
);
481 g_string_free (vendor_name
, TRUE
);
483 g_free( plugin_path
);
485 if (!modem
->vendor_handle
)
487 g_critical ("Vendor %s not found from %s",vendor
, plugindir
);
491 if (!g_module_symbol (modem
->vendor_handle
,"vendor_handle_init", &vendor_init_symbol
) )
493 g_critical ("'vendor_handle_init' symbol %s not found from %s",vendor
, plugindir
);
494 g_module_close(modem
->vendor_handle
);
495 modem
->vendor_handle
= NULL
;
498 vendor_init
= (VendorInit
)vendor_init_symbol
;
499 return vendor_init (modem
->vendor
, modem
->modem_if
);
503 * Finds the correct vendor handler
504 * @param modem modem to attach the handler
505 * @param vendor the vendor's name. E.g. "telit"
506 * @return TRUE if load was successful, otherwise FALSE
508 gboolean
gsmd_modem_load_serial_plugin (Modem
* modem
, const gchar
* plugin
)
510 g_debug("%s : Serial plugin: %s", __func__
, plugin
);
511 SerialPluginInit serial_init
= NULL
;
512 gpointer serial_init_symbol
= NULL
;
513 GString
* plugin_name
= NULL
;
514 //perform vendor init
515 //plugin_telit_unsolicite_handler_init (modem);
520 plugin_name
= g_string_new ("");
522 const gchar
*plugindir
= g_getenv("GSMD2SERIALPLUGINDIR");
525 plugindir
= GSMD2PLUGINDIR
;
527 g_string_printf (plugin_name
, "serial%s", plugin
);
528 gchar
*plugin_path
= g_module_build_path(plugindir
, plugin_name
->str
);
529 modem
->serial_plugin_handle
= g_module_open (plugin_path
,G_MODULE_BIND_MASK
);
530 g_string_free (plugin_name
, TRUE
);
534 if (!modem
->serial_plugin_handle
)
536 g_critical ("%s : Serial plugin %s not found from %s",__func__
, plugin
, plugindir
);
539 if (!g_module_symbol(modem
->serial_plugin_handle
,"serial_plugin_init", &serial_init_symbol
) )
541 g_critical ("%s : Serial plugin %s init function not found",__func__
, plugin
);
542 g_module_close(modem
->serial_plugin_handle
);
543 modem
->serial_plugin_handle
= NULL
;
546 g_module_make_resident(modem
->serial_plugin_handle
);
547 serial_init
= (SerialPluginInit
)serial_init_symbol
;
549 modem
->serial_if
= g_new0(SerialInterface
, 1);
551 return serial_init (modem
->serial_if
, modem
->modem_if
);
555 * @brief Adds default scanner symbols and registers at commands to modem struct
557 * @param modem modem to initialize
559 void gsmd_modem_init_standard_at_handler(ModemInterface
* modem
)
561 g_debug("%s", __func__
);
563 while (symbol_p
->symbol_name
)
565 g_scanner_add_symbol (modem
->scanner
, symbol_p
->symbol_name
,
566 GINT_TO_POINTER(symbol_p
->symbol_token
));
570 while (command_p
->command
)
572 gsmd_modem_register_command (modem
,command_p
);
578 * @brief Function to call when command needs to be cancelled prematurely
580 * Removes timeout and calls error_function
582 * @param data pointer to atcommand context to be cancelled
583 * @param user_data not used
585 void gsmd_modem_clear_queue_func(gpointer data
,
588 AtCommandContext
*at
= (AtCommandContext
*)data
;
589 gsmd_utils_send_error(at
, GSMD_ERROR_RESET
, "Reseting modem");
590 if (at
->timeout_event_id
!= 0)
592 g_debug("%s : Removing timeout id: %d",
594 at
->timeout_event_id
);
596 g_source_remove(at
->timeout_event_id
);
598 gsmd_at_command_context_free(at
);
603 * @brief Closes all serial ports
605 * @param modem pointer to modem whose serial ports to close
607 void gsmd_modem_close_serial_ports(Modem
*modem
)
609 g_debug("%s",__func__
);
612 if (modem
->serial_devices
)
614 for (i
=0;i
<modem
->serial_devices
->len
;i
++)
616 SerialDevice
*serial
= g_array_index(modem
->serial_devices
,SerialDevice
*,i
);
617 if (modem
->serial_if
->close_serial
)
619 modem
->serial_if
->close_serial(modem
->serial_if
,serial
->serial
->fd
);
621 gsmd_serial_free(serial
->serial
);
622 g_queue_foreach(serial
->commandQueue
,gsmd_modem_clear_queue_func
,NULL
);
623 g_queue_free(serial
->commandQueue
);
625 g_array_free(modem
->serial_devices
,TRUE
);
626 modem
->serial_devices
= NULL
;
629 modem
->modem_if
->status
= MODEM_UNINITIALIZED
;
633 * @brief Initializes modem's serial ports
635 * @param modem modem whose serial ports to initialize
636 * @return TRUE if they were intialized
638 gboolean
gsmd_modem_init_serial_ports(Modem
*modem
)
640 g_debug("%s",__func__
);
642 //Make sure we aren't initializing the modem twice
643 if (modem
->modem_if
->status
!= MODEM_UNINITIALIZED
)
646 modem
->modem_if
->status
= MODEM_SERIAL_INIT
;
650 g_assert(modem
->modem_if
);
651 g_assert(modem
->modem_if
->devices
);
653 modem
->serial_devices
= g_array_new(TRUE
,TRUE
,sizeof(SerialDevice
*));
656 GList
*device_it
= modem
->modem_if
->devices
;
659 gchar
*device
= device_it
->data
;
660 g_debug("Adding device %s",device
);
661 gint device_fd
= modem
->serial_if
->open_serial( modem
->serial_if
, device
);
665 g_warning ("%s : init_serial failed\n",
667 gsmd_modem_close_serial_ports (modem
);
671 Serial
*serial
= gsmd_serial_open_port (device_fd
);
674 g_warning("%s : Failed to open device %s",
677 //open failed, release the resource
678 gsmd_modem_close_serial_ports (modem
);
681 SerialDevice
*serial_device
= g_new0(SerialDevice
, 1);
682 serial_device
->serial
= serial
;
683 serial_device
->commandQueue
= g_queue_new();
684 serial_device
->modem
= modem
;
685 serial_device
->device_index
= i
;
687 gsmd_serial_register_trigger( serial
, "\r\n",
689 (gpointer
)serial_device
,
691 gsmd_serial_register_trigger( serial
, "\r",
693 (gpointer
)serial_device
,
695 gsmd_serial_register_trigger( serial
, "\n",
697 (gpointer
)serial_device
,
700 g_array_append_val(modem
->serial_devices
,serial_device
);
701 device_it
= g_list_next(device_it
);
705 if ( modem
->vendor
->wakeup_modem
)
707 if (modem
->vendor
->wakeup_modem(modem
->vendor
))
709 gsmd_modem_post_alive_test(modem
->modem_if
,TRUE
);
714 gsmd_modem_post_alive_test(modem
->modem_if
,TRUE
);
721 * @brief Opens a modem device.
723 * Before using modem, this function must be called to open modem and
724 * get modem device struct pointer
726 * @param devices list of device file names
727 * @param vendor The libname name of the vendor
728 * for example "telit"
729 * @param serial_plugin The libname name of the serial plugin
730 * for example "fsomuxer"
731 * @param no_cache should caching be used(FALSE) or not (TRUE)
732 * @param conf configuration file
733 * @param ipc_init pointer to ipc initialization function
734 * @param interface_devices a list that maps interfaces to devices
735 * @return pointer to newly created modem interface struct
737 ModemInterface
* gsmd_modem_open (gchar
**devices
,
739 const gchar
* serial_plugin
,
743 int *interface_devices
)
746 Modem
* modem
= gsmd_modem_allocate();
747 modem
->modem_if
->no_cache
= no_cache
;
748 modem
->modem_if
->conf_file
= conf
;
749 gchar
*device
= NULL
;
758 gsmd_modem_init (modem
->modem_if
);
760 modem
->modem_if
->ipc_data
= ipc_init(modem
->modem_if
);
762 if (!modem
->modem_if
->ipc_data
)
764 g_warning("Cannot initialize ipc!\n");
769 if (!gsmd_modem_load_vendor_handler (modem
, vendor
))
771 g_warning ("Can't find the vendor or vendor init failed: %s\n", vendor
);
775 if (!gsmd_modem_load_serial_plugin (modem
, serial_plugin
))
777 g_warning ("Can't find the serial plugin or plugin init failed: %s\n", serial_plugin
);
781 gsmd_modem_init_standard_at_handler(modem
->modem_if
);
783 if ( modem
->serial_if
->get_ports
)
785 modem
->modem_if
->devices
= modem
->serial_if
->get_ports(modem
->serial_if
);
786 if ( modem
->modem_if
->devices
)
788 g_debug("%s : Using ports given by serial plugin", __func__
);
791 if ( !modem
->modem_if
->devices
)
793 g_debug("%s : Using ports given from command line or configuration file", __func__
);
798 g_debug("%s : '%s'", __func__
, device
);
799 modem
->modem_if
->devices
= g_list_append(modem
->modem_if
->devices
,device
);
805 if (!gsmd_modem_init_serial_ports(modem
))
809 if ( !gsmd_modem_assign_device_indices(modem
->modem_if
,interface_devices
) )
811 gsmd_modem_free(modem
->modem_if
);
815 return modem
->modem_if
;
819 * @brief Changes sim's status
821 * Calls gsmd_modem_general_at_init_sim_ready when appropriate
823 * @param modem modem whose sim status to change
824 * @param status new status to set
826 void gsmd_modem_change_sim_status(ModemInterface
*modem
, SIMStatus status
)
829 Modem
*modem_priv
= (Modem
*)modem
->priv
;
830 if ( modem
->sim_status
< SIM_READY
831 && status
>= SIM_READY
)
833 if ( modem_priv
->vendor
->init_at_sim_ready
)
835 modem_priv
->vendor
->init_at_sim_ready (modem_priv
->vendor
);
839 gsmd_modem_general_at_init_sim_ready(modem
);
842 modem
->sim_status
= status
;
846 * @brief Frees all serial devices within the modem
848 * @param modem modem whose serial devices to free
850 void gsmd_modem_serial_devices_free(Modem
*modem
)
853 if (modem
->serial_devices
)
855 for (i
=0;i
<modem
->serial_devices
->len
;i
++)
857 SerialDevice
*device
= g_array_index(modem
->serial_devices
,SerialDevice
*,i
);
858 /* //ask vendor to close it */
859 /* if (modem->vendor->close_serial) */
860 /* modem->vendor->close_serial(modem->vendor, */
862 /* else //or close it ourselves */
863 /* close(serial->fd); */
864 gsmd_serial_free(device
->serial
);
865 g_queue_foreach(device
->commandQueue
,gsmd_modem_clear_queue_func
,NULL
);
866 g_queue_free(device
->commandQueue
);
870 g_array_free(modem
->serial_devices
,FALSE
);
871 modem
->serial_devices
= NULL
;
876 * @brief Frees modem struct
878 * @param modem The pointer to the modem device struct which to be close
880 void gsmd_modem_free (ModemInterface
* modem
)
882 Modem
*modem_priv
= (Modem
*)modem
->priv
;
883 g_assert (modem_priv
);
884 g_debug("%s", __func__
);
886 if (modem_priv
->vendor_handle
)
887 dlclose (modem_priv
->vendor_handle
);
888 g_free (modem
->call
);
889 g_free (modem
->call_ipc
);
892 g_free (modem
->sms_ipc
);
894 gsmd_network_deinitialize(modem
);
895 g_free (modem
->network
);
896 g_free (modem
->network_ipc
);
898 g_free (modem
->device
);
899 g_free (modem
->device_ipc
);
902 g_free (modem
->pdp_ipc
);
905 gsmd_sim_deinitialize(modem
);
907 g_free (modem
->sim_ipc
);
910 for (i
=0; i
< INTERFACE_LAST
; i
++)
912 g_hash_table_destroy (modem
->caches
[i
]);
915 g_scanner_destroy (modem
->scanner
);
916 g_hash_table_destroy (modem_priv
->commands_table
);
918 gsmd_modem_serial_devices_free(modem_priv
);
921 GList
*list
= modem
->calls
;
924 Call
*call
= (Call
*)list
->data
;
926 list
= g_list_next( list
);
928 g_list_free(modem
->calls
);
931 g_key_file_free(modem
->conf_file
);
937 /************************service function**************************************/
940 * @brief Get serial device with specified index
942 * @param modem pointer to modem whose serial device to get
943 * @param device_index index of the device to get
944 * @return serial device or NULL if none found
946 SerialDevice
* gsmd_modem_get_serial_device_index(Modem
*modem
,
950 g_assert(modem
->serial_devices
);
951 if ( modem
->serial_devices
->len
> device_index
)
953 return g_array_index(modem
->serial_devices
, SerialDevice
*, device_index
);
957 g_warning("%s : Invalid index: %d. We have %d device(s)",
958 __func__
, device_index
, modem
->serial_devices
->len
);
965 * @brief Gets specific interface's serial device
967 * @param modem modem whose serial devices to get
968 * @param interface interface whose serial to get
969 * @return serialdevice mapped to specified interface
971 SerialDevice
* gsmd_modem_get_serial_device(Modem
*modem
,InterfaceType interface
)
974 g_return_val_if_fail(modem
->serial_devices
, NULL
);
975 guint device_index
= modem
->modem_if
->interface_devices
[interface
];
976 return gsmd_modem_get_serial_device_index(modem
, device_index
);
980 * @brief Sends initializing at commands to the modem
982 * @param modem modem to initialize
984 void gsmd_modem_general_at_init (ModemInterface
* modem
)
987 gsmd_modem_post_at_command_id (modem
,
989 NULL
, NULL
, NULL
, NULL
,
993 gsmd_modem_post_at_command_id (modem
,
995 NULL
, NULL
, NULL
, NULL
,
999 gsmd_modem_post_at_command_id( modem
,
1001 NULL
, NULL
, NULL
, NULL
,
1005 gsmd_modem_post_at_command_id( modem
,
1007 NULL
, NULL
, NULL
, NULL
,
1011 gsmd_modem_post_at_command_id( modem
,
1013 NULL
, NULL
, NULL
, NULL
,
1017 gsmd_modem_post_at_command_id( modem
,
1019 NULL
, NULL
, NULL
, NULL
,
1023 gsmd_modem_post_at_command_id (modem
,
1025 NULL
, NULL
, NULL
, NULL
,
1030 * @brief Sends initializing at commands that need sim_status >=
1031 * SIM_READY to the modem
1033 * @param modem modem to initialize
1035 void gsmd_modem_general_at_init_sim_ready (ModemInterface
* modem
)
1038 gsmd_modem_post_at_command_id (modem
,
1040 NULL
,NULL
,NULL
,NULL
,
1044 gsmd_modem_post_at_command_id (modem
,
1046 NULL
, NULL
, NULL
, NULL
,
1050 gsmd_modem_post_at_command_id (modem
,
1052 NULL
, NULL
, NULL
, NULL
,
1055 gsmd_modem_post_at_command_id (modem
,
1057 NULL
, NULL
, NULL
, NULL
,
1061 gsmd_modem_post_at_command_id (modem
,
1063 NULL
, NULL
, NULL
, NULL
,
1067 gsmd_modem_post_at_command_id (modem
,
1069 NULL
, NULL
, NULL
, NULL
,
1076 * @brief Get AT command processed currently
1078 * @param modem modem device struct pointer
1079 * @param device_index index of the device whose command to get
1080 * @return atcommand that is currently processed
1082 AtCommandContext
* gsmd_modem_get_current_at_command_index (ModemInterface
*modem
,
1086 Modem
*modem_priv
= (Modem
*)modem
->priv
;
1087 g_assert (modem_priv
);
1088 g_assert (modem_priv
->serial_devices
);
1089 SerialDevice
*device
= gsmd_modem_get_serial_device_index( modem_priv
, device_index
);
1091 return g_queue_peek_head(device
->commandQueue
);
1096 * @brief Get the AT command that is processed at the moment
1098 * @param modem modem device struct pointer
1099 * @param interface which interface's command to get
1100 * @return at command that is currently processed
1102 AtCommandContext
* gsmd_modem_get_current_at_command (ModemInterface
*modem
,
1103 InterfaceType interface
)
1105 return gsmd_modem_get_current_at_command_index(modem
,
1106 gsmd_modem_get_interface_device_index(modem
,
1111 * @brief Send AT command to front of the queue
1113 * Diffrent from modem_add_command, forces command to be the first in
1116 * @param modem modem device struct pointer
1117 * @param at AT command to send
1118 * @param interface which interface's queue is this command forced to
1121 void gsmd_modem_send_command_force_next (Modem
*modem
,
1122 AtCommandContext
*at
,
1123 InterfaceType interface
)
1128 SerialDevice
*device
= gsmd_modem_get_serial_device( modem
, interface
);
1132 AtCommandContext
*current_at
= g_queue_pop_head ( device
->commandQueue
);
1133 g_queue_push_tail ( device
->commandQueue
, at
);
1136 g_queue_push_head (device
->commandQueue
, current_at
);
1143 * @brief Adds an modem alive test command (AT) or soft reset (ATZ) to the front
1144 * of the queue ignoring uncancellable commands and processes it
1146 * @param modem_if pointer to modem device struct
1147 * @param reset if TRUE, send ATZ instead of AT
1149 void gsmd_modem_post_alive_test (ModemInterface
*modem_if
, gboolean reset
)
1151 g_debug("%s",__func__
);
1153 Modem
*modem
= (Modem
*)modem_if
->priv
;
1155 g_assert(modem
->serial_devices
);
1156 SerialDevice
*device
= gsmd_modem_get_serial_device( modem
, INTERFACE_GENERAL
);
1159 AtCommandContext
*at
= NULL
;
1162 g_assert(modem
->modem_if
->status
< MODEM_READY
);
1163 at
= gsmd_at_command_context_new_from_id(modem
->modem_if
,
1173 at
= gsmd_at_command_context_new_from_id(modem
->modem_if
,
1181 g_queue_push_head (device
->commandQueue
, at
);
1182 gsmd_modem_process_next_command(modem
,INTERFACE_GENERAL
);
1189 * @brief Add an AT command to command queue
1191 * @param modem pointer to modem device struct
1192 * @param at custom at command to add
1193 * @param interface interface to post the command to
1194 * @param cancel should we try to cancel the current command and
1195 * place this command first (or second if current command can't
1196 * be cancelled) in queue.
1197 * @return TRUE if command was posted properly
1200 gboolean
gsmd_modem_post_at_command_internal ( ModemInterface
*modem
,
1201 AtCommandContext
*at
,
1202 InterfaceType interface
,
1207 gsmd_utils_print_data(__func__
,"command: ",at
->command
->command
);
1208 Modem
*modem_priv
= (Modem
*)modem
->priv
;
1209 if ( !modem_priv
->serial_devices
)
1211 //If serial ports aren't initialized then initialize them
1212 gsmd_modem_init_serial_ports(modem_priv
);
1214 // modem is not ready so fail this request
1217 if (modem
->status
< MODEM_INITIALIZING
)
1219 gsmd_utils_print_data(__func__
,
1220 "Modem is uninitialized, unable to add command: ",
1221 at
->command
->command
);
1223 g_debug("%s : Unable to add command %s because modem is uninitialized",
1224 __func__,at->command->command);
1226 gsmd_utils_send_error(at
, GSMD_ERROR_RESET
, "Modem not ready yet");
1227 gsmd_at_command_context_free(at
);
1231 SerialDevice
*device
= gsmd_modem_get_serial_device( modem_priv
,
1236 g_warning("%s : improper device index",__func__
);
1239 AtCommandContext
*current_at
= gsmd_modem_get_current_at_command ( modem
,
1242 //If no commands in queue, insert this one and process the queue
1247 g_debug("%s : No commands in queue, no need to cancel",
1250 g_queue_push_tail (device
->commandQueue
, at
);
1251 gsmd_modem_process_next_command(modem_priv
,interface
);
1258 //if there are commands in the queue and we can cancel the first
1259 // one, break it (+++) and push ours first
1260 if (current_at
->command
->cancellable
)
1262 g_debug("%s : Cancelling current command",__func__
);
1263 //Remove timeout for the previous command
1264 if (current_at
->timeout_event_id
!= 0)
1266 g_debug("%s : Removing timeout id: %d",
1268 current_at
->timeout_event_id
);
1270 g_source_remove(current_at
->timeout_event_id
);
1273 g_queue_push_head (device
->commandQueue
, at
);
1274 gsmd_modem_serial_write_simple (modem
,
1278 //Process the new command
1279 gsmd_modem_process_next_command(modem_priv
,interface
);
1281 else //if the current command isn't cancellable,
1283 //push our new command second in line
1284 g_debug("%s : Current command can't be overridden, moving next in queue",
1286 g_queue_pop_head(device
->commandQueue
);
1287 g_queue_push_head(device
->commandQueue
, at
);
1288 g_queue_push_head(device
->commandQueue
,current_at
);
1295 g_queue_push_tail (device
->commandQueue
, at
);
1301 * @brief Add a custom AT command to command queue. Cancels the first
1302 * command if possible and tries to run this command as soon as possible.
1304 * @param modem pointer to modem device struct
1305 * @param at custom at command to add
1306 * @param interface interface to post the command to
1307 * @return result of gsmd_modem_post_at_command_internal
1309 gboolean
gsmd_modem_post_at_command_and_cancel (ModemInterface
*modem
,
1310 AtCommandContext
*at
,
1311 InterfaceType interface
)
1313 return gsmd_modem_post_at_command_internal(modem
, at
, interface
, TRUE
);
1317 * @brief Add an AT command to command queue
1319 * @param modem pointer to modem device struct
1320 * @param at custom at command to add
1321 * @param interface interface to post the command to
1322 * @return result of gsmd_modem_post_at_command_internal
1324 gboolean
gsmd_modem_post_at_command ( ModemInterface
*modem
,
1325 AtCommandContext
*at
,
1326 InterfaceType interface
)
1328 return gsmd_modem_post_at_command_internal(modem
, at
, interface
, FALSE
);
1333 * @brief Posts at command to the queue
1336 * @param modem pointer to modem interface
1337 * @param command_id id of the command to post
1338 * @param param parameter for the command
1339 * @param ipc_data ipc data
1340 * @param error_function error function to call incase an error is occurred
1341 * @param error_data data to pass with error_function call
1342 * @param interface interface to post the command to
1343 * @param handler_data if command creater wants to add data to at command
1344 * for the handler, it can create a new GHashTable and insert it there. If
1345 * no handler_data is specified then a new handler_data will be created
1348 gboolean
gsmd_modem_post_at_command_id ( ModemInterface
* modem
,
1349 AtCommandID command_id
,
1352 ErrorFunction error_function
,
1353 gpointer error_data
,
1354 InterfaceType interface
,
1355 GHashTable
*handler_data
)
1357 AtCommandContext
*at
= gsmd_at_command_context_new_from_id( modem
,
1364 return gsmd_modem_post_at_command (modem
, at
,interface
);
1369 * @brief Posts at command to the front of the queue if possible
1371 * This command will cancel current command if possible and place itself
1372 * to the front of the command queue (or second if first can't be cancelled)
1374 * @param modem pointer to modem interface
1375 * @param command_id id of the command to post
1376 * @param param parameter for the command
1377 * @param ipc_data ipc data
1378 * @param error_function error function to call incase an error is occurred
1379 * @param error_data data to pass with error_function call
1380 * @param interface interface to post the command to
1381 * @param handler_data if command creater wants to add data to at command
1382 * for the handler, it can create a new GHashTable and insert it there. If
1383 * no handler_data is specified then a new handler_data will be created
1386 gboolean
gsmd_modem_post_at_command_id_and_cancel ( ModemInterface
* modem
,
1387 AtCommandID command_id
,
1390 ErrorFunction error_function
,
1391 gpointer error_data
,
1392 InterfaceType interface
,
1393 GHashTable
*handler_data
)
1395 AtCommandContext
*at
= gsmd_at_command_context_new_from_id( modem
,
1402 return gsmd_modem_post_at_command_and_cancel (modem
, at
,interface
);
1410 * @brief Create new AT command context struct
1412 * @param atcmd at command to use
1413 * @param param parameter for the command
1414 * @param ipc_data ipc data
1415 * @param error_function error function to call incase an error is occurred
1416 * @param error_data data to pass with error_function call
1417 * @param handler_data if command creater wants to add data to at command
1418 * for the handler, it can create a new GHashTable and insert it there. If
1419 * no handler_data is specified then a new handler_data will be created
1421 * @return newly created at command context
1423 AtCommandContext
* gsmd_at_command_context_new (AtCommand
*atcmd
,
1426 GHashTable
*handler_data
,
1427 ErrorFunction error_function
,
1428 gpointer error_data
)
1430 AtCommandContext
*at
= NULL
;
1431 at
= g_slice_new0 (AtCommandContext
);
1434 g_warning ("Failed to create new AtCommandContext.\n");
1437 at
->command
= atcmd
;
1440 at
->command_param
= g_strdup(param
);
1441 at
->retry_counter
= atcmd
->retry
;
1442 at
->timeout_event_id
= 0;
1443 at
->ipc_data
= ipc_data
;
1444 at
->error_function
= error_function
;
1445 at
->error_data
= error_data
;
1447 at
->handler_data
= gsmd_utils_create_hash_table();
1449 at
->handler_data
= handler_data
;
1453 if ( at
->error_function
&& !at
->error_data
)
1455 g_warning("%s : AT command '%s' has error function but no error data!",
1456 __func__
, atcmd
->command
);
1464 * @brief Creates a new at command context from at command id
1466 * @param modem Modem whose commands to use
1467 * @param cmd_id command's id
1468 * @param param parameter for the command
1469 * @param ipc_data ipc data
1470 * @param error_function error function to call incase an error is occurred
1471 * @param error_data data to pass with error_function call
1472 * @param handler_data if command creater wants to add data to at command
1473 * for the handler, it can create a new GHashTable and insert it there. If
1474 * no handler_data is specified then a new handler_data will be created
1476 * @return newly created at command context
1478 AtCommandContext
* gsmd_at_command_context_new_from_id (ModemInterface
*modem
,
1482 ErrorFunction error_function
,
1483 gpointer error_data
,
1484 GHashTable
*handler_data
)
1486 Modem
*modem_priv
= (Modem
*)modem
->priv
;
1487 AtCommandContext
*at
= NULL
;
1488 AtCommand
*command
= (AtCommand
*) g_hash_table_lookup(modem_priv
->commands_table
,
1489 GINT_TO_POINTER(cmd_id
));
1492 at
= gsmd_at_command_context_new(command
,
1502 * @brief Free the AT command context struct
1504 * @param at The AT command context pointer
1506 void gsmd_at_command_context_free (AtCommandContext
* at
)
1508 if (at
== NULL
) return;
1509 if (at
->command_param
)
1510 g_free(at
->command_param
);
1512 if (at
->command
->free_function
)
1514 at
->command
->free_function(at
);
1516 if ( at
->handler_data
)
1518 g_hash_table_destroy(at
->handler_data
);
1520 g_slice_free (AtCommandContext
,at
);
1524 * @brief Function called after a command has been finished.
1526 * AtCommand will be removed from queue and freed.
1527 * If gsm modem failed to respond to command, AT command can be
1528 * sent to gsm modem to test weither it is still alive. This is
1529 * done when test_alive is TRUE.
1531 * @param modem pointer to the modem
1532 * @param interface device whose command to finish
1533 * @param test_alive should test alive command be sent
1535 static void gsmd_modem_finish_command (Modem
* modem
,
1536 InterfaceType interface
,
1537 gboolean test_alive
)
1539 /* g_debug("%s\n",__func__); */
1540 SerialDevice
*device
= gsmd_modem_get_serial_device( modem
, interface
);
1546 GQueue
*queue
= device
->commandQueue
;
1548 AtCommandContext
*at
= g_queue_pop_head (queue
);
1552 /* gsmd_utils_print_data(__func__, */
1553 /* "Removing command ", */
1554 /* at->command->command); */
1556 //g_debug("%s : %s",__func__,at->command->command);
1557 if (at
->timeout_event_id
!= 0)
1559 /* g_debug("%s : Removing timeout id: %d", __func__, at->timeout_event_id); */
1560 g_source_remove(at
->timeout_event_id
);
1562 gsmd_at_command_context_free (at
);
1566 g_debug("Got no next command to finish\n");
1568 // if command handler (e.g. some vendor command)
1569 // marked the modem not alive
1570 if ( modem
->modem_if
->status
== MODEM_RESET
)
1572 gsmd_modem_close_serial_ports(modem
);
1573 gsmd_modem_init_serial_ports(modem
);
1575 else if (test_alive
)
1577 g_debug("%s : testing that modem is alive",__func__
);
1578 gsmd_modem_post_alive_test(modem
->modem_if
, FALSE
);
1582 /* g_debug("%s : processing next command",__func__); */
1583 gsmd_modem_process_next_command(modem
,interface
);
1588 * @brief Function to be called when serial has finished writing current command.
1590 * This indicates that the command has been written and to stop handler from
1591 * reading previous command's data.
1593 * For example on some modem's AT+CPIN? responds with CPIN: READY\\r\\nOK\\r\\n,
1594 * for others it returns with just CPIN: READY\\r\\n
1595 * If AT+CPIN command's handler were to assume that it never replies with OK,
1596 * and there were ATD command in the queue after AT+CPIN?. This would
1597 * cause ATD's handler to handle AT+CPIN's OK as an indicator that a call
1598 * has been initiated. gsmd_modem_data_in checks at->write_complete before
1599 * allowing at's handler to handle the data to prevent these errors.
1601 * @param write write data associated witht the command
1602 * @param data pointer to at command context
1604 static void gsmd_modem_write_complete(WriteData
*write
, gpointer data
)
1606 g_debug("%s", __func__
);
1607 AtCommandContext
*at
= (AtCommandContext
*)data
;
1608 at
->write_complete
= TRUE
;
1612 * @brief Takes the next command from command queue and processes it
1614 * @param modem whose next command to process
1615 * @param interface which interface's next command to process
1617 static void gsmd_modem_process_next_command (Modem
* modem
, InterfaceType interface
)
1619 /* g_debug("%s: device: %d",__func__,interface); */
1620 AtCommandContext
*at
= gsmd_modem_get_current_at_command ( modem
->modem_if
,
1623 if (modem
->vendor
->command_prepare
)
1625 at
= modem
->vendor
->command_prepare(modem
->vendor
,modem
->modem_if
,at
);
1628 gsmd_utils_print_data(__func__
,
1629 "Running command_prepare AT command: ",
1630 at
->command
->command
);
1633 g_debug("%s : Running command_prepare AT command: '%s'",
1635 at->command->command);
1637 SerialDevice
*device
= gsmd_modem_get_serial_device(modem
, interface
);
1639 GQueue
*queue
= device
->commandQueue
;
1640 g_queue_push_head (queue
, at
);
1645 //Get current command again to allow vendor to insert their own command
1646 at
= gsmd_modem_get_current_at_command ( modem
->modem_if
,
1651 g_debug("%s : No commands in queue", __func__
);
1654 //Most commands require PIN code to be set
1655 if (at
->command
->required_state
> modem
->modem_if
->sim_status
)
1657 g_debug("%s : sim status: %d, command '%s' requires: %d",
1658 __func__
, modem
->modem_if
->sim_status
,
1659 at
->command
->command
, at
->command
->required_state
);
1660 if (at
->error_function
)
1662 gsmd_utils_send_error(at
,
1663 GSMD_ERROR_SIM_UNAUTHORIZED
,
1664 "SIM AUTHENTICATION ERROR");
1667 gsmd_modem_finish_command(modem
, interface
, FALSE
);
1671 AtCommandPrepare prepare
= at
->command
->prepare
;
1672 gboolean prepare_ok
= TRUE
;
1674 gsmd_utils_print_data(__func__
,
1675 "Processing command ",
1676 at
->command
->command
);
1679 modem
->is_timeout
= TRUE
;//set the timeout flag
1681 GString
*command
= g_string_new (at
->command
->command
);
1684 if (at
->command_param
)
1686 g_string_printf(command
,at
->command
->command
,
1694 prepare_ok
= (*prepare
)(modem
->modem_if
);
1696 // TODO handle failed prepare
1699 g_warning("%s: Prepare failed!", __func__
);
1700 gsmd_utils_send_error(at
,
1701 GSMD_ERROR_INTERNAL
,
1702 "COMMAND PREPARE FAILED");
1703 gsmd_modem_finish_command(modem
, interface
, FALSE
);
1707 WriteData
*data
= g_try_new0(WriteData
,1);
1709 data
->command
= g_strdup(command
->str
);
1710 g_string_free(command
,TRUE
);
1715 data
->timeout
= at
->command
->timeout
+ TIME_OUT_PADDING
;
1719 data
->timeoutid
= &at
->timeout_event_id
;
1720 data
->timeout_data
= gsmd_modem_get_serial_device(modem
,
1722 data
->timeout_function
= &gsmd_modem_timeout_handle
;
1723 data
->write_complete_data
= at
;
1724 data
->write_complete_function
= &gsmd_modem_write_complete
;
1725 if (!gsmd_modem_serial_queue_write (modem
->modem_if
, data
,interface
))
1727 g_warning("%s: Queue write failed!", __func__
);
1733 * @brief Initializes scanner for modem's input
1735 * @param modem whose scanner to initialize
1736 * @param str string to initialize scanner with
1739 void gsmd_modem_scanner_init (ModemInterface
*modem
, GString
*str
)
1741 GScanner
* scanner
= modem
->scanner
;
1742 g_scanner_input_text (scanner
, str
->str
, str
->len
);
1743 g_scanner_get_next_token (scanner
);
1744 g_scanner_peek_next_token (scanner
);
1748 gboolean
gsmd_modem_call_activity(gpointer data
)
1750 ModemInterface
*modem
= (ModemInterface
*)data
;
1751 g_debug("%s", __func__
);
1752 gsmd_modem_post_at_command_id (modem
,
1754 NULL
, NULL
, NULL
, NULL
,
1757 /* AtCommandContext *at = gsmd_at_command_context_new_from_id (modem, */
1758 /* CUR_CALLS_QUERY, */
1768 void gsmd_modem_monitor_call_activity(ModemInterface
*modem
)
1770 if ( modem
->no_call_monitoring_needed
)
1774 if (modem
->call_monitor_timer
!= 0)
1776 g_source_remove(modem
->call_monitor_timer
);
1778 modem
->call_monitor_timer
= g_timeout_add(1000,&gsmd_modem_call_activity
,modem
);
1782 * @brief Function to handle data read from serial port
1784 * Checks SerialData on which device received the data, then
1785 * checks which was the last command sent to that interface
1786 * and runs that commands handler. If the handler doesn't understand
1787 * data, then unsolicite handler is called. This function also retries
1788 * the command if necessary.
1790 * @param buffer data that has been read
1791 * @param data pointer to SerialData containing information on
1792 * what was read (buffer)
1794 void gsmd_modem_data_in (GString
*buffer
, gpointer data
)
1796 SerialDevice
*serial
= (SerialDevice
*)data
;
1797 Modem
*modem
= serial
->modem
;
1798 ModemInterface
*modem_if
= modem
->modem_if
;
1799 AtCommandHandlerStatus status
= AT_HANDLER_DONT_UNDERSTAND
;
1800 AtCommandHandler handler
= NULL
;
1801 AtCommandContext
*at
= NULL
;
1804 at
= gsmd_modem_get_current_at_command_index ( modem_if
, serial
->device_index
);
1805 if ( at
&& !at
->write_complete
)
1807 g_debug("%s : Got input, but current command has not been written.", __func__
);
1810 if (at
&& at
->command
)
1814 handler
= at
->handler
;
1816 else if ( at
->command
->handler
)
1818 handler
= at
->command
->handler
;
1822 handler
= &gsmd_utils_handler_ok
;
1825 GString
*debug_str
= g_string_new("");
1826 g_string_printf(debug_str
,"Received from port %d: ",serial
->device_index
);
1828 gsmd_utils_print_data(__func__
,
1831 g_string_free(debug_str
,TRUE
);
1833 if ( modem
->vendor
->data_in
)
1835 modem
->vendor
->data_in(modem_if
, at
, buffer
);
1837 gsmd_modem_scanner_init (modem_if
, buffer
);
1842 status
= (*handler
)(modem_if
, at
, buffer
);
1845 case AT_HANDLER_DONE
:
1846 case AT_HANDLER_DONE_ERROR
:
1847 //if handled then process next command if there is
1848 modem
->is_timeout
= FALSE
;
1849 gsmd_modem_finish_command(modem
,
1850 serial
->device_index
,
1853 case AT_HANDLER_ERROR
:
1854 modem
->is_timeout
= FALSE
;
1855 gsmd_modem_finish_command(modem
,
1856 serial
->device_index
,
1858 // run unsolicite because we don't know if the message
1859 // belonged to handler or not
1860 gsmd_modem_handler_unsolicite( modem_if
, NULL
, buffer
);
1862 case AT_HANDLER_NEED_MORE
:
1864 case AT_HANDLER_DONT_UNDERSTAND
:
1865 gsmd_modem_handler_unsolicite( modem_if
, NULL
, buffer
);
1867 case AT_HANDLER_RETRY
:
1868 gsmd_modem_retry_current_command( modem
,
1869 serial
->device_index
);
1876 if (gsmd_modem_handler_unsolicite( modem_if
, NULL
, buffer
) ==
1878 modem
->is_timeout
= FALSE
;
1890 * @brief Sms indicator parser, parses new sms's index
1892 * @param scanner whose data to parse
1895 gint
gsmd_modem_sms_indicator_parse (GScanner
* scanner
)
1897 //TODO reimplement without assuming that we'll always get proper values
1898 g_debug("%s",__func__
);
1899 //input: CMTI: "SM", 1
1901 if (scanner
->token
== SYMBOL_CMTI
)
1903 g_scanner_get_next_token (scanner
);// get ,
1904 g_scanner_get_next_token (scanner
);//get s
1905 g_scanner_get_next_token (scanner
);//get m
1906 g_scanner_get_next_token (scanner
);//get ,
1907 pos
= scanner
->value
.v_int
;
1908 //g_message("sms pos is %d\n",pos);
1915 * @brief Registers a new command for the modem
1917 * @param modem modem to register the new command to
1918 * @param command command to register
1920 void gsmd_modem_register_command (ModemInterface
*modem
,
1921 const AtCommand
*command
)
1923 Modem
*modem_priv
= (Modem
*)modem
->priv
;
1924 g_hash_table_insert(modem_priv
->commands_table
,
1925 GINT_TO_POINTER(command
->cmd_id
),
1930 * @brief Helper function to register serial trigger
1932 * @param modem pointer to modem interface
1933 * @param trigger_str trigger string
1934 * @param handler handler for received data that has the trigger string
1935 * @param handler_data user data for the handler
1936 * @param onetime is this a onetime trigger (discarded when trigged)
1938 * @param interface interface to apply the trigger to
1939 * @return newly created trigger. It is returned only so that it can
1940 * be deregistered with gsmd_serial_deregister_trigger
1942 Trigger
* gsmd_modem_serial_register_trigger(ModemInterface
*modem
,
1943 const gchar
*trigger_str
,
1944 SerialDataIn handler
,
1945 gpointer handler_data
,
1947 InterfaceType interface
)
1949 Modem
*modem_priv
= (Modem
*)modem
->priv
;
1950 SerialDevice
*device
= gsmd_modem_get_serial_device(modem_priv
, interface
);
1958 g_debug("%s : Using default handler/data", __func__
);
1959 handler
= &gsmd_modem_data_in
;
1960 handler_data
= device
;
1963 return gsmd_serial_register_trigger(device
->serial
,
1971 * @brief Queue a new write to serial port
1973 * @param modem pointer to modem interface
1974 * @param data writedata that contains timeout information
1975 * and the data to write to serial port
1976 * @param interface which interface to be used to write command
1977 * @return FALSE if write failed
1979 gboolean
gsmd_modem_serial_queue_write ( ModemInterface
*modem
,
1981 InterfaceType interface
)
1983 Modem
*modem_priv
= (Modem
*)modem
->priv
;
1984 SerialDevice
*device
= gsmd_modem_get_serial_device(modem_priv
, interface
);
1987 if ( !gsmd_serial_queue_write( device
->serial
, data
) )
1989 g_warning("%s : Error in serial.", __func__
);
1990 gsmd_modem_close_serial_ports(modem_priv
);
1996 g_warning("%s : Writing data to improper serial device %d",
1998 device
->device_index
);
2006 * @brief Writes data directly to serial port
2008 * @param modem pointer to modem interface
2009 * @param data writedata that contains timeout information
2010 * and the data to write to serial port
2011 * @param interface which interface to be used to write command
2012 * @return FALSE if write failed
2014 gboolean
gsmd_modem_serial_write ( ModemInterface
*modem
,
2016 InterfaceType interface
)
2018 Modem
*modem_priv
= (Modem
*)modem
->priv
;
2019 SerialDevice
*device
= gsmd_modem_get_serial_device(modem_priv
,
2024 if ( !gsmd_serial_write( device
->serial
, data
) )
2026 g_warning("%s : Error in serial.", __func__
);
2027 gsmd_modem_close_serial_ports(modem_priv
);
2033 g_warning("%s : Writing data to improper serial device %d",
2035 device
->device_index
);
2043 * @brief Write command (or data) directly to serial port
2045 * @param modem modem device struct pointer
2046 * @param command AT command (or data) to write
2047 * @param interface which interface to be used to write command
2049 gboolean
gsmd_modem_serial_write_simple ( ModemInterface
*modem
,
2050 const gchar
*command
,
2051 InterfaceType interface
)
2053 WriteData
*data
= g_try_new0(WriteData
,1);
2054 data
->command
= g_strdup(command
);
2055 data
->timeoutid
= NULL
;
2057 data
->timeout_data
= NULL
;
2058 data
->timeout_function
= NULL
;
2059 return gsmd_modem_serial_write(modem
,data
,interface
);
2063 * @brief Initializes modem
2065 * Calls all interface initializers aswell.
2067 * @param modem pointer to modem to initialize
2069 static void gsmd_modem_init (ModemInterface
* modem
)
2071 Modem
*modem_priv
= (Modem
*)modem
->priv
;
2073 modem_priv
->vendor
= g_new0(VendorInterface
, 1);
2074 gsmd_device_init (modem
);
2075 gsmd_pdp_init (modem
);
2076 gsmd_sim_init (modem
);
2077 gsmd_network_init (modem
);
2078 gsmd_call_init (modem
);
2079 gsmd_sms_init (modem
);
2084 * @brief Timeout handler
2086 * Fakes that modem has received TIME_OUT message and runs the
2087 * (timeouted) command's handler to handle that input. This allows
2088 * command handler's creator to perform actions before command is being
2089 * deleted. If handler doesn't return HANDLER_DONE or HANDLER_DONE_ERROR
2090 * then command's error function is called by this function.
2091 * Finally the command is removed.
2093 * @param data pointer to serialdata
2094 * @return always returns false
2096 static gboolean
gsmd_modem_timeout_handle (gpointer data
)
2098 SerialDevice
*serial
= (SerialDevice
*) data
;
2099 guint device_index
= serial
->device_index
;
2100 AtCommandHandlerStatus handled
= AT_HANDLER_DONT_UNDERSTAND
;
2101 Modem
* modem
= serial
->modem
;
2102 AtCommandHandler handler
;
2103 AtCommandContext
*at
= gsmd_modem_get_current_at_command_index ( modem
->modem_if
,
2108 g_warning("%s : No current command!",__func__
);
2111 g_debug("%s: timeout id: %d, userdata: %p",__func__
,at
->timeout_event_id
, data
);
2112 // Setting timeout_event_id to 0 as it is removed when we return FALSE here.
2113 at
->timeout_event_id
= 0;
2114 g_assert( at
->command
);
2115 handler
= at
->command
->handler
;
2117 g_debug("Timeout on command %s\n",at
->command
->command
);
2119 if (modem
->is_timeout
)
2121 modem
->is_timeout
= FALSE
;//clear the timeout flag
2123 //If it has a handler, test if it can handle TIME_OUT
2126 //copy TIME_OUT string to input buffer
2127 GString
*timeout_buffer
= g_string_new (TIME_OUT
) ;//
2128 gsmd_modem_scanner_init (modem
->modem_if
, timeout_buffer
);
2129 g_debug("Running command's handler for TIME_OUT");
2130 handled
= (*handler
)(modem
->modem_if
, at
, timeout_buffer
);
2131 g_string_free (timeout_buffer
, TRUE
);
2134 //if it couldn't handle it or didn't have a handler, let
2135 //unsolicite handler take care of it
2137 if (!handler
|| (handled
!= AT_HANDLER_DONE
&& handled
!= AT_HANDLER_DONE_ERROR
))
2139 gsmd_utils_send_error(at
,
2140 GSMD_ERROR_DEVICE_TIMEOUT
,
2145 gsmd_modem_finish_command(modem
,device_index
, TRUE
);
2150 /***********************end of service function********************************/
2154 * @brief Change network status and use ipc data if new commands are issued
2156 * This function will post current operator query command if network's new
2157 * status is registered. This is used by getstatus fso method.
2159 * @param modem pointer to modem struct
2160 * @param status new network status
2161 * @param ipc_data ipc data used to post new commands if necessary
2162 * @param error_function error function to call if error occurs
2163 * @param error_data data to be supplied to error function call
2165 void gsmd_modem_change_network_status_data(ModemInterface
*modem
,
2166 NetworkStatus status
,
2168 ErrorFunction error_function
,
2169 gpointer error_data
)
2171 //TODO check that these assumptions are sane
2172 /* Simplified assumptions for actions for new statuses
2173 NETWORK_UNREGISTERED -> clear provider name, send empty status signal
2174 NETWORK_REGISTERED -> ask provider name and signal strength
2175 NETWORK_BUSY -> send empty status signal
2176 NETWORK_DENIED -> send empty status signal
2177 NETWORK_UNKNOWN -> send empty status signal
2178 NETWORK_ROAMING -> ask provider name and signal strength
2181 GString
* message
= g_string_new ("");
2182 g_string_printf(message
, "%d",status
);
2186 gsmd_utils_table_insert_int(modem
->caches
[INTERFACE_NETWORK
],
2187 GSMD_MODEM_KEY_NETWORK_STATUS
,
2192 case NETWORK_UNREGISTERED
:
2194 case NETWORK_DENIED
:
2195 case NETWORK_UNKNOWN
:
2197 if (modem
->network
->provider_name
)
2199 g_string_free(modem
->network
->provider_name
,TRUE
);
2201 GHashTable
*status
= gsmd_utils_create_hash_table();
2202 gsmd_utils_table_insert_string(status
,"provider","");
2203 gsmd_utils_table_insert_string(status
,"registration",message
->str
);
2204 gsmd_utils_table_insert_int(status
,"strength",0);
2205 modem
->network
->provider_name
= g_string_new("");
2206 modem
->network_ipc
->status(modem
->network_ipc
,
2208 g_hash_table_destroy(status
);
2211 case NETWORK_ROAMING
:
2212 case NETWORK_REGISTERED
:
2213 gsmd_modem_post_at_command_id( modem
,
2227 g_string_free(message
,TRUE
);
2231 * @brief Change network status
2233 * @param modem modem interface pointer
2236 void gsmd_modem_change_network_status(ModemInterface
*modem
,
2237 NetworkStatus status
)
2239 gsmd_modem_change_network_status_data(modem
,status
,
2247 * @brief Handles network status (+CREG) messages
2249 * @param modem modem to apply network status
2250 * @param response string to handle
2253 void gsmd_modem_handle_network_status(ModemInterface
*modem
,
2256 GError
**error
= NULL
;
2257 GRegex
*regex
= g_regex_new ("\\+CREG:\\s(?<status>[0-5]),?(?<lac>\\d*),?(?<id>\\d*)",
2261 GMatchInfo
*match_info
;
2262 NetworkStatus status
= NETWORK_UNKNOWN
;
2263 gchar
*match
= NULL
;
2265 if (g_regex_match (regex
, response
->str
, 0, &match_info
))
2267 if (gsmd_utils_match_exists(match_info
,"status"))
2269 match
= g_match_info_fetch_named(match_info
,
2271 status
= g_ascii_digit_value(match
[0]);
2272 gsmd_modem_change_network_status(modem
,status
);
2277 g_match_info_free (match_info
);
2278 g_regex_unref (regex
);
2283 * @brief Handles clip messages
2284 * Creates a new call with unknown call id
2286 * @param modem modem whose clip to handle
2287 * @param response string with CLIP
2290 void gsmd_modem_handle_incoming_call(ModemInterface
*modem
,
2293 g_debug("%s",__func__
);
2295 +CLIP: "040123456789",128,"",128,"",0
2297 \+CLIP:\s"(\+?\w+)".*
2300 GError
**error
= NULL
;
2301 GRegex
*regex
= g_regex_new ("\\+CLIP:\\s(?<phone>\"\\+?\\w+\")",
2305 GMatchInfo
*match_info
;
2306 gchar
*match
= NULL
;
2309 if (g_regex_match (regex
, response
->str
, 0, &match_info
))
2311 if (gsmd_utils_match_exists(match_info
,"phone"))
2313 match
= g_match_info_fetch_named(match_info
,
2316 gchar
*number
= NULL
;
2317 if (g_str_equal(match
,"\"\""))
2318 number
= g_strdup("Unknown number");
2321 GString
*temp
= g_string_new(&match
[1]);
2322 g_string_erase(temp
,temp
->len
-1,1);
2323 number
= g_strdup(temp
->str
);
2324 g_string_free(temp
,TRUE
);
2327 g_debug("%s : incoming call from : %s",__func__
,number
);
2329 Call
*call
= gsmd_utils_find_call_number(modem
,number
);
2332 call
= gsmd_utils_new_call(modem
,
2334 "", //TODO type ignored
2337 gsmd_modem_monitor_call_activity(modem
);
2339 gsmd_utils_call_send_status(modem
,
2349 g_debug("Didn't understand +clip");
2352 g_match_info_free (match_info
);
2353 g_regex_unref (regex
);
2358 * @brief Finds first call with incoming status and sends call status signal
2359 * Should be called when ring message is received from gsm modem.
2361 * @param modem modem who sent ring message
2364 void gsmd_modem_handle_ring(ModemInterface
*modem
)
2366 Call
*call
= gsmd_utils_find_first_call_status(modem
,CALL_INCOMING
);
2369 gsmd_utils_call_send_status(modem
,
2376 * @brief Handles CCWA (call waiting) messages from modem
2378 * @param modem modem whose call waiting message to handle
2379 * @param response string with CCWA
2382 void gsmd_modem_handle_call_waiting(ModemInterface
*modem
,
2386 +CCWA: "0401234567",129,1,"",0
2391 GError
**error
= NULL
;
2392 GRegex
*regex
= g_regex_new ("\\+CCWA:\\s\"(?<phone>\\+?\\d+)\"",
2396 GMatchInfo
*match_info
;
2397 gchar
*match
= NULL
;
2399 if (g_regex_match (regex
, response
->str
, 0, &match_info
))
2401 if (gsmd_utils_match_exists(match_info
,"phone"))
2403 match
= g_match_info_fetch_named(match_info
,
2406 Call
*call
= gsmd_utils_find_call_number(modem
,match
);
2409 call
= gsmd_utils_new_call(modem
,
2411 "", //TODO type ignored
2416 gsmd_utils_call_send_status(modem
,
2425 g_debug("Didn't understand +ccwa");
2428 g_match_info_free (match_info
);
2429 g_regex_unref (regex
);
2433 * @brief Parses clcc line and applies information to modem's calls
2434 * Can also create new calls if necessary.
2436 * @param modem pointer to modem whose calls to modify
2437 * @param clcc line returned by clcc
2438 * @return handled call or NULL
2440 Call
* gsmd_modem_apply_current_call(ModemInterface
*modem
, const gchar
*clcc
)
2443 Test data with clip and ecam:
2444 +CLIP: "044123456",128,"",128,"",0
2450 +CLIP: "044123456",128,"",128,"",0
2453 +CLCC: 1,1,4,0,0,"044123456",128,""
2455 Test data with two calls
2456 +CLCC: 1,0,0,0,0,"+35840123456",145,""
2457 +CLCC: 2,1,5,0,0,"044654321",128,""
2461 In the first example #ECAM has call id 0
2462 but CLCC says call id is 1
2463 Call id can't be trusted to be call->vendor_id,
2464 but vendor_id _could_ be clcc's id -1
2466 \+CLCC:\s\d+,(\d),(\d),(\d),\d,"(\+?\d+)"
2469 static GRegex
*regex
= NULL
;
2472 regex
= g_regex_new ("\\+CLCC:\\s(?<index>\\d+),(?<direction>\\d),"
2473 "(?<state>\\d),(?<mode>\\d),\\d,\"(?<number>\\+?\\d+)\"",
2478 GMatchInfo
*match_info
;
2481 if (g_regex_match (regex
, clcc
, 0, &match_info
))
2483 if (gsmd_utils_match_exists(match_info
,"index"))
2485 gint index
= gsmd_utils_fetch_match_int(match_info
,
2488 gint state
= gsmd_utils_fetch_match_int(match_info
,
2491 gchar
*number
= g_match_info_fetch_named(match_info
,
2494 //phone number types might cause a problem if modem
2495 //automatically converts them to national/international
2496 //format. This would cause the call to not be found
2497 call
= gsmd_utils_find_call_number(modem
,number
);
2500 gsmd_utils_print_calls(modem
);
2501 call
= gsmd_utils_new_call(modem
,number
,"",CALL_IDLE
);
2503 if (call
->index
< 0)
2505 call
->index
= index
;
2507 else if (call
->index
!= index
)
2509 // TODO handle this?
2510 g_warning("%s : Number matches but index does not (%d != %d)",__func__
, call
->index
, index
);
2511 gsmd_utils_print_calls(modem
);
2517 call
->status
= CALL_CONNECTED
;
2520 call
->status
= CALL_HOLD
;
2524 call
->status
= CALL_CALLING
;
2528 call
->status
= CALL_INCOMING
;
2532 //Mode is currently ignored
2533 g_debug("%s: Got a call to/from %s with status %s",
2536 gsmd_utils_call_status_to_string(call
->status
));
2543 g_match_info_free (match_info
);
2549 * @brief Iterates all calls in current calls list in given table
2550 * and calls gsmd_modem_apply_current_call on each of them
2552 * @param modem modem who own's the calls to parse
2553 * @param table GHashtable containing pointer to current calls list under
2554 * GSMD_MODEM_KEY_CALL_STATUS_ARRAY key
2556 void gsmd_modem_current_calls_parse(ModemInterface
*modem
,GHashTable
*table
)
2561 GValue
*val
= g_hash_table_lookup(table
,
2562 GSMD_MODEM_KEY_CALL_STATUS_ARRAY
);
2564 GList
*calls
= NULL
;
2568 GList
*list
= g_value_get_pointer(val
);
2572 gchar
*line
= list
->data
;
2573 Call
*call
= gsmd_modem_apply_current_call(modem
,line
);
2576 calls
= g_list_append (calls
, call
);
2578 list
= g_list_next( list
);
2581 if (modem
->call_monitor_timer
!= 0)
2583 g_debug("%s : Checking calls", __func__
);
2584 gboolean need_activity_monitor
= FALSE
;
2585 GList
*list
= modem
->calls
;
2586 GList
*calls_to_remove
= NULL
;
2589 Call
*call
= (Call
*)list
->data
;
2591 gboolean found
= FALSE
;
2594 if (tmp
->data
== (gpointer
)call
)
2599 tmp
= g_list_next(tmp
);
2603 g_debug("%s : Call %d not anymore", __func__
, call
->id
);
2604 calls_to_remove
= g_list_append(calls_to_remove
, call
);
2606 else if ( call
->status
== CALL_INCOMING
)
2608 need_activity_monitor
= TRUE
;
2610 list
= g_list_next(list
);
2612 list
= calls_to_remove
;
2615 gsmd_utils_remove_call_direct(modem
,(Call
*)list
->data
,TRUE
);
2616 list
= g_list_next(list
);
2618 g_list_free(calls_to_remove
);
2619 if ( need_activity_monitor
)
2621 modem
->call_monitor_timer
= 0;
2622 gsmd_modem_monitor_call_activity (modem
);
2628 * @brief Free function for list current calls method
2629 * Frees current calls array from the at command
2631 * @param at at command context to free current calls array
2634 void gsmd_modem_current_calls_free(AtCommandContext
*at
)
2639 GValue
*val
= g_hash_table_lookup(at
->handler_data
,
2640 GSMD_MODEM_KEY_CALL_STATUS_ARRAY
);
2645 list
= g_value_get_pointer(val
);
2650 list
= g_list_next( list
);
2653 g_list_free(g_value_get_pointer(val
));
2657 * @brief Handler for a command to list current calls
2658 * Adds calls to a list and then updates call structs
2659 * within modem to match.
2661 * @param modem pointer to modem interface
2662 * @param at current at command's context
2663 * @param response message to handle
2664 * @return handler status
2667 AtCommandHandlerStatus
gsmd_modem_handler_current_calls(ModemInterface
*modem
,
2668 AtCommandContext
*at
,
2671 g_debug("%s",__func__
);
2672 GError
**error
= NULL
;
2673 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)",
2677 AtCommandHandlerStatus status
= AT_HANDLER_DONT_UNDERSTAND
;
2678 GMatchInfo
*match_info
;
2682 if (g_regex_match (regex
, response
->str
, 0, &match_info
))
2684 if (gsmd_utils_match_exists(match_info
,"index"))
2688 val
= g_hash_table_lookup(at
->handler_data
,
2689 GSMD_MODEM_KEY_CALL_STATUS_ARRAY
);
2691 list
= g_value_get_pointer(val
);
2693 list
= g_list_append(list
,g_strdup(response
->str
));
2695 gsmd_utils_table_insert_pointer(at
->handler_data
,
2696 GSMD_MODEM_KEY_CALL_STATUS_ARRAY
,
2700 status
= AT_HANDLER_NEED_MORE
;
2702 else if (gsmd_utils_match_exists(match_info
,"error"))
2704 gsmd_utils_send_error(at
,
2706 "FAILED TO READ CURRENT CALL LIST");
2707 status
= AT_HANDLER_DONE_ERROR
;
2709 else if (gsmd_utils_match_exists(match_info
,"timeout"))
2711 gsmd_utils_send_error(at
,
2712 GSMD_ERROR_DEVICE_TIMEOUT
,
2713 "TIMEOUT WHEN READING CURRENT CALL LIST");
2714 status
= AT_HANDLER_DONE_ERROR
;
2716 else if (gsmd_utils_match_exists(match_info
,"ok"))
2719 gsmd_modem_current_calls_parse(modem
,at
->handler_data
);
2722 status
= AT_HANDLER_DONE
;
2728 g_match_info_free (match_info
);
2729 g_regex_unref (regex
);
2737 * @brief Handler for command to test if modem is alive
2739 * @param modem pointer to modem interface
2740 * @param at current at command's context
2741 * @param response message to handle
2742 * @return handler status
2745 AtCommandHandlerStatus
gsmd_modem_handler_alive(ModemInterface
*modem
,
2746 AtCommandContext
*at
,
2749 g_debug("%s",__func__
);
2750 Modem
*modem_priv
= (Modem
*)modem
->priv
;
2751 GScanner
* scanner
= modem
->scanner
;
2753 //we've got a response, modem is alive. Start initializations
2754 if (scanner
->token
== SYMBOL_OK
)
2756 if (modem
->status
== MODEM_SERIAL_INIT
)
2758 modem
->status
= MODEM_INITIALIZING
;
2760 if ( modem_priv
->vendor
->init_at
)
2762 modem_priv
->vendor
->init_at (modem_priv
->vendor
);
2766 gsmd_modem_general_at_init(modem
);
2769 return AT_HANDLER_DONE
;
2772 //Modem didn't reply or replied with an error
2773 if (scanner
->token
== SYMBOL_TIME_OUT
||
2774 scanner
->token
== SYMBOL_ERROR
)
2776 modem
->status
= MODEM_UNINITIALIZED
;
2777 modem
->sim_status
= SIM_UNKNOWN
;
2779 //Ask vendor if it can deal with an unresponsive modem
2780 if (modem_priv
->vendor
->not_responding
&&
2781 modem_priv
->vendor
->not_responding(modem_priv
->vendor
))
2782 return AT_HANDLER_RETRY
;
2785 gsmd_modem_close_serial_ports(modem_priv
);
2786 return AT_HANDLER_DONE
;
2790 return AT_HANDLER_DONT_UNDERSTAND
;
2794 * @brief Handles unsolicited messages such as +CREG.
2796 * Unsolicite mesaage is an unexpected message or reply or a reply the
2797 * command's handler didn't understand.
2799 * @param modem pointer to modem interface
2800 * @param at current at command's context
2801 * @param response message to handle
2802 * @return handler status
2805 AtCommandHandlerStatus
gsmd_modem_handler_unsolicite (ModemInterface
*modem
,
2806 AtCommandContext
*at
,
2809 Modem
*modem_priv
= (Modem
*)modem
->priv
;
2810 GScanner
* scanner
= modem
->scanner
;
2812 g_debug("%s", __func__
);
2816 if (g_scanner_eof(scanner
))
2817 return AT_HANDLER_DONE
;
2819 //Let vendor override unsolicite messages first
2820 if (modem_priv
->vendor
->unsolicite_handler
) //if there is vendor handler
2823 AtCommandHandlerStatus status
;
2824 /* g_debug("%s: Running vendor_unsolicite_handler", __func__); */
2825 //if vendor handled it, then we dont need to handle it ourselves
2826 status
= modem_priv
->vendor
->unsolicite_handler (modem
, NULL
, response
);
2827 if ( status
!= AT_HANDLER_DONT_UNDERSTAND
)
2829 /* g_debug("%s: vendor_unsolicite_handler understood", __func__); */
2833 gsmd_modem_scanner_init (modem
, response
);
2837 g_debug("%s: Running our default handler", __func__
);
2839 switch (scanner
->token
)
2842 g_scanner_get_next_token (scanner
);
2843 switch (scanner
->token
)
2846 gsmd_modem_handle_call_waiting(modem
,response
);
2847 case SYMBOL_CLIP
://display the incoming call phoneNo
2848 gsmd_modem_handle_incoming_call(modem
,response
);
2850 case SYMBOL_CRING
://display +CRING: VOICE
2851 // don't handle RING, we use CLIP
2852 gsmd_modem_handle_ring(modem
);
2856 gsmd_modem_handle_network_status(modem
,response
);
2858 case SYMBOL_CMTI
://sms indicator
2859 g_debug("%s: CMTI", __func__
);
2860 sms_pos
= gsmd_modem_sms_indicator_parse (scanner
);
2861 if (sms_pos
> 0 && modem
->sim_ipc
->incoming_message
)
2863 modem
->sim_ipc
->incoming_message(modem
->sim_ipc
,
2870 g_warning ("Got unrecognized unsolicited symbol: %s\n",
2876 * NOTE! Handling NO CARRIER and BUSY have to be overridden in
2877 * vendor unsolicite handler if multiple concurrent calls are to be
2878 * implemented. By default we assume that only concurrent call
2879 * is possible and we remove the first call in both previously
2882 case SYMBOL_BUSY
://remote hangup the call
2883 g_debug("%s: BUSY", __func__
);
2884 call
= gsmd_utils_call_get_current(modem
);
2888 gsmd_utils_remove_call(modem
,call_id
, TRUE
);
2892 case SYMBOL_RING
://handled in CLIP
2897 g_scanner_get_next_token(scanner
);
2898 if (scanner
->token
== SYMBOL_CARRIER
)
2900 call
= gsmd_utils_call_get_current(modem
);
2906 gsmd_utils_remove_call(modem
,call_id
, TRUE
);
2911 g_scanner_unexp_token (scanner
,
2926 return AT_HANDLER_DONE
;
2928 /**********************End of Default handler**********************************/
2932 * @brief Re-excute current AT command at the tail of command queue
2934 * @param modem Modem device struct pointer
2935 * @param interface interface whose current command to retry
2937 void gsmd_modem_retry_current_command (Modem
* modem
, InterfaceType interface
)
2939 g_debug("%s: device: %d", __func__
,interface
);
2941 g_assert ( modem
->serial_devices
);
2942 AtCommandContext
*at
= gsmd_modem_get_current_at_command ( modem
->modem_if
,
2944 modem
->is_timeout
= FALSE
;
2947 //Remove old timeout
2948 if (at
->timeout_event_id
!= 0)
2950 g_debug("%s : Removing timeout id: %d", __func__
, at
->timeout_event_id
);
2951 g_source_remove(at
->timeout_event_id
);
2952 at
->timeout_event_id
= 0;
2956 if (at
->retry_counter
> 0)
2958 g_debug("Retrying command %s",at
->command
->command
);
2959 at
->retry_counter
--;
2960 gsmd_modem_process_next_command (modem
,interface
);
2964 g_debug("Finished retrying command %s",at
->command
->command
);
2965 gsmd_modem_finish_command(modem
,interface
,FALSE
);
2973 * @brief Finds all commands with specified command id in the command queue
2974 * and removes them. Doesn't properly cancel the command if it's currently
2975 * being processed (e.g. if it has already been sent to gsm modem)
2977 * @param modem modem whose commands to cancel
2978 * @param cmd_id id of the commands to cancel
2979 * @param interface which interface's commands to cancel
2980 * @return TRUE if atleast one command was cancelled
2982 gboolean
gsmd_modem_cancel_command_id(ModemInterface
*modem
,
2984 InterfaceType interface
)
2986 Modem
* modem_priv
= (Modem
*)modem
->priv
;
2987 SerialDevice
*device
= gsmd_modem_get_serial_device(modem_priv
, interface
);
2989 GQueue
* queue
= device
->commandQueue
;
2992 gboolean res
= FALSE
;
2994 gint len
= g_queue_get_length (queue
);
2996 AtCommandContext
* at
= NULL
;
2997 for (i
=0; i
< len
; i
++) //the tail should not be remove which is handling
2999 at
= (AtCommandContext
*) g_queue_peek_nth (queue
, i
);
3000 if ( at
->command
->cmd_id
== cmd_id
)
3002 //g_queue_remove (queue, (gpointer) at);
3003 list
= g_list_append (list
, at
);
3009 g_queue_remove (queue
, list
->data
);
3010 gsmd_at_command_context_free(list
->data
);
3011 list
= g_list_next (list
);
3017 * @brief Assigns device indices to each of gsmd2's interfaces
3019 * @param modem modem whose interface devices to set
3020 * @param indices a list of indices to set
3021 * @return TRUE if indices were properly assigned
3023 gboolean
gsmd_modem_assign_device_indices(ModemInterface
*modem
, int *indices
)
3026 int last_device
= -1;
3027 for (i
=0;i
<INTERFACE_LAST
;i
++)
3029 int dev
= indices
[i
];
3030 SerialDevice
*device
= gsmd_modem_get_serial_device_index((Modem
*)modem
->priv
,dev
);
3033 if ( last_device
< 0)
3037 g_warning("%s : Assigning device %d because device %d is not available",
3038 __func__
, last_device
, dev
);
3042 modem
->interface_devices
[i
]=dev
;
3049 * @brief Gets given interface's device index
3050 * Modem might have several serial devices, each interface
3051 * (CALL,SMS,SIM,NETWORK,...) is assigned to one of those devices.
3054 * @param modem modem whose interface to lookup
3055 * @param interface interface whose device to lookup
3056 * @return interface's device index
3058 guint
gsmd_modem_get_interface_device_index(ModemInterface
*modem
,
3059 InterfaceType interface
)
3062 return modem
->interface_devices
[interface
];
3066 * @brief Finds command with specified command id from commands_table
3068 * @param modem modem whose command to find
3069 * @param cmd_id command id to find
3070 * @return command's pointer or NULL if none found
3072 AtCommand
* gsmd_modem_get_command (ModemInterface
*modem
,
3075 Modem
*modem_priv
= (Modem
*)modem
->priv
;
3076 return (AtCommand
*)g_hash_table_lookup(modem_priv
->commands_table
,
3077 GINT_TO_POINTER(cmd_id
));
3081 * @brief Sets modem's state to RESET
3083 * @param modem modem to set
3085 void gsmd_modem_reset(ModemInterface
*modem
)
3087 g_debug("%s",__func__
);
3090 modem
->status
= MODEM_RESET
;