高通MDM9x07 qcmap數據撥號

qcmap底層基於高通的數據服務接DSI接口


DSI:Data Service Interface,數據業務接口
netctrl:網絡控制
bring up / tear down:數據呼叫通道的建立、銷燬
APN:Access Point Name,移動接入點名稱
PDN:Packet data network,包數據網絡(分組業務網絡)
DNS:Domain Name Service,域名解析服務
Qos:Quality Of Service,業務質量控制
QMI:Qualcomm Messaging Interface,高通消息傳遞接口
本庫啓動的時候作爲一個守護進程,底層依賴QMI提供功能,客戶端啓動進程後調用本庫連接守護進程處理數據業務。
本庫提供:
    1. WWAN數據業務的建立、銷燬和基本配置,可以配置APN、IP協議族、技術選擇優先級、用戶名密碼、profile ID等
    2. Qos(DSI_NetCtrl provides methods for applications to request UE-initiated QoS)
    3. 多播和多媒體多播
    4. DNS(Domain Name Service)
    5. 各種數據業務狀態查詢
    6. 支持雙IP數據呼叫,客戶端只要使用單個接口即可,不用連接兩次
    7. 支持多PDN同時建立數據業務,應用程序必須控制路由
    8. 支持多個進程連接DSI_NetCtrl,每個進程可以獨立控制數據連接的建立和銷燬,多PDN場景也可以用多個進程處理

【數據呼叫流程】
    1. dsi_init,初始化,客戶端連接到守護進程
    2. dsi_start_data_call,設置數據連接參數,啓動數據連接,啓動前可以配置多次,可以配置的參數包括:
        2.1 UMTS / CDMA ID
        2.2 APN
        2.3 IP Version (IPv4 / IPv6/ IPv4v6)
        2.4 APN用戶名密碼
        2.5 認證優先級
        2.6 技術類型 / 擴展技術名稱
    3. dsi_stop_data_call,銷燬數據連接(同時網絡側可能發起數據連接銷燬,此時將網絡狀態通知到dsi進程)

【Qos】
    主要功能:
        流量監管(對進入接口的,超出限制速率的報文進行丟棄)
        流量整形(對接口發送的,超出限制速率的報文先進行緩存,等待流量不超出速率時發送)
        擁塞避免(在出現網絡擁塞時對符合條件的報文進行丟棄)
        擁塞管理(在出現網絡擁塞時採用隊列調度的方法對符合條件的隊列中的報文優先發送)
        流策略(可根據不同的流分類實現諸如禁止/允許通過,重標記報文優先級、重標記報文VLAN標籤、重定向流量、過濾報文、
            流量鏡像、啓用流量統計功能等行爲)。
    dsi庫支持用戶發起的和網絡側發起的Qos。
 

【qcmap】

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
參考代碼:

void qcmap_ppp_init(qcmap_ppp_t *self,client_status_ind_t client_cb_ind) {
    qmi_idl_service_object_type qcmap_msgr_qmi_idl_service_object;
    uint32_t num_services = 0, num_entries = 0;
    qmi_service_info info[10];
    qmi_client_error_type qmi_error, qmi_err_code = QMI_NO_ERR;

    assert(self);
    
    self->qcmap_msgr_enable = FALSE;
    self->qmi_qcmap_msgr_handle = 0;
    self->mobile_ap_handle = 0;

    qcmap_msgr_qmi_idl_service_object = qcmap_msgr_get_service_object_v01;//when faild, add your trick for this~

    if (qcmap_msgr_qmi_idl_service_object == NULL)
    {
        LOG("qcmap_msgr service object not available");
        return;
    }

    qmi_error = qmi_client_notifier_init(qcmap_msgr_qmi_idl_service_object,
                                        &self->qmi_qcmap_msgr_os_params,
                                        &self->qmi_qcmap_msgr_notifier);
    if (qmi_error < 0)
    {
        LOG("qmi_client_notifier_init(qcmap_msgr) returned %d", qmi_error);
        return;
    }

    /* Check if the service is up, if not wait on a signal */
    while(1)
    {
        qmi_error = qmi_client_get_service_list(qcmap_msgr_qmi_idl_service_object,
                                                NULL,
                                                NULL,
                                                &num_services);
        LOG("qmi_client_get_service_list: %d",qmi_error);

        if(qmi_error == QMI_NO_ERR)
            break;
        /* wait for server to come up */
        QMI_CCI_OS_SIGNAL_WAIT(&self->qmi_qcmap_msgr_os_params, 0);
    }

    num_entries = num_services;

    LOG("qmi_client_get_service_list: num_e %d num_s %d", num_entries, num_services);
    /* The server has come up, store the information in info variable */
    qmi_error = qmi_client_get_service_list(qcmap_msgr_qmi_idl_service_object,
                                            info,
                                            &num_entries,
                                            &num_services);

    LOG("qmi_client_get_service_list: num_e %d num_s %d error %d", num_entries, num_services, qmi_error);

    if (qmi_error != QMI_NO_ERR)
    {
        qmi_client_release(self->qmi_qcmap_msgr_notifier);
        self->qmi_qcmap_msgr_notifier = NULL;
        LOG("Can not get qcmap_msgr service list %d",
            qmi_error);
        return;
    }

    qmi_error = qmi_client_init(&info[0],
                                qcmap_msgr_qmi_idl_service_object,
                                client_cb_ind,
                                NULL,
                                NULL,
                                &self->qmi_qcmap_msgr_handle);

    LOG("qmi_client_init: %d", qmi_error);

    if (qmi_error != QMI_NO_ERR)
    {
        qmi_client_release(self->qmi_qcmap_msgr_notifier);
        self->qmi_qcmap_msgr_notifier = NULL;
        LOG("Can not init qcmap_msgr client %d", qmi_error);
        return;
    }
}

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

static void qcmap_ppp_uninit(qcmap_ppp_t *self) {
    qmi_client_error_type qmi_error;
    assert(self);

    qmi_error = qmi_client_release(self->qmi_qcmap_msgr_notifier);
    self->qmi_qcmap_msgr_notifier = NULL;

    if (qmi_error != QMI_NO_ERR)
    {
        LOG("Can not release client qcmap notifier %d",qmi_error);
    }

    qmi_error = qmi_client_release(self->qmi_qcmap_msgr_handle);
    self->qmi_qcmap_msgr_handle = NULL;

    if (qmi_error != QMI_NO_ERR)
    {
        LOG("Can not release client qcmap handle %d",qmi_error);
    }
}

2.2 建立/關閉撥號連接

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

  • 使能ap
/* Enable MobileAP */
static boolean qcmap_ppp_enable(qcmap_ppp_t *self) {
    qmi_client_error_type qmi_error, qmi_err_code = QMI_NO_ERR;
    qcmap_msgr_mobile_ap_enable_resp_msg_v01 qcmap_enable_resp_msg_v01;
    qcmap_msgr_mobile_ap_status_ind_register_req_msg_v01 qcmap_mobile_ap_status_ind_reg;
    qcmap_msgr_wwan_status_ind_register_req_msg_v01 wwan_status_ind_reg;
    qcmap_msgr_station_mode_status_ind_register_req_msg_v01 qcmap_station_mode_status_ind_reg;
    qcmap_msgr_mobile_ap_status_ind_register_resp_msg_v01 qcmap_mobile_ap_status_ind_rsp;
    qcmap_msgr_wwan_status_ind_register_resp_msg_v01 wwan_status_ind_rsp;
    qcmap_msgr_station_mode_status_ind_register_resp_msg_v01 qcmap_station_mode_status_ind_rsp;

    memset(&qcmap_enable_resp_msg_v01, 0, sizeof(qcmap_msgr_mobile_ap_enable_resp_msg_v01));
    memset(&wwan_status_ind_reg, 0, sizeof(qcmap_msgr_wwan_status_ind_register_req_msg_v01));
    memset(&wwan_status_ind_rsp, 0, sizeof(qcmap_msgr_wwan_status_ind_register_resp_msg_v01));
    wwan_status_ind_reg.register_indication = 1;

    qmi_error = qmi_client_send_msg_sync(self->qmi_qcmap_msgr_handle,
                                            QMI_QCMAP_MSGR_WWAN_STATUS_IND_REG_REQ_V01,
                                            (void*)&wwan_status_ind_reg,
                                            sizeof(qcmap_msgr_wwan_status_ind_register_req_msg_v01),
                                            (void*)&wwan_status_ind_rsp,
                                            sizeof(qcmap_msgr_wwan_status_ind_register_resp_msg_v01),
                                            QCMAP_MSGR_QMI_TIMEOUT_VALUE);

    LOG("qmi_client_send_msg_sync: error %d result %d",
                    qmi_error, wwan_status_ind_rsp.resp.result);

    if (( qmi_error == QMI_TIMEOUT_ERR ) ||
        ( qmi_error != QMI_NO_ERR ) ||
        ( wwan_status_ind_rsp.resp.result != QMI_NO_ERR ))
    {
        LOG("Can not register for wwan status %d : %d",
                    qmi_error, wwan_status_ind_rsp.resp.error);
        return FALSE;
    }
    LOG("Registered for wwan status");

    memset(&qcmap_mobile_ap_status_ind_reg, 0, sizeof(qcmap_msgr_mobile_ap_status_ind_register_req_msg_v01));
    memset(&qcmap_mobile_ap_status_ind_rsp, 0, sizeof(qcmap_msgr_mobile_ap_status_ind_register_resp_msg_v01));
    qcmap_mobile_ap_status_ind_reg.register_indication = 1;

    qmi_error = qmi_client_send_msg_sync(self->qmi_qcmap_msgr_handle,
                                        QMI_QCMAP_MSGR_MOBILE_AP_STATUS_IND_REG_REQ_V01,
                                        (void*)&qcmap_mobile_ap_status_ind_reg,
                                        sizeof(qcmap_msgr_mobile_ap_status_ind_register_req_msg_v01),
                                        (void*)&qcmap_mobile_ap_status_ind_rsp,
                                        sizeof(qcmap_msgr_mobile_ap_status_ind_register_resp_msg_v01),
                                        QCMAP_MSGR_QMI_TIMEOUT_VALUE);

    LOG("qmi_client_send_msg_sync: error %d result %d",
                    qmi_error, qcmap_mobile_ap_status_ind_rsp.resp.result);
    if ( ( qmi_error == QMI_TIMEOUT_ERR ) ||
        ( qmi_error != QMI_NO_ERR ) ||
        ( qcmap_mobile_ap_status_ind_rsp.resp.result != QMI_NO_ERR ))
    {
        LOG("Can not register for mobile ap status %d : %d",
                    qmi_error, qcmap_mobile_ap_status_ind_rsp.resp.error);
        return FALSE;
    }
    LOG("Registered for mobile ap status");

    memset(&qcmap_station_mode_status_ind_reg, 0, sizeof(qcmap_msgr_station_mode_status_ind_register_req_msg_v01));
    memset(&qcmap_station_mode_status_ind_rsp, 0, sizeof(qcmap_msgr_station_mode_status_ind_register_resp_msg_v01));
    qcmap_station_mode_status_ind_reg.register_indication = 1;

    qmi_error = qmi_client_send_msg_sync(self->qmi_qcmap_msgr_handle,
                        QMI_QCMAP_MSGR_STATION_MODE_STATUS_IND_REG_REQ_V01,
                        (void*)&qcmap_station_mode_status_ind_reg,
                        sizeof(qcmap_msgr_station_mode_status_ind_register_req_msg_v01),
                        (void*)&qcmap_station_mode_status_ind_rsp,
                        sizeof(qcmap_msgr_station_mode_status_ind_register_resp_msg_v01),
                        QCMAP_MSGR_QMI_TIMEOUT_VALUE);

    LOG("qmi_client_send_msg_sync: error %d result %d",
            qmi_error, qcmap_station_mode_status_ind_rsp.resp.result);
    if ( ( qmi_error == QMI_TIMEOUT_ERR ) ||
        ( qmi_error != QMI_NO_ERR ) ||
        ( qcmap_station_mode_status_ind_rsp.resp.result != QMI_NO_ERR ))
    {
        LOG("Can not register for station mode indications %d : %d",
                    qmi_error, qcmap_station_mode_status_ind_rsp.resp.error);
        return FALSE;
    }
    LOG("Registered for station mode status");

    qmi_error = qmi_client_send_msg_sync(self->qmi_qcmap_msgr_handle,
                                        QMI_QCMAP_MSGR_MOBILE_AP_ENABLE_REQ_V01,
                                        NULL,
                                        0,
                                        (void*)&qcmap_enable_resp_msg_v01,
                                        sizeof(qcmap_msgr_mobile_ap_enable_resp_msg_v01),
                                        QCMAP_MSGR_QMI_TIMEOUT_VALUE);
    LOG("qmi_client_send_msg_sync: error %d result %d valid %d",
                    qmi_error, qcmap_enable_resp_msg_v01.resp.result, qcmap_enable_resp_msg_v01.mobile_ap_handle_valid);
    if (( qmi_error == QMI_TIMEOUT_ERR ) ||
        ( qmi_error != QMI_NO_ERR ) ||
        ( qcmap_enable_resp_msg_v01.resp.result != QMI_NO_ERR) ||
        ( qcmap_enable_resp_msg_v01.mobile_ap_handle_valid != TRUE ))
    {
        LOG("Can not enable qcmap %d : %d",
            qmi_error, qcmap_enable_resp_msg_v01.resp.error);
        return FALSE;
    }

    if( qcmap_enable_resp_msg_v01.mobile_ap_handle > 0 )
    {
        self->mobile_ap_handle = qcmap_enable_resp_msg_v01.mobile_ap_handle;
        self->qcmap_msgr_enable = TRUE;
        LOG("QCMAP Enabled\n");
        return TRUE;
    }
    else
    {
        LOG("QCMAP Enable Failure\n");
    }

    return FALSE;
}
  • 去使能
/* 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;
}
  • 斷開服務
/* DisconnectBackHual */
static boolean qcmap_ppp_disconnect(qcmap_ppp_t *self) {
    qcmap_msgr_wwan_call_type_v01 call_type = QCMAP_MSGR_WWAN_CALL_TYPE_V4_V01;

    qcmap_msgr_tear_down_wwan_req_msg_v01 qcmap_tear_down_wwan_req_msg;
    qcmap_msgr_tear_down_wwan_resp_msg_v01 qcmap_tear_down_wwan_resp_msg;
    qmi_client_error_type qmi_error;
    

    LOG("Bringing down wwan");
    qcmap_tear_down_wwan_req_msg.mobile_ap_handle = self->mobile_ap_handle;

    qcmap_tear_down_wwan_req_msg.call_type_valid = TRUE;

    qcmap_tear_down_wwan_req_msg.call_type = call_type;

    qmi_error = qmi_client_send_msg_sync(self->qmi_qcmap_msgr_handle,
                                        QMI_QCMAP_MSGR_TEAR_DOWN_WWAN_REQ_V01,
                                        &qcmap_tear_down_wwan_req_msg,
                                        sizeof(qcmap_msgr_tear_down_wwan_req_msg_v01),
                                        &qcmap_tear_down_wwan_resp_msg,
                                        sizeof(qcmap_msgr_tear_down_wwan_resp_msg_v01),
                                        QCMAP_MSGR_QMI_TIMEOUT_VALUE);

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

    /*
        If WWAN is already disabled, and we are trying to disable 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.
        3. Disable backhaul from the 1st client.
        4. Now from the 2nd client.
    */
    if (call_type == QCMAP_MSGR_WWAN_CALL_TYPE_V4_V01 &&
        qcmap_tear_down_wwan_resp_msg.conn_status ==
        QCMAP_MSGR_WWAN_STATUS_DISCONNECTED_V01)
    {
        LOG("WWAN is already disabled.");
    }
    else if (call_type == QCMAP_MSGR_WWAN_CALL_TYPE_V6_V01 &&
        qcmap_tear_down_wwan_resp_msg.conn_status ==
        QCMAP_MSGR_WWAN_STATUS_IPV6_DISCONNECTED_V01)
    {
        LOG("IPv6 WWAN is already disabled.");
    }
    else
        LOG("Tearing down wwan...");
    return TRUE;
}

/* Get WWAN Statistics. */
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) {
    qcmap_msgr_get_wwan_stats_req_msg_v01 get_wwan_stats_req_msg;
    qcmap_msgr_get_wwan_stats_resp_msg_v01 get_wwan_stats_resp_msg;
    qmi_client_error_type qmi_error;

    

    get_wwan_stats_req_msg.mobile_ap_handle = self->mobile_ap_handle;
    get_wwan_stats_req_msg.ip_family = ip_family;

    qmi_error = qmi_client_send_msg_sync(self->qmi_qcmap_msgr_handle,
                                        QMI_QCMAP_MSGR_GET_WWAN_STATS_REQ_V01,
                                        &get_wwan_stats_req_msg,
                                        sizeof(qcmap_msgr_get_wwan_stats_req_msg_v01),
                                        &get_wwan_stats_resp_msg,
                                        sizeof(qcmap_msgr_get_wwan_stats_resp_msg_v01),
                                        QCMAP_MSGR_QMI_TIMEOUT_VALUE);

    if ( ( qmi_error == QMI_TIMEOUT_ERR ) ||
        ( qmi_error != QMI_NO_ERR ) ||
        ( get_wwan_stats_resp_msg.resp.result != QMI_NO_ERR ) )
    {
    LOG("Can not get wwan stats %d : %d",
        qmi_error, get_wwan_stats_resp_msg.resp.error);
    return FALSE;
    }

    wwan_stats->bytes_rx = get_wwan_stats_resp_msg.wwan_stats.bytes_rx;
    wwan_stats->bytes_tx = get_wwan_stats_resp_msg.wwan_stats.bytes_tx;
    wwan_stats->pkts_rx = get_wwan_stats_resp_msg.wwan_stats.pkts_rx;
    wwan_stats->pkts_tx = get_wwan_stats_resp_msg.wwan_stats.pkts_tx;
    wwan_stats->pkts_dropped_rx = get_wwan_stats_resp_msg.wwan_stats.pkts_dropped_rx;
    wwan_stats->pkts_dropped_tx = get_wwan_stats_resp_msg.wwan_stats.pkts_dropped_tx;
    LOG("Get WWAN Stats succeeded...");
    return TRUE;
}

/* Reset WWAN Statistics. */
static boolean qcmap_ppp_reset_statistics(qcmap_ppp_t *self, qcmap_msgr_ip_family_enum_v01 ip_family) {
    qcmap_msgr_reset_wwan_stats_req_msg_v01 reset_wwan_stats_req_msg;
    qcmap_msgr_reset_wwan_stats_resp_msg_v01 reset_wwan_stats_resp_msg;
    qmi_client_error_type qmi_error;

    

    reset_wwan_stats_req_msg.mobile_ap_handle = self->mobile_ap_handle;
    reset_wwan_stats_req_msg.ip_family = ip_family;

    qmi_error = qmi_client_send_msg_sync(self->qmi_qcmap_msgr_handle,
                                        QMI_QCMAP_MSGR_RESET_WWAN_STATS_REQ_V01,
                                        &reset_wwan_stats_req_msg,
                                        sizeof(qcmap_msgr_reset_wwan_stats_req_msg_v01),
                                        &reset_wwan_stats_resp_msg,
                                        sizeof(qcmap_msgr_reset_wwan_stats_resp_msg_v01),
                                        QCMAP_MSGR_QMI_TIMEOUT_VALUE);

    if ( ( qmi_error == QMI_TIMEOUT_ERR ) ||
        ( qmi_error != QMI_NO_ERR ) ||
        ( reset_wwan_stats_resp_msg.resp.result != QMI_NO_ERR ) )
    {
        LOG("Can not reset wwan stats %d : %d",
            qmi_error, reset_wwan_stats_resp_msg.resp.error);
            return FALSE;
    }

    LOG("Reset WWAN Stats succeeded...");
    return TRUE;
}

/* Enable/Disable Autoconnect mode */
static boolean qcmap_ppp_set_auto_connect(qcmap_ppp_t *self, boolean enable) {
    qcmap_msgr_set_auto_connect_req_msg_v01 set_auto_connect_req_msg;
    qcmap_msgr_set_auto_connect_resp_msg_v01 set_auto_connect_resp_msg;
    qmi_client_error_type qmi_error;

    

    set_auto_connect_req_msg.mobile_ap_handle = self->mobile_ap_handle;
    set_auto_connect_req_msg.enable = enable;

    qmi_error = qmi_client_send_msg_sync(self->qmi_qcmap_msgr_handle,
                                        QMI_QCMAP_MSGR_SET_AUTO_CONNECT_REQ_V01,
                                        &set_auto_connect_req_msg,
                                        sizeof(qcmap_msgr_set_auto_connect_req_msg_v01),
                                        &set_auto_connect_resp_msg,
                                        sizeof(qcmap_msgr_set_auto_connect_resp_msg_v01),
                                        QCMAP_MSGR_QMI_TIMEOUT_VALUE);
    if ( ( qmi_error == QMI_TIMEOUT_ERR ) ||
        ( qmi_error != QMI_NO_ERR ) ||
        ( set_auto_connect_resp_msg.resp.result != QMI_NO_ERR ) )
    {
    LOG("Can not set auto connect flag %d : %d",
            qmi_error, set_auto_connect_resp_msg.resp.error);
        return FALSE;
    }

    LOG("Auto Connect Mode Set succeeded...");
    return TRUE;
}

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

2.3 PPP狀態

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

static void qcmap_ppp_ind(
    qmi_client_type user_handle,
    unsigned int msg_id,
    void *ind_buf,
    unsigned int ind_buf_len,
    void *ind_cb_data )
{
    qmi_client_error_type qmi_error;
    LOG("qcmap_msgr_qmi_qcmap_ind: user_handle %X msg_id %d ind_buf_len %d.", user_handle, msg_id, ind_buf_len);
}

2.4 建立連接可選項

  • 禁用ipv6

static boolean qcmap_ppp_disable_ipv6(qcmap_ppp_t *self) {
    int qcmap_msgr_errno;
    int ret = 0;
    qcmap_msgr_disable_ipv6_req_msg_v01 qcmap_disable_ipv6_req_msg;
    qcmap_msgr_disable_ipv6_resp_msg_v01 qcmap_disable_ipv6_resp_msg;
    qmi_client_error_type qmi_error;

    /* Enable IPV6. */
    LOG("Disable IPV6");
    qcmap_disable_ipv6_req_msg.mobile_ap_handle = self->mobile_ap_handle;

    qmi_error = qmi_client_send_msg_sync(self->qmi_qcmap_msgr_handle,
                                        QMI_QCMAP_MSGR_DISABLE_IPV6_REQ_V01,
                                        &qcmap_disable_ipv6_req_msg,
                                        sizeof(qcmap_msgr_disable_ipv6_req_msg_v01),
                                        &qcmap_disable_ipv6_resp_msg,
                                        sizeof(qcmap_msgr_disable_ipv6_resp_msg_v01),
                                        QCMAP_MSGR_QMI_TIMEOUT_VALUE);

    if ( ( qmi_error == QMI_TIMEOUT_ERR ) ||
        ( qmi_error != QMI_NO_ERR ) ||
        ( qcmap_disable_ipv6_resp_msg.resp.result != QMI_NO_ERR ) )
    {
    LOG("Can not disable ipv6 %d : %d",
        qmi_error, qcmap_disable_ipv6_resp_msg.resp.error);
    return FALSE;
    }

    LOG("Disabled IPV6...");
    return TRUE;
}
  • 配置自動連接(沒測試出效果)
/* Enable/Disable Autoconnect mode */
static boolean qcmap_ppp_set_auto_connect(qcmap_ppp_t *self, boolean enable) {
    qcmap_msgr_set_auto_connect_req_msg_v01 set_auto_connect_req_msg;
    qcmap_msgr_set_auto_connect_resp_msg_v01 set_auto_connect_resp_msg;
    qmi_client_error_type qmi_error;

    

    set_auto_connect_req_msg.mobile_ap_handle = self->mobile_ap_handle;
    set_auto_connect_req_msg.enable = enable;

    qmi_error = qmi_client_send_msg_sync(self->qmi_qcmap_msgr_handle,
                                        QMI_QCMAP_MSGR_SET_AUTO_CONNECT_REQ_V01,
                                        &set_auto_connect_req_msg,
                                        sizeof(qcmap_msgr_set_auto_connect_req_msg_v01),
                                        &set_auto_connect_resp_msg,
                                        sizeof(qcmap_msgr_set_auto_connect_resp_msg_v01),
                                        QCMAP_MSGR_QMI_TIMEOUT_VALUE);
    if ( ( qmi_error == QMI_TIMEOUT_ERR ) ||
        ( qmi_error != QMI_NO_ERR ) ||
        ( set_auto_connect_resp_msg.resp.result != QMI_NO_ERR ) )
    {
    LOG("Can not set auto connect flag %d : %d",
            qmi_error, set_auto_connect_resp_msg.resp.error);
        return FALSE;
    }

    LOG("Auto Connect Mode Set succeeded...");
    return TRUE;
}
  • 查詢wwan統計信息(流量)
/* Get WWAN Status */
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) {
    qmi_client_error_type qmi_error, qmi_err_code = QMI_NO_ERR;
    qcmap_msgr_wwan_status_req_msg_v01 wan_status_req;
    qcmap_msgr_wwan_status_resp_msg_v01 wan_status_resp;
    

    memset(&wan_status_resp, 0, sizeof(qcmap_msgr_wwan_status_resp_msg_v01));
    wan_status_req.mobile_ap_handle = self->mobile_ap_handle;
    wan_status_req.call_type_valid = 1;
    wan_status_req.call_type = QCMAP_MSGR_WWAN_CALL_TYPE_V4_V01;
    qmi_error = qmi_client_send_msg_sync(self->qmi_qcmap_msgr_handle,
                                        QMI_QCMAP_MSGR_WWAN_STATUS_REQ_V01,
                                        &wan_status_req,
                                        sizeof(qcmap_msgr_wwan_status_req_msg_v01),
                                        (void*)&wan_status_resp,
                                        sizeof(qcmap_msgr_wwan_status_resp_msg_v01),
                                        QCMAP_MSGR_QMI_TIMEOUT_VALUE);

    LOG("qmi_client_send_msg_sync(enable): error %d result %d",
        qmi_error, wan_status_resp.resp.result);

    if ( ( qmi_error == QMI_TIMEOUT_ERR ) ||
        ( qmi_error != QMI_NO_ERR ) ||
        ( wan_status_resp.resp.result != QMI_NO_ERR ) )
    {
    LOG("Can not get IPV4 WAN status  %d : %d",
        qmi_error, wan_status_resp.resp.error);
    return FALSE;
    }
    if(wan_status_resp.conn_status_valid ==1)
    {
    *v4_status=wan_status_resp.conn_status;
    if(wan_status_resp.conn_status == QCMAP_MSGR_WWAN_STATUS_CONNECTING_V01)
    {
        LOG(" IPV4 WWAN is Connecting \n");
    }
    else if(wan_status_resp.conn_status == QCMAP_MSGR_WWAN_STATUS_CONNECTED_V01)
    {
        LOG(" IPV4 WWAN is connected \n");
    }
    else if(wan_status_resp.conn_status == QCMAP_MSGR_WWAN_STATUS_DISCONNECTING_V01)
    {
        LOG(" IPV4 WWAN is Disconnecting \n");
    }
    else if(wan_status_resp.conn_status == QCMAP_MSGR_WWAN_STATUS_DISCONNECTED_V01)
    {
        LOG(" IPV4 WWAN is Disconnected \n");
    }
    }

#ifdef ENABLE_IPV6
    memset(&wan_status_resp, 0, sizeof(qcmap_msgr_wwan_status_resp_msg_v01));
    wan_status_req.mobile_ap_handle = self->mobile_ap_handle;
    wan_status_req.call_type_valid = 1;
    wan_status_req.call_type = QCMAP_MSGR_WWAN_CALL_TYPE_V6_V01;
    qmi_error = qmi_client_send_msg_sync(self->qmi_qcmap_msgr_handle,
                                        QMI_QCMAP_MSGR_WWAN_STATUS_REQ_V01,
                                        &wan_status_req,
                                        sizeof(qcmap_msgr_wwan_status_req_msg_v01),
                                        (void*)&wan_status_resp,
                                        sizeof(qcmap_msgr_wwan_status_resp_msg_v01),
                                        QCMAP_MSGR_QMI_TIMEOUT_VALUE);

    LOG("qmi_client_send_msg_sync(enable): error %d result %d",
        qmi_error, wan_status_resp.resp.result);

    if ( ( qmi_error == QMI_TIMEOUT_ERR ) ||
        ( qmi_error != QMI_NO_ERR ) ||
        ( wan_status_resp.resp.result != QMI_NO_ERR ) )
    {
        LOG("Can not get IPV6 WAN status %d : %d",
            qmi_error, wan_status_resp.resp.error);
        return FALSE;
    }
    if(wan_status_resp.conn_status_valid == 1)
    {
    *v6_status=wan_status_resp.conn_status;
    if(wan_status_resp.conn_status == QCMAP_MSGR_WWAN_STATUS_IPV6_CONNECTING_V01)
    {
        LOG(" IPV6 WWAN is Connecting \n");
    }
    else if(wan_status_resp.conn_status == QCMAP_MSGR_WWAN_STATUS_IPV6_CONNECTED_V01)
    {
        LOG(" IPV6 WWAN is connected \n");
    }
    else if(wan_status_resp.conn_status == QCMAP_MSGR_WWAN_STATUS_IPV6_DISCONNECTING_V01)
    {
        LOG(" IPV6 WWAN is Disconnecting \n");
    }
    else if(wan_status_resp.conn_status == QCMAP_MSGR_WWAN_STATUS_IPV6_DISCONNECTED_V01)
    {
        LOG(" IPV6 WWAN is Disconnected \n");
    }
    }
#endif

    return TRUE;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章