3 * oFono - Open Source Telephony
5 * Copyright (C) 2011 ST-Ericsson AB.
6 * Copyright (C) 2009-2010 Nokia Corporation and/or its subsidiary(-ies).
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
37 #include <gisi/message.h>
38 #include <gisi/client.h>
39 #include <gisi/iter.h>
41 #include <ofono/log.h>
42 #include <ofono/modem.h>
43 #include <ofono/sms.h>
52 /* This is a straightforward copy of the EF_smsp structure */
65 /* Sub-block used by PN_SMS */
89 uint8_t cseg; /* Current segment */
90 uint8_t tseg; /* Total segments */
108 struct sim_efsmsp params;
111 static uint8_t bearer_to_cs_pref(int bearer)
115 return SMS_ROUTE_NOT_AVAILABLE;
117 return SMS_ROUTE_PRIORITY_1;
119 return SMS_ROUTE_PRIORITY_2;
121 return SMS_ROUTE_PRIORITY_1;
124 return SMS_ROUTE_NOT_AVAILABLE;
127 static uint8_t bearer_to_ps_pref(int bearer)
131 return SMS_ROUTE_PRIORITY_1;
133 return SMS_ROUTE_NOT_AVAILABLE;
135 return SMS_ROUTE_PRIORITY_1;
137 return SMS_ROUTE_PRIORITY_2;
140 return SMS_ROUTE_NOT_AVAILABLE;
143 static int cs_ps_pref_to_bearer(uint8_t cs, uint8_t ps)
145 if (cs == SMS_ROUTE_NOT_AVAILABLE && ps == SMS_ROUTE_PRIORITY_1)
148 if (cs == SMS_ROUTE_PRIORITY_1 && ps == SMS_ROUTE_NOT_AVAILABLE)
151 if (cs == SMS_ROUTE_PRIORITY_2 && ps == SMS_ROUTE_PRIORITY_1)
154 if (cs == SMS_ROUTE_PRIORITY_1 && ps == SMS_ROUTE_PRIORITY_2)
160 static gboolean check_sim(const GIsiMessage *msg, uint8_t msgid, uint8_t service)
165 if (g_isi_msg_error(msg) < 0) {
166 DBG("Error: %s", g_isi_msg_strerror(msg));
170 if (g_isi_msg_id(msg) != msgid) {
171 DBG("Unexpected msg: %s", sms_message_id_name(g_isi_msg_id(msg)));
175 if (!g_isi_msg_data_get_byte(msg, 0, &type))
178 if (type != service) {
179 DBG("Unexpected service type: 0x%02X", type);
183 if (!g_isi_msg_data_get_byte(msg, 1, &cause))
186 if (cause != SIM_SERV_OK) {
187 DBG("Request failed: %s", sim_isi_cause_name(cause));
194 static gboolean check_sms(const GIsiMessage *msg, uint8_t msgid, int expect)
200 * Quirk for the cause code position in the response. More
201 * recent versions of the API use 16bit subblock IDs, causing
202 * the cause to be bumped forward by one byte.
204 if (ISI_VERSION_AT_LEAST(msg->version, 9, 1))
209 if (g_isi_msg_error(msg) < 0) {
210 DBG("Error: %s", g_isi_msg_strerror(msg));
214 if (g_isi_msg_id(msg) != msgid) {
215 DBG("Unexpected msg: %s",
216 sms_message_id_name(g_isi_msg_id(msg)));
223 if (!g_isi_msg_data_get_byte(msg, pos, &cause)) {
224 DBG("Unable to parse cause");
231 if (cause == SMS_ERR_PP_RESERVED) {
232 DBG("Request failed: 0x%02"PRIx8" (%s).\n\n Unable to "
233 "bootstrap SMS routing.\n It appears some other "
234 "component is already\n registered as the SMS "
235 "routing endpoint.\n As a consequence, "
236 "only sending SMSs is going to work.\n\n",
237 cause, sms_isi_cause_name(cause));
241 DBG("Request failed: %s", sms_isi_cause_name(cause));
245 static void sca_sim_query_resp_cb(const GIsiMessage *msg, void *data)
247 struct isi_cb_data *cbd = data;
248 struct ofono_sms *sms = cbd->user;
249 struct sms_data *sd = ofono_sms_get_data(sms);
250 ofono_sms_sca_query_cb_t cb = cbd->cb;
252 struct ofono_phone_number sca;
253 struct sms_params *info;
254 size_t len = sizeof(struct sms_params);
257 if (!check_sim(msg, SIM_SMS_RESP, READ_PARAMETER))
260 if (!g_isi_msg_data_get_struct(msg, 2, (const void **) &info, len))
263 if (info->alphalen > 17)
265 else if (info->alphalen < 1)
268 info->alpha[info->alphalen - 1] = '\0';
270 sd->params.absent = info->absent;
271 sd->params.tp_pid = info->tp_pid;
272 sd->params.tp_dcs = info->tp_dcs;
273 sd->params.tp_vp = info->tp_vp;
275 memcpy(sd->params.dst, info->dst, sizeof(sd->params.dst));
276 memcpy(sd->params.sca, info->sca, sizeof(sd->params.sca));
278 sd->params.alphalen = info->alphalen;
279 memcpy(sd->params.alpha, info->alpha, sizeof(sd->params.alpha));
282 * Bitmask indicating absence of parameters --
283 * If second bit is set it indicates that the SCA is absent
285 if (info->absent & 0x2)
288 bcd_len = info->sca[0];
290 if (bcd_len == 0 || bcd_len > 12)
293 extract_bcd_number(info->sca + 2, bcd_len - 1, sca.number);
294 sca.type = 0x80 | info->sca[1];
296 CALLBACK_WITH_SUCCESS(cb, &sca, cbd->data);
300 CALLBACK_WITH_FAILURE(cb, NULL, cbd->data);
303 static gboolean sca_sim_query(GIsiClient *client, void *data, GDestroyNotify notify)
305 const uint8_t msg[] = {
308 1, /* Location, default is 1 */
311 return g_isi_client_send(client, msg, sizeof(msg), sca_sim_query_resp_cb,
315 static void isi_sca_query(struct ofono_sms *sms,
316 ofono_sms_sca_query_cb_t cb, void *data)
318 struct sms_data *sd = ofono_sms_get_data(sms);
319 struct isi_cb_data *cbd = isi_cb_data_new(sms, cb, data);
321 if (cbd == NULL || sd->sim == NULL)
324 if (sca_sim_query(sd->sim, cbd, g_free))
328 CALLBACK_WITH_FAILURE(cb, NULL, data);
332 static void sca_sim_set_resp_cb(const GIsiMessage *msg, void *data)
334 struct isi_cb_data *cbd = data;
335 ofono_sms_sca_set_cb_t cb = cbd->cb;
337 if (!check_sim(msg, SIM_SMS_RESP, UPDATE_PARAMETER)) {
338 CALLBACK_WITH_FAILURE(cb, cbd->data);
342 CALLBACK_WITH_SUCCESS(cb, cbd->data);
345 static gboolean sca_sim_set(GIsiClient *client, struct sim_efsmsp *params,
346 const struct ofono_phone_number *sca, void *data,
347 GDestroyNotify notify)
352 1, /* Location, default is 1 */
354 struct iovec iov[2] = {
355 { msg, sizeof(msg) },
356 { params, sizeof(struct sim_efsmsp) },
361 params->absent &= ~SMS_PI_SERVICE_CENTER_ADDRESS;
363 encode_bcd_number(sca->number, bcd + 2);
364 bcd[0] = 1 + (strlen(sca->number) + 1) / 2;
365 bcd[1] = sca->type & 0xFF;
367 return g_isi_client_vsend(client, iov, 2, sca_sim_set_resp_cb,
371 static void isi_sca_set(struct ofono_sms *sms,
372 const struct ofono_phone_number *sca,
373 ofono_sms_sca_set_cb_t cb, void *data)
375 struct sms_data *sd = ofono_sms_get_data(sms);
376 struct isi_cb_data *cbd = isi_cb_data_new(sms, cb, data);
378 if (cbd == NULL || sd->sim == NULL)
381 if (sca_sim_set(sd->sim, &sd->params, sca, cbd, g_free))
385 CALLBACK_WITH_FAILURE(cb, data);
389 static void submit_failure_debug(struct sms_report *report)
393 if (report->type == SMS_CAUSE_TYPE_COMMON)
394 cause = sms_isi_cause_name(report->cause);
396 cause = sms_gsm_cause_name(report->cause);
398 DBG("Message 0x%02"PRIx8" failed: %s", report->ref, cause);
401 static void submit_tpdu_resp_cb(const GIsiMessage *msg, void *data)
403 struct isi_cb_data *cbd = data;
404 ofono_sms_submit_cb_t cb = cbd->cb;
405 struct sms_report *report;
406 size_t len = sizeof(struct sms_report);
408 if (!check_sms(msg, SMS_MESSAGE_SEND_RESP, -1))
411 if (g_isi_msg_data_len(msg) < len)
414 if (!g_isi_msg_data_get_struct(msg, 0, (const void **) &report, len))
417 if (report->type == SMS_CAUSE_TYPE_COMMON && report->cause == SMS_OK) {
418 CALLBACK_WITH_SUCCESS(cb, report->ref, cbd->data);
422 submit_failure_debug(report);
425 CALLBACK_WITH_FAILURE(cb, -1, cbd->data);
428 static void submit_gsm_tpdu_resp_cb(const GIsiMessage *msg, void *data)
430 struct isi_cb_data *cbd = data;
431 ofono_sms_submit_cb_t cb = cbd->cb;
432 struct sms_report *report;
433 size_t len = sizeof(struct sms_report);
434 GIsiSubBlockIter iter;
436 if (!check_sms(msg, SMS_MESSAGE_SEND_RESP, -1))
439 for (g_isi_sb_iter_init(&iter, msg, 2);
440 g_isi_sb_iter_is_valid(&iter);
441 g_isi_sb_iter_next(&iter)) {
443 if (g_isi_sb_iter_get_id(&iter) != SMS_GSM_REPORT)
446 if (!g_isi_sb_iter_get_struct(&iter, (void **) &report, len, 2))
449 if (report->type == SMS_CAUSE_TYPE_COMMON &&
450 report->cause == SMS_OK) {
451 CALLBACK_WITH_SUCCESS(cb, report->ref, cbd->data);
455 submit_failure_debug(report);
459 CALLBACK_WITH_FAILURE(cb, -1, cbd->data);
462 static gboolean submit_tpdu(GIsiClient *client, unsigned char *pdu, int pdu_len,
463 int tpdu_len, int mms, void *data,
464 GDestroyNotify notify)
466 uint8_t use_sca = (pdu_len - tpdu_len) > 1;
467 size_t sca_sb_len = use_sca ? 18 : 0;
468 size_t tpdu_sb_len = ALIGN4(6 + tpdu_len);
469 size_t tpdu_pad_len = tpdu_sb_len - (6 + tpdu_len);
472 SMS_MESSAGE_SEND_REQ,
473 mms, /* More messages to send */
474 SMS_ROUTE_ANY, /* Use any (default) route */
475 0, /* Repeated message */
477 use_sca ? 3 : 2, /* Subblock count */
478 ISI_16BIT(SMS_SB_SMS_PARAMETERS),
479 ISI_16BIT(8), /* Subblock length */
480 SMS_PARAMETER_LOCATION_DEFAULT,
481 SMS_PI_SERVICE_CENTER_ADDRESS,
483 ISI_16BIT(SMS_SB_TPDU),
484 ISI_16BIT(tpdu_sb_len),
487 /* Databytes aligned to next 32bit boundary */
489 uint8_t sca_sb[18] = {
490 ISI_16BIT(SMS_SB_ADDRESS),
493 0, /* Filled in later */
495 uint8_t padding[4] = { 0 };
496 struct iovec iov[4] = {
497 { msg, sizeof(msg) },
498 { pdu + pdu_len - tpdu_len, tpdu_len },
499 { padding, tpdu_pad_len },
500 { sca_sb, sca_sb_len },
504 sca_sb[5] = pdu_len - tpdu_len;
505 memcpy(sca_sb + 6, pdu, pdu_len - tpdu_len);
508 return g_isi_client_vsend_with_timeout(client, iov, 4, SMS_TIMEOUT,
509 submit_tpdu_resp_cb, data,
513 static gboolean submit_gsm_tpdu(GIsiClient *client, unsigned char *pdu,
514 int pdu_len, int tpdu_len, int mms,
515 void *data, GDestroyNotify notify)
517 uint8_t use_sca = (pdu_len - tpdu_len) > 1;
518 size_t sca_sb_len = use_sca ? 16 : 0;
519 size_t tpdu_sb_len = ALIGN4(4 + tpdu_len);
520 size_t tpdu_pad_len = tpdu_sb_len - (4 + tpdu_len);
523 SMS_MESSAGE_SEND_REQ,
524 mms, /* More messages to send */
526 0, /* Repeated message */
528 SMS_TYPE_TEXT_MESSAGE,
529 1, /* Subblock count */
531 tpdu_sb_len + sca_sb_len,
533 use_sca ? 2 : 1, /* Sub-sub blocks */
537 0, /* Packing required? */
538 /* Databytes aligned to next 32bit boundary */
540 uint8_t sca_sb[16] = {
542 16, /* Subblock length */
543 SMS_GSM_0411_ADDRESS,
544 0, /* Filled in later */
546 uint8_t padding[4] = { 0 };
547 struct iovec iov[4] = {
548 { msg, sizeof(msg) },
549 { pdu + pdu_len - tpdu_len, tpdu_len },
550 { padding, tpdu_pad_len },
551 { sca_sb, sca_sb_len },
555 sca_sb[3] = pdu_len - tpdu_len;
556 memcpy(sca_sb + 4, pdu, pdu_len - tpdu_len);
560 * Modem seems to time out SMS_MESSAGE_SEND_REQ in 5 seconds.
561 * Wait normal timeout plus the modem timeout.
563 return g_isi_client_vsend_with_timeout(client, iov, 4, SMS_TIMEOUT + 5,
564 submit_gsm_tpdu_resp_cb, data,
568 static void isi_submit(struct ofono_sms *sms, unsigned char *pdu,
569 int pdu_len, int tpdu_len, int mms,
570 ofono_sms_submit_cb_t cb, void *data)
572 struct sms_data *sd = ofono_sms_get_data(sms);
573 struct isi_cb_data *cbd = isi_cb_data_new(sms, cb, data);
578 if (ISI_VERSION_AT_LEAST(&sd->version, 9, 1)) {
579 if (submit_tpdu(sd->client, pdu, pdu_len, tpdu_len, mms,
583 if (submit_gsm_tpdu(sd->client, pdu, pdu_len, tpdu_len, mms,
589 CALLBACK_WITH_FAILURE(cb, -1, data);
593 static void bearer_query_resp_cb(const GIsiMessage *msg, void *data)
595 struct isi_cb_data *cbd = data;
596 ofono_sms_bearer_query_cb_t cb = cbd->cb;
597 GIsiSubBlockIter iter;
600 if (!check_sms(msg, SMS_SETTINGS_READ_RESP, SMS_OK))
603 if (!g_isi_msg_data_get_byte(msg, 1, &sb))
606 for (g_isi_sb_iter_init_full(&iter, msg, 2, TRUE, sb);
607 g_isi_sb_iter_is_valid(&iter);
608 g_isi_sb_iter_next(&iter)) {
610 if (g_isi_sb_iter_get_id(&iter) != SMS_SB_ROUTE_INFO)
613 if (!g_isi_msg_data_get_byte(msg, 5, &cs))
616 if (!g_isi_msg_data_get_byte(msg, 6, &ps))
619 CALLBACK_WITH_SUCCESS(cb, cs_ps_pref_to_bearer(cs, ps),
625 CALLBACK_WITH_FAILURE(cb, 0, cbd->data);
628 static void isi_bearer_query(struct ofono_sms *sms,
629 ofono_sms_bearer_query_cb_t cb, void *data)
631 struct sms_data *sd = ofono_sms_get_data(sms);
632 struct isi_cb_data *cbd = isi_cb_data_new(sms, cb, data);
633 const uint8_t msg[] = {
634 SMS_SETTINGS_READ_REQ,
635 SMS_SETTING_TYPE_ROUTE,
644 if (g_isi_client_send(sd->client, msg, sizeof(msg), bearer_query_resp_cb,
649 CALLBACK_WITH_FAILURE(cb, 0, data);
653 static void bearer_set_resp_cb(const GIsiMessage *msg, void *data)
655 struct isi_cb_data *cbd = data;
656 ofono_sms_bearer_set_cb_t cb = cbd->cb;
658 if (check_sms(msg, SMS_SETTINGS_UPDATE_RESP, SMS_OK))
659 CALLBACK_WITH_SUCCESS(cb, cbd->data);
661 CALLBACK_WITH_FAILURE(cb, cbd->data);
664 static void isi_bearer_set(struct ofono_sms *sms, int bearer,
665 ofono_sms_bearer_set_cb_t cb, void *data)
667 struct sms_data *sd = ofono_sms_get_data(sms);
668 struct isi_cb_data *cbd = isi_cb_data_new(sms, cb, data);
669 const uint8_t msg[] = {
670 SMS_SETTINGS_UPDATE_REQ,
671 SMS_SETTING_TYPE_ROUTE,
672 1, /* Subblock count */
673 ISI_16BIT(SMS_SB_ROUTE_INFO),
674 ISI_16BIT(8), /* Subblock length */
675 bearer_to_cs_pref(bearer), /* CS priority */
676 bearer_to_ps_pref(bearer), /* PS priority */
683 if (g_isi_client_send(sd->client, msg, sizeof(msg), bearer_set_resp_cb,
688 CALLBACK_WITH_FAILURE(cb, data);
692 static void send_status_ind_cb(const GIsiMessage *msg, void *data)
694 struct sms_status *info;
695 size_t len = sizeof(struct sms_status);
699 if (g_isi_msg_id(msg) != SMS_MESSAGE_SEND_STATUS_IND)
702 if (!g_isi_msg_data_get_struct(msg, 0, (const void **) &info, len))
705 DBG("status=0x%"PRIx8", ref=0x%"PRIx8", route=0x%"PRIx8
706 ", cseg=0x%"PRIx8", tseg=0x%"PRIx8,
707 info->status, info->ref, info->route, info->cseg,
710 DBG("TODO: Status notification");
713 static void gsm_report_resp_cb(const GIsiMessage *msg, void *data)
715 if (!check_sms(msg, SMS_GSM_RECEIVED_PP_REPORT_RESP, SMS_OK))
716 DBG("Sending report failed");
719 static void report_resp_cb(const GIsiMessage *msg, void *data)
721 if (!check_sms(msg, SMS_RECEIVED_MSG_REPORT_RESP, SMS_OK))
722 DBG("Sending report failed");
725 static gboolean send_gsm_deliver_report(GIsiClient *client, gboolean success,
726 void *data, GDestroyNotify destroy)
728 const uint8_t msg[] = {
729 SMS_GSM_RECEIVED_PP_REPORT_REQ,
730 success ? 0 : SMS_CAUSE_TYPE_GSM,
731 success ? SMS_OK : SMS_GSM_ERR_MEMORY_CAPACITY_EXC,
732 0, 0, 0, /* Filler */
734 SMS_GSM_DELIVER_REPORT,
735 8, /* Subblock length */
736 0, /* Message parameters */
738 0, 0, 0, /* Filler */
742 return g_isi_client_send(client, msg, sizeof(msg), gsm_report_resp_cb,
746 static gboolean send_deliver_report(GIsiClient *client, gboolean success,
747 void *data, GDestroyNotify destroy)
749 const uint8_t msg[] = {
750 SMS_RECEIVED_MSG_REPORT_REQ,
751 success ? 0 : SMS_CAUSE_TYPE_GSM,
752 success ? SMS_OK : SMS_GSM_ERR_MEMORY_CAPACITY_EXC,
753 0, 0, 0, /* Filler */
757 return g_isi_client_send(client, msg, sizeof(msg), report_resp_cb,
761 static gboolean parse_sms_address(GIsiSubBlockIter *iter, unsigned offset,
762 struct sms_addr *add)
766 if (!g_isi_sb_iter_get_byte(iter, &add->type, offset))
769 if (!g_isi_sb_iter_get_byte(iter, &add->len, offset + 1))
775 if (!g_isi_sb_iter_get_struct(iter, (void **) &add->data, add->len,
782 static gboolean parse_sms_tpdu(GIsiSubBlockIter *iter, unsigned offset,
783 struct sms_common *com)
787 if (!g_isi_sb_iter_get_byte(iter, &com->len, offset))
793 if (!g_isi_sb_iter_get_struct(iter, (void **) &com->data, com->len,
800 static gboolean parse_gsm_tpdu(GIsiSubBlockIter *parent, struct sms_addr *add,
801 struct sms_common *com)
803 GIsiSubBlockIter iter;
805 for (g_isi_sb_subiter_init(parent, &iter, 2);
806 g_isi_sb_iter_is_valid(&iter);
807 g_isi_sb_iter_next(&iter)) {
809 switch (g_isi_sb_iter_get_id(&iter)) {
812 if (!parse_sms_address(&iter, 2, add))
815 if (add->type != SMS_GSM_0411_ADDRESS)
820 case SMS_COMMON_DATA:
822 if (!parse_sms_tpdu(&iter, 2, com))
832 static void routing_ntf_cb(const GIsiMessage *msg, void *data)
834 struct ofono_sms *sms = data;
835 struct sms_data *sd = ofono_sms_get_data(sms);
836 struct sms_common tpdu;
837 struct sms_addr addr;
838 GIsiSubBlockIter iter;
842 if (g_isi_msg_id(msg) != SMS_PP_ROUTING_NTF)
845 for (g_isi_sb_iter_init(&iter, msg, 2);
846 g_isi_sb_iter_is_valid(&iter);
847 g_isi_sb_iter_next(&iter)) {
849 if (g_isi_sb_iter_get_id(&iter) != SMS_GSM_TPDU)
852 if (!parse_gsm_tpdu(&iter, &addr, &tpdu))
856 if (tpdu.data == NULL || addr.data == NULL ||
857 tpdu.len + addr.len > sizeof(pdu))
860 memcpy(pdu, addr.data, addr.len);
861 memcpy(pdu + addr.len, tpdu.data, tpdu.len);
864 if ((tpdu.data[0] & 0x03) == 0x02)
865 ofono_sms_status_notify(sms, pdu, tpdu.len + addr.len, tpdu.len);
867 ofono_sms_deliver_notify(sms, pdu, tpdu.len + addr.len, tpdu.len);
869 send_gsm_deliver_report(sd->client, TRUE, NULL, NULL);
872 static void received_msg_ind_cb(const GIsiMessage *msg, void *data)
874 struct ofono_sms *sms = data;
875 struct sms_data *sd = ofono_sms_get_data(sms);
876 struct sms_common tpdu;
877 struct sms_addr addr;
878 GIsiSubBlockIter iter;
885 if (g_isi_msg_id(msg) != SMS_RECEIVED_MSG_IND)
888 if (!g_isi_msg_data_get_byte(msg, 1, &sbcount))
891 for (g_isi_sb_iter_init_full(&iter, msg, 2, TRUE, sbcount);
892 g_isi_sb_iter_is_valid(&iter);
893 g_isi_sb_iter_next(&iter)) {
895 switch (g_isi_sb_iter_get_id(&iter)) {
898 if (!parse_sms_address(&iter, 4, &addr))
901 if (addr.type != SMS_SMSC_ADDRESS)
908 if (!parse_sms_tpdu(&iter, 4, &tpdu))
915 if (tpdu.data == NULL || addr.data == NULL ||
916 tpdu.len + addr.len > sizeof(pdu))
919 memcpy(pdu, addr.data, addr.len);
920 memcpy(pdu + addr.len, tpdu.data, tpdu.len);
923 if ((tpdu.data[0] & 0x03) == 0x02)
924 ofono_sms_status_notify(sms, pdu, tpdu.len + addr.len, tpdu.len);
926 ofono_sms_deliver_notify(sms, pdu, tpdu.len + addr.len, tpdu.len);
928 send_deliver_report(sd->client, TRUE, NULL, NULL);
931 static void reception_resp_cb(const GIsiMessage *msg, void *data)
933 struct ofono_sms *sms = data;
938 if (!check_sms(msg, SMS_RECEIVE_MESSAGE_RESP, SMS_RECEPTION_ACTIVE))
941 ofono_sms_register(sms);
944 static void routing_resp_cb(const GIsiMessage *msg, void *data)
946 struct ofono_sms *sms = data;
951 if (!check_sms(msg, SMS_PP_ROUTING_RESP, SMS_OK))
954 ofono_sms_register(sms);
957 static void sim_reachable_cb(const GIsiMessage *msg, void *data)
959 struct ofono_sms *sms = data;
960 struct sms_data *sd = ofono_sms_get_data(sms);
965 if (g_isi_msg_error(msg) < 0) {
966 DBG("Unable to bootstrap SIM service");
968 g_isi_client_destroy(sd->sim);
973 ISI_RESOURCE_DBG(msg);
976 static gboolean set_routing(GIsiClient *client, void *data,
977 GDestroyNotify destroy)
979 const uint8_t msg[] = {
982 1, /* Sub-block count */
984 8, /* Sub-block length */
985 SMS_GSM_TPDU_ROUTING,
987 0, 0, 0, /* Filler */
988 0, /* Sub-sub-block count */
991 return g_isi_client_send(client, msg, sizeof(msg), routing_resp_cb,
995 static gboolean unset_routing(GIsiClient *client)
997 const uint8_t msg[] = {
1000 0x01, /* Sub-block count */
1002 0x08, /* Sub-block length */
1003 SMS_GSM_TPDU_ROUTING,
1004 SMS_GSM_MT_ALL_TYPE,
1005 0, 0, 0, /* Filler */
1006 0, /* Sub-sub-block count */
1009 return g_isi_client_send(client, msg, sizeof(msg), NULL, NULL, NULL);
1012 static gboolean activate_reception(GIsiClient *client, void *data,
1013 GDestroyNotify destroy)
1015 const uint8_t msg[] = {
1016 SMS_RECEIVE_MESSAGE_REQ,
1017 SMS_RECEPTION_ACTIVATE,
1021 return g_isi_client_send(client, msg, sizeof(msg), reception_resp_cb,
1025 static gboolean deactivate_reception(GIsiClient *client)
1027 const uint8_t msg[] = {
1028 SMS_RECEIVE_MESSAGE_REQ,
1029 SMS_RECEPTION_DEACTIVATE,
1033 return g_isi_client_send(client, msg, sizeof(msg), NULL, NULL, NULL);
1036 static void sms_reachable_cb(const GIsiMessage *msg, void *data)
1038 struct ofono_sms *sms = data;
1039 struct sms_data *sd = ofono_sms_get_data(sms);
1041 if (g_isi_msg_error(msg) < 0) {
1042 DBG("unable to find SMS resource");
1043 ofono_sms_remove(sms);
1050 ISI_RESOURCE_DBG(msg);
1052 sd->version.major = g_isi_msg_version_major(msg);
1053 sd->version.minor = g_isi_msg_version_minor(msg);
1055 if (ISI_VERSION_AT_LEAST(&sd->version, 9, 1))
1056 activate_reception(sd->client, sms, NULL);
1058 set_routing(sd->client, sms, NULL);
1060 g_isi_client_verify(sd->sim, sim_reachable_cb, sms, NULL);
1063 static int isi_sms_probe(struct ofono_sms *sms, unsigned int vendor,
1066 GIsiModem *modem = user;
1067 struct sms_data *sd = g_try_new0(struct sms_data, 1);
1072 sd->params.absent = 0xFF;
1073 sd->params.alphalen = 1; /* Includes final UCS2-coded NUL */
1075 sd->client = g_isi_client_create(modem, PN_SMS);
1076 if (sd->client == NULL)
1079 sd->sim = g_isi_client_create(modem, PN_SIM);
1080 if (sd->sim == NULL)
1083 ofono_sms_set_data(sms, sd);
1085 g_isi_client_ind_subscribe(sd->client, SMS_MESSAGE_SEND_STATUS_IND,
1086 send_status_ind_cb, sms);
1087 g_isi_client_ind_subscribe(sd->client, SMS_RECEIVED_MSG_IND,
1088 received_msg_ind_cb, sms);
1089 g_isi_client_ntf_subscribe(sd->client, SMS_PP_ROUTING_NTF,
1090 routing_ntf_cb, sms);
1091 g_isi_client_verify(sd->client, sms_reachable_cb, sms, NULL);
1096 g_isi_client_destroy(sd->client);
1101 static void isi_sms_remove(struct ofono_sms *sms)
1103 struct sms_data *sd = ofono_sms_get_data(sms);
1108 ofono_sms_set_data(sms, NULL);
1111 * Send a promiscuous routing release, so as not to
1112 * hog resources unnecessarily after being removed
1114 if (ISI_VERSION_AT_LEAST(&sd->version, 9, 1))
1115 deactivate_reception(sd->client);
1117 unset_routing(sd->client);
1119 g_isi_client_destroy(sd->client);
1120 g_isi_client_destroy(sd->sim);
1124 static struct ofono_sms_driver driver = {
1126 .probe = isi_sms_probe,
1127 .remove = isi_sms_remove,
1128 .sca_query = isi_sca_query,
1129 .sca_set = isi_sca_set,
1130 .submit = isi_submit,
1131 .bearer_query = isi_bearer_query,
1132 .bearer_set = isi_bearer_set,
1135 void isi_sms_init(void)
1137 ofono_sms_driver_register(&driver);
1140 void isi_sms_exit(void)
1142 ofono_sms_driver_unregister(&driver);