高通9X07模塊QMI架構使用入門


QMI(Qualcomm Message Interface) 高通用來替代OneRPC/DM的協議,用來與modem通信。
本文是摸索高通QMI機制一點經驗,重點解讀了如果建立撥號連接,僅供參考。qmi詳細使用參考:高通QMI協議

1. QMI協議常用組件

  • DMS(設備管理Device Management)
    提供查詢設備信息功能
    參考: qmi/device_management_service_v01.h
  • NAS(網絡訪問Network Access)
    提供網絡管理功能
    參考:qmi/network_access_service_v01.h
  • WDS(數據連接)
    參考:qmi/wireless_data_service_v01.h
  • UIM(管理User Identity Module)
    提供查詢UIM卡信息
    參考:qmi/user_identity_module_v01.h
  • CTL(控制服務)
    用戶發起其他服務請求前,必須先申請 ClientID, 這個ID就是由控制服務分配的, 這個服務永遠在線
    參考:qmi/control_service_v01.h
  • 數據(撥號服務)
    建立數據連接
    參考:data/qualcomm_mobile_access_point_msgr_v01.h

每個服務模塊都定義了 請求響應通知Indication, 請求分為同步和異步,其中異步請求的結果通過indication通知。

2. QMI舉例

越來越多9X07模塊被用於物聯網,那么首要解決的問題即建立數據連接,所以本文使用QMI建立數據網絡連接示意。

2.1 QMI初始化及釋放

9X07模塊提供了qcmap_msgr服務來進行撥號,通過與dsi_netctrl對比,qcmap_msgr接口更清晰,而且操作也簡單。
AP側使用QMI架構和modem通信初始化流程是固定的:

qcmap_msgr_get_service_object_v01查詢服務對象 =>
qmi_client_notifier_init初始化client通知信息 =>
qmi_client_get_service_list查詢支持的服務列表個數 =>
qmi_client_get_service_list查詢支持的服務列表信息 =>
qmi_client_init使用其中一個服務信息初始化client
參考代碼:

 1 void qcmap_ppp_init(qcmap_ppp_t *self,client_status_ind_t client_cb_ind) {
 2     qmi_idl_service_object_type qcmap_msgr_qmi_idl_service_object;
 3     uint32_t num_services = 0, num_entries = 0;
 4     qmi_service_info info[10];
 5     qmi_client_error_type qmi_error, qmi_err_code = QMI_NO_ERR;
 6 
 7     assert(self);
 8     
 9     self->qcmap_msgr_enable = FALSE;
10     self->qmi_qcmap_msgr_handle = 0;
11     self->mobile_ap_handle = 0;
12 
13     qcmap_msgr_qmi_idl_service_object = qcmap_msgr_get_service_object_v01;//when faild, add your trick for this~
14 
15     if (qcmap_msgr_qmi_idl_service_object == NULL)
16     {
17         LOG("qcmap_msgr service object not available");
18         return;
19     }
20 
21     qmi_error = qmi_client_notifier_init(qcmap_msgr_qmi_idl_service_object,
22                                         &self->qmi_qcmap_msgr_os_params,
23                                         &self->qmi_qcmap_msgr_notifier);
24     if (qmi_error < 0)
25     {
26         LOG("qmi_client_notifier_init(qcmap_msgr) returned %d", qmi_error);
27         return;
28     }
29 
30     /* Check if the service is up, if not wait on a signal */
31     while(1)
32     {
33         qmi_error = qmi_client_get_service_list(qcmap_msgr_qmi_idl_service_object,
34                                                 NULL,
35                                                 NULL,
36                                                 &num_services);
37         LOG("qmi_client_get_service_list: %d",qmi_error);
38 
39         if(qmi_error == QMI_NO_ERR)
40             break;
41         /* wait for server to come up */
42         QMI_CCI_OS_SIGNAL_WAIT(&self->qmi_qcmap_msgr_os_params, 0);
43     }
44 
45     num_entries = num_services;
46 
47     LOG("qmi_client_get_service_list: num_e %d num_s %d", num_entries, num_services);
48     /* The server has come up, store the information in info variable */
49     qmi_error = qmi_client_get_service_list(qcmap_msgr_qmi_idl_service_object,
50                                             info,
51                                             &num_entries,
52                                             &num_services);
53 
54     LOG("qmi_client_get_service_list: num_e %d num_s %d error %d", num_entries, num_services, qmi_error);
55 
56     if (qmi_error != QMI_NO_ERR)
57     {
58         qmi_client_release(self->qmi_qcmap_msgr_notifier);
59         self->qmi_qcmap_msgr_notifier = NULL;
60         LOG("Can not get qcmap_msgr service list %d",
61             qmi_error);
62         return;
63     }
64 
65     qmi_error = qmi_client_init(&info[0],
66                                 qcmap_msgr_qmi_idl_service_object,
67                                 client_cb_ind,
68                                 NULL,
69                                 NULL,
70                                 &self->qmi_qcmap_msgr_handle);
71 
72     LOG("qmi_client_init: %d", qmi_error);
73 
74     if (qmi_error != QMI_NO_ERR)
75     {
76         qmi_client_release(self->qmi_qcmap_msgr_notifier);
77         self->qmi_qcmap_msgr_notifier = NULL;
78         LOG("Can not init qcmap_msgr client %d", qmi_error);
79         return;
80     }
81 }

 

對應釋放過程比較簡單,主要是釋放client初始化信息:

 1 static void qcmap_ppp_uninit(qcmap_ppp_t *self) {
 2     qmi_client_error_type qmi_error;
 3     assert(self);
 4 
 5     qmi_error = qmi_client_release(self->qmi_qcmap_msgr_notifier);
 6     self->qmi_qcmap_msgr_notifier = NULL;
 7 
 8     if (qmi_error != QMI_NO_ERR)
 9     {
10         LOG("Can not release client qcmap notifier %d",qmi_error);
11     }
12 
13     qmi_error = qmi_client_release(self->qmi_qcmap_msgr_handle);
14     self->qmi_qcmap_msgr_handle = NULL;
15 
16     if (qmi_error != QMI_NO_ERR)
17     {
18         LOG("Can not release client qcmap handle %d",qmi_error);
19     }
20 }

 

2.2 建立/關閉撥號連接

建立撥號步驟:使能AP,連接服務

  • 使能ap
  1 /* Enable MobileAP */
  2 static boolean qcmap_ppp_enable(qcmap_ppp_t *self) {
  3     qmi_client_error_type qmi_error, qmi_err_code = QMI_NO_ERR;
  4     qcmap_msgr_mobile_ap_enable_resp_msg_v01 qcmap_enable_resp_msg_v01;
  5     qcmap_msgr_mobile_ap_status_ind_register_req_msg_v01 qcmap_mobile_ap_status_ind_reg;
  6     qcmap_msgr_wwan_status_ind_register_req_msg_v01 wwan_status_ind_reg;
  7     qcmap_msgr_station_mode_status_ind_register_req_msg_v01 qcmap_station_mode_status_ind_reg;
  8     qcmap_msgr_mobile_ap_status_ind_register_resp_msg_v01 qcmap_mobile_ap_status_ind_rsp;
  9     qcmap_msgr_wwan_status_ind_register_resp_msg_v01 wwan_status_ind_rsp;
 10     qcmap_msgr_station_mode_status_ind_register_resp_msg_v01 qcmap_station_mode_status_ind_rsp;
 11 
 12     memset(&qcmap_enable_resp_msg_v01, 0, sizeof(qcmap_msgr_mobile_ap_enable_resp_msg_v01));
 13     memset(&wwan_status_ind_reg, 0, sizeof(qcmap_msgr_wwan_status_ind_register_req_msg_v01));
 14     memset(&wwan_status_ind_rsp, 0, sizeof(qcmap_msgr_wwan_status_ind_register_resp_msg_v01));
 15     wwan_status_ind_reg.register_indication = 1;
 16 
 17     qmi_error = qmi_client_send_msg_sync(self->qmi_qcmap_msgr_handle,
 18                                             QMI_QCMAP_MSGR_WWAN_STATUS_IND_REG_REQ_V01,
 19                                             (void*)&wwan_status_ind_reg,
 20                                             sizeof(qcmap_msgr_wwan_status_ind_register_req_msg_v01),
 21                                             (void*)&wwan_status_ind_rsp,
 22                                             sizeof(qcmap_msgr_wwan_status_ind_register_resp_msg_v01),
 23                                             QCMAP_MSGR_QMI_TIMEOUT_VALUE);
 24 
 25     LOG("qmi_client_send_msg_sync: error %d result %d",
 26                     qmi_error, wwan_status_ind_rsp.resp.result);
 27 
 28     if (( qmi_error == QMI_TIMEOUT_ERR ) ||
 29         ( qmi_error != QMI_NO_ERR ) ||
 30         ( wwan_status_ind_rsp.resp.result != QMI_NO_ERR ))
 31     {
 32         LOG("Can not register for wwan status %d : %d",
 33                     qmi_error, wwan_status_ind_rsp.resp.error);
 34         return FALSE;
 35     }
 36     LOG("Registered for wwan status");
 37 
 38     memset(&qcmap_mobile_ap_status_ind_reg, 0, sizeof(qcmap_msgr_mobile_ap_status_ind_register_req_msg_v01));
 39     memset(&qcmap_mobile_ap_status_ind_rsp, 0, sizeof(qcmap_msgr_mobile_ap_status_ind_register_resp_msg_v01));
 40     qcmap_mobile_ap_status_ind_reg.register_indication = 1;
 41 
 42     qmi_error = qmi_client_send_msg_sync(self->qmi_qcmap_msgr_handle,
 43                                         QMI_QCMAP_MSGR_MOBILE_AP_STATUS_IND_REG_REQ_V01,
 44                                         (void*)&qcmap_mobile_ap_status_ind_reg,
 45                                         sizeof(qcmap_msgr_mobile_ap_status_ind_register_req_msg_v01),
 46                                         (void*)&qcmap_mobile_ap_status_ind_rsp,
 47                                         sizeof(qcmap_msgr_mobile_ap_status_ind_register_resp_msg_v01),
 48                                         QCMAP_MSGR_QMI_TIMEOUT_VALUE);
 49 
 50     LOG("qmi_client_send_msg_sync: error %d result %d",
 51                     qmi_error, qcmap_mobile_ap_status_ind_rsp.resp.result);
 52     if ( ( qmi_error == QMI_TIMEOUT_ERR ) ||
 53         ( qmi_error != QMI_NO_ERR ) ||
 54         ( qcmap_mobile_ap_status_ind_rsp.resp.result != QMI_NO_ERR ))
 55     {
 56         LOG("Can not register for mobile ap status %d : %d",
 57                     qmi_error, qcmap_mobile_ap_status_ind_rsp.resp.error);
 58         return FALSE;
 59     }
 60     LOG("Registered for mobile ap status");
 61 
 62     memset(&qcmap_station_mode_status_ind_reg, 0, sizeof(qcmap_msgr_station_mode_status_ind_register_req_msg_v01));
 63     memset(&qcmap_station_mode_status_ind_rsp, 0, sizeof(qcmap_msgr_station_mode_status_ind_register_resp_msg_v01));
 64     qcmap_station_mode_status_ind_reg.register_indication = 1;
 65 
 66     qmi_error = qmi_client_send_msg_sync(self->qmi_qcmap_msgr_handle,
 67                         QMI_QCMAP_MSGR_STATION_MODE_STATUS_IND_REG_REQ_V01,
 68                         (void*)&qcmap_station_mode_status_ind_reg,
 69                         sizeof(qcmap_msgr_station_mode_status_ind_register_req_msg_v01),
 70                         (void*)&qcmap_station_mode_status_ind_rsp,
 71                         sizeof(qcmap_msgr_station_mode_status_ind_register_resp_msg_v01),
 72                         QCMAP_MSGR_QMI_TIMEOUT_VALUE);
 73 
 74     LOG("qmi_client_send_msg_sync: error %d result %d",
 75             qmi_error, qcmap_station_mode_status_ind_rsp.resp.result);
 76     if ( ( qmi_error == QMI_TIMEOUT_ERR ) ||
 77         ( qmi_error != QMI_NO_ERR ) ||
 78         ( qcmap_station_mode_status_ind_rsp.resp.result != QMI_NO_ERR ))
 79     {
 80         LOG("Can not register for station mode indications %d : %d",
 81                     qmi_error, qcmap_station_mode_status_ind_rsp.resp.error);
 82         return FALSE;
 83     }
 84     LOG("Registered for station mode status");
 85 
 86     qmi_error = qmi_client_send_msg_sync(self->qmi_qcmap_msgr_handle,
 87                                         QMI_QCMAP_MSGR_MOBILE_AP_ENABLE_REQ_V01,
 88                                         NULL,
 89                                         0,
 90                                         (void*)&qcmap_enable_resp_msg_v01,
 91                                         sizeof(qcmap_msgr_mobile_ap_enable_resp_msg_v01),
 92                                         QCMAP_MSGR_QMI_TIMEOUT_VALUE);
 93     LOG("qmi_client_send_msg_sync: error %d result %d valid %d",
 94                     qmi_error, qcmap_enable_resp_msg_v01.resp.result, qcmap_enable_resp_msg_v01.mobile_ap_handle_valid);
 95     if (( qmi_error == QMI_TIMEOUT_ERR ) ||
 96         ( qmi_error != QMI_NO_ERR ) ||
 97         ( qcmap_enable_resp_msg_v01.resp.result != QMI_NO_ERR) ||
 98         ( qcmap_enable_resp_msg_v01.mobile_ap_handle_valid != TRUE ))
 99     {
100         LOG("Can not enable qcmap %d : %d",
101             qmi_error, qcmap_enable_resp_msg_v01.resp.error);
102         return FALSE;
103     }
104 
105     if( qcmap_enable_resp_msg_v01.mobile_ap_handle > 0 )
106     {
107         self->mobile_ap_handle = qcmap_enable_resp_msg_v01.mobile_ap_handle;
108         self->qcmap_msgr_enable = TRUE;
109         LOG("QCMAP Enabled\n");
110         return TRUE;
111     }
112     else
113     {
114         LOG("QCMAP Enable Failure\n");
115     }
116 
117     return FALSE;
118 }

 

  • 去使能
/* Disable MobileAP */
static boolean qcmap_ppp_disable(qcmap_ppp_t *self) {
    qcmap_msgr_mobile_ap_disable_req_msg_v01 qcmap_disable_req_msg_v01;
    qcmap_msgr_mobile_ap_disable_resp_msg_v01 qcmap_disable_resp_msg_v01;
    qmi_client_error_type qmi_error = QMI_NO_ERR;

    

    if (!self->qcmap_msgr_enable)
    {
        /* QCMAP is not enabled */
        LOG("QCMAP not enabled\n");
        return FALSE;
    }

    qcmap_disable_req_msg_v01.mobile_ap_handle = self->mobile_ap_handle;
    qmi_error = qmi_client_send_msg_sync(self->qmi_qcmap_msgr_handle,
                                        QMI_QCMAP_MSGR_MOBILE_AP_DISABLE_REQ_V01,
                                        &qcmap_disable_req_msg_v01,
                                        sizeof(qcmap_msgr_mobile_ap_disable_req_msg_v01),
                                        &qcmap_disable_resp_msg_v01,
                                        sizeof(qcmap_msgr_mobile_ap_disable_resp_msg_v01),
                                        QCMAP_MSGR_QMI_TIMEOUT_VALUE);

    if ( ( qmi_error == QMI_TIMEOUT_ERR ) ||
        ( qmi_error != QMI_NO_ERR ) ||
        ( (qcmap_disable_resp_msg_v01.resp.error != QMI_ERR_NO_EFFECT_V01 &&
            qcmap_disable_resp_msg_v01.resp.error != QMI_ERR_NONE_V01)) ||
        ( qcmap_disable_resp_msg_v01.resp.result != QMI_NO_ERR ))
    {
        LOG( "Can not disable qcmap %d : %d",
            qmi_error, qcmap_disable_resp_msg_v01.resp.error);
        return FALSE;
    }

    /*.If backhaul is not connected, Mobileap will be disabled instantly. And since
        call back function is being called much before the response pending flag is set to TRUE,
        responses are not sent to the client.
        Hence, we set qcmap_disable_resp_msg_v01.resp.error to QMI_ERR_NO_EFFECT_V01
        So that the caller of this function sends a response back to the client. (Used for IoE 9x25)
        */
    if (qcmap_disable_resp_msg_v01.resp.error == QMI_ERR_NO_EFFECT_V01)
        LOG( "Already disable qcmap %d", qcmap_disable_resp_msg_v01.resp.error);

    self->mobile_ap_handle = 0;
    self->qcmap_msgr_enable = FALSE;
    return TRUE;
}

 

  • 連接服務
/* ConnectBackHaul */
static boolean qcmap_ppp_connect(qcmap_ppp_t *self) {
    int qcmap_msgr_errno;
    int ret = 0;
    qcmap_msgr_wwan_call_type_v01 call_type = QCMAP_MSGR_WWAN_CALL_TYPE_V4_V01;

    qcmap_msgr_bring_up_wwan_req_msg_v01 qcmap_bring_up_wwan_req_msg;
    qcmap_msgr_bring_up_wwan_resp_msg_v01 qcmap_bring_up_wwan_resp_msg;
    qmi_client_error_type qmi_error;

    


    /* Bring up the data call. */
    LOG("Bring up wwan");
    qcmap_bring_up_wwan_req_msg.mobile_ap_handle = self->mobile_ap_handle;
    qcmap_bring_up_wwan_req_msg.call_type_valid = TRUE;

    qcmap_bring_up_wwan_req_msg.call_type = call_type;

    qmi_error = qmi_client_send_msg_sync(self->qmi_qcmap_msgr_handle,
                                        QMI_QCMAP_MSGR_BRING_UP_WWAN_REQ_V01,
                                        &qcmap_bring_up_wwan_req_msg,
                                        sizeof(qcmap_msgr_bring_up_wwan_req_msg_v01),
                                        &qcmap_bring_up_wwan_resp_msg,
                                        sizeof(qcmap_msgr_bring_up_wwan_resp_msg_v01),
                                        QCMAP_MSGR_QMI_TIMEOUT_VALUE);

    if ( ( qmi_error == QMI_TIMEOUT_ERR ) ||
        ( qmi_error != QMI_NO_ERR ) ||
        ( qcmap_bring_up_wwan_resp_msg.resp.result != QMI_NO_ERR ) )
    {
    LOG("Can not bring up wwan qcmap %d : %d",
        qmi_error, qcmap_bring_up_wwan_resp_msg.resp.error);
    return FALSE;
    }

 /* If WWAN is already enabled, and we are trying to enable again from a different client, set error number to QMI_ERR_NO_EFFECT_V01, so that the correspondingclient can be informed. We hit this scenario in the following case: 1. Start QCMAP_CLI and enable Backhaul. 2. Start MCM_MOBILEAP_CLI and try enabling backhaul again. */ if (call_type == QCMAP_MSGR_WWAN_CALL_TYPE_V4_V01 && qcmap_bring_up_wwan_resp_msg.conn_status == QCMAP_MSGR_WWAN_STATUS_CONNECTED_V01) { LOG("WWAN is already enabled."); } else if (call_type == QCMAP_MSGR_WWAN_CALL_TYPE_V6_V01 && qcmap_bring_up_wwan_resp_msg.conn_status == QCMAP_MSGR_WWAN_STATUS_IPV6_CONNECTED_V01) { LOG("IPv6 WWAN is already enabled."); } else LOG("Bringing up wwan..."); return TRUE; }
 

 

  • 斷開服務
  1 /* DisconnectBackHual */
  2 static boolean qcmap_ppp_disconnect(qcmap_ppp_t *self) {
  3     qcmap_msgr_wwan_call_type_v01 call_type = QCMAP_MSGR_WWAN_CALL_TYPE_V4_V01;
  4 
  5     qcmap_msgr_tear_down_wwan_req_msg_v01 qcmap_tear_down_wwan_req_msg;
  6     qcmap_msgr_tear_down_wwan_resp_msg_v01 qcmap_tear_down_wwan_resp_msg;
  7     qmi_client_error_type qmi_error;
  8     
  9 
 10     LOG("Bringing down wwan");
 11     qcmap_tear_down_wwan_req_msg.mobile_ap_handle = self->mobile_ap_handle;
 12 
 13     qcmap_tear_down_wwan_req_msg.call_type_valid = TRUE;
 14 
 15     qcmap_tear_down_wwan_req_msg.call_type = call_type;
 16 
 17     qmi_error = qmi_client_send_msg_sync(self->qmi_qcmap_msgr_handle,
 18                                         QMI_QCMAP_MSGR_TEAR_DOWN_WWAN_REQ_V01,
 19                                         &qcmap_tear_down_wwan_req_msg,
 20                                         sizeof(qcmap_msgr_tear_down_wwan_req_msg_v01),
 21                                         &qcmap_tear_down_wwan_resp_msg,
 22                                         sizeof(qcmap_msgr_tear_down_wwan_resp_msg_v01),
 23                                         QCMAP_MSGR_QMI_TIMEOUT_VALUE);
 24 
 25     if ( ( qmi_error == QMI_TIMEOUT_ERR ) ||
 26         ( qmi_error != QMI_NO_ERR) ||
 27         ( qcmap_tear_down_wwan_resp_msg.resp.result != QMI_NO_ERR ) )
 28     {
 29     LOG("Can not tear down wwan qcmap %d : %d",
 30         qmi_error, qcmap_tear_down_wwan_resp_msg.resp.error);
 31     return FALSE;
 32     }
 33 
 34     /*
 35         If WWAN is already disabled, and we are trying to disable again from a different client,
 36         set error number to QMI_ERR_NO_EFFECT_V01, so that the correspondingclient can be
 37         informed. We hit this scenario in the following case:
 38         1. Start QCMAP_CLI and enable Backhaul.
 39         2. Start MCM_MOBILEAP_CLI and try enabling backhaul again.
 40         3. Disable backhaul from the 1st client.
 41         4. Now from the 2nd client.
 42     */
 43     if (call_type == QCMAP_MSGR_WWAN_CALL_TYPE_V4_V01 &&
 44         qcmap_tear_down_wwan_resp_msg.conn_status ==
 45         QCMAP_MSGR_WWAN_STATUS_DISCONNECTED_V01)
 46     {
 47         LOG("WWAN is already disabled.");
 48     }
 49     else if (call_type == QCMAP_MSGR_WWAN_CALL_TYPE_V6_V01 &&
 50         qcmap_tear_down_wwan_resp_msg.conn_status ==
 51         QCMAP_MSGR_WWAN_STATUS_IPV6_DISCONNECTED_V01)
 52     {
 53         LOG("IPv6 WWAN is already disabled.");
 54     }
 55     else
 56         LOG("Tearing down wwan...");
 57     return TRUE;
 58 }
 59 
 60 /* Get WWAN Statistics. */
 61 static boolean qcmap_ppp_get_statistics(qcmap_ppp_t *self, qcmap_msgr_ip_family_enum_v01 ip_family, qcmap_msgr_wwan_statistics_type_v01 *wwan_stats) {
 62     qcmap_msgr_get_wwan_stats_req_msg_v01 get_wwan_stats_req_msg;
 63     qcmap_msgr_get_wwan_stats_resp_msg_v01 get_wwan_stats_resp_msg;
 64     qmi_client_error_type qmi_error;
 65 
 66     
 67 
 68     get_wwan_stats_req_msg.mobile_ap_handle = self->mobile_ap_handle;
 69     get_wwan_stats_req_msg.ip_family = ip_family;
 70 
 71     qmi_error = qmi_client_send_msg_sync(self->qmi_qcmap_msgr_handle,
 72                                         QMI_QCMAP_MSGR_GET_WWAN_STATS_REQ_V01,
 73                                         &get_wwan_stats_req_msg,
 74                                         sizeof(qcmap_msgr_get_wwan_stats_req_msg_v01),
 75                                         &get_wwan_stats_resp_msg,
 76                                         sizeof(qcmap_msgr_get_wwan_stats_resp_msg_v01),
 77                                         QCMAP_MSGR_QMI_TIMEOUT_VALUE);
 78 
 79     if ( ( qmi_error == QMI_TIMEOUT_ERR ) ||
 80         ( qmi_error != QMI_NO_ERR ) ||
 81         ( get_wwan_stats_resp_msg.resp.result != QMI_NO_ERR ) )
 82     {
 83     LOG("Can not get wwan stats %d : %d",
 84         qmi_error, get_wwan_stats_resp_msg.resp.error);
 85     return FALSE;
 86     }
 87 
 88     wwan_stats->bytes_rx = get_wwan_stats_resp_msg.wwan_stats.bytes_rx;
 89     wwan_stats->bytes_tx = get_wwan_stats_resp_msg.wwan_stats.bytes_tx;
 90     wwan_stats->pkts_rx = get_wwan_stats_resp_msg.wwan_stats.pkts_rx;
 91     wwan_stats->pkts_tx = get_wwan_stats_resp_msg.wwan_stats.pkts_tx;
 92     wwan_stats->pkts_dropped_rx = get_wwan_stats_resp_msg.wwan_stats.pkts_dropped_rx;
 93     wwan_stats->pkts_dropped_tx = get_wwan_stats_resp_msg.wwan_stats.pkts_dropped_tx;
 94     LOG("Get WWAN Stats succeeded...");
 95     return TRUE;
 96 }
 97 
 98 /* Reset WWAN Statistics. */
 99 static boolean qcmap_ppp_reset_statistics(qcmap_ppp_t *self, qcmap_msgr_ip_family_enum_v01 ip_family) {
100     qcmap_msgr_reset_wwan_stats_req_msg_v01 reset_wwan_stats_req_msg;
101     qcmap_msgr_reset_wwan_stats_resp_msg_v01 reset_wwan_stats_resp_msg;
102     qmi_client_error_type qmi_error;
103 
104     
105 
106     reset_wwan_stats_req_msg.mobile_ap_handle = self->mobile_ap_handle;
107     reset_wwan_stats_req_msg.ip_family = ip_family;
108 
109     qmi_error = qmi_client_send_msg_sync(self->qmi_qcmap_msgr_handle,
110                                         QMI_QCMAP_MSGR_RESET_WWAN_STATS_REQ_V01,
111                                         &reset_wwan_stats_req_msg,
112                                         sizeof(qcmap_msgr_reset_wwan_stats_req_msg_v01),
113                                         &reset_wwan_stats_resp_msg,
114                                         sizeof(qcmap_msgr_reset_wwan_stats_resp_msg_v01),
115                                         QCMAP_MSGR_QMI_TIMEOUT_VALUE);
116 
117     if ( ( qmi_error == QMI_TIMEOUT_ERR ) ||
118         ( qmi_error != QMI_NO_ERR ) ||
119         ( reset_wwan_stats_resp_msg.resp.result != QMI_NO_ERR ) )
120     {
121         LOG("Can not reset wwan stats %d : %d",
122             qmi_error, reset_wwan_stats_resp_msg.resp.error);
123             return FALSE;
124     }
125 
126     LOG("Reset WWAN Stats succeeded...");
127     return TRUE;
128 }
129 
130 /* Enable/Disable Autoconnect mode */
131 static boolean qcmap_ppp_set_auto_connect(qcmap_ppp_t *self, boolean enable) {
132     qcmap_msgr_set_auto_connect_req_msg_v01 set_auto_connect_req_msg;
133     qcmap_msgr_set_auto_connect_resp_msg_v01 set_auto_connect_resp_msg;
134     qmi_client_error_type qmi_error;
135 
136     
137 
138     set_auto_connect_req_msg.mobile_ap_handle = self->mobile_ap_handle;
139     set_auto_connect_req_msg.enable = enable;
140 
141     qmi_error = qmi_client_send_msg_sync(self->qmi_qcmap_msgr_handle,
142                                         QMI_QCMAP_MSGR_SET_AUTO_CONNECT_REQ_V01,
143                                         &set_auto_connect_req_msg,
144                                         sizeof(qcmap_msgr_set_auto_connect_req_msg_v01),
145                                         &set_auto_connect_resp_msg,
146                                         sizeof(qcmap_msgr_set_auto_connect_resp_msg_v01),
147                                         QCMAP_MSGR_QMI_TIMEOUT_VALUE);
148     if ( ( qmi_error == QMI_TIMEOUT_ERR ) ||
149         ( qmi_error != QMI_NO_ERR ) ||
150         ( set_auto_connect_resp_msg.resp.result != QMI_NO_ERR ) )
151     {
152     LOG("Can not set auto connect flag %d : %d",
153             qmi_error, set_auto_connect_resp_msg.resp.error);
154         return FALSE;
155     }
156 
157     LOG("Auto Connect Mode Set succeeded...");
158     return TRUE;
159 }

 

至此,就可以完成撥號的連接和斷開。

2.3 PPP狀態

如果關注狀態通知,需要處理知函數client_cb_ind中狀態通知。主要包含了建立撥號成功/失敗,網絡狀態變化(切換網絡模式)的斷開通知等。

 1 static void qcmap_ppp_ind(
 2     qmi_client_type user_handle,
 3     unsigned int msg_id,
 4     void *ind_buf,
 5     unsigned int ind_buf_len,
 6     void *ind_cb_data )
 7 {
 8     qmi_client_error_type qmi_error;
 9     LOG("qcmap_msgr_qmi_qcmap_ind: user_handle %X msg_id %d ind_buf_len %d.", user_handle, msg_id, ind_buf_len);
10 }

 

2.4 建立連接可選項
  • 禁用ipv6
 1 static boolean qcmap_ppp_disable_ipv6(qcmap_ppp_t *self) {
 2     int qcmap_msgr_errno;
 3     int ret = 0;
 4     qcmap_msgr_disable_ipv6_req_msg_v01 qcmap_disable_ipv6_req_msg;
 5     qcmap_msgr_disable_ipv6_resp_msg_v01 qcmap_disable_ipv6_resp_msg;
 6     qmi_client_error_type qmi_error;
 7 
 8     /* Enable IPV6. */
 9     LOG("Disable IPV6");
10     qcmap_disable_ipv6_req_msg.mobile_ap_handle = self->mobile_ap_handle;
11 
12     qmi_error = qmi_client_send_msg_sync(self->qmi_qcmap_msgr_handle,
13                                         QMI_QCMAP_MSGR_DISABLE_IPV6_REQ_V01,
14                                         &qcmap_disable_ipv6_req_msg,
15                                         sizeof(qcmap_msgr_disable_ipv6_req_msg_v01),
16                                         &qcmap_disable_ipv6_resp_msg,
17                                         sizeof(qcmap_msgr_disable_ipv6_resp_msg_v01),
18                                         QCMAP_MSGR_QMI_TIMEOUT_VALUE);
19 
20     if ( ( qmi_error == QMI_TIMEOUT_ERR ) ||
21         ( qmi_error != QMI_NO_ERR ) ||
22         ( qcmap_disable_ipv6_resp_msg.resp.result != QMI_NO_ERR ) )
23     {
24     LOG("Can not disable ipv6 %d : %d",
25         qmi_error, qcmap_disable_ipv6_resp_msg.resp.error);
26     return FALSE;
27     }
28 
29     LOG("Disabled IPV6...");
30     return TRUE;
31 }

 

  • 配置自動連接(沒測試出效果)
 1 /* Enable/Disable Autoconnect mode */
 2 static boolean qcmap_ppp_set_auto_connect(qcmap_ppp_t *self, boolean enable) {
 3     qcmap_msgr_set_auto_connect_req_msg_v01 set_auto_connect_req_msg;
 4     qcmap_msgr_set_auto_connect_resp_msg_v01 set_auto_connect_resp_msg;
 5     qmi_client_error_type qmi_error;
 6 
 7     
 8 
 9     set_auto_connect_req_msg.mobile_ap_handle = self->mobile_ap_handle;
10     set_auto_connect_req_msg.enable = enable;
11 
12     qmi_error = qmi_client_send_msg_sync(self->qmi_qcmap_msgr_handle,
13                                         QMI_QCMAP_MSGR_SET_AUTO_CONNECT_REQ_V01,
14                                         &set_auto_connect_req_msg,
15                                         sizeof(qcmap_msgr_set_auto_connect_req_msg_v01),
16                                         &set_auto_connect_resp_msg,
17                                         sizeof(qcmap_msgr_set_auto_connect_resp_msg_v01),
18                                         QCMAP_MSGR_QMI_TIMEOUT_VALUE);
19     if ( ( qmi_error == QMI_TIMEOUT_ERR ) ||
20         ( qmi_error != QMI_NO_ERR ) ||
21         ( set_auto_connect_resp_msg.resp.result != QMI_NO_ERR ) )
22     {
23     LOG("Can not set auto connect flag %d : %d",
24             qmi_error, set_auto_connect_resp_msg.resp.error);
25         return FALSE;
26     }
27 
28     LOG("Auto Connect Mode Set succeeded...");
29     return TRUE;
30 }

 

  • 查詢wwan統計信息(流量)
 1 /* Get WWAN Status */
 2 static boolean qcmap_ppp_get_status(qcmap_ppp_t *self, qcmap_msgr_wwan_status_enum_v01 *v4_status, qcmap_msgr_wwan_status_enum_v01 *v6_status) {
 3     qmi_client_error_type qmi_error, qmi_err_code = QMI_NO_ERR;
 4     qcmap_msgr_wwan_status_req_msg_v01 wan_status_req;
 5     qcmap_msgr_wwan_status_resp_msg_v01 wan_status_resp;
 6     
 7 
 8     memset(&wan_status_resp, 0, sizeof(qcmap_msgr_wwan_status_resp_msg_v01));
 9     wan_status_req.mobile_ap_handle = self->mobile_ap_handle;
10     wan_status_req.call_type_valid = 1;
11     wan_status_req.call_type = QCMAP_MSGR_WWAN_CALL_TYPE_V4_V01;
12     qmi_error = qmi_client_send_msg_sync(self->qmi_qcmap_msgr_handle,
13                                         QMI_QCMAP_MSGR_WWAN_STATUS_REQ_V01,
14                                         &wan_status_req,
15                                         sizeof(qcmap_msgr_wwan_status_req_msg_v01),
16                                         (void*)&wan_status_resp,
17                                         sizeof(qcmap_msgr_wwan_status_resp_msg_v01),
18                                         QCMAP_MSGR_QMI_TIMEOUT_VALUE);
19 
20     LOG("qmi_client_send_msg_sync(enable): error %d result %d",
21         qmi_error, wan_status_resp.resp.result);
22 
23     if ( ( qmi_error == QMI_TIMEOUT_ERR ) ||
24         ( qmi_error != QMI_NO_ERR ) ||
25         ( wan_status_resp.resp.result != QMI_NO_ERR ) )
26     {
27     LOG("Can not get IPV4 WAN status  %d : %d",
28         qmi_error, wan_status_resp.resp.error);
29     return FALSE;
30     }
31     if(wan_status_resp.conn_status_valid ==1)
32     {
33     *v4_status=wan_status_resp.conn_status;
34     if(wan_status_resp.conn_status == QCMAP_MSGR_WWAN_STATUS_CONNECTING_V01)
35     {
36         LOG(" IPV4 WWAN is Connecting \n");
37     }
38     else if(wan_status_resp.conn_status == QCMAP_MSGR_WWAN_STATUS_CONNECTED_V01)
39     {
40         LOG(" IPV4 WWAN is connected \n");
41     }
42     else if(wan_status_resp.conn_status == QCMAP_MSGR_WWAN_STATUS_DISCONNECTING_V01)
43     {
44         LOG(" IPV4 WWAN is Disconnecting \n");
45     }
46     else if(wan_status_resp.conn_status == QCMAP_MSGR_WWAN_STATUS_DISCONNECTED_V01)
47     {
48         LOG(" IPV4 WWAN is Disconnected \n");
49     }
50     }
51 
52 #ifdef ENABLE_IPV6
53     memset(&wan_status_resp, 0, sizeof(qcmap_msgr_wwan_status_resp_msg_v01));
54     wan_status_req.mobile_ap_handle = self->mobile_ap_handle;
55     wan_status_req.call_type_valid = 1;
56     wan_status_req.call_type = QCMAP_MSGR_WWAN_CALL_TYPE_V6_V01;
57     qmi_error = qmi_client_send_msg_sync(self->qmi_qcmap_msgr_handle,
58                                         QMI_QCMAP_MSGR_WWAN_STATUS_REQ_V01,
59                                         &wan_status_req,
60                                         sizeof(qcmap_msgr_wwan_status_req_msg_v01),
61                                         (void*)&wan_status_resp,
62                                         sizeof(qcmap_msgr_wwan_status_resp_msg_v01),
63                                         QCMAP_MSGR_QMI_TIMEOUT_VALUE);
64 
65     LOG("qmi_client_send_msg_sync(enable): error %d result %d",
66         qmi_error, wan_status_resp.resp.result);
67 
68     if ( ( qmi_error == QMI_TIMEOUT_ERR ) ||
69         ( qmi_error != QMI_NO_ERR ) ||
70         ( wan_status_resp.resp.result != QMI_NO_ERR ) )
71     {
72         LOG("Can not get IPV6 WAN status %d : %d",
73             qmi_error, wan_status_resp.resp.error);
74         return FALSE;
75     }
76     if(wan_status_resp.conn_status_valid == 1)
77     {
78     *v6_status=wan_status_resp.conn_status;
79     if(wan_status_resp.conn_status == QCMAP_MSGR_WWAN_STATUS_IPV6_CONNECTING_V01)
80     {
81         LOG(" IPV6 WWAN is Connecting \n");
82     }
83     else if(wan_status_resp.conn_status == QCMAP_MSGR_WWAN_STATUS_IPV6_CONNECTED_V01)
84     {
85         LOG(" IPV6 WWAN is connected \n");
86     }
87     else if(wan_status_resp.conn_status == QCMAP_MSGR_WWAN_STATUS_IPV6_DISCONNECTING_V01)
88     {
89         LOG(" IPV6 WWAN is Disconnecting \n");
90     }
91     else if(wan_status_resp.conn_status == QCMAP_MSGR_WWAN_STATUS_IPV6_DISCONNECTED_V01)
92     {
93         LOG(" IPV6 WWAN is Disconnected \n");
94     }
95     }
96 #endif
97 
98     return TRUE;
99 }

 

綜上,基本用到的就這些接口了,比起直接使用高通提供的QCMAP_Client類接口,本文實現更原生、靈活,經過驗證可以在國內多家9X07模塊上正確穩定的執行。

3 其他組件服務功能

請自行研究實現,不做贅述了。



作者:LittleFat
鏈接:https://www.jianshu.com/p/82a8177b8299
來源:簡書
簡書著作權歸作者所有,任何形式的轉載都請聯系作者獲得授權並注明出處。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM