/* * --------------------------------------------------------------------------- * 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() */
/* * --------------------------------------------------------------------------- * 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() */