2 * Copyright (c) 2015 Samsung Electronics Co., Ltd. All rights reserved
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
19 #include "MsgGconfWrapper.h"
20 #include "MsgException.h"
22 #include "MsgUtilStorage.h"
23 #include "MsgNotificationWrapper.h"
25 #include "SmsCdmaPluginTransport.h"
26 #include "SmsCdmaPluginCodec.h"
27 #include "SmsCdmaPluginEventHandler.h"
28 #include "SmsCdmaPluginCallback.h"
31 #include "TapiUtility.h"
33 #include "TelNetwork.h"
34 #include "ITapiNetText.h"
37 extern struct tapi_handle *pTapiHandle;
38 extern bool isMemAvailable;
41 /*==================================================================================================
42 FUNCTION IMPLEMENTATION
43 ==================================================================================================*/
45 SmsPluginTransport* SmsPluginTransport::pInstance = NULL;
48 SmsPluginTransport::SmsPluginTransport()
55 if (MsgSettingGetInt(MSG_MESSAGE_ID_COUNTER, (int *)&msgSubmitId) != MSG_SUCCESS) {
56 MSG_INFO("MsgSettingGetInt() is failed");
61 SmsPluginTransport::~SmsPluginTransport()
66 SmsPluginTransport* SmsPluginTransport::instance()
69 pInstance = new SmsPluginTransport();
75 unsigned char SmsPluginTransport::getMsgRef()
81 unsigned char SmsPluginTransport::getSeqNum()
83 msgSeqNum = ((msgSeqNum + 1) % SMS_SEQ_NUM_MAX);
89 unsigned char SmsPluginTransport::getSubmitMsgId()
91 msgSubmitId = ((msgSubmitId + 1) % SMS_MAX_MESSAGE_ID);
93 MsgSettingSetInt(MSG_MESSAGE_ID_COUNTER, msgSubmitId);
99 void SmsPluginTransport::convertMsgInfoToTelesvcMsg(const MSG_MESSAGE_INFO_S *pMsgInfo, sms_trans_msg_s *pTransMsg)
101 switch (pTransMsg->type) {
102 case SMS_TRANS_P2P_MSG: {
103 MSG_DEBUG("Convert MSG_MESSAGE_INFO_S data to SMS_TRANS_MSG_S data.");
104 sms_trans_p2p_msg_s *pPtpMsg = (sms_trans_p2p_msg_s *)&(pTransMsg->data.p2p_msg);
106 convertMsgInfoToPtp(pMsgInfo, pPtpMsg);
110 MSG_DEBUG("Error Unsupported Transport Type");
116 void SmsPluginTransport::convertMsgInfoToPtp(const MSG_MESSAGE_INFO_S *pMsgInfo, sms_trans_p2p_msg_s *pPtpMsg)
118 /* 1. Set Teleservice ID */
119 pPtpMsg->telesvc_id = SMS_TRANS_TELESVC_CMT_95;
121 /* 2. Set Service category */
122 pPtpMsg->svc_ctg = SMS_TRANS_SVC_CTG_UNDEFINED;
124 /* 3. Convert Address values */
125 pPtpMsg->address.digit_mode = SMS_DIGIT_4BIT_DTMF;
126 pPtpMsg->address.number_mode = SMS_NUMBER_MODE_NONE_DATANETWORK;
127 pPtpMsg->address.number_type = SMS_NUMBER_TYPE_UNKNOWN;
128 pPtpMsg->address.number_plan = SMS_NPI_UNKNOWN;
129 pPtpMsg->address.addr_len = strlen(pMsgInfo->addressList[0].addressVal);
130 strncpy(pPtpMsg->address.szData, pMsgInfo->addressList[0].addressVal, pPtpMsg->address.addr_len);
132 if (pMsgInfo->addressList[0].addressVal[0] == '+') {
133 pPtpMsg->address.digit_mode = SMS_DIGIT_8BIT;
134 pPtpMsg->address.number_type = SMS_NUMBER_TYPE_INTERNATIONAL;
136 pPtpMsg->address.number_type = SMS_NUMBER_TYPE_NATIONAL;
139 /* 4. Convert Sub-address values */
142 /* 5. Set Reply sequence number. */
143 pPtpMsg->reply_seq = getSeqNum();
145 /* convert msgInfo to Teleservice Message */
146 switch (pPtpMsg->telesvc_msg.type) {
147 case SMS_TYPE_SUBMIT:
148 convertMsgInfoToSubmit(pMsgInfo, &(pPtpMsg->telesvc_msg.data.submit));
156 void SmsPluginTransport::convertMsgInfoToSubmit(const MSG_MESSAGE_INFO_S *pMsgInfo, sms_telesvc_submit_s *pSubmit)
162 pSubmit->msg_id.msg_id = getSubmitMsgId();
163 pSubmit->msg_id.header_ind = false;
165 /* 2. Set User Data */
166 unsigned char decodeData[SMS_MAX_USER_DATA_LEN + 1];
167 memset(decodeData, 0x00, sizeof(decodeData));
169 MsgTextConvert *textCvt = MsgTextConvert::instance();
171 msg_encode_type_t encodeType = MSG_ENCODE_GSM7BIT;
174 if (pMsgInfo->bTextSms == true) {
175 if (pMsgInfo->encodeType == MSG_ENCODE_GSM7BIT) {
176 pSubmit->user_data.encode_type = SMS_ENCODE_GSM7BIT;
177 } else if (pMsgInfo->encodeType == MSG_ENCODE_8BIT) {
178 pSubmit->user_data.encode_type = SMS_ENCODE_OCTET;
179 } else if (pMsgInfo->encodeType == MSG_ENCODE_UCS2) {
180 pSubmit->user_data.encode_type = SMS_ENCODE_UNICODE;
181 } else if (pMsgInfo->encodeType == MSG_ENCODE_AUTO) {
182 textCvt->convertUTF8ToAuto(decodeData, SMS_MAX_USER_DATA_LEN + 1, (unsigned char*)pMsgInfo->msgText, (int)pMsgInfo->dataSize, &encodeType);
183 if (encodeType == MSG_ENCODE_ASCII7BIT) {
184 pSubmit->user_data.encode_type = SMS_ENCODE_7BIT_ASCII;
185 } else if (encodeType == MSG_ENCODE_8BIT) {
186 pSubmit->user_data.encode_type = SMS_ENCODE_OCTET;
187 } else if (encodeType == MSG_ENCODE_UCS2) {
188 pSubmit->user_data.encode_type = SMS_ENCODE_UNICODE;
193 memset(pSubmit->user_data.user_data, 0x00, sizeof(pSubmit->user_data.user_data));
194 snprintf((char *)pSubmit->user_data.user_data, sizeof(pSubmit->user_data.user_data), "%s", pMsgInfo->msgText);
195 pSubmit->user_data.data_len = pMsgInfo->dataSize;
197 MSG_DEBUG("encode type : [%d]", pSubmit->user_data.encode_type);
199 /* 3. Set Valid period */
201 pSubmit->val_period.format = SMS_TIME_ABSOLUTE;
202 pSubmit->val_period.time.abs_time.year = 0;
203 pSubmit->val_period.time.abs_time.month = 0;
204 pSubmit->val_period.time.abs_time.day = 0;
205 pSubmit->val_period.time.abs_time.hours = 0;
206 pSubmit->val_period.time.abs_time.minutes = 0;
207 pSubmit->val_period.time.abs_time.seconds = 0;
209 pSubmit->val_period.format = SMS_TIME_RELATIVE;
210 pSubmit->val_period.time.rel_time.rel_time = SMS_REL_TIME_INDEFINITE;
213 /* 4. Set Defer valid period */
216 /* 5. Set Priority */
217 switch (pMsgInfo->priority) {
218 case MSG_MESSAGE_PRIORITY_HIGH:
219 pSubmit->priority = SMS_PRIORITY_URGENT;
222 pSubmit->priority = SMS_PRIORITY_NORMAL;
227 pSubmit->privacy = SMS_PRIVACY_NOT_RESTRICTED;
229 /* 7. Set Reply option */
230 if (MsgSettingGetBool(SMS_SEND_DELIVERY_REPORT, (bool *)&(pSubmit->reply_opt.deliver_ack_req)) != MSG_SUCCESS)
231 MSG_INFO("MsgSettingGetBool() is failed");
233 /* 8. Set Alert priority */
234 pSubmit->alert_priority = SMS_ALERT_MOBILE_DEFAULT;
236 /* 9. Set Language */
237 pSubmit->language = SMS_LAN_UNKNOWN;
239 /* 10. Set Callback number */
240 /* TODO :: Set callback number to MSISDN */
242 /* 11. Set Multi encode data */
245 /* 12. Set Deposit id */
248 /* 13. Set Service category program data */
253 void SmsPluginTransport::submitRequest(sms_request_info_s *pReqInfo)
255 int tapiRet = TAPI_API_SUCCESS;
257 if (pReqInfo == NULL) {
258 THROW(MsgException::SMS_PLG_ERROR, "pReqInfo is NULL");
261 /* Get address informations. */
262 MsgDbHandler *dbHandle = getDbHandle();
263 MsgStoGetAddressByMsgId(dbHandle, pReqInfo->msgInfo.msgId, &pReqInfo->msgInfo.nAddressCnt, &pReqInfo->msgInfo.addressList);
265 MSG_DEBUG("pReqInfo->msgInfo.nAddressCnt [%d]", pReqInfo->msgInfo.nAddressCnt);
269 char keyName[MAX_VCONFKEY_NAME_LEN];
272 memset(keyName, 0x00, sizeof(keyName));
273 snprintf(keyName, sizeof(keyName), "%s/%d", MSG_SIM_MSISDN, simIndex);
275 if (MsgSettingGetString(keyName, &msisdn) != MSG_SUCCESS) {
276 MSG_INFO("MsgSettingGetString() is failed");
279 /* Tapi Data Structure */
280 TelSmsDatapackageInfo_t tapi_data_pkg;
281 memset(&tapi_data_pkg, 0x00, sizeof(TelSmsDatapackageInfo_t));
283 bool bMoreMsgToSend = false;
285 tapi_data_pkg.format = (TelSmsNetType_t)TAPI_NETTEXT_NETTYPE_3GPP2;
287 /* convert msg_info to trans_msg */
288 sms_trans_msg_s trans_msg;
289 memset(&trans_msg, 0x00, sizeof(sms_trans_msg_s));
291 trans_msg.type = (sms_trans_msg_type_t)SMS_TRANS_P2P_MSG;
292 trans_msg.data.p2p_msg.telesvc_msg.type = (sms_message_type_t)SMS_TYPE_SUBMIT;
294 convertMsgInfoToTelesvcMsg(&pReqInfo->msgInfo, &trans_msg);
296 /* encode msg data */
297 unsigned char tel_sms_data[TAPI_NETTEXT_SMDATA_SIZE_MAX+1] = {0, };
299 tapi_data_pkg.MsgLength = SmsPluginMsgCodec::instance()->encodeMsg(&trans_msg, tel_sms_data);
301 memcpy((void *)tapi_data_pkg.szData, (void *)tel_sms_data, sizeof(tapi_data_pkg.szData));
303 MSG_DEBUG("Submit Request TPDU.");
304 char pduDbg[TAPI_NETTEXT_SMDATA_SIZE_MAX*2];
305 memset(pduDbg, 0x00, sizeof(pduDbg));
307 for (int i = 0; i < tapi_data_pkg.MsgLength; i++) {
308 snprintf(pduDbg+(i*2), sizeof(pduDbg)- (i*2), "%02x", tapi_data_pkg.szData[i]);
310 MSG_DEBUG("Encode PDU= [%s]", pduDbg);
312 sms_network_status_t retStatus;
314 for (int cnt = 0; cnt < MAX_SMS_SEND_RETRY; ++cnt) {
316 sms_sent_info_s sent_info;
317 memset(&sent_info, 0x00, sizeof(sms_sent_info_s));
318 memcpy(&sent_info.reqInfo, pReqInfo, sizeof(sent_info.reqInfo));
320 sent_info.bLast = true;
322 SmsPluginEventHandler::instance()->SetSentInfo(&sent_info);
325 tel_get_property_int(pTapiHandle, TAPI_PROP_NETWORK_SERVICE_TYPE, &svc_type);
327 if (svc_type < TAPI_NETWORK_SERVICE_TYPE_2G) {
328 MSG_DEBUG("Network service is not available : [%d]", svc_type);
329 SmsPluginEventHandler::instance()->handleSentStatus(MSG_NETWORK_SEND_PENDING);
333 curStatus = SMS_NETWORK_SENDING;
336 tapiRet = tel_send_sms(pTapiHandle, &tapi_data_pkg, bMoreMsgToSend, TapiEventSentStatus, NULL);
338 if (tapiRet == TAPI_API_SUCCESS) {
339 MSG_DEBUG("######## tel_send_sms Success !!! return : [%d] #######", tapiRet);
341 SmsPluginEventHandler::instance()->handleSentStatus(MSG_NETWORK_SEND_FAIL);
342 THROW(MsgException::SMS_PLG_ERROR, "######## tel_send_sms Fail !!! return : [%d] #######", tapiRet);
345 /* Tizen Validation System */
346 MSG_SMS_VLD_INFO("%d, SMS Send Start, %s->%s, %s", pReqInfo->msgInfo.msgId, \
347 (msisdn == NULL)?"ME":msisdn, \
348 pReqInfo->msgInfo.addressList[0].addressVal, \
349 (tapiRet == TAPI_API_SUCCESS)?"Success":"Fail");
351 MSG_SMS_VLD_TXT("%d, [%s]", pReqInfo->msgInfo.msgId, pReqInfo->msgInfo.msgText);
353 retStatus = getNetStatus();
355 if (retStatus != SMS_NETWORK_SEND_FAIL_TEMPORARY)
359 MSG_SMS_VLD_INFO("%d, SMS Send End, %s->%s, %s", pReqInfo->msgInfo.msgId, \
360 (msisdn == NULL)?"ME":msisdn, \
361 pReqInfo->msgInfo.addressList[0].addressVal, \
362 (retStatus == SMS_NETWORK_SEND_SUCCESS)?"Success":"Fail");
364 if (retStatus == SMS_NETWORK_SEND_SUCCESS) {
365 MSG_DEBUG("######## Msg Sent was Successful !!! #######");
367 if (retStatus == SMS_NETWORK_SEND_FAIL_TIMEOUT || retStatus == SMS_NETWORK_SEND_FAIL_TEMPORARY
368 || retStatus == SMS_NETWORK_SEND_FAIL_MANDATORY_INFO_MISSING || retStatus == SMS_NETWORK_SEND_FAIL_FDN_RESTRICED)
369 SmsPluginEventHandler::instance()->handleSentStatus(MSG_NETWORK_SEND_FAIL);
371 if (retStatus == SMS_NETWORK_SEND_FAIL_FDN_RESTRICED)
372 MsgInsertTicker("Unable to send the message while Fixed dialling mode is enabled", SMS_FDN_RESTRICTED, true, 0);
373 else if (retStatus == SMS_NETWORK_SEND_PENDING)
374 MsgInsertTicker("Unable to send message. It will be sent when service available.", SMS_MESSAGE_SENDING_PENDING, true, 0);
376 MsgInsertTicker("Sending SMS is failed", SMS_MESSAGE_SENDING_FAIL, true, pReqInfo->msgInfo.msgId);
391 void SmsPluginTransport::sendDeliverReport(msg_error_t err, sms_trans_p2p_msg_s *p_p2p_msg)
395 int tapiRet = TAPI_API_SUCCESS;
396 TelSmsResponse_t response;
398 sms_trans_msg_s trans_msg;
399 memset(&trans_msg, 0x00, sizeof(sms_trans_msg_s));
401 trans_msg.type = (sms_trans_msg_type_t)SMS_TRANS_ACK_MSG;
404 memcpy(&(trans_msg.data.ack_msg.address), &(p_p2p_msg->address), sizeof(sms_trans_addr_s));
406 sms_trans_cause_code_s cause_code;
407 memset(&cause_code, 0x00, sizeof(sms_trans_cause_code_s));
409 if (p_p2p_msg->reply_seq > 0)
410 cause_code.reply_seq = p_p2p_msg->reply_seq;
413 if (err == MSG_SUCCESS) {
414 cause_code.error_class = SMS_TRANS_ERR_CLASS_NONE;
416 response = TAPI_NETTEXT_SENDSMS_SUCCESS;
418 if (isMemAvailable == false) {
419 tapiRet = tel_set_sms_memory_status(pTapiHandle, TAPI_NETTEXT_PDA_MEMORY_STATUS_AVAILABLE, TapiEventMemoryStatus, NULL);
421 if (tapiRet == TAPI_API_SUCCESS)
422 MSG_DEBUG("######## tel_set_sms_memory_status() Success !!! #######");
424 MSG_DEBUG("######## tel_set_sms_memory_status() Failed !!! return : [%d] #######", tapiRet);
427 } else if (err == MSG_ERR_MESSAGE_COUNT_FULL) {
429 cause_code.error_class = SMS_TRANS_ERR_CLASS_TEMPORARY;
431 response = TAPI_NETTEXT_ME_FULL;
432 /* MsgInsertTicker("Not enough memory. Delete some items.", SMS_MESSAGE_MEMORY_FULL, true, 0); */
434 tapiRet = tel_set_sms_memory_status(pTapiHandle, TAPI_NETTEXT_PDA_MEMORY_STATUS_FULL, TapiEventMemoryStatus, NULL);
436 if (tapiRet == TAPI_API_SUCCESS)
437 MSG_DEBUG("######## tel_set_sms_memory_status() Success !!! #######");
439 MSG_DEBUG("######## tel_set_sms_memory_status() Failed !!! return : [%d] #######", tapiRet);
441 } else if (err == MSG_ERR_UNKNOWN) {
442 cause_code.error_class = SMS_TRANS_ERR_CLASS_TEMPORARY;
443 cause_code.cause_code = SMS_CAUSE_CODE_SERVICE_TERMINATION_DENIED;
445 response = TAPI_NETTEXT_SENDSMS_SUCCESS;
447 } else if (err == MSG_ERR_INVALID_MSG_TYPE) {
448 cause_code.error_class = SMS_TRANS_ERR_CLASS_PERMANENT;
449 cause_code.cause_code = SMS_CAUSE_CODE_INVAILD_TELESERVICE_ID;
451 response = TAPI_NETTEXT_INVALID_MSG;
453 cause_code.error_class = SMS_TRANS_ERR_CLASS_TEMPORARY;
454 response = TAPI_NETTEXT_SIM_FULL;
457 memcpy(&(trans_msg.data.ack_msg.cause_code), &(cause_code), sizeof(sms_trans_cause_code_s));
459 MSG_DEBUG("err : [%d], response : [%02x]", err, response);
463 unsigned char buf[512];
464 memset(buf, 0x00, sizeof(buf));
465 bufLen = SmsPluginMsgCodec::encodeMsg(&trans_msg, buf);
468 MSG_DEBUG("######## DeliverReport tpdu #########");
469 for (int i=0; i < bufLen; i++) {
470 printf("[%02x] ", buf[i]);
472 MSG_DEBUG("#################################");
474 /* Make Telephony Structure */
475 TelSmsDatapackageInfo_t pkgInfo;
477 pkgInfo.format = TAPI_NETTEXT_NETTYPE_3GPP2;
480 memset((void*)pkgInfo.szData, 0x00, sizeof(pkgInfo.szData));
481 memcpy((void*)pkgInfo.szData, buf, bufLen);
483 pkgInfo.szData[bufLen] = 0;
484 pkgInfo.MsgLength = bufLen;
487 /* Send Deliver Report */
488 tapiRet = tel_send_sms_deliver_report(pTapiHandle, &pkgInfo, response, TapiEventDeliveryReportCNF, NULL);
490 if (tapiRet == TAPI_API_SUCCESS)
491 MSG_DEBUG("######## tel_send_sms_deliver_report() Success !!! #######");
493 MSG_DEBUG("######## tel_send_sms_deliver_report() Fail !!! return : [%d] #######", tapiRet);
499 void SmsPluginTransport::setNetStatus(sms_network_status_t sentStatus)
502 curStatus = sentStatus;
508 sms_network_status_t SmsPluginTransport::getNetStatus()
514 if (curStatus == SMS_NETWORK_SENDING)
515 ret = cv.timedwait(mx.pMsgMutex(), 125);
519 if (ret == ETIMEDOUT) {
520 MSG_DEBUG("WARNING: SENT STATUS TIME-OUT");
521 curStatus = SMS_NETWORK_SEND_FAIL_TIMEOUT;