int iw_set_oem_data_req(
        struct net_device *dev, 
        struct iw_request_info *info,
        union iwreq_data *wrqu,
        char *extra)
{
    eHalStatus status = eHAL_STATUS_SUCCESS;
    struct iw_oem_data_req *pOemDataReq = NULL;
    tOemDataReqConfig oemDataReqConfig;

    tANI_U32 oemDataReqID = 0;

    hdd_adapter_t *pAdapter = (netdev_priv(dev));
    hdd_wext_state_t *pwextBuf = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);

    if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress)
    {
       VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
                                  "%s:LOGP in Progress. Ignore!!!",__func__);
       return -EBUSY;
    }

    do
    {
        if(NULL != wrqu->data.pointer)
        {
            pOemDataReq = (struct iw_oem_data_req *)wrqu->data.pointer;
        }

        if(pOemDataReq == NULL)
        {
            hddLog(LOGE, "in %s oemDataReq == NULL", __func__);
            status = eHAL_STATUS_FAILURE;
            break;
        }

        vos_mem_zero(&oemDataReqConfig, sizeof(tOemDataReqConfig));

        if (copy_from_user((&oemDataReqConfig)->oemDataReq,
                           pOemDataReq->oemDataReq, OEM_DATA_REQ_SIZE))
        {
            VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
                      "%s: copy_from_user() failed!", __func__);
            return -EFAULT;
        }

        status = sme_OemDataReq(WLAN_HDD_GET_HAL_CTX(pAdapter), 
                                                pAdapter->sessionId,
                                                &oemDataReqConfig, 
                                                &oemDataReqID, 
                                                &hdd_OemDataReqCallback, 
                                                dev);
    
        pwextBuf->oemDataReqID = oemDataReqID;
        pwextBuf->oemDataReqInProgress = TRUE;

    } while(0);
    
    return status;
}
Exemple #2
0
static void wlan_hdd_cancel_existing_remain_on_channel(hdd_adapter_t *pAdapter)
{
    hdd_cfg80211_state_t *cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );
    int status = 0;

    if(cfgState->remain_on_chan_ctx != NULL)
    {
        hddLog( LOG1, "Cancel Existing Remain on Channel");

        /* Wait till remain on channel ready indication before issuing cancel 
         * remain on channel request, otherwise if remain on channel not 
         * received and if the driver issues cancel remain on channel then lim 
         * will be in unknown state.
         */
        status = wait_for_completion_interruptible_timeout(&pAdapter->rem_on_chan_ready_event,
               msecs_to_jiffies(WAIT_REM_CHAN_READY));
        if (!status)
        {
            hddLog( LOGE, 
                    "%s: timeout waiting for remain on channel ready indication",
                    __func__);
        }

        INIT_COMPLETION(pAdapter->cancel_rem_on_chan_var);
        
        /* Issue abort remain on chan request to sme.
         * The remain on channel callback will make sure the remain_on_chan
         * expired event is sent.
        */
        if ( ( WLAN_HDD_INFRA_STATION == pAdapter->device_mode ) ||
             ( WLAN_HDD_P2P_CLIENT == pAdapter->device_mode ) ||
             ( WLAN_HDD_P2P_DEVICE == pAdapter->device_mode )
           )
        {
            sme_CancelRemainOnChannel( WLAN_HDD_GET_HAL_CTX( pAdapter ),
                                                     pAdapter->sessionId );
        }
        else if ( (WLAN_HDD_SOFTAP== pAdapter->device_mode) ||
                  (WLAN_HDD_P2P_GO == pAdapter->device_mode)
                )
        {
            WLANSAP_CancelRemainOnChannel(
                                     (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
        }

        status = wait_for_completion_interruptible_timeout(&pAdapter->cancel_rem_on_chan_var,
               msecs_to_jiffies(WAIT_CANCEL_REM_CHAN));

        if (!status)
        {
            hddLog( LOGE, 
                    "%s: timeout waiting for cancel remain on channel ready indication",
                    __func__);
        }
    }
}
/**--------------------------------------------------------------------------------------------

  \brief __iw_get_oem_data_rsp() -

  This function gets the oem data response. This invokes
  the respective sme functionality. Function for handling the oem data rsp 
  IOCTL 

  \param - dev  - Pointer to the net device
         - info - Pointer to the iw_oem_data_req
         - wrqu - Pointer to the iwreq data
         - extra - Pointer to the data

  \return - 0 for success, non zero for failure

-----------------------------------------------------------------------------------------------*/
int __iw_get_oem_data_rsp(
        struct net_device *dev,
        struct iw_request_info *info,
        union iwreq_data *wrqu,
        char *extra)
{
    int                                   rc = 0;
    eHalStatus                            status;
    struct iw_oem_data_rsp*               pHddOemDataRsp;
    tOemDataRsp*                          pSmeOemDataRsp;
    hdd_adapter_t *pAdapter;
    hdd_context_t *pHddCtx;

    ENTER();
    pAdapter = (netdev_priv(dev));
    if (NULL == pAdapter)
    {
        VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
                  "%s: Adapter is NULL",__func__);
        return -EINVAL;
    }
    pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
    rc = wlan_hdd_validate_context(pHddCtx);
    if (0 != rc)
    {
        return rc;
    }
    do
    {
        //get the oem data response from sme
        status = sme_getOemDataRsp(WLAN_HDD_GET_HAL_CTX(pAdapter), &pSmeOemDataRsp);
        if (status != eHAL_STATUS_SUCCESS)
        {
            hddLog(LOGE, "%s: failed in sme_getOemDataRsp", __func__);
            rc = -EIO;
            break;
        }
        else
        {
            if (pSmeOemDataRsp != NULL)
            {
                pHddOemDataRsp = (struct iw_oem_data_rsp*)(extra);
                vos_mem_copy(pHddOemDataRsp->oemDataRsp, pSmeOemDataRsp->oemDataRsp, OEM_DATA_RSP_SIZE); 
            }
            else
            {
                hddLog(LOGE, "%s: pSmeOemDataRsp = NULL", __func__);
                rc = -EIO;
                break;
            }
        }
    } while(0);

    EXIT();
    return rc;
}
Exemple #4
0
int hdd_setP2pNoa( struct net_device *dev, tANI_U8 *command )
{
    hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
    tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
    VOS_STATUS status = VOS_STATUS_SUCCESS;
    tP2pPsConfig NoA;
    int count, duration, interval;
    char *param;

    param = strchr(command, ' ');
    if (param == NULL)
        return -1;
    param++;
    sscanf(param, "%d %d %d", &count, &duration, &interval);
    VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
               "%s: P2P_SET GO NoA: count=%d duration=%d interval=%d \n",
                __func__, count, duration, interval);

    /* PS Selection
     * Periodic NoA (2)
     * Single NOA   (4)
     */
    NoA.opp_ps = 0;
    NoA.ctWindow = 0;
    if (count == 1)
    {
        NoA.duration = 0;
        NoA.single_noa_duration = duration;
        NoA.psSelection = P2P_POWER_SAVE_TYPE_SINGLE_NOA;
    }
    else
    {
        NoA.duration = duration;
        NoA.single_noa_duration = 0;
        NoA.psSelection = P2P_POWER_SAVE_TYPE_PERIODIC_NOA;
    }
    NoA.interval = interval;
    NoA.count = count;
    NoA.sessionid = pAdapter->sessionId;

    VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
                "%s: P2P_PS_ATTR:oppPS %d ctWindow %d duration %d "
                "interval %d count %d single noa duration %d "
                "PsSelection %x \n", __func__, NoA.opp_ps, 
                NoA.ctWindow, NoA.duration, NoA.interval, 
                NoA.count, NoA.single_noa_duration,
                NoA.psSelection);

    sme_p2pSetPs(hHal, &NoA);
    return status;
}
Exemple #5
0
/**--------------------------------------------------------------------------------------------

  \brief iw_set_oem_data_req() - 

  This function sets the oem data req configuration. This invokes
  the respective sme oem data req functionality. Function for 
  handling the set IOCTL for the oem data req configuration

  \param - dev  - Pointer to the net device
     - info - Pointer to the iw_oem_data_req
     - wrqu - Pointer to the iwreq data
     - extra - Pointer to the data

  \return - 0 for success, non zero for failure

-----------------------------------------------------------------------------------------------*/
int iw_set_oem_data_req(
        struct net_device *dev, 
        struct iw_request_info *info,
        union iwreq_data *wrqu,
        char *extra)
{
    eHalStatus status = eHAL_STATUS_SUCCESS;
    struct iw_oem_data_req *pOemDataReq = NULL;
    tOemDataReqConfig oemDataReqConfig;

    tANI_U32 oemDataReqID = 0;

    hdd_adapter_t *pAdapter = (netdev_priv(dev));
    hdd_wext_state_t *pwextBuf = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);


    do
    {
        if(NULL != wrqu->data.pointer)
        {
            pOemDataReq = (struct iw_oem_data_req *)wrqu->data.pointer;
        }

        if(pOemDataReq == NULL)
        {
            hddLog(LOGE, "in %s oemDataReq == NULL\n", __FUNCTION__);
            status = eHAL_STATUS_FAILURE;
            break;
        }

        vos_mem_zero(&oemDataReqConfig, sizeof(tOemDataReqConfig));

        vos_mem_copy((&oemDataReqConfig)->oemDataReq, pOemDataReq->oemDataReq, OEM_DATA_REQ_SIZE);
    
        status = sme_OemDataReq(WLAN_HDD_GET_HAL_CTX(pAdapter), 
                                                pAdapter->sessionId,
                                                &oemDataReqConfig, 
                                                &oemDataReqID, 
                                                &hdd_OemDataReqCallback, 
                                                dev);
    
        pwextBuf->oemDataReqID = oemDataReqID;
        pwextBuf->oemDataReqInProgress = TRUE;

    } while(0);
    
    return status;
}
int iw_get_oem_data_rsp(
        struct net_device *dev, 
        struct iw_request_info *info,
        union iwreq_data *wrqu,
        char *extra)
{
    int                                   rc = 0;
    eHalStatus                            status;
    struct iw_oem_data_rsp*               pHddOemDataRsp;
    tOemDataRsp*                          pSmeOemDataRsp;

    hdd_adapter_t *pAdapter = (netdev_priv(dev));

    if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress)
    {
       VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
                                  "%s:LOGP in Progress. Ignore!!!",__func__);
       return -EBUSY;
    }

    do
    {
        
        status = sme_getOemDataRsp(WLAN_HDD_GET_HAL_CTX(pAdapter), &pSmeOemDataRsp);
        if (status != eHAL_STATUS_SUCCESS)
        {
            hddLog(LOGE, "%s: failed in sme_getOemDataRsp", __func__);
            rc = -EIO;
            break;
        }
        else
        {
            if (pSmeOemDataRsp != NULL)
            {
                pHddOemDataRsp = (struct iw_oem_data_rsp*)(extra);
                vos_mem_copy(pHddOemDataRsp->oemDataRsp, pSmeOemDataRsp->oemDataRsp, OEM_DATA_RSP_SIZE); 
            }
            else
            {
                hddLog(LOGE, "%s: pSmeOemDataRsp = NULL", __func__);
                rc = -EIO;
                break;
            }
        }
    } while(0);

    return rc;
}
Exemple #7
0
int hdd_setP2pPs( struct net_device *dev, void *msgData )
{
    hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
    tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
    VOS_STATUS status = VOS_STATUS_SUCCESS;
    tP2pPsConfig NoA;
    p2p_app_setP2pPs_t *pappNoA = (p2p_app_setP2pPs_t *) msgData;

    NoA.opp_ps = pappNoA->opp_ps;
    NoA.ctWindow = pappNoA->ctWindow;
    NoA.duration = pappNoA->duration;
    NoA.interval = pappNoA->interval;
    NoA.count = pappNoA->count;
    NoA.single_noa_duration = pappNoA->single_noa_duration;
    NoA.psSelection = pappNoA->psSelection;
    NoA.sessionid = pAdapter->sessionId;

    sme_p2pSetPs(hHal, &NoA);
    return status;
}
Exemple #8
0
/**--------------------------------------------------------------------------------------------

  \brief iw_get_oem_data_rsp() - 

  This function gets the oem data response. This invokes
  the respective sme functionality. Function for handling the oem data rsp 
  IOCTL 

  \param - dev  - Pointer to the net device
         - info - Pointer to the iw_oem_data_req
         - wrqu - Pointer to the iwreq data
         - extra - Pointer to the data

  \return - 0 for success, non zero for failure

-----------------------------------------------------------------------------------------------*/
int iw_get_oem_data_rsp(
        struct net_device *dev, 
        struct iw_request_info *info,
        union iwreq_data *wrqu,
        char *extra)
{
    eHalStatus                            status = eHAL_STATUS_SUCCESS;
    struct iw_oem_data_rsp*               pHddOemDataRsp;
    tOemDataRsp*                          pSmeOemDataRsp;

    hdd_adapter_t *pAdapter = (netdev_priv(dev));

    do
    {
        //get the oem data response from sme
        status = sme_getOemDataRsp(WLAN_HDD_GET_HAL_CTX(pAdapter), &pSmeOemDataRsp);
        if(status != eHAL_STATUS_SUCCESS)
        {
            hddLog(LOGE, "%s: failed in sme_getOemDataRsp\n", __FUNCTION__);
            break;
        }
        else
        {
            if(pSmeOemDataRsp != NULL)
            {
                pHddOemDataRsp = (struct iw_oem_data_rsp*)(extra);
                vos_mem_copy(pHddOemDataRsp->oemDataRsp, pSmeOemDataRsp->oemDataRsp, OEM_DATA_RSP_SIZE); 
            }
            else
            {
                hddLog(LOGE, "%s: pSmeOemDataRsp = NULL\n", __FUNCTION__);
                status = eHAL_STATUS_FAILURE;
                break;
            }
        }
    } while(0);

    return eHAL_STATUS_SUCCESS;
}
Exemple #9
0
int hdd_setP2pOpps( struct net_device *dev, tANI_U8 *command )
{
    hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
    tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
    VOS_STATUS status = VOS_STATUS_SUCCESS;
    tP2pPsConfig NoA;
    char *param;
    int legacy_ps, opp_ps, ctwindow;

    param = strchr(command, ' ');
    if (param == NULL)
        return -1;
    param++;
    sscanf(param, "%d %d %d", &legacy_ps, &opp_ps, &ctwindow);
    VOS_TRACE (VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
                 "%s: P2P_SET GO PS: legacy_ps=%d opp_ps=%d ctwindow=%d \n",
                 __func__, legacy_ps, opp_ps, ctwindow);

    /* PS Selection
     * Opportunistic Power Save (1)
     */

    /* From wpa_cli user need to use separate command to set ctWindow and Opps
     * When user want to set ctWindow during that time other parameters
     * values are coming from wpa_supplicant as -1. 
     * Example : User want to set ctWindow with 30 then wpa_cli command : 
     * P2P_SET ctwindow 30 
     * Command Received at hdd_hostapd_ioctl is as below: 
     * P2P_SET_PS -1 -1 30 (legacy_ps = -1, opp_ps = -1, ctwindow = 30)
     */ 
    if (ctwindow != -1)
    {

        VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
                    "Opportunistic Power Save is %s \n", 
                    (TRUE == pAdapter->ops) ? "Enable" : "Disable" );

        if (ctwindow != pAdapter->ctw)
        {
            pAdapter->ctw = ctwindow;
        
            if(pAdapter->ops)
            {
                NoA.opp_ps = pAdapter->ops;
                NoA.ctWindow = pAdapter->ctw;
                NoA.duration = 0;
                NoA.single_noa_duration = 0;
                NoA.interval = 0;
                NoA.count = 0;
                NoA.psSelection = P2P_POWER_SAVE_TYPE_OPPORTUNISTIC;
                NoA.sessionid = pAdapter->sessionId;
 
                VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
                            "%s: P2P_PS_ATTR:oppPS %d ctWindow %d duration %d "
                            "interval %d count %d single noa duration %d "
                            "PsSelection %x \n", __func__, NoA.opp_ps, 
                            NoA.ctWindow, NoA.duration, NoA.interval, 
                            NoA.count, NoA.single_noa_duration,
                            NoA.psSelection);

               sme_p2pSetPs(hHal, &NoA);
           }
           return 0;
        }
    }

    if (opp_ps != -1)
    {
        pAdapter->ops = opp_ps;

        if ((opp_ps != -1) && (pAdapter->ctw)) 
        {
            NoA.opp_ps = opp_ps;
            NoA.ctWindow = pAdapter->ctw;
            NoA.duration = 0;
            NoA.single_noa_duration = 0;
            NoA.interval = 0;
            NoA.count = 0;
            NoA.psSelection = P2P_POWER_SAVE_TYPE_OPPORTUNISTIC;
            NoA.sessionid = pAdapter->sessionId;

            VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
                        "%s: P2P_PS_ATTR:oppPS %d ctWindow %d duration %d "
                        "interval %d count %d single noa duration %d "
                        "PsSelection %x \n", __func__, NoA.opp_ps, 
                        NoA.ctWindow, NoA.duration, NoA.interval, 
                        NoA.count, NoA.single_noa_duration,
                        NoA.psSelection);

           sme_p2pSetPs(hHal, &NoA);
        }
    }
    return status;
}
Exemple #10
0
int wlan_hdd_action( struct wiphy *wiphy, struct net_device *dev,
                     struct ieee80211_channel *chan,
                     enum nl80211_channel_type channel_type,
                     bool channel_type_valid,
                     const u8 *buf, size_t len, u64 *cookie )
#endif //LINUX_VERSION_CODE
{
    hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev );
    hdd_cfg80211_state_t *cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );
    tANI_U16 extendedWait = 0;
    tANI_U8 type = WLAN_HDD_GET_TYPE_FRM_FC(buf[0]);
    tANI_U8 subType = WLAN_HDD_GET_SUBTYPE_FRM_FC(buf[0]);
    tActionFrmType actionFrmType;
    bool noack = 0;

#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
    hdd_adapter_t *goAdapter;
#endif

#ifdef WLAN_FEATURE_P2P_DEBUG
    if ((type == SIR_MAC_MGMT_FRAME) &&
            (subType == SIR_MAC_MGMT_ACTION) &&
            (buf[WLAN_HDD_PUBLIC_ACTION_FRAME_OFFSET] == WLAN_HDD_PUBLIC_ACTION_FRAME))
    {
        actionFrmType = buf[WLAN_HDD_PUBLIC_ACTION_FRAME_TYPE_OFFSET];
        if(actionFrmType > MAX_P2P_ACTION_FRAME_TYPE)
        {
            hddLog(VOS_TRACE_LEVEL_ERROR,"[P2P] unknown[%d] ---> OTA",
                                   actionFrmType);
        }
        else
        {
            hddLog(VOS_TRACE_LEVEL_ERROR,"[P2P] %s ---> OTA",
            p2p_action_frame_type[actionFrmType]);
            if( (actionFrmType == WLAN_HDD_PROV_DIS_REQ) &&
                (globalP2PConnectionStatus == P2P_NOT_ACTIVE) )
            {
                 globalP2PConnectionStatus = P2P_GO_NEG_PROCESS;
                 hddLog(LOGE,"[P2P State]Inactive state to "
                            "GO negotation progress state");
            }
            else if( (actionFrmType == WLAN_HDD_GO_NEG_CNF) &&
                (globalP2PConnectionStatus == P2P_GO_NEG_PROCESS) )
            {
                 globalP2PConnectionStatus = P2P_GO_NEG_COMPLETED;
                 hddLog(LOGE,"[P2P State]GO nego progress to GO nego"
                             " completed state");
            }
        }
    }
#endif

#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,3,0))
    noack = dont_wait_for_ack;
#endif

    //If the wait is coming as 0 with off channel set
    //then set the wait to 200 ms
    if (offchan && !wait)
        wait = ACTION_FRAME_DEFAULT_WAIT;

    hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d",
                            __func__,pAdapter->device_mode);

    //Call sme API to send out a action frame.
    // OR can we send it directly through data path??
    // After tx completion send tx status back.
    if ( ( WLAN_HDD_SOFTAP == pAdapter->device_mode ) ||
         ( WLAN_HDD_P2P_GO == pAdapter->device_mode )
       )
    {
        if (type == SIR_MAC_MGMT_FRAME)
        {
            if (subType == SIR_MAC_MGMT_PROBE_RSP)
            {
                /* Drop Probe response recieved from supplicant, as for GO and 
                   SAP PE itself sends probe response
                   */ 
                goto err_rem_channel;
            }
            else if ((subType == SIR_MAC_MGMT_DISASSOC) ||
                    (subType == SIR_MAC_MGMT_DEAUTH))
            {
                /* During EAP failure or P2P Group Remove supplicant
                 * is sending del_station command to driver. From
                 * del_station function, Driver will send deauth frame to
                 * p2p client. No need to send disassoc frame from here.
                 * so Drop the frame here and send tx indication back to
                 * supplicant.
                 */
                tANI_U8 dstMac[ETH_ALEN] = {0};
                memcpy(&dstMac, &buf[WLAN_HDD_80211_FRM_DA_OFFSET], ETH_ALEN);
                hddLog(VOS_TRACE_LEVEL_INFO,
                        "%s: Deauth/Disassoc received for STA:"
                        "%02x:%02x:%02x:%02x:%02x:%02x",
                        __func__,
                        dstMac[0], dstMac[1], dstMac[2],
                        dstMac[3], dstMac[4], dstMac[5]);
                goto err_rem_channel;
            }
        }
    }

    if( NULL != cfgState->buf )
        return -EBUSY;

    hddLog( LOG1, "Action frame tx request");

#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
    goAdapter = hdd_get_adapter( pAdapter->pHddCtx, WLAN_HDD_P2P_GO );

    //If GO adapter exists and operating on same frequency
    //then we will not request remain on channel
    if( goAdapter && ( ieee80211_frequency_to_channel(chan->center_freq)
                         == goAdapter->sessionCtx.ap.operatingChannel ) )
    {
        goto send_frame;
    }
#endif

#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
    if( offchan && wait)
    {
        int status;

        // In case of P2P Client mode if we are already
        // on the same channel then send the frame directly

        if((cfgState->remain_on_chan_ctx != NULL) &&
           (cfgState->current_freq == chan->center_freq)
          )
        {
            hddLog(LOG1,"action frame: extending the wait time\n");
            extendedWait = (tANI_U16)wait;
            goto send_frame;
        }

        INIT_COMPLETION(pAdapter->offchannel_tx_event);

        status = wlan_hdd_request_remain_on_channel(wiphy, dev,
                                        chan, channel_type, wait, cookie,
                                        OFF_CHANNEL_ACTION_TX);

        if(0 != status)
        {
            if( (-EBUSY == status) &&
                (cfgState->current_freq == chan->center_freq) )
            {
                goto send_frame;
            }
            goto err_rem_channel;
        }

        /* Wait for driver to be ready on the requested channel */
        status = wait_for_completion_interruptible_timeout(
                     &pAdapter->offchannel_tx_event,
                     msecs_to_jiffies(WAIT_CHANGE_CHANNEL_FOR_OFFCHANNEL_TX));
        if(!status)
        {
            hddLog( LOGE, "Not able to complete remain on channel request"
                          " within timeout period");
            goto err_rem_channel;
        }
    }
    else if ( offchan )
    {
        /* Check before sending action frame
           whether we already remain on channel */
        if(NULL == cfgState->remain_on_chan_ctx)
        {
            goto err_rem_channel;
        }
    }
    send_frame:
#endif

    if(!noack)
    {
        cfgState->buf = vos_mem_malloc( len ); //buf;
        if( cfgState->buf == NULL )
            return -ENOMEM;

        cfgState->len = len;

        vos_mem_copy( cfgState->buf, buf, len);

#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
        if( cfgState->remain_on_chan_ctx )
        {
            cfgState->action_cookie = cfgState->remain_on_chan_ctx->cookie;
            *cookie = cfgState->action_cookie;
        }
        else
        {
#endif
            *cookie = (tANI_U32) cfgState->buf;
            cfgState->action_cookie = *cookie;
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
        }
#endif
    } 

    if ( (WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
         (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) ||
         ( WLAN_HDD_P2P_DEVICE == pAdapter->device_mode )
       )
    {
        tANI_U8 sessionId = pAdapter->sessionId;         
        
        if ((type == SIR_MAC_MGMT_FRAME) && 
                (subType == SIR_MAC_MGMT_ACTION) &&
                (buf[WLAN_HDD_PUBLIC_ACTION_FRAME_OFFSET] == WLAN_HDD_PUBLIC_ACTION_FRAME))
        {
            actionFrmType = buf[WLAN_HDD_PUBLIC_ACTION_FRAME_TYPE_OFFSET];
            hddLog(LOG1, "Tx Action Frame %u \n", actionFrmType);
            if (actionFrmType == WLAN_HDD_PROV_DIS_REQ)
            {
                cfgState->actionFrmState = HDD_PD_REQ_ACK_PENDING;
                hddLog(LOG1, "%s: HDD_PD_REQ_ACK_PENDING \n", __func__);
            }
            else if (actionFrmType == WLAN_HDD_GO_NEG_REQ)
            {
                cfgState->actionFrmState = HDD_GO_NEG_REQ_ACK_PENDING;
                hddLog(LOG1, "%s: HDD_GO_NEG_REQ_ACK_PENDING \n", __func__);
            }
        }

        if (eHAL_STATUS_SUCCESS !=
               sme_sendAction( WLAN_HDD_GET_HAL_CTX(pAdapter),
                               sessionId, buf, len, extendedWait, noack))
        {
            VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
                     "%s: sme_sendAction returned fail", __func__);
            goto err;
        }
    }
    else if( ( WLAN_HDD_SOFTAP== pAdapter->device_mode ) ||
              ( WLAN_HDD_P2P_GO == pAdapter->device_mode )
            )
     {
        if( VOS_STATUS_SUCCESS !=
             WLANSAP_SendAction( (WLAN_HDD_GET_CTX(pAdapter))->pvosContext,
                                  buf, len, 0 ) )
        {
            VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
                    "%s: WLANSAP_SendAction returned fail", __func__);
            goto err;
        }
    }

    return 0;
err:
    if(!noack)
    {
       hdd_sendActionCnf( pAdapter, FALSE );
    }
    return 0;
err_rem_channel:
    *cookie = (tANI_U32)cfgState;
    cfg80211_mgmt_tx_status( pAdapter->dev, *cookie, buf, len, FALSE, GFP_KERNEL );
    return 0;
}
Exemple #11
0
int wlan_hdd_cfg80211_cancel_remain_on_channel( struct wiphy *wiphy,
                                      struct net_device *dev, u64 cookie )
{
    hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
    hdd_cfg80211_state_t *cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );
    int status = 0;

    hddLog( LOG1, "Cancel remain on channel req");

    if (((hdd_context_t*)pAdapter->pHddCtx)->isLogpInProgress)
    {
        VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
                "%s:LOGP in Progress. Ignore!!!", __func__);
        return -EAGAIN;
    }
    /* FIXME cancel currently running remain on chan.
     * Need to check cookie and cancel accordingly
     */
    if( (cfgState->remain_on_chan_ctx == NULL) ||
        (cfgState->remain_on_chan_ctx->cookie != cookie) )
    {
        hddLog( LOGE,
            "%s: No Remain on channel pending with specified cookie value",
             __func__);
        return -EINVAL;
    }
    
    /* wait until remain on channel ready event received 
     * for already issued remain on channel request */
    status = wait_for_completion_interruptible_timeout(&pAdapter->rem_on_chan_ready_event,
            msecs_to_jiffies(WAIT_REM_CHAN_READY));
    if (!status)
    {
        hddLog( LOGE, 
                "%s: timeout waiting for remain on channel ready indication",
                __func__);
    }
    INIT_COMPLETION(pAdapter->cancel_rem_on_chan_var);
    /* Issue abort remain on chan request to sme.
     * The remain on channel callback will make sure the remain_on_chan
     * expired event is sent.
     */
    if ( ( WLAN_HDD_INFRA_STATION == pAdapter->device_mode ) ||
         ( WLAN_HDD_P2P_CLIENT == pAdapter->device_mode ) ||
         ( WLAN_HDD_P2P_DEVICE == pAdapter->device_mode )
       )
    {
        tANI_U8 sessionId = pAdapter->sessionId; 
        sme_CancelRemainOnChannel( WLAN_HDD_GET_HAL_CTX( pAdapter ),
                                            sessionId );
    }
    else if ( (WLAN_HDD_SOFTAP== pAdapter->device_mode) ||
              (WLAN_HDD_P2P_GO == pAdapter->device_mode)
            )
    {
        WLANSAP_CancelRemainOnChannel(
                                (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
    }
    else 
    {
       hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid device_mode = %d",
                            __func__, pAdapter->device_mode);
       return -EIO;
    }
    wait_for_completion_interruptible_timeout(&pAdapter->cancel_rem_on_chan_var,
            msecs_to_jiffies(WAIT_CANCEL_REM_CHAN));
    return 0;
}
Exemple #12
0
static int wlan_hdd_request_remain_on_channel( struct wiphy *wiphy,
                                   struct net_device *dev,
                                   struct ieee80211_channel *chan,
                                   enum nl80211_channel_type channel_type,
                                   unsigned int duration, u64 *cookie,
                                   rem_on_channel_request_type_t request_type )
{
    hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
    hdd_remain_on_chan_ctx_t *pRemainChanCtx;
    hdd_cfg80211_state_t *cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );
    hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d",
                                 __func__,pAdapter->device_mode);

    hddLog( LOG1,
        "chan(hw_val)0x%x chan(centerfreq) %d chan type 0x%x, duration %d",
        chan->hw_value, chan->center_freq, channel_type, duration );

    //Cancel existing remain On Channel if any
    wlan_hdd_cancel_existing_remain_on_channel(pAdapter);

    /* When P2P-GO and if we are trying to unload the driver then
     * wlan driver is keep on receiving the remain on channel command
     * and which is resulting in crash. So not allowing any remain on
     * channel requets when Load/Unload is in progress*/
    if (((hdd_context_t*)pAdapter->pHddCtx)->isLoadUnloadInProgress)
    {
        hddLog( LOGE,
                "%s: Wlan Load/Unload is in progress", __func__);
        return -EBUSY;
    }

    if (((hdd_context_t*)pAdapter->pHddCtx)->isLogpInProgress)
    {
        VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
                "%s:LOGP in Progress. Ignore!!!", __func__);
        return -EAGAIN;
    }
    pRemainChanCtx = vos_mem_malloc( sizeof(hdd_remain_on_chan_ctx_t) );
    if( NULL == pRemainChanCtx )
    {
        hddLog(VOS_TRACE_LEVEL_FATAL,
             "%s: Not able to allocate memory for Channel context",
                                         __func__);
        return -ENOMEM;
    }

    vos_mem_copy( &pRemainChanCtx->chan, chan,
                   sizeof(struct ieee80211_channel) );

    pRemainChanCtx->chan_type = channel_type;
    pRemainChanCtx->duration = duration;
    pRemainChanCtx->dev = dev;
    *cookie = (tANI_U32) pRemainChanCtx;
    pRemainChanCtx->cookie = *cookie;
    pRemainChanCtx->rem_on_chan_request = request_type;
    cfgState->remain_on_chan_ctx = pRemainChanCtx;
    cfgState->current_freq = chan->center_freq;
    
    INIT_COMPLETION(pAdapter->rem_on_chan_ready_event);

    //call sme API to start remain on channel.
    if ( ( WLAN_HDD_INFRA_STATION == pAdapter->device_mode ) ||
         ( WLAN_HDD_P2P_CLIENT == pAdapter->device_mode ) ||
         ( WLAN_HDD_P2P_DEVICE == pAdapter->device_mode )
       )
    {
        tANI_U8 sessionId = pAdapter->sessionId; 
        //call sme API to start remain on channel.
        sme_RemainOnChannel(
                       WLAN_HDD_GET_HAL_CTX(pAdapter), sessionId,
                       chan->hw_value, duration,
                       wlan_hdd_remain_on_channel_callback, pAdapter );

        sme_RegisterMgmtFrame(WLAN_HDD_GET_HAL_CTX(pAdapter),
                              sessionId, (SIR_MAC_MGMT_FRAME << 2) |
                              (SIR_MAC_MGMT_PROBE_REQ << 4), NULL, 0 );

    }
    else if ( ( WLAN_HDD_SOFTAP== pAdapter->device_mode ) ||
              ( WLAN_HDD_P2P_GO == pAdapter->device_mode )
            )
    {
        //call sme API to start remain on channel.
        if (VOS_STATUS_SUCCESS != WLANSAP_RemainOnChannel(
                          (WLAN_HDD_GET_CTX(pAdapter))->pvosContext,
                          chan->hw_value, duration,
                          wlan_hdd_remain_on_channel_callback, pAdapter ))

        {
           VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
                    "%s: WLANSAP_RemainOnChannel returned fail", __func__);
           cfgState->remain_on_chan_ctx = NULL;
           vos_mem_free (pRemainChanCtx);
           return -EINVAL;
        }


        if (VOS_STATUS_SUCCESS != WLANSAP_RegisterMgmtFrame(
                    (WLAN_HDD_GET_CTX(pAdapter))->pvosContext,
                    (SIR_MAC_MGMT_FRAME << 2) | ( SIR_MAC_MGMT_PROBE_REQ << 4),
                    NULL, 0 ))
        {
            VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
                    "%s: WLANSAP_RegisterMgmtFrame returned fail", __func__);
            WLANSAP_CancelRemainOnChannel(
                    (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
            return -EINVAL;
        }

    }
    return 0;

}
static eHalStatus hdd_IndicateScanResult(hdd_scan_info_t *scanInfo, tCsrScanResultInfo *scan_result)
{
   hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(scanInfo->dev) ;
   tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
   tSirBssDescription *descriptor = &scan_result->BssDescriptor;
   struct iw_event event;
   char *current_event = scanInfo->start;
   char *end = scanInfo->end;
   char *last_event;
   char *current_pad;
   v_U16_t ie_length = 0;
   v_U16_t capabilityInfo;
   char *modestr;
   int error;
   char custom[MAX_CUSTOM_LEN];
   char *p;

   hddLog( LOG1, "hdd_IndicateScanResult " MAC_ADDRESS_STR,
          MAC_ADDR_ARRAY(descriptor->bssId));

   error = 0;
   last_event = current_event;
   vos_mem_zero(&event, sizeof (event));

   /* BSSID */
   event.cmd = SIOCGIWAP;
   event.u.ap_addr.sa_family = ARPHRD_ETHER;
   vos_mem_copy (event.u.ap_addr.sa_data, descriptor->bssId,
                  sizeof (descriptor->bssId));
   current_event = iwe_stream_add_event(scanInfo->info,current_event, end,
                   &event, IW_EV_ADDR_LEN);

   if (last_event == current_event)
   {
      /* no space to add event */
      /* Error code may be E2BIG */
       hddLog( LOGE, "hdd_IndicateScanResult: no space for SIOCGIWAP ");
       return -E2BIG;
   }

   last_event = current_event;
   vos_mem_zero(&event, sizeof (struct iw_event));

 /* Protocol Name */
   event.cmd = SIOCGIWNAME;

   switch (descriptor->nwType)
   {
   case eSIR_11A_NW_TYPE:
       modestr = "a";
       break;
   case eSIR_11B_NW_TYPE:
       modestr = "b";
       break;
   case eSIR_11G_NW_TYPE:
       modestr = "g";
       break;
   case eSIR_11N_NW_TYPE:
       modestr = "n";
       break;
   default:
       hddLog( LOGW, "%s: Unknown network type [%d]",
              __func__, descriptor->nwType);
       modestr = "?";
       break;
   }
   snprintf(event.u.name, IFNAMSIZ, "IEEE 802.11%s", modestr);
   current_event = iwe_stream_add_event(scanInfo->info,current_event, end,
                   &event, IW_EV_CHAR_LEN);

   if (last_event == current_event)
   { /* no space to add event */
       hddLog( LOGE, "hdd_IndicateScanResult: no space for SIOCGIWNAME");
      /* Error code, may be E2BIG */
       return -E2BIG;
   }

   last_event = current_event;
   vos_mem_zero( &event, sizeof (struct iw_event));

   /*Freq*/
   event.cmd = SIOCGIWFREQ;

   event.u.freq.m = descriptor->channelId;
   event.u.freq.e = 0;
   event.u.freq.i = 0;
   current_event = iwe_stream_add_event(scanInfo->info,current_event, end,
                                        &event, IW_EV_FREQ_LEN);

   if (last_event == current_event)
   { /* no space to add event */
       hddLog( LOGE, "hdd_IndicateScanResult: no space for SIOCGIWFREQ");
       return -E2BIG;
   }

   last_event = current_event;
   vos_mem_zero( &event, sizeof (struct iw_event));

   /* BSS Mode */
   event.cmd = SIOCGIWMODE;

   capabilityInfo = descriptor->capabilityInfo;

   if (SIR_MAC_GET_ESS(capabilityInfo))
   {
       event.u.mode = IW_MODE_MASTER;
   }
   else if (SIR_MAC_GET_IBSS(capabilityInfo))
   {
       event.u.mode = IW_MODE_ADHOC;
   }
   else
   {
       /* neither ESS or IBSS */
       event.u.mode = IW_MODE_AUTO;
   }

   current_event = iwe_stream_add_event(scanInfo->info,current_event, end,
                                        &event, IW_EV_UINT_LEN);

   if (last_event == current_event)
   { /* no space to add event */
       hddLog( LOGE, "hdd_IndicateScanResult: no space for SIOCGIWMODE");
       return -E2BIG;
   }
   /* To extract SSID */
   ie_length = GET_IE_LEN_IN_BSS( descriptor->length );

   if (ie_length > 0)
   {
       /* dot11BeaconIEs is a large struct, so we make it static to
          avoid stack overflow.  This API is only invoked via ioctl,
          so it is serialized by the kernel rtnl_lock and hence does
          not need to be reentrant */
       static tDot11fBeaconIEs dot11BeaconIEs;
       tDot11fIESSID *pDot11SSID;
       tDot11fIESuppRates *pDot11SuppRates;
       tDot11fIEExtSuppRates *pDot11ExtSuppRates;
       tDot11fIEHTCaps *pDot11IEHTCaps;
       int numBasicRates = 0;
       int maxNumRates = 0;

       pDot11IEHTCaps = NULL;

       dot11fUnpackBeaconIEs ((tpAniSirGlobal)
           hHal, (tANI_U8 *) descriptor->ieFields, ie_length,  &dot11BeaconIEs);

       pDot11SSID = &dot11BeaconIEs.SSID;


       if (pDot11SSID->present ) {
          last_event = current_event;
          vos_mem_zero (&event, sizeof (struct iw_event));

          event.cmd = SIOCGIWESSID;
          event.u.data.flags = 1;
          event.u.data.length = scan_result->ssId.length;
          current_event = iwe_stream_add_point (scanInfo->info,current_event, end,
                  &event, (char *)scan_result->ssId.ssId);

          if(last_event == current_event)
          { /* no space to add event */
             hddLog( LOGE, "hdd_IndicateScanResult: no space for SIOCGIWESSID");
             return -E2BIG;
          }
       }

      if( hdd_GetWPARSNIEs( ( tANI_U8 *) descriptor->ieFields, ie_length, &last_event, &current_event, scanInfo )  < 0    )
      {
          hddLog( LOGE, "hdd_IndicateScanResult: no space for SIOCGIWESSID");
          return -E2BIG;
      }

      last_event = current_event;
      current_pad = current_event + IW_EV_LCP_LEN;
      vos_mem_zero( &event, sizeof (struct iw_event));

      /*Rates*/
      event.cmd = SIOCGIWRATE;


      pDot11SuppRates = &dot11BeaconIEs.SuppRates;

      if (pDot11SuppRates->present )
      {
          int i;

          numBasicRates = pDot11SuppRates->num_rates;
          for (i=0; i<pDot11SuppRates->num_rates; i++)
          {
              if (0 != (pDot11SuppRates->rates[i] & 0x7F))
              {
                  event.u.bitrate.value = hdd_TranslateABGRateToMbpsRate (
                      &pDot11SuppRates->rates[i]);

                  current_pad = iwe_stream_add_value (scanInfo->info,current_event,
                      current_pad, end, &event, IW_EV_PARAM_LEN);
              }
          }

      }

      pDot11ExtSuppRates = &dot11BeaconIEs.ExtSuppRates;

      if (pDot11ExtSuppRates->present )
      {
          int i,no_of_rates;
          maxNumRates = numBasicRates + pDot11ExtSuppRates->num_rates;

          /* Check to make sure the total number of rates
               doesn't exceed IW_MAX_BITRATES */

          maxNumRates = VOS_MIN(maxNumRates , IW_MAX_BITRATES);

          if((maxNumRates - numBasicRates) > MAX_RATES)
          {
             no_of_rates = MAX_RATES;
             hddLog( LOGW, "Accessing array out of bound that array is pDot11ExtSuppRates->rates ");
          }
          else
          {
            no_of_rates = maxNumRates - numBasicRates;
          }
          for ( i=0; i< no_of_rates ; i++ )
          {
              if (0 != (pDot11ExtSuppRates->rates[i] & 0x7F))
              {
                  event.u.bitrate.value = hdd_TranslateABGRateToMbpsRate (
                      &pDot11ExtSuppRates->rates[i]);

                  current_pad = iwe_stream_add_value (scanInfo->info,current_event,
                      current_pad, end, &event, IW_EV_PARAM_LEN);
              }
          }
      }


      if ((current_pad - current_event) >= IW_EV_LCP_LEN)
      {
          current_event = current_pad;
      }
      else
      {
          if (last_event == current_event)
          { /* no space to add event */
              hddLog( LOGE, "hdd_IndicateScanResult: no space for SIOCGIWRATE");
              return -E2BIG;
          }
      }

      last_event = current_event;
      vos_mem_zero (&event, sizeof (struct iw_event));


      event.cmd = SIOCGIWENCODE;

      if (SIR_MAC_GET_PRIVACY(capabilityInfo))
      {
         event.u.data.flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY;
      }
      else
      {
         event.u.data.flags = IW_ENCODE_DISABLED;
      }
      event.u.data.length = 0;

      current_event = iwe_stream_add_point(scanInfo->info,current_event, end, &event, (char *)pDot11SSID->ssid);


      if(last_event == current_event)
      { /* no space to add event
               Error code, may be E2BIG */
          hddLog( LOGE, "hdd_IndicateScanResult: no space for SIOCGIWENCODE");
          return -E2BIG;
      }
   }

   last_event = current_event;
   vos_mem_zero( &event, sizeof (struct iw_event));

    /*RSSI*/
   event.cmd = IWEVQUAL;
   event.u.qual.qual = descriptor->rssi;
   event.u.qual.noise = descriptor->sinr;

   /*To keep the rssi icon of the connected AP in the scan window
    *and the rssi icon of the wireless networks in sync */
   if (( eConnectionState_Associated ==
              pAdapter->sessionCtx.station.conn_info.connState ) &&
              ( VOS_TRUE == vos_mem_compare(descriptor->bssId,
                             pAdapter->sessionCtx.station.conn_info.bssId,
                             VOS_MAC_ADDR_SIZE)))
   {
      event.u.qual.level = pAdapter->rssi;
   }
   else
   {
      event.u.qual.level = VOS_MIN ((descriptor->rssi + descriptor->sinr), 0);
   }

   event.u.qual.updated = IW_QUAL_ALL_UPDATED;

   current_event = iwe_stream_add_event(scanInfo->info,current_event,
       end, &event, IW_EV_QUAL_LEN);

   if(last_event == current_event)
   { /* no space to add event */
       hddLog( LOGE, "hdd_IndicateScanResult: no space for IWEVQUAL");
       return -E2BIG;
   }


   /* AGE */
   event.cmd = IWEVCUSTOM;
   p = custom;
   p += scnprintf(p, MAX_CUSTOM_LEN, " Age: %lu",
                 vos_timer_get_system_ticks() - descriptor->nReceivedTime);
   event.u.data.length = p - custom;
   current_event = iwe_stream_add_point (scanInfo->info,current_event, end,
                                         &event, custom);
   if(last_event == current_event)
   { /* no space to add event */
      hddLog( LOGE, "hdd_IndicateScanResult: no space for IWEVCUSTOM (age)");
      return -E2BIG;
   }

   scanInfo->start = current_event;

   return 0;
}
int iw_get_scan(struct net_device *dev,
                         struct iw_request_info *info,
                         union iwreq_data *wrqu, char *extra)
{
   hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev) ;
   hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
   tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
   tCsrScanResultInfo *pScanResult;
   eHalStatus status = eHAL_STATUS_SUCCESS;
   hdd_scan_info_t scanInfo;
   tScanResultHandle pResult;
   int i = 0;

   VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: enter buffer length %d!!!",
       __func__, (wrqu->data.length)?wrqu->data.length:IW_SCAN_MAX_DATA);
   ENTER();

   if (TRUE == pHddCtx->scan_info.mScanPending)
   {
       VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:mScanPending is TRUE !!!",__func__);
       return -EAGAIN;
   }

   if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress) {
      VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:LOGP in Progress. Ignore!!!",__func__);
      return -EAGAIN;
   }

   scanInfo.dev = dev;
   scanInfo.start = extra;
   scanInfo.info = info;

   if (0 == wrqu->data.length)
   {
       scanInfo.end = extra + IW_SCAN_MAX_DATA;
   }
   else
   {
       scanInfo.end = extra + wrqu->data.length;
   }

   status = sme_ScanGetResult(hHal,pAdapter->sessionId,NULL,&pResult);

   if (NULL == pResult)
   {
       
       hddLog(LOG1,"iw_get_scan: NULL Scan Result ");
       return 0;
   }

   pScanResult = sme_ScanResultGetFirst(hHal, pResult);

   while (pScanResult)
   {
       status = hdd_IndicateScanResult(&scanInfo, pScanResult);
       if (0 != status)
       {
           break;
       }
       i++;
       pScanResult = sme_ScanResultGetNext(hHal, pResult);
   }

   sme_ScanResultPurge(hHal, pResult);

   EXIT();
   VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: exit total %d BSS reported !!!",__func__, i);
   return status;
}
static eHalStatus hdd_IndicateScanResult(hdd_scan_info_t *scanInfo, tCsrScanResultInfo *scan_result)
{
   hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(scanInfo->dev) ;
   tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter);
   tSirBssDescription *descriptor = &scan_result->BssDescriptor;
   struct iw_event event;
   char *current_event = scanInfo->start;
   char *end = scanInfo->end;
   char *last_event;
   char *current_pad;
   v_U16_t ie_length = 0;
   v_U16_t capabilityInfo;
   char *modestr;
   int error;
   char custom[MAX_CUSTOM_LEN];
   char *p;

   hddLog( LOG1, "hdd_IndicateScanResult %02x:%02x:%02x:%02x:%02x:%02x",
          descriptor->bssId[0],
          descriptor->bssId[1],
          descriptor->bssId[2],
          descriptor->bssId[3],
          descriptor->bssId[4],
          descriptor->bssId[5]);

   error = 0;
   last_event = current_event;
   vos_mem_zero(&event, sizeof (event));

   
   event.cmd = SIOCGIWAP;
   event.u.ap_addr.sa_family = ARPHRD_ETHER;
   vos_mem_copy (event.u.ap_addr.sa_data, descriptor->bssId,
                  sizeof (descriptor->bssId));
   current_event = iwe_stream_add_event(scanInfo->info,current_event, end,
                   &event, IW_EV_ADDR_LEN);

   if (last_event == current_event)
   {
      
      
       hddLog( LOGW, "hdd_IndicateScanResult: no space for SIOCGIWAP ");
       return -E2BIG;
   }

   last_event = current_event;
   vos_mem_zero(&event, sizeof (struct iw_event));

 
   event.cmd = SIOCGIWNAME;

   switch (descriptor->nwType)
   {
   case eSIR_11A_NW_TYPE:
       modestr = "a";
       break;
   case eSIR_11B_NW_TYPE:
       modestr = "b";
       break;
   case eSIR_11G_NW_TYPE:
       modestr = "g";
       break;
   case eSIR_11N_NW_TYPE:
       modestr = "n";
       break;
   default:
       hddLog( LOGW, "%s: Unknown network type [%d]",
              __func__, descriptor->nwType);
       modestr = "?";
       break;
   }
   snprintf(event.u.name, IFNAMSIZ, "IEEE 802.11%s", modestr);
   current_event = iwe_stream_add_event(scanInfo->info,current_event, end,
                   &event, IW_EV_CHAR_LEN);

   if (last_event == current_event)
   { 
       hddLog( LOGW, "hdd_IndicateScanResult: no space for SIOCGIWNAME");
      
       return -E2BIG;
   }

   last_event = current_event;
   vos_mem_zero( &event, sizeof (struct iw_event));

   
   event.cmd = SIOCGIWFREQ;

   event.u.freq.m = descriptor->channelId;
   event.u.freq.e = 0;
   event.u.freq.i = 0;
   current_event = iwe_stream_add_event(scanInfo->info,current_event, end,
                                        &event, IW_EV_FREQ_LEN);

   if (last_event == current_event)
   { 
       return -E2BIG;
   }

   last_event = current_event;
   vos_mem_zero( &event, sizeof (struct iw_event));

   
   event.cmd = SIOCGIWMODE;

   capabilityInfo = descriptor->capabilityInfo;

   if (SIR_MAC_GET_ESS(capabilityInfo))
   {
       event.u.mode = IW_MODE_INFRA;
   }
   else if (SIR_MAC_GET_IBSS(capabilityInfo))
   {
       event.u.mode = IW_MODE_ADHOC;
   }
   else
   {
       
       event.u.mode = IW_MODE_AUTO;
   }

   current_event = iwe_stream_add_event(scanInfo->info,current_event, end,
                                        &event, IW_EV_UINT_LEN);

   if (last_event == current_event)
   { 
       hddLog( LOGW, "hdd_IndicateScanResult: no space for SIOCGIWMODE");
       return -E2BIG;
   }
   
   ie_length = GET_IE_LEN_IN_BSS( descriptor->length );

   if (ie_length > 0)
   {
       static tDot11fBeaconIEs dot11BeaconIEs;
       tDot11fIESSID *pDot11SSID;
       tDot11fIESuppRates *pDot11SuppRates;
       tDot11fIEExtSuppRates *pDot11ExtSuppRates;
       tDot11fIEHTCaps *pDot11IEHTCaps;
       int numBasicRates = 0;
       int maxNumRates = 0;

       pDot11IEHTCaps = NULL;

       dot11fUnpackBeaconIEs ((tpAniSirGlobal)
           hHal, (tANI_U8 *) descriptor->ieFields, ie_length,  &dot11BeaconIEs);

       pDot11SSID = &dot11BeaconIEs.SSID;


       if (pDot11SSID->present ) {
          last_event = current_event;
          vos_mem_zero (&event, sizeof (struct iw_event));

          event.cmd = SIOCGIWESSID;
          event.u.data.flags = 1;
          event.u.data.length = scan_result->ssId.length;
          current_event = iwe_stream_add_point (scanInfo->info,current_event, end,
                  &event, (char *)scan_result->ssId.ssId);

          if(last_event == current_event)
          { 
             hddLog( LOGW, "hdd_IndicateScanResult: no space for SIOCGIWESSID");
             return -E2BIG;
          }
       }

      if( hdd_GetWPARSNIEs( ( tANI_U8 *) descriptor->ieFields, ie_length, &last_event, &current_event, scanInfo )  < 0    )
      {
          hddLog( LOGW, "hdd_IndicateScanResult: no space for SIOCGIWESSID");
          return -E2BIG;
      }

      last_event = current_event;
      current_pad = current_event + IW_EV_LCP_LEN;
      vos_mem_zero( &event, sizeof (struct iw_event));

      
      event.cmd = SIOCGIWRATE;


      pDot11SuppRates = &dot11BeaconIEs.SuppRates;

      if (pDot11SuppRates->present )
      {
          int i;

          numBasicRates = pDot11SuppRates->num_rates;
          for (i=0; i<pDot11SuppRates->num_rates; i++)
          {
              if (0 != (pDot11SuppRates->rates[i] & 0x7F))
              {
                  event.u.bitrate.value = hdd_TranslateABGRateToMbpsRate (
                      &pDot11SuppRates->rates[i]);

                  current_pad = iwe_stream_add_value (scanInfo->info,current_event,
                      current_pad, end, &event, IW_EV_PARAM_LEN);
              }
          }

      }

      pDot11ExtSuppRates = &dot11BeaconIEs.ExtSuppRates;

      if (pDot11ExtSuppRates->present )
      {
          int i,no_of_rates;
          maxNumRates = numBasicRates + pDot11ExtSuppRates->num_rates;


          maxNumRates = VOS_MIN(maxNumRates , IW_MAX_BITRATES);

          if((maxNumRates - numBasicRates) > MAX_RATES)
          {
             no_of_rates = MAX_RATES;
             hddLog( LOGW, "Accessing array out of bound that array is pDot11ExtSuppRates->rates ");
          }
          else
          {
            no_of_rates = maxNumRates - numBasicRates;
          }
          for ( i=0; i< no_of_rates ; i++ )
          {
              if (0 != (pDot11ExtSuppRates->rates[i] & 0x7F))
              {
                  event.u.bitrate.value = hdd_TranslateABGRateToMbpsRate (
                      &pDot11ExtSuppRates->rates[i]);

                  current_pad = iwe_stream_add_value (scanInfo->info,current_event,
                      current_pad, end, &event, IW_EV_PARAM_LEN);
              }
          }
      }


      if ((current_pad - current_event) >= IW_EV_LCP_LEN)
      {
          current_event = current_pad;
      }
      else
      {
          if (last_event == current_event)
          { 
              hddLog( LOGW, "hdd_IndicateScanResult: no space for SIOCGIWRATE");
              return -E2BIG;
          }
      }

      last_event = current_event;
      vos_mem_zero (&event, sizeof (struct iw_event));


      event.cmd = SIOCGIWENCODE;

      if (SIR_MAC_GET_PRIVACY(capabilityInfo))
      {
         event.u.data.flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY;
      }
      else
      {
         event.u.data.flags = IW_ENCODE_DISABLED;
      }
      event.u.data.length = 0;

      current_event = iwe_stream_add_point(scanInfo->info,current_event, end, &event, (char *)pDot11SSID->ssid);


      if(last_event == current_event)
      { 
          return -E2BIG;
      }
   }

   last_event = current_event;
   vos_mem_zero( &event, sizeof (struct iw_event));

    
   event.cmd = IWEVQUAL;
   event.u.qual.qual = descriptor->rssi;
   event.u.qual.noise = descriptor->sinr;

   
   if (( eConnectionState_Associated == 
              pAdapter->sessionCtx.station.conn_info.connState ) &&
              ( VOS_TRUE == vos_mem_compare(descriptor->bssId, 
                             pAdapter->sessionCtx.station.conn_info.bssId, 
                             WNI_CFG_BSSID_LEN)))
   {
      event.u.qual.level = pAdapter->rssi;
   }
   else
   {
      event.u.qual.level = VOS_MIN ((descriptor->rssi + descriptor->sinr), 0);
   }
   
   event.u.qual.updated = IW_QUAL_ALL_UPDATED;

   current_event = iwe_stream_add_event(scanInfo->info,current_event,
       end, &event, IW_EV_QUAL_LEN);

   if(last_event == current_event)
   { 
       hddLog( LOGW, "hdd_IndicateScanResult: no space for IWEVQUAL");
       return -E2BIG;
   }


   
   event.cmd = IWEVCUSTOM;
   p = custom;
   p += scnprintf(p, MAX_CUSTOM_LEN, " Age: %lu",
                 vos_timer_get_system_ticks() - descriptor->nReceivedTime);
   event.u.data.length = p - custom;
   current_event = iwe_stream_add_point (scanInfo->info,current_event, end,
                                         &event, custom);
   if(last_event == current_event)
   { 
      hddLog( LOGW, "hdd_IndicateScanResult: no space for IWEVCUSTOM (age)");
      return -E2BIG;
   }

   scanInfo->start = current_event;

   return 0;
}
Exemple #16
0
        vos_mem_copy(&setKey.Key[0],
                     &Keys->KeyMaterial[key_index][0],
                     Keys->KeyLength[key_index]);

        setKey.keyDirection = eSIR_TX_ONLY;

        vos_mem_copy(setKey.peerMac,
                     &pHddStaCtx->conn_info.bssId[0],
                     WNI_CFG_BSSID_LEN);

        setKey.encType =
            pWextState->roamProfile.EncryptionType.encryptionType[0];

        /* issue set key request */
        status = sme_RoamSetKey( WLAN_HDD_GET_HAL_CTX(pAdapter),
                                 pAdapter->sessionId, &setKey, &roamId );

        if ( 0 != status )
        {
            hddLog(VOS_TRACE_LEVEL_ERROR,
                   "%s: sme_RoamSetKey failed, returned %d", __func__,
                   status);
            return -EINVAL;
        }
    }
}

/* In SoftAp mode setting key direction for default mode */
else if ( WLAN_HDD_SOFTAP == pAdapter->device_mode )
{
/**--------------------------------------------------------------------------------------------

  \brief __iw_set_oem_data_req() -

  This function sets the oem data req configuration. This invokes
  the respective sme oem data req functionality. Function for 
  handling the set IOCTL for the oem data req configuration

  \param - dev  - Pointer to the net device
     - info - Pointer to the iw_oem_data_req
     - wrqu - Pointer to the iwreq data
     - extra - Pointer to the data

  \return - 0 for success, non zero for failure

-----------------------------------------------------------------------------------------------*/
int __iw_set_oem_data_req(
        struct net_device *dev,
        struct iw_request_info *info,
        union iwreq_data *wrqu,
        char *extra)
{
    int rc = 0;
    eHalStatus status = eHAL_STATUS_SUCCESS;
    struct iw_oem_data_req *pOemDataReq = NULL;
    tOemDataReqConfig oemDataReqConfig;
    tANI_U32 oemDataReqID = 0;
    hdd_adapter_t *pAdapter;
    hdd_context_t *pHddCtx;
    hdd_wext_state_t *pwextBuf;

    ENTER();
    pAdapter = (netdev_priv(dev));
    if (NULL == pAdapter)
    {
       VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
                 "%s: Adapter is NULL",__func__);
       return -EINVAL;
    }
    pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
    rc = wlan_hdd_validate_context(pHddCtx);
    if (0 != rc)
    {
        return rc;
    }

    pwextBuf = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
    if (NULL == pwextBuf)
    {
        VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
                  "%s: pwextBuf is NULL",__func__);
        return -EINVAL;
    }

    do
    {
        if (NULL != wrqu->data.pointer)
        {
            pOemDataReq = (struct iw_oem_data_req *)wrqu->data.pointer;
        }

        if (pOemDataReq == NULL)
        {
            hddLog(LOGE, "in %s oemDataReq == NULL", __func__);
            rc = -EIO;
            break;
        }

        vos_mem_zero(&oemDataReqConfig, sizeof(tOemDataReqConfig));

        if (copy_from_user((&oemDataReqConfig)->oemDataReq,
                           pOemDataReq->oemDataReq, OEM_DATA_REQ_SIZE))
        {
            VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
                      "%s: copy_from_user() failed!", __func__);
            rc = -EFAULT;
            break;
        }

        status = sme_OemDataReq(WLAN_HDD_GET_HAL_CTX(pAdapter), 
                                                pAdapter->sessionId,
                                                &oemDataReqConfig, 
                                                &oemDataReqID, 
                                                &hdd_OemDataReqCallback, 
                                                dev);
        if (status != eHAL_STATUS_SUCCESS)
        {
            VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
                      "%s: sme_OemDataReq status %d", __func__, status);
            rc = -EFAULT;
            break;
        }
    
        pwextBuf->oemDataReqID = oemDataReqID;
        pwextBuf->oemDataReqInProgress = TRUE;

    } while(0);

    EXIT();
    return rc;
}