datacall_demo.c 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222
  1. /*============================================================================
  2. Copyright (c) 2020 Quectel Wireless Solution, Co., Ltd. All Rights Reserved.
  3. Quectel Wireless Solution Proprietary and Confidential.
  4. =============================================================================*/
  5. /*===========================================================================
  6. EDIT HISTORY FOR MODULE
  7. This section contains comments describing changes made to the module.
  8. Notice that changes are listed in reverse chronological order.
  9. WHEN WHO WHAT, WHERE, WHY
  10. ---------- ------------ ----------------------------------------------------
  11. =============================================================================*/
  12. #include <stdio.h>
  13. #include <string.h>
  14. #include <stdlib.h>
  15. #include "ql_api_osi.h"
  16. #include "ql_log.h"
  17. #include "ql_api_nw.h"
  18. #include "ql_api_datacall.h"
  19. #define QL_DATACALL_LOG_LEVEL QL_LOG_LEVEL_INFO
  20. #define QL_DATACALL_DEMO_LOG(msg, ...) QL_LOG(QL_DATACALL_LOG_LEVEL, "ql_datacall_demo", msg, ##__VA_ARGS__)
  21. #define QL_SIM_NUM 2
  22. typedef struct
  23. {
  24. bool state;
  25. ql_sem_t act_sem;
  26. ql_sem_t deact_sem;
  27. }datacall_context_s;
  28. ql_task_t datacall_task = NULL;
  29. ql_sem_t ql_data_reg_sem[QL_SIM_NUM] = {0};
  30. datacall_context_s datacall_ctx[QL_SIM_NUM][PROFILE_IDX_NUM] = {0};
  31. void ql_nw_ind_callback(uint8_t sim_id, unsigned int ind_type, void *ind_msg_buf)
  32. {
  33. if(QUEC_NW_DATA_REG_STATUS_IND == ind_type)
  34. {
  35. ql_nw_common_reg_status_info_s *data_reg_status=(ql_nw_common_reg_status_info_s *)ind_msg_buf;
  36. QL_DATACALL_DEMO_LOG("Sim%d data reg status changed, current status is %d", sim_id, data_reg_status->state);
  37. if((QL_NW_REG_STATE_HOME_NETWORK == data_reg_status->state) || (QL_NW_REG_STATE_ROAMING == data_reg_status->state))
  38. {
  39. ql_rtos_semaphore_release(ql_data_reg_sem[sim_id]);
  40. }
  41. }
  42. }
  43. void ql_datacall_ind_callback(uint8_t sim_id, unsigned int ind_type, int profile_idx, bool result, void *ctx)
  44. {
  45. QL_DATACALL_DEMO_LOG("nSim = %d, profile_idx=%d, ind_type=0x%x, result=%d", sim_id, profile_idx, ind_type, result);
  46. if((profile_idx < PROFILE_IDX_MIN) || (profile_idx > PROFILE_IDX_MAX))
  47. {
  48. return;
  49. }
  50. switch(ind_type)
  51. {
  52. case QUEC_DATACALL_ACT_RSP_IND: //only received in asyn mode
  53. {
  54. datacall_ctx[sim_id][profile_idx - 1].state = (result == true)? QL_PDP_ACTIVED:QL_PDP_DEACTIVED;
  55. ql_rtos_semaphore_release(datacall_ctx[sim_id][profile_idx - 1].act_sem);
  56. break;
  57. }
  58. case QUEC_DATACALL_DEACT_RSP_IND: //only received in asyn mode
  59. {
  60. datacall_ctx[sim_id][profile_idx - 1].state = (result == true)? QL_PDP_DEACTIVED:QL_PDP_ACTIVED;
  61. ql_rtos_semaphore_release(datacall_ctx[sim_id][profile_idx - 1].deact_sem);
  62. break;
  63. }
  64. case QUEC_DATACALL_PDP_DEACTIVE_IND: //received in both asyn mode and sync mode
  65. {
  66. datacall_ctx[sim_id][profile_idx - 1].state = QL_PDP_DEACTIVED;
  67. ql_event_t event={0};
  68. event.id = QUEC_DATACALL_PDP_DEACTIVE_IND;
  69. event.param1 = profile_idx;
  70. ql_rtos_event_send(datacall_task, &event);
  71. break;
  72. }
  73. }
  74. }
  75. static void datacall_app_thread(void * arg)
  76. {
  77. int ret = 0, retry_count = 0;
  78. uint8_t sim_id = 0;
  79. int profile_idx = 1; //range 1 to 7
  80. ql_nw_reg_status_info_s nw_info = {0};
  81. ql_data_call_info_s info ={0};
  82. ql_event_t event;
  83. ql_rtos_semaphore_create(&ql_data_reg_sem[sim_id], 0);
  84. ret = ql_nw_register_cb(ql_nw_ind_callback);
  85. if(0 != ret)
  86. {
  87. QL_DATACALL_DEMO_LOG("ql_nw_register_cb err, ret=0x%x", ret);
  88. goto exit;
  89. }
  90. ret = ql_nw_get_reg_status(sim_id, &nw_info);
  91. QL_DATACALL_DEMO_LOG("ret: 0x%x, current data reg status=%d", ret, nw_info.data_reg.state);
  92. if((QL_NW_REG_STATE_HOME_NETWORK != nw_info.data_reg.state) && (QL_NW_REG_STATE_ROAMING != nw_info.data_reg.state))
  93. {
  94. ql_rtos_semaphore_wait(ql_data_reg_sem[sim_id], QL_WAIT_FOREVER); //wait network registered
  95. }
  96. ret = ql_datacall_register_cb(sim_id, profile_idx, ql_datacall_ind_callback, NULL);
  97. QL_DATACALL_DEMO_LOG("ql_datacall_register_cb ret=0x%x", ret);
  98. ret = ql_set_data_call_asyn_mode(sim_id, profile_idx, 1); //If set to asynchronous mode, act_sem and deact_sem are need to be created
  99. ql_rtos_semaphore_create(&datacall_ctx[sim_id][profile_idx-1].act_sem, 0);
  100. ql_rtos_semaphore_create(&datacall_ctx[sim_id][profile_idx-1].deact_sem, 0);
  101. ret=ql_start_data_call(sim_id, profile_idx, QL_PDP_TYPE_IP, "cmnet", NULL, NULL, 0);
  102. if(0 != ret)
  103. {
  104. QL_DATACALL_DEMO_LOG("ql_start_data_call err, ret=0x%x", ret);
  105. goto exit;
  106. }
  107. ql_rtos_semaphore_wait(datacall_ctx[sim_id][profile_idx-1].act_sem, QL_WAIT_FOREVER); //wait QUEC_DATACALL_ACT_RSP_IND
  108. QL_DATACALL_DEMO_LOG("datacall state=%d", datacall_ctx[sim_id][profile_idx-1].state);
  109. ret = ql_get_data_call_info(sim_id, profile_idx, &info);
  110. QL_DATACALL_DEMO_LOG("ql_get_data_call_info ret: 0x%x", ret);
  111. QL_DATACALL_DEMO_LOG("info.profile_idx: %d, info.ip_version: %d", info.profile_idx, info.ip_version);
  112. QL_DATACALL_DEMO_LOG("info->v4.state: %d, info.v6.state: %d", info.v4.state, info.v6.state);
  113. if(info.v4.state)
  114. {
  115. QL_DATACALL_DEMO_LOG("info.v4.addr.ip: %s", ip4addr_ntoa(&(info.v4.addr.ip)));
  116. QL_DATACALL_DEMO_LOG("info.v4.addr.pri_dns: %s", ip4addr_ntoa(&(info.v4.addr.pri_dns)));
  117. QL_DATACALL_DEMO_LOG("info.v4.addr.sec_dns: %s", ip4addr_ntoa(&(info.v4.addr.sec_dns)));
  118. }
  119. if(info.v6.state)
  120. {
  121. QL_DATACALL_DEMO_LOG("info.v6.addr.ip: %s", ip6addr_ntoa(&(info.v6.addr.ip)));
  122. QL_DATACALL_DEMO_LOG("info.v6.addr.pri_dns: %s", ip6addr_ntoa(&(info.v6.addr.pri_dns)));
  123. QL_DATACALL_DEMO_LOG("info.v6.addr.sec_dns: %s", ip6addr_ntoa(&(info.v6.addr.sec_dns)));
  124. }
  125. while(1)
  126. {
  127. if(ql_event_try_wait(&event) != 0)
  128. {
  129. continue;
  130. }
  131. if(QUEC_DATACALL_PDP_DEACTIVE_IND == event.id)
  132. {
  133. ql_rtos_task_sleep_ms(5000); //wait network status update
  134. ret = ql_nw_get_reg_status(sim_id, &nw_info);
  135. if((QL_NW_REG_STATE_HOME_NETWORK != nw_info.data_reg.state) && (QL_NW_REG_STATE_ROAMING != nw_info.data_reg.state))
  136. {
  137. ql_rtos_semaphore_wait(ql_data_reg_sem[sim_id], QL_WAIT_FOREVER);
  138. }
  139. ret = ql_set_data_call_asyn_mode(sim_id, profile_idx, 0); //Set to sync mode
  140. //Try reconnect 10 times, time interval is 20 seconds
  141. while(((ret = ql_start_data_call(sim_id, profile_idx, QL_PDP_TYPE_IP, "cmnet", NULL, NULL, 0)) != QL_DATACALL_SUCCESS) && (retry_count < 10))
  142. {
  143. retry_count++;
  144. QL_DATACALL_DEMO_LOG("gprs reconnect fail, the retry count is %d", retry_count);
  145. ql_rtos_task_sleep_ms(20000);
  146. }
  147. if(QL_DATACALL_SUCCESS == ret)
  148. {
  149. retry_count = 0;
  150. datacall_ctx[sim_id][profile_idx - 1].state = QL_PDP_ACTIVED;
  151. ret = ql_get_data_call_info(sim_id, profile_idx, &info);
  152. QL_DATACALL_DEMO_LOG("ql_get_data_call_info ret: 0x%x", ret);
  153. QL_DATACALL_DEMO_LOG("info.profile_idx: %d, info.ip_version: %d", info.profile_idx, info.ip_version);
  154. QL_DATACALL_DEMO_LOG("info->v4.state: %d, info.v6.state: %d", info.v4.state, info.v6.state);
  155. if(info.v4.state)
  156. {
  157. QL_DATACALL_DEMO_LOG("info.v4.addr.ip: %s", ip4addr_ntoa(&(info.v4.addr.ip)));
  158. QL_DATACALL_DEMO_LOG("info.v4.addr.pri_dns: %s", ip4addr_ntoa(&(info.v4.addr.pri_dns)));
  159. QL_DATACALL_DEMO_LOG("info.v4.addr.sec_dns: %s", ip4addr_ntoa(&(info.v4.addr.sec_dns)));
  160. }
  161. if(info.v6.state)
  162. {
  163. QL_DATACALL_DEMO_LOG("info.v6.addr.ip: %s", ip6addr_ntoa(&(info.v6.addr.ip)));
  164. QL_DATACALL_DEMO_LOG("info.v6.addr.pri_dns: %s", ip6addr_ntoa(&(info.v6.addr.pri_dns)));
  165. QL_DATACALL_DEMO_LOG("info.v6.addr.sec_dns: %s", ip6addr_ntoa(&(info.v6.addr.sec_dns)));
  166. }
  167. }
  168. }
  169. }
  170. exit:
  171. ql_rtos_semaphore_delete(ql_data_reg_sem[sim_id]);
  172. ql_rtos_semaphore_delete(datacall_ctx[sim_id][profile_idx-1].act_sem);
  173. ql_rtos_semaphore_delete(datacall_ctx[sim_id][profile_idx-1].deact_sem);
  174. ql_datacall_unregister_cb(sim_id, profile_idx, ql_datacall_ind_callback, NULL);
  175. ql_rtos_task_delete(datacall_task);
  176. }
  177. void ql_datacall_app_init(void)
  178. {
  179. QlOSStatus err = QL_OSI_SUCCESS;
  180. err = ql_rtos_task_create(&datacall_task, 4*1024, APP_PRIORITY_NORMAL, "QDATACALLDEMO", datacall_app_thread, NULL, 10);
  181. if(err != QL_OSI_SUCCESS)
  182. {
  183. QL_DATACALL_DEMO_LOG("task created failed");
  184. return;
  185. }
  186. }