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.
33 #include "gsmd-error.h"
38 static void gsmd_sms_handler_read_free(AtCommandContext
*at
);
40 static gboolean
gsmd_sim_decoder_pdu (guchar
* src
,SmsParam
* pdu
);
43 AtCommandHandlerStatus
gsmd_sim_handler_query_pin_status (ModemInterface
*modem
,
48 AtCommandHandlerStatus
gsmd_sim_handler_query_imsi( ModemInterface
*modem
,
52 AtCommandHandlerStatus
gsmd_sim_handler_pin(ModemInterface
*modem
,
56 AtCommandHandlerStatus
gsmd_sim_handler_read (ModemInterface
*modem
,
60 AtCommandHandlerStatus
gsmd_sim_handler_delete(ModemInterface
*modem
,
65 AtCommandHandlerStatus
gsmd_sim_handler_query_service_center (ModemInterface
*modem
,
70 AtCommandHandlerStatus
gsmd_sim_handler_set_service_center (ModemInterface
*modem
,
75 AtCommandHandlerStatus
gsmd_sim_handler_get_subscriber_numbers (ModemInterface
*modem
,
80 AtCommandHandlerStatus
gsmd_sim_handler_list_messages (ModemInterface
*modem
,
85 AtCommandHandlerStatus
gsmd_sim_handler_send_message (ModemInterface
*modem
,
90 void gsmd_sim_list_messages_free (AtCommandContext
*at
);
94 /* void gsmd_sim_storage_spaces_free(AtCommandContext *at); */
96 /* AtCommandHandlerStatus gsmd_sim_handler_get_storage_spaces( */
97 /* ModemInterface *modem, */
98 /* AtCommandContext *at, */
99 /* GString *response); */
101 AtCommandHandlerStatus
gsmd_sim_handler_get_phonebook_status(
102 ModemInterface
*modem
,
103 AtCommandContext
*at
,
106 /* AtCommandHandlerStatus gsmd_sim_handler_set_default_storage_space( */
107 /* ModemInterface *modem, */
108 /* AtCommandContext *at, */
109 /* GString *response); */
111 AtCommandHandlerStatus
gsmd_sim_handler_store_entry(
112 ModemInterface
*modem
,
113 AtCommandContext
*at
,
116 AtCommandHandlerStatus
gsmd_sim_handler_delete_entry(
117 ModemInterface
*modem
,
118 AtCommandContext
*at
,
122 AtCommandHandlerStatus
gsmd_sim_handler_get_index_boundaries(
123 ModemInterface
*modem
,
124 AtCommandContext
*at
,
127 AtCommandHandlerStatus
gsmd_sim_handler_retrieve_entry(
128 ModemInterface
*modem
,
129 AtCommandContext
*at
,
133 static const AtCommand
137 { PIN_QUERY
, "AT+CPIN?\r\n", 20000,
139 gsmd_sim_handler_query_pin_status
, NULL
, SIM_UNKNOWN
, NULL
},
140 //Query subscriber numbers
141 { QUERY_SUBSCRIBER_NUMBERS
, "AT+CNUM\r\n", 20000,
143 gsmd_sim_handler_get_subscriber_numbers
, NULL
, SIM_UNKNOWN
, NULL
},
146 { PIN_SETUP
, "AT+CPIN=\"%s\"\r\n", 20000,
148 gsmd_sim_handler_pin
, NULL
, SIM_UNKNOWN
, NULL
},
151 { PIN_CHANGE
, "AT+CPIN=%s\r\n", 20000,
153 gsmd_sim_handler_pin
, NULL
, SIM_UNKNOWN
, NULL
},
156 { PUK_SETUP
, "AT+CPIN=%s\r\n", 20000,
158 gsmd_sim_handler_pin
, NULL
, SIM_UNKNOWN
, NULL
},
161 { IMSI_QUERY
, "AT+CIMI\r\n", 5000,
163 gsmd_sim_handler_query_imsi
, NULL
, SIM_READY
},
165 { SMS_READ
, "AT+CMGR=%s\r\n", 5000,
167 gsmd_sim_handler_read
, NULL
, SIM_READY
, gsmd_sms_handler_read_free
},
170 { SMS_DELETE
, "AT+CMGD=%s\r\n", 5000,
172 gsmd_sim_handler_delete
, NULL
, SIM_READY
, NULL
},
174 //Query sms service center
175 { SMS_CENTER_QUERY
, "AT+CSCA?\r\n", 20000,
177 gsmd_sim_handler_query_service_center
, NULL
, SIM_READY
, NULL
},
179 //Set sms service center
180 { SMS_SET_CENTER
, "AT+CSCA=%s\r\n", 20000,
182 gsmd_sim_handler_set_service_center
, NULL
, SIM_READY
, NULL
},
185 { SMS_LIST
, "AT+CMGL=%s\r\n", 30000,
186 FALSE
, 0, gsmd_sim_handler_list_messages
,
187 NULL
, SIM_READY
,gsmd_sim_list_messages_free
},
189 //Send message from storage
190 { SIM_SEND
, "AT+CMSS=%s\r\n", 30000,
191 FALSE
, 0, gsmd_sim_handler_send_message
,
192 NULL
, SIM_READY
,NULL
},
194 //Get available storage space
195 /* { PHONEBOOK_SPACES_QUERY, "AT+CPBS=?\r\n", 100, */
197 /* gsmd_sim_handler_get_storage_spaces, NULL, SIM_READY, */
198 /* gsmd_sim_storage_spaces_free}, */
200 //Get current storage space status
201 { PHONEBOOK_STATUS_QUERY
, "AT+CPBS?\r\n", 100,
203 gsmd_sim_handler_get_phonebook_status
, NULL
, SIM_READY
,
207 /* { PHONEBOOK_SPACE_SET, "AT+CPBS=%s\r\n", 100, */
209 /* gsmd_sim_handler_set_default_storage_space, NULL, SIM_READY, */
212 //Get storage item's index boundaries
213 { PHONEBOOK_GET_INDEX_BOUNDARIES
, "AT+CPBR=?\r\n", 100,
215 gsmd_sim_handler_get_index_boundaries
, NULL
, SIM_READY
, NULL
},
217 //Get entry from storage
218 { PHONEBOOK_ENTRY_GET
, "AT+CPBR=%s\r\n", 100,
220 gsmd_sim_handler_retrieve_entry
, NULL
, SIM_READY
, NULL
},
223 { PHONEBOOK_ENTRY_SET
, "AT+CPBW=%s\r\n", 100,
225 gsmd_sim_handler_store_entry
, NULL
, SIM_READY
, NULL
},
227 //Delete storage entry
228 { PHONEBOOK_ENTRY_DELETE
, "AT+CPBW=%s\r\n", 100,
230 gsmd_sim_handler_delete_entry
, NULL
, SIM_READY
, NULL
},
232 { 0, NULL
, 100, TRUE
, 1,
233 NULL
, NULL
, SIM_UNKNOWN
},
235 }, *sim_command_p
= sim_commands
;
237 static const SymbolTable
239 { "SIM", SYMBOL_SIM
, },
241 }, *sim_symbol_p
= sim_symbols
;
242 void gsmd_sim_init_at_handler(ModemInterface
* modem
)
244 g_debug("%s", __func__
);
246 while (sim_symbol_p
->symbol_name
) {
247 g_scanner_add_symbol (modem
->scanner
, sim_symbol_p
->symbol_name
,
248 GINT_TO_POINTER(sim_symbol_p
->symbol_token
));
251 while (sim_command_p
->command
) {
252 gsmd_modem_register_command (modem
,sim_command_p
);
257 * @brief Changes auth (pin) status, sends auth_status signal if
258 * status was changed.
260 * @param modem modem whose auth status to change
261 * @param status new pin status
262 * @param send_reply should reply to get_auth_status ipc method
265 void gsmd_sim_change_auth_status( ModemInterface
*modem
,
268 const gchar
*message
,
271 if ( status
!= modem
->sim_status
) {
272 g_debug("Changing auth status from %d to %d.",modem
->sim_status
, status
);
276 gsmd_utils_table_insert_string(modem
->caches
[INTERFACE_SIM
],
277 GSMD_SIM_KEY_AUTH_STATUS
,
282 //Send a reply to get auth_status ipc method if necessary
283 if (send_reply
&& modem
->sim_ipc
->get_auth_status_reply
&& ipc_data
)
284 modem
->sim_ipc
->get_auth_status_reply(modem
->sim_ipc
,
288 //If sim status has changed, send a signal
289 if (modem
->sim_ipc
->auth_status
&& status
!= modem
->sim_status
) {
290 modem
->sim_ipc
->auth_status(modem
->sim_ipc
,
294 //finally change modem's sim status
295 gsmd_modem_change_sim_status(modem
,status
);
301 * Sends a reply to all pin related ipc method calls
303 * @param modem modem pointer
304 * @param cmd_id command/method call id
306 void gsmd_sim_send_pin_reply(ModemInterface
*modem
, AtCommandContext
*at
)
308 switch (at
->command
->cmd_id
) {
310 modem
->sim_ipc
->send_auth_code_reply(modem
->sim_ipc
,at
->ipc_data
);
313 modem
->sim_ipc
->change_auth_code_reply(modem
->sim_ipc
,at
->ipc_data
);
316 modem
->sim_ipc
->unlock_reply(modem
->sim_ipc
,at
->ipc_data
);
321 void gsmd_sim_list_messages_free (AtCommandContext
*at
)
323 GValue
*val
= g_hash_table_lookup(at
->handler_data
,
324 GSMD_SIM_KEY_MESSAGE_LIST
);
325 GArray
*list
= g_value_get_pointer(val
);
327 g_array_free(list
,TRUE
);
330 static gboolean
gsmd_sim_handler_list_messages_remove_last(GHashTable
*table
)
332 g_debug("%s",__func__
);
333 GValue
*val
= g_hash_table_lookup(table
,GSMD_SIM_KEY_MESSAGE_LIST
);
337 GArray
*list
= g_value_get_pointer(val
);
342 g_array_remove_index(list
,list
->len
-1);
347 AtCommandHandlerStatus
gsmd_sim_handler_list_messages (ModemInterface
*modem
,
348 AtCommandContext
*at
,
363 AtCommandHandlerStatus status
= AT_HANDLER_DONT_UNDERSTAND
;
365 if( gsmd_utils_parse_cms_error(modem
, response
,&cms_code
) ) {
367 case CMS_ERROR_INVALID_MESSAGE_INDEX
: {
369 * At least on Neo 1973 this means that there
370 * are no message with given status
372 GValue
*val
= g_hash_table_lookup(at
->handler_data
,
373 GSMD_SIM_KEY_MESSAGE_LIST
);
374 modem
->sim_ipc
->list_messages_reply(modem
->sim_ipc
,
376 g_value_get_pointer(val
));
377 return AT_HANDLER_DONE
;
380 g_warning("%s : CMS ERROR: %d", __func__
, cms_code
);
381 gsmd_utils_send_error(at
,
383 "UNABLE TO LIST MESSAGES");
384 return AT_HANDLER_DONE_ERROR
;
387 GError
**error
= NULL
;
388 GRegex
*regex
= g_regex_new ("\\+CMGL:\\s(?<id>\\d+),.*|(?<error>ERROR)|(?<ok>OK)|(?<pdu>[0-9A-F]+)", 0, 0, error
);
390 GMatchInfo
*match_info
;
393 if (g_regex_match (regex
, response
->str
, 0, &match_info
)) {
397 if (gsmd_utils_match_exists(match_info
,"id")) {
398 gchar
*match
= g_match_info_fetch_named(match_info
,"id");
400 GValue
*val
= g_hash_table_lookup(at
->handler_data
,
401 GSMD_SIM_KEY_MESSAGE_LIST
);
403 gsmd_utils_send_error(at
,
405 "INVALID HANDLER DATA");
406 status
= AT_HANDLER_DONE_ERROR
;
409 GArray
*list
= g_value_get_pointer(val
);
410 gint id
= atoi(match
);
411 g_array_append_val(list
,id
);
414 status
= AT_HANDLER_NEED_MORE
;
417 if (gsmd_utils_match_exists(match_info
,"error")) {
418 gsmd_utils_send_error(at
,
420 "UNABLE TO LIST MESSAGES");
421 status
= AT_HANDLER_DONE_ERROR
;
422 } else if (gsmd_utils_match_exists(match_info
,"ok")) {
423 GValue
*val
= g_hash_table_lookup(at
->handler_data
,
424 GSMD_SIM_KEY_MESSAGE_LIST
);
426 gsmd_utils_send_error(at
,
428 "INVALID HANDLER DATA");
429 status
= AT_HANDLER_DONE_ERROR
;
431 modem
->sim_ipc
->list_messages_reply(modem
->sim_ipc
,
433 g_value_get_pointer(val
));
437 status
= AT_HANDLER_DONE
;
439 //Check pdu, if this pdu is from a multipart message, but it's
440 //not the first part, then remove it from the list
441 if (gsmd_utils_match_exists(match_info
,"pdu")) {
442 gchar
*match
= g_match_info_fetch_named(match_info
,"pdu");
443 SmsParam
*sms
= g_try_new0(SmsParam
,1);
444 if (gsmd_sim_decoder_pdu((guchar
*)match
,sms
)) {
445 if (sms
->multipart
&& sms
->multipart_index
!= 1)
446 gsmd_sim_handler_list_messages_remove_last(at
->handler_data
);
448 gsmd_sms_sms_param_free(sms
);
450 status
= AT_HANDLER_NEED_MORE
;
458 g_match_info_free (match_info
);
459 g_regex_unref (regex
);
466 AtCommandHandlerStatus
gsmd_sim_handler_send_message (ModemInterface
*modem
,
467 AtCommandContext
*at
,
470 g_debug("%s",__func__
);
472 AtCommandHandlerStatus status
= AT_HANDLER_DONT_UNDERSTAND
;
473 if (gsmd_utils_send_error_from_response(at
,
475 "UNKNOWN ERROR OCCURRED WHEN SENDING MESSAGE",
476 "TIMEOUT OCCURRED WHEN SENDING MESSAGE"))
477 return AT_HANDLER_DONE_ERROR
;
480 GError
**error
= NULL
;
481 GRegex
*regex
= g_regex_new ("\\+CMSS:\\s(?<id>\\d+)|(?<cms>\\+CMS\\sERROR).*|(?<ok>OK)", 0, 0, error
);
483 GMatchInfo
*match_info
;
486 if (g_regex_match (regex
, response
->str
, 0, &match_info
)) {
488 if (gsmd_utils_match_exists(match_info
,"id")) {
489 gsmd_utils_table_insert_int(at
->handler_data
,
490 GSMD_SIM_KEY_CMSS_ID
,
491 gsmd_utils_fetch_match_int(match_info
,
493 status
= AT_HANDLER_NEED_MORE
;
496 if (gsmd_utils_match_exists(match_info
,"ok")) {
497 GValue
*val
= g_hash_table_lookup(at
->handler_data
,GSMD_SIM_KEY_CMSS_ID
);
500 g_warning("%s : Invalid handler data. Didn't get CMSS id",
503 gsmd_utils_send_error(at
,
505 "INVALID HANDLER DATA");
506 status
= AT_HANDLER_DONE_ERROR
;
508 modem
->sim_ipc
->send_message_reply(modem
->sim_ipc
,at
->ipc_data
);
509 if (modem
->sms_ipc
->message_sent
) {
510 modem
->sms_ipc
->message_sent(modem
->sms_ipc
,TRUE
,NULL
);
512 status
= AT_HANDLER_DONE
;
516 if (gsmd_utils_match_exists(match_info
,"cms")) {
517 status
= gsmd_sms_process_sms_error_response (modem
,
525 g_match_info_free (match_info
);
526 g_regex_unref (regex
);
533 * @brief Handler to modems response from setupPin command
535 * @param modem modem whose response to handle
536 * @return true if responses were recognized
539 AtCommandHandlerStatus
gsmd_sim_handler_pin(ModemInterface
*modem
,
540 AtCommandContext
*at
,
544 AtCommandHandlerStatus ret
= AT_HANDLER_DONT_UNDERSTAND
;
546 GScanner
* scanner
= modem
->scanner
;
549 g_debug("gsmd_sim_handler_setup_pin %d", scanner
->token
);
551 g_debug("gsmd_sim_handler_setup_pin error - no scanner");
552 return AT_HANDLER_DONE
;
557 switch (scanner
->token
) {
559 gsmd_sim_send_pin_reply(modem
, at
);
560 gsmd_sim_change_auth_status(modem
,NULL
,SIM_READY
,"READY",FALSE
);
562 ret
= AT_HANDLER_DONE
;
565 gsmd_utils_send_error(at
,
567 "FAILED TO CHANGE AUTH CODE");
569 if (modem
->sim_status
== SIM_NEED_PUK
)
570 gsmd_sim_change_auth_status(modem
,NULL
,SIM_READY
,"READY",FALSE
);
573 /* What should be done on each status
574 SIM_UNKNOWN=0 -> we're still at unknown state
575 SIM_MISSING_SIM -> we still don't have a sim card
576 SIM_NEED_PIN -> pin was wrong, we still need pin
577 SIM_NEED_PUK -> puk code was wrong, we still need puk
578 SIM_READY -> we never needed any code so nothing changed
580 ret
= AT_HANDLER_DONE_ERROR
;
583 g_warning("%s : No match to setupPin handler", __func__
);
590 void gsmd_sim_cache_auth_status(ModemInterface
*modem
,
591 AtCommandContext
*at
,
593 const gchar
*message
)
595 g_debug("%s: status: %d, message: %s",__func__
,status
,message
);
596 gsmd_utils_table_insert_string(at
->handler_data
,GSMD_SIM_KEY_AUTH_MESSAGE
,message
);
597 gsmd_utils_table_insert_int(at
->handler_data
,GSMD_SIM_KEY_AUTH_STATUS
,status
);
601 * @brief Handler to modems response from queryPinStatus command
603 * @param modem modem whose response to handle
604 * @return true if responses were recognized
607 AtCommandHandlerStatus
gsmd_sim_handler_query_pin_status (ModemInterface
*modem
,
608 AtCommandContext
*at
,
611 g_debug("%s",__func__
);
612 GScanner
* scanner
= modem
->scanner
;
616 if (scanner
->token
== SYMBOL_OK
) {
618 GValue
*status
= g_hash_table_lookup(at
->handler_data
,GSMD_SIM_KEY_AUTH_STATUS
);
619 GValue
*message
= g_hash_table_lookup(at
->handler_data
,GSMD_SIM_KEY_AUTH_MESSAGE
);
621 if (!status
|| !message
) {
622 g_warning("%s : Invalid handler data. status: %p, message: %p",
626 gsmd_utils_send_error(at
,GSMD_ERROR_UNKNOWN
,"INVALID HANDLER DATA");
627 return AT_HANDLER_DONE_ERROR
;
630 gsmd_sim_change_auth_status(modem
,
632 g_value_get_int(status
),
633 g_value_get_string(message
),
636 return AT_HANDLER_DONE
;
639 if (gsmd_utils_send_error_from_response(at
,
641 "ERROR READING PIN STATUS",
642 "TIMEOUT READING PIN STATUS"))
643 return AT_HANDLER_DONE_ERROR
;
645 if (scanner
->token
!= '+') {
646 return AT_HANDLER_DONT_UNDERSTAND
;
649 g_scanner_get_next_token (scanner
);
650 switch (scanner
->token
) {
653 g_scanner_get_next_token (scanner
);
654 //g_scanner_get_next_token (scanner);
655 if (scanner
->token
== SYMBOL_ERROR
) {
656 g_scanner_peek_next_token(scanner
);
657 if (scanner
->next_token
== ':') {
658 g_scanner_get_next_token (scanner
);
659 g_scanner_get_next_token(scanner
);//arrive error value
660 if ( ERR_NO_SIM_CARD
== scanner
->value
.v_int
) {
661 gsmd_sim_change_auth_status(modem
,
667 gsmd_sim_change_auth_status(modem
,
674 return AT_HANDLER_DONE
;
676 g_scanner_unexp_token (scanner
, ':', NULL
, "symbol",
681 g_scanner_unexp_token (scanner
, SYMBOL_ERROR
, NULL
, "symbol",
686 g_scanner_get_next_token (scanner
);//get ':'
687 g_scanner_get_next_token (scanner
);
688 if (scanner
->token
== SYMBOL_READY
) {
689 gsmd_sim_cache_auth_status(modem
,
695 return AT_HANDLER_NEED_MORE
;
697 } else if (scanner
->token
== SYMBOL_SIM
) {
699 g_scanner_get_next_token (scanner
);
700 g_scanner_peek_next_token(scanner
);
701 if (scanner
->token
== SYMBOL_PIN
) {
702 gsmd_sim_cache_auth_status(modem
,
708 } else if (scanner
->token
== SYMBOL_PUK
) {
709 gsmd_sim_cache_auth_status(modem
,
715 return AT_HANDLER_NEED_MORE
;
717 g_scanner_unexp_token (scanner
, SYMBOL_READY
, NULL
, "symbol",
722 g_warning("No match after getting + \n");
728 return AT_HANDLER_DONT_UNDERSTAND
;
734 * @brief AtCommand to setup pin value(s)
736 * @param modem modem whose response to handle
737 * @param pin_code pin code(s) to set
739 static void gsmd_sim_command_setup_pin (SIMInterface
*sim
,
741 const char* pin_code
)
743 ModemInterface
*modem
= (ModemInterface
*)sim
->priv
;
744 gsmd_modem_post_at_command_id( modem
,
748 (ErrorFunction
)modem
->sim_ipc
->send_auth_code_error
,
749 (gpointer
)modem
->sim_ipc
,
756 * @brief AtCommand to query pin status
758 * @param modem modem whose response to handle
760 static void gsmd_sim_command_query_pin_status (SIMInterface
*sim
,
763 ModemInterface
*modem
= (ModemInterface
*)sim
->priv
;
764 GValue
*val
= g_hash_table_lookup(modem
->caches
[INTERFACE_SIM
],GSMD_SIM_KEY_AUTH_STATUS
);
765 if (!modem
->no_cache
&& val
) {
766 modem
->sim_ipc
->get_auth_status_reply(modem
->sim_ipc
,
768 g_value_get_string(val
));
770 gsmd_modem_post_at_command_id( modem
,
774 (ErrorFunction
)modem
->sim_ipc
->get_auth_status_error
,
775 (gpointer
)modem
->sim_ipc
,
783 void gsmd_sim_command_unlock(SIMInterface
*sim
,
788 g_debug("%s",__func__
);
789 ModemInterface
*modem
= (ModemInterface
*)sim
->priv
;
790 GString
* param
= g_string_new ("");
791 g_string_printf(param
, "\"%s\",\"%s\"",puk
,new_pin
);
793 gsmd_modem_post_at_command_id( modem
,
797 (ErrorFunction
)modem
->sim_ipc
->unlock_error
,
798 (gpointer
)modem
->sim_ipc
,
801 g_string_free(param
,TRUE
);
805 void gsmd_sim_command_change_auth_code(SIMInterface
*sim
,
810 ModemInterface
*modem
= (ModemInterface
*)sim
->priv
;
811 GString
* param
= g_string_new ("");
812 g_string_printf(param
, "\"%s\",\"%s\"",old_pin
,new_pin
);
814 gsmd_modem_post_at_command_id( modem
,
818 (ErrorFunction
)modem
->sim_ipc
->change_auth_code_error
,
819 (gpointer
)modem
->sim_ipc
,
822 g_string_free(param
,TRUE
);
827 * Handler for reply to query_imsi command.
829 * @param modem pointer to modem struct
830 * @param response response sent by gsm modem
831 * @return AT_HANDLER_DONE when response is recognized
834 AtCommandHandlerStatus
gsmd_sim_handler_query_imsi( ModemInterface
*modem
,
835 AtCommandContext
*at
,
840 +CIMI: 244917070350971
845 AtCommandHandlerStatus status
= AT_HANDLER_DONT_UNDERSTAND
;
846 GError
*error
= NULL
;
847 GRegex
*regex
= g_regex_new ("^\\+CIMI:\\s(?<imsi>\\d+)$|^(?<imsi2>\\d+)$|^(?<error>ERROR)$|^(?<ok>OK)$",
850 g_debug("%s : '%s'", __func__
, error
->message
);
851 g_error_free( error
);
852 return AT_HANDLER_ERROR
;
854 GMatchInfo
*match_info
;
858 if (g_regex_match (regex
, response
->str
, 0, &match_info
)) {
859 if (gsmd_utils_match_exists(match_info
,"imsi")) {
860 gchar
*match
= g_match_info_fetch_named(match_info
,
862 g_debug("%s : imsi : %s", __func__
, match
);
864 gsmd_utils_table_insert_string(at
->handler_data
,
869 status
= AT_HANDLER_NEED_MORE
;
870 } else if (gsmd_utils_match_exists(match_info
,"imsi2")) {
871 gchar
*match
= g_match_info_fetch_named(match_info
,
874 g_debug("%s : imsi2 : %s", __func__
, match
);
875 gsmd_utils_table_insert_string(at
->handler_data
,
880 status
= AT_HANDLER_NEED_MORE
;
881 } else if (gsmd_utils_match_exists(match_info
,"error")) {
882 gsmd_utils_send_error(at
,
884 "FAILED TO READ IMSI");
885 status
= AT_HANDLER_DONE_ERROR
;
886 } else if (gsmd_utils_match_exists(match_info
,"ok")) {
887 val
= g_hash_table_lookup(at
->handler_data
,GSMD_SIM_KEY_IMSI
);
888 g_debug("%s : ok : %p", __func__
, val
);
890 status
= AT_HANDLER_DONE
;
892 // If we didn't get the response,
893 // then this OK is not for us
894 status
= AT_HANDLER_DONT_UNDERSTAND
;
900 g_match_info_free (match_info
);
901 g_regex_unref (regex
);
908 gboolean
gsmd_sim_command_get_sim_info_reply(ModemInterface
*modem
,
912 g_debug("%s", __func__
);
913 if( !modem
->no_cache
) {
914 GValue
*imsi
= g_hash_table_lookup(info
,GSMD_SIM_KEY_IMSI
);
916 gsmd_utils_table_insert_copy(modem
->caches
[INTERFACE_SIM
],GSMD_SIM_KEY_IMSI
,imsi
);
919 modem
->sim_ipc
->get_sim_info_reply( modem
->sim_ipc
,
925 AtCommandHandlerStatus
gsmd_sim_handler_get_sim_info( ModemInterface
*modem
,
926 AtCommandContext
*at
,
929 AtCommandHandlerStatus status
= AT_HANDLER_DONT_UNDERSTAND
;
930 switch (at
->command
->cmd_id
) {
932 g_debug("%s : IMSI_QUERY", __func__
);
933 status
= at
->command
->handler(modem
,at
,response
);
935 case AT_HANDLER_DONE_ERROR
:
936 case AT_HANDLER_ERROR
:
937 return AT_HANDLER_DONE_ERROR
;
939 case AT_HANDLER_DONE
:
940 if ( !g_hash_table_lookup(at
->handler_data
,GSMD_SIM_KEY_IMSI
) ) {
941 gsmd_utils_send_error(at
,GSMD_ERROR_UNKNOWN
,"UNABLE TO READ IMSI");
942 return AT_HANDLER_DONE_ERROR
;
944 gsmd_sim_command_get_sim_info_reply(modem
, at
->ipc_data
, at
->handler_data
);
945 /* gsmd_modem_post_at_command_id( modem, */
946 /* QUERY_SUBSCRIBER_NUMBERS, */
949 /* (ErrorFunction)modem->sim_ipc->get_subscriber_numbers_error, */
950 /* (gpointer)modem->sim_ipc, */
954 case AT_HANDLER_DONT_UNDERSTAND
:
955 case AT_HANDLER_NEED_MORE
:
956 case AT_HANDLER_RETRY
:
964 void gsmd_sim_command_get_sim_info(SIMInterface
*sim
,
967 ModemInterface
*modem
= (ModemInterface
*)sim
->priv
;
969 GValue
*subs_num
= NULL
;
970 GValue
*dialcode
= NULL
;
971 if (!modem
->no_cache
) {
972 imsi
= g_hash_table_lookup(modem
->caches
[INTERFACE_SIM
],GSMD_SIM_KEY_IMSI
);
973 subs_num
= g_hash_table_lookup(modem
->caches
[INTERFACE_SIM
],GSMD_SIM_KEY_SUBSCRIBER_NUMBER
);
974 dialcode
= g_hash_table_lookup(modem
->caches
[INTERFACE_SIM
],GSMD_SIM_KEY_DIAL_CODE
);
977 if (imsi
&& subs_num
&& dialcode
) {
978 g_debug("%s: sim info is cached",__func__
);
979 GHashTable
*info
= gsmd_utils_create_hash_table();
980 gsmd_utils_table_insert_copy(info
,GSMD_SIM_KEY_IMSI
,imsi
);
981 gsmd_utils_table_insert_copy(info
,GSMD_SIM_KEY_SUBSCRIBER_NUMBER
,subs_num
);
982 gsmd_utils_table_insert_copy(info
,GSMD_SIM_KEY_DIAL_CODE
, dialcode
);
983 modem
->sim_ipc
->get_sim_info_reply(modem
->sim_ipc
,
986 g_hash_table_destroy(info
);
988 AtCommandContext
*cmd
= NULL
;
989 cmd
= gsmd_at_command_context_new_from_id( modem
,
993 (ErrorFunction
)modem
->sim_ipc
->get_sim_info_error
,
994 (gpointer
)modem
->sim_ipc
,
996 cmd
->handler
= &gsmd_sim_handler_get_sim_info
;
997 gsmd_modem_post_at_command(modem
,cmd
,INTERFACE_SIM
);
1003 gboolean
gsmd_sim_command_get_phonebook_info_reply(ModemInterface
*modem
,
1007 g_debug("%s", __func__
);
1008 if( !modem
->no_cache
) {
1009 GValue
*slots
= g_hash_table_lookup(info
,GSMD_SIM_KEY_PHONEBOOK_SLOTS
);
1010 GValue
*used
= g_hash_table_lookup(info
,GSMD_SIM_KEY_PHONEBOOK_SLOTS_USED
);
1011 GValue
*number_len
= g_hash_table_lookup(info
,GSMD_SIM_KEY_PHONEBOOK_NUMBER_LEN
);
1012 GValue
*name_len
= g_hash_table_lookup(info
,GSMD_SIM_KEY_PHONEBOOK_NAME_LEN
);
1014 gsmd_utils_table_insert_copy(info
,GSMD_SIM_KEY_PHONEBOOK_SLOTS
,slots
);
1017 gsmd_utils_table_insert_copy(info
,GSMD_SIM_KEY_PHONEBOOK_SLOTS_USED
, used
);
1020 gsmd_utils_table_insert_copy(info
,GSMD_SIM_KEY_PHONEBOOK_NUMBER_LEN
,number_len
);
1023 gsmd_utils_table_insert_copy(info
,GSMD_SIM_KEY_PHONEBOOK_NAME_LEN
,name_len
);
1026 modem
->sim_ipc
->get_sim_info_reply( modem
->sim_ipc
,
1033 AtCommandHandlerStatus
gsmd_sim_handler_get_phonebook_info( ModemInterface
*modem
,
1034 AtCommandContext
*at
,
1037 AtCommandHandlerStatus status
= AT_HANDLER_DONT_UNDERSTAND
;
1038 AtCommandContext
*cmd
= NULL
;
1039 switch (at
->command
->cmd_id
) {
1040 case PHONEBOOK_GET_INDEX_BOUNDARIES
:
1041 g_debug("%s : PHONEBOOK_GET_INDEX_BOUNDARIES", __func__
);
1042 status
= at
->command
->handler(modem
,at
,response
);
1044 case AT_HANDLER_DONE_ERROR
:
1045 case AT_HANDLER_ERROR
:
1046 return AT_HANDLER_DONE_ERROR
;
1048 case AT_HANDLER_DONE
:
1049 cmd
= gsmd_at_command_context_new_from_id( modem
,
1050 PHONEBOOK_STATUS_QUERY
,
1053 (ErrorFunction
)modem
->sim_ipc
->get_phonebook_info_error
,
1054 (gpointer
)modem
->sim_ipc
,
1056 at
->handler_data
= NULL
;
1057 cmd
->handler
= &gsmd_sim_handler_get_phonebook_info
;
1058 gsmd_modem_post_at_command(modem
,cmd
,INTERFACE_SIM
);
1060 case AT_HANDLER_DONT_UNDERSTAND
:
1061 case AT_HANDLER_NEED_MORE
:
1062 case AT_HANDLER_RETRY
:
1066 case PHONEBOOK_STATUS_QUERY
:
1067 g_debug("%s : PHONEBOOK_STATUS_QUERY", __func__
);
1068 status
= at
->command
->handler(modem
,at
,response
);
1070 case AT_HANDLER_DONE_ERROR
:
1071 case AT_HANDLER_ERROR
:
1072 return AT_HANDLER_DONE_ERROR
;
1074 case AT_HANDLER_DONE
:
1075 gsmd_sim_command_get_phonebook_info_reply(modem
, at
->ipc_data
, at
->handler_data
);
1077 case AT_HANDLER_DONT_UNDERSTAND
:
1078 case AT_HANDLER_NEED_MORE
:
1079 case AT_HANDLER_RETRY
:
1087 * @brief Requests phonebook info
1089 * @param sim SIM interface
1090 * @param ipc_data IPC method context data
1092 void gsmd_sim_command_get_phonebook_info(SIMInterface
*sim
,
1095 ModemInterface
*modem
= (ModemInterface
*)sim
->priv
;
1096 GValue
*slots
= NULL
;
1097 GValue
*used
= NULL
;
1098 GValue
*number_len
= NULL
;
1099 GValue
*name_len
= NULL
;
1100 if (!modem
->no_cache
) {
1101 slots
= g_hash_table_lookup(modem
->caches
[INTERFACE_SIM
],GSMD_SIM_KEY_PHONEBOOK_SLOTS
);
1102 used
= g_hash_table_lookup(modem
->caches
[INTERFACE_SIM
],GSMD_SIM_KEY_PHONEBOOK_SLOTS_USED
);
1103 number_len
= g_hash_table_lookup(modem
->caches
[INTERFACE_SIM
],GSMD_SIM_KEY_PHONEBOOK_NUMBER_LEN
);
1104 name_len
= g_hash_table_lookup(modem
->caches
[INTERFACE_SIM
],GSMD_SIM_KEY_PHONEBOOK_NAME_LEN
);
1107 if (slots
&& used
&& number_len
&& name_len
) {
1108 g_debug("%s: info is cached",__func__
);
1109 GHashTable
*info
= gsmd_utils_create_hash_table();
1110 gsmd_utils_table_insert_copy(info
,GSMD_SIM_KEY_PHONEBOOK_SLOTS
,slots
);
1111 gsmd_utils_table_insert_copy(info
,GSMD_SIM_KEY_PHONEBOOK_SLOTS_USED
, used
);
1112 gsmd_utils_table_insert_copy(info
,GSMD_SIM_KEY_PHONEBOOK_NUMBER_LEN
,number_len
);
1113 gsmd_utils_table_insert_copy(info
,GSMD_SIM_KEY_PHONEBOOK_NAME_LEN
,name_len
);
1114 modem
->sim_ipc
->get_phonebook_info_reply(modem
->sim_ipc
,
1117 g_hash_table_destroy(info
);
1119 AtCommandContext
*cmd
= NULL
;
1120 cmd
= gsmd_at_command_context_new_from_id( modem
,
1121 PHONEBOOK_GET_INDEX_BOUNDARIES
,
1124 (ErrorFunction
)modem
->sim_ipc
->get_phonebook_info_error
,
1125 (gpointer
)modem
->sim_ipc
,
1127 cmd
->handler
= &gsmd_sim_handler_get_phonebook_info
;
1128 gsmd_modem_post_at_command(modem
,cmd
,INTERFACE_SIM
);
1134 * @brief Creates at command to set service center
1136 * @param modem modem to send command to
1137 * @param centerNo center number
1139 void gsmd_sim_command_set_service_center (SIMInterface
*sim
,
1141 const char* centerNo
)
1143 ModemInterface
*modem
= (ModemInterface
*)sim
->priv
;
1144 GString
* command
= g_string_new ("");
1146 if (g_strrstr (centerNo
, "+")) {
1147 //Internation format
1153 g_string_printf (command
, "%s,%d", centerNo
, format
);
1154 gsmd_modem_post_at_command_id( modem
,
1158 (ErrorFunction
)modem
->sim_ipc
->set_service_center_number_error
,
1159 (gpointer
)modem
->sim_ipc
,
1162 g_string_free(command
,TRUE
);
1166 * @brief Handler for replies sent by the gsm modem when a service center query
1169 * @param modem modem whose replies to interpret
1170 * @return true if replies were correct
1172 AtCommandHandlerStatus
gsmd_sim_handler_query_service_center (ModemInterface
*modem
,
1173 AtCommandContext
*at
,
1176 //input is +CSCA: "+393359609600", 145
1177 GScanner
* scanner
= modem
->scanner
;
1178 if (scanner
->token
== SYMBOL_OK
) {
1179 if (modem
->sim_ipc
->get_service_center_number_reply
) {
1180 GValue
*val
= g_hash_table_lookup(at
->handler_data
,GSMD_SIM_KEY_SERVICE_CENTER
);
1182 g_warning("%s : Invalid handler data. service center: %p",
1186 gsmd_utils_send_error(at
,
1188 "INVALID HANDLER DATA");
1190 modem
->sim_ipc
->get_service_center_number_reply(modem
->sim_ipc
,
1192 g_value_get_string(val
));
1195 return AT_HANDLER_DONE
;
1197 if (scanner
->token
== '+') {
1198 g_scanner_get_next_token (scanner
);
1199 if (scanner
->token
== SYMBOL_CSCA
) {
1200 g_scanner_get_next_token (scanner
);//get :
1201 if (scanner
->token
== ':') {
1202 g_scanner_get_next_token (scanner
);
1203 gsmd_utils_table_insert_string(at
->handler_data
,GSMD_SIM_KEY_SERVICE_CENTER
,scanner
->value
.v_string
);
1206 return AT_HANDLER_NEED_MORE
;
1210 return AT_HANDLER_DONT_UNDERSTAND
;
1215 * @brief Creates at command to query service center
1217 * @param modem modem to send command to
1219 void gsmd_sim_command_query_service_center (SIMInterface
*sim
,
1222 ModemInterface
*modem
= (ModemInterface
*)sim
->priv
;
1223 GValue
*val
= g_hash_table_lookup(modem
->caches
[INTERFACE_SIM
],GSMD_SIM_KEY_SERVICE_CENTER
);
1224 if (val
&& modem
->no_cache
) {
1225 modem
->sim_ipc
->get_service_center_number_reply(modem
->sim_ipc
,
1227 g_value_get_string(val
));
1229 gsmd_modem_post_at_command_id( modem
,
1233 (ErrorFunction
)modem
->sim_ipc
->get_service_center_number_error
,
1234 (gpointer
)modem
->sim_ipc
,
1243 * @brief Handler for replies sent by the gsm modem when a service center query
1246 * @param modem modem whose replies to interpret
1247 * @return true if replies were correct
1250 AtCommandHandlerStatus
gsmd_sim_handler_get_subscriber_numbers (ModemInterface
*modem
,
1251 AtCommandContext
*at
,
1262 return AT_HANDLER_DONE
;
1267 * @brief Handler for replies sent by the gsm modem when a set service centre
1270 * @param modem modem whose replies to interpret
1271 * @return true if replies were correct
1273 AtCommandHandlerStatus
gsmd_sim_handler_set_service_center (ModemInterface
*modem
,
1274 AtCommandContext
*at
,
1277 GScanner
* scanner
= modem
->scanner
;
1279 switch (scanner
->token
) {
1281 modem
->sim_ipc
->set_service_center_number_reply(modem
->sim_ipc
,
1283 return AT_HANDLER_DONE
;
1286 gsmd_utils_send_error(at
,
1288 "FAILED TO SET SERVICE CENTER");
1289 return AT_HANDLER_DONE_ERROR
;
1294 return AT_HANDLER_DONT_UNDERSTAND
;
1297 static void gsmd_sim_command_store_message (SIMInterface
*sim
,
1299 const gchar
*message
,
1300 const gchar
*number
)
1305 > 0011000C915348500496870000AA0AE8329BFD4697D9EC37
1308 g_debug("%s : Storing message %s to %s",__func__
,message
,number
);
1309 ModemInterface
*modem
= (ModemInterface
*)sim
->priv
;
1310 gsmd_sms_send_pdu (modem
,
1316 (ErrorFunction
)modem
->sim_ipc
->store_message_error
,
1324 * @brief 7 bit decode
1326 * @param src source message
1327 * @param dst destination message
1328 * @param src_length length of the source string
1329 * @return resulting destination's string
1331 static int gsmd_sim_decode_7bits(const guchar
*src
, guchar
* dst
, gint src_length
)
1333 //divide bytes into groups, each group has 7 bytes, decode it
1335 gint src_p
=0;//processed bytes in source gourp
1336 gint dst_p
=0;//processed bytes in dest group
1337 gint cur_index
=0;// char index of current processing group
1338 gint cur_left
=0;// the left bits from last byte
1339 while (src_p
< src_length
) {
1340 *dst
= ((*src
<< cur_index
) | cur_left
) & 0x7f;
1341 cur_left
= *src
>> (7 - cur_index
);
1345 if (cur_index
== 7) {
1354 g_assert(dst_p
< 512);
1361 * @brief Normalizes received telephonenumber.
1363 * Adds + to the beginning of
1364 * phone number if the phonenumber is in international format.
1366 * @param pdu sms parameters
1368 static void gsmd_sim_normalize_received_telnumber (SmsParam
* pdu
)
1371 gint len
= strlen ((const char*)pdu
->TPA
);
1372 if (pdu
->TOA
== 0x91) {
1373 //international format
1374 //add +before the number
1375 for (i
=len
; i
>0; i
--) {
1376 pdu
->TPA
[i
] = pdu
->TPA
[i
-1];
1379 pdu
->TPA
[len
+1] = '\0';
1389 //method call handler
1391 * @brief Handler for delete sms command's replies.
1393 * @param modem whose replies to handle
1394 * @return true if response was recognized
1396 AtCommandHandlerStatus
gsmd_sim_handler_delete(ModemInterface
*modem
,
1397 AtCommandContext
*at
,
1400 GScanner
* scanner
= modem
->scanner
;
1402 symbol
= scanner
->token
;
1403 if (scanner
->token
== SYMBOL_OK
) {
1404 if (modem
->sim_ipc
->delete_message_reply
) {
1405 modem
->sim_ipc
->delete_message_reply(modem
->sim_ipc
,at
->ipc_data
);
1407 return AT_HANDLER_DONE
;
1410 if (gsmd_utils_send_error_from_response(at
,
1412 "UNKNOWN ERROR OCCURRED WHEN DELETING A MESSAGE",
1413 "TIMOUT OCCURRED WHEN DELETING A MESSAGE")) {
1414 return AT_HANDLER_DONE_ERROR
;
1418 return AT_HANDLER_DONT_UNDERSTAND
;
1424 static gboolean
gsmd_sim_convert(guchar
** src
,
1430 if (strlen((char*)*src
) < src_length
+ move
)
1432 if (!gsmd_sms_string_to_bytes(*src
,dst
,src_length
,dst_length
))
1439 static gboolean
gsmd_sim_convert_number(guchar
** src
,
1445 if (!gsmd_sms_invert_number(*src
,dst
,src_length
,is_encode
))
1447 if (strlen((char*)*src
) < move
)
1453 static gboolean
sim_decoder_pdu_header( guchar
**src
, SmsParam
*pdu
)
1457 //the SMSC Number length
1458 if (!gsmd_sim_convert(src
,&tmp
,2,NULL
,4))
1464 if (!gsmd_sim_convert_number(src
,pdu
->SCA
,tmp
,FALSE
,tmp
))
1471 static gboolean
sim_decoder_pdu_type( guchar
**src
, SmsParam
*pdu
)
1475 if (!gsmd_sim_convert(src
,&tmp
,2,NULL
,2))
1478 //check if it is send or receive
1479 pdu
->storing
= (tmp
& 1);
1480 //check if it's multipart
1481 pdu
->multipart
= (tmp
&64);
1483 if (pdu
->storing
) //if encoding submitted message, ignore reference number
1490 static gboolean
sim_decoder_pdu_sender_num( guchar
**src
, SmsParam
*pdu
)
1496 //the real status does not match the spec, in spec the 7bits should be 1 to
1497 //include the reply path. but the real value is 04H
1498 //include reply info
1500 //length of sender number
1501 if (!gsmd_sim_convert(src
,&tmp
,2,NULL
,2))
1507 //length of sender number
1508 if (!gsmd_sim_convert(src
,&pdu
->TOA
,2,NULL
,2))
1511 if (!gsmd_sim_convert_number(src
,pdu
->TPA
,tmp
,FALSE
,tmp
))
1514 gsmd_sim_normalize_received_telnumber (pdu
);
1519 static gboolean
sim_decoder_pdu_protocol( guchar
**src
, SmsParam
*pdu
)
1521 return gsmd_sim_convert(src
,&pdu
->TP_PID
,2,NULL
,2);
1524 static gboolean
sim_decoder_pdu_coding_scheme( guchar
**src
, SmsParam
*pdu
)
1526 return gsmd_sim_convert(src
,&pdu
->TP_DCS
,2,NULL
,2);
1529 static gboolean
sim_decoder_pdu_validity_period( guchar
**src
, SmsParam
*pdu
)
1532 *src
+=2; //if submit format, skip validity period
1539 static gboolean
sim_decoder_pdu_timestamp( guchar
**src
, SmsParam
*pdu
)
1541 if (!pdu
->storing
) {
1542 if (!gsmd_sim_convert_number(src
,pdu
->TP_SCTS
,14,FALSE
,14))
1545 memset(pdu
->TP_SCTS
,0,14);
1552 static gboolean
sim_decoder_pdu_userdata( guchar
**src
, SmsParam
*pdu
)
1560 if (!gsmd_sim_convert(src
,&tmp
,2,NULL
,2))
1564 if (pdu
->multipart
) {
1565 if (!gsmd_sim_convert(src
,&div
,2,NULL
,6))
1567 if (!gsmd_sim_convert(src
,&pdu
->multipart_ref
,2,NULL
,2))
1569 if (!gsmd_sim_convert(src
,&pdu
->multipart_count
,2,NULL
,2))
1571 if (!gsmd_sim_convert(src
,&pdu
->multipart_index
,2,NULL
,2))
1578 //if header doesn't stop at the edge of septet, skip fill bytes
1579 if (pdu
->TP_DCS
== GSM_7BIT
&& (div
% 7) != 0) {
1580 div
+= (7-((div
)%7));
1582 //skip back userdata header
1586 pdu
->multipart_ref
= 0;
1587 pdu
->multipart_count
= 0;
1588 pdu
->multipart_index
= 0;
1591 if (pdu
->TP_DCS
== GSM_7BIT
) {
1593 len
= (tmp
- tmp
/8)*2;
1594 if (!gsmd_sim_convert(src
,buf
,len
,&dst_length
,0))
1597 gsmd_sim_decode_7bits (buf
, pdu
->TP_UD
, dst_length
); //TP-DU
1599 //If it's multipart, remove its header
1601 memmove(pdu
->TP_UD
,&pdu
->TP_UD
[div
],tmp
-div
);
1602 memset(&pdu
->TP_UD
[tmp
-div
],0,div
);
1606 pdu
->TP_UD_LEN
= dst_length
;
1609 } else if (pdu
->TP_DCS
== GSM_UCS2
) {
1612 if (!gsmd_sim_convert(src
,buf
,len
,&dst_length
,0))
1614 memset (pdu
->TP_UD
, 0, sizeof(pdu
->TP_UD
));
1615 memcpy (pdu
->TP_UD
, buf
, dst_length
);
1616 pdu
->TP_UD_LEN
= dst_length
;
1621 g_warning("Not supported format");
1628 static gboolean
sim_decoder_pdu_userdata_normalize( guchar
**src
, SmsParam
*pdu
)
1630 gchar code_buffer
[161];
1638 pdu
->number
= g_strdup((gchar
*)pdu
->TPA
);
1640 if (!pdu
->storing
) {
1641 pdu
->timestamp
= gsmd_utils_convert_to_timestamp((gchar
*)pdu
->TP_SCTS
);
1647 if (pdu
->TP_DCS
== GSM_7BIT
) {
1648 pdu
->message
= g_strdup((gchar
*)pdu
->TP_UD
);
1649 } else if (pdu
->TP_DCS
== GSM_UCS2
) {
1651 memset (code_buffer
, 0, sizeof(code_buffer
));
1653 * The intel CPU is little-endian, but the ucs2 in sms
1654 * is big-endian, so the usc_string byte order need to
1656 * For example chinese hello in utf16 is 4F60 597D
1657 * but usc_string is 604F 7D59
1658 * Following while() is to convert the byte order
1661 for (i
=0; i
< pdu
->TP_UD_LEN
; i
+= 2) {
1668 pdu
->message
= g_strdup(g_utf16_to_utf8 ((gunichar2
*)pdu
->TP_UD
,
1681 * @brief Pdu decoder
1683 * @param src string to decode
1684 * @param pdu sms parameters
1685 * @return true if pdu was succesfully decoded
1687 static gboolean
gsmd_sim_decoder_pdu (guchar
* src
,SmsParam
* pdu
)
1689 g_debug("%s : %s",__func__
,src
);
1692 if (!sim_decoder_pdu_header(&src
,pdu
))
1694 if (!sim_decoder_pdu_type(&src
,pdu
))
1696 if (!sim_decoder_pdu_sender_num(&src
,pdu
))
1698 if (!sim_decoder_pdu_protocol(&src
,pdu
))
1700 if (!sim_decoder_pdu_coding_scheme(&src
,pdu
))
1702 if (!sim_decoder_pdu_validity_period(&src
,pdu
))
1704 if (!sim_decoder_pdu_timestamp(&src
,pdu
))
1706 if (!sim_decoder_pdu_userdata(&src
,pdu
))
1708 return sim_decoder_pdu_userdata_normalize(&src
,pdu
);
1712 * @brief Removes the trailing \r\n from input stream
1714 * @param input input to modify
1715 * @return modified string
1717 static guchar
* gsmd_sim_get_sms_body (GString
* input
)
1719 gchar
*s
= g_strdup(input
->str
);
1721 g_string_truncate(input
, 0);
1722 g_string_append(input
,s
);
1724 return (guchar
*)input
->str
;
1729 static void gsmd_sim_command_list_messages (SIMInterface
*sim
,
1731 const gchar
*status
)
1733 ModemInterface
*modem
= (ModemInterface
*)sim
->priv
;
1734 g_debug("%s: Listing messages with status %s",__func__
,status
);
1735 gchar
*valid
[] = {"new","read","sending","sent","all"};
1737 GHashTable
*data
= gsmd_utils_create_hash_table();
1739 GArray
*list
= g_array_new(FALSE
,TRUE
,sizeof(int));
1740 gsmd_utils_table_insert_pointer(data
,GSMD_SIM_KEY_MESSAGE_LIST
,list
);
1741 GString
*param
= g_string_new("");
1745 if (g_str_equal(status
,valid
[i
])) {
1746 g_string_printf(param
,"%d",i
);
1747 gsmd_modem_post_at_command_id( modem
,
1751 (ErrorFunction
)modem
->sim_ipc
->list_messages_error
,
1752 (gpointer
)modem
->sim_ipc
,
1755 g_string_free(param
,TRUE
);
1760 g_string_free(param
,TRUE
);
1761 g_array_free(list
,TRUE
);
1762 g_hash_table_destroy(data
);
1763 GError
*error
= g_error_new(GSMD_ERROR
,
1765 "INVALID SMS STATUS");
1767 modem
->sim_ipc
->list_messages_error(ipc_data
,
1771 g_error_free(error
);
1775 * @brief Creates the at command to delete a sms message.
1777 * @param modem modem whose sms to delete
1778 * @param pos sms message's index
1780 static void gsmd_sim_command_delete (SIMInterface
*sim
,
1784 ModemInterface
*modem
= (ModemInterface
*)sim
->priv
;
1785 gchar
*pos_str
= g_strdup_printf ("%d", pos
);
1786 gsmd_modem_post_at_command_id( modem
,
1790 (ErrorFunction
)modem
->sim_ipc
->delete_message_error
,
1791 (gpointer
)modem
->sim_ipc
,
1798 * @brief Sends a sms from database
1800 * Fetches specified sms from the database, prepares it for sending and
1801 * calls gsmd_sms_command_send to actually send the message.
1803 * @param modem modem whose message to send
1804 * @param msgid id of the mssage to send
1806 void gsmd_sim_command_send_message (SIMInterface
*sim
,
1809 gboolean want_report
)
1811 //TODO want_report is currently ignored
1812 ModemInterface
*modem
= (ModemInterface
*)sim
->priv
;
1813 GString
* message
= g_string_new ("");
1814 g_string_printf(message
, "%d",index
);
1816 gsmd_modem_post_at_command_id( modem
,
1820 (ErrorFunction
)modem
->sim_ipc
->send_message_error
,
1821 (gpointer
)modem
->sim_ipc
,
1824 g_string_free(message
,TRUE
);
1828 * @brief Free function for retrieve_message method
1830 * @param at at command context which contents should be freed
1832 static void gsmd_sms_handler_read_free(AtCommandContext
*at
)
1834 g_debug("%s",__func__
);
1835 GValue
*val
= g_hash_table_lookup(at
->handler_data
,
1836 GSMD_SIM_KEY_PDU_MULTIPART_LIST
);
1841 GList
*list
= g_value_get_pointer(val
);
1847 multipart_sms
*sms
= iter
->data
;
1849 g_free(sms
->message
);
1852 iter
= g_list_next(iter
);
1855 g_hash_table_remove(at
->handler_data
,
1856 GSMD_SIM_KEY_PDU_MULTIPART_LIST
);
1864 * @brief Gets message part's contents from given index
1866 * Finds given index in glist containing multipart_sms and
1867 * returns it's message, NULL if not found.
1869 * @param list list containing multipart_sms
1870 * @param index index to find
1871 * @return message contents or null if not found
1873 gchar
*gsmd_sim_handler_read_assemble_get_index(GList
*list
,gint index
)
1876 multipart_sms
*sms
= list
->data
;
1877 if (sms
&& sms
->multipart_index
== index
)
1878 return sms
->message
;
1879 list
= g_list_next(list
);
1886 * @brief Gets the count of messages to assemble
1888 * Gets the first multipart_sms from glist and returns it's
1890 * @param list GList containing multipart_sms
1891 * @return messages in to assemble
1893 gint
gsmd_sim_handler_read_assemble_get_count(GList
*list
)
1898 multipart_sms
*sms
= list
->data
;
1902 return sms
->multipart_count
;
1907 * @brief Assemble multipart messages
1909 * Once all multipart messages are retrieved with AT+CMGL=4
1910 * this function assembles those messages together and sends
1912 * @param modem pointer to modem interface
1913 * @param at at command context
1914 * @return handler status
1916 AtCommandHandlerStatus
gsmd_sim_handler_read_assemble(ModemInterface
*modem
,
1917 AtCommandContext
*at
)
1919 GList
*list
= gsmd_utils_table_get_pointer(at
->handler_data
,
1920 GSMD_SIM_KEY_PDU_MULTIPART_LIST
,
1924 gsmd_utils_send_error(at
,
1926 "INVALID HANDLER DATA");
1927 return AT_HANDLER_DONE_ERROR
;
1930 gint count
= gsmd_sim_handler_read_assemble_get_count(list
);
1933 gsmd_utils_send_error(at
,
1935 "INVALID HANDLER DATA");
1936 return AT_HANDLER_DONE_ERROR
;
1939 GString
*result
= g_string_new("");
1942 for (i
=1;i
<=count
;i
++) {
1943 gchar
*part
= gsmd_sim_handler_read_assemble_get_index(list
,i
);
1945 g_string_append(result
,part
);
1947 g_string_append_printf(result
,"<Message %d/%d missing>",i
,count
);
1951 g_debug("%s : Assembled message is '%s'",__func__
,result
->str
);
1953 modem
->sim_ipc
->retrieve_message_reply(modem
->sim_ipc
,
1955 gsmd_utils_table_get_string(at
->handler_data
,
1956 GSMD_SIM_KEY_NUMBER
,
1959 gsmd_utils_table_get_int(at
->handler_data
,
1960 GSMD_SIM_KEY_TIMESTAMP
,
1963 g_string_free(result
,TRUE
);
1965 return AT_HANDLER_DONE
;
1970 * @brief Checks if given pdu is multipart and part of message we are assembling
1971 * and adds it to at->handler_data if it is.
1973 * @param modem pointer to modem interface
1974 * @param at at command context
1975 * @param pdu of the message to check
1976 * @return handler status
1978 AtCommandHandlerStatus
gsmd_sim_handler_read_check_pdu(ModemInterface
*modem
,
1979 AtCommandContext
*at
,
1982 g_debug("%s",__func__
);
1983 SmsParam
*sms
= g_try_new0(SmsParam
,1);
1985 if (!gsmd_sim_decoder_pdu((guchar
*)pdu
,sms
)) {
1986 gsmd_sms_sms_param_free(sms
);
1987 return AT_HANDLER_DONT_UNDERSTAND
;
1990 if (!sms
->multipart
) {
1991 gsmd_sms_sms_param_free(sms
);
1992 return AT_HANDLER_NEED_MORE
;
1996 gint ref
= gsmd_utils_table_get_int(at
->handler_data
,
1997 GSMD_SIM_KEY_PDU_MULTIPART_REF
,
2000 if (sms
->multipart_ref
!= ref
) {
2001 g_debug("%s : got multipart ref %d, wanted %d",
2006 gsmd_sms_sms_param_free(sms
);
2007 return AT_HANDLER_NEED_MORE
;
2012 GList
*list
= gsmd_utils_table_get_pointer(at
->handler_data
,
2013 GSMD_SIM_KEY_PDU_MULTIPART_LIST
,
2016 multipart_sms
*part
= g_try_new0(multipart_sms
,1);
2017 part
->multipart_count
= sms
->multipart_count
;
2018 part
->multipart_index
= sms
->multipart_index
;
2019 part
->multipart_ref
= sms
->multipart_ref
;
2020 part
->message
= g_strdup(sms
->message
);
2022 g_debug("%s : Got part %d/%d of multipart message : '%s'",
2024 part
->multipart_index
,
2025 part
->multipart_count
,
2028 list
= g_list_append(list
,part
);
2030 gsmd_utils_table_insert_pointer(at
->handler_data
,
2031 GSMD_SIM_KEY_PDU_MULTIPART_LIST
,
2033 gsmd_sms_sms_param_free(sms
);
2034 return AT_HANDLER_NEED_MORE
;
2038 * @brief Handler to find multipart message's each part
2040 * When retrieving a multipart message, all parts must be retrieved
2041 * so at+cmgl=4 is sent to modem to list all messages. This function
2042 * Finds all of the messages parts, assembles then and sends the
2045 * @param modem pointer to modem interface
2046 * @param at command context
2047 * @param response from modem
2048 * @return handler status
2050 AtCommandHandlerStatus
gsmd_sim_handler_read_list (ModemInterface
*modem
,
2051 AtCommandContext
*at
,
2054 g_debug("%s",__func__
);
2067 AtCommandHandlerStatus status
= AT_HANDLER_DONT_UNDERSTAND
;
2068 GError
**error
= NULL
;
2069 GRegex
*regex
= g_regex_new ("\\+CMGL:\\s(?<id>\\d+),.*|(?<error>ERROR)|(?<ok>OK)|(?<pdu>[0-9A-F]+)", 0, 0, error
);
2071 GMatchInfo
*match_info
;
2074 if (g_regex_match (regex
, response
->str
, 0, &match_info
)) {
2076 if (gsmd_utils_match_exists(match_info
,"id")) {
2077 status
= AT_HANDLER_NEED_MORE
;
2078 } else //If error occurs, then return error
2079 if (gsmd_utils_match_exists(match_info
,"error")) {
2080 gsmd_utils_send_error(at
,
2082 "UNABLE TO READ MESSAGE");
2083 status
= AT_HANDLER_DONE_ERROR
;
2084 //If we get ok, then we'll assemble the pieces
2086 } else if (gsmd_utils_match_exists(match_info
,"ok")) {
2087 status
= gsmd_sim_handler_read_assemble(modem
,at
);
2088 } else //when we have a pdu, then check it and add to
2090 if (gsmd_utils_match_exists(match_info
,"pdu")) {
2091 status
= gsmd_sim_handler_read_check_pdu(modem
,
2098 g_match_info_free (match_info
);
2099 g_regex_unref (regex
);
2106 * @brief Handler for replies sent by the gsm modem when a read command is sent.
2108 * First message's pdu is returned and decoded. If it isn't a multipart message
2109 * then message's contents are sent through ipc. Otherwise the message is
2110 * assembled from it's parts.
2112 * To assemble a message all it's parts have to be found. Message has a
2113 * reference to identify it from other multipart messages. This is stored
2114 * to at->handler_data. Then AT+CMGL=4
2115 * is sent to gsm modem to list all messages. Replies to them are handled
2116 * by gsmd_sim_handler_read_list which uses gsmd_sim_handler_read_check_pdu
2117 * to check if listed message has proper reference code. If it has proper
2118 * reference code then it is added to a list in at->handler_data.
2119 * once AT+CMGL=4 is done (OK is returned) then gsmd_sim_handler_read_assemble
2120 * is called to assemble the message from list within at->handler_data.
2121 * Once message is assembled, it is sent to ipc.
2124 * @param modem pointer to modem interface
2125 * @param at at command context
2126 * @param response modem's response
2127 * @return handler status
2129 AtCommandHandlerStatus
gsmd_sim_handler_read (ModemInterface
*modem
,
2130 AtCommandContext
*at
,
2133 g_debug("%s",__func__
);
2134 //Do we have pdu to parse?
2135 gboolean pdu_ready
= gsmd_utils_table_get_boolean(at
->handler_data
,
2136 GSMD_SIM_KEY_PDU_READY
,
2139 //Is it a multipart message? Then let gsmd_sim_handler_read_list
2140 //handle AT+CMGL=4's responses
2141 if (gsmd_utils_table_get_boolean(at
->handler_data
,
2142 GSMD_SIM_KEY_PDU_MULTIPART_LISTING
,
2144 return gsmd_sim_handler_read_list(modem
,at
,response
);
2147 GScanner
* scanner
= modem
->scanner
;
2149 GString
* input_data
;
2153 symbol
= scanner
->token
;
2155 //pdu_ready will be set when there is +CMGR
2159 SmsParam
*pdu
= g_try_new0(SmsParam
,1);
2161 input_data
= g_string_new (response
->str
);
2162 src
= gsmd_sim_get_sms_body (input_data
);
2164 if (!gsmd_sim_decoder_pdu (src
, pdu
)) {
2165 gsmd_sms_sms_param_free(pdu
);
2166 return AT_HANDLER_DONT_UNDERSTAND
;
2169 if (pdu
->multipart
) { //if it's multipart then only the first part
2170 //is a valid one from ipc's perspective
2171 //and others are invalid
2172 g_debug("%s : Got first sms of multipart message"
2176 if (pdu
->multipart_index
!= 1) {
2177 gsmd_utils_send_error(at
,
2178 GSMD_ERROR_UNKNOWN
, //TODO change better error code
2179 "INVALID MESSAGE INDEX");
2180 gsmd_sms_sms_param_free(pdu
);
2181 return AT_HANDLER_DONE_ERROR
;
2183 //mark handler_data that we are dealing with
2184 //multipart message and store messages reference
2186 gsmd_utils_table_insert_boolean(at
->handler_data
,
2187 GSMD_SIM_KEY_PDU_MULTIPART
,
2189 gsmd_utils_table_insert_int(at
->handler_data
,
2190 GSMD_SIM_KEY_PDU_MULTIPART_REF
,
2191 pdu
->multipart_ref
);
2195 //If it's normal (single) message, store the message
2196 gsmd_utils_table_insert_string(at
->handler_data
,
2197 GSMD_SIM_KEY_MESSAGE
,
2201 //and store phone number and timestamp
2202 gsmd_utils_table_insert_string(at
->handler_data
,
2203 GSMD_SIM_KEY_NUMBER
,
2206 gsmd_utils_table_insert_int(at
->handler_data
,
2207 GSMD_SIM_KEY_TIMESTAMP
,
2211 g_string_free (input_data
, TRUE
);
2213 gsmd_utils_table_insert_boolean(at
->handler_data
,
2214 GSMD_SIM_KEY_PDU_READY
,
2216 gsmd_sms_sms_param_free(pdu
);
2217 return AT_HANDLER_NEED_MORE
;
2222 //once we've got ok, check if the message is a multipart one
2223 //then we'll need to find the rest
2224 if (gsmd_utils_table_get_boolean(at
->handler_data
,
2225 GSMD_SIM_KEY_PDU_MULTIPART
,
2228 gsmd_utils_table_insert_boolean(at
->handler_data
,
2229 GSMD_SIM_KEY_PDU_MULTIPART_LISTING
,
2232 gsmd_modem_serial_write_simple( modem
,
2235 return AT_HANDLER_NEED_MORE
;
2238 GValue
*msg
= g_hash_table_lookup(at
->handler_data
,GSMD_SIM_KEY_MESSAGE
);
2239 GValue
*num
= g_hash_table_lookup(at
->handler_data
,GSMD_SIM_KEY_NUMBER
);
2240 GValue
*time
= g_hash_table_lookup(at
->handler_data
,GSMD_SIM_KEY_TIMESTAMP
);
2241 if (!msg
|| !num
|| !time
) {
2242 gsmd_utils_send_error(at
,
2244 "INVALID HANDLER DATA");
2245 g_warning("%s : Invalid handler data, number or message missing",__func__
);
2246 return AT_HANDLER_ERROR
;
2249 if (modem
->sim_ipc
->retrieve_message_reply
) {
2250 modem
->sim_ipc
->retrieve_message_reply(modem
->sim_ipc
,
2252 g_value_get_string(num
),
2253 g_value_get_string(msg
),
2254 g_value_get_int(time
));
2257 return AT_HANDLER_DONE
;
2259 g_scanner_get_next_token (scanner
);
2260 if (scanner
->token
== SYMBOL_CMS
) {
2261 g_warning ("read sms from simcard error\n");
2262 gsmd_utils_send_error(at
,
2264 "FAILED TO READ FROM SIM CARD");
2265 return AT_HANDLER_DONE_ERROR
;
2266 } else if (scanner
->token
== SYMBOL_CMGR
) {
2268 g_scanner_get_next_token (scanner
);//get :
2269 g_scanner_get_next_token (scanner
);//get status
2270 //sms_status = scanner->value.v_int;
2271 gsmd_utils_table_insert_boolean(at
->handler_data
,
2272 GSMD_SIM_KEY_PDU_READY
,
2276 return AT_HANDLER_NEED_MORE
;
2279 return AT_HANDLER_DONT_UNDERSTAND
;
2285 * @brief Creates the at command to read a sms message
2287 * @param modem modem where to read from
2288 * @param pos index of the message to read
2290 void gsmd_sim_command_read (SIMInterface
*sim
,
2294 gchar
*pos_str
= g_strdup_printf ("%d", pos
);
2295 ModemInterface
*modem
= (ModemInterface
*)sim
->priv
;
2296 GHashTable
*data
= gsmd_utils_create_hash_table();
2298 gsmd_utils_table_insert_boolean(data
,
2299 GSMD_SIM_KEY_PDU_READY
,
2302 gsmd_modem_post_at_command_id( modem
,
2306 (ErrorFunction
)modem
->sim_ipc
->retrieve_message_error
,
2307 (gpointer
)modem
->sim_ipc
,
2313 /* void gsmd_sim_free_storage_spaces_array(GHashTable *table) */
2316 /* GValue *val = g_hash_table_lookup(table,GSMD_SIM_KEY_STORAGE_SPACES); */
2318 /* GArray *array = g_value_get_pointer(val); */
2320 /* for (i=0;i<array->len;i++) { */
2321 /* g_string_free(g_array_index(array, */
2326 /* g_array_free(array,TRUE); */
2332 /* static void gsmd_sim_storage_spaces_free(AtCommandContext *at) */
2334 /* gsmd_sim_free_storage_spaces_array(at->handler_data); */
2337 /* AtCommandHandlerStatus */
2338 /* gsmd_sim_handler_get_storage_spaces(ModemInterface *modem, */
2339 /* AtCommandContext *at, */
2340 /* GString *response) */
2345 /* +CPBS: ("SM","FD","LD","MC","RC") */
2351 /* AtCommandHandlerStatus status = AT_HANDLER_DONT_UNDERSTAND; */
2352 /* GError *error = NULL; */
2353 /* GRegex *regex = g_regex_new ("(?<cpbs>\\+CPBS:\\s\\((\"\\w+\",?)+\\))|(?<error>ERROR)|(?<ok>OK)", 0, 0, NULL); */
2354 /* GMatchInfo *match_info; */
2356 /* if (g_regex_match (regex, response->str, 0, &match_info)) { */
2357 /* if (gsmd_utils_match_exists(match_info,"cpbs")) { */
2358 /* g_free(error); */
2359 /* g_match_info_free (match_info); */
2360 /* g_regex_unref (regex); */
2362 /* match_info = NULL; */
2365 /* regex = g_regex_new ("\"(?<id>\\w+)\"", 0, 0, NULL); */
2367 /* if (g_regex_match (regex, response->str, 0, &match_info)) { */
2368 /* GString *line = NULL; */
2371 /* GArray *array = g_array_new(FALSE, */
2373 /* sizeof(GString*)); */
2374 /* gchar *match = NULL; */
2376 /* while (g_match_info_matches (match_info)) { */
2377 /* match = g_match_info_fetch_named(match_info,"id"); */
2378 /* line = g_string_new(match); */
2379 /* g_free(match); */
2380 /* g_array_append_val(array,line); */
2381 /* g_match_info_next (match_info, NULL); */
2384 /* gsmd_utils_table_insert_pointer(at->handler_data, */
2385 /* GSMD_SIM_KEY_STORAGE_SPACES, */
2390 /* status = AT_HANDLER_NEED_MORE; */
2392 /* } else if (gsmd_utils_match_exists(match_info,"error")) { */
2393 /* gsmd_utils_send_error(at, */
2394 /* GSMD_ERROR_UNKNOWN, */
2395 /* "FAILED TO GET STORAGE SPACES"); */
2397 /* status = AT_HANDLER_DONE_ERROR; */
2398 /* } else if (gsmd_utils_match_exists(match_info,"ok")) { */
2399 /* GValue *val = g_hash_table_lookup(at->handler_data, */
2400 /* GSMD_SIM_KEY_STORAGE_SPACES); */
2403 /* g_warning("%s : Invalid handler data. storage spaces: %p", */
2407 /* gsmd_utils_send_error(at, */
2408 /* GSMD_ERROR_UNKNOWN, */
2409 /* "INVALID HANDLER DATA"); */
2410 /* status = AT_HANDLER_DONE_ERROR; */
2412 /* gsmd_sim_free_storage_spaces_array(modem->caches[INTERFACE_SIM]); */
2413 /* g_hash_table_remove(modem->caches[INTERFACE_SIM],GSMD_SIM_KEY_STORAGE_SPACES); */
2415 /* /\* modem->sim_ipc->get_storage_spaces_reply(modem->sim_ipc, *\/ */
2416 /* /\* at->ipc_data, *\/ */
2417 /* /\* g_value_get_pointer(val)); *\/ */
2418 /* gsmd_utils_table_insert_pointer(modem->caches[INTERFACE_SIM], */
2419 /* GSMD_SIM_KEY_STORAGE_SPACES, */
2420 /* g_value_get_pointer(val)); */
2421 /* g_hash_table_remove(at->handler_data,GSMD_SIM_KEY_STORAGE_SPACES); */
2422 /* status = AT_HANDLER_DONE; */
2429 /* g_free(error); */
2430 /* g_match_info_free (match_info); */
2431 /* g_regex_unref (regex); */
2434 /* return status; */
2438 /* void gsmd_sim_command_get_storage_spaces(SIMInterface *sim, */
2439 /* gpointer ipc_data) */
2441 /* ModemInterface *modem = (ModemInterface*)sim->priv; */
2442 /* GValue *val = g_hash_table_lookup(modem->caches[INTERFACE_SIM],GSMD_SIM_KEY_STORAGE_SPACES); */
2444 /* if (!modem->no_cache && val) { */
2445 /* /\* modem->sim_ipc->get_storage_spaces_reply(modem->sim_ipc, *\/ */
2446 /* /\* ipc_data, *\/ */
2447 /* /\* g_value_get_pointer(val)); *\/ */
2450 /* gsmd_modem_post_at_command_id( modem, */
2451 /* PHONEBOOK_SPACES_QUERY, */
2454 /* (ErrorFunction)modem->sim_ipc->get_storage_spaces_error, */
2455 /* (gpointer)modem->sim_ipc, */
2456 /* INTERFACE_SIM, */
2461 AtCommandHandlerStatus
gsmd_sim_handler_get_phonebook_status(ModemInterface
*modem
,
2462 AtCommandContext
*at
,
2472 \+CPBS:\s"(\w+)",\d+,\d+
2474 AtCommandHandlerStatus status
= AT_HANDLER_DONT_UNDERSTAND
;
2475 GError
*error
= NULL
;
2476 GRegex
*regex
= g_regex_new ("\\+CPBS:\\s\"(?<space>\\w+)\",(?<used>\\d+),(?<total>\\d+)|"
2477 "(?<error>ERROR)|(?<ok>OK)", 0, 0, &error
);
2478 GMatchInfo
*match_info
;
2481 if (g_regex_match (regex
, response
->str
, 0, &match_info
)) {
2482 if (gsmd_utils_match_exists(match_info
,"used")) {
2483 gchar
*match
= g_match_info_fetch_named(match_info
,"used");
2484 gint used
= atoi(match
);
2485 gsmd_utils_table_insert_int(at
->handler_data
,GSMD_SIM_KEY_PHONEBOOK_SLOTS_USED
,used
);
2488 status
= AT_HANDLER_NEED_MORE
;
2491 if (gsmd_utils_match_exists(match_info
,"error")) {
2492 gsmd_utils_send_error(at
,
2494 "FAILED TO GET DEFAULT PHONEBOOK STORAGE SPACE");
2495 status
= AT_HANDLER_DONE_ERROR
;
2498 if (gsmd_utils_match_exists(match_info
,"ok")) {
2499 GValue
*val
= g_hash_table_lookup(at
->handler_data
,
2500 GSMD_SIM_KEY_PHONEBOOK_SLOTS_USED
);
2502 g_warning("%s : Invalid handler data.", __func__
);
2504 gsmd_utils_send_error(at
,
2506 "INVALID HANDLER DATA");
2508 status
= AT_HANDLER_DONE
;
2514 g_error_free(error
);
2516 g_match_info_free (match_info
);
2517 g_regex_unref (regex
);
2524 /* AtCommandHandlerStatus gsmd_sim_handler_set_default_storage_space(ModemInterface *modem, */
2525 /* AtCommandContext *at, */
2526 /* GString *response) */
2528 /* AtCommandHandlerStatus status = AT_HANDLER_DONT_UNDERSTAND; */
2529 /* GError **error = NULL; */
2530 /* GRegex *regex = g_regex_new ("(?<error>ERROR)|(?<ok>OK)", 0, 0, error); */
2531 /* GMatchInfo *match_info; */
2534 /* if (g_regex_match (regex, response->str, 0, &match_info)) { */
2535 /* if (gsmd_utils_match_exists(match_info,"error")) { */
2536 /* gsmd_utils_send_error(at, */
2537 /* GSMD_ERROR_UNKNOWN, */
2538 /* "FAILED TO SET DEFAULT PHONEBOOK STORAGE SPACE"); */
2539 /* status = AT_HANDLER_DONE_ERROR; */
2542 /* if (gsmd_utils_match_exists(match_info,"ok")) { */
2543 /* //Since storage space changed, it's index boundaries */
2544 /* //might have changed aswell */
2545 /* gsmd_utils_table_insert_int(modem->caches[INTERFACE_SIM], */
2546 /* GSMD_SIM_KEY_LOWEST_INDEX, */
2549 /* gsmd_utils_table_insert_int(modem->caches[INTERFACE_SIM], */
2550 /* GSMD_SIM_KEY_HIGHEST_INDEX, */
2553 /* GValue *val = g_hash_table_lookup(at->handler_data,GSMD_SIM_KEY_DEFAULT_STORAGE_SPACE); */
2556 /* g_warning("%s : Invalid handler data. default storage space: %p", */
2560 /* gsmd_utils_send_error(at, */
2561 /* GSMD_ERROR_UNKNOWN, */
2562 /* "INVALID HANDLER DATA"); */
2565 /* gsmd_utils_table_insert_copy(modem->caches[INTERFACE_SIM], */
2566 /* GSMD_SIM_KEY_DEFAULT_STORAGE_SPACE, */
2569 /* modem->sim_ipc->set_default_storage_space_reply(modem->sim_ipc, */
2570 /* at->ipc_data); */
2572 /* status = AT_HANDLER_DONE; */
2577 /* g_free(error); */
2578 /* g_match_info_free (match_info); */
2579 /* g_regex_unref (regex); */
2582 /* return status; */
2586 /* void gsmd_sim_command_set_default_storage_space(SIMInterface *sim, */
2587 /* gpointer ipc_data, */
2588 /* const char *space) */
2590 /* ModemInterface *modem = (ModemInterface*)sim->priv; */
2592 /* GHashTable *data = gsmd_utils_create_hash_table(); */
2593 /* gsmd_utils_table_insert_string(data, */
2594 /* GSMD_SIM_KEY_DEFAULT_STORAGE_SPACE, */
2597 /* gsmd_modem_post_at_command_id( modem, */
2598 /* PHONEBOOK_SPACE_SET, */
2601 /* (ErrorFunction)modem->sim_ipc->set_default_storage_space_error, */
2602 /* (gpointer)modem->sim_ipc, */
2603 /* INTERFACE_SIM, */
2608 AtCommandHandlerStatus
gsmd_sim_handler_get_index_boundaries(
2609 ModemInterface
*modem
,
2610 AtCommandContext
*at
,
2616 +CPBR: (1-250),20,20
2620 Regular expression: \+CPBR:\s\((\d+)-(\d+)\)
2622 AtCommandHandlerStatus status
= AT_HANDLER_DONT_UNDERSTAND
;
2623 GError
*error
= NULL
;
2624 GRegex
*regex
= g_regex_new ("\\+CPBR:\\s\\((?<min>\\d+)-(?<max>\\d+)\\),(?<number_len>\\d+),(?<name_len>\\d+)|"
2625 "(?<error>ERROR)|(?<ok>OK)", 0, 0, &error
);
2626 GMatchInfo
*match_info
;
2627 gchar
*match
= NULL
;
2631 if (g_regex_match (regex
, response
->str
, 0, &match_info
)) {
2632 if (gsmd_utils_match_exists(match_info
,"min")) {
2633 match
= g_match_info_fetch_named(match_info
,"min");
2634 gint min
= atoi(match
);
2637 match
= g_match_info_fetch_named(match_info
,"max");
2638 gint max
= atoi(match
);
2639 gsmd_utils_table_insert_int(at
->handler_data
,GSMD_SIM_KEY_PHONEBOOK_SLOTS
, max
-min
+1);
2642 match
= g_match_info_fetch_named(match_info
,"number_len");
2643 gint number_len
= atoi(match
);
2644 gsmd_utils_table_insert_int(at
->handler_data
,GSMD_SIM_KEY_PHONEBOOK_NUMBER_LEN
, number_len
);
2647 match
= g_match_info_fetch_named(match_info
,"name_len");
2648 gint name_len
= atoi(match
);
2649 gsmd_utils_table_insert_int(at
->handler_data
,GSMD_SIM_KEY_PHONEBOOK_NAME_LEN
, name_len
);
2652 status
= AT_HANDLER_NEED_MORE
;
2653 } else if (gsmd_utils_match_exists(match_info
,"error")) {
2654 //TODO should empty string be sent as a reply instead?
2655 gsmd_utils_send_error(at
,
2657 "UNABLE TO READ PHONEBOOK INFO");
2658 status
= AT_HANDLER_DONE_ERROR
;
2659 } else if (gsmd_utils_match_exists(match_info
,"ok")) {
2660 GValue
*slots
= g_hash_table_lookup(at
->handler_data
,GSMD_SIM_KEY_PHONEBOOK_SLOTS
);
2661 GValue
*number_len
= g_hash_table_lookup(at
->handler_data
,GSMD_SIM_KEY_PHONEBOOK_NUMBER_LEN
);
2662 GValue
*name_len
= g_hash_table_lookup(at
->handler_data
,GSMD_SIM_KEY_PHONEBOOK_NAME_LEN
);
2664 if (!slots
|| !number_len
|| !name_len
) {
2665 g_warning("%s : Invalid handler data. slots: %p, number_len: %p, name_len: %p",
2666 __func__
, slots
, number_len
, name_len
);
2668 gsmd_utils_send_error(at
,
2670 "INVALID HANDLER DATA");
2671 status
= AT_HANDLER_DONE_ERROR
;
2673 status
= AT_HANDLER_DONE
;
2680 g_error_free(error
);
2682 g_match_info_free (match_info
);
2683 g_regex_unref (regex
);
2690 AtCommandHandlerStatus
gsmd_sim_handler_delete_entry(ModemInterface
*modem
,
2691 AtCommandContext
*at
,
2694 AtCommandHandlerStatus status
= AT_HANDLER_DONT_UNDERSTAND
;
2695 GError
**error
= NULL
;
2696 GRegex
*regex
= g_regex_new ("(?<error>ERROR)|(?<ok>OK)", 0, 0, error
);
2697 GMatchInfo
*match_info
;
2700 if (g_regex_match (regex
, response
->str
, 0, &match_info
)) {
2701 if (gsmd_utils_match_exists(match_info
,"error")) {
2702 gsmd_utils_send_error(at
,
2704 "FAILED TO DELETE PHONEBOOK ENTRY");
2705 status
= AT_HANDLER_DONE_ERROR
;
2708 if (gsmd_utils_match_exists(match_info
,"ok")) {
2709 modem
->sim_ipc
->delete_entry_reply(modem
->sim_ipc
,
2711 status
= AT_HANDLER_DONE
;
2717 g_match_info_free (match_info
);
2718 g_regex_unref (regex
);
2724 void gsmd_sim_command_delete_entry(SIMInterface
*sim
,
2728 GString
* message
= g_string_new ("");
2729 g_string_printf(message
, "%d",index
);
2731 ModemInterface
*modem
= (ModemInterface
*)sim
->priv
;
2732 gsmd_modem_post_at_command_id( modem
,
2733 PHONEBOOK_ENTRY_DELETE
,
2736 (ErrorFunction
)modem
->sim_ipc
->delete_entry_error
,
2737 (gpointer
)modem
->sim_ipc
,
2740 g_string_free(message
,TRUE
);
2745 AtCommandHandlerStatus
gsmd_sim_handler_store_entry(
2746 ModemInterface
*modem
,
2747 AtCommandContext
*at
,
2751 AT+CPBW=2,+35844123456789,145,Name
2756 AtCommandHandlerStatus status
= AT_HANDLER_DONT_UNDERSTAND
;
2757 GError
**error
= NULL
;
2758 GRegex
*regex
= g_regex_new ("(?<error>ERROR)|(?<ok>OK)", 0, 0, error
);
2759 GMatchInfo
*match_info
;
2762 if (g_regex_match (regex
, response
->str
, 0, &match_info
)) {
2763 if (gsmd_utils_match_exists(match_info
,"error")) {
2764 gsmd_utils_send_error(at
,
2766 "FAILED TO STORE PHONEBOOK ENTRY");
2767 status
= AT_HANDLER_DONE_ERROR
;
2770 if (gsmd_utils_match_exists(match_info
,"ok")) {
2771 modem
->sim_ipc
->store_entry_reply(modem
->sim_ipc
,
2773 status
= AT_HANDLER_DONE
;
2779 g_match_info_free (match_info
);
2780 g_regex_unref (regex
);
2789 void gsmd_sim_command_store_entry(SIMInterface
*sim
,
2795 GString
* message
= g_string_new ("");
2796 // TODO Better number checks
2797 if(*number
== '+') {
2798 g_string_printf(message
, "%d,%s,145,%s",index
,number
,name
);
2800 g_string_printf(message
, "%d,%s,129,%s",index
,number
,name
);
2803 ModemInterface
*modem
= (ModemInterface
*)sim
->priv
;
2804 gsmd_modem_post_at_command_id( modem
,
2805 PHONEBOOK_ENTRY_SET
,
2808 (ErrorFunction
)modem
->sim_ipc
->store_entry_error
,
2809 (gpointer
)modem
->sim_ipc
,
2812 g_string_free(message
,TRUE
);
2816 AtCommandHandlerStatus
gsmd_sim_handler_retrieve_entry(ModemInterface
*modem
,
2817 AtCommandContext
*at
,
2823 +CPBR: 1,"040123456789",129,"Name"
2827 Regular expression: \+CPBR:\s(\d+),"(\w+)",(\d+),"(\w+)"
2829 AtCommandHandlerStatus status
= AT_HANDLER_DONT_UNDERSTAND
;
2830 GError
**error
= NULL
;
2831 GRegex
*regex
= g_regex_new ("\\+CPBR:\\s(?<id>\\d)+,\"(?<number>\\+?\\w+)\",(?<type>\\d+),\"(?<text>\\w+)\"|(?<error>ERROR)|(?<ok>OK)", 0, 0, error
);
2833 GMatchInfo
*match_info
;
2836 if (g_regex_match (regex
, response
->str
, 0, &match_info
)) {
2837 if (gsmd_utils_match_exists(match_info
,"id")) {
2839 gchar
*type
= g_match_info_fetch_named(match_info
,"type");
2840 gchar
*name
= g_match_info_fetch_named(match_info
,"text");
2841 gchar
*number
= g_match_info_fetch_named(match_info
,"number");
2843 //TODO only send this once we have ok
2844 modem
->sim_ipc
->retrieve_entry_reply(modem
->sim_ipc
,
2852 status
= AT_HANDLER_NEED_MORE
;
2855 if (gsmd_utils_match_exists(match_info
,"error")) {
2856 //TODO should empty string be sent as a reply instead?
2857 gsmd_utils_send_error(at
,
2859 "UNABLE TO READ PHONEBOOK INDEX BOUNDARIES");
2860 status
= AT_HANDLER_DONE_ERROR
;
2863 if (gsmd_utils_match_exists(match_info
,"ok")) {
2864 status
= AT_HANDLER_DONE
;
2870 g_match_info_free (match_info
);
2871 g_regex_unref (regex
);
2879 void gsmd_sim_command_retrieve_entry(SIMInterface
*sim
,
2883 GString
* message
= g_string_new ("");
2884 g_string_printf(message
, "%d",index
);
2886 ModemInterface
*modem
= (ModemInterface
*)sim
->priv
;
2887 gsmd_modem_post_at_command_id( modem
,
2888 PHONEBOOK_ENTRY_GET
,
2891 (ErrorFunction
)modem
->sim_ipc
->retrieve_entry_error
,
2892 (gpointer
)modem
->sim_ipc
,
2895 g_string_free(message
,TRUE
);
2899 void gsmd_sim_init(ModemInterface
*modem
)
2901 modem
->sim
->priv
= (gpointer
)modem
;
2902 modem
->sim
->send_auth_code
= &gsmd_sim_command_setup_pin
;
2903 modem
->sim
->get_auth_status
= &gsmd_sim_command_query_pin_status
;
2904 modem
->sim
->get_sim_info
= &gsmd_sim_command_get_sim_info
;
2905 modem
->sim
->change_auth_code
= &gsmd_sim_command_change_auth_code
;
2906 modem
->sim
->unlock
= &gsmd_sim_command_unlock
;
2907 modem
->sim
->list_messages
= &gsmd_sim_command_list_messages
;
2908 modem
->sim
->send_message
= &gsmd_sim_command_send_message
;
2909 modem
->sim
->delete_message
= &gsmd_sim_command_delete
;
2910 modem
->sim
->set_service_center_number
= &gsmd_sim_command_set_service_center
;
2911 modem
->sim
->get_service_center_number
= &gsmd_sim_command_query_service_center
;
2912 modem
->sim
->store_message
= &gsmd_sim_command_store_message
;
2913 modem
->sim
->retrieve_message
= &gsmd_sim_command_read
;
2914 modem
->sim
->retrieve_entry
= &gsmd_sim_command_retrieve_entry
;
2915 modem
->sim
->store_entry
= &gsmd_sim_command_store_entry
;
2916 modem
->sim
->delete_entry
= &gsmd_sim_command_delete_entry
;
2917 modem
->sim
->get_phonebook_info
= &gsmd_sim_command_get_phonebook_info
;
2918 gsmd_sim_init_at_handler(modem
);
2922 void gsmd_sim_deinitialize(ModemInterface
*modem
)