blob: 7323949742b3b69f10e8486cfb8f8d6e22c91f64 [file] [log] [blame]
b.liud440f9f2025-04-18 10:44:31 +08001/*-----------------------------------------------------------------------------------------------*/
2/**
3 @file ql_sms.h
4 @brief SMS service API.
5*/
6/*-----------------------------------------------------------------------------------------------*/
7
8/*-------------------------------------------------------------------------------------------------
9 Copyright (c) 2019 Quectel Wireless Solution, Co., Ltd. All Rights Reserved.
10 Quectel Wireless Solution Proprietary and Confidential.
11-------------------------------------------------------------------------------------------------*/
12
13/*-------------------------------------------------------------------------------------------------
14 EDIT HISTORY
15 This section contains comments describing changes made to the file.
16 Notice that changes are listed in reverse chronological order.
17 $Header: $
18 when who what, where, why
19 -------- --- ----------------------------------------------------------
20 20200107 solomon.cui Add GSM-7bit and ISO 8859-1 conversion.
21 20191225 solomon.cui Modify fucntion description.
22 20191017 solomon.cui Free async reponse not user data.
23 20190815 solomon.cui Add service type for sending message.
24 20190627 solomon.cui Support asynchronously send msg and pdu
25 20190625 solomon.cui Convert timestamp frome hex to dec.
26 20190614 solomon.cui Created .
27-------------------------------------------------------------------------------------------------*/
28#include "mbtk_type.h"
29#include "mbtk_pdu_sms.h"
30#include "mbtk_ril_api.h"
31#include "mbtk_log.h"
32#include "ql_sms.h"
33#include "ql_type.h"
34
35#include <stdint.h>
36#include <stdio.h>
37#include <stdlib.h>
38#include <sys/epoll.h>
39#include <unistd.h>
40#include <errno.h>
41#include <pthread.h>
42#include <string.h>
43#include <fcntl.h>
44#include <time.h>
45
46#define MBTK_ERR_OK 0
47#define TELEPHONE_NUM_MAX 16
48#define MSM_NUMBER_MAX 2048+1
49#define RES_NUM_MIN 128
50#define TIME_ZONE_CN 32
51#define HAL_SMS_CONTENT_LEN 1024
52
53typedef struct {
54 mbtk_ril_handle* handle;
55 ql_sms_msg_recv_cb_f recv_cb;
56 ql_sms_service_error_cb_f server_cb;
57}ql_sms_info_handle_t;
58
59
60static ql_sms_info_handle_t* sms_handle = NULL;
61
62static void ql_sms_state_change_cb(const void* data, int data_len)
63{
64 LOGV("sms_state_change_cb()----------start\n");
65 mbtk_ril_sms_state_info_t *ptr = (mbtk_ril_sms_state_info_t *)data;
66
67 ql_sms_msg_t sms_msg;
68 ql_sms_timestamp_t sms_timestamp;
69 ql_sms_user_data_head_t sms_user_data_head;
70
71 memset(&sms_msg,0x00, sizeof(ql_sms_msg_t));
72 memset(&sms_timestamp,0x00, sizeof(ql_sms_timestamp_t));
73 memset(&sms_user_data_head,0x00, sizeof(ql_sms_user_data_head_t));
74
75 char smsc[MDAPI_MAX_PDU_SIZE] = {0};
76 char received_pdu[MDAPI_MAX_PDU_SIZE] = {0};
77 char msg[MDAPI_MAX_PDU_SIZE] = {0};
78 char num[MDAPI_MAX_PDU_SIZE] = {0};
79 uint8 year[8] = {0};
80 uint8 month[4] = {0};
81 uint8 day[4] = {0};
82 uint8 hour[4] = {0};
83 uint8 minutes[4]= {0};
84 uint8 seconds[4]= {0};
85 //char timezone[4] = {0};
86 char date[32] = {0};
87 int charset = 0;
88 int ret = -1;
89 int curr_pack = 1;
90 int total_pack = 1;
91 if(ptr == NULL)
92 {
93 LOGE("ptr is null");
94 }
95 LOGE("ptr: %s\n,data_len = %d\n", (char *)ptr->pdu, data_len);
96 if(data_len > MDAPI_MAX_PDU_SIZE)
97 {
98 strncpy(received_pdu, (const char *)ptr->pdu, MDAPI_MAX_PDU_SIZE-1);
99 }
100 else
101 {
102 strncpy(received_pdu, (const char *)ptr->pdu, data_len);
103 }
104 ret = smsPduDecode((const char *)received_pdu, data_len, num, smsc, msg, &charset, &curr_pack, &total_pack,date);
105 if(ret != 0)
106 {
107 LOGE("smsPduDecode fail ret: %d\n",ret);
108 return ;
109 }
110
111 LOGE("[EVENT][MT_SMS]PDU decode:smsc: %s\n, phone number: %s\ncharset: %d\n msg_len: %d\n message content: %s\n curr_pack: %d\n total_pack: %d\n date: %s", smsc, num, charset, strlen(msg), msg, curr_pack, total_pack, date);
112
113 sms_msg.format = charset;
114 memcpy(sms_msg.addr, num, strlen(num));
115 sms_msg.content_size = strlen(msg);
116 memcpy(sms_msg.content, msg, strlen(msg));
117
118 if(sscanf(date, "%4[^-]-%2[^-]-%2[^ ] %2[^:]:%2[^:]:%2s", year, month, day, hour, minutes, seconds)<=0)
119 {
120 LOGE("sscanf failed\n");
121 }
122
123 int tmp_year = atoi((char *)year);
124
125 sms_timestamp.year = tmp_year-2000;
126 sms_timestamp.month = atoi((char *)month);
127 sms_timestamp.day = atoi((char *)day);
128 sms_timestamp.hours = atoi((char *)hour);
129 sms_timestamp.minutes = atoi((char *)minutes);
130 sms_timestamp.seconds = atoi((char *)seconds);
131 sms_timestamp.timezone = TIME_ZONE_CN;
132
133 LOGE("Year: %d\n", sms_timestamp.year);
134 LOGE("Month: %d\n", sms_timestamp.month);
135 LOGE("Day: %d\n", sms_timestamp.day);
136 LOGE("Hour: %d\n", sms_timestamp.hours);
137 LOGE("Minute: %d\n", sms_timestamp.minutes);
138 LOGE("Second: %d\n", sms_timestamp.seconds);
139
140 if(total_pack > 1 && curr_pack < total_pack)
141 {
142 sms_user_data_head.valid = TRUE;
143 sms_user_data_head.total_seg = total_pack;
144 sms_user_data_head.cur_seg_num = curr_pack;
145 }
146 else
147 {
148 sms_user_data_head.valid = FALSE;
149 sms_user_data_head.total_seg = total_pack;
150 sms_user_data_head.cur_seg_num = curr_pack;
151 }
152
153 if(sms_handle->recv_cb)
154 {
155 sms_handle->recv_cb(&sms_msg, &sms_timestamp, &sms_user_data_head);
156 }
157
158}
159
160static void ql_sms_server_change_cb(const void* data, int data_len)
161{
162 if(data_len != sizeof(int))
163 {
164 LOGE("[ql_sms_server_change_cb] data_len[%d] than int[%d] fail. ", data_len, sizeof(int));
165 }
166 else
167 {
168 int server_state = *(int *)data;
169 if(server_state == 1 && sms_handle->server_cb)
170 {
171 sms_handle->server_cb(QL_ERR_ABORTED);
172 }
173 }
174}
175
176
177/*-----------------------------------------------------------------------------------------------*/
178/**
179 @brief Initializes SMS service.
180 @return Whether the SMS service was initialized successfully.
181 @retval QL_ERR_OK successful.
182 @retval QL_ERR_UNKNOWN unknown error, failed to connect to service.
183 @retval QL_ERR_SERVICE_NOT_READY service is not ready, need to retry.
184 @retval Other error code defined by ql_type.h.
185 */
186/*-----------------------------------------------------------------------------------------------*/
187int ql_sms_init(void)
188{
189 if(NULL == sms_handle)
190 {
191 sms_handle = (ql_sms_info_handle_t*)malloc(sizeof(ql_sms_info_handle_t));
192 if(NULL == sms_handle)
193 {
194 LOGE("[ql_sms_init] sms handle malloc fail.");
195 return QL_ERR_FAILED;
196 }
197
198 sms_handle->handle = mbtk_ril_open(MBTK_AT_PORT_DEF);
199 if(NULL == sms_handle->handle)
200 {
201 LOGE("[ql_sms_init] mbtk handle init fail.");
202 if(sms_handle)
203 {
204 free(sms_handle);
205 sms_handle = NULL;
206 return QL_ERR_FAILED;
207 }
208 }
209
210 int err = mbtk_sms_cnmi_set(sms_handle->handle);
211 if(err)
212 {
213 LOGE("set cnmi fail");
214 return QL_ERR_FAILED;
215 }
216
217 int ret = mbtk_sms_state_change_cb_reg( ql_sms_state_change_cb);
218 if(ret != MBTK_ERR_OK)
219 {
220 LOGE("[ql_sms_init] set sms state cb fail.[%d]", ret);
221 if(sms_handle->handle)
222 {
223 mbtk_ril_close(MBTK_AT_PORT_DEF);
224 sms_handle->handle = NULL;
225 return QL_ERR_FAILED;
226 }
227 }
228
229 ret = mbtk_net_reg_state_change_cb_reg(ql_sms_server_change_cb);
230 if(ret != MBTK_ERR_OK)
231 {
232 LOGE("[ql_sim_init] set sim server cb fail.[%d]", ret);
233 if(sms_handle->handle)
234 {
235 mbtk_ril_close(MBTK_AT_PORT_DEF);
236 sms_handle->handle = NULL;
237 return QL_ERR_FAILED;
238 }
239 }
240
241 sms_handle->recv_cb = NULL;
242 sms_handle->server_cb = NULL;
243 }
244
245 return QL_ERR_OK;
246
247}
248
249/*-----------------------------------------------------------------------------------------------*/
250/**
251 @brief Deinitializes SMS service.
252 @return Whether the SMS service was deinitialized successfully.
253 @retval QL_ERR_OK successful.
254 @retval QL_ERR_UNKNOWN unknown error, failed to connect to service.
255 @retval QL_ERR_SERVICE_NOT_READY service is not ready, need to retry.
256 @retval Other error code defined by ql_type.h.
257 */
258/*-----------------------------------------------------------------------------------------------*/
259int ql_sms_deinit(void)
260{
261 if(NULL == sms_handle)
262 {
263 LOGE("[ql_sms_deinit] sms handle not init.");
264 return QL_ERR_NOT_INIT;
265 }
266
267 int ret = 0;
268 sms_handle->server_cb = NULL;
269 sms_handle->recv_cb = NULL;
270
271 if(NULL != sms_handle->handle)
272 {
273 ret = mbtk_ril_close(MBTK_AT_PORT_DEF);
274 if(ret != MBTK_ERR_OK)
275 {
276 LOGE("[ql_sms_deinit] mbtk handle deinit fail.[%d]", ret);
277 return QL_ERR_FAILED;
278 }
279 sms_handle->handle = NULL;
280 }
281
282 if(ret != QL_ERR_OK)
283 {
284 LOGE("[ql_sms_deinit] cb thread free deinit fail.");
285 return QL_ERR_FAILED;
286 }
287
288 free(sms_handle);
289 sms_handle = NULL;
290 return QL_ERR_OK;
291
292}
293
294/*-----------------------------------------------------------------------------------------------*/
295/**
296 @brief Sets the service center address.
297 @param[in] addr service center address.
298 @param[in] len service center address length.
299 @return Whether the service center address was set successfully.
300 @retval QL_ERR_OK successful.
301 @retval QL_ERR_INVALID_ARG invalid argument.
302 @retval QL_ERR_UNKNOWN unknown error, failed to connect to service.
303 @retval QL_ERR_SERVICE_NOT_READY service is not ready, need to retry.
304 @retval Other error code defined by ql_type.h.
305 */
306/*-----------------------------------------------------------------------------------------------*/
307int ql_sms_set_service_center_addr(char *addr, int len);
308
309/*-----------------------------------------------------------------------------------------------*/
310/**
311 @brief Gets the service center address.
312 @param[out] addr service center address.
313 @param[in] len service center address length.
314 @return Whether the service center address was successfully obtained.
315 @retval QL_ERR_OK successful.
316 @retval QL_ERR_INVALID_ARG invalid argument.
317 @retval QL_ERR_UNKNOWN unknown error, failed to connect to service.
318 @retval QL_ERR_SERVICE_NOT_READY service is not ready, need to retry.
319 @retval Other error code defined by ql_type.h.
320 */
321/*-----------------------------------------------------------------------------------------------*/
322int ql_sms_get_service_center_addr(char *addr, int len);
323
324/*-----------------------------------------------------------------------------------------------*/
325/**
326 @brief Sends message synchronously.
327 @param[in] p_msg pointer to ql_sms_msg_t.
328 @return Whether the message was successfully sent synchronously.
329 @retval QL_ERR_OK successful.
330 @retval QL_ERR_INVALID_ARG invalid argument.
331 @retval QL_ERR_UNKNOWN unknown error, failed to connect to service.
332 @retval QL_ERR_SERVICE_NOT_READY service is not ready, need to retry.
333 @retval Other error code defined by ql_type.h.
334 */
335/*-----------------------------------------------------------------------------------------------*/
336int ql_sms_send_msg(ql_sms_msg_t *p_msg);
337
338/*-----------------------------------------------------------------------------------------------*/
339/**
340 @brief Sends message asynchronously.
341 @param[in] p_msg pointer to ql_sms_msg_t
342 @param[out] id id for this async operation
343 @param[in] cb async callback
344 @return Whether the message was successfully sent asynchronously.
345 @retval QL_ERR_OK successful.
346 @retval QL_ERR_INVALID_ARG invalid argument.
347 @retval QL_ERR_UNKNOWN unknown error, failed to connect to service.
348 @retval QL_ERR_SERVICE_NOT_READY service is not ready, need to retry.
349 @retval Other error code defined by ql_type.h.
350 */
351/*-----------------------------------------------------------------------------------------------*/
352int ql_sms_send_msg_async(ql_sms_msg_t *p_msg, int *id, ql_sms_msg_async_cb_f cb)
353{
354 if (NULL == sms_handle)
355 {
356 LOGE("handle NULL");
357 return QL_ERR_FAILED;
358 }
359
360 if (NULL == p_msg)
361 {
362 LOGE("p_msgt NULL");
363 return QL_ERR_FAILED;
364 }
365
366 if(NULL == id)
367 {
368 LOGE("id NULL");
369 return QL_ERR_FAILED;
370 }
371
372 int8 *phone_num = NULL;
373 int8 *msg = NULL;
374 int32 msg_len;
375
376 char cmgs[MSM_NUMBER_MAX] = {0};
377 char resp[RES_NUM_MIN] = {0};
378
379 char smscPDU[30] = {0};
380 char **pdu = NULL;
381 char smsc[4] = {0};
382 char msg_e_b[HAL_SMS_CONTENT_LEN] = {0};// +1 for end of string.*2:A char array contains two elements of a string for each value
383
384 int char_set = 0;
385 //int lsms_flag = 0;
386 int err = 0;
387 int i = 0;
388
389 msg = (int8 *)p_msg->content;
390
391 msg_len = strlen(p_msg->content);
392
393 phone_num = (int8 *)p_msg->addr;
394
395 if (p_msg->format == 0)//7
396 char_set = 0;
397 else if (p_msg->format == 1)//8
398 char_set = 1;
399 else if (p_msg->format == 2)//UCS2
400 char_set = 2;
401 else
402 {
403 LOGE("ql_sms_send_msg_async format error");
404 return QL_ERR_FAILED;
405 }
406
407 if(strcmp((char*)msg,"") == 0 || msg[0] == '\0')
408 {
409 LOGE("ql_sms_send_msg_async msg [%s]",msg);
410 return QL_ERR_FAILED;
411 }
412
413 if(strcmp((char*)phone_num,"") == 0 || phone_num[0] == '\0')
414 {
415 LOGE("ql_sms_send_msg_async phone_num [%s]",phone_num);
416 return QL_ERR_FAILED;
417 }
418
419 kal_int32 msg_num = 0;
420 kal_int32 pdu_msg_len = 0;
421 kal_int32 status = MDAPI_RET_ERROR;
422 kal_int32 index = 0;
423
424 if(char_set == 1) //8bit
425 {
426 ArrayToStr((unsigned char *)msg, (unsigned int)msg_len, msg_e_b);
427 status = _mdapi_sms_get_msg_num(msg_e_b, char_set, &msg_num, &pdu_msg_len);
428 }
429 else //7bit usc2
430 {
431 status = _mdapi_sms_get_msg_num((char *)msg, char_set, &msg_num, &pdu_msg_len);
432 }
433
434 LOGE("msg_len = [%d] ,msg_num=[%d]",msg_len, msg_num);
435 if(status == MDAPI_RET_ERROR)
436 {
437 LOGE("get message number failed");
438 return QL_ERR_FAILED;
439 }
440 else
441 {
442 //allocate memery for **pdu
443 pdu = (char **)malloc(sizeof(char *) * msg_num);
444 if(pdu == NULL)
445 {
446 LOGE("allocate memory for pdu failed");
447 return QL_ERR_FAILED;
448 }
449 else
450 {
451 for(index = 0; index < msg_num; index++)
452 {
453 pdu[index] = (char *)malloc(sizeof(char)*MAX_PDU_SIZE);
454 if(pdu[index] == NULL)
455 {
456 for(i = 0; i < index; i++)
457 {
458 free(pdu[i]);
459 pdu[i] = NULL;
460 }
461 free(pdu);
462 pdu = NULL;
463 LOGE("allocate memory for pdu[%d] failed",index);
464 return QL_ERR_FAILED;
465 }
466 else
467 {
468 memset(pdu[index], 0, MAX_PDU_SIZE);
469 LOGE("pdu[%d} init value is: %s ",index, pdu[index]);
470 }
471 }
472 }
473 }
474
475 //allocate memory for **pdu success
476 if(index == msg_num)
477 {
478 if(char_set == 1)//8bit
479 {
480 smsPduEncode(smsc, (char *)phone_num, msg_e_b, char_set, smscPDU, pdu);
481 }
482 else
483 {
484 smsPduEncode(smsc, (char *)phone_num, (char *)msg, char_set, smscPDU, pdu);
485 }
486 for(index = 0; index < msg_num; index++)
487 {
488 char pdu_data[MAX_PDU_SIZE] = {0};
489 char *p = pdu_data;
490
491 LOGE("index:%d",index);
492 LOGE("smscPDU: %s, pdu: %s",smscPDU, pdu[index]);
493 sprintf(p, "%s",smscPDU);
494 LOGE("pdu_data:%s\n", pdu_data);
495 int sc = strlen(pdu_data);
496 sprintf(p+strlen(p), "%s", pdu[index]);
497 LOGE("pdu_data:%s", pdu_data);
498
499 int t = strlen(pdu_data);
500 sprintf(cmgs, "%d,%s", (t-sc)/2, pdu_data);
501 LOGE("cmgs:%s\n", cmgs);
502 memset(resp, 0, sizeof(resp));
503
504 err = mbtk_sms_cmgf_set(sms_handle->handle, 0);
505 if(err)
506 {
507 LOGE("cmgf set error : %d", err);
508 for(index = 0; index < msg_num; index++){
509 free(pdu[index]);
510 pdu[index] = NULL;
511 }
512 free(pdu);
513 pdu = NULL;
514 return QL_ERR_FAILED;
515 }
516 else
517 {
518 LOGD("cmgf set success");
519 }
520
521 err = mbtk_sms_cmgs_set(sms_handle->handle, cmgs, resp);
522 if(err)
523 {
524 LOGE("cmgs send fail (%d)",err);
525 for(index = 0; index < msg_num; index++){
526 free(pdu[index]);
527 pdu[index] = NULL;
528 }
529 free(pdu);
530 pdu = NULL;
531 return QL_ERR_FAILED;
532 }
533 else
534 {
535 LOGD("cmgs send success, resp:%s", resp);
536 }
537
538 }
539 }
540
541 for(index = 0; index < msg_num; index++){
542 free(pdu[index]);
543 pdu[index] = NULL;
544 }
545 free(pdu);
546 pdu = NULL;
547
548 *id = 1;
549 cb(1, 1);
550
551 return QL_ERR_OK;
552}
553
554/*-----------------------------------------------------------------------------------------------*/
555/**
556 @brief Sets SMS message reception callback hanlder.
557 @param[in] cb message reception callback handler.
558 @return Whether the message reception callback hanlder was set successfully.
559 @retval QL_ERR_OK successful.
560 @retval QL_ERR_INVALID_ARG invalid argument.
561 @retval QL_ERR_UNKNOWN unknown error, failed to connect to service.
562 @retval QL_ERR_SERVICE_NOT_READY service is not ready, need to retry.
563 @retval Other error code defined by ql_type.h.
564 */
565/*-----------------------------------------------------------------------------------------------*/
566int ql_sms_set_msg_recv_cb(ql_sms_msg_recv_cb_f cb)
567{
568 if(NULL == sms_handle)
569 {
570 LOGE("[ql_sms_set_msg_recv_cb] sms handle not init.");
571 return QL_ERR_NOT_INIT;
572 }
573
574 sms_handle->recv_cb = cb;
575
576 return QL_ERR_OK;
577
578}
579
580/*-----------------------------------------------------------------------------------------------*/
581/**
582 @brief Sends PDU synchronously.
583 @param[in] p_pdu SMS PDU.
584 @return Whether the PDU was successfully sent synchronously.
585 @retval QL_ERR_OK successful.
586 @retval QL_ERR_INVALID_ARG invalid argument.
587 @retval QL_ERR_UNKNOWN unknown error, failed to connect to service.
588 @retval QL_ERR_SERVICE_NOT_READY service is not ready, need to retry.
589 @retval Other error code defined by ql_type.h.
590 */
591/*-----------------------------------------------------------------------------------------------*/
592int ql_sms_send_pdu(ql_sms_pdu_t *p_pdu);
593
594/*-----------------------------------------------------------------------------------------------*/
595/**
596 @brief Sends PDU asynchronously.
597 @param[in] p_pdu sms pdu.
598 @param[out] id id for this async operation.
599 @param[in] cb async callback.
600 @return Whether the PDU was successfully sent asynchronously.
601 @retval QL_ERR_OK successful.
602 @retval QL_ERR_INVALID_ARG invalid argument.
603 @retval QL_ERR_UNKNOWN unknown error, failed to connect to service.
604 @retval QL_ERR_SERVICE_NOT_READY service is not ready, need to retry.
605 @retval Other error code defined by ql_type.h.
606 */
607/*-----------------------------------------------------------------------------------------------*/
608int ql_sms_send_pdu_async(ql_sms_pdu_t *p_pdu, int *id, ql_sms_pdu_async_cb_f cb);
609
610/*-----------------------------------------------------------------------------------------------*/
611/**
612 @brief Sets SMS PDU reception callback hanlder.
613 @param[in] cb PDU reception callback handler.
614 @return Whether the PDU reception callback hanlder was set successfully.
615 @retval QL_ERR_OK successful.
616 @retval QL_ERR_INVALID_ARG invalid argument.
617 @retval QL_ERR_UNKNOWN unknown error, failed to connect to service.
618 @retval QL_ERR_SERVICE_NOT_READY service is not ready, need to retry.
619 @retval Other error code defined by ql_type.h.
620 */
621/*-----------------------------------------------------------------------------------------------*/
622int ql_sms_set_pdu_recv_cb(ql_sms_pdu_recv_cb_f cb);
623
624/*-----------------------------------------------------------------------------------------------*/
625/**
626 @brief Registration server error callback. Currently, only if the server exits abnormally,
627 the callback function will be executed, and the error code is QL_ERR_ABORTED;
628 @param[in] cb Callback function
629 @return
630 QL_ERR_OK - successful
631 Other - error code defined by ql_type.h
632 */
633/*-----------------------------------------------------------------------------------------------*/
634int ql_sms_set_service_error_cb(ql_sms_service_error_cb_f cb)
635{
636 if(NULL == sms_handle)
637 {
638 LOGE("[ql_sms_set_service_error_cb] sms handle not init.");
639 return QL_ERR_NOT_INIT;
640 }
641
642 sms_handle->server_cb = cb;
643
644 return QL_ERR_OK;
645}
646
647/*-----------------------------------------------------------------------------------------------*/
648/**
649 @brief Binds the current control point to a specific subscription.
650 @param[in] sub Subscription type.
651 @return Whether the subscription was successfully bound.
652 @retval QL_ERR_OK successful.
653 @retval QL_ERR_INVALID_ARG invalid argument.
654 @retval QL_ERR_UNKNOWN unknown error, failed to connect to service.
655 @retval QL_ERR_SERVICE_NOT_READY service is not ready, need to retry.
656 @retval Other error code defined by ql_type.h.
657 */
658/*-----------------------------------------------------------------------------------------------*/
659int ql_sms_bind_subscription(QL_SMS_SUBSCRIPTION_E sub);
660