Beispiel #1
0
/*
 * ---------------------------------------------------------------------------
 *  sme_log_event
 *
 *      Callback function to be registered as the SME event callback.
 *      Copies the signal content into a new udi_log_t struct and adds
 *      it to the read queue for the SME client.
 *
 *  Arguments:
 *      arg             This is the value given to unifi_add_udi_hook, in
 *                      this case a pointer to the client instance.
 *      signal          Pointer to the received signal.
 *      signal_len      Size of the signal structure in bytes.
 *      bulkdata        Pointers to any associated bulk data.
 *      dir             Direction of the signal. Zero means from host,
 *                      non-zero means to host.
 *
 *  Returns:
 *      None.
 * ---------------------------------------------------------------------------
 */
    void
sme_log_event(ul_client_t *pcli,
        const u8 *signal, int signal_len,
        const bulk_data_param_t *bulkdata,
        int dir)
{
    unifi_priv_t *priv;
    CSR_SIGNAL unpacked_signal;
    CsrWifiSmeDataBlock mlmeCommand;
    CsrWifiSmeDataBlock dataref1;
    CsrWifiSmeDataBlock dataref2;
    CsrResult result = CSR_RESULT_SUCCESS;
    int r;

    /* Just a sanity check */
    if ((signal == NULL) || (signal_len <= 0)) {
        return;
    }

    priv = uf_find_instance(pcli->instance);
    if (!priv) {
        unifi_error(priv, "sme_log_event: invalid priv\n");
        return;
    }

    if (priv->smepriv == NULL) {
        unifi_error(priv, "sme_log_event: invalid smepriv\n");
        return;
    }

    unifi_trace(priv, UDBG3,
            "sme_log_event: Process signal 0x%.4X\n",
            CSR_GET_UINT16_FROM_LITTLE_ENDIAN(signal));


    /* If the signal is known, then do any filtering required, otherwise it pass it to the SME. */
    r = read_unpack_signal(signal, &unpacked_signal);
    if (r == CSR_RESULT_SUCCESS) {
        if ((unpacked_signal.SignalPrimitiveHeader.SignalId == CSR_DEBUG_STRING_INDICATION_ID) ||
            (unpacked_signal.SignalPrimitiveHeader.SignalId == CSR_DEBUG_WORD16_INDICATION_ID))
        {
            return;
        }
        if (unpacked_signal.SignalPrimitiveHeader.SignalId == CSR_MA_PACKET_INDICATION_ID)
        {
            u16 frmCtrl;
            u8 unicastPdu = TRUE;
            u8 *macHdrLocation;
            u8 *raddr = NULL, *taddr = NULL;
            CsrWifiMacAddress peerMacAddress;
            /* Check if we need to send CsrWifiRouterCtrlMicFailureInd*/
            CSR_MA_PACKET_INDICATION *ind = &unpacked_signal.u.MaPacketIndication;

            macHdrLocation = (u8 *) bulkdata->d[0].os_data_ptr;
            /* Fetch the frame control value from  mac header */
            frmCtrl = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(macHdrLocation);

            /* Point to the addresses */
            raddr = macHdrLocation + MAC_HEADER_ADDR1_OFFSET;
            taddr = macHdrLocation + MAC_HEADER_ADDR2_OFFSET;

            memcpy(peerMacAddress.a, taddr, ETH_ALEN);

            if(ind->ReceptionStatus == CSR_MICHAEL_MIC_ERROR)
            {
                if (*raddr & 0x1)
                    unicastPdu = FALSE;

                CsrWifiRouterCtrlMicFailureIndSend (priv->CSR_WIFI_SME_IFACEQUEUE, 0,
                        (ind->VirtualInterfaceIdentifier & 0xff), peerMacAddress,
                        unicastPdu);
                return;
            }
            else
            {
                if(ind->ReceptionStatus == CSR_RX_SUCCESS)
                {
                    u8 pmBit = (frmCtrl & 0x1000)?0x01:0x00;
                    u16 interfaceTag = (ind->VirtualInterfaceIdentifier & 0xff);
                    CsrWifiRouterCtrlStaInfo_t *srcStaInfo =  CsrWifiRouterCtrlGetStationRecordFromPeerMacAddress(priv, taddr, interfaceTag);
                    if((srcStaInfo != NULL) && (uf_check_broadcast_bssid(priv, bulkdata)== FALSE))
                    {
                        uf_process_pm_bit_for_peer(priv, srcStaInfo, pmBit, interfaceTag);

                        /* Update station last activity flag */
                        srcStaInfo->activity_flag = TRUE;
                    }
                }
            }
        }

        if (unpacked_signal.SignalPrimitiveHeader.SignalId == CSR_MA_PACKET_CONFIRM_ID)
        {
            CSR_MA_PACKET_CONFIRM *cfm = &unpacked_signal.u.MaPacketConfirm;
            u16 interfaceTag = (cfm->VirtualInterfaceIdentifier & 0xff);
            netInterface_priv_t *interfacePriv;
            CSR_MA_PACKET_REQUEST *req;
            CsrWifiMacAddress peerMacAddress;

            if (interfaceTag >= CSR_WIFI_NUM_INTERFACES)
            {
                unifi_error(priv, "Bad MA_PACKET_CONFIRM interfaceTag %d\n", interfaceTag);
                return;
            }

            unifi_trace(priv, UDBG1, "MA-PACKET Confirm (%x, %x)\n", cfm->HostTag, cfm->TransmissionStatus);

            interfacePriv = priv->interfacePriv[interfaceTag];
#ifdef CSR_SUPPORT_SME
            if(interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_AP ||
                 interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_P2PGO) {

                if(cfm->HostTag == interfacePriv->multicastPduHostTag){
                    uf_process_ma_pkt_cfm_for_ap(priv, interfaceTag, cfm);
                }
            }
#endif

            req = &interfacePriv->m4_signal.u.MaPacketRequest;

            if(cfm->HostTag & 0x80000000)
            {
                if (cfm->TransmissionStatus != CSR_TX_SUCCESSFUL)
                {
                    result = CSR_RESULT_FAILURE;
                }
#ifdef CSR_SUPPORT_SME
                memcpy(peerMacAddress.a, req->Ra.x, ETH_ALEN);
                /* Check if this is a confirm for EAPOL M4 frame and we need to send transmistted ind*/
                if (interfacePriv->m4_sent && (cfm->HostTag == interfacePriv->m4_hostTag))
                {
                    unifi_trace(priv, UDBG1, "%s: Sending M4 Transmit CFM\n", __FUNCTION__);
                    CsrWifiRouterCtrlM4TransmittedIndSend(priv->CSR_WIFI_SME_IFACEQUEUE, 0,
                            interfaceTag,
                            peerMacAddress,
                            result);
                    interfacePriv->m4_sent = FALSE;
                    interfacePriv->m4_hostTag = 0xffffffff;
                }
#endif
                /* If EAPOL was requested via router APIs then send cfm else ignore*/
                if((cfm->HostTag & 0x80000000) != CSR_WIFI_EAPOL_M4_HOST_TAG) {
                    CsrWifiRouterMaPacketCfmSend((u16)signal[2],
                        cfm->VirtualInterfaceIdentifier,
                        result,
                        (cfm->HostTag & 0x3fffffff), cfm->Rate);
                } else {
                    unifi_trace(priv, UDBG1, "%s: M4 received from netdevice\n", __FUNCTION__);
                }
                return;
            }
        }
    }

    mlmeCommand.length = signal_len;
    mlmeCommand.data = (u8*)signal;

    dataref1.length = bulkdata->d[0].data_length;
    if (dataref1.length > 0) {
        dataref1.data = (u8 *) bulkdata->d[0].os_data_ptr;
    } else
    {
        dataref1.data = NULL;
    }

    dataref2.length = bulkdata->d[1].data_length;
    if (dataref2.length > 0) {
        dataref2.data = (u8 *) bulkdata->d[1].os_data_ptr;
    } else
    {
        dataref2.data = NULL;
    }

    CsrWifiRouterCtrlHipIndSend(priv->CSR_WIFI_SME_IFACEQUEUE, mlmeCommand.length, mlmeCommand.data,
            dataref1.length, dataref1.data,
            dataref2.length, dataref2.data);

} /* sme_log_event() */
/*
 * ---------------------------------------------------------------------------
 *  sme_native_log_event
 *
 *      Callback function to be registered as the SME event callback.
 *      Copies the signal content into a new udi_log_t struct and adds
 *      it to the read queue for the SME client.
 *
 *  Arguments:
 *      arg             This is the value given to unifi_add_udi_hook, in
 *                      this case a pointer to the client instance.
 *      signal          Pointer to the received signal.
 *      signal_len      Size of the signal structure in bytes.
 *      bulkdata        Pointers to any associated bulk data.
 *      dir             Direction of the signal. Zero means from host,
 *                      non-zero means to host.
 *
 *  Returns:
 *      None.
 * ---------------------------------------------------------------------------
 */
void
sme_native_log_event(ul_client_t *pcli,
                     const u8 *sig_packed, int sig_len,
                     const bulk_data_param_t *bulkdata,
                     int dir)
{
    unifi_priv_t *priv;
    udi_log_t *logptr;
    u8 *p;
    int i, r;
    int signal_len;
    int total_len;
    udi_msg_t *msgptr;
    CSR_SIGNAL signal;
    ul_client_t *client = pcli;

    func_enter();

    if (client == NULL) {
        unifi_error(NULL, "sme_native_log_event: client has exited\n");
        return;
    }

    priv = uf_find_instance(client->instance);
    if (!priv) {
        unifi_error(priv, "invalid priv\n");
        return;
    }

    /* Just a sanity check */
    if ((sig_packed == NULL) || (sig_len <= 0)) {
        return;
    }

    /* Get the unpacked signal */
    r = read_unpack_signal(sig_packed, &signal);
    if (r == 0) {
        signal_len = SigGetSize(&signal);
    } else {
        u16 receiver_id = CSR_GET_UINT16_FROM_LITTLE_ENDIAN((sig_packed) + sizeof(u16)) & 0xFF00;

        /* The control indications are 1 byte, pass them to client. */
        if (sig_len == 1) {
            unifi_trace(priv, UDBG5,
                        "Control indication (0x%x) for native SME.\n",
                        *sig_packed);

            *(u8*)&signal = *sig_packed;
            signal_len = sig_len;
        } else if (receiver_id == 0) {
            /*
             * Also "unknown" signals with a ReceiverId of 0 are passed to the client
             * without unpacking. (This is a code size optimisation to allow signals
             * that the driver not interested in to be dropped from the unpack code).
             */
            unifi_trace(priv, UDBG5,
                        "Signal 0x%.4X with ReceiverId 0 for native SME.\n",
                        CSR_GET_UINT16_FROM_LITTLE_ENDIAN(sig_packed));

            *(u8*)&signal = *sig_packed;
            signal_len = sig_len;
        } else {
            unifi_error(priv,
                        "sme_native_log_event - Received unknown signal 0x%.4X.\n",
                        CSR_GET_UINT16_FROM_LITTLE_ENDIAN(sig_packed));
            return;
        }
    }

    unifi_trace(priv, UDBG3, "sme_native_log_event: signal 0x%.4X for %d\n",
                signal.SignalPrimitiveHeader.SignalId,
                client->client_id);

    total_len = signal_len;
    /* Calculate the buffer we need to store signal plus bulk data */
    for (i = 0; i < UNIFI_MAX_DATA_REFERENCES; i++) {
        total_len += bulkdata->d[i].data_length;
    }

    /* Allocate log structure plus actual signal. */
    logptr = (udi_log_t *)kmalloc(sizeof(udi_log_t) + total_len, GFP_KERNEL);

    if (logptr == NULL) {
        unifi_error(priv,
                    "Failed to allocate %d bytes for a UDI log record\n",
                    sizeof(udi_log_t) + total_len);
        return;
    }

    /* Fill in udi_log struct */
    INIT_LIST_HEAD(&logptr->q);
    msgptr = &logptr->msg;
    msgptr->length = sizeof(udi_msg_t) + total_len;
    msgptr->timestamp = jiffies_to_msecs(jiffies);
    msgptr->direction = dir;
    msgptr->signal_length = signal_len;

    /* Copy signal and bulk data to the log */
    p = (u8 *)(msgptr + 1);
    memcpy(p, &signal, signal_len);
    p += signal_len;

    /* Append any bulk data */
    for (i = 0; i < UNIFI_MAX_DATA_REFERENCES; i++) {
        int len = bulkdata->d[i].data_length;

        /*
         * Len here might not be the same as the length in the bulk data slot.
         * The slot length will always be even, but len could be odd.
         */
        if (len > 0) {
            if (bulkdata->d[i].os_data_ptr) {
                memcpy(p, bulkdata->d[i].os_data_ptr, len);
            } else {
                memset(p, 0, len);
            }
            p += len;
        }
    }

    /* Add to tail of log queue */
    down(&client->udi_sem);
    list_add_tail(&logptr->q, &client->udi_log);
    up(&client->udi_sem);

    /* Wake any waiting user process */
    wake_up_interruptible(&client->udi_wq);

    func_exit();

} /* sme_native_log_event() */
/*
 * ---------------------------------------------------------------------------
 *  sme_native_mlme_event_handler
 *
 *      Callback function to be used as the udi_event_callback when registering
 *      as a client.
 *      This function implements a blocking request-reply interface for WEXT.
 *      To use it, a client specifies this function as the udi_event_callback
 *      to ul_register_client(). The signal dispatcher in
 *      unifi_receive_event() will call this function to deliver a signal.
 *
 *  Arguments:
 *      pcli            Pointer to the client instance.
 *      signal          Pointer to the received signal.
 *      signal_len      Size of the signal structure in bytes.
 *      bulkdata        Pointer to structure containing any associated bulk data.
 *      dir             Direction of the signal. Zero means from host,
 *                      non-zero means to host.
 *
 *  Returns:
 *      None.
 * ---------------------------------------------------------------------------
 */
void
sme_native_mlme_event_handler(ul_client_t *pcli,
                              const u8 *sig_packed, int sig_len,
                              const bulk_data_param_t *bulkdata,
                              int dir)
{
    CSR_SIGNAL signal;
    int signal_len;
    unifi_priv_t *priv = uf_find_instance(pcli->instance);
    int id, r;

    func_enter();

    /* Just a sanity check */
    if ((sig_packed == NULL) || (sig_len <= 0)) {
        return;
    }

    /* Get the unpacked signal */
    r = read_unpack_signal(sig_packed, &signal);
    if (r == 0) {
        signal_len = SigGetSize(&signal);
    } else {
        unifi_error(priv,
                    "sme_native_mlme_event_handler - Received unknown signal 0x%.4X.\n",
                    CSR_GET_UINT16_FROM_LITTLE_ENDIAN(sig_packed));
        return;
    }

    id = signal.SignalPrimitiveHeader.SignalId;
    unifi_trace(priv, UDBG4, "wext - Process signal 0x%.4X\n", id);

    /*
     * Take the appropriate action for the signal.
     */
    switch (id) {
        /*
         * Confirm replies from UniFi.
         * These all have zero or one CSR_DATAREF member. (FIXME: check this is still true for softmac)
         */
        case CSR_MA_PACKET_CONFIRM_ID:
        case CSR_MLME_RESET_CONFIRM_ID:
        case CSR_MLME_GET_CONFIRM_ID:
        case CSR_MLME_SET_CONFIRM_ID:
        case CSR_MLME_GET_NEXT_CONFIRM_ID:
        case CSR_MLME_POWERMGT_CONFIRM_ID:
        case CSR_MLME_SCAN_CONFIRM_ID:
        case CSR_MLME_HL_SYNC_CONFIRM_ID:
        case CSR_MLME_MEASURE_CONFIRM_ID:
        case CSR_MLME_SETKEYS_CONFIRM_ID:
        case CSR_MLME_DELETEKEYS_CONFIRM_ID:
        case CSR_MLME_HL_SYNC_CANCEL_CONFIRM_ID:
        case CSR_MLME_ADD_PERIODIC_CONFIRM_ID:
        case CSR_MLME_DEL_PERIODIC_CONFIRM_ID:
        case CSR_MLME_ADD_AUTONOMOUS_SCAN_CONFIRM_ID:
        case CSR_MLME_DEL_AUTONOMOUS_SCAN_CONFIRM_ID:
        case CSR_MLME_SET_PACKET_FILTER_CONFIRM_ID:
        case CSR_MLME_STOP_MEASURE_CONFIRM_ID:
        case CSR_MLME_PAUSE_AUTONOMOUS_SCAN_CONFIRM_ID:
        case CSR_MLME_ADD_TRIGGERED_GET_CONFIRM_ID:
        case CSR_MLME_DEL_TRIGGERED_GET_CONFIRM_ID:
        case CSR_MLME_ADD_BLACKOUT_CONFIRM_ID:
        case CSR_MLME_DEL_BLACKOUT_CONFIRM_ID:
        case CSR_MLME_ADD_RX_TRIGGER_CONFIRM_ID:
        case CSR_MLME_DEL_RX_TRIGGER_CONFIRM_ID:
        case CSR_MLME_CONNECT_STATUS_CONFIRM_ID:
        case CSR_MLME_MODIFY_BSS_PARAMETER_CONFIRM_ID:
        case CSR_MLME_ADD_TEMPLATE_CONFIRM_ID:
        case CSR_MLME_CONFIG_QUEUE_CONFIRM_ID:
        case CSR_MLME_ADD_TSPEC_CONFIRM_ID:
        case CSR_MLME_DEL_TSPEC_CONFIRM_ID:
        case CSR_MLME_START_AGGREGATION_CONFIRM_ID:
        case CSR_MLME_STOP_AGGREGATION_CONFIRM_ID:
        case CSR_MLME_SM_START_CONFIRM_ID:
        case CSR_MLME_LEAVE_CONFIRM_ID:
        case CSR_MLME_SET_TIM_CONFIRM_ID:
        case CSR_MLME_GET_KEY_SEQUENCE_CONFIRM_ID:
        case CSR_MLME_SET_CHANNEL_CONFIRM_ID:
        case CSR_MLME_ADD_MULTICAST_ADDRESS_CONFIRM_ID:
        case CSR_DEBUG_GENERIC_CONFIRM_ID:
            unifi_mlme_copy_reply_and_wakeup_client(pcli, &signal, signal_len, bulkdata);
            break;

        case CSR_MLME_CONNECTED_INDICATION_ID:
            /* We currently ignore the connected-ind for softmac f/w development */
            unifi_info(priv, "CSR_MLME_CONNECTED_INDICATION_ID ignored\n");
            break;

        default:
            break;
    }

    func_exit();
} /* sme_native_mlme_event_handler() */
Beispiel #4
0
/*
 * ---------------------------------------------------------------------------
 *  sme_log_event
 *
 *      Callback function to be registered as the SME event callback.
 *      Copies the signal content into a new udi_log_t struct and adds
 *      it to the read queue for the SME client.
 *
 *  Arguments:
 *      arg             This is the value given to unifi_add_udi_hook, in
 *                      this case a pointer to the client instance.
 *      signal          Pointer to the received signal.
 *      signal_len      Size of the signal structure in bytes.
 *      bulkdata        Pointers to any associated bulk data.
 *      dir             Direction of the signal. Zero means from host,
 *                      non-zero means to host.
 *
 *  Returns:
 *      None.
 * ---------------------------------------------------------------------------
 */
void
sme_log_event(ul_client_t *pcli,
              const u8 *signal, int signal_len,
              const bulk_data_param_t *bulkdata,
              int dir)
{
    unifi_priv_t *priv;
    CSR_SIGNAL unpacked_signal;
    unifi_DataBlock mlmeCommand;
    unifi_DataBlock dataref1;
    unifi_DataBlock dataref2;
    int r;

    func_enter();

    /* Just a sanity check */
    if ((signal == NULL) || (signal_len <= 0)) {
        func_exit();
        return;
    }

    priv = uf_find_instance(pcli->instance);
    if (!priv) {
        unifi_error(priv, "sme_log_event: invalid priv\n");
        func_exit();
        return;
    }

    if (priv->smepriv == NULL) {
        unifi_error(priv, "sme_log_event: invalid smepriv\n");
        func_exit();
        return;
    }

    unifi_trace(priv, UDBG3,
                "sme_log_event: Process signal 0x%X %s\n",
                *((CsrUint16*)signal),
                lookup_signal_name(*((CsrUint16*)signal)));


    /*
     * Indicate CSR_MLME_EAPOL_CONFIRM_ID and CSR_MA_UNITDATA_CONFIRM_ID
     * using the respective SYS API.
     */
    r = read_unpack_signal(signal, &unpacked_signal);
    if (r) {
        unifi_error(priv, "sme_log_event: Received unknown or corrupted signal.\n");
        func_exit();
        return;
    }

    if (unpacked_signal.SignalPrimitiveHeader.SignalId == CSR_MLME_EAPOL_CONFIRM_ID) {
        CSR_MLME_EAPOL_CONFIRM *cfm = &unpacked_signal.u.MlmeEapolConfirm;

        /* Retrieve the appHandle from the LSB of the ReceiverId. */
        unifi_sys_eapol_cfm(priv->smepriv, (void*)((unsigned int)signal[2]),
                            (cfm->ResultCode) ? unifi_EapolRcFailure : unifi_EapolRcSuccess);
        func_exit();
        return;
    }

    if (unpacked_signal.SignalPrimitiveHeader.SignalId == CSR_MA_UNITDATA_CONFIRM_ID) {
        CSR_MA_UNITDATA_CONFIRM *cfm = &unpacked_signal.u.MaUnitdataConfirm;

        /* Retrieve the appHandle from the LSB of the ReceiverId. */
        unifi_sys_ma_unitdata_cfm(priv->smepriv,
                                  (void*)((unsigned int)signal[2]),
                                  (cfm->TransmissionStatus) ? unifi_Error : unifi_Success,
                                  cfm->TransmissionStatus,
                                  cfm->ProvidedPriority,
                                  cfm->ProvidedServiceClass,
                                  cfm->ProvidedHostTag);

        func_exit();
        return;
    }

    mlmeCommand.length = signal_len;
    mlmeCommand.data = (CsrUint8*)signal;

    dataref1.length = bulkdata->d[0].data_length;
    if (dataref1.length > 0) {
        dataref1.data = (CsrUint8 *) bulkdata->d[0].os_data_ptr;
    } else
    {
        dataref1.data = NULL;
    }

    dataref2.length = bulkdata->d[1].data_length;
    if (dataref2.length > 0) {
        dataref2.data = (CsrUint8 *) bulkdata->d[1].os_data_ptr;
    } else
    {
        dataref2.data = NULL;
    }

    unifi_sys_hip_ind(priv->smepriv, mlmeCommand.length, mlmeCommand.data,
                                     dataref1.length, dataref1.data,
                                     dataref2.length, dataref2.data);

    func_exit();
} /* sme_log_event() */